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
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*
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
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
os_memorySet(TI_HANDLE OsContext,void * pMemPtr,TI_INT32 Value,TI_UINT32 Length)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*
os_memoryAlloc4HwDma(TI_HANDLE pOsContext,TI_UINT32 Size)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
os_memory4HwDmaFree(TI_HANDLE pOsContext,void * pMem_ptr,TI_UINT32 Size)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
os_memoryZero(TI_HANDLE OsContext,void * pMemPtr,TI_UINT32 Length)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
os_memoryCopy(TI_HANDLE OsContext,void * pDstPtr,void * pSrcPtr,TI_UINT32 Size)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
os_memoryCompare(TI_HANDLE OsContext,TI_UINT8 * Buf1,TI_UINT8 * Buf2,TI_INT32 Count)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
os_memoryCopyFromUser(TI_HANDLE OsContext,void * pDstPtr,void * pSrcPtr,TI_UINT32 Size)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
os_memoryCopyToUser(TI_HANDLE OsContext,void * pDstPtr,void * pSrcPtr,TI_UINT32 Size)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