--- /dev/null
+++ b/drivers/bcmdrivers/gmac/src/shared/linux_osl.c
@@ -0,0 +1,1713 @@
+/*
+ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Linux OS Independent Layer
+ *
+ * $Id: linux_osl.c 322208 2012-03-20 01:53:23Z $
+ */
+
+#define LINUX_PORT
+
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <linuxver.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <linux/delay.h>
+#ifdef mips
+#include <asm/paccess.h>
+#endif /* mips */
+#include <pcicfg.h>
+
+
+
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+
+#define PCI_CFG_RETRY 		10
+
+#define OS_HANDLE_MAGIC		0x1234abcd	/* Magic # to recognize osh */
+#define BCM_MEM_FILENAME_LEN 	24		/* Mem. filename length */
+
+#ifdef DHD_USE_STATIC_BUF
+#define STATIC_BUF_MAX_NUM	16
+#define STATIC_BUF_SIZE	(PAGE_SIZE*2)
+#define STATIC_BUF_TOTAL_LEN	(STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
+
+typedef struct bcm_static_buf {
+	struct semaphore static_sem;
+	unsigned char *buf_ptr;
+	unsigned char buf_use[STATIC_BUF_MAX_NUM];
+} bcm_static_buf_t;
+
+static bcm_static_buf_t *bcm_static_buf = 0;
+
+#define STATIC_PKT_MAX_NUM	8
+
+typedef struct bcm_static_pkt {
+	struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM];
+	struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM];
+	struct semaphore osl_pkt_sem;
+	unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2];
+} bcm_static_pkt_t;
+
+static bcm_static_pkt_t *bcm_static_skb = 0;
+#endif /* DHD_USE_STATIC_BUF */
+
+typedef struct bcm_mem_link {
+	struct bcm_mem_link *prev;
+	struct bcm_mem_link *next;
+	uint	size;
+	int	line;
+	void 	*osh;
+	char	file[BCM_MEM_FILENAME_LEN];
+} bcm_mem_link_t;
+
+struct osl_info {
+	osl_pubinfo_t pub;
+#ifdef CTFPOOL
+	ctfpool_t *ctfpool;
+#endif /* CTFPOOL */
+	uint magic;
+	void *pdev;
+	atomic_t malloced;
+	atomic_t pktalloced; 	/* Number of allocated packet buffers */
+	uint failed;
+	uint bustype;
+	bcm_mem_link_t *dbgmem_list;
+#if defined(DSLCPE_DELAY)
+	shared_osl_t *oshsh; /* osh shared */
+#endif
+	spinlock_t dbgmem_lock;
+	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)
+
+/* PCMCIA attribute space access macros */
+#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
+struct pcmcia_dev {
+	dev_link_t link;	/* PCMCIA device pointer */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+	dev_node_t node;	/* PCMCIA node structure */
+#endif
+	void *base;		/* Mapped attribute memory window */
+	size_t size;		/* Size of window */
+	void *drv;		/* Driver data */
+};
+#endif /* defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) */
+
+/* Global ASSERT type flag */
+uint32 g_assert_type = FALSE;
+
+static int16 linuxbcmerrormap[] =
+{	0, 			/* 0 */
+	-EINVAL,		/* BCME_ERROR */
+	-EINVAL,		/* BCME_BADARG */
+	-EINVAL,		/* BCME_BADOPTION */
+	-EINVAL,		/* BCME_NOTUP */
+	-EINVAL,		/* BCME_NOTDOWN */
+	-EINVAL,		/* BCME_NOTAP */
+	-EINVAL,		/* BCME_NOTSTA */
+	-EINVAL,		/* BCME_BADKEYIDX */
+	-EINVAL,		/* BCME_RADIOOFF */
+	-EINVAL,		/* BCME_NOTBANDLOCKED */
+	-EINVAL, 		/* BCME_NOCLK */
+	-EINVAL, 		/* BCME_BADRATESET */
+	-EINVAL, 		/* BCME_BADBAND */
+	-E2BIG,			/* BCME_BUFTOOSHORT */
+	-E2BIG,			/* BCME_BUFTOOLONG */
+	-EBUSY, 		/* BCME_BUSY */
+	-EINVAL, 		/* BCME_NOTASSOCIATED */
+	-EINVAL, 		/* BCME_BADSSIDLEN */
+	-EINVAL, 		/* BCME_OUTOFRANGECHAN */
+	-EINVAL, 		/* BCME_BADCHAN */
+	-EFAULT, 		/* BCME_BADADDR */
+	-ENOMEM, 		/* BCME_NORESOURCE */
+	-EOPNOTSUPP,		/* BCME_UNSUPPORTED */
+	-EMSGSIZE,		/* BCME_BADLENGTH */
+	-EINVAL,		/* BCME_NOTREADY */
+	-EPERM,			/* BCME_EPERM */
+	-ENOMEM, 		/* BCME_NOMEM */
+	-EINVAL, 		/* BCME_ASSOCIATED */
+	-ERANGE, 		/* BCME_RANGE */
+	-EINVAL, 		/* BCME_NOTFOUND */
+	-EINVAL, 		/* BCME_WME_NOT_ENABLED */
+	-EINVAL, 		/* BCME_TSPEC_NOTFOUND */
+	-EINVAL, 		/* BCME_ACM_NOTSUPPORTED */
+	-EINVAL,		/* BCME_NOT_WME_ASSOCIATION */
+	-EIO,			/* BCME_SDIO_ERROR */
+	-ENODEV,		/* BCME_DONGLE_DOWN */
+	-EINVAL,		/* BCME_VERSION */
+	-EIO,			/* BCME_TXFAIL */
+	-EIO,			/* BCME_RXFAIL */
+	-ENODEV,		/* BCME_NODEVICE */
+	-EINVAL,		/* BCME_NMODE_DISABLED */
+	-ENODATA,		/* BCME_NONRESIDENT */
+
+/* When an new error code is added to bcmutils.h, add os
+ * specific error translation here as well
+ */
+/* check if BCME_LAST changed since the last time this function was updated */
+#if BCME_LAST != -42
+#error "You need to add a OS error translation in the linuxbcmerrormap \
+	for new error code defined in bcmutils.h"
+#endif
+};
+
+/* translate bcmerrors into linux errors */
+int
+osl_error(int bcmerror)
+{
+	if (bcmerror > 0)
+		bcmerror = 0;
+	else if (bcmerror < BCME_LAST)
+		bcmerror = BCME_ERROR;
+
+	/* Array bounds covered by ASSERT in osl_attach */
+	return linuxbcmerrormap[-bcmerror];
+}
+
+extern uint8* dhd_os_prealloc(void *osh, int section, int size);
+
+EXPORT_SYMBOL(osl_attach);
+osl_t *
+osl_attach(void *pdev, uint bustype, bool pkttag)
+{
+	osl_t *osh;
+
+	osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
+	ASSERT(osh);
+
+	bzero(osh, sizeof(osl_t));
+
+	/* Check that error map has the right number of entries in it */
+	ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
+
+	osh->magic = OS_HANDLE_MAGIC;
+	atomic_set(&osh->malloced, 0);
+	osh->failed = 0;
+	osh->dbgmem_list = NULL;
+	spin_lock_init(&(osh->dbgmem_lock));
+	osh->pdev = pdev;
+	osh->pub.pkttag = pkttag;
+	osh->bustype = bustype;
+
+	switch (bustype) {
+		case PCI_BUS:
+		case SI_BUS:
+		case PCMCIA_BUS:
+			osh->pub.mmbus = TRUE;
+			break;
+		case JTAG_BUS:
+		case SDIO_BUS:
+		case USB_BUS:
+		case SPI_BUS:
+		case RPC_BUS:
+			osh->pub.mmbus = FALSE;
+			break;
+		default:
+			ASSERT(FALSE);
+			break;
+	}
+
+#if defined(DHD_USE_STATIC_BUF)
+	if (!bcm_static_buf) {
+		if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+
+			STATIC_BUF_TOTAL_LEN))) {
+			printk("can not alloc static buf!\n");
+		}
+		else
+			printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf);
+
+
+		sema_init(&bcm_static_buf->static_sem, 1);
+
+		bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE;
+	}
+
+	if (!bcm_static_skb) {
+		int i;
+		void *skb_buff_ptr = 0;
+		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 *)*16);
+		for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++)
+			bcm_static_skb->pkt_use[i] = 0;
+
+		sema_init(&bcm_static_skb->osl_pkt_sem, 1);
+	}
+#endif /* DHD_USE_STATIC_BUF */
+
+	spin_lock_init(&(osh->pktalloc_lock));
+
+#ifdef BCMDBG
+	if (pkttag) {
+		struct sk_buff *skb;
+		ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb));
+	}
+#endif
+	return osh;
+}
+
+void
+osl_detach(osl_t *osh)
+{
+	if (osh == NULL)
+		return;
+
+#ifdef DHD_USE_STATIC_BUF
+		if (bcm_static_buf) {
+			bcm_static_buf = 0;
+		}
+		if (bcm_static_skb) {
+			bcm_static_skb = 0;
+		}
+#endif
+
+	ASSERT(osh->magic == OS_HANDLE_MAGIC);
+	kfree(osh);
+}
+
+static struct sk_buff *osl_alloc_skb(unsigned int len)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+	gfp_t flags = GFP_ATOMIC;
+
+	return __dev_alloc_skb(len, flags);
+#else
+	return dev_alloc_skb(len);
+#endif
+}
+
+#ifdef CTFPOOL
+
+#ifdef CTFPOOL_SPINLOCK
+#define CTFPOOL_LOCK(ctfpool, flags)	spin_lock_irqsave(&(ctfpool)->lock, flags)
+#define CTFPOOL_UNLOCK(ctfpool, flags)	spin_unlock_irqrestore(&(ctfpool)->lock, flags)
+#else
+#define CTFPOOL_LOCK(ctfpool, flags)	spin_lock_bh(&(ctfpool)->lock)
+#define CTFPOOL_UNLOCK(ctfpool, flags)	spin_unlock_bh(&(ctfpool)->lock)
+#endif /* CTFPOOL_SPINLOCK */
+/*
+ * Allocate and add an object to packet pool.
+ */
+void *
+osl_ctfpool_add(osl_t *osh)
+{
+	struct sk_buff *skb;
+#ifdef CTFPOOL_SPINLOCK
+	unsigned long flags;
+#endif /* CTFPOOL_SPINLOCK */
+
+	if ((osh == NULL) || (osh->ctfpool == NULL))
+		return NULL;
+
+	CTFPOOL_LOCK(osh->ctfpool, flags);
+	ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj);
+
+	/* No need to allocate more objects */
+	if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) {
+		CTFPOOL_UNLOCK(osh->ctfpool, flags);
+		return NULL;
+	}
+
+	/* Allocate a new skb and add it to the ctfpool */
+	skb = osl_alloc_skb(osh->ctfpool->obj_size);
+	if (skb == NULL) {
+		printk("%s: skb alloc of len %d failed\n", __FUNCTION__,
+		       osh->ctfpool->obj_size);
+		CTFPOOL_UNLOCK(osh->ctfpool, flags);
+		return NULL;
+	}
+
+	/* Add to ctfpool */
+	skb->next = (struct sk_buff *)osh->ctfpool->head;
+	osh->ctfpool->head = skb;
+	osh->ctfpool->fast_frees++;
+	osh->ctfpool->curr_obj++;
+
+#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING
+#ifdef SKB_RECYCLING_DEBUG
+    if ((osh->ctfpool->unit == 2)) {
+        static int count = 0;
+        printk("<%d>allocated skb=%p\n", count, skb);
+        count++;
+    }
+#endif /* SKB_RECYCLING_DEBUG */
+    /* Fot reset during release to pool */
+    skb->reset_size = skb->truesize;
+#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */
+
+	/* Hijack a skb member to store ptr to ctfpool */
+	CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool;
+
+	/* Use bit flag to indicate skb from fast ctfpool */
+	PKTFAST(osh, skb) = FASTBUF;
+
+	CTFPOOL_UNLOCK(osh->ctfpool, flags);
+
+	return skb;
+}
+
+/*
+ * Add new objects to the pool.
+ */
+void
+osl_ctfpool_replenish(osl_t *osh, uint thresh)
+{
+	if ((osh == NULL) || (osh->ctfpool == NULL))
+		return;
+
+	/* Do nothing if no refills are required */
+	while ((osh->ctfpool->refills > 0) && (thresh--)) {
+		osl_ctfpool_add(osh);
+		osh->ctfpool->refills--;
+	}
+}
+
+/*
+ * Initialize the packet pool with specified number of objects.
+ */
+int32
+#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING
+osl_ctfpool_init(int unit, osl_t *osh, uint numobj, uint size)
+#else
+osl_ctfpool_init(osl_t *osh, uint numobj, uint size)
+#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */
+{
+	osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC);
+	ASSERT(osh->ctfpool);
+	bzero(osh->ctfpool, sizeof(ctfpool_t));
+
+	osh->ctfpool->max_obj = numobj;
+	osh->ctfpool->obj_size = size;
+
+#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING
+    osh->ctfpool->unit = unit;
+#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */
+	spin_lock_init(&osh->ctfpool->lock);
+
+	while (numobj--) {
+		if (!osl_ctfpool_add(osh))
+			return -1;
+		osh->ctfpool->fast_frees--;
+	}
+
+#ifdef SKB_RECYCLING_DEBUG
+    printk("ctfpool = %p\n", osh->ctfpool);
+#endif /* SKB_RECYCLING_DEBUG */
+	return 0;
+}
+
+/*
+ * Cleanup the packet pool objects.
+ */
+void
+osl_ctfpool_cleanup(osl_t *osh)
+{
+	struct sk_buff *skb, *nskb;
+#ifdef CTFPOOL_SPINLOCK
+	unsigned long flags;
+#endif /* CTFPOOL_SPINLOCK */
+
+	if ((osh == NULL) || (osh->ctfpool == NULL))
+		return;
+
+	CTFPOOL_LOCK(osh->ctfpool, flags);
+
+	skb = osh->ctfpool->head;
+
+	while (skb != NULL) {
+		nskb = skb->next;
+		dev_kfree_skb(skb);
+		skb = nskb;
+		osh->ctfpool->curr_obj--;
+	}
+
+	ASSERT(osh->ctfpool->curr_obj == 0);
+	osh->ctfpool->head = NULL;
+	CTFPOOL_UNLOCK(osh->ctfpool, flags);
+
+	kfree(osh->ctfpool);
+	osh->ctfpool = NULL;
+}
+
+void
+osl_ctfpool_stats(osl_t *osh, void *b)
+{
+	struct bcmstrbuf *bb;
+
+	if ((osh == NULL) || (osh->ctfpool == NULL))
+		return;
+
+#ifdef DHD_USE_STATIC_BUF
+	if (bcm_static_buf) {
+		bcm_static_buf = 0;
+	}
+	if (bcm_static_skb) {
+		bcm_static_skb = 0;
+	}
+#endif /* DHD_USE_STATIC_BUF */
+
+	bb = b;
+
+	ASSERT((osh != NULL) && (bb != NULL));
+
+	bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n",
+	            osh->ctfpool->max_obj, osh->ctfpool->obj_size,
+	            osh->ctfpool->curr_obj, osh->ctfpool->refills);
+	bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n",
+	            osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees,
+	            osh->ctfpool->slow_allocs);
+}
+
+static inline struct sk_buff *
+osl_pktfastget(osl_t *osh, uint len)
+{
+	struct sk_buff *skb;
+#ifdef CTFPOOL_SPINLOCK
+	unsigned long flags;
+#endif /* CTFPOOL_SPINLOCK */
+
+	/* Try to do fast allocate. Return null if ctfpool is not in use
+	 * or if there are no items in the ctfpool.
+	 */
+	if (osh->ctfpool == NULL)
+		return NULL;
+
+	CTFPOOL_LOCK(osh->ctfpool, flags);
+	if (osh->ctfpool->head == NULL) {
+		ASSERT(osh->ctfpool->curr_obj == 0);
+		osh->ctfpool->slow_allocs++;
+		CTFPOOL_UNLOCK(osh->ctfpool, flags);
+#ifdef 	SKB_RECYCLING_DEBUG
+        WARN_ON_ONCE(1);
+#endif /* SKB_RECYCLING_DEBUG */
+		return NULL;
+	}
+
+	ASSERT(len <= osh->ctfpool->obj_size);
+	if (len > osh->ctfpool->obj_size) {
+		CTFPOOL_UNLOCK(osh->ctfpool, flags);
+		return NULL;
+	}
+
+	/* Get an object from ctfpool */
+	skb = (struct sk_buff *)osh->ctfpool->head;
+	osh->ctfpool->head = (void *)skb->next;
+
+#ifdef SKB_RECYCLING_DEBUG
+    {
+        if (skb->next == NULL) {
+            printk("Get a skb whose next is empty: osh->ctfpool=%p, \
+            skb=%p,  skb->next=%p, osh->ctfpool->head=%p\n",
+            osh->ctfpool, skb, skb->next, osh->ctfpool->head);
+        }
+    }
+#endif  /* SKB_RECYCLING_DEBUG */
+
+
+	osh->ctfpool->fast_allocs++;
+	osh->ctfpool->curr_obj--;
+	ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head);
+	CTFPOOL_UNLOCK(osh->ctfpool, flags);
+
+	/* Init skb struct */
+	skb->next = skb->prev = NULL;
+	skb->data = skb->head + 16;
+	skb->tail = skb->head + 16;
+
+	skb->len = 0;
+	skb->cloned = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+	skb->list = NULL;
+#endif
+	atomic_set(&skb->users, 1);
+
+	PKTSETCLINK(skb, NULL);
+	PKTCCLRATTR(skb);
+#ifdef HNDCTF
+	PKTFAST(osh, skb) &= ~(CTFBUF | SKIPCT | CHAINED);
+#endif
+	return skb;
+}
+#endif /* CTFPOOL */
+/* Convert a driver packet to native(OS) packet
+ * In the process, packettag is zeroed out before sending up
+ * IP code depends on skb->cb to be setup correctly with various options
+ * In our case, that means it should be 0
+ */
+struct sk_buff * BCMFASTPATH
+osl_pkt_tonative(osl_t *osh, void *pkt)
+{
+	struct sk_buff *nskb;
+
+	if (osh->pub.pkttag)
+		OSL_PKTTAG_CLEAR(pkt);
+
+	/* Decrement the packet counter */
+	for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
+		atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced);
+	}
+	return (struct sk_buff *)pkt;
+}
+
+/* Convert a native(OS) packet to driver packet.
+ * In the process, native packet is destroyed, there is no copying
+ * Also, a packettag is zeroed out
+ */
+void * BCMFASTPATH
+osl_pkt_frmnative(osl_t *osh, void *pkt)
+{
+	struct sk_buff *nskb;
+
+	if (osh->pub.pkttag)
+		OSL_PKTTAG_CLEAR(pkt);
+
+	/* Increment the packet counter */
+	for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
+		atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced);
+	}
+	return (void *)pkt;
+}
+
+/* Return a new packet. zero out pkttag */
+void * BCMFASTPATH
+osl_pktget(osl_t *osh, uint len)
+{
+	struct sk_buff *skb;
+
+#ifdef CTFPOOL
+	/* Allocate from local pool */
+	skb = osl_pktfastget(osh, len);
+
+#ifdef SKB_RECYCLING_DEBUG
+    if (skb == NULL) {
+        printk("<%s> osl_pktfastget fail! ctfpool=%p, ctfpool->head=%p, \
+		    ctfpool->curr_obj=%u, ctfpool->fast_allocs=%u, \
+			ctfpool->fast_frees=%u, ctfpool->slow_allocs=%u\n",
+            __FUNCTION__, osh->ctfpool, osh->ctfpool->head,
+			osh->ctfpool->curr_obj,  osh->ctfpool->fast_allocs,
+			osh->ctfpool->fast_frees, osh->ctfpool->slow_allocs);
+    }
+#endif /* SKB_RECYCLING_DEBUG */
+
+	if ((skb != NULL) || ((skb = osl_alloc_skb(len)) != NULL)) {
+#else /* CTFPOOL */
+	if ((skb = osl_alloc_skb(len))) {
+#endif /* CTFPOOL */
+		skb_put(skb, len);
+		skb->priority = 0;
+
+		atomic_inc(&osh->pktalloced);
+	}
+
+	PKTSETCLINK(skb, NULL);
+
+	return ((void*) skb);
+}
+
+#ifdef CTFPOOL
+static inline void
+osl_pktfastfree(osl_t *osh, struct sk_buff *skb)
+{
+	ctfpool_t *ctfpool;
+#ifdef CTFPOOL_SPINLOCK
+	unsigned long flags;
+#endif /* CTFPOOL_SPINLOCK */
+
+#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING
+
+	if (skb->destructor) {
+		WARN_ON(in_irq());
+		skb->destructor(skb);
+	}
+
+        skb->data_len = 0;
+        skb->truesize = skb->reset_size;
+
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
+	skb->tstamp.tv.sec = 0; /*ING*/
+#else
+    skb->tstamp.tv64 = 0;
+#endif
+#else
+	skb->stamp.tv_sec = 0;
+#endif
+#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */
+
+	/* We only need to init the fields that we change */
+	skb->dev = NULL;
+
+#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+        skb->dst = NULL;
+#endif
+#endif /* !CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */
+        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);
+
+	/* Add object to the ctfpool */
+	CTFPOOL_LOCK(ctfpool, flags);
+	skb->next = (struct sk_buff *)ctfpool->head;
+	ctfpool->head = (void *)skb;
+
+	ctfpool->fast_frees++;
+	ctfpool->curr_obj++;
+
+	ASSERT(ctfpool->curr_obj <= ctfpool->max_obj);
+	CTFPOOL_UNLOCK(ctfpool, flags);
+}
+
+#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING
+bool pktfastfree_wrapper(struct sk_buff *skb)
+{
+    int rval = FALSE;
+
+    if (PKTISFAST(NULL, skb)) {
+        osl_pktfastfree(NULL, skb);
+        rval = TRUE;
+    }
+
+    return rval;
+}
+#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */
+
+#endif /* CTFPOOL */
+
+/* Free the driver packet. Free the tag if present */
+void BCMFASTPATH
+osl_pktfree(osl_t *osh, void *p, bool send)
+{
+	struct sk_buff *skb, *nskb;
+
+	skb = (struct sk_buff*) p;
+
+	if (send && osh->pub.tx_fn)
+		osh->pub.tx_fn(osh->pub.tx_ctx, p, 0);
+
+	PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE);
+
+	/* perversion: we use skb->next to chain multi-skb packets */
+	while (skb) {
+		nskb = skb->next;
+		skb->next = NULL;
+
+
+#ifdef CTFMAP
+		/* Clear the map ptr before freeing */
+		PKTCLRCTF(osh, skb);
+		CTFMAPPTR(osh, skb) = NULL;
+#endif /* CTFMAP */
+
+#ifdef CTFPOOL
+		if ((PKTISFAST(osh, skb)) && (atomic_read(&skb->users) == 1))
+			osl_pktfastfree(osh, skb);
+		else {
+#else /* CTFPOOL */
+		{
+#endif /* CTFPOOL */
+
+			if (skb->destructor)
+				/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
+				 * destructor exists
+				 */
+				dev_kfree_skb_any(skb);
+			else
+				/* can free immediately (even in_irq()) if destructor
+				 * does not exist
+				 */
+				dev_kfree_skb(skb);
+		}
+		atomic_dec(&osh->pktalloced);
+		skb = nskb;
+	}
+}
+
+#ifdef DHD_USE_STATIC_BUF
+void*
+osl_pktget_static(osl_t *osh, uint len)
+{
+	int i = 0;
+	struct sk_buff *skb;
+
+	if (len > (PAGE_SIZE*2)) {
+		printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len);
+		return osl_pktget(osh, len);
+	}
+
+	down(&bcm_static_skb->osl_pkt_sem);
+
+	if (len <= PAGE_SIZE) {
+		for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+			if (bcm_static_skb->pkt_use[i] == 0)
+				break;
+		}
+
+		if (i != STATIC_PKT_MAX_NUM) {
+			bcm_static_skb->pkt_use[i] = 1;
+			up(&bcm_static_skb->osl_pkt_sem);
+			skb = bcm_static_skb->skb_4k[i];
+			skb->tail = skb->data + len;
+			skb->len = len;
+			return skb;
+		}
+	}
+
+
+	for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+		if (bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] == 0)
+			break;
+	}
+
+	if (i != STATIC_PKT_MAX_NUM) {
+		bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1;
+		up(&bcm_static_skb->osl_pkt_sem);
+		skb = bcm_static_skb->skb_8k[i];
+		skb->tail = skb->data + len;
+		skb->len = len;
+		return skb;
+	}
+
+	up(&bcm_static_skb->osl_pkt_sem);
+	printk("%s: all static pkt in use!\n", __FUNCTION__);
+	return osl_pktget(osh, len);
+}
+
+void
+osl_pktfree_static(osl_t *osh, void *p, bool send)
+{
+	int i;
+
+	for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+		if (p == bcm_static_skb->skb_4k[i]) {
+			down(&bcm_static_skb->osl_pkt_sem);
+			bcm_static_skb->pkt_use[i] = 0;
+			up(&bcm_static_skb->osl_pkt_sem);
+			return;
+		}
+	}
+
+	for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+		if (p == bcm_static_skb->skb_8k[i]) {
+			down(&bcm_static_skb->osl_pkt_sem);
+			bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0;
+			up(&bcm_static_skb->osl_pkt_sem);
+			return;
+		}
+	}
+
+	return osl_pktfree(osh, p, send);
+}
+#endif /* DHD_USE_STATIC_BUF */
+
+uint32
+osl_pci_read_config(osl_t *osh, uint offset, uint size)
+{
+	uint val = 0;
+	uint retry = PCI_CFG_RETRY;
+
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+	/* only 4byte access supported */
+	ASSERT(size == 4);
+
+	do {
+		pci_read_config_dword(osh->pdev, offset, &val);
+		if (val != 0xffffffff)
+			break;
+	} while (retry--);
+
+#ifdef BCMDBG
+	if (retry < PCI_CFG_RETRY)
+		printk("PCI CONFIG READ access to %d required %d retries\n", offset,
+		       (PCI_CFG_RETRY - retry));
+#endif /* BCMDBG */
+
+	return (val);
+}
+
+void
+osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
+{
+	uint retry = PCI_CFG_RETRY;
+
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+	/* only 4byte access supported */
+	ASSERT(size == 4);
+
+	do {
+		pci_write_config_dword(osh->pdev, offset, val);
+		if (offset != PCI_BAR0_WIN)
+			break;
+		if (osl_pci_read_config(osh, offset, size) == val)
+			break;
+	} while (retry--);
+
+#ifdef BCMDBG
+	if (retry < PCI_CFG_RETRY)
+		printk("PCI CONFIG WRITE access to %d required %d retries\n", offset,
+		       (PCI_CFG_RETRY - retry));
+#endif /* BCMDBG */
+}
+
+/* return bus # for the pci device pointed by osh->pdev */
+uint
+osl_pci_bus(osl_t *osh)
+{
+	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+	return ((struct pci_dev *)osh->pdev)->bus->number;
+}
+
+/* return slot # for the pci device pointed by osh->pdev */
+uint
+osl_pci_slot(osl_t *osh)
+{
+	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+	return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);
+}
+
+/* return the pci device pointed by osh->pdev */
+struct pci_dev *
+osl_pci_device(osl_t *osh)
+{
+	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+	return osh->pdev;
+}
+
+static void
+osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write)
+{
+}
+
+void
+osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size)
+{
+	osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE);
+}
+
+void
+osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size)
+{
+	osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE);
+}
+
+void *
+osl_malloc(osl_t *osh, uint size)
+{
+	void *addr;
+
+	/* only ASSERT if osh is defined */
+	if (osh)
+		ASSERT(osh->magic == OS_HANDLE_MAGIC);
+
+#ifdef DHD_USE_STATIC_BUF
+	if (bcm_static_buf)
+	{
+		int i = 0;
+		if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE))
+		{
+			down(&bcm_static_buf->static_sem);
+
+			for (i = 0; i < STATIC_BUF_MAX_NUM; i++)
+			{
+				if (bcm_static_buf->buf_use[i] == 0)
+					break;
+			}
+
+			if (i == STATIC_BUF_MAX_NUM)
+			{
+				up(&bcm_static_buf->static_sem);
+				printk("all static buff in use!\n");
+				goto original;
+			}
+
+			bcm_static_buf->buf_use[i] = 1;
+			up(&bcm_static_buf->static_sem);
+
+			bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size);
+			if (osh)
+				atomic_add(size, &osh->malloced);
+
+			return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i));
+		}
+	}
+original:
+#endif /* DHD_USE_STATIC_BUF */
+
+	if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
+		if (osh)
+			osh->failed++;
+		return (NULL);
+	}
+	if (osh)
+		atomic_add(size, &osh->malloced);
+
+	return (addr);
+}
+
+void
+osl_mfree(osl_t *osh, void *addr, uint size)
+{
+#ifdef DHD_USE_STATIC_BUF
+	if (bcm_static_buf)
+	{
+		if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr
+			<= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN)))
+		{
+			int buf_idx = 0;
+
+			buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE;
+
+			down(&bcm_static_buf->static_sem);
+			bcm_static_buf->buf_use[buf_idx] = 0;
+			up(&bcm_static_buf->static_sem);
+
+			if (osh) {
+				ASSERT(osh->magic == OS_HANDLE_MAGIC);
+				atomic_sub(size, &osh->malloced);
+			}
+			return;
+		}
+	}
+#endif /* DHD_USE_STATIC_BUF */
+	if (osh) {
+		ASSERT(osh->magic == OS_HANDLE_MAGIC);
+		atomic_sub(size, &osh->malloced);
+	}
+	kfree(addr);
+}
+
+uint
+osl_malloced(osl_t *osh)
+{
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+	return (atomic_read(&osh->malloced));
+}
+
+uint
+osl_malloc_failed(osl_t *osh)
+{
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+	return (osh->failed);
+}
+
+
+uint
+osl_dma_consistent_align(void)
+{
+	return (PAGE_SIZE);
+}
+
+void*
+osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap)
+{
+#ifdef CONFIG_BCM_IPROC_GMAC_ACP
+	void *va;
+	uint16 align = (1 << align_bits);
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+	if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
+		size += align;
+	*alloced = size;
+
+	va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO);
+	if (va)
+		*pap = (ulong)__virt_to_phys((ulong)va);
+	return va;
+
+#else
+	void *ret;
+//	int gfp = GFP_KERNEL; //GFP_ATOMIC | GFP_DMA;
+	/* platform device reference */
+	struct platform_device *pdev;
+
+	uint16 align = (1 << align_bits);
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+	if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
+		size += align;
+	*alloced = size;
+
+//	ret = (void *)__get_free_pages(gfp, get_order(size));
+//	if (ret != NULL) {
+//		memset(ret, 0, size);
+//		*pap = virt_to_phys(ret);
+//	}
+	pdev = (struct platform_device *)osh->pdev;
+	ret = dma_alloc_coherent(&pdev->dev, size, (dma_addr_t*)pap, GFP_KERNEL);
+	return ret;
+
+#endif /* CONFIG_BCM_IPROC_GMAC_ACP */
+}
+
+void
+osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa)
+{
+#ifdef CONFIG_BCM_IPROC_GMAC_ACP
+	kfree(va);
+#else
+	/* platform device reference */
+	struct platform_device *pdev;
+
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+//	free_pages((unsigned long)va, get_order(size));
+	pdev = (struct platform_device *)osh->pdev;
+	dma_free_coherent(&pdev->dev, size, va, (dma_addr_t)pa);
+#endif /* CONFIG_BCM_IPROC_GMAC_ACP */
+}
+
+uint BCMFASTPATH
+osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah)
+{
+	int dir;
+	/* platform device reference */
+	struct platform_device *pdev;
+
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+	pdev = (struct platform_device *)osh->pdev;
+	dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE;
+
+#if defined(BCMDMASGLISTOSL)
+	if (dmah != NULL) {
+		int32 nsegs, i, totsegs = 0, totlen = 0;
+		struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2];
+		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) && (totsegs + nsegs <= MAX_DMA_SEGS));
+  #ifndef CONFIG_BCM_IPROC_GMAC_ACP
+				dma_map_sg(&pdev->dev, sg, nsegs, dir);
+  #endif /* CONFIG_BCM_IPROC_GMAC_ACP */
+			} else {
+				nsegs = 1;
+				ASSERT(totsegs + nsegs <= MAX_DMA_SEGS);
+				sg->page_link = 0;
+				sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb));
+  #ifndef CONFIG_BCM_IPROC_GMAC_ACP
+				dma_map_single(&pdev->dev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir);
+  #endif /* CONFIG_BCM_IPROC_GMAC_ACP */
+			}
+			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;
+		}
+  #ifdef CONFIG_BCM_IPROC_GMAC_ACP
+       return virt_to_phys(va);
+  #else
+		return dmah->segs[0].addr;
+  #endif /* CONFIG_BCM_IPROC_GMAC_ACP */
+	}
+#endif /* defined(BCMDMASGLISTOSL) */
+
+#ifdef CONFIG_BCM_IPROC_GMAC_ACP
+	return virt_to_phys(va);
+#else
+	return dma_map_single(&pdev->dev, va, size, dir);
+#endif /* CONFIG_BCM_IPROC_GMAC_ACP */
+}
+
+void BCMFASTPATH
+osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction)
+{
+#ifndef CONFIG_BCM_IPROC_GMAC_ACP
+	int dir;
+	/* platform device reference */
+	struct platform_device *pdev;
+
+	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+	pdev = (struct platform_device *)osh->pdev;
+	dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE;
+	dma_unmap_single(&pdev->dev, (uint32)pa, size, dir);
+#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */
+}
+
+
+void
+osl_delay(uint usec)
+{
+	uint d;
+
+	while (usec > 0) {
+		d = MIN(usec, 1000);
+		udelay(d);
+		usec -= d;
+	}
+}
+
+#if defined(DSLCPE_DELAY)
+
+void
+osl_oshsh_init(osl_t *osh, shared_osl_t* oshsh)
+{
+	extern unsigned long loops_per_jiffy;
+	osh->oshsh = oshsh;
+	osh->oshsh->MIPS = loops_per_jiffy / (500000/HZ);
+}
+
+int
+in_long_delay(osl_t *osh)
+{
+	return osh->oshsh->long_delay;
+}
+
+void
+osl_long_delay(osl_t *osh, uint usec, bool yield)
+{
+	uint d;
+	bool yielded = TRUE;
+	int usec_to_delay = usec;
+	unsigned long tick1, tick2, tick_diff = 0;
+
+	/* delay at least requested usec */
+	while (usec_to_delay > 0) {
+		if (!yield || !yielded) {
+			d = MIN(usec_to_delay, 10);
+			udelay(d);
+			usec_to_delay -= d;
+		}
+		if (usec_to_delay > 0) {
+			osh->oshsh->long_delay++;
+			OSL_GETCYCLES(tick1);
+			spin_unlock_bh(osh->oshsh->lock);
+			if (usec_to_delay > 0 && !in_irq() && !in_softirq() && !in_interrupt()) {
+				schedule();
+				yielded = TRUE;
+			} else {
+				yielded = FALSE;
+			}
+			spin_lock_bh(osh->oshsh->lock);
+			OSL_GETCYCLES(tick2);
+
+			if (yielded) {
+				tick_diff = TICKDIFF(tick2, tick1);
+				tick_diff = (tick_diff * 2)/(osh->oshsh->MIPS);
+				if (tick_diff) {
+					usec_to_delay -= tick_diff;
+				} else
+					yielded = 0;
+			}
+			osh->oshsh->long_delay--;
+			ASSERT(osh->oshsh->long_delay >= 0);
+		}
+	}
+}
+#endif /* DSLCPE_DELAY */
+
+/* Clone a packet.
+ * The pkttag contents are NOT cloned.
+ */
+void *
+osl_pktdup(osl_t *osh, void *skb)
+{
+	void * p;
+
+	/* clear the CTFBUF flag if set and map the rest of the buffer
+	 * before cloning.
+	 */
+	PKTCTFMAP(osh, skb);
+
+	if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL)
+		return NULL;
+
+#ifdef CTFPOOL
+	if (PKTISFAST(osh, skb)) {
+		ctfpool_t *ctfpool;
+
+		/* if the buffer allocated from ctfpool is cloned then
+		 * we can't be sure when it will be freed. since there
+		 * is a chance that we will be losing a buffer
+		 * from our pool, we increment the refill count for the
+		 * object to be alloced later.
+		 */
+		ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb);
+		ASSERT(ctfpool != NULL);
+		PKTCLRFAST(osh, p);
+		PKTCLRFAST(osh, skb);
+		ctfpool->refills++;
+	}
+#endif /* CTFPOOL */
+
+	/* skb_clone copies skb->cb.. we don't want that */
+	if (osh->pub.pkttag)
+		OSL_PKTTAG_CLEAR(p);
+
+	/* Increment the packet counter */
+	atomic_inc(&osh->pktalloced);
+	return (p);
+}
+
+
+/*
+ * OSLREGOPS specifies the use of osl_XXX routines to be used for register access
+ */
+#ifdef OSLREGOPS
+uint8
+osl_readb(osl_t *osh, volatile uint8 *r)
+{
+	osl_rreg_fn_t rreg	= ((osl_pubinfo_t*)osh)->rreg_fn;
+	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
+
+	return (uint8)((rreg)(ctx, (void*)r, sizeof(uint8)));
+}
+
+
+uint16
+osl_readw(osl_t *osh, volatile uint16 *r)
+{
+	osl_rreg_fn_t rreg	= ((osl_pubinfo_t*)osh)->rreg_fn;
+	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
+
+	return (uint16)((rreg)(ctx, (void*)r, sizeof(uint16)));
+}
+
+uint32
+osl_readl(osl_t *osh, volatile uint32 *r)
+{
+	osl_rreg_fn_t rreg	= ((osl_pubinfo_t*)osh)->rreg_fn;
+	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
+
+	return (uint32)((rreg)(ctx, (void*)r, sizeof(uint32)));
+}
+
+void
+osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v)
+{
+	osl_wreg_fn_t wreg	= ((osl_pubinfo_t*)osh)->wreg_fn;
+	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
+
+	((wreg)(ctx, (void*)r, v, sizeof(uint8)));
+}
+
+
+void
+osl_writew(osl_t *osh, volatile uint16 *r, uint16 v)
+{
+	osl_wreg_fn_t wreg	= ((osl_pubinfo_t*)osh)->wreg_fn;
+	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
+
+	((wreg)(ctx, (void*)r, v, sizeof(uint16)));
+}
+
+void
+osl_writel(osl_t *osh, volatile uint32 *r, uint32 v)
+{
+	osl_wreg_fn_t wreg	= ((osl_pubinfo_t*)osh)->wreg_fn;
+	void *ctx		= ((osl_pubinfo_t*)osh)->reg_ctx;
+
+	((wreg)(ctx, (void*)r, v, sizeof(uint32)));
+}
+#endif /* OSLREGOPS */
+
+/*
+ * BINOSL selects the slightly slower function-call-based binary compatible osl.
+ */
+#ifdef BINOSL
+
+uint32
+osl_sysuptime(void)
+{
+	return ((uint32)jiffies * (1000 / HZ));
+}
+
+int
+osl_printf(const char *format, ...)
+{
+	va_list args;
+	static char printbuf[1024];
+	int len;
+
+	/* sprintf into a local buffer because there *is* no "vprintk()".. */
+	va_start(args, format);
+	len = vsnprintf(printbuf, 1024, format, args);
+	va_end(args);
+
+	if (len > sizeof(printbuf)) {
+		printk("osl_printf: buffer overrun\n");
+		return (0);
+	}
+
+	return (printk("%s", printbuf));
+}
+
+int
+osl_sprintf(char *buf, const char *format, ...)
+{
+	va_list args;
+	int rc;
+
+	va_start(args, format);
+	rc = vsprintf(buf, format, args);
+	va_end(args);
+	return (rc);
+}
+
+int
+osl_snprintf(char *buf, size_t n, const char *format, ...)
+{
+	va_list args;
+	int rc;
+
+	va_start(args, format);
+	rc = vsnprintf(buf, n, format, args);
+	va_end(args);
+	return (rc);
+}
+
+int
+osl_vsprintf(char *buf, const char *format, va_list ap)
+{
+	return (vsprintf(buf, format, ap));
+}
+
+int
+osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap)
+{
+	return (vsnprintf(buf, n, format, ap));
+}
+
+int
+osl_strcmp(const char *s1, const char *s2)
+{
+	return (strcmp(s1, s2));
+}
+
+int
+osl_strncmp(const char *s1, const char *s2, uint n)
+{
+	return (strncmp(s1, s2, n));
+}
+
+int
+osl_strlen(const char *s)
+{
+	return (strlen(s));
+}
+
+char*
+osl_strcpy(char *d, const char *s)
+{
+	return (strcpy(d, s));
+}
+
+char*
+osl_strncpy(char *d, const char *s, uint n)
+{
+	return (strncpy(d, s, n));
+}
+
+char*
+osl_strchr(const char *s, int c)
+{
+	return (strchr(s, c));
+}
+
+char*
+osl_strrchr(const char *s, int c)
+{
+	return (strrchr(s, c));
+}
+
+void*
+osl_memset(void *d, int c, size_t n)
+{
+	return memset(d, c, n);
+}
+
+void*
+osl_memcpy(void *d, const void *s, size_t n)
+{
+	return memcpy(d, s, n);
+}
+
+void*
+osl_memmove(void *d, const void *s, size_t n)
+{
+	return memmove(d, s, n);
+}
+
+int
+osl_memcmp(const void *s1, const void *s2, size_t n)
+{
+	return memcmp(s1, s2, n);
+}
+
+uint32
+osl_readl(volatile uint32 *r)
+{
+	return (readl(r));
+}
+
+uint16
+osl_readw(volatile uint16 *r)
+{
+	return (readw(r));
+}
+
+uint8
+osl_readb(volatile uint8 *r)
+{
+	return (readb(r));
+}
+
+void
+osl_writel(uint32 v, volatile uint32 *r)
+{
+	writel(v, r);
+}
+
+void
+osl_writew(uint16 v, volatile uint16 *r)
+{
+	writew(v, r);
+}
+
+void
+osl_writeb(uint8 v, volatile uint8 *r)
+{
+	writeb(v, r);
+}
+
+void *
+osl_uncached(void *va)
+{
+#ifdef mips
+	return ((void*)KSEG1ADDR(va));
+#else
+	return ((void*)va);
+#endif /* mips */
+}
+
+void *
+osl_cached(void *va)
+{
+#ifdef mips
+	return ((void*)KSEG0ADDR(va));
+#else
+	return ((void*)va);
+#endif /* mips */
+}
+
+uint
+osl_getcycles(void)
+{
+	uint cycles;
+
+#if defined(mips)
+	cycles = read_c0_count() * 2;
+#elif defined(__i386__)
+	rdtscl(cycles);
+#else
+	cycles = 0;
+#endif /* defined(mips) */
+	return cycles;
+}
+
+void *
+osl_reg_map(uint32 pa, uint size)
+{
+	return (ioremap_nocache((unsigned long)pa, (unsigned long)size));
+}
+
+void
+osl_reg_unmap(void *va)
+{
+	iounmap(va);
+}
+
+int
+osl_busprobe(uint32 *val, uint32 addr)
+{
+#ifdef mips
+	return get_dbe(*val, (uint32 *)addr);
+#else
+	*val = readl((uint32 *)(uintptr)addr);
+	return 0;
+#endif /* mips */
+}
+
+bool
+osl_pktshared(void *skb)
+{
+	return (((struct sk_buff*)skb)->cloned);
+}
+
+uchar*
+osl_pktdata(osl_t *osh, void *skb)
+{
+	return (((struct sk_buff*)skb)->data);
+}
+
+uint
+osl_pktlen(osl_t *osh, void *skb)
+{
+	return (((struct sk_buff*)skb)->len);
+}
+
+uint
+osl_pktheadroom(osl_t *osh, void *skb)
+{
+	return (uint) skb_headroom((struct sk_buff *) skb);
+}
+
+uint
+osl_pkttailroom(osl_t *osh, void *skb)
+{
+	return (uint) skb_tailroom((struct sk_buff *) skb);
+}
+
+void*
+osl_pktnext(osl_t *osh, void *skb)
+{
+	return (((struct sk_buff*)skb)->next);
+}
+
+void
+osl_pktsetnext(void *skb, void *x)
+{
+	((struct sk_buff*)skb)->next = (struct sk_buff*)x;
+}
+
+void
+osl_pktsetlen(osl_t *osh, void *skb, uint len)
+{
+	__pskb_trim((struct sk_buff*)skb, len);
+}
+
+uchar*
+osl_pktpush(osl_t *osh, void *skb, int bytes)
+{
+	return (skb_push((struct sk_buff*)skb, bytes));
+}
+
+uchar*
+osl_pktpull(osl_t *osh, void *skb, int bytes)
+{
+	return (skb_pull((struct sk_buff*)skb, bytes));
+}
+
+void*
+osl_pkttag(void *skb)
+{
+	return ((void*)(((struct sk_buff*)skb)->cb));
+}
+
+void*
+osl_pktlink(void *skb)
+{
+	return (((struct sk_buff*)skb)->prev);
+}
+
+void
+osl_pktsetlink(void *skb, void *x)
+{
+	((struct sk_buff*)skb)->prev = (struct sk_buff*)x;
+}
+
+uint
+osl_pktprio(void *skb)
+{
+	return (((struct sk_buff*)skb)->priority);
+}
+
+void
+osl_pktsetprio(void *skb, uint x)
+{
+	((struct sk_buff*)skb)->priority = x;
+}
+#endif	/* BINOSL */
+
+uint
+osl_pktalloced(osl_t *osh)
+{
+	return (atomic_read(&osh->pktalloced));
+}
+
+/* Linux Kernel: File Operations: start */
+void *
+osl_os_open_image(char *filename)
+{
+	struct file *fp;
+
+	fp = filp_open(filename, O_RDONLY, 0);
+	/*
+	 * 2.6.11 (FC4) supports filp_open() but later revs don't?
+	 * Alternative:
+	 * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
+	 * ???
+	 */
+	 if (IS_ERR(fp))
+		 fp = NULL;
+
+	 return fp;
+}
+
+int
+osl_os_get_image_block(char *buf, int len, void *image)
+{
+	struct file *fp = (struct file *)image;
+	int rdlen;
+
+	if (!image)
+		return 0;
+
+	rdlen = kernel_read(fp, fp->f_pos, buf, len);
+	if (rdlen > 0)
+		fp->f_pos += rdlen;
+
+	return rdlen;
+}
+
+void
+osl_os_close_image(void *image)
+{
+	if (image)
+		filp_close((struct file *)image, NULL);
+}
+/* Linux Kernel: File Operations: end */
diff --git a/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c
new file mode 100755
index 0000000..9ad67a0
