Home | History | Annotate | Download | only in src
      1 /*
      2  * osmemapi.c
      3  *
      4  * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  *  * Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *  * Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in
     15  *    the documentation and/or other materials provided with the
     16  *    distribution.
     17  *  * Neither the name Texas Instruments nor the names of its
     18  *    contributors may be used to endorse or promote products derived
     19  *    from this software without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 
     35 /*
     36  * src/osmemapi.c
     37  *
     38  */
     39 
     40 #include "arch_ti.h"
     41 
     42 #include <linux/stddef.h>
     43 #include <linux/string.h>
     44 #include <linux/time.h>
     45 #include <linux/timer.h>
     46 
     47 #include <linux/module.h>
     48 #include <linux/kernel.h>
     49 #include <linux/netdevice.h>
     50 #include <linux/etherdevice.h>
     51 #include <linux/vmalloc.h>
     52 #include <linux/string.h>
     53 #include <linux/delay.h>
     54 #include <linux/time.h>
     55 #include <linux/list.h>
     56 
     57 #include "osApi.h"
     58 #include "tidef.h"
     59 #include "WlanDrvIf.h"
     60 
     61 typedef void (*os_free)(void *);
     62 struct os_mem_block
     63 {
     64 	struct list_head blk_list;
     65 	os_free f_free;
     66 	__u32 size;
     67 	__u32 signature;
     68 };
     69 #define MEM_BLOCK_START  (('m'<<24) | ('e'<<16) | ('m'<<8) | 's')
     70 #define MEM_BLOCK_END    (('m'<<24) | ('e'<<16) | ('m'<<8) | 'e')
     71 
     72 /****************************************************************************************
     73  *                        																*
     74  *						OS Memory API													*
     75  *																						*
     76  ****************************************************************************************/
     77 
     78 /****************************************************************************************
     79  *                        os_memoryAlloc()
     80  ****************************************************************************************
     81 DESCRIPTION:    Allocates resident (nonpaged) system-space memory.
     82 
     83 ARGUMENTS:		OsContext	- our adapter context.
     84 				Size		- Specifies the size, in bytes, to be allocated.
     85 
     86 RETURN:			Pointer to the allocated memory.
     87 				NULL if there is insufficient memory available.
     88 
     89 NOTES:         	With the call to vmalloc it is assumed that this function will
     90 				never be called in an interrupt context. vmalloc has the potential to
     91 				sleep the caller while waiting for memory to become available.
     92 
     93 *****************************************************************************************/
     94 void*
     95 os_memoryAlloc(
     96         TI_HANDLE OsContext,
     97         TI_UINT32 Size
     98         )
     99 {
    100 	struct os_mem_block *blk;
    101 	__u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32);
    102 	gfp_t flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
    103 
    104 #ifdef TI_MEM_ALLOC_TRACE
    105 	os_printf("MTT:%s:%d ::os_memoryAlloc(0x%p, %lu) : %lu\n",__FUNCTION__, __LINE__,OsContext,Size,total_size);
    106 #endif
    107 	/*
    108 	Memory optimization issue. Allocate up to 2 pages (8k) from the SLAB
    109 	    allocator (2^n), otherwise allocate from virtual pool.
    110 	If full Async mode is used, allow up to 6 pages (24k) for DMA-able
    111 	  memory, so the TxCtrlBlk table can be transacted over DMA.
    112 	*/
    113 #ifdef FULL_ASYNC_MODE
    114 	if (total_size < 6 * 4096)
    115 #else
    116 	if (total_size < 2 * 4096)
    117 #endif
    118 	{
    119 		blk = kmalloc(total_size, flags);
    120 		if (!blk)
    121 		{
    122 			printk("%s: NULL\n",__func__);
    123 			return NULL;
    124 		}
    125 		blk->f_free = (os_free)kfree;
    126 	}
    127 	else
    128 	{
    129 		/* We expect that the big allocations should be made outside
    130 		     the interrupt, otherwise fail
    131 		*/
    132 		if (in_interrupt()) {
    133 			printk("%s: NULL\n",__func__);
    134 			return NULL;
    135 		}
    136 	        blk = vmalloc(total_size);
    137 	        if (!blk) {
    138 			printk("%s: NULL\n",__func__);
    139 			return NULL;
    140 		}
    141 		blk->f_free = (os_free)vfree;
    142 	}
    143 
    144 	os_profile (OsContext, 4, total_size);
    145 
    146 	/*list_add(&blk->blk_list, &drv->mem_blocks);*/
    147 	blk->size = Size;
    148 	blk->signature = MEM_BLOCK_START;
    149 	*(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END;
    150 	return (void *)((char *)blk + sizeof(struct os_mem_block));
    151 }
    152 
    153 
    154 /****************************************************************************************
    155  *                        os_memoryCAlloc()
    156  ****************************************************************************************
    157 DESCRIPTION:    Allocates an array in memory with elements initialized to 0.
    158 
    159 ARGUMENTS:		OsContext	-	our adapter context.
    160 				Number		-	Number of elements
    161 				Size		-	Length in bytes of each element
    162 
    163 RETURN:			None
    164 
    165 NOTES:
    166 *****************************************************************************************/
    167 void*
    168 os_memoryCAlloc(
    169         TI_HANDLE OsContext,
    170         TI_UINT32 Number,
    171         TI_UINT32 Size
    172         )
    173 {
    174 	void* pAllocatedMem;
    175 	TI_UINT32 MemSize;
    176 
    177 #ifdef TI_MEM_ALLOC_TRACE
    178 	os_printf("MTT:%s:%d ::os_memoryCAlloc(0x%p, %lu, %lu) : %lu\n",__FUNCTION__,__LINE__,OsContext,Number,Size,Number*Size);
    179 #endif
    180 	MemSize = Number * Size;
    181 
    182 	pAllocatedMem = os_memoryAlloc(OsContext, MemSize);
    183 
    184 	if (!pAllocatedMem)
    185 		return NULL;
    186 
    187 	memset(pAllocatedMem,0,MemSize);
    188 
    189 	return pAllocatedMem;
    190 }
    191 
    192 
    193 
    194 /****************************************************************************************
    195  *                        os_memoryFree()
    196  ****************************************************************************************
    197 DESCRIPTION:    This function releases a block of memory previously allocated with the
    198 				os_memoryAlloc function.
    199 
    200 
    201 ARGUMENTS:		OsContext	-	our adapter context.
    202 				pMemPtr		-	Pointer to the base virtual address of the allocated memory.
    203 								This address was returned by the os_memoryAlloc function.
    204 				Size		-	Specifies the size, in bytes, of the memory block to be released.
    205 								This parameter must be identical to the Length that was passed to
    206 								os_memoryAlloc.
    207 
    208 RETURN:			None
    209 
    210 NOTES:
    211 *****************************************************************************************/
    212 void
    213 os_memoryFree(
    214         TI_HANDLE OsContext,
    215         void* pMemPtr,
    216         TI_UINT32 Size
    217         )
    218 {
    219 	struct os_mem_block *blk;
    220 
    221 	if (!pMemPtr) {
    222 		printk("%s: NULL\n",__func__);
    223 		return;
    224 	}
    225 	blk = (struct os_mem_block *)((char *)pMemPtr - sizeof(struct os_mem_block));
    226 
    227 #ifdef TI_MEM_ALLOC_TRACE
    228 	os_printf("MTT:%s:%d ::os_memoryFree(0x%p, 0x%p, %lu) : %d\n",__FUNCTION__,__LINE__,OsContext,pMemPtr,Size,-Size);
    229 #endif
    230 	if (blk->signature != MEM_BLOCK_START)
    231 	{
    232 		printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n",
    233 			__FUNCTION__, blk->signature);
    234 		return;
    235 	}
    236 	*(char *)(&blk->signature) = '~';
    237 	if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block))
    238 		!= MEM_BLOCK_END)
    239 	{
    240 		printk("\n\n%s: memory block corruption. Size=%u\n\n\n",
    241 			__FUNCTION__, blk->size);
    242 	}
    243 
    244 	os_profile (OsContext, 5, blk->size + sizeof(struct os_mem_block) + sizeof(__u32));
    245 	blk->f_free(blk);
    246 }
    247 
    248 
    249 /****************************************************************************************
    250  *                        os_memorySet()
    251  ****************************************************************************************
    252 DESCRIPTION:    This function fills a block of memory with given value.
    253 
    254 ARGUMENTS:		OsContext	- our adapter context.
    255 				pMemPtr		- Specifies the base address of a block of memory
    256 				Value		- Specifies the value to set
    257 				Length		- Specifies the size, in bytes, to copy.
    258 
    259 RETURN:			None
    260 
    261 NOTES:
    262 *****************************************************************************************/
    263 void
    264 os_memorySet(
    265     TI_HANDLE OsContext,
    266     void* pMemPtr,
    267     TI_INT32 Value,
    268     TI_UINT32 Length
    269     )
    270 {
    271 	if (!pMemPtr) {
    272 		printk("%s: NULL\n",__func__);
    273 		return;
    274 	}
    275 	memset(pMemPtr,Value,Length);
    276 }
    277 
    278 /****************************************************************************************
    279  *                        _os_memoryAlloc4HwDma()
    280  ****************************************************************************************
    281 DESCRIPTION:    Allocates resident (nonpaged) system-space memory for DMA operations.
    282 
    283 ARGUMENTS:		OsContext	- our adapter context.
    284 				Size		- Specifies the size, in bytes, to be allocated.
    285 
    286 RETURN:			Pointer to the allocated memory.
    287 				NULL if there is insufficient memory available.
    288 
    289 NOTES:
    290 
    291 *****************************************************************************************/
    292 void*
    293 os_memoryAlloc4HwDma(
    294     TI_HANDLE pOsContext,
    295     TI_UINT32 Size
    296     )
    297 {
    298 	struct os_mem_block *blk;
    299 	__u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32);
    300 	gfp_t flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
    301 
    302 	/*
    303 	if the size is greater than 2 pages then we cant allocate the memory
    304 	    through kmalloc so the function fails
    305 	*/
    306 	if (Size < 2 * OS_PAGE_SIZE)
    307 	{
    308 		blk = kmalloc(total_size, flags | GFP_DMA);
    309 		if (!blk) {
    310 			printk("%s: NULL\n",__func__);
    311 			return NULL;
    312 		}
    313 		blk->f_free = (os_free)kfree;
    314 	}
    315 	else
    316 	{
    317 		printk("\n\n%s: memory cant be allocated-Size = %d\n\n\n",
    318 			__FUNCTION__, Size);
    319 		return NULL;
    320 	}
    321 	blk->size = Size;
    322 	blk->signature = MEM_BLOCK_START;
    323 	*(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END;
    324 
    325 	return (void *)((char *)blk + sizeof(struct os_mem_block));
    326 }
    327 
    328 /****************************************************************************************
    329  *                        _os_memory4HwDmaFree()
    330  ****************************************************************************************
    331 DESCRIPTION:    This function releases a block of memory previously allocated with the
    332 				_os_memoryAlloc4HwDma function.
    333 
    334 
    335 ARGUMENTS:		OsContext	-	our adapter context.
    336 				pMemPtr		-	Pointer to the base virtual address of the allocated memory.
    337 								This address was returned by the os_memoryAlloc function.
    338 				Size		-	Specifies the size, in bytes, of the memory block to be released.
    339 								This parameter must be identical to the Length that was passed to
    340 								os_memoryAlloc.
    341 
    342 RETURN:			None
    343 
    344 NOTES:
    345 *****************************************************************************************/
    346 void
    347 os_memory4HwDmaFree(
    348     TI_HANDLE pOsContext,
    349     void* pMem_ptr,
    350     TI_UINT32 Size
    351     )
    352 {
    353 	struct os_mem_block *blk;
    354 
    355 	if (!pMem_ptr) {
    356 		printk("%s: NULL\n",__func__);
    357 		return;
    358 	}
    359 	blk = (struct os_mem_block *)((char *)pMem_ptr - sizeof(struct os_mem_block));
    360 
    361 	if (blk->signature != MEM_BLOCK_START)
    362 	{
    363 		printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n",
    364 			__FUNCTION__, blk->signature);
    365 		return;
    366 	}
    367 	*(char *)(&blk->signature) = '~';
    368 	if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block))
    369 		!= MEM_BLOCK_END)
    370 	{
    371 		printk("\n\n%s: memory block corruption. Size=%u\n\n\n",
    372 			__FUNCTION__, blk->size);
    373 	}
    374 
    375 	blk->f_free(blk);
    376 }
    377 
    378 /****************************************************************************************
    379  *                        os_memoryZero()
    380  ****************************************************************************************
    381 DESCRIPTION:    This function fills a block of memory with 0s.
    382 
    383 ARGUMENTS:		OsContext	- our adapter context.
    384 				pMemPtr		- Specifies the base address of a block of memory
    385 				Length		- Specifies how many bytes to fill with 0s.
    386 
    387 RETURN:			None
    388 
    389 NOTES:
    390 *****************************************************************************************/
    391 void
    392 os_memoryZero(
    393     TI_HANDLE OsContext,
    394     void* pMemPtr,
    395     TI_UINT32 Length
    396     )
    397 {
    398 	if (!pMemPtr) {
    399 		printk("%s: NULL\n",__func__);
    400 		return;
    401 	}
    402 	memset(pMemPtr,0,Length);
    403 }
    404 
    405 
    406 /****************************************************************************************
    407  *                        os_memoryCopy()
    408  ****************************************************************************************
    409 DESCRIPTION:    This function copies a specified number of bytes from one caller-supplied
    410 				location to another.
    411 
    412 ARGUMENTS:		OsContext	- our adapter context.
    413 				pDstPtr		- Destination buffer
    414 				pSrcPtr		- Source buffer
    415 				Size		- Specifies the size, in bytes, to copy.
    416 
    417 RETURN:			None
    418 
    419 NOTES:
    420 *****************************************************************************************/
    421 void
    422 os_memoryCopy(
    423     TI_HANDLE OsContext,
    424     void* pDstPtr,
    425     void* pSrcPtr,
    426     TI_UINT32 Size
    427     )
    428 {
    429 
    430 	memcpy(pDstPtr,pSrcPtr,Size);
    431 }
    432 
    433 /****************************************************************************************
    434  *                        os_memoryCompare()
    435  ****************************************************************************************
    436 DESCRIPTION:    Compare characters in two buffers.
    437 
    438 ARGUMENTS:		OsContext	- our adapter context.
    439 				Buf1		- First buffer
    440 				Buf2		- Second buffer
    441 				Count		- Number of characters
    442 
    443 RETURN:			The return value indicates the relationship between the buffers:
    444                 < 0 Buf1 less than Buf2
    445                 0 Buf1 identical to Buf2
    446                 > 0 Buf1 greater than Buf2
    447 
    448 NOTES:
    449 *****************************************************************************************/
    450 TI_INT32
    451 os_memoryCompare(
    452         TI_HANDLE OsContext,
    453         TI_UINT8* Buf1,
    454         TI_UINT8* Buf2,
    455         TI_INT32 Count
    456         )
    457 {
    458 	return memcmp(Buf1, Buf2, Count);
    459 }
    460 
    461 
    462 
    463 
    464 /****************************************************************************************
    465  *                        os_memoryCopyFromUser()
    466  ****************************************************************************************
    467 DESCRIPTION:    This function copies a specified number of bytes from one caller-supplied
    468 				location to another. source buffer is in USER-MODE address space
    469 
    470 ARGUMENTS:		OsContext	- our adapter context.
    471 				pDstPtr		- Destination buffer
    472 				pSrcPtr		- Source buffer
    473 				Size		- Specifies the size, in bytes, to copy.
    474 
    475 RETURN:			None
    476 
    477 NOTES:
    478 *****************************************************************************************/
    479 int
    480 os_memoryCopyFromUser(
    481     TI_HANDLE OsContext,
    482     void* pDstPtr,
    483     void* pSrcPtr,
    484     TI_UINT32 Size
    485     )
    486 {
    487 	return copy_from_user(pDstPtr,pSrcPtr,Size);
    488 }
    489 
    490 /****************************************************************************************
    491  *                        os_memoryCopyToUser()
    492  ****************************************************************************************
    493 DESCRIPTION:    This function copies a specified number of bytes from one caller-supplied
    494 				location to another. desination buffer is in USER-MODE address space
    495 
    496 ARGUMENTS:		OsContext	- our adapter context.
    497 				pDstPtr		- Destination buffer
    498 				pSrcPtr		- Source buffer
    499 				Size		- Specifies the size, in bytes, to copy.
    500 
    501 RETURN:			None
    502 
    503 NOTES:
    504 *****************************************************************************************/
    505 int
    506 os_memoryCopyToUser(
    507     TI_HANDLE OsContext,
    508     void* pDstPtr,
    509     void* pSrcPtr,
    510     TI_UINT32 Size
    511     )
    512 {
    513 	return copy_to_user(pDstPtr,pSrcPtr,Size);
    514 }
    515