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 
    103 #ifdef TI_MEM_ALLOC_TRACE
    104 	os_printf("MTT:%s:%d ::os_memoryAlloc(0x%p, %lu) : %lu\n",__FUNCTION__, __LINE__,OsContext,Size,total_size);
    105 #endif
    106 	/*
    107 	Memory optimization issue. Allocate up to 2 pages (8k) from the SLAB
    108 	    allocator (2^n), otherwise allocate from virtual pool.
    109 	If full Async mode is used, allow up to 6 pages (24k) for DMA-able
    110 	  memory, so the TxCtrlBlk table can be transacted over DMA.
    111 	*/
    112 #ifdef FULL_ASYNC_MODE
    113 	if (total_size < 6 * 4096)
    114 #else
    115 	if (total_size < 2 * 4096)
    116 #endif
    117 	{
    118 		if (in_atomic())
    119 			blk = kmalloc(total_size, GFP_ATOMIC);
    120 		else
    121 			blk = kmalloc(total_size, GFP_KERNEL);
    122 		if (!blk) {
    123 			printk("%s: NULL\n",__func__);
    124 			return NULL;
    125 		}
    126 		blk->f_free = (os_free)kfree;
    127 	}
    128 	else {
    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 
    246 	blk->f_free(blk);
    247 }
    248 
    249 
    250 /****************************************************************************************
    251  *                        os_memorySet()
    252  ****************************************************************************************
    253 DESCRIPTION:    This function fills a block of memory with given value.
    254 
    255 ARGUMENTS:		OsContext	- our adapter context.
    256 				pMemPtr		- Specifies the base address of a block of memory
    257 				Value		- Specifies the value to set
    258 				Length		- Specifies the size, in bytes, to copy.
    259 
    260 RETURN:			None
    261 
    262 NOTES:
    263 *****************************************************************************************/
    264 void
    265 os_memorySet(
    266     TI_HANDLE OsContext,
    267     void* pMemPtr,
    268     TI_INT32 Value,
    269     TI_UINT32 Length
    270     )
    271 {
    272 	if (!pMemPtr) {
    273 		printk("%s: NULL\n",__func__);
    274 		return;
    275 	}
    276 	memset(pMemPtr,Value,Length);
    277 }
    278 
    279 /****************************************************************************************
    280  *                        _os_memoryAlloc4HwDma()
    281  ****************************************************************************************
    282 DESCRIPTION:    Allocates resident (nonpaged) system-space memory for DMA operations.
    283 
    284 ARGUMENTS:		OsContext	- our adapter context.
    285 				Size		- Specifies the size, in bytes, to be allocated.
    286 
    287 RETURN:			Pointer to the allocated memory.
    288 				NULL if there is insufficient memory available.
    289 
    290 NOTES:
    291 
    292 *****************************************************************************************/
    293 void*
    294 os_memoryAlloc4HwDma(
    295     TI_HANDLE pOsContext,
    296     TI_UINT32 Size
    297     )
    298 {
    299 	struct os_mem_block *blk;
    300 	__u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32);
    301 	/*
    302 	if the size is greater than 2 pages then we cant allocate the memory
    303 	    through kmalloc so the function fails
    304 	*/
    305 	if (Size < 2 * OS_PAGE_SIZE)
    306 	{
    307 		blk = kmalloc(total_size, GFP_ATOMIC|GFP_DMA);
    308 		if (!blk) {
    309 			printk("%s: NULL\n",__func__);
    310 			return NULL;
    311 		}
    312 		blk->f_free = (os_free)kfree;
    313 	}
    314 	else
    315 	{
    316 		printk("\n\n%s: memory cant be allocated-Size = %d\n\n\n",
    317 			__FUNCTION__, Size);
    318 		return NULL;
    319 	}
    320 	blk->size = Size;
    321 	blk->signature = MEM_BLOCK_START;
    322 	*(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END;
    323 
    324 	return (void *)((char *)blk + sizeof(struct os_mem_block));
    325 }
    326 
    327 /****************************************************************************************
    328  *                        _os_memory4HwDmaFree()
    329  ****************************************************************************************
    330 DESCRIPTION:    This function releases a block of memory previously allocated with the
    331 				_os_memoryAlloc4HwDma function.
    332 
    333 
    334 ARGUMENTS:		OsContext	-	our adapter context.
    335 				pMemPtr		-	Pointer to the base virtual address of the allocated memory.
    336 								This address was returned by the os_memoryAlloc function.
    337 				Size		-	Specifies the size, in bytes, of the memory block to be released.
    338 								This parameter must be identical to the Length that was passed to
    339 								os_memoryAlloc.
    340 
    341 RETURN:			None
    342 
    343 NOTES:
    344 *****************************************************************************************/
    345 void
    346 os_memory4HwDmaFree(
    347     TI_HANDLE pOsContext,
    348     void* pMem_ptr,
    349     TI_UINT32 Size
    350     )
    351 {
    352 	struct os_mem_block *blk;
    353 
    354 	if (!pMem_ptr) {
    355 		printk("%s: NULL\n",__func__);
    356 		return;
    357 	}
    358 	blk = (struct os_mem_block *)((char *)pMem_ptr - sizeof(struct os_mem_block));
    359 
    360 	if (blk->signature != MEM_BLOCK_START)
    361 	{
    362 		printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n",
    363 			__FUNCTION__, blk->signature);
    364 		return;
    365 	}
    366 	*(char *)(&blk->signature) = '~';
    367 	if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block))
    368 		!= MEM_BLOCK_END)
    369 	{
    370 		printk("\n\n%s: memory block corruption. Size=%u\n\n\n",
    371 			__FUNCTION__, blk->size);
    372 	}
    373 
    374 	blk->f_free(blk);
    375 }
    376 
    377 /****************************************************************************************
    378  *                        os_memoryZero()
    379  ****************************************************************************************
    380 DESCRIPTION:    This function fills a block of memory with 0s.
    381 
    382 ARGUMENTS:		OsContext	- our adapter context.
    383 				pMemPtr		- Specifies the base address of a block of memory
    384 				Length		- Specifies how many bytes to fill with 0s.
    385 
    386 RETURN:			None
    387 
    388 NOTES:
    389 *****************************************************************************************/
    390 void
    391 os_memoryZero(
    392     TI_HANDLE OsContext,
    393     void* pMemPtr,
    394     TI_UINT32 Length
    395     )
    396 {
    397 	if (!pMemPtr) {
    398 		printk("%s: NULL\n",__func__);
    399 		return;
    400 	}
    401 	memset(pMemPtr,0,Length);
    402 }
    403 
    404 
    405 /****************************************************************************************
    406  *                        os_memoryCopy()
    407  ****************************************************************************************
    408 DESCRIPTION:    This function copies a specified number of bytes from one caller-supplied
    409 				location to another.
    410 
    411 ARGUMENTS:		OsContext	- our adapter context.
    412 				pDstPtr		- Destination buffer
    413 				pSrcPtr		- Source buffer
    414 				Size		- Specifies the size, in bytes, to copy.
    415 
    416 RETURN:			None
    417 
    418 NOTES:
    419 *****************************************************************************************/
    420 void
    421 os_memoryCopy(
    422     TI_HANDLE OsContext,
    423     void* pDstPtr,
    424     void* pSrcPtr,
    425     TI_UINT32 Size
    426     )
    427 {
    428 
    429 	memcpy(pDstPtr,pSrcPtr,Size);
    430 }
    431 
    432 /****************************************************************************************
    433  *                        os_memoryCompare()
    434  ****************************************************************************************
    435 DESCRIPTION:    Compare characters in two buffers.
    436 
    437 ARGUMENTS:		OsContext	- our adapter context.
    438 				Buf1		- First buffer
    439 				Buf2		- Second buffer
    440 				Count		- Number of characters
    441 
    442 RETURN:			The return value indicates the relationship between the buffers:
    443                 < 0 Buf1 less than Buf2
    444                 0 Buf1 identical to Buf2
    445                 > 0 Buf1 greater than Buf2
    446 
    447 NOTES:
    448 *****************************************************************************************/
    449 TI_INT32
    450 os_memoryCompare(
    451         TI_HANDLE OsContext,
    452         TI_UINT8* Buf1,
    453         TI_UINT8* Buf2,
    454         TI_INT32 Count
    455         )
    456 {
    457 	return memcmp(Buf1, Buf2, Count);
    458 }
    459 
    460 
    461 
    462 
    463 /****************************************************************************************
    464  *                        os_memoryCopyFromUser()
    465  ****************************************************************************************
    466 DESCRIPTION:    This function copies a specified number of bytes from one caller-supplied
    467 				location to another. source buffer is in USER-MODE address space
    468 
    469 ARGUMENTS:		OsContext	- our adapter context.
    470 				pDstPtr		- Destination buffer
    471 				pSrcPtr		- Source buffer
    472 				Size		- Specifies the size, in bytes, to copy.
    473 
    474 RETURN:			None
    475 
    476 NOTES:
    477 *****************************************************************************************/
    478 int
    479 os_memoryCopyFromUser(
    480     TI_HANDLE OsContext,
    481     void* pDstPtr,
    482     void* pSrcPtr,
    483     TI_UINT32 Size
    484     )
    485 {
    486 	return copy_from_user(pDstPtr,pSrcPtr,Size);
    487 }
    488 
    489 /****************************************************************************************
    490  *                        os_memoryCopyToUser()
    491  ****************************************************************************************
    492 DESCRIPTION:    This function copies a specified number of bytes from one caller-supplied
    493 				location to another. desination buffer is in USER-MODE address space
    494 
    495 ARGUMENTS:		OsContext	- our adapter context.
    496 				pDstPtr		- Destination buffer
    497 				pSrcPtr		- Source buffer
    498 				Size		- Specifies the size, in bytes, to copy.
    499 
    500 RETURN:			None
    501 
    502 NOTES:
    503 *****************************************************************************************/
    504 int
    505 os_memoryCopyToUser(
    506     TI_HANDLE OsContext,
    507     void* pDstPtr,
    508     void* pSrcPtr,
    509     TI_UINT32 Size
    510     )
    511 {
    512 	return copy_to_user(pDstPtr,pSrcPtr,Size);
    513 }
    514