aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcmdhd/linux_osl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcmdhd/linux_osl.c')
-rw-r--r--drivers/net/wireless/bcmdhd/linux_osl.c203
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;
+}