It should improve msgbuf throughput (PCIe devices like BCM43602). Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 45767master
parent
5e5c0edd7e
commit
565eac46b6
@ -0,0 +1,23 @@ |
||||
From: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Date: Thu, 7 May 2015 12:59:19 +0300
|
||||
Subject: [PATCH] brcmfmac: cleanup a sizeof()
|
||||
|
||||
"flowrings" and "*flowrings" are both pointers so this always returns
|
||||
sizeof(void *) and the current code works fine. But "*flowrings" is
|
||||
intended here and static checkers complain, so lets change it.
|
||||
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
@@ -1617,7 +1617,7 @@ static void brcmf_pcie_setup(struct devi
|
||||
bus->msgbuf->commonrings[i] =
|
||||
&devinfo->shared.commonrings[i]->commonring;
|
||||
|
||||
- flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(flowrings),
|
||||
+ flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*flowrings),
|
||||
GFP_KERNEL);
|
||||
if (!flowrings)
|
||||
goto fail;
|
@ -0,0 +1,33 @@ |
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 7 May 2015 14:13:03 +0200
|
||||
Subject: [PATCH] brcmfmac: check result of USB firmware request
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This prevents silence failures with driver waiting (infinitely) for a
|
||||
callback.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Acked-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
|
||||
@@ -1270,8 +1270,13 @@ static int brcmf_usb_probe_cb(struct brc
|
||||
bus->chiprev = bus_pub->chiprev;
|
||||
|
||||
/* request firmware here */
|
||||
- brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), NULL,
|
||||
- brcmf_usb_probe_phase2);
|
||||
+ ret = brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo),
|
||||
+ NULL, brcmf_usb_probe_phase2);
|
||||
+ if (ret) {
|
||||
+ brcmf_err("firmware request failed: %d\n", ret);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
fail:
|
@ -0,0 +1,47 @@ |
||||
From: "Fu, Zhonghui" <zhonghui.fu@linux.intel.com>
|
||||
Date: Mon, 11 May 2015 10:41:32 +0800
|
||||
Subject: [PATCH] brcmfmac: prohibit ACPI power management for brcmfmac driver
|
||||
|
||||
ACPI will manage WiFi chip's power state during suspend/resume
|
||||
process on some tablet platforms(such as ASUS T100TA). This is
|
||||
not supported by brcmfmac driver now, and the context of WiFi
|
||||
chip will be damaged after resume. This patch informs ACPI not
|
||||
to manage WiFi chip's power state.
|
||||
|
||||
Signed-off-by: Zhonghui Fu <zhonghui.fu@linux.intel.com>
|
||||
Acked-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
+#include <linux/acpi.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <defs.h>
|
||||
@@ -1122,6 +1123,8 @@ static int brcmf_ops_sdio_probe(struct s
|
||||
int err;
|
||||
struct brcmf_sdio_dev *sdiodev;
|
||||
struct brcmf_bus *bus_if;
|
||||
+ struct device *dev;
|
||||
+ struct acpi_device *adev;
|
||||
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
brcmf_dbg(SDIO, "Class=%x\n", func->class);
|
||||
@@ -1129,6 +1132,12 @@ static int brcmf_ops_sdio_probe(struct s
|
||||
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
|
||||
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
|
||||
|
||||
+ /* prohibit ACPI power management for this device */
|
||||
+ dev = &func->dev;
|
||||
+ adev = ACPI_COMPANION(dev);
|
||||
+ if (adev)
|
||||
+ adev->flags.power_manageable = 0;
|
||||
+
|
||||
/* Consume func num 1 but dont do anything with it. */
|
||||
if (func->num == 1)
|
||||
return 0;
|
@ -0,0 +1,30 @@ |
||||
From: Arnd Bergmann <arnd@arndb.de>
|
||||
Date: Tue, 12 May 2015 23:54:25 +0200
|
||||
Subject: [PATCH] brcmfmac: avoid gcc-5.1 warning
|
||||
|
||||
gcc-5.0 gained a new warning in the fwsignal portion of the brcmfmac
|
||||
driver:
|
||||
|
||||
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c: In function 'brcmf_fws_txs_process':
|
||||
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c:1478:8: warning: 'skb' may be used uninitialized in this function [-Wmaybe-uninitialized]
|
||||
|
||||
This is a false positive, and marking the brcmf_fws_hanger_poppkt function
|
||||
as 'static inline' makes the warning go away. I have checked the object
|
||||
file output and while a little code gets moved around, the size of
|
||||
the binary remains identical.
|
||||
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -635,7 +635,7 @@ static int brcmf_fws_hanger_pushpkt(stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
|
||||
+static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
|
||||
u32 slot_id, struct sk_buff **pktout,
|
||||
bool remove_item)
|
||||
{
|
@ -0,0 +1,45 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 20 May 2015 14:09:47 +0200
|
||||
Subject: [PATCH] brcmfmac: allow device tree node without 'interrupts'
|
||||
property
|
||||
|
||||
As described in the device tree bindings for 'brcm,bcm4329-fmac'
|
||||
nodes, the interrupts property is optional. So adding a check
|
||||
for the presence of this property before attempting to parse
|
||||
and map the interrupt. If not present or parsing fails return
|
||||
and fallback to in-band sdio interrupt.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/of.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/of.c
|
||||
@@ -39,10 +39,16 @@ void brcmf_of_probe(struct brcmf_sdio_de
|
||||
if (!sdiodev->pdata)
|
||||
return;
|
||||
|
||||
+ if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
|
||||
+ sdiodev->pdata->drive_strength = val;
|
||||
+
|
||||
+ /* make sure there are interrupts defined in the node */
|
||||
+ if (!of_find_property(np, "interrupts", NULL))
|
||||
+ return;
|
||||
+
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq) {
|
||||
brcmf_err("interrupt could not be mapped\n");
|
||||
- devm_kfree(dev, sdiodev->pdata);
|
||||
return;
|
||||
}
|
||||
irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
|
||||
@@ -50,7 +56,4 @@ void brcmf_of_probe(struct brcmf_sdio_de
|
||||
sdiodev->pdata->oob_irq_supported = true;
|
||||
sdiodev->pdata->oob_irq_nr = irq;
|
||||
sdiodev->pdata->oob_irq_flags = irqf;
|
||||
-
|
||||
- if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
|
||||
- sdiodev->pdata->drive_strength = val;
|
||||
}
|
@ -0,0 +1,87 @@ |
||||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Wed, 20 May 2015 14:09:48 +0200
|
||||
Subject: [PATCH] brcmfmac: Improve throughput by scheduling msbug flow worker.
|
||||
|
||||
The tx flow worker in msgbuf gets scheduled at tx till a certain
|
||||
threshold has been reached. Then the tx completes will take over
|
||||
the scheduling. When amsdu and ampdu is used the frames are
|
||||
transferred wireless in a very bulky fashion, in combination
|
||||
with this scheduling algorithm and buffer limiters in the stack
|
||||
this can result in limited throughput. This change causes the
|
||||
flow worker to be scheduled more frequently from tx.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
|
||||
@@ -249,8 +249,8 @@ void brcmf_flowring_delete(struct brcmf_
|
||||
}
|
||||
|
||||
|
||||
-void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
- struct sk_buff *skb)
|
||||
+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
+ struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
@@ -271,6 +271,7 @@ void brcmf_flowring_enqueue(struct brcmf
|
||||
if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)
|
||||
brcmf_flowring_block(flow, flowid, false);
|
||||
}
|
||||
+ return skb_queue_len(&ring->skblist);
|
||||
}
|
||||
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
|
||||
@@ -64,8 +64,8 @@ u32 brcmf_flowring_create(struct brcmf_f
|
||||
void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid);
|
||||
void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid);
|
||||
u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid);
|
||||
-void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
- struct sk_buff *skb);
|
||||
+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
+ struct sk_buff *skb);
|
||||
struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid);
|
||||
void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
|
||||
struct sk_buff *skb);
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -73,7 +73,7 @@
|
||||
#define BRCMF_MSGBUF_TX_FLUSH_CNT1 32
|
||||
#define BRCMF_MSGBUF_TX_FLUSH_CNT2 96
|
||||
|
||||
-#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 64
|
||||
+#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96
|
||||
#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
|
||||
|
||||
struct msgbuf_common_hdr {
|
||||
@@ -797,6 +797,8 @@ static int brcmf_msgbuf_txdata(struct br
|
||||
struct brcmf_flowring *flow = msgbuf->flow;
|
||||
struct ethhdr *eh = (struct ethhdr *)(skb->data);
|
||||
u32 flowid;
|
||||
+ u32 queue_count;
|
||||
+ bool force;
|
||||
|
||||
flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
|
||||
if (flowid == BRCMF_FLOWRING_INVALID_ID) {
|
||||
@@ -804,8 +806,9 @@ static int brcmf_msgbuf_txdata(struct br
|
||||
if (flowid == BRCMF_FLOWRING_INVALID_ID)
|
||||
return -ENOMEM;
|
||||
}
|
||||
- brcmf_flowring_enqueue(flow, flowid, skb);
|
||||
- brcmf_msgbuf_schedule_txdata(msgbuf, flowid, false);
|
||||
+ queue_count = brcmf_flowring_enqueue(flow, flowid, skb);
|
||||
+ force = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0);
|
||||
+ brcmf_msgbuf_schedule_txdata(msgbuf, flowid, force);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,41 @@ |
||||
From: Franky Lin <frankyl@broadcom.com>
|
||||
Date: Wed, 20 May 2015 14:09:49 +0200
|
||||
Subject: [PATCH] brcmfmac: remove pci shared structure rev4 support
|
||||
|
||||
All pcie full dongle chips supported by fmac are using rev 5+ shared
|
||||
structure. This patch removes the rev4 related code.
|
||||
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Franky Lin <frankyl@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
@@ -112,10 +112,9 @@ enum brcmf_pcie_state {
|
||||
BRCMF_PCIE_MB_INT_D2H3_DB0 | \
|
||||
BRCMF_PCIE_MB_INT_D2H3_DB1)
|
||||
|
||||
-#define BRCMF_PCIE_MIN_SHARED_VERSION 4
|
||||
+#define BRCMF_PCIE_MIN_SHARED_VERSION 5
|
||||
#define BRCMF_PCIE_MAX_SHARED_VERSION 5
|
||||
#define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF
|
||||
-#define BRCMF_PCIE_SHARED_TXPUSH_SUPPORT 0x4000
|
||||
|
||||
#define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000
|
||||
#define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000
|
||||
@@ -1280,11 +1279,6 @@ brcmf_pcie_init_share_ram_info(struct br
|
||||
brcmf_err("Unsupported PCIE version %d\n", version);
|
||||
return -EINVAL;
|
||||
}
|
||||
- if (shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT) {
|
||||
- brcmf_err("Unsupported legacy TX mode 0x%x\n",
|
||||
- shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
|
||||
addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
|
||||
shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
|
@ -0,0 +1,120 @@ |
||||
From: Franky Lin <frankyl@broadcom.com>
|
||||
Date: Wed, 20 May 2015 14:09:50 +0200
|
||||
Subject: [PATCH] brcmfmac: remove dummy cache flush/invalidate function
|
||||
|
||||
brcmf_dma_flush and brcmf_dma_invalidate_cache are not necessary and
|
||||
have never been implemented.
|
||||
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Franky Lin <frankyl@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
|
||||
@@ -22,17 +22,6 @@
|
||||
#include "core.h"
|
||||
#include "commonring.h"
|
||||
|
||||
-
|
||||
-/* dma flushing needs implementation for mips and arm platforms. Should
|
||||
- * be put in util. Note, this is not real flushing. It is virtual non
|
||||
- * cached memory. Only write buffers should have to be drained. Though
|
||||
- * this may be different depending on platform......
|
||||
- * SEE ALSO msgbuf.c
|
||||
- */
|
||||
-#define brcmf_dma_flush(addr, len)
|
||||
-#define brcmf_dma_invalidate_cache(addr, len)
|
||||
-
|
||||
-
|
||||
void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
|
||||
int (*cr_ring_bell)(void *ctx),
|
||||
int (*cr_update_rptr)(void *ctx),
|
||||
@@ -206,14 +195,9 @@ int brcmf_commonring_write_complete(stru
|
||||
address = commonring->buf_addr;
|
||||
address += (commonring->f_ptr * commonring->item_len);
|
||||
if (commonring->f_ptr > commonring->w_ptr) {
|
||||
- brcmf_dma_flush(address,
|
||||
- (commonring->depth - commonring->f_ptr) *
|
||||
- commonring->item_len);
|
||||
address = commonring->buf_addr;
|
||||
commonring->f_ptr = 0;
|
||||
}
|
||||
- brcmf_dma_flush(address, (commonring->w_ptr - commonring->f_ptr) *
|
||||
- commonring->item_len);
|
||||
|
||||
commonring->f_ptr = commonring->w_ptr;
|
||||
|
||||
@@ -258,8 +242,6 @@ void *brcmf_commonring_get_read_ptr(stru
|
||||
if (commonring->r_ptr == commonring->depth)
|
||||
commonring->r_ptr = 0;
|
||||
|
||||
- brcmf_dma_invalidate_cache(ret_addr, *n_ items * commonring->item_len);
|
||||
-
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -278,16 +278,6 @@ struct brcmf_msgbuf_pktids {
|
||||
struct brcmf_msgbuf_pktid *array;
|
||||
};
|
||||
|
||||
-
|
||||
-/* dma flushing needs implementation for mips and arm platforms. Should
|
||||
- * be put in util. Note, this is not real flushing. It is virtual non
|
||||
- * cached memory. Only write buffers should have to be drained. Though
|
||||
- * this may be different depending on platform......
|
||||
- */
|
||||
-#define brcmf_dma_flush(addr, len)
|
||||
-#define brcmf_dma_invalidate_cache(addr, len)
|
||||
-
|
||||
-
|
||||
static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf);
|
||||
|
||||
|
||||
@@ -462,7 +452,6 @@ static int brcmf_msgbuf_tx_ioctl(struct
|
||||
memcpy(msgbuf->ioctbuf, buf, buf_len);
|
||||
else
|
||||
memset(msgbuf->ioctbuf, 0, buf_len);
|
||||
- brcmf_dma_flush(ioctl_buf, buf_len);
|
||||
|
||||
err = brcmf_commonring_write_complete(commonring);
|
||||
brcmf_commonring_unlock(commonring);
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
@@ -276,15 +276,6 @@ static const u32 brcmf_ring_itemsize[BRC
|
||||
};
|
||||
|
||||
|
||||
-/* dma flushing needs implementation for mips and arm platforms. Should
|
||||
- * be put in util. Note, this is not real flushing. It is virtual non
|
||||
- * cached memory. Only write buffers should have to be drained. Though
|
||||
- * this may be different depending on platform......
|
||||
- */
|
||||
-#define brcmf_dma_flush(addr, len)
|
||||
-#define brcmf_dma_invalidate_cache(addr, len)
|
||||
-
|
||||
-
|
||||
static u32
|
||||
brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
|
||||
{
|
||||
@@ -1174,7 +1165,6 @@ static int brcmf_pcie_init_scratchbuffer
|
||||
goto fail;
|
||||
|
||||
memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
|
||||
- brcmf_dma_flush(devinfo->shared.scratch, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
|
||||
|
||||
addr = devinfo->shared.tcm_base_address +
|
||||
BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
|
||||
@@ -1192,7 +1182,6 @@ static int brcmf_pcie_init_scratchbuffer
|
||||
goto fail;
|
||||
|
||||
memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
|
||||
- brcmf_dma_flush(devinfo->shared.ringupd, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
|
||||
|
||||
addr = devinfo->shared.tcm_base_address +
|
||||
BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
|
@ -0,0 +1,270 @@ |
||||
From: Franky Lin <frankyl@broadcom.com>
|
||||
Date: Wed, 20 May 2015 14:09:51 +0200
|
||||
Subject: [PATCH] brcmfmac: add support for dma indices feature
|
||||
|
||||
PCIe full dongle firmware can support a dma indices feature with which
|
||||
firmware can update/fetch the read/write indices of message buffer
|
||||
rings on both host to dongle and dongle to host directions. The support is
|
||||
announced by firmware through shared flags.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Franky Lin <frankyl@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
@@ -115,6 +115,8 @@ enum brcmf_pcie_state {
|
||||
#define BRCMF_PCIE_MIN_SHARED_VERSION 5
|
||||
#define BRCMF_PCIE_MAX_SHARED_VERSION 5
|
||||
#define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF
|
||||
+#define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000
|
||||
+#define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000
|
||||
|
||||
#define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000
|
||||
#define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000
|
||||
@@ -146,6 +148,10 @@ enum brcmf_pcie_state {
|
||||
#define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8
|
||||
#define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12
|
||||
#define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16
|
||||
+#define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET 20
|
||||
+#define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET 28
|
||||
+#define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET 36
|
||||
+#define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET 44
|
||||
#define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET 0
|
||||
#define BRCMF_SHARED_RING_MAX_SUB_QUEUES 52
|
||||
|
||||
@@ -247,6 +253,13 @@ struct brcmf_pciedev_info {
|
||||
bool mbdata_completed;
|
||||
bool irq_allocated;
|
||||
bool wowl_enabled;
|
||||
+ u8 dma_idx_sz;
|
||||
+ void *idxbuf;
|
||||
+ u32 idxbuf_sz;
|
||||
+ dma_addr_t idxbuf_dmahandle;
|
||||
+ u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
|
||||
+ void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
|
||||
+ u16 value);
|
||||
};
|
||||
|
||||
struct brcmf_pcie_ringbuf {
|
||||
@@ -323,6 +336,25 @@ brcmf_pcie_write_tcm16(struct brcmf_pcie
|
||||
}
|
||||
|
||||
|
||||
+static u16
|
||||
+brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
|
||||
+{
|
||||
+ u16 *address = devinfo->idxbuf + mem_offset;
|
||||
+
|
||||
+ return (*(address));
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void
|
||||
+brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
|
||||
+ u16 value)
|
||||
+{
|
||||
+ u16 *address = devinfo->idxbuf + mem_offset;
|
||||
+
|
||||
+ *(address) = value;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static u32
|
||||
brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
|
||||
{
|
||||
@@ -868,7 +900,7 @@ static int brcmf_pcie_ring_mb_write_rptr
|
||||
brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
|
||||
commonring->w_ptr, ring->id);
|
||||
|
||||
- brcmf_pcie_write_tcm16(devinfo, ring->r_idx_addr, commonring->r_ptr);
|
||||
+ devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -886,7 +918,7 @@ static int brcmf_pcie_ring_mb_write_wptr
|
||||
brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
|
||||
commonring->r_ptr, ring->id);
|
||||
|
||||
- brcmf_pcie_write_tcm16(devinfo, ring->w_idx_addr, commonring->w_ptr);
|
||||
+ devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -915,7 +947,7 @@ static int brcmf_pcie_ring_mb_update_rpt
|
||||
if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
|
||||
return -EIO;
|
||||
|
||||
- commonring->r_ptr = brcmf_pcie_read_tcm16(devinfo, ring->r_idx_addr);
|
||||
+ commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr);
|
||||
|
||||
brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
|
||||
commonring->w_ptr, ring->id);
|
||||
@@ -933,7 +965,7 @@ static int brcmf_pcie_ring_mb_update_wpt
|
||||
if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
|
||||
return -EIO;
|
||||
|
||||
- commonring->w_ptr = brcmf_pcie_read_tcm16(devinfo, ring->w_idx_addr);
|
||||
+ commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr);
|
||||
|
||||
brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
|
||||
commonring->r_ptr, ring->id);
|
||||
@@ -1038,6 +1070,13 @@ static void brcmf_pcie_release_ringbuffe
|
||||
}
|
||||
kfree(devinfo->shared.flowrings);
|
||||
devinfo->shared.flowrings = NULL;
|
||||
+ if (devinfo->idxbuf) {
|
||||
+ dma_free_coherent(&devinfo->pdev->dev,
|
||||
+ devinfo->idxbuf_sz,
|
||||
+ devinfo->idxbuf,
|
||||
+ devinfo->idxbuf_dmahandle);
|
||||
+ devinfo->idxbuf = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -1053,19 +1092,72 @@ static int brcmf_pcie_init_ringbuffers(s
|
||||
u32 addr;
|
||||
u32 ring_mem_ptr;
|
||||
u32 i;
|
||||
+ u64 address;
|
||||
+ u32 bufsz;
|
||||
u16 max_sub_queues;
|
||||
+ u8 idx_offset;
|
||||
|
||||
ring_addr = devinfo->shared.ring_info_addr;
|
||||
brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr);
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
|
||||
+ max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
|
||||
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
|
||||
- d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
|
||||
- d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
|
||||
- h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
|
||||
- h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
+ if (devinfo->dma_idx_sz != 0) {
|
||||
+ bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) *
|
||||
+ devinfo->dma_idx_sz * 2;
|
||||
+ devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
|
||||
+ &devinfo->idxbuf_dmahandle,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!devinfo->idxbuf)
|
||||
+ devinfo->dma_idx_sz = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (devinfo->dma_idx_sz == 0) {
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
|
||||
+ d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
|
||||
+ d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
|
||||
+ h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
|
||||
+ h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
+ idx_offset = sizeof(u32);
|
||||
+ devinfo->write_ptr = brcmf_pcie_write_tcm16;
|
||||
+ devinfo->read_ptr = brcmf_pcie_read_tcm16;
|
||||
+ brcmf_dbg(PCIE, "Using TCM indices\n");
|
||||
+ } else {
|
||||
+ memset(devinfo->idxbuf, 0, bufsz);
|
||||
+ devinfo->idxbuf_sz = bufsz;
|
||||
+ idx_offset = devinfo->dma_idx_sz;
|
||||
+ devinfo->write_ptr = brcmf_pcie_write_idx;
|
||||
+ devinfo->read_ptr = brcmf_pcie_read_idx;
|
||||
+
|
||||
+ h2d_w_idx_ptr = 0;
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET;
|
||||
+ address = (u64)devinfo->idxbuf_dmahandle;
|
||||
+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
|
||||
+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
|
||||
+
|
||||
+ h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset;
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET;
|
||||
+ address += max_sub_queues * idx_offset;
|
||||
+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
|
||||
+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
|
||||
+
|
||||
+ d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset;
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET;
|
||||
+ address += max_sub_queues * idx_offset;
|
||||
+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
|
||||
+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
|
||||
+
|
||||
+ d2h_r_idx_ptr = d2h_w_idx_ptr +
|
||||
+ BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
|
||||
+ addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET;
|
||||
+ address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
|
||||
+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
|
||||
+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
|
||||
+ brcmf_dbg(PCIE, "Using host memory indices\n");
|
||||
+ }
|
||||
|
||||
addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET;
|
||||
ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
@@ -1079,8 +1171,8 @@ static int brcmf_pcie_init_ringbuffers(s
|
||||
ring->id = i;
|
||||
devinfo->shared.commonrings[i] = ring;
|
||||
|
||||
- h2d_w_idx_ptr += sizeof(u32);
|
||||
- h2d_r_idx_ptr += sizeof(u32);
|
||||
+ h2d_w_idx_ptr += idx_offset;
|
||||
+ h2d_r_idx_ptr += idx_offset;
|
||||
ring_mem_ptr += BRCMF_RING_MEM_SZ;
|
||||
}
|
||||
|
||||
@@ -1094,13 +1186,11 @@ static int brcmf_pcie_init_ringbuffers(s
|
||||
ring->id = i;
|
||||
devinfo->shared.commonrings[i] = ring;
|
||||
|
||||
- d2h_w_idx_ptr += sizeof(u32);
|
||||
- d2h_r_idx_ptr += sizeof(u32);
|
||||
+ d2h_w_idx_ptr += idx_offset;
|
||||
+ d2h_r_idx_ptr += idx_offset;
|
||||
ring_mem_ptr += BRCMF_RING_MEM_SZ;
|
||||
}
|
||||
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
|
||||
- max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
|
||||
devinfo->shared.nrof_flowrings =
|
||||
max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
|
||||
rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
|
||||
@@ -1124,15 +1214,15 @@ static int brcmf_pcie_init_ringbuffers(s
|
||||
ring);
|
||||
ring->w_idx_addr = h2d_w_idx_ptr;
|
||||
ring->r_idx_addr = h2d_r_idx_ptr;
|
||||
- h2d_w_idx_ptr += sizeof(u32);
|
||||
- h2d_r_idx_ptr += sizeof(u32);
|
||||
+ h2d_w_idx_ptr += idx_offset;
|
||||
+ h2d_r_idx_ptr += idx_offset;
|
||||
}
|
||||
devinfo->shared.flowrings = rings;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
- brcmf_err("Allocating commonring buffers failed\n");
|
||||
+ brcmf_err("Allocating ring buffers failed\n");
|
||||
brcmf_pcie_release_ringbuffers(devinfo);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -1269,6 +1359,14 @@ brcmf_pcie_init_share_ram_info(struct br
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ /* check firmware support dma indicies */
|
||||
+ if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) {
|
||||
+ if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX)
|
||||
+ devinfo->dma_idx_sz = sizeof(u16);
|
||||
+ else
|
||||
+ devinfo->dma_idx_sz = sizeof(u32);
|
||||
+ }
|
||||
+
|
||||
addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
|
||||
shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
|
||||
if (shared->max_rxbufpost == 0)
|
Loading…
Reference in new issue