2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/version.h>
20 #include <linux/sched.h>
22 #include <bcmendian.h>
27 #include <linux/delay.h>
30 #define PCI_CFG_RETRY 10
32 #define OS_HANDLE_MAGIC 0x1234abcd
33 #define BCM_MEM_FILENAME_LEN 24
35 #ifdef DHD_USE_STATIC_BUF
36 #define MAX_STATIC_BUF_NUM 16
37 #define STATIC_BUF_SIZE (PAGE_SIZE*2)
38 #define STATIC_BUF_TOTAL_LEN (MAX_STATIC_BUF_NUM*STATIC_BUF_SIZE)
39 typedef struct bcm_static_buf
{
40 struct semaphore static_sem
;
41 unsigned char *buf_ptr
;
42 unsigned char buf_use
[MAX_STATIC_BUF_NUM
];
45 static bcm_static_buf_t
*bcm_static_buf
;
47 #define MAX_STATIC_PKT_NUM 8
48 typedef struct bcm_static_pkt
{
49 struct sk_buff
*skb_4k
[MAX_STATIC_PKT_NUM
];
50 struct sk_buff
*skb_8k
[MAX_STATIC_PKT_NUM
];
51 struct semaphore osl_pkt_sem
;
52 unsigned char pkt_use
[MAX_STATIC_PKT_NUM
* 2];
54 static bcm_static_pkt_t
*bcm_static_skb
;
55 #endif /* DHD_USE_STATIC_BUF */
57 typedef struct bcm_mem_link
{
58 struct bcm_mem_link
*prev
;
59 struct bcm_mem_link
*next
;
62 char file
[BCM_MEM_FILENAME_LEN
];
72 bcm_mem_link_t
*dbgmem_list
;
75 static int16 linuxbcmerrormap
[] = { 0,
119 #if BCME_LAST != BCME_NONRESIDENT
120 #error "You need to add a OS error translation in the linuxbcmerrormap \
121 for new error code defined in bcmutils.h"
125 /* Global ASSERT type flag */
126 uint32 g_assert_type
;
128 int osl_error(int bcmerror
)
132 else if (bcmerror
< BCME_LAST
)
133 bcmerror
= BCME_ERROR
;
135 return linuxbcmerrormap
[-bcmerror
];
138 void *dhd_os_prealloc(int section
, unsigned long size
);
139 osl_t
*osl_attach(void *pdev
, uint bustype
, bool pkttag
)
143 osh
= kmalloc(sizeof(osl_t
), GFP_ATOMIC
);
146 bzero(osh
, sizeof(osl_t
));
148 ASSERT(ABS(BCME_LAST
) == (ARRAYSIZE(linuxbcmerrormap
) - 1));
150 osh
->magic
= OS_HANDLE_MAGIC
;
153 osh
->dbgmem_list
= NULL
;
155 osh
->pub
.pkttag
= pkttag
;
156 osh
->bustype
= bustype
;
162 osh
->pub
.mmbus
= TRUE
;
168 osh
->pub
.mmbus
= FALSE
;
175 #ifdef DHD_USE_STATIC_BUF
177 if (!bcm_static_buf
) {
178 bcm_static_buf
= (bcm_static_buf_t
*) dhd_os_prealloc(3,
179 STATIC_BUF_SIZE
+ STATIC_BUF_TOTAL_LEN
);
180 if (!bcm_static_buf
) {
181 printk(KERN_ERR
"can not alloc static buf!\n");
183 printk(KERN_ERR
"alloc static buf at %x!\n",
184 (unsigned int)bcm_static_buf
);
186 init_MUTEX(&bcm_static_buf
->static_sem
);
188 bcm_static_buf
->buf_ptr
=
189 (unsigned char *)bcm_static_buf
+ STATIC_BUF_SIZE
;
193 if (!bcm_static_skb
) {
195 void *skb_buff_ptr
= 0;
197 (bcm_static_pkt_t
*) ((char *)bcm_static_buf
+ 2048);
198 skb_buff_ptr
= dhd_os_prealloc(4, 0);
200 bcopy(skb_buff_ptr
, bcm_static_skb
,
201 sizeof(struct sk_buff
*) * 16);
202 for (i
= 0; i
< MAX_STATIC_PKT_NUM
* 2; i
++)
203 bcm_static_skb
->pkt_use
[i
] = 0;
205 init_MUTEX(&bcm_static_skb
->osl_pkt_sem
);
207 #endif /* DHD_USE_STATIC_BUF */
211 void osl_detach(osl_t
*osh
)
216 #ifdef DHD_USE_STATIC_BUF
223 ASSERT(osh
->magic
== OS_HANDLE_MAGIC
);
227 void *osl_pktget(osl_t
*osh
, uint len
)
231 skb
= dev_alloc_skb(len
);
236 osh
->pub
.pktalloced
++;
242 void osl_pktfree(osl_t
*osh
, void *p
, bool send
)
244 struct sk_buff
*skb
, *nskb
;
246 skb
= (struct sk_buff
*)p
;
248 if (send
&& osh
->pub
.tx_fn
)
249 osh
->pub
.tx_fn(osh
->pub
.tx_ctx
, p
, 0);
256 dev_kfree_skb_any(skb
);
260 osh
->pub
.pktalloced
--;
266 #ifdef DHD_USE_STATIC_BUF
267 void *osl_pktget_static(osl_t
*osh
, uint len
)
272 if (len
> (PAGE_SIZE
* 2)) {
273 printk(KERN_ERR
"Do we really need this big skb??\n");
274 return osl_pktget(osh
, len
);
277 down(&bcm_static_skb
->osl_pkt_sem
);
278 if (len
<= PAGE_SIZE
) {
279 for (i
= 0; i
< MAX_STATIC_PKT_NUM
; i
++) {
280 if (bcm_static_skb
->pkt_use
[i
] == 0)
284 if (i
!= MAX_STATIC_PKT_NUM
) {
285 bcm_static_skb
->pkt_use
[i
] = 1;
286 up(&bcm_static_skb
->osl_pkt_sem
);
288 skb
= bcm_static_skb
->skb_4k
[i
];
289 skb
->tail
= skb
->data
+ len
;
296 for (i
= 0; i
< MAX_STATIC_PKT_NUM
; i
++) {
297 if (bcm_static_skb
->pkt_use
[i
+ MAX_STATIC_PKT_NUM
] == 0)
301 if (i
!= MAX_STATIC_PKT_NUM
) {
302 bcm_static_skb
->pkt_use
[i
+ MAX_STATIC_PKT_NUM
] = 1;
303 up(&bcm_static_skb
->osl_pkt_sem
);
304 skb
= bcm_static_skb
->skb_8k
[i
];
305 skb
->tail
= skb
->data
+ len
;
311 up(&bcm_static_skb
->osl_pkt_sem
);
312 printk(KERN_ERR
"all static pkt in use!\n");
313 return osl_pktget(osh
, len
);
316 void osl_pktfree_static(osl_t
*osh
, void *p
, bool send
)
320 for (i
= 0; i
< MAX_STATIC_PKT_NUM
* 2; i
++) {
321 if (p
== bcm_static_skb
->skb_4k
[i
]) {
322 down(&bcm_static_skb
->osl_pkt_sem
);
323 bcm_static_skb
->pkt_use
[i
] = 0;
324 up(&bcm_static_skb
->osl_pkt_sem
);
329 return osl_pktfree(osh
, p
, send
);
331 #endif /* DHD_USE_STATIC_BUF */
333 uint32
osl_pci_read_config(osl_t
*osh
, uint offset
, uint size
)
336 uint retry
= PCI_CFG_RETRY
;
338 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
342 pci_read_config_dword(osh
->pdev
, offset
, &val
);
343 if (val
!= 0xffffffff)
350 void osl_pci_write_config(osl_t
*osh
, uint offset
, uint size
, uint val
)
352 uint retry
= PCI_CFG_RETRY
;
354 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
358 pci_write_config_dword(osh
->pdev
, offset
, val
);
359 if (offset
!= PCI_BAR0_WIN
)
361 if (osl_pci_read_config(osh
, offset
, size
) == val
)
367 uint
osl_pci_bus(osl_t
*osh
)
369 ASSERT(osh
&& (osh
->magic
== OS_HANDLE_MAGIC
) && osh
->pdev
);
371 return ((struct pci_dev
*)osh
->pdev
)->bus
->number
;
374 uint
osl_pci_slot(osl_t
*osh
)
376 ASSERT(osh
&& (osh
->magic
== OS_HANDLE_MAGIC
) && osh
->pdev
);
378 return PCI_SLOT(((struct pci_dev
*)osh
->pdev
)->devfn
);
382 osl_pcmcia_attr(osl_t
*osh
, uint offset
, char *buf
, int size
, bool write
)
386 void osl_pcmcia_read_attr(osl_t
*osh
, uint offset
, void *buf
, int size
)
388 osl_pcmcia_attr(osh
, offset
, (char *)buf
, size
, FALSE
);
391 void osl_pcmcia_write_attr(osl_t
*osh
, uint offset
, void *buf
, int size
)
393 osl_pcmcia_attr(osh
, offset
, (char *)buf
, size
, TRUE
);
396 void *osl_malloc(osl_t
*osh
, uint size
)
401 ASSERT(osh
->magic
== OS_HANDLE_MAGIC
);
403 #ifdef DHD_USE_STATIC_BUF
404 if (bcm_static_buf
) {
406 if ((size
>= PAGE_SIZE
) && (size
<= STATIC_BUF_SIZE
)) {
407 down(&bcm_static_buf
->static_sem
);
408 for (i
= 0; i
< MAX_STATIC_BUF_NUM
; i
++) {
409 if (bcm_static_buf
->buf_use
[i
] == 0)
412 if (i
== MAX_STATIC_BUF_NUM
) {
413 up(&bcm_static_buf
->static_sem
);
414 printk(KERN_ERR
"all static buff in use!\n");
417 bcm_static_buf
->buf_use
[i
] = 1;
418 up(&bcm_static_buf
->static_sem
);
420 bzero(bcm_static_buf
->buf_ptr
+ STATIC_BUF_SIZE
* i
,
423 osh
->malloced
+= size
;
425 return (void *)(bcm_static_buf
->buf_ptr
+
426 STATIC_BUF_SIZE
* i
);
430 #endif /* DHD_USE_STATIC_BUF */
432 addr
= kmalloc(size
, GFP_ATOMIC
);
439 osh
->malloced
+= size
;
444 void osl_mfree(osl_t
*osh
, void *addr
, uint size
)
446 #ifdef DHD_USE_STATIC_BUF
447 if (bcm_static_buf
) {
448 if ((addr
> (void *)bcm_static_buf
) && ((unsigned char *)addr
449 <= ((unsigned char *)
451 STATIC_BUF_TOTAL_LEN
))) {
454 ((unsigned char *)addr
-
455 bcm_static_buf
->buf_ptr
) / STATIC_BUF_SIZE
;
456 down(&bcm_static_buf
->static_sem
);
457 bcm_static_buf
->buf_use
[buf_idx
] = 0;
458 up(&bcm_static_buf
->static_sem
);
461 ASSERT(osh
->magic
== OS_HANDLE_MAGIC
);
462 osh
->malloced
-= size
;
467 #endif /* DHD_USE_STATIC_BUF */
469 ASSERT(osh
->magic
== OS_HANDLE_MAGIC
);
470 osh
->malloced
-= size
;
475 uint
osl_malloced(osl_t
*osh
)
477 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
478 return osh
->malloced
;
481 uint
osl_malloc_failed(osl_t
*osh
)
483 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
487 void *osl_dma_alloc_consistent(osl_t
*osh
, uint size
, unsigned long *pap
)
489 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
491 return pci_alloc_consistent(osh
->pdev
, size
, (dma_addr_t
*) pap
);
494 void osl_dma_free_consistent(osl_t
*osh
, void *va
, uint size
, unsigned long pa
)
496 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
498 pci_free_consistent(osh
->pdev
, size
, va
, (dma_addr_t
) pa
);
501 uint
osl_dma_map(osl_t
*osh
, void *va
, uint size
, int direction
)
505 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
506 dir
= (direction
== DMA_TX
) ? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE
;
507 return pci_map_single(osh
->pdev
, va
, size
, dir
);
510 void osl_dma_unmap(osl_t
*osh
, uint pa
, uint size
, int direction
)
514 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
515 dir
= (direction
== DMA_TX
) ? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE
;
516 pci_unmap_single(osh
->pdev
, (uint32
) pa
, size
, dir
);
519 #if defined(BCMDBG_ASSERT)
520 void osl_assert(char *exp
, char *file
, int line
)
525 basename
= strrchr(file
, '/');
534 snprintf(tempbuf
, 256,
535 "assertion \"%s\" failed: file \"%s\", line %d\n", exp
,
538 /* Print assert message and give it time to be written
539 to /var/log/messages */
540 if (!in_interrupt()) {
542 printk(KERN_ERR
"%s", tempbuf
);
543 printk(KERN_ERR
"panic in %d seconds\n", delay
);
544 set_current_state(TASK_INTERRUPTIBLE
);
545 schedule_timeout(delay
* HZ
);
548 switch (g_assert_type
) {
550 panic(KERN_ERR
"%s", tempbuf
);
553 printk(KERN_ERR
"%s", tempbuf
);
557 printk(KERN_ERR
"%s", tempbuf
);
562 #endif /* BCMDBG_ASSERT */
565 #endif /* defined(BCMDBG_ASSERT) */
567 void osl_delay(uint usec
)
578 void *osl_pktdup(osl_t
*osh
, void *skb
)
582 p
= skb_clone((struct sk_buff
*)skb
, GFP_ATOMIC
);
587 bzero((void *)((struct sk_buff
*)p
)->cb
, OSL_PKTTAG_SZ
);
589 osh
->pub
.pktalloced
++;
This page took 0.044839 seconds and 5 git commands to generate.