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