• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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*
os_memoryAlloc(TI_HANDLE OsContext,TI_UINT32 Size)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*
os_memoryCAlloc(TI_HANDLE OsContext,TI_UINT32 Number,TI_UINT32 Size)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
os_memoryFree(TI_HANDLE OsContext,void * pMemPtr,TI_UINT32 Size)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
os_memorySet(TI_HANDLE OsContext,void * pMemPtr,TI_INT32 Value,TI_UINT32 Length)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*
os_memoryAlloc4HwDma(TI_HANDLE pOsContext,TI_UINT32 Size)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
os_memory4HwDmaFree(TI_HANDLE pOsContext,void * pMem_ptr,TI_UINT32 Size)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
os_memoryZero(TI_HANDLE OsContext,void * pMemPtr,TI_UINT32 Length)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
os_memoryCopy(TI_HANDLE OsContext,void * pDstPtr,void * pSrcPtr,TI_UINT32 Size)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
os_memoryCompare(TI_HANDLE OsContext,TI_UINT8 * Buf1,TI_UINT8 * Buf2,TI_INT32 Count)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
os_memoryCopyFromUser(TI_HANDLE OsContext,void * pDstPtr,void * pSrcPtr,TI_UINT32 Size)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
os_memoryCopyToUser(TI_HANDLE OsContext,void * pDstPtr,void * pSrcPtr,TI_UINT32 Size)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