diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/net/wireless/bcmdhd/linux_osl.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/net/wireless/bcmdhd/linux_osl.c')
-rw-r--r-- | drivers/net/wireless/bcmdhd/linux_osl.c | 919 |
1 files changed, 919 insertions, 0 deletions
diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c new file mode 100644 index 00000000000..1a544378c1e --- /dev/null +++ b/drivers/net/wireless/bcmdhd/linux_osl.c | |||
@@ -0,0 +1,919 @@ | |||
1 | /* | ||
2 | * Linux OS Independent Layer | ||
3 | * | ||
4 | * Copyright (C) 1999-2011, 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.168.2.7 2011-01-27 17:01:13 Exp $ | ||
25 | */ | ||
26 | |||
27 | |||
28 | #define LINUX_PORT | ||
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 | |||
39 | #ifdef BCMASSERT_LOG | ||
40 | #include <bcm_assert_log.h> | ||
41 | #endif | ||
42 | |||
43 | #include <linux/fs.h> | ||
44 | |||
45 | #define PCI_CFG_RETRY 10 | ||
46 | |||
47 | #define OS_HANDLE_MAGIC 0x1234abcd | ||
48 | #define BCM_MEM_FILENAME_LEN 24 | ||
49 | |||
50 | #ifdef DHD_USE_STATIC_BUF | ||
51 | #define STATIC_BUF_MAX_NUM 16 | ||
52 | #define STATIC_BUF_SIZE (PAGE_SIZE * 2) | ||
53 | #define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) | ||
54 | |||
55 | typedef struct bcm_static_buf { | ||
56 | struct semaphore static_sem; | ||
57 | unsigned char *buf_ptr; | ||
58 | unsigned char buf_use[STATIC_BUF_MAX_NUM]; | ||
59 | } bcm_static_buf_t; | ||
60 | |||
61 | static bcm_static_buf_t *bcm_static_buf = 0; | ||
62 | |||
63 | #define STATIC_PKT_MAX_NUM 8 | ||
64 | |||
65 | typedef struct bcm_static_pkt { | ||
66 | struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM]; | ||
67 | struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM]; | ||
68 | struct semaphore osl_pkt_sem; | ||
69 | unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2]; | ||
70 | } bcm_static_pkt_t; | ||
71 | |||
72 | static bcm_static_pkt_t *bcm_static_skb = 0; | ||
73 | #endif | ||
74 | |||
75 | typedef struct bcm_mem_link { | ||
76 | struct bcm_mem_link *prev; | ||
77 | struct bcm_mem_link *next; | ||
78 | uint size; | ||
79 | int line; | ||
80 | char file[BCM_MEM_FILENAME_LEN]; | ||
81 | } bcm_mem_link_t; | ||
82 | |||
83 | struct osl_info { | ||
84 | osl_pubinfo_t pub; | ||
85 | #ifdef CTFPOOL | ||
86 | ctfpool_t *ctfpool; | ||
87 | #endif | ||
88 | uint magic; | ||
89 | void *pdev; | ||
90 | atomic_t malloced; | ||
91 | uint failed; | ||
92 | uint bustype; | ||
93 | bcm_mem_link_t *dbgmem_list; | ||
94 | }; | ||
95 | |||
96 | |||
97 | |||
98 | |||
99 | uint32 g_assert_type = FALSE; | ||
100 | |||
101 | static int16 linuxbcmerrormap[] = | ||
102 | { 0, | ||
103 | -EINVAL, | ||
104 | -EINVAL, | ||
105 | -EINVAL, | ||
106 | -EINVAL, | ||
107 | -EINVAL, | ||
108 | -EINVAL, | ||
109 | -EINVAL, | ||
110 | -EINVAL, | ||
111 | -EINVAL, | ||
112 | -EINVAL, | ||
113 | -EINVAL, | ||
114 | -EINVAL, | ||
115 | -EINVAL, | ||
116 | -E2BIG, | ||
117 | -E2BIG, | ||
118 | -EBUSY, | ||
119 | -EINVAL, | ||
120 | -EINVAL, | ||
121 | -EINVAL, | ||
122 | -EINVAL, | ||
123 | -EFAULT, | ||
124 | -ENOMEM, | ||
125 | -EOPNOTSUPP, | ||
126 | -EMSGSIZE, | ||
127 | -EINVAL, | ||
128 | -EPERM, | ||
129 | -ENOMEM, | ||
130 | -EINVAL, | ||
131 | -ERANGE, | ||
132 | -EINVAL, | ||
133 | -EINVAL, | ||
134 | -EINVAL, | ||
135 | -EINVAL, | ||
136 | -EINVAL, | ||
137 | -EIO, | ||
138 | -ENODEV, | ||
139 | -EINVAL, | ||
140 | -EIO, | ||
141 | -EIO, | ||
142 | -ENODEV, | ||
143 | -EINVAL, | ||
144 | -ENODATA, | ||
145 | |||
146 | |||
147 | |||
148 | #if BCME_LAST != -42 | ||
149 | #error "You need to add a OS error translation in the linuxbcmerrormap \ | ||
150 | for new error code defined in bcmutils.h" | ||
151 | #endif | ||
152 | }; | ||
153 | |||
154 | |||
155 | int | ||
156 | osl_error(int bcmerror) | ||
157 | { | ||
158 | if (bcmerror > 0) | ||
159 | bcmerror = 0; | ||
160 | else if (bcmerror < BCME_LAST) | ||
161 | bcmerror = BCME_ERROR; | ||
162 | |||
163 | |||
164 | return linuxbcmerrormap[-bcmerror]; | ||
165 | } | ||
166 | |||
167 | extern uint8* dhd_os_prealloc(void *osh, int section, int size); | ||
168 | |||
169 | osl_t * | ||
170 | osl_attach(void *pdev, uint bustype, bool pkttag) | ||
171 | { | ||
172 | osl_t *osh; | ||
173 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) | ||
174 | gfp_t flags; | ||
175 | |||
176 | flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
177 | osh = kmalloc(sizeof(osl_t), flags); | ||
178 | #else | ||
179 | osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); | ||
180 | #endif | ||
181 | ASSERT(osh); | ||
182 | |||
183 | bzero(osh, sizeof(osl_t)); | ||
184 | |||
185 | |||
186 | ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); | ||
187 | |||
188 | osh->magic = OS_HANDLE_MAGIC; | ||
189 | atomic_set(&osh->malloced, 0); | ||
190 | osh->failed = 0; | ||
191 | osh->dbgmem_list = NULL; | ||
192 | osh->pdev = pdev; | ||
193 | osh->pub.pkttag = pkttag; | ||
194 | osh->bustype = bustype; | ||
195 | |||
196 | switch (bustype) { | ||
197 | case PCI_BUS: | ||
198 | case SI_BUS: | ||
199 | case PCMCIA_BUS: | ||
200 | osh->pub.mmbus = TRUE; | ||
201 | break; | ||
202 | case JTAG_BUS: | ||
203 | case SDIO_BUS: | ||
204 | case USB_BUS: | ||
205 | case SPI_BUS: | ||
206 | case RPC_BUS: | ||
207 | osh->pub.mmbus = FALSE; | ||
208 | break; | ||
209 | default: | ||
210 | ASSERT(FALSE); | ||
211 | break; | ||
212 | } | ||
213 | |||
214 | #if defined(DHD_USE_STATIC_BUF) | ||
215 | if (!bcm_static_buf) { | ||
216 | if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ | ||
217 | STATIC_BUF_TOTAL_LEN))) { | ||
218 | printk("can not alloc static buf!\n"); | ||
219 | } | ||
220 | else | ||
221 | printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); | ||
222 | |||
223 | |||
224 | sema_init(&bcm_static_buf->static_sem, 1); | ||
225 | |||
226 | bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; | ||
227 | } | ||
228 | |||
229 | if (!bcm_static_skb) { | ||
230 | int i; | ||
231 | void *skb_buff_ptr = 0; | ||
232 | bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); | ||
233 | skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); | ||
234 | |||
235 | bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * 16); | ||
236 | for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) | ||
237 | bcm_static_skb->pkt_use[i] = 0; | ||
238 | |||
239 | sema_init(&bcm_static_skb->osl_pkt_sem, 1); | ||
240 | } | ||
241 | #endif | ||
242 | |||
243 | return osh; | ||
244 | } | ||
245 | |||
246 | void | ||
247 | osl_detach(osl_t *osh) | ||
248 | { | ||
249 | if (osh == NULL) | ||
250 | return; | ||
251 | |||
252 | ASSERT(osh->magic == OS_HANDLE_MAGIC); | ||
253 | kfree(osh); | ||
254 | } | ||
255 | |||
256 | static struct sk_buff *osl_alloc_skb(unsigned int len) | ||
257 | { | ||
258 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) | ||
259 | gfp_t flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
260 | |||
261 | return __dev_alloc_skb(len, flags); | ||
262 | #else | ||
263 | return dev_alloc_skb(len); | ||
264 | #endif | ||
265 | } | ||
266 | |||
267 | #ifdef CTFPOOL | ||
268 | |||
269 | void * | ||
270 | osl_ctfpool_add(osl_t *osh) | ||
271 | { | ||
272 | struct sk_buff *skb; | ||
273 | |||
274 | if ((osh == NULL) || (osh->ctfpool == NULL)) | ||
275 | return NULL; | ||
276 | |||
277 | spin_lock_bh(&osh->ctfpool->lock); | ||
278 | ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj); | ||
279 | |||
280 | |||
281 | if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) { | ||
282 | spin_unlock_bh(&osh->ctfpool->lock); | ||
283 | return NULL; | ||
284 | } | ||
285 | |||
286 | |||
287 | skb = osl_alloc_skb(osh->ctfpool->obj_size); | ||
288 | if (skb == NULL) { | ||
289 | printf("%s: skb alloc of len %d failed\n", __FUNCTION__, | ||
290 | osh->ctfpool->obj_size); | ||
291 | spin_unlock_bh(&osh->ctfpool->lock); | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
295 | |||
296 | skb->next = (struct sk_buff *)osh->ctfpool->head; | ||
297 | osh->ctfpool->head = skb; | ||
298 | osh->ctfpool->fast_frees++; | ||
299 | osh->ctfpool->curr_obj++; | ||
300 | |||
301 | |||
302 | CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool; | ||
303 | |||
304 | |||
305 | PKTFAST(osh, skb) = FASTBUF; | ||
306 | |||
307 | spin_unlock_bh(&osh->ctfpool->lock); | ||
308 | |||
309 | return skb; | ||
310 | } | ||
311 | |||
312 | |||
313 | void | ||
314 | osl_ctfpool_replenish(osl_t *osh, uint thresh) | ||
315 | { | ||
316 | if ((osh == NULL) || (osh->ctfpool == NULL)) | ||
317 | return; | ||
318 | |||
319 | |||
320 | while ((osh->ctfpool->refills > 0) && (thresh--)) { | ||
321 | osl_ctfpool_add(osh); | ||
322 | osh->ctfpool->refills--; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | |||
327 | int32 | ||
328 | osl_ctfpool_init(osl_t *osh, uint numobj, uint size) | ||
329 | { | ||
330 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) | ||
331 | gfp_t flags; | ||
332 | |||
333 | flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
334 | osh->ctfpool = kmalloc(sizeof(ctfpool_t), flags); | ||
335 | #else | ||
336 | osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); | ||
337 | #endif | ||
338 | ASSERT(osh->ctfpool); | ||
339 | bzero(osh->ctfpool, sizeof(ctfpool_t)); | ||
340 | |||
341 | osh->ctfpool->max_obj = numobj; | ||
342 | osh->ctfpool->obj_size = size; | ||
343 | |||
344 | spin_lock_init(&osh->ctfpool->lock); | ||
345 | |||
346 | while (numobj--) { | ||
347 | if (!osl_ctfpool_add(osh)) | ||
348 | return -1; | ||
349 | osh->ctfpool->fast_frees--; | ||
350 | } | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | |||
356 | void | ||
357 | osl_ctfpool_cleanup(osl_t *osh) | ||
358 | { | ||
359 | struct sk_buff *skb, *nskb; | ||
360 | |||
361 | if ((osh == NULL) || (osh->ctfpool == NULL)) | ||
362 | return; | ||
363 | |||
364 | spin_lock_bh(&osh->ctfpool->lock); | ||
365 | |||
366 | skb = osh->ctfpool->head; | ||
367 | |||
368 | while (skb != NULL) { | ||
369 | nskb = skb->next; | ||
370 | dev_kfree_skb(skb); | ||
371 | skb = nskb; | ||
372 | osh->ctfpool->curr_obj--; | ||
373 | } | ||
374 | |||
375 | ASSERT(osh->ctfpool->curr_obj == 0); | ||
376 | osh->ctfpool->head = NULL; | ||
377 | spin_unlock_bh(&osh->ctfpool->lock); | ||
378 | |||
379 | kfree(osh->ctfpool); | ||
380 | osh->ctfpool = NULL; | ||
381 | } | ||
382 | |||
383 | void | ||
384 | osl_ctfpool_stats(osl_t *osh, void *b) | ||
385 | { | ||
386 | struct bcmstrbuf *bb; | ||
387 | |||
388 | if ((osh == NULL) || (osh->ctfpool == NULL)) | ||
389 | return; | ||
390 | |||
391 | #ifdef DHD_USE_STATIC_BUF | ||
392 | if (bcm_static_buf) { | ||
393 | bcm_static_buf = 0; | ||
394 | } | ||
395 | if (bcm_static_skb) { | ||
396 | bcm_static_skb = 0; | ||
397 | } | ||
398 | #endif | ||
399 | |||
400 | bb = b; | ||
401 | |||
402 | ASSERT((osh != NULL) && (bb != NULL)); | ||
403 | |||
404 | bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n", | ||
405 | osh->ctfpool->max_obj, osh->ctfpool->obj_size, | ||
406 | osh->ctfpool->curr_obj, osh->ctfpool->refills); | ||
407 | bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n", | ||
408 | osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees, | ||
409 | osh->ctfpool->slow_allocs); | ||
410 | } | ||
411 | |||
412 | static inline struct sk_buff * | ||
413 | osl_pktfastget(osl_t *osh, uint len) | ||
414 | { | ||
415 | struct sk_buff *skb; | ||
416 | |||
417 | |||
418 | if (osh->ctfpool == NULL) | ||
419 | return NULL; | ||
420 | |||
421 | spin_lock_bh(&osh->ctfpool->lock); | ||
422 | if (osh->ctfpool->head == NULL) { | ||
423 | ASSERT(osh->ctfpool->curr_obj == 0); | ||
424 | osh->ctfpool->slow_allocs++; | ||
425 | spin_unlock_bh(&osh->ctfpool->lock); | ||
426 | return NULL; | ||
427 | } | ||
428 | |||
429 | ASSERT(len <= osh->ctfpool->obj_size); | ||
430 | |||
431 | |||
432 | skb = (struct sk_buff *)osh->ctfpool->head; | ||
433 | osh->ctfpool->head = (void *)skb->next; | ||
434 | |||
435 | osh->ctfpool->fast_allocs++; | ||
436 | osh->ctfpool->curr_obj--; | ||
437 | ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head); | ||
438 | spin_unlock_bh(&osh->ctfpool->lock); | ||
439 | |||
440 | |||
441 | skb->next = skb->prev = NULL; | ||
442 | skb->data = skb->head + 16; | ||
443 | skb->tail = skb->head + 16; | ||
444 | |||
445 | skb->len = 0; | ||
446 | skb->cloned = 0; | ||
447 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) | ||
448 | skb->list = NULL; | ||
449 | #endif | ||
450 | atomic_set(&skb->users, 1); | ||
451 | |||
452 | return skb; | ||
453 | } | ||
454 | #endif | ||
455 | |||
456 | |||
457 | void * BCMFASTPATH | ||
458 | osl_pktget(osl_t *osh, uint len) | ||
459 | { | ||
460 | struct sk_buff *skb; | ||
461 | |||
462 | #ifdef CTFPOOL | ||
463 | skb = osl_pktfastget(osh, len); | ||
464 | if ((skb != NULL) || ((skb = osl_alloc_skb(len)) != NULL)) { | ||
465 | #else | ||
466 | if ((skb = osl_alloc_skb(len))) { | ||
467 | #endif | ||
468 | skb_put(skb, len); | ||
469 | skb->priority = 0; | ||
470 | |||
471 | osh->pub.pktalloced++; | ||
472 | } | ||
473 | |||
474 | return ((void*) skb); | ||
475 | } | ||
476 | |||
477 | #ifdef CTFPOOL | ||
478 | static inline void | ||
479 | osl_pktfastfree(osl_t *osh, struct sk_buff *skb) | ||
480 | { | ||
481 | ctfpool_t *ctfpool; | ||
482 | |||
483 | ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); | ||
484 | ASSERT(ctfpool != NULL); | ||
485 | |||
486 | |||
487 | spin_lock_bh(&ctfpool->lock); | ||
488 | skb->next = (struct sk_buff *)ctfpool->head; | ||
489 | ctfpool->head = (void *)skb; | ||
490 | |||
491 | ctfpool->fast_frees++; | ||
492 | ctfpool->curr_obj++; | ||
493 | |||
494 | ASSERT(ctfpool->curr_obj <= ctfpool->max_obj); | ||
495 | spin_unlock_bh(&ctfpool->lock); | ||
496 | |||
497 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) | ||
498 | skb->tstamp.tv.sec = 0; | ||
499 | #else | ||
500 | skb->stamp.tv_sec = 0; | ||
501 | #endif | ||
502 | |||
503 | |||
504 | skb->dev = NULL; | ||
505 | skb->dst = NULL; | ||
506 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
507 | skb->ip_summed = 0; | ||
508 | skb->destructor = NULL; | ||
509 | } | ||
510 | #endif | ||
511 | |||
512 | |||
513 | void BCMFASTPATH | ||
514 | osl_pktfree(osl_t *osh, void *p, bool send) | ||
515 | { | ||
516 | struct sk_buff *skb, *nskb; | ||
517 | |||
518 | skb = (struct sk_buff*) p; | ||
519 | |||
520 | if (send && osh->pub.tx_fn) | ||
521 | osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); | ||
522 | |||
523 | |||
524 | while (skb) { | ||
525 | nskb = skb->next; | ||
526 | skb->next = NULL; | ||
527 | |||
528 | |||
529 | #ifdef CTFPOOL | ||
530 | if (PKTISFAST(osh, skb)) | ||
531 | osl_pktfastfree(osh, skb); | ||
532 | else { | ||
533 | #else | ||
534 | { | ||
535 | #endif | ||
536 | |||
537 | if (skb->destructor) | ||
538 | |||
539 | dev_kfree_skb_any(skb); | ||
540 | else | ||
541 | |||
542 | dev_kfree_skb(skb); | ||
543 | } | ||
544 | |||
545 | osh->pub.pktalloced--; | ||
546 | |||
547 | skb = nskb; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | #ifdef DHD_USE_STATIC_BUF | ||
552 | void * | ||
553 | osl_pktget_static(osl_t *osh, uint len) | ||
554 | { | ||
555 | int i; | ||
556 | struct sk_buff *skb; | ||
557 | |||
558 | if (len > (PAGE_SIZE * 2)) { | ||
559 | printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); | ||
560 | return osl_pktget(osh, len); | ||
561 | } | ||
562 | |||
563 | down(&bcm_static_skb->osl_pkt_sem); | ||
564 | |||
565 | if (len <= PAGE_SIZE) { | ||
566 | for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { | ||
567 | if (bcm_static_skb->pkt_use[i] == 0) | ||
568 | break; | ||
569 | } | ||
570 | |||
571 | if (i != STATIC_PKT_MAX_NUM) { | ||
572 | bcm_static_skb->pkt_use[i] = 1; | ||
573 | up(&bcm_static_skb->osl_pkt_sem); | ||
574 | skb = bcm_static_skb->skb_4k[i]; | ||
575 | skb->tail = skb->data + len; | ||
576 | skb->len = len; | ||
577 | return skb; | ||
578 | } | ||
579 | } | ||
580 | |||
581 | |||
582 | for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { | ||
583 | if (bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] == 0) | ||
584 | break; | ||
585 | } | ||
586 | |||
587 | if (i != STATIC_PKT_MAX_NUM) { | ||
588 | bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1; | ||
589 | up(&bcm_static_skb->osl_pkt_sem); | ||
590 | skb = bcm_static_skb->skb_8k[i]; | ||
591 | skb->tail = skb->data + len; | ||
592 | skb->len = len; | ||
593 | return skb; | ||
594 | } | ||
595 | |||
596 | up(&bcm_static_skb->osl_pkt_sem); | ||
597 | printk("%s: all static pkt in use!\n", __FUNCTION__); | ||
598 | return osl_pktget(osh, len); | ||
599 | } | ||
600 | |||
601 | void | ||
602 | osl_pktfree_static(osl_t *osh, void *p, bool send) | ||
603 | { | ||
604 | int i; | ||
605 | |||
606 | for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { | ||
607 | if (p == bcm_static_skb->skb_4k[i]) { | ||
608 | down(&bcm_static_skb->osl_pkt_sem); | ||
609 | bcm_static_skb->pkt_use[i] = 0; | ||
610 | up(&bcm_static_skb->osl_pkt_sem); | ||
611 | return; | ||
612 | } | ||
613 | } | ||
614 | |||
615 | for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { | ||
616 | if (p == bcm_static_skb->skb_8k[i]) { | ||
617 | down(&bcm_static_skb->osl_pkt_sem); | ||
618 | bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0; | ||
619 | up(&bcm_static_skb->osl_pkt_sem); | ||
620 | return; | ||
621 | } | ||
622 | } | ||
623 | |||
624 | return osl_pktfree(osh, p, send); | ||
625 | } | ||
626 | #endif | ||
627 | |||
628 | uint32 | ||
629 | osl_pci_read_config(osl_t *osh, uint offset, uint size) | ||
630 | { | ||
631 | uint val = 0; | ||
632 | uint retry = PCI_CFG_RETRY; | ||
633 | |||
634 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
635 | |||
636 | |||
637 | ASSERT(size == 4); | ||
638 | |||
639 | do { | ||
640 | pci_read_config_dword(osh->pdev, offset, &val); | ||
641 | if (val != 0xffffffff) | ||
642 | break; | ||
643 | } while (retry--); | ||
644 | |||
645 | |||
646 | return (val); | ||
647 | } | ||
648 | |||
649 | void | ||
650 | osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) | ||
651 | { | ||
652 | uint retry = PCI_CFG_RETRY; | ||
653 | |||
654 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
655 | |||
656 | |||
657 | ASSERT(size == 4); | ||
658 | |||
659 | do { | ||
660 | pci_write_config_dword(osh->pdev, offset, val); | ||
661 | if (offset != PCI_BAR0_WIN) | ||
662 | break; | ||
663 | if (osl_pci_read_config(osh, offset, size) == val) | ||
664 | break; | ||
665 | } while (retry--); | ||
666 | |||
667 | } | ||
668 | |||
669 | |||
670 | uint | ||
671 | osl_pci_bus(osl_t *osh) | ||
672 | { | ||
673 | ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); | ||
674 | |||
675 | return ((struct pci_dev *)osh->pdev)->bus->number; | ||
676 | } | ||
677 | |||
678 | |||
679 | uint | ||
680 | osl_pci_slot(osl_t *osh) | ||
681 | { | ||
682 | ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); | ||
683 | |||
684 | return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); | ||
685 | } | ||
686 | |||
687 | static void | ||
688 | osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) | ||
689 | { | ||
690 | } | ||
691 | |||
692 | void | ||
693 | osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) | ||
694 | { | ||
695 | osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); | ||
696 | } | ||
697 | |||
698 | void | ||
699 | osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) | ||
700 | { | ||
701 | osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); | ||
702 | } | ||
703 | |||
704 | void * | ||
705 | osl_malloc(osl_t *osh, uint size) | ||
706 | { | ||
707 | void *addr; | ||
708 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) | ||
709 | gfp_t flags; | ||
710 | |||
711 | |||
712 | if (osh) | ||
713 | ASSERT(osh->magic == OS_HANDLE_MAGIC); | ||
714 | |||
715 | flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
716 | if ((addr = kmalloc(size, flags)) == NULL) { | ||
717 | #else | ||
718 | if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { | ||
719 | #endif | ||
720 | if (osh) | ||
721 | osh->failed++; | ||
722 | return (NULL); | ||
723 | } | ||
724 | if (osh) | ||
725 | atomic_add(size, &osh->malloced); | ||
726 | |||
727 | return (addr); | ||
728 | } | ||
729 | |||
730 | void | ||
731 | osl_mfree(osl_t *osh, void *addr, uint size) | ||
732 | { | ||
733 | if (osh) { | ||
734 | ASSERT(osh->magic == OS_HANDLE_MAGIC); | ||
735 | atomic_sub(size, &osh->malloced); | ||
736 | } | ||
737 | kfree(addr); | ||
738 | } | ||
739 | |||
740 | uint | ||
741 | osl_malloced(osl_t *osh) | ||
742 | { | ||
743 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
744 | return (atomic_read(&osh->malloced)); | ||
745 | } | ||
746 | |||
747 | uint | ||
748 | osl_malloc_failed(osl_t *osh) | ||
749 | { | ||
750 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
751 | return (osh->failed); | ||
752 | } | ||
753 | |||
754 | |||
755 | |||
756 | uint | ||
757 | osl_dma_consistent_align(void) | ||
758 | { | ||
759 | return (PAGE_SIZE); | ||
760 | } | ||
761 | |||
762 | void* | ||
763 | osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap) | ||
764 | { | ||
765 | uint16 align = (1 << align_bits); | ||
766 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
767 | |||
768 | if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) | ||
769 | size += align; | ||
770 | *alloced = size; | ||
771 | |||
772 | return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); | ||
773 | } | ||
774 | |||
775 | void | ||
776 | osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) | ||
777 | { | ||
778 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
779 | |||
780 | pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); | ||
781 | } | ||
782 | |||
783 | uint BCMFASTPATH | ||
784 | osl_dma_map(osl_t *osh, void *va, uint size, int direction) | ||
785 | { | ||
786 | int dir; | ||
787 | |||
788 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
789 | dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; | ||
790 | return (pci_map_single(osh->pdev, va, size, dir)); | ||
791 | } | ||
792 | |||
793 | void BCMFASTPATH | ||
794 | osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) | ||
795 | { | ||
796 | int dir; | ||
797 | |||
798 | ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); | ||
799 | dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; | ||
800 | pci_unmap_single(osh->pdev, (uint32)pa, size, dir); | ||
801 | } | ||
802 | |||
803 | #if defined(BCMASSERT_LOG) | ||
804 | void | ||
805 | osl_assert(char *exp, char *file, int line) | ||
806 | { | ||
807 | char tempbuf[256]; | ||
808 | char *basename; | ||
809 | |||
810 | basename = strrchr(file, '/'); | ||
811 | |||
812 | if (basename) | ||
813 | basename++; | ||
814 | |||
815 | if (!basename) | ||
816 | basename = file; | ||
817 | |||
818 | #ifdef BCMASSERT_LOG | ||
819 | snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n", | ||
820 | exp, basename, line); | ||
821 | |||
822 | bcm_assert_log(tempbuf); | ||
823 | #endif | ||
824 | |||
825 | |||
826 | } | ||
827 | #endif | ||
828 | |||
829 | void | ||
830 | osl_delay(uint usec) | ||
831 | { | ||
832 | uint d; | ||
833 | |||
834 | while (usec > 0) { | ||
835 | d = MIN(usec, 1000); | ||
836 | udelay(d); | ||
837 | usec -= d; | ||
838 | } | ||
839 | } | ||
840 | |||
841 | |||
842 | |||
843 | void * | ||
844 | osl_pktdup(osl_t *osh, void *skb) | ||
845 | { | ||
846 | void * p; | ||
847 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) | ||
848 | gfp_t flags; | ||
849 | |||
850 | flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; | ||
851 | if ((p = skb_clone((struct sk_buff *)skb, flags)) == NULL) | ||
852 | #else | ||
853 | if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) | ||
854 | #endif | ||
855 | return NULL; | ||
856 | |||
857 | #ifdef CTFPOOL | ||
858 | if (PKTISFAST(osh, skb)) { | ||
859 | ctfpool_t *ctfpool; | ||
860 | |||
861 | |||
862 | ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); | ||
863 | ASSERT(ctfpool != NULL); | ||
864 | PKTCLRFAST(osh, p); | ||
865 | PKTCLRFAST(osh, skb); | ||
866 | ctfpool->refills++; | ||
867 | } | ||
868 | #endif | ||
869 | |||
870 | |||
871 | if (osh->pub.pkttag) | ||
872 | bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); | ||
873 | |||
874 | |||
875 | osh->pub.pktalloced++; | ||
876 | return (p); | ||
877 | } | ||
878 | |||
879 | |||
880 | |||
881 | |||
882 | |||
883 | |||
884 | |||
885 | void * | ||
886 | osl_os_open_image(char *filename) | ||
887 | { | ||
888 | struct file *fp; | ||
889 | |||
890 | fp = filp_open(filename, O_RDONLY, 0); | ||
891 | |||
892 | if (IS_ERR(fp)) | ||
893 | fp = NULL; | ||
894 | |||
895 | return fp; | ||
896 | } | ||
897 | |||
898 | int | ||
899 | osl_os_get_image_block(char *buf, int len, void *image) | ||
900 | { | ||
901 | struct file *fp = (struct file *)image; | ||
902 | int rdlen; | ||
903 | |||
904 | if (!image) | ||
905 | return 0; | ||
906 | |||
907 | rdlen = kernel_read(fp, fp->f_pos, buf, len); | ||
908 | if (rdlen > 0) | ||
909 | fp->f_pos += rdlen; | ||
910 | |||
911 | return rdlen; | ||
912 | } | ||
913 | |||
914 | void | ||
915 | osl_os_close_image(void *image) | ||
916 | { | ||
917 | if (image) | ||
918 | filp_close((struct file *)image, NULL); | ||
919 | } | ||