/*
* Linux OS Independent Layer
*
- * $Copyright Open Broadcom Corporation$
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * 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 503131 2014-09-17 12:16:08Z $
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * $Id: linux_osl.c 602478 2015-11-26 04:46:12Z $
*/
#define LINUX_PORT
#include <linuxver.h>
#include <bcmdefs.h>
-#if defined(BCM47XX_CA9) && defined(__ARM_ARCH_7A__)
+
+#if !defined(STBLINUX)
+#if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)
#include <asm/cacheflush.h>
-#endif /* BCM47XX_CA9 && __ARM_ARCH_7A__ */
+#endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
+#endif /* STBLINUX */
#include <linux/random.h>
#include <pcicfg.h>
-
#ifdef BCM_SECURE_DMA
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
-#ifdef BCM47XX_ACP_WAR
-#include <linux/spinlock.h>
-extern spinlock_t l2x0_reg_lock;
-#endif
-#if defined(BCMPCIE)
-#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_FLOWRING)
-#include <bcmpcie.h>
-#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_FLOWRING */
-#endif /* BCMPCIE */
+#ifdef BCM_OBJECT_TRACE
+#include <bcmutils.h>
+#endif /* BCM_OBJECT_TRACE */
#define PCI_CFG_RETRY 10
#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */
#define DUMPBUFSZ 1024
+/* dependancy check */
+#if !defined(BCMPCIE) && defined(DHD_USE_STATIC_CTRLBUF)
+#error "DHD_USE_STATIC_CTRLBUF suppored PCIE target only"
+#endif /* !BCMPCIE && DHD_USE_STATIC_CTRLBUF */
+
#ifdef CONFIG_DHD_USE_STATIC_BUF
+#ifdef DHD_USE_STATIC_CTRLBUF
+#define DHD_SKB_1PAGE_BUFSIZE (PAGE_SIZE*1)
+#define DHD_SKB_2PAGE_BUFSIZE (PAGE_SIZE*2)
+#define DHD_SKB_4PAGE_BUFSIZE (PAGE_SIZE*4)
+
+#define PREALLOC_FREE_MAGIC 0xFEDC
+#define PREALLOC_USED_MAGIC 0xFCDE
+#else
#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)
+#endif /* DHD_USE_STATIC_CTRLBUF */
#define STATIC_BUF_MAX_NUM 16
#define STATIC_BUF_SIZE (PAGE_SIZE*2)
static bcm_static_buf_t *bcm_static_buf = 0;
-#define STATIC_PKT_MAX_NUM 8
-#if defined(ENHANCED_STATIC_BUF)
+#ifdef DHD_USE_STATIC_CTRLBUF
+#define STATIC_PKT_4PAGE_NUM 0
+#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE
+#elif defined(ENHANCED_STATIC_BUF)
#define STATIC_PKT_4PAGE_NUM 1
#define DHD_SKB_MAX_BUFSIZE DHD_SKB_4PAGE_BUFSIZE
#else
#define STATIC_PKT_4PAGE_NUM 0
-#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE
-#endif /* ENHANCED_STATIC_BUF */
+#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE
+#endif /* DHD_USE_STATIC_CTRLBUF */
+
+#ifdef DHD_USE_STATIC_CTRLBUF
+#define STATIC_PKT_1PAGE_NUM 0
+#define STATIC_PKT_2PAGE_NUM 64
+#else
+#define STATIC_PKT_1PAGE_NUM 8
+#define STATIC_PKT_2PAGE_NUM 8
+#endif /* DHD_USE_STATIC_CTRLBUF */
+
+#define STATIC_PKT_1_2PAGE_NUM \
+ ((STATIC_PKT_1PAGE_NUM) + (STATIC_PKT_2PAGE_NUM))
+#define STATIC_PKT_MAX_NUM \
+ ((STATIC_PKT_1_2PAGE_NUM) + (STATIC_PKT_4PAGE_NUM))
typedef struct bcm_static_pkt {
- struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM];
- struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM];
+#ifdef DHD_USE_STATIC_CTRLBUF
+ struct sk_buff *skb_8k[STATIC_PKT_2PAGE_NUM];
+ unsigned char pkt_invalid[STATIC_PKT_2PAGE_NUM];
+ spinlock_t osl_pkt_lock;
+ uint32 last_allocated_index;
+#else
+ struct sk_buff *skb_4k[STATIC_PKT_1PAGE_NUM];
+ struct sk_buff *skb_8k[STATIC_PKT_2PAGE_NUM];
#ifdef ENHANCED_STATIC_BUF
struct sk_buff *skb_16k;
-#endif
+#endif /* ENHANCED_STATIC_BUF */
struct semaphore osl_pkt_sem;
- unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM];
+#endif /* DHD_USE_STATIC_CTRLBUF */
+ unsigned char pkt_use[STATIC_PKT_MAX_NUM];
} bcm_static_pkt_t;
static bcm_static_pkt_t *bcm_static_skb = 0;
-#if defined(BCMPCIE) && defined(DHD_USE_STATIC_FLOWRING)
-#define STATIC_BUF_FLOWRING_SIZE ((PAGE_SIZE)*(7))
-#define STATIC_BUF_FLOWRING_NUM 42
-#define RINGID_TO_FLOWID(idx) ((idx) + (BCMPCIE_H2D_COMMON_MSGRINGS) \
- - (BCMPCIE_H2D_TXFLOWRINGID))
-typedef struct bcm_static_flowring_buf {
- spinlock_t flowring_lock;
- void *buf_ptr[STATIC_BUF_FLOWRING_NUM];
- unsigned char buf_use[STATIC_BUF_FLOWRING_NUM];
-} bcm_static_flowring_buf_t;
-
-bcm_static_flowring_buf_t *bcm_static_flowring = 0;
-#endif /* BCMPCIE && DHD_USE_STATIC_FLOWRING */
-
void* wifi_platform_prealloc(void *adapter, int section, unsigned long size);
#endif /* CONFIG_DHD_USE_STATIC_BUF */
struct osl_info {
osl_pubinfo_t pub;
+ uint32 flags; /* If specific cases to be handled in the OSL */
#ifdef CTFPOOL
ctfpool_t *ctfpool;
#endif /* CTFPOOL */
struct list_head ctrace_list;
int ctrace_num;
#endif /* BCMDBG_CTRACE */
- uint32 flags; /* If specific cases to be handled in the OSL */
#ifdef BCM_SECURE_DMA
struct cma_dev *cma;
struct sec_mem_elem *sec_list_512;
} sec_cma_coherent[SEC_CMA_COHERENT_MAX];
#endif /* BCM_SECURE_DMA */
-
};
#ifdef BCM_SECURE_DMA
phys_addr_t g_contig_delta_va_pa;
static void osl_sec_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa);
#endif /* BCM_SECURE_DMA */
+#ifdef BCM_OBJECT_TRACE
+/* don't clear the first 4 byte that is the pkt sn */
+#define OSL_PKTTAG_CLEAR(p) \
+do { \
+ struct sk_buff *s = (struct sk_buff *)(p); \
+ ASSERT(OSL_PKTTAG_SZ == 32); \
+ *(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)
+#else
#define OSL_PKTTAG_CLEAR(p) \
do { \
struct sk_buff *s = (struct sk_buff *)(p); \
*(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
*(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
} while (0)
+#endif /* BCM_OBJECT_TRACE */
/* PCMCIA attribute space access macros */
/* Global ASSERT type flag */
-uint32 g_assert_type = 0;
+uint32 g_assert_type = 1;
module_param(g_assert_type, int, 0);
static int16 linuxbcmerrormap[] =
-EIO, /* BCME_MICERR */
-ERANGE, /* BCME_REPLAY */
-EINVAL, /* BCME_IE_NOTFOUND */
+ -EINVAL, /* BCME_DATA_NOTFOUND */
/* 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 != -52
+#if BCME_LAST != -53
#error "You need to add a OS error translation in the linuxbcmerrormap \
for new error code defined in bcmutils.h"
#endif
};
-
-#if 1
-static inline void *
-pci_alloc_consistent1(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle)
-{
- return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC);
-}
-
-static inline dma_addr_t
-pci_map_single1(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
-{
- return dma_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_free_consistent1(struct pci_dev *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, vaddr, dma_handle);
-}
-
-static inline void
-pci_unmap_single1(struct pci_dev *hwdev, dma_addr_t dma_addr,
- size_t size, int direction)
-{
- dma_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
-}
-#endif
+uint lmtest = FALSE;
/* translate bcmerrors into linux errors */
int
}
atomic_add(1, &osh->cmn->refcount);
+ bcm_object_trace_init();
+
/* Check that error map has the right number of entries in it */
ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
osl_sec_dma_setup_contig_mem(osh, CMA_MEMBLOCK, CONT_ARMREGION);
-#ifdef BCM47XX_CA9
- osh->contig_base_alloc_coherent_va = osl_sec_dma_ioremap(osh,
- phys_to_page((u32)osh->contig_base_alloc),
- CMA_DMA_DESC_MEMBLOCK, TRUE, TRUE);
-#else
osh->contig_base_alloc_coherent_va = osl_sec_dma_ioremap(osh,
phys_to_page((u32)osh->contig_base_alloc),
CMA_DMA_DESC_MEMBLOCK, FALSE, TRUE);
-#endif /* BCM47XX_CA9 */
osh->contig_base_alloc_coherent = osh->contig_base_alloc;
osl_sec_dma_init_consistent(osh);
int osl_static_mem_init(osl_t *osh, void *adapter)
{
#ifdef CONFIG_DHD_USE_STATIC_BUF
- if (!bcm_static_buf && adapter) {
- if (!(bcm_static_buf = (bcm_static_buf_t *)wifi_platform_prealloc(adapter,
- 3, STATIC_BUF_SIZE + STATIC_BUF_TOTAL_LEN))) {
- printk("can not alloc static buf!\n");
- bcm_static_skb = NULL;
- ASSERT(osh->magic == OS_HANDLE_MAGIC);
- return -ENOMEM;
- }
- else
- printk("alloc static buf at %p!\n", bcm_static_buf);
-
-
- sema_init(&bcm_static_buf->static_sem, 1);
+ if (!bcm_static_buf && adapter) {
+ if (!(bcm_static_buf = (bcm_static_buf_t *)wifi_platform_prealloc(adapter,
+ 3, STATIC_BUF_SIZE + STATIC_BUF_TOTAL_LEN))) {
+ printk("can not alloc static buf!\n");
+ bcm_static_skb = NULL;
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ return -ENOMEM;
+ } else {
+ printk("alloc static buf at %p!\n", bcm_static_buf);
+ }
- bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE;
- }
+ sema_init(&bcm_static_buf->static_sem, 1);
-#ifdef BCMSDIO
- if (!bcm_static_skb && adapter) {
- int i;
- void *skb_buff_ptr = 0;
- bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048);
- skb_buff_ptr = wifi_platform_prealloc(adapter, 4, 0);
- if (!skb_buff_ptr) {
- printk("cannot alloc static buf!\n");
- bcm_static_buf = NULL;
- bcm_static_skb = NULL;
- ASSERT(osh->magic == OS_HANDLE_MAGIC);
- return -ENOMEM;
+ bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE;
}
- 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++)
- bcm_static_skb->pkt_use[i] = 0;
+#if defined(BCMSDIO) || defined(DHD_USE_STATIC_CTRLBUF)
+ if (!bcm_static_skb && adapter) {
+ int i;
+ void *skb_buff_ptr = 0;
+ bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048);
+ skb_buff_ptr = wifi_platform_prealloc(adapter, 4, 0);
+ if (!skb_buff_ptr) {
+ printk("cannot alloc static buf!\n");
+ bcm_static_buf = NULL;
+ bcm_static_skb = NULL;
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ return -ENOMEM;
+ }
- sema_init(&bcm_static_skb->osl_pkt_sem, 1);
- }
-#endif /* BCMSDIO */
-#if defined(BCMPCIE) && defined(DHD_USE_STATIC_FLOWRING)
- if (!bcm_static_flowring && adapter) {
- int i;
- void *flowring_ptr = 0;
- bcm_static_flowring =
- (bcm_static_flowring_buf_t *)((char *)bcm_static_buf + 4096);
- flowring_ptr = wifi_platform_prealloc(adapter, 10, 0);
- if (!flowring_ptr) {
- printk("%s: flowring_ptr is NULL\n", __FUNCTION__);
- bcm_static_buf = NULL;
- bcm_static_skb = NULL;
- bcm_static_flowring = NULL;
- ASSERT(osh->magic == OS_HANDLE_MAGIC);
- return -ENOMEM;
- }
+ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) *
+ (STATIC_PKT_MAX_NUM));
+ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+ bcm_static_skb->pkt_use[i] = 0;
+ }
- bcopy(flowring_ptr, bcm_static_flowring->buf_ptr,
- sizeof(void *) * STATIC_BUF_FLOWRING_NUM);
- for (i = 0; i < STATIC_BUF_FLOWRING_NUM; i++) {
- bcm_static_flowring->buf_use[i] = 0;
+#ifdef DHD_USE_STATIC_CTRLBUF
+ spin_lock_init(&bcm_static_skb->osl_pkt_lock);
+ bcm_static_skb->last_allocated_index = 0;
+#else
+ sema_init(&bcm_static_skb->osl_pkt_sem, 1);
+#endif /* DHD_USE_STATIC_CTRLBUF */
}
-
- spin_lock_init(&bcm_static_flowring->flowring_lock);
- }
-#endif /* BCMPCIE && DHD_USE_STATIC_FLOWRING */
+#endif /* BCMSDIO || DHD_USE_STATIC_CTRLBUF */
#endif /* CONFIG_DHD_USE_STATIC_BUF */
return 0;
{
if (osh == NULL)
return;
+
#ifdef BCM_SECURE_DMA
osl_sec_dma_free_contig_mem(osh, CMA_MEMBLOCK, CONT_ARMREGION);
osl_sec_dma_deinit_elem_mem_block(osh, CMA_BUFSIZE_512, CMA_BUFNUM, osh->sec_list_base_512);
osl_sec_dma_iounmap(osh, osh->contig_base_va, CMA_MEMBLOCK);
#endif /* BCM_SECURE_DMA */
+
+ bcm_object_trace_deinit();
+
ASSERT(osh->magic == OS_HANDLE_MAGIC);
atomic_sub(1, &osh->cmn->refcount);
if (atomic_read(&osh->cmn->refcount) == 0) {
bcm_static_skb = 0;
}
#endif /* BCMSDIO */
-#if defined(BCMPCIE) && defined(DHD_USE_STATIC_FLOWRING)
- if (bcm_static_flowring) {
- bcm_static_flowring = 0;
- }
-#endif /* BCMPCIE && DHD_USE_STATIC_FLOWRING */
#endif /* CONFIG_DHD_USE_STATIC_BUF */
return 0;
}
#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_ZONE_DMA)
flags |= GFP_ATOMIC;
#endif
+#ifdef DHD_USE_ATOMIC_PKTGET
+ flags = GFP_ATOMIC;
+#endif /* DHD_USE_ATOMIC_PKTGET */
skb = __dev_alloc_skb(len, flags);
#else
skb = dev_alloc_skb(len);
bcm_static_skb = 0;
}
#endif /* BCMSDIO */
-#if defined(BCMPCIE) && defined(DHD_USE_STATIC_FLOWRING)
- if (bcm_static_flowring) {
- bcm_static_flowring = 0;
- }
-#endif /* BCMPCIE && DHD_USE_STATIC_FLOWRING */
#endif /* CONFIG_DHD_USE_STATIC_BUF */
bb = b;
#ifdef BCMDBG_CTRACE
osl_pktget(osl_t *osh, uint len, int line, char *file)
#else
+#ifdef BCM_OBJECT_TRACE
+osl_pktget(osl_t *osh, uint len, int line, const char *caller)
+#else
osl_pktget(osl_t *osh, uint len)
+#endif /* BCM_OBJECT_TRACE */
#endif /* BCMDBG_CTRACE */
{
struct sk_buff *skb;
+ uchar num = 0;
+ if (lmtest != FALSE) {
+ get_random_bytes(&num, sizeof(uchar));
+ if ((num + 1) <= (256 * lmtest / 100))
+ return NULL;
+ }
#ifdef CTFPOOL
/* Allocate from local pool */
ADD_CTRACE(osh, skb, file, line);
#endif
atomic_inc(&osh->cmn->pktalloced);
+#ifdef BCM_OBJECT_TRACE
+ bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, caller, line);
+#endif /* BCM_OBJECT_TRACE */
}
return ((void*) skb);
/* Free the driver packet. Free the tag if present */
void BCMFASTPATH
+#ifdef BCM_OBJECT_TRACE
+osl_pktfree(osl_t *osh, void *p, bool send, int line, const char *caller)
+#else
osl_pktfree(osl_t *osh, void *p, bool send)
+#endif /* BCM_OBJECT_TRACE */
{
struct sk_buff *skb, *nskb;
if (osh == NULL)
PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE);
+#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_CTRLBUF)
+ if (skb && (skb->mac_len == PREALLOC_USED_MAGIC)) {
+ printk("%s: pkt %p is from static pool\n",
+ __FUNCTION__, p);
+ dump_stack();
+ return;
+ }
+
+ if (skb && (skb->mac_len == PREALLOC_FREE_MAGIC)) {
+ printk("%s: pkt %p is from static pool and not in used\n",
+ __FUNCTION__, p);
+ dump_stack();
+ return;
+ }
+#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_CTRLBUF */
+
/* perversion: we use skb->next to chain multi-skb packets */
while (skb) {
nskb = skb->next;
#endif
+#ifdef BCM_OBJECT_TRACE
+ bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, caller, line);
+#endif /* BCM_OBJECT_TRACE */
+
#ifdef CTFPOOL
if (PKTISFAST(osh, skb)) {
if (atomic_read(&skb->users) == 1)
{
int i = 0;
struct sk_buff *skb;
+#ifdef DHD_USE_STATIC_CTRLBUF
+ unsigned long flags;
+#endif /* DHD_USE_STATIC_CTRLBUF */
if (!bcm_static_skb)
return osl_pktget(osh, len);
return osl_pktget(osh, len);
}
+#ifdef DHD_USE_STATIC_CTRLBUF
+ spin_lock_irqsave(&bcm_static_skb->osl_pkt_lock, flags);
+
+ if (len <= DHD_SKB_2PAGE_BUFSIZE) {
+ uint32 index;
+ for (i = 0; i < STATIC_PKT_2PAGE_NUM; i++) {
+ index = bcm_static_skb->last_allocated_index % STATIC_PKT_2PAGE_NUM;
+ bcm_static_skb->last_allocated_index++;
+ if (bcm_static_skb->skb_8k[index] &&
+ bcm_static_skb->pkt_use[index] == 0) {
+ break;
+ }
+ }
+
+ if ((i != STATIC_PKT_2PAGE_NUM) &&
+ (index >= 0) && (index < STATIC_PKT_2PAGE_NUM)) {
+ bcm_static_skb->pkt_use[index] = 1;
+ skb = bcm_static_skb->skb_8k[index];
+ skb->data = skb->head;
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+ skb_set_tail_pointer(skb, NET_SKB_PAD);
+#else
+ skb->tail = skb->data + NET_SKB_PAD;
+#endif /* NET_SKBUFF_DATA_USES_OFFSET */
+ skb->data += NET_SKB_PAD;
+ skb->cloned = 0;
+ skb->priority = 0;
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+ skb_set_tail_pointer(skb, len);
+#else
+ skb->tail = skb->data + len;
+#endif /* NET_SKBUFF_DATA_USES_OFFSET */
+ skb->len = len;
+ skb->mac_len = PREALLOC_USED_MAGIC;
+ spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags);
+ return skb;
+ }
+ }
+
+ spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags);
+ printk("%s: all static pkt in use!\n", __FUNCTION__);
+ return NULL;
+#else
down(&bcm_static_skb->osl_pkt_sem);
if (len <= DHD_SKB_1PAGE_BUFSIZE) {
for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
- if (bcm_static_skb->pkt_use[i] == 0)
+ if (bcm_static_skb->skb_4k[i] &&
+ bcm_static_skb->pkt_use[i] == 0) {
break;
+ }
}
if (i != STATIC_PKT_MAX_NUM) {
}
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)
+ for (i = STATIC_PKT_1PAGE_NUM; i < STATIC_PKT_1_2PAGE_NUM; i++) {
+ if (bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM] &&
+ bcm_static_skb->pkt_use[i] == 0) {
break;
+ }
}
- if (i != STATIC_PKT_MAX_NUM) {
- bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 1;
- skb = bcm_static_skb->skb_8k[i];
+ if ((i >= STATIC_PKT_1PAGE_NUM) && (i < STATIC_PKT_1_2PAGE_NUM)) {
+ bcm_static_skb->pkt_use[i] = 1;
+ skb = bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM];
#ifdef NET_SKBUFF_DATA_USES_OFFSET
skb_set_tail_pointer(skb, len);
#else
}
#if defined(ENHANCED_STATIC_BUF)
- if (bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] == 0) {
- bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] = 1;
+ if (bcm_static_skb->skb_16k &&
+ bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] == 0) {
+ bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] = 1;
skb = bcm_static_skb->skb_16k;
#ifdef NET_SKBUFF_DATA_USES_OFFSET
up(&bcm_static_skb->osl_pkt_sem);
printk("%s: all static pkt in use!\n", __FUNCTION__);
return osl_pktget(osh, len);
+#endif /* DHD_USE_STATIC_CTRLBUF */
}
void
osl_pktfree_static(osl_t *osh, void *p, bool send)
{
int i;
+#ifdef DHD_USE_STATIC_CTRLBUF
+ struct sk_buff *skb = (struct sk_buff *)p;
+ unsigned long flags;
+#endif /* DHD_USE_STATIC_CTRLBUF */
+
+ if (!p) {
+ return;
+ }
+
if (!bcm_static_skb) {
osl_pktfree(osh, p, send);
return;
}
+#ifdef DHD_USE_STATIC_CTRLBUF
+ spin_lock_irqsave(&bcm_static_skb->osl_pkt_lock, flags);
+
+ for (i = 0; i < STATIC_PKT_2PAGE_NUM; i++) {
+ if (p == bcm_static_skb->skb_8k[i]) {
+ if (bcm_static_skb->pkt_use[i] == 0) {
+ printk("%s: static pkt idx %d(%p) is double free\n",
+ __FUNCTION__, i, p);
+ } else {
+ bcm_static_skb->pkt_use[i] = 0;
+ }
+
+ if (skb->mac_len != PREALLOC_USED_MAGIC) {
+ printk("%s: static pkt idx %d(%p) is not in used\n",
+ __FUNCTION__, i, p);
+ }
+
+ skb->mac_len = PREALLOC_FREE_MAGIC;
+ spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags);
+ return;
+ }
+ }
+
+ spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags);
+ printk("%s: packet %p does not exist in the pool\n", __FUNCTION__, p);
+#else
down(&bcm_static_skb->osl_pkt_sem);
- for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
+ for (i = 0; i < STATIC_PKT_1PAGE_NUM; i++) {
if (p == bcm_static_skb->skb_4k[i]) {
bcm_static_skb->pkt_use[i] = 0;
up(&bcm_static_skb->osl_pkt_sem);
}
}
- for (i = 0; i < STATIC_PKT_MAX_NUM; i++) {
- if (p == bcm_static_skb->skb_8k[i]) {
- bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0;
+ for (i = STATIC_PKT_1PAGE_NUM; i < STATIC_PKT_1_2PAGE_NUM; i++) {
+ if (p == bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM]) {
+ bcm_static_skb->pkt_use[i] = 0;
up(&bcm_static_skb->osl_pkt_sem);
return;
}
}
#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 - 1] = 0;
up(&bcm_static_skb->osl_pkt_sem);
return;
}
#endif
up(&bcm_static_skb->osl_pkt_sem);
osl_pktfree(osh, p, send);
+#endif /* DHD_USE_STATIC_CTRLBUF */
}
-
-#if defined(BCMPCIE) && defined(DHD_USE_STATIC_FLOWRING)
-void*
-osl_dma_alloc_consistent_static(osl_t *osh, uint size, uint16 align_bits,
- uint *alloced, dmaaddr_t *pap, uint16 idx)
-{
- void *va = NULL;
- uint16 align = (1 << align_bits);
- uint16 flow_id = RINGID_TO_FLOWID(idx);
- unsigned long flags;
-
- ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
- if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
- size += align;
-
- if ((flow_id < 0) || (flow_id >= STATIC_BUF_FLOWRING_NUM)) {
- printk("%s: flow_id %d is wrong\n", __FUNCTION__, flow_id);
- return osl_dma_alloc_consistent(osh, size, align_bits,
- alloced, pap);
- }
-
- if (!bcm_static_flowring) {
- printk("%s: bcm_static_flowring is not initialized\n",
- __FUNCTION__);
- return osl_dma_alloc_consistent(osh, size, align_bits,
- alloced, pap);
- }
-
- if (size > STATIC_BUF_FLOWRING_SIZE) {
- printk("%s: attempt to allocate huge packet, size=%d\n",
- __FUNCTION__, size);
- return osl_dma_alloc_consistent(osh, size, align_bits,
- alloced, pap);
- }
-
- *alloced = size;
-
- spin_lock_irqsave(&bcm_static_flowring->flowring_lock, flags);
- if (bcm_static_flowring->buf_use[flow_id]) {
- printk("%s: flowring %d is already alloced\n",
- __FUNCTION__, flow_id);
- spin_unlock_irqrestore(&bcm_static_flowring->flowring_lock, flags);
- return NULL;
- }
-
- va = bcm_static_flowring->buf_ptr[flow_id];
- if (va) {
- *pap = (ulong)__virt_to_phys((ulong)va);
- bcm_static_flowring->buf_use[flow_id] = 1;
- }
- spin_unlock_irqrestore(&bcm_static_flowring->flowring_lock, flags);
-
- return va;
-}
-
-void
-osl_dma_free_consistent_static(osl_t *osh, void *va, uint size,
- dmaaddr_t pa, uint16 idx)
-{
- uint16 flow_id = RINGID_TO_FLOWID(idx);
- unsigned long flags;
-
- ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
- if ((flow_id < 0) || (flow_id >= STATIC_BUF_FLOWRING_NUM)) {
- printk("%s: flow_id %d is wrong\n", __FUNCTION__, flow_id);
- return osl_dma_free_consistent(osh, va, size, pa);
- }
-
- if (!bcm_static_flowring) {
- printk("%s: bcm_static_flowring is not initialized\n",
- __FUNCTION__);
- return osl_dma_free_consistent(osh, va, size, pa);
- }
-
- spin_lock_irqsave(&bcm_static_flowring->flowring_lock, flags);
- if (bcm_static_flowring->buf_use[flow_id]) {
- bcm_static_flowring->buf_use[flow_id] = 0;
- } else {
- printk("%s: flowring %d is already freed\n",
- __FUNCTION__, flow_id);
- }
- spin_unlock_irqrestore(&bcm_static_flowring->flowring_lock, flags);
-}
-#endif /* BCMPCIE && DHD_USE_STATIC_FLOWRING */
#endif /* CONFIG_DHD_USE_STATIC_BUF */
uint32
*alloced = size;
#ifndef BCM_SECURE_DMA
-#if defined(BCM47XX_CA9) && defined(__ARM_ARCH_7A__)
+#if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)
va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO);
if (va)
*pap = (ulong)__virt_to_phys((ulong)va);
{
dma_addr_t pap_lin;
struct pci_dev *hwdev = osh->pdev;
-#ifdef PCIE_TX_DEFERRAL
- va = dma_alloc_coherent(&hwdev->dev, size, &pap_lin, GFP_KERNEL);
+ gfp_t flags;
+#ifdef DHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL
+ flags = GFP_ATOMIC;
+#else
+ flags = GFP_KERNEL;
+#endif /* DHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL */
+ va = dma_alloc_coherent(&hwdev->dev, size, &pap_lin, flags);
+#ifdef BCMDMA64OSL
+ PHYSADDRLOSET(*pap, pap_lin & 0xffffffff);
+ PHYSADDRHISET(*pap, (pap_lin >> 32) & 0xffffffff);
#else
- va = dma_alloc_coherent(&hwdev->dev, size, &pap_lin, GFP_ATOMIC);
-#endif
*pap = (dmaaddr_t)pap_lin;
+#endif /* BCMDMA64OSL */
}
-#endif /* BCM47XX_CA9 && __ARM_ARCH_7A__ */
+#endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
#else
va = osl_sec_dma_alloc_consistent(osh, size, align_bits, pap);
#endif /* BCM_SECURE_DMA */
void
osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa)
{
-#ifndef BCM_SECURE_DMA
-#if !defined(BCM47XX_CA9) || !defined(__ARM_ARCH_7A__)
- struct pci_dev *hwdev = osh->pdev;
-#endif
+#ifdef BCMDMA64OSL
+ dma_addr_t paddr;
+#endif /* BCMDMA64OSL */
ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-#if defined(BCM47XX_CA9) && defined(__ARM_ARCH_7A__)
+#ifndef BCM_SECURE_DMA
+#if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)
kfree(va);
#else
- dma_free_coherent(&hwdev->dev, size, va, (dma_addr_t)pa);
-#endif /* BCM47XX_CA9 && __ARM_ARCH_7A__ */
+#ifdef BCMDMA64OSL
+ PHYSADDRTOULONG(pa, paddr);
+ pci_free_consistent(osh->pdev, size, va, paddr);
+#else
+ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa);
+#endif /* BCMDMA64OSL */
+#endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */
#else
osl_sec_dma_free_consistent(osh, va, size, pa);
#endif /* BCM_SECURE_DMA */
osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah)
{
int dir;
-#ifdef BCM47XX_ACP_WAR
- uint pa;
-#endif
+#ifdef BCMDMA64OSL
+ dmaaddr_t ret;
+ dma_addr_t map_addr;
+#endif /* BCMDMA64OSL */
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[MAX_DMA_SEGS * 2];
-#ifdef BCM47XX_ACP_WAR
- struct scatterlist *s;
-#endif
- 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));
-#ifdef BCM47XX_ACP_WAR
- for_each_sg(sg, s, nsegs, i) {
- if (sg_phys(s) >= ACP_WIN_LIMIT) {
- dma_map_page(&((struct pci_dev *)osh->pdev)->dev,
- sg_page(s), s->offset, s->length, dir);
- }
- }
-#else
- pci_map_sg(osh->pdev, sg, nsegs, dir);
-#endif
- } else {
- nsegs = 1;
- ASSERT(totsegs + nsegs <= MAX_DMA_SEGS);
- sg->page_link = 0;
- sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb));
-#ifdef BCM47XX_ACP_WAR
- if (virt_to_phys(PKTDATA(osh, skb)) >= ACP_WIN_LIMIT)
-#endif
- pci_map_single1(osh->pdev, PKTDATA(osh, skb), 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 /* __ARM_ARCH_7A__ && BCMDMASGLISTOSL */
-#ifdef BCM47XX_ACP_WAR
- pa = virt_to_phys(va);
- if (pa < ACP_WIN_LIMIT)
- return (pa);
-#endif
- return (pci_map_single1(osh->pdev, va, size, dir));
+
+
+#ifdef BCMDMA64OSL
+ map_addr = pci_map_single(osh->pdev, va, size, dir);
+ PHYSADDRLOSET(ret, map_addr & 0xffffffff);
+ PHYSADDRHISET(ret, (map_addr >> 32) & 0xffffffff);
+ return ret;
+#else
+ return (pci_map_single(osh->pdev, va, size, dir));
+#endif /* BCMDMA64OSL */
}
void BCMFASTPATH
-osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction)
+osl_dma_unmap(osl_t *osh, dmaaddr_t pa, uint size, int direction)
{
int dir;
+#ifdef BCMDMA64OSL
+ dma_addr_t paddr;
+#endif /* BCMDMA64OSL */
ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-#ifdef BCM47XX_ACP_WAR
- if (pa < ACP_WIN_LIMIT)
- return;
-#endif
+
+
dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
- pci_unmap_single1(osh->pdev, (uint32)pa, size, dir);
+#ifdef BCMDMA64OSL
+ PHYSADDRTOULONG(pa, paddr);
+ pci_unmap_single(osh->pdev, paddr, size, dir);
+#else
+ pci_unmap_single(osh->pdev, (uint32)pa, size, dir);
+#endif /* BCMDMA64OSL */
+}
+
+/* OSL function for CPU relax */
+inline void BCMFASTPATH
+osl_cpu_relax(void)
+{
+ cpu_relax();
}
-#if defined(BCM47XX_CA9) && defined(__ARM_ARCH_7A__)
+#if (defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING) || \
+ defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_SOC_EXYNOS8890))
+#include <asm/dma-mapping.h>
+
+/*
+ * Note that its gauranteed that the Ring is cache line aligned, but
+ * the messages are not. And we see that __dma_inv_range in
+ * arch/arm64/mm/cache.S invalidates only if the request size is
+ * cache line aligned. If not, it will Clean and invalidate.
+ * So we'll better invalidate the whole ring.
+ *
+ * Also, the latest Kernel versions invoke cache maintenance operations
+ * from arch/arm64/mm/dma-mapping.c, __swiotlb_sync_single_for_device
+ * Only if is_device_dma_coherent returns 0. Since we don't have BSP
+ * source, assuming that its the case, since we pass NULL for the dev ptr
+ */
inline void BCMFASTPATH
osl_cache_flush(void *va, uint size)
{
+ /*
+ * using long for address arithmatic is OK, in linux
+ * 32 bit its 4 bytes and 64 bit its 8 bytes
+ */
+ unsigned long end_cache_line_start;
+ unsigned long end_addr;
+ unsigned long next_cache_line_start;
+
+ end_addr = (unsigned long)va + size;
+
+ /* Start address beyond the cache line we plan to operate */
+ end_cache_line_start = (end_addr & ~(L1_CACHE_BYTES - 1));
+ next_cache_line_start = end_cache_line_start + L1_CACHE_BYTES;
+
+ /* Align the start address to cache line boundary */
+ va = (void *)((unsigned long)va & ~(L1_CACHE_BYTES - 1));
+
+ /* Ensure that size is also aligned and extends partial line to full */
+ size = next_cache_line_start - (unsigned long)va;
+
#ifndef BCM_SECURE_DMA
-#ifdef BCM47XX_ACP_WAR
- if (virt_to_phys(va) < ACP_WIN_LIMIT)
- return;
-#endif
+
+#ifdef CONFIG_ARM64
+ /*
+ * virt_to_dma is not present in arm64/include/dma-mapping.h
+ * So have to convert the va to pa first and then get the dma addr
+ * of the same.
+ */
+ {
+ phys_addr_t pa;
+ dma_addr_t dma_addr;
+ pa = virt_to_phys(va);
+ dma_addr = phys_to_dma(NULL, pa);
+ if (size > 0)
+ dma_sync_single_for_device(OSH_NULL, dma_addr, size, DMA_TX);
+ }
+#else
if (size > 0)
dma_sync_single_for_device(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_TX);
+#endif /* !CONFIG_ARM64 */
#else
phys_addr_t orig_pa = (phys_addr_t)(va - g_contig_delta_va_pa);
if (size > 0)
inline void BCMFASTPATH
osl_cache_inv(void *va, uint size)
{
+ /*
+ * using long for address arithmatic is OK, in linux
+ * 32 bit its 4 bytes and 64 bit its 8 bytes
+ */
+ unsigned long end_cache_line_start;
+ unsigned long end_addr;
+ unsigned long next_cache_line_start;
+
+ end_addr = (unsigned long)va + size;
+
+ /* Start address beyond the cache line we plan to operate */
+ end_cache_line_start = (end_addr & ~(L1_CACHE_BYTES - 1));
+ next_cache_line_start = end_cache_line_start + L1_CACHE_BYTES;
+
+ /* Align the start address to cache line boundary */
+ va = (void *)((unsigned long)va & ~(L1_CACHE_BYTES - 1));
+
+ /* Ensure that size is also aligned and extends partial line to full */
+ size = next_cache_line_start - (unsigned long)va;
+
#ifndef BCM_SECURE_DMA
-#ifdef BCM47XX_ACP_WAR
- if (virt_to_phys(va) < ACP_WIN_LIMIT)
- return;
-#endif
+
+#ifdef CONFIG_ARM64
+ /*
+ * virt_to_dma is not present in arm64/include/dma-mapping.h
+ * So have to convert the va to pa first and then get the dma addr
+ * of the same.
+ */
+ {
+ phys_addr_t pa;
+ dma_addr_t dma_addr;
+ pa = virt_to_phys(va);
+ dma_addr = phys_to_dma(NULL, pa);
+ dma_sync_single_for_cpu(OSH_NULL, dma_addr, size, DMA_RX);
+ }
+#else
dma_sync_single_for_cpu(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_RX);
+#endif /* !CONFIG_ARM64 */
#else
phys_addr_t orig_pa = (phys_addr_t)(va - g_contig_delta_va_pa);
dma_sync_single_for_cpu(OSH_NULL, orig_pa, size, DMA_RX);
inline void osl_prefetch(const void *ptr)
{
- /* Borrowed from linux/linux-2.6/include/asm-arm/processor.h */
- __asm__ __volatile__(
- "pld\t%0"
- :
- : "o" (*(char *)ptr)
- : "cc");
+ /* PLD instruction is not applicable in ARM 64. We don't care for now */
+#ifndef CONFIG_ARM64
+ __asm__ __volatile__("pld\t%0" :: "o"(*(const char *)ptr) : "cc");
+#endif
}
int osl_arch_is_coherent(void)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
return 0;
-#else
- return arch_is_coherent();
-#endif
}
+
+
+inline int osl_acp_war_enab(void)
+{
+ return 0;
+}
+
#endif
#if defined(BCMASSERT_LOG)
#ifdef BCMASSERT_LOG
snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n",
exp, basename, line);
- printk("%s", tempbuf);
#endif /* BCMASSERT_LOG */
+#if defined(BCMASSERT_LOG)
+ switch (g_assert_type) {
+ case 0:
+ panic("%s", tempbuf);
+ break;
+ case 1:
+ printk("%s", tempbuf);
+ break;
+ case 2:
+ printk("%s", tempbuf);
+ BUG();
+ break;
+ default:
+ break;
+ }
+#endif
+
}
#endif
#ifdef BCMDBG_CTRACE
osl_pktdup(osl_t *osh, void *skb, int line, char *file)
#else
+#ifdef BCM_OBJECT_TRACE
+osl_pktdup(osl_t *osh, void *skb, int line, const char *caller)
+#else
osl_pktdup(osl_t *osh, void *skb)
+#endif /* BCM_OBJECT_TRACE */
#endif /* BCMDBG_CTRACE */
{
void * p;
/* Increment the packet counter */
atomic_inc(&osh->cmn->pktalloced);
+#ifdef BCM_OBJECT_TRACE
+ bcm_object_trace_opr(p, BCM_OBJDBG_ADD_PKT, caller, line);
+#endif /* BCM_OBJECT_TRACE */
+
#ifdef BCMDBG_CTRACE
ADD_CTRACE(osh, (struct sk_buff *)p, file, line);
#endif
/* Linux Kernel: File Operations: end */
-#ifdef BCM47XX_ACP_WAR
-inline void osl_pcie_rreg(osl_t *osh, ulong addr, void *v, uint size)
-{
- uint32 flags;
- int pci_access = 0;
-
- if (osh && BUSTYPE(osh->bustype) == PCI_BUS)
- pci_access = 1;
-
- if (pci_access)
- spin_lock_irqsave(&l2x0_reg_lock, flags);
- switch (size) {
- case sizeof(uint8):
- *(uint8*)v = readb((volatile uint8*)(addr));
- break;
- case sizeof(uint16):
- *(uint16*)v = readw((volatile uint16*)(addr));
- break;
- case sizeof(uint32):
- *(uint32*)v = readl((volatile uint32*)(addr));
- break;
- case sizeof(uint64):
- *(uint64*)v = *((volatile uint64*)(addr));
- break;
- }
- if (pci_access)
- spin_unlock_irqrestore(&l2x0_reg_lock, flags);
-}
-#endif /* BCM47XX_ACP_WAR */
/* APIs to set/get specific quirks in OSL layer */
void
{
return (osh->flags & mask);
}
+
#ifdef BCM_SECURE_DMA
static void
vunmap(contig_base_va);
}
-static void
-osl_sec_dma_deinit_elem_mem_block(osl_t *osh, size_t mbsize, int max, void *sec_list_base)
-{
- if (sec_list_base)
- kfree(sec_list_base);
-}
-
static void
osl_sec_dma_init_elem_mem_block(osl_t *osh, size_t mbsize, int max, sec_mem_elem_t **list)
{
}
+static void
+osl_sec_dma_deinit_elem_mem_block(osl_t *osh, size_t mbsize, int max, void *sec_list_base)
+{
+ if (sec_list_base)
+ kfree(sec_list_base);
+}
+
static sec_mem_elem_t * BCMFASTPATH
osl_sec_dma_alloc_mem_elem(osl_t *osh, void *va, uint size, int direction,
struct sec_cma_info *ptr_cma_info, uint offset)
printf("%s free failed size=%d \n", __FUNCTION__, sec_mem_elem->size);
}
-
static sec_mem_elem_t * BCMFASTPATH
osl_sec_dma_find_rem_elem(osl_t *osh, struct sec_cma_info *ptr_cma_info, dma_addr_t dma_handle)
{
(direction == DMA_TX ? DMA_TO_DEVICE:DMA_FROM_DEVICE));
return dma_handle;
-
}
void BCMFASTPATH
}
#endif /* BCM_SECURE_DMA */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) && defined(TSQ_MULTIPLIER)
+#include <linux/kallsyms.h>
+#include <net/sock.h>
+void
+osl_pkt_orphan_partial(struct sk_buff *skb)
+{
+ uint32 fraction;
+ static void *p_tcp_wfree = NULL;
+
+ if (!skb->destructor || skb->destructor == sock_wfree)
+ return;
+
+ if (unlikely(!p_tcp_wfree)) {
+ char sym[KSYM_SYMBOL_LEN];
+ sprint_symbol(sym, (unsigned long)skb->destructor);
+ sym[9] = 0;
+ if (!strcmp(sym, "tcp_wfree"))
+ p_tcp_wfree = skb->destructor;
+ else
+ return;
+ }
+
+ if (unlikely(skb->destructor != p_tcp_wfree || !skb->sk))
+ return;
+
+ /* abstract a certain portion of skb truesize from the socket
+ * sk_wmem_alloc to allow more skb can be allocated for this
+ * socket for better cusion meeting WiFi device requirement
+ */
+ fraction = skb->truesize * (TSQ_MULTIPLIER - 1) / TSQ_MULTIPLIER;
+ skb->truesize -= fraction;
+ atomic_sub(fraction, &skb->sk->sk_wmem_alloc);
+}
+#endif /* LINUX_VERSION >= 3.6.0 && TSQ_MULTIPLIER */