1 /****************************************************************************
2 **+-----------------------------------------------------------------------+**
3 **| |**
4 **| Copyright(c) 1998 - 2008 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
37 #include "arch_ti.h"
38
39 #include <linux/stddef.h>
40 #include <linux/string.h>
41 #include <linux/time.h>
42 #include <linux/timer.h>
43
44 #include <linux/module.h>
45 #include <linux/kernel.h>
46 #include <linux/netdevice.h>
47 #include <linux/etherdevice.h>
48 #include <linux/vmalloc.h>
49 #include <linux/string.h>
50 #include <linux/delay.h>
51 #include <linux/time.h>
52 #include <linux/list.h>
53
54 #include "osApi.h"
55 #include "osTIType.h"
56 #include "esta_drv.h"
57
58 typedef void (*os_free)(void *);
59 struct os_mem_block
60 {
61 struct list_head blk_list;
62 os_free f_free;
63 __u32 size;
64 __u32 signature;
65 };
66 #define MEM_BLOCK_START (('m'<<24) | ('e'<<16) | ('m'<<8) | 's')
67 #define MEM_BLOCK_END (('m'<<24) | ('e'<<16) | ('m'<<8) | 'e')
68
69 /****************************************************************************************
70 * *
71 * OS Memory API *
72 * *
73 ****************************************************************************************/
74
75 /****************************************************************************************
76 * os_memoryAlloc()
77 ****************************************************************************************
78 DESCRIPTION: Allocates resident (nonpaged) system-space memory.
79
80 ARGUMENTS: OsContext - our adapter context.
81 Size - Specifies the size, in bytes, to be allocated.
82
83 RETURN: Pointer to the allocated memory.
84 NULL if there is insufficient memory available.
85
86 NOTES: With the call to vmalloc it is assumed that this function will
87 never be called in an interrupt context. vmalloc has the potential to
88 sleep the caller while waiting for memory to become available.
89
90 *****************************************************************************************/
91 PVOID
os_memoryAlloc(TI_HANDLE OsContext,UINT32 Size)92 os_memoryAlloc(
93 TI_HANDLE OsContext,
94 UINT32 Size
95 )
96 {
97 struct os_mem_block *blk;
98 __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32);
99
100 #ifdef TI_MEM_ALLOC_TRACE
101 os_printf("MTT:%s:%d ::os_memoryAlloc(0x%p, %lu) : %lu\n",__FUNCTION__, __LINE__,OsContext,Size,total_size);
102 #endif
103 if( total_size < Size ) { /* Dm: Security fix */
104 return NULL;
105 }
106 /*
107 memory optimization issue. Allocate 8 kB and less from the SLAB allocator (2^n)
108 otherwise allocate from virtual pool.
109 */
110 /* 2 pages */
111 if (total_size < 2 * 4096)
112 {
113 if (in_atomic())
114 blk = kmalloc(total_size, GFP_ATOMIC);
115 else
116 blk = kmalloc(total_size, GFP_KERNEL);
117 if (!blk)
118 return NULL;
119 blk->f_free = (os_free)kfree;
120 }
121 else
122 {
123 /* We expect that the big allocations should be made outside the interrupt,
124 otherwise fail
125 */
126 if (in_atomic())
127 return NULL;
128 blk = vmalloc(total_size);
129 if (!blk)
130 return NULL;
131 blk->f_free = (os_free)vfree;
132 }
133
134 os_profile (OsContext, 4, total_size);
135
136 /*list_add(&blk->blk_list, &drv->mem_blocks);*/
137 blk->size = Size;
138 blk->signature = MEM_BLOCK_START;
139 *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END;
140 return (PVOID)((char *)blk + sizeof(struct os_mem_block));
141 }
142
143 /****************************************************************************************
144 * os_memoryPreFree()
145 ****************************************************************************************
146 DESCRIPTION: Frees preallocated by the kernel memory.
147
148 ARGUMENTS: ptr - pointer to memory
149 *****************************************************************************************/
os_memoryPreFree(void * ptr)150 void os_memoryPreFree( void *ptr )
151 {
152 }
153
154 /****************************************************************************************
155 * os_memoryPreAlloc()
156 ****************************************************************************************
157 DESCRIPTION: Gets system-space memory preallocated by kernel.
158
159 ARGUMENTS: OsContext - our adapter context.
160 section - section number
161 Size - Specifies the size, in bytes, to be allocated.
162
163 RETURN: Pointer to the allocated memory.
164 NULL if there is insufficient memory available.
165 *****************************************************************************************/
166 PVOID
os_memoryPreAlloc(TI_HANDLE OsContext,int section,UINT32 Size)167 os_memoryPreAlloc(
168 TI_HANDLE OsContext,
169 int section,
170 UINT32 Size
171 )
172 {
173 struct os_mem_block *blk;
174 __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32);
175
176 #ifdef TI_MEM_ALLOC_TRACE
177 os_printf("MTT:%s:%d ::os_memoryPreAlloc(0x%p, %lu) : %lu\n",__FUNCTION__, __LINE__,OsContext,Size,total_size);
178 #endif
179 if( total_size < Size ) { /* Dm: Security fix */
180 return NULL;
181 }
182
183 blk = (struct os_mem_block *)wifi_kernel_prealloc( section, total_size );
184 if( !blk ) {
185 return os_memoryAlloc(OsContext, Size);
186 }
187 blk->f_free = (os_free)os_memoryPreFree;
188
189 os_profile (OsContext, 4, total_size);
190
191 /*list_add(&blk->blk_list, &drv->mem_blocks);*/
192 blk->size = Size;
193 blk->signature = MEM_BLOCK_START;
194 *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END;
195 return (PVOID)((char *)blk + sizeof(struct os_mem_block));
196 }
197
198
199 /****************************************************************************************
200 * os_memoryCAlloc()
201 ****************************************************************************************
202 DESCRIPTION: Allocates an array in memory with elements initialized to 0.
203
204 ARGUMENTS: OsContext - our adapter context.
205 Number - Number of elements
206 Size - Length in bytes of each element
207
208 RETURN: None
209
210 NOTES:
211 *****************************************************************************************/
212 PVOID
os_memoryCAlloc(TI_HANDLE OsContext,UINT32 Number,UINT32 Size)213 os_memoryCAlloc(
214 TI_HANDLE OsContext,
215 UINT32 Number,
216 UINT32 Size
217 )
218 {
219 PVOID pAllocatedMem;
220 ULONG MemSize;
221
222 #ifdef TI_MEM_ALLOC_TRACE
223 os_printf("MTT:%s:%d ::os_memoryCAlloc(0x%p, %lu, %lu) : %lu\n",__FUNCTION__,__LINE__,OsContext,Number,Size,Number*Size);
224 #endif
225 MemSize = Number * Size;
226
227 if( (Number > 0) && (Size >= (0xFFFFFFFFUL / Number)) ) { /* Dm: Security fix */
228 return NULL;
229 }
230
231 pAllocatedMem = os_memoryAlloc(OsContext, MemSize);
232
233 if(!pAllocatedMem)
234 return NULL;
235
236 memset(pAllocatedMem,0,MemSize);
237
238 return pAllocatedMem;
239 }
240
241 /****************************************************************************************
242 * os_memoryFree()
243 ****************************************************************************************
244 DESCRIPTION: This function releases a block of memory previously allocated with the
245 os_memoryAlloc function.
246
247
248 ARGUMENTS: OsContext - our adapter context.
249 pMemPtr - Pointer to the base virtual address of the allocated memory.
250 This address was returned by the os_memoryAlloc function.
251 Size - Specifies the size, in bytes, of the memory block to be released.
252 This parameter must be identical to the Length that was passed to
253 os_memoryAlloc.
254
255 RETURN: None
256
257 NOTES:
258 *****************************************************************************************/
259 VOID
os_memoryFree(TI_HANDLE OsContext,PVOID pMemPtr,UINT32 Size)260 os_memoryFree(
261 TI_HANDLE OsContext,
262 PVOID pMemPtr,
263 UINT32 Size
264 )
265 {
266 struct os_mem_block *blk =
267 (struct os_mem_block *)((char *)pMemPtr - sizeof(struct os_mem_block));
268
269 #ifdef TI_MEM_ALLOC_TRACE
270 os_printf("MTT:%s:%d ::os_memoryFree(0x%p, 0x%p, %lu) : %d\n",__FUNCTION__,__LINE__,OsContext,pMemPtr,Size,-Size);
271 #endif
272 if (blk->signature != MEM_BLOCK_START)
273 {
274 printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n",
275 __FUNCTION__, blk->signature);
276 return;
277 }
278 *(char *)(&blk->signature) = '~';
279 if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block))
280 != MEM_BLOCK_END)
281 {
282 printk("\n\n%s: memory block corruption. Size=%u\n\n\n",
283 __FUNCTION__, blk->size);
284 }
285
286 os_profile (OsContext, 5, blk->size + sizeof(struct os_mem_block) + sizeof(__u32));
287
288 blk->f_free(blk);
289 }
290
291
292 /****************************************************************************************
293 * os_memorySet()
294 ****************************************************************************************
295 DESCRIPTION: This function fills a block of memory with given value.
296
297 ARGUMENTS: OsContext - our adapter context.
298 pMemPtr - Specifies the base address of a block of memory
299 Value - Specifies the value to set
300 Length - Specifies the size, in bytes, to copy.
301
302 RETURN: None
303
304 NOTES:
305 *****************************************************************************************/
306 VOID
os_memorySet(TI_HANDLE OsContext,PVOID pMemPtr,INT32 Value,UINT32 Length)307 os_memorySet(
308 TI_HANDLE OsContext,
309 PVOID pMemPtr,
310 INT32 Value,
311 UINT32 Length
312 )
313 {
314 memset(pMemPtr,Value,Length);
315 }
316
317 /****************************************************************************************
318 * _os_memoryAlloc4HwDma()
319 ****************************************************************************************
320 DESCRIPTION: Allocates resident (nonpaged) system-space memory for DMA operations.
321
322 ARGUMENTS: OsContext - our adapter context.
323 Size - Specifies the size, in bytes, to be allocated.
324
325 RETURN: Pointer to the allocated memory.
326 NULL if there is insufficient memory available.
327
328 NOTES:
329
330 *****************************************************************************************/
331 PVOID
os_memoryAlloc4HwDma(TI_HANDLE pOsContext,UINT32 Size)332 os_memoryAlloc4HwDma(
333 TI_HANDLE pOsContext,
334 UINT32 Size
335 )
336 {
337 struct os_mem_block *blk;
338 __u32 total_size = Size + sizeof(struct os_mem_block) + sizeof(__u32);
339 /*
340 if the size is greater than 2 pages then we cant allocate the memory through kmalloc so the function fails
341 */
342 if (Size < 2 * OS_PAGE_SIZE)
343 {
344 blk = kmalloc(total_size, GFP_ATOMIC);
345 if (!blk)
346 return NULL;
347 blk->f_free = (os_free)kfree;
348 }
349 else
350 {
351 printk("\n\n%s: memory cant be allocated-Size = %d\n\n\n",
352 __FUNCTION__, Size);
353 return NULL;
354 }
355
356 blk->size = Size;
357 blk->signature = MEM_BLOCK_START;
358 *(__u32 *)((unsigned char *)blk + total_size - sizeof(__u32)) = MEM_BLOCK_END;
359 return (PVOID)((char *)blk + sizeof(struct os_mem_block));
360 }
361
362 /****************************************************************************************
363 * _os_memory4HwDmaFree()
364 ****************************************************************************************
365 DESCRIPTION: This function releases a block of memory previously allocated with the
366 _os_memoryAlloc4HwDma function.
367
368
369 ARGUMENTS: OsContext - our adapter context.
370 pMemPtr - Pointer to the base virtual address of the allocated memory.
371 This address was returned by the os_memoryAlloc function.
372 Size - Specifies the size, in bytes, of the memory block to be released.
373 This parameter must be identical to the Length that was passed to
374 os_memoryAlloc.
375
376 RETURN: None
377
378 NOTES:
379 *****************************************************************************************/
380 void
os_memory4HwDmaFree(TI_HANDLE pOsContext,PVOID pMem_ptr,UINT32 Size)381 os_memory4HwDmaFree(
382 TI_HANDLE pOsContext,
383 PVOID pMem_ptr,
384 UINT32 Size
385 )
386 {
387 struct os_mem_block *blk =
388 (struct os_mem_block *)((char *)pMem_ptr - sizeof(struct os_mem_block));
389
390 if (blk->signature != MEM_BLOCK_START)
391 {
392 printk("\n\n%s: memory block signature is incorrect - 0x%x\n\n\n",
393 __FUNCTION__, blk->signature);
394 return;
395 }
396 *(char *)(&blk->signature) = '~';
397 if (*(__u32 *)((unsigned char *)blk + blk->size + sizeof(struct os_mem_block))
398 != MEM_BLOCK_END)
399 {
400 printk("\n\n%s: memory block corruption. Size=%u\n\n\n",
401 __FUNCTION__, blk->size);
402 }
403
404 blk->f_free(blk);
405 }
406
407 /****************************************************************************************
408 * os_memoryZero()
409 ****************************************************************************************
410 DESCRIPTION: This function fills a block of memory with 0s.
411
412 ARGUMENTS: OsContext - our adapter context.
413 pMemPtr - Specifies the base address of a block of memory
414 Length - Specifies how many bytes to fill with 0s.
415
416 RETURN: None
417
418 NOTES:
419 *****************************************************************************************/
420 VOID
os_memoryZero(TI_HANDLE OsContext,PVOID pMemPtr,UINT32 Length)421 os_memoryZero(
422 TI_HANDLE OsContext,
423 PVOID pMemPtr,
424 UINT32 Length
425 )
426 {
427 memset(pMemPtr,0,Length);
428 }
429
430
431 /****************************************************************************************
432 * os_memoryCopy()
433 ****************************************************************************************
434 DESCRIPTION: This function copies a specified number of bytes from one caller-supplied
435 location to another.
436
437 ARGUMENTS: OsContext - our adapter context.
438 pDstPtr - Destination buffer
439 pSrcPtr - Source buffer
440 Size - Specifies the size, in bytes, to copy.
441
442 RETURN: None
443
444 NOTES:
445 *****************************************************************************************/
446 VOID
os_memoryCopy(TI_HANDLE OsContext,PVOID pDstPtr,PVOID pSrcPtr,UINT32 Size)447 os_memoryCopy(
448 TI_HANDLE OsContext,
449 PVOID pDstPtr,
450 PVOID pSrcPtr,
451 UINT32 Size
452 )
453 {
454 memcpy(pDstPtr,pSrcPtr,Size);
455 }
456
457 /****************************************************************************************
458 * os_memoryCompare()
459 ****************************************************************************************
460 DESCRIPTION: Compare characters in two buffers.
461
462 ARGUMENTS: OsContext - our adapter context.
463 Buf1 - First buffer
464 Buf2 - Second buffer
465 Count - Number of characters
466
467 RETURN: The return value indicates the relationship between the buffers:
468 < 0 Buf1 less than Buf2
469 0 Buf1 identical to Buf2
470 > 0 Buf1 greater than Buf2
471
472 NOTES:
473 *****************************************************************************************/
474 INT32
os_memoryCompare(TI_HANDLE OsContext,PUINT8 Buf1,PUINT8 Buf2,INT32 Count)475 os_memoryCompare(
476 TI_HANDLE OsContext,
477 PUINT8 Buf1,
478 PUINT8 Buf2,
479 INT32 Count
480 )
481 {
482 return memcmp(Buf1, Buf2, Count);
483 }
484