diff options
Diffstat (limited to 'drivers/net/wireless/bcmdhd/linux_osl.c')
-rw-r--r-- | drivers/net/wireless/bcmdhd/linux_osl.c | 203 |
1 files changed, 116 insertions, 87 deletions
diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c index d03a095f5fe..32f03d9f5a5 100644 --- a/drivers/net/wireless/bcmdhd/linux_osl.c +++ b/drivers/net/wireless/bcmdhd/linux_osl.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.c 355147 2012-09-05 15:03:49Z $ + * $Id: linux_osl.c 390461 2013-03-12 07:21:34Z $ */ #define LINUX_PORT @@ -35,10 +35,6 @@ #include <linux/delay.h> #include <pcicfg.h> -#ifdef BCMASSERT_LOG -#include <bcm_assert_log.h> -#endif - #include <linux/fs.h> @@ -48,7 +44,7 @@ #define BCM_MEM_FILENAME_LEN 24 #ifdef CONFIG_DHD_USE_STATIC_BUF -#define DHD_SKB_HDRSIZE 336 +#define DHD_SKB_HDRSIZE 336 #define DHD_SKB_1PAGE_BUFSIZE ((PAGE_SIZE*1)-DHD_SKB_HDRSIZE) #define DHD_SKB_2PAGE_BUFSIZE ((PAGE_SIZE*2)-DHD_SKB_HDRSIZE) #define DHD_SKB_4PAGE_BUFSIZE ((PAGE_SIZE*4)-DHD_SKB_HDRSIZE) @@ -72,7 +68,7 @@ static bcm_static_buf_t *bcm_static_buf = 0; #else #define STATIC_PKT_4PAGE_NUM 0 #define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE -#endif +#endif typedef struct bcm_static_pkt { struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM]; @@ -104,6 +100,7 @@ struct osl_info { uint magic; void *pdev; atomic_t malloced; + atomic_t pktalloced; uint failed; uint bustype; bcm_mem_link_t *dbgmem_list; @@ -111,6 +108,16 @@ struct osl_info { spinlock_t pktalloc_lock; }; +#define OSL_PKTTAG_CLEAR(p) \ +do { \ + struct sk_buff *s = (struct sk_buff *)(p); \ + ASSERT(OSL_PKTTAG_SZ == 32); \ + *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \ + *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \ + *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \ + *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \ +} while (0) + @@ -188,14 +195,9 @@ osl_t * osl_attach(void *pdev, uint bustype, bool pkttag) { osl_t *osh; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - gfp_t flags; - flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; - osh = kmalloc(sizeof(osl_t), flags); -#else - osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); -#endif + if (!(osh = kmalloc(sizeof(osl_t), GFP_ATOMIC))) + return osh; ASSERT(osh); @@ -252,9 +254,9 @@ osl_attach(void *pdev, uint bustype, bool pkttag) bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); - bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)* + bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM)); - for (i = 0; i < (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM); i++) + for (i = 0; i < STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM; i++) bcm_static_skb->pkt_use[i] = 0; sema_init(&bcm_static_skb->osl_pkt_sem, 1); @@ -288,9 +290,10 @@ osl_detach(osl_t *osh) static struct sk_buff *osl_alloc_skb(unsigned int len) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - gfp_t flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; + struct sk_buff *skb; - return __dev_alloc_skb(len, flags); + skb = __dev_alloc_skb(len, GFP_ATOMIC); + return skb; #else return dev_alloc_skb(len); #endif @@ -370,14 +373,7 @@ osl_ctfpool_replenish(osl_t *osh, uint thresh) int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - gfp_t flags; - - flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; - osh->ctfpool = kmalloc(sizeof(ctfpool_t), flags); -#else osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); -#endif ASSERT(osh->ctfpool); bzero(osh->ctfpool, sizeof(ctfpool_t)); @@ -498,6 +494,9 @@ osl_pktfastget(osl_t *osh, uint len) #endif atomic_set(&skb->users, 1); + PKTSETCLINK(skb, NULL); + PKTCCLRATTR(skb); + return skb; } #endif @@ -505,22 +504,15 @@ osl_pktfastget(osl_t *osh, uint len) struct sk_buff * BCMFASTPATH osl_pkt_tonative(osl_t *osh, void *pkt) { -#ifndef WL_UMK struct sk_buff *nskb; - unsigned long flags; -#endif if (osh->pub.pkttag) - bzero((void*)((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); + OSL_PKTTAG_CLEAR(pkt); -#ifndef WL_UMK for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { - spin_lock_irqsave(&osh->pktalloc_lock, flags); - osh->pub.pktalloced--; - spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); } -#endif return (struct sk_buff *)pkt; } @@ -528,22 +520,15 @@ osl_pkt_tonative(osl_t *osh, void *pkt) void * BCMFASTPATH osl_pkt_frmnative(osl_t *osh, void *pkt) { -#ifndef WL_UMK struct sk_buff *nskb; - unsigned long flags; -#endif if (osh->pub.pkttag) - bzero((void*)((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); + OSL_PKTTAG_CLEAR(pkt); -#ifndef WL_UMK for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { - spin_lock_irqsave(&osh->pktalloc_lock, flags); - osh->pub.pktalloced++; - spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); } -#endif return (void *)pkt; } @@ -552,7 +537,6 @@ void * BCMFASTPATH osl_pktget(osl_t *osh, uint len) { struct sk_buff *skb; - unsigned long flags; #ifdef CTFPOOL @@ -564,10 +548,7 @@ osl_pktget(osl_t *osh, uint len) skb_put(skb, len); skb->priority = 0; - - spin_lock_irqsave(&osh->pktalloc_lock, flags); - osh->pub.pktalloced++; - spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + atomic_inc(&osh->pktalloced); } return ((void*) skb); @@ -590,10 +571,17 @@ osl_pktfastfree(osl_t *osh, struct sk_buff *skb) skb->dev = NULL; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) skb->dst = NULL; - memset(skb->cb, 0, sizeof(skb->cb)); +#endif + OSL_PKTTAG_CLEAR(skb); skb->ip_summed = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) + skb_orphan(skb); +#else skb->destructor = NULL; +#endif ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ASSERT(ctfpool != NULL); @@ -616,7 +604,11 @@ void BCMFASTPATH osl_pktfree(osl_t *osh, void *p, bool send) { struct sk_buff *skb, *nskb; - unsigned long flags; + if (osh == NULL) + { + printk("%s: osh == NULL \n", __FUNCTION__); + return; + } skb = (struct sk_buff*) p; @@ -647,9 +639,7 @@ osl_pktfree(osl_t *osh, void *p, bool send) dev_kfree_skb(skb); } - spin_lock_irqsave(&osh->pktalloc_lock, flags); - osh->pub.pktalloced--; - spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + atomic_dec(&osh->pktalloced); skb = nskb; } } @@ -661,10 +651,8 @@ osl_pktget_static(osl_t *osh, uint len) int i = 0; struct sk_buff *skb; - if (len > DHD_SKB_MAX_BUFSIZE) { - printk("osl_pktget_static: Do we really need this big skb??" - " len=%d\n", len); + printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); return osl_pktget(osh, len); } @@ -689,7 +677,6 @@ osl_pktget_static(osl_t *osh, uint len) } if (len <= DHD_SKB_2PAGE_BUFSIZE) { - for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { if (bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] == 0) @@ -721,7 +708,7 @@ osl_pktget_static(osl_t *osh, uint len) #endif up(&bcm_static_skb->osl_pkt_sem); - printk("osl_pktget_static: all static pkt in use!\n"); + printk("%s: all static pkt in use!\n", __FUNCTION__); return osl_pktget(osh, len); } @@ -752,15 +739,13 @@ osl_pktfree_static(osl_t *osh, void *p, bool send) } #ifdef ENHANCED_STATIC_BUF if (p == bcm_static_skb->skb_16k) { - bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM*2] = 0; + bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] = 0; up(&bcm_static_skb->osl_pkt_sem); return; } #endif up(&bcm_static_skb->osl_pkt_sem); - osl_pktfree(osh, p, send); - return; } #endif @@ -820,7 +805,11 @@ osl_pci_slot(osl_t *osh) { ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); +#if defined(__ARM_ARCH_7A__) && LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) + return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1; +#else return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); +#endif } @@ -853,9 +842,6 @@ void * osl_malloc(osl_t *osh, uint size) { void *addr; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - gfp_t flags; -#endif if (osh) @@ -895,12 +881,7 @@ osl_malloc(osl_t *osh, uint size) original: #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; - if ((addr = kmalloc(size, flags)) == NULL) { -#else if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { -#endif if (osh) osh->failed++; return (NULL); @@ -986,12 +967,45 @@ osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) } uint BCMFASTPATH -osl_dma_map(osl_t *osh, void *va, uint size, int direction) +osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) { int dir; ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; + +#if defined(__ARM_ARCH_7A__) && defined(BCMDMASGLISTOSL) + if (dmah != NULL) { + int32 nsegs, i, totsegs = 0, totlen = 0; + struct scatterlist *sg, _sg[16]; + struct sk_buff *skb; + for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) { + sg = &_sg[totsegs]; + if (skb_is_nonlinear(skb)) { + nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb)); + ASSERT((nsegs > 0) && (nsegs <= 16)); + pci_map_sg(osh->pdev, sg, nsegs, dir); + } else { + nsegs = 1; + sg->page_link = 0; + sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb)); + + pci_map_single(osh->pdev, PKTDATA(osh, skb), + PKTISCTF(osh, skb) ? CTFMAPSZ : PKTLEN(osh, skb), dir); + } + totsegs += nsegs; + totlen += PKTLEN(osh, skb); + } + dmah->nsegs = totsegs; + dmah->origsize = totlen; + for (i = 0, sg = _sg; i < totsegs; i++, sg++) { + dmah->segs[i].addr = sg_phys(sg); + dmah->segs[i].length = sg->length; + } + return dmah->segs[0].addr; + } +#endif + return (pci_map_single(osh->pdev, va, size, dir)); } @@ -1020,12 +1034,10 @@ osl_assert(const char *exp, const char *file, int line) if (!basename) basename = file; -#ifdef BCMASSERT_LOG snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n", exp, basename, line); - bcm_assert_log(tempbuf); -#endif + printk("%s", tempbuf); } @@ -1049,20 +1061,13 @@ void * osl_pktdup(osl_t *osh, void *skb) { void * p; - unsigned long irqflags; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - gfp_t flags; -#endif + + ASSERT(!PKTISCHAINED(skb)); PKTCTFMAP(osh, skb); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; - if ((p = skb_clone((struct sk_buff *)skb, flags)) == NULL) -#else - if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) -#endif + if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) return NULL; #ifdef CTFPOOL @@ -1079,13 +1084,15 @@ osl_pktdup(osl_t *osh, void *skb) #endif + PKTSETCLINK(p, NULL); + PKTCCLRATTR(p); + + if (osh->pub.pkttag) - bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); + OSL_PKTTAG_CLEAR(p); - spin_lock_irqsave(&osh->pktalloc_lock, irqflags); - osh->pub.pktalloced++; - spin_unlock_irqrestore(&osh->pktalloc_lock, irqflags); + atomic_inc(&osh->pktalloced); return (p); } @@ -1094,6 +1101,12 @@ osl_pktdup(osl_t *osh, void *skb) +uint +osl_pktalloced(osl_t *osh) +{ + return (atomic_read(&osh->pktalloced)); +} + void * osl_os_open_image(char *filename) @@ -1130,3 +1143,19 @@ osl_os_close_image(void *image) if (image) filp_close((struct file *)image, NULL); } + +int +osl_os_image_size(void *image) +{ + int len = 0, curroffset; + + if (image) { + + curroffset = generic_file_llseek(image, 0, 1); + + len = generic_file_llseek(image, 0, 2); + + generic_file_llseek(image, curroffset, 0); + } + return len; +} |