diff options
Diffstat (limited to 'drivers/net/wireless/bcm4329/linux_osl.c')
-rw-r--r-- | drivers/net/wireless/bcm4329/linux_osl.c | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/drivers/net/wireless/bcm4329/linux_osl.c b/drivers/net/wireless/bcm4329/linux_osl.c new file mode 100644 index 00000000000..cf72a077bd9 --- /dev/null +++ b/drivers/net/wireless/bcm4329/linux_osl.c | |||
@@ -0,0 +1,625 @@ | |||
1 | /* | ||
2 | * Linux OS Independent Layer | ||
3 | * | ||
4 | * Copyright (C) 1999-2010, Broadcom Corporation | ||
5 | * | ||
6 | * Unless you and Broadcom execute a separate written software license | ||
7 | * agreement governing use of this software, this software is licensed to you | ||
8 | * under the terms of the GNU General Public License version 2 (the "GPL"), | ||
9 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the | ||
10 | * following added to such license: | ||
11 | * | ||
12 | * As a special exception, the copyright holders of this software give you | ||
13 | * permission to link this software with independent modules, and to copy and | ||
14 | * distribute the resulting executable under terms of your choice, provided that | ||
15 | * you also meet, for each linked independent module, the terms and conditions of | ||
16 | * the license of that module. An independent module is a module which is not | ||
17 | * derived from this software. The special exception does not apply to any | ||
18 | * modifications of the software. | ||
19 | * | ||
20 | * Notwithstanding the above, under no circumstances may you combine this | ||
21 | * software in any way with any other Broadcom software provided under a license | ||
22 | * other than the GPL, without Broadcom's express prior written consent. | ||
23 | * | ||
24 | * $Id: linux_osl.c,v 1.125.12.3.8.7 2010/05/04 21:10:04 Exp $ | ||
25 | */ | ||
26 | |||
27 | |||
28 | #define LINUX_OSL | ||
29 | |||
30 | #include <typedefs.h> | ||
31 | #include <bcmendian.h> | ||
32 | #include <linuxver.h> | ||
33 | #include <bcmdefs.h> | ||
34 | #include <osl.h> | ||
35 | #include <bcmutils.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <pcicfg.h> | ||
38 | #include <linux/mutex.h> | ||
39 | |||
40 | #define PCI_CFG_RETRY 10 | ||
41 | |||
42 | #define OS_HANDLE_MAGIC 0x1234abcd | ||
43 | #define BCM_MEM_FILENAME_LEN 24 | ||
44 | |||
45 | #ifdef DHD_USE_STATIC_BUF | ||
46 | #define MAX_STATIC_BUF_NUM 16 | ||
47 | #define STATIC_BUF_SIZE (PAGE_SIZE*2) | ||
48 | #define STATIC_BUF_TOTAL_LEN (MAX_STATIC_BUF_NUM*STATIC_BUF_SIZE) | ||
49 | typedef struct bcm_static_buf { | ||
50 | struct mutex static_sem; | ||
51 | unsigned char *buf_ptr; | ||
52 | unsigned char buf_use[MAX_STATIC_BUF_NUM]; | ||
53 | } bcm_static_buf_t; | ||
54 | |||
55 | static bcm_static_buf_t *bcm_static_buf = 0; | ||
56 | |||
57 | #define MAX_STATIC_PKT_NUM 8 | ||
58 | typedef struct bcm_static_pkt { | ||
59 | struct sk_buff *skb_4k[MAX_STATIC_PKT_NUM]; | ||
60 | struct sk_buff *skb_8k[MAX_STATIC_PKT_NUM]; | ||
61 | struct mutex osl_pkt_sem; | ||
62 | unsigned char pkt_use[MAX_STATIC_PKT_NUM*2]; | ||
63 | } bcm_static_pkt_t; | ||
64 | static bcm_static_pkt_t *bcm_static_skb = 0; | ||
65 | |||
66 | #endif | ||
67 | typedef struct bcm_mem_link { | ||
68 | struct bcm_mem_link *prev; | ||
69 | struct bcm_mem_link *next; | ||
70 | uint size; | ||
71 | int line; | ||
72 | char file[BCM_MEM_FILENAME_LEN]; | ||
73 | } bcm_mem_link_t; | ||
74 | |||
75 | struct osl_info { | ||
76 | osl_pubinfo_t pub; | ||
77 | uint magic; | ||
78 | void *pdev; | ||
79 | uint malloced; | ||
80 | uint failed; | ||
81 | uint bustype; | ||
82 | bcm_mem_link_t *dbgmem_list; | ||
83 | }; | ||
84 | |||
85 | static int16 linuxbcmerrormap[] = | ||
86 | { 0, | ||
87 | -EINVAL, | ||
88 | -EINVAL, | ||
89 | -EINVAL, | ||
90 | -EINVAL, | ||
91 | -EINVAL, | ||
92 | -EINVAL, | ||
93 | -EINVAL, | ||
94 | -EINVAL, | ||
95 | -EINVAL, | ||
96 | -EINVAL, | ||
97 | -EINVAL, | ||
98 | -EINVAL, | ||
99 | -EINVAL, | ||
100 | -E2BIG, | ||
101 | -E2BIG, | ||
102 | -EBUSY, | ||
103 | -EINVAL, | ||
104 | -EINVAL, | ||
105 | -EINVAL, | ||
106 | -EINVAL, | ||
107 | -EFAULT, | ||
108 | -ENOMEM, | ||
109 | -EOPNOTSUPP, | ||
110 | -EMSGSIZE, | ||
111 | -EINVAL, | ||
112 | -EPERM, | ||
113 | -ENOMEM, | ||
114 | -EINVAL, | ||
115 | -ERANGE, | ||
116 | -EINVAL, | ||
117 | -EINVAL, | ||
118 | -EINVAL, | ||
119 | -EINVAL, | ||
120 | -EINVAL, | ||
121 | -EIO, | ||
122 | -ENODEV, | ||
123 | -EINVAL, | ||
124 | -EIO, | ||
125 | -EIO, | ||
126 | -EINVAL, | ||
127 | -EINVAL, | ||
128 | |||
129 | |||
130 | |||
131 | #if BCME_LAST != -41 | ||
132 | #error "You need to add a OS error translation in the linuxbcmerrormap \ | ||
133 | for new error code defined in bcmutils.h" | ||
134 | #endif | ||
135 | }; | ||
136 | |||
137 | |||
138 | int | ||
139 | osl_error(int bcmerror) | ||
140 | { | ||
141 | if (bcmerror > 0) | ||
142 | bcmerror = 0; | ||
143 | else if (bcmerror < BCME_LAST) | ||
144 | bcmerror = BCME_ERROR; | ||
145 | |||
146 | |||
147 | return linuxbcmerrormap[-bcmerror]; | ||
148 | } | ||
149 | |||
150 | void * dhd_os_prealloc(int section, unsigned long size); | ||
151 | osl_t * | ||
152 | osl_attach(void *pdev, uint bustype, bool pkttag) | ||
153 | { | ||
154 | osl_t *osh; | ||
155 | gfp_t flags; | ||
156 | |||
157 | flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
158 | osh = kmalloc(sizeof(osl_t), flags); | ||
159 | ASSERT(osh); | ||
160 | |||
161 | bzero(osh, sizeof(osl_t)); | ||
162 | |||
163 | |||
164 | ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); | ||
165 | |||
166 | osh->magic = OS_HANDLE_MAGIC; | ||
167 | osh->malloced = 0; | ||
168 | osh->failed = 0; | ||
169 | osh->dbgmem_list = NULL; | ||
170 | osh->pdev = pdev; | ||
171 | osh->pub.pkttag = pkttag; | ||
172 | osh->bustype = bustype; | ||
173 | |||
174 | switch (bustype) { | ||
175 | case PCI_BUS: | ||
176 | case SI_BUS: | ||
177 | case PCMCIA_BUS: | ||
178 | osh->pub.mmbus = TRUE; | ||
179 | break; | ||
180 | case JTAG_BUS: | ||
181 | case SDIO_BUS: | ||
182 | case USB_BUS: | ||
183 | case SPI_BUS: | ||
184 | osh->pub.mmbus = FALSE; | ||
185 | break; | ||
186 | default: | ||
187 | ASSERT(FALSE); | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | #ifdef DHD_USE_STATIC_BUF | ||
192 | |||
193 | |||
194 | if (!bcm_static_buf) { | ||
195 | if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(3, STATIC_BUF_SIZE+ | ||
196 | STATIC_BUF_TOTAL_LEN))) { | ||
197 | printk("can not alloc static buf!\n"); | ||
198 | } | ||
199 | else { | ||
200 | /* printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); */ | ||
201 | } | ||
202 | |||
203 | mutex_init(&bcm_static_buf->static_sem); | ||
204 | |||
205 | |||
206 | bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; | ||
207 | |||
208 | } | ||
209 | |||
210 | if (!bcm_static_skb) | ||
211 | { | ||
212 | int i; | ||
213 | void *skb_buff_ptr = 0; | ||
214 | bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); | ||
215 | skb_buff_ptr = dhd_os_prealloc(4, 0); | ||
216 | |||
217 | bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16); | ||
218 | for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++) | ||
219 | bcm_static_skb->pkt_use[i] = 0; | ||
220 | |||
221 | mutex_init(&bcm_static_skb->osl_pkt_sem); | ||
222 | } | ||
223 | #endif | ||
224 | return osh; | ||
225 | } | ||
226 | |||
227 | void | ||
228 | osl_detach(osl_t *osh) | ||
229 | { | ||
230 | if (osh == NULL) | ||
231 | return; | ||
232 | |||
233 | #ifdef DHD_USE_STATIC_BUF | ||
234 | if (bcm_static_buf) { | ||
235 | bcm_static_buf = 0; | ||
236 | } | ||
237 | if (bcm_static_skb) { | ||
238 | bcm_static_skb = 0; | ||
239 | } | ||
240 | #endif | ||
241 | ASSERT(osh->magic == OS_HANDLE_MAGIC); | ||
242 | kfree(osh); | ||
243 | } | ||
244 | |||
245 | |||
246 | void* | ||
247 | osl_pktget(osl_t *osh, uint len) | ||
248 | { | ||
249 | struct sk_buff *skb; | ||
250 | gfp_t flags; | ||
251 | |||
252 | flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
253 | if ((skb = __dev_alloc_skb(len, flags))) { | ||
254 | skb_put(skb, len); | ||
255 | skb->priority = 0; | ||
256 | |||
257 | |||
258 | osh->pub.pktalloced++; | ||
259 | } | ||
260 | |||
261 | return ((void*) skb); | ||
262 | } | ||
263 | |||
264 | |||
265 | void | ||
266 | osl_pktfree(osl_t *osh, void *p, bool send) | ||
267 | { | ||
268 | struct sk_buff *skb, *nskb; | ||
269 | |||
270 | skb = (struct sk_buff*) p; | ||
271 | |||
272 | if (send && osh->pub.tx_fn) | ||
273 | osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); | ||
274 | |||
275 | |||
276 | while (skb) { | ||
277 | nskb = skb->next; | ||
278 | skb->next = NULL; | ||
279 | |||
280 | |||
281 | if (skb->destructor) { | ||
282 | |||
283 | dev_kfree_skb_any(skb); | ||
284 | } else { | ||
285 | |||
286 | dev_kfree_skb(skb); | ||
287 | } | ||
288 | |||
289 | osh->pub.pktalloced--; | ||
290 | |||
291 | skb = nskb; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | #ifdef DHD_USE_STATIC_BUF | ||
296 | void* | ||
297 | osl_pktget_static(osl_t *osh, uint len) | ||
298 | { | ||
299 | int i = 0; | ||
300 | struct sk_buff *skb; | ||
301 | |||
302 | |||
303 | if (len > (PAGE_SIZE*2)) | ||
304 | { | ||
305 | printk("Do we really need this big skb??\n"); | ||
306 | return osl_pktget(osh, len); | ||
307 | } | ||
308 | |||
309 | |||
310 | mutex_lock(&bcm_static_skb->osl_pkt_sem); | ||
311 | if (len <= PAGE_SIZE) | ||
312 | { | ||
313 | |||
314 | for (i = 0; i < MAX_STATIC_PKT_NUM; i++) | ||
315 | { | ||
316 | if (bcm_static_skb->pkt_use[i] == 0) | ||
317 | break; | ||
318 | } | ||
319 | |||
320 | if (i != MAX_STATIC_PKT_NUM) | ||
321 | { | ||
322 | bcm_static_skb->pkt_use[i] = 1; | ||
323 | mutex_unlock(&bcm_static_skb->osl_pkt_sem); | ||
324 | |||
325 | skb = bcm_static_skb->skb_4k[i]; | ||
326 | skb->tail = skb->data + len; | ||
327 | skb->len = len; | ||
328 | |||
329 | return skb; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | |||
334 | for (i = 0; i < MAX_STATIC_PKT_NUM; i++) | ||
335 | { | ||
336 | if (bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] == 0) | ||
337 | break; | ||
338 | } | ||
339 | |||
340 | if (i != MAX_STATIC_PKT_NUM) | ||
341 | { | ||
342 | bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] = 1; | ||
343 | mutex_unlock(&bcm_static_skb->osl_pkt_sem); | ||
344 | skb = bcm_static_skb->skb_8k[i]; | ||
345 | skb->tail = skb->data + len; | ||
346 | skb->len = len; | ||
347 | |||
348 | return skb; | ||
349 | } | ||
350 | |||
351 | |||
352 | |||
353 | mutex_unlock(&bcm_static_skb->osl_pkt_sem); | ||
354 | printk("all static pkt in use!\n"); | ||
355 | return osl_pktget(osh, len); | ||
356 | } | ||
357 | |||
358 | |||
359 | void | ||
360 | osl_pktfree_static(osl_t *osh, void *p, bool send) | ||
361 | { | ||
362 | int i; | ||
363 | |||
364 | for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++) | ||
365 | { | ||
366 | if (p == bcm_static_skb->skb_4k[i]) | ||
367 | { | ||
368 | mutex_lock(&bcm_static_skb->osl_pkt_sem); | ||
369 | bcm_static_skb->pkt_use[i] = 0; | ||
370 | mutex_unlock(&bcm_static_skb->osl_pkt_sem); | ||
371 | |||
372 | |||
373 | return; | ||
374 | } | ||
375 | } | ||
376 | return osl_pktfree(osh, p, send); | ||
377 | } | ||
378 | #endif | ||
379 | uint32 | ||
380 | osl_pci_read_config(osl_t *osh, uint offset, uint size) | ||
381 | { | ||
382 | uint val = 0; | ||
383 | uint retry = PCI_CFG_RETRY; | ||
384 | |||
385 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
386 | |||
387 | |||
388 | ASSERT(size == 4); | ||
389 | |||
390 | do { | ||
391 | pci_read_config_dword(osh->pdev, offset, &val); | ||
392 | if (val != 0xffffffff) | ||
393 | break; | ||
394 | } while (retry--); | ||
395 | |||
396 | |||
397 | return (val); | ||
398 | } | ||
399 | |||
400 | void | ||
401 | osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) | ||
402 | { | ||
403 | uint retry = PCI_CFG_RETRY; | ||
404 | |||
405 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
406 | |||
407 | |||
408 | ASSERT(size == 4); | ||
409 | |||
410 | do { | ||
411 | pci_write_config_dword(osh->pdev, offset, val); | ||
412 | if (offset != PCI_BAR0_WIN) | ||
413 | break; | ||
414 | if (osl_pci_read_config(osh, offset, size) == val) | ||
415 | break; | ||
416 | } while (retry--); | ||
417 | |||
418 | } | ||
419 | |||
420 | |||
421 | uint | ||
422 | osl_pci_bus(osl_t *osh) | ||
423 | { | ||
424 | ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); | ||
425 | |||
426 | return ((struct pci_dev *)osh->pdev)->bus->number; | ||
427 | } | ||
428 | |||
429 | |||
430 | uint | ||
431 | osl_pci_slot(osl_t *osh) | ||
432 | { | ||
433 | ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); | ||
434 | |||
435 | return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); | ||
436 | } | ||
437 | |||
438 | static void | ||
439 | osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) | ||
440 | { | ||
441 | } | ||
442 | |||
443 | void | ||
444 | osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) | ||
445 | { | ||
446 | osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); | ||
447 | } | ||
448 | |||
449 | void | ||
450 | osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) | ||
451 | { | ||
452 | osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); | ||
453 | } | ||
454 | |||
455 | |||
456 | |||
457 | void* | ||
458 | osl_malloc(osl_t *osh, uint size) | ||
459 | { | ||
460 | void *addr; | ||
461 | gfp_t flags; | ||
462 | |||
463 | if (osh) | ||
464 | ASSERT(osh->magic == OS_HANDLE_MAGIC); | ||
465 | |||
466 | #ifdef DHD_USE_STATIC_BUF | ||
467 | if (bcm_static_buf) | ||
468 | { | ||
469 | int i = 0; | ||
470 | if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE)) | ||
471 | { | ||
472 | mutex_lock(&bcm_static_buf->static_sem); | ||
473 | |||
474 | for (i = 0; i < MAX_STATIC_BUF_NUM; i++) | ||
475 | { | ||
476 | if (bcm_static_buf->buf_use[i] == 0) | ||
477 | break; | ||
478 | } | ||
479 | |||
480 | if (i == MAX_STATIC_BUF_NUM) | ||
481 | { | ||
482 | mutex_unlock(&bcm_static_buf->static_sem); | ||
483 | printk("all static buff in use!\n"); | ||
484 | goto original; | ||
485 | } | ||
486 | |||
487 | bcm_static_buf->buf_use[i] = 1; | ||
488 | mutex_unlock(&bcm_static_buf->static_sem); | ||
489 | |||
490 | bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size); | ||
491 | if (osh) | ||
492 | osh->malloced += size; | ||
493 | |||
494 | return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i)); | ||
495 | } | ||
496 | } | ||
497 | original: | ||
498 | #endif | ||
499 | flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
500 | if ((addr = kmalloc(size, flags)) == NULL) { | ||
501 | if (osh) | ||
502 | osh->failed++; | ||
503 | return (NULL); | ||
504 | } | ||
505 | if (osh) | ||
506 | osh->malloced += size; | ||
507 | |||
508 | return (addr); | ||
509 | } | ||
510 | |||
511 | void | ||
512 | osl_mfree(osl_t *osh, void *addr, uint size) | ||
513 | { | ||
514 | #ifdef DHD_USE_STATIC_BUF | ||
515 | if (bcm_static_buf) | ||
516 | { | ||
517 | if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr | ||
518 | <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN))) | ||
519 | { | ||
520 | int buf_idx = 0; | ||
521 | |||
522 | buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE; | ||
523 | |||
524 | mutex_lock(&bcm_static_buf->static_sem); | ||
525 | bcm_static_buf->buf_use[buf_idx] = 0; | ||
526 | mutex_unlock(&bcm_static_buf->static_sem); | ||
527 | |||
528 | if (osh) { | ||
529 | ASSERT(osh->magic == OS_HANDLE_MAGIC); | ||
530 | osh->malloced -= size; | ||
531 | } | ||
532 | return; | ||
533 | } | ||
534 | } | ||
535 | #endif | ||
536 | if (osh) { | ||
537 | ASSERT(osh->magic == OS_HANDLE_MAGIC); | ||
538 | osh->malloced -= size; | ||
539 | } | ||
540 | kfree(addr); | ||
541 | } | ||
542 | |||
543 | uint | ||
544 | osl_malloced(osl_t *osh) | ||
545 | { | ||
546 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
547 | return (osh->malloced); | ||
548 | } | ||
549 | |||
550 | uint | ||
551 | osl_malloc_failed(osl_t *osh) | ||
552 | { | ||
553 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
554 | return (osh->failed); | ||
555 | } | ||
556 | |||
557 | void* | ||
558 | osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap) | ||
559 | { | ||
560 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
561 | |||
562 | return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); | ||
563 | } | ||
564 | |||
565 | void | ||
566 | osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) | ||
567 | { | ||
568 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
569 | |||
570 | pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); | ||
571 | } | ||
572 | |||
573 | uint | ||
574 | osl_dma_map(osl_t *osh, void *va, uint size, int direction) | ||
575 | { | ||
576 | int dir; | ||
577 | |||
578 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
579 | dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; | ||
580 | return (pci_map_single(osh->pdev, va, size, dir)); | ||
581 | } | ||
582 | |||
583 | void | ||
584 | osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) | ||
585 | { | ||
586 | int dir; | ||
587 | |||
588 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
589 | dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; | ||
590 | pci_unmap_single(osh->pdev, (uint32)pa, size, dir); | ||
591 | } | ||
592 | |||
593 | |||
594 | void | ||
595 | osl_delay(uint usec) | ||
596 | { | ||
597 | uint d; | ||
598 | |||
599 | while (usec > 0) { | ||
600 | d = MIN(usec, 1000); | ||
601 | udelay(d); | ||
602 | usec -= d; | ||
603 | } | ||
604 | } | ||
605 | |||
606 | |||
607 | |||
608 | void * | ||
609 | osl_pktdup(osl_t *osh, void *skb) | ||
610 | { | ||
611 | void * p; | ||
612 | gfp_t flags; | ||
613 | |||
614 | flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
615 | if ((p = skb_clone((struct sk_buff*)skb, flags)) == NULL) | ||
616 | return NULL; | ||
617 | |||
618 | |||
619 | if (osh->pub.pkttag) | ||
620 | bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); | ||
621 | |||
622 | |||
623 | osh->pub.pktalloced++; | ||
624 | return (p); | ||
625 | } | ||