mac80211: update brcmfmac including missing boardrev workaround
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 49174
This commit is contained in:
parent
e920824fdd
commit
894aed060e
13 changed files with 1439 additions and 8 deletions
|
@ -0,0 +1,54 @@
|
|||
From: Hui Wang <hui.wang@canonical.com>
|
||||
Date: Wed, 9 Mar 2016 15:25:26 +0800
|
||||
Subject: [PATCH] brcmfmac: Remove waitqueue_active check
|
||||
|
||||
We met a problem of pm_suspend when repeated closing/opening the lid
|
||||
on a Lenovo laptop (1/20 reproduce rate), below is the log:
|
||||
|
||||
[ 199.735876] PM: Entering mem sleep
|
||||
[ 199.750516] e1000e: EEE TX LPI TIMER: 00000011
|
||||
[ 199.856638] Trying to free nonexistent resource <000000000000d000-000000000000d0ff>
|
||||
[ 201.753566] brcmfmac: brcmf_pcie_suspend: Timeout on response for entering D3 substate
|
||||
[ 201.753581] pci_legacy_suspend(): brcmf_pcie_suspend+0x0/0x1f0 [brcmfmac] returns -5
|
||||
[ 201.753585] dpm_run_callback(): pci_pm_suspend+0x0/0x160 returns -5
|
||||
[ 201.753589] PM: Device 0000:04:00.0 failed to suspend async: error -5
|
||||
|
||||
Through debugging, we found when problem happens, it is not the device
|
||||
fails to enter D3, but the signal D3_ACK comes too early to pass the
|
||||
waitqueue_active() check.
|
||||
|
||||
Just like this:
|
||||
brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D3_INFORM);
|
||||
// signal is triggered here
|
||||
wait_event_timeout(devinfo->mbdata_resp_wait, devinfo->mbdata_completed,
|
||||
BRCMF_PCIE_MBDATA_TIMEOUT);
|
||||
|
||||
So far I think it is safe to remove waitqueue_active check since there
|
||||
is only one place to trigger this signal (sending
|
||||
BRCMF_H2D_HOST_D3_INFORM). And it is not a problem calling wake_up
|
||||
event earlier than calling wait_event.
|
||||
|
||||
Cc: Brett Rudley <brudley@broadcom.com>
|
||||
Cc: Hante Meuleman <meuleman@broadcom.com>
|
||||
Cc: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Cc: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Cc: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Hui Wang <hui.wang@canonical.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
@@ -677,10 +677,8 @@ static void brcmf_pcie_handle_mb_data(st
|
||||
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
|
||||
if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {
|
||||
brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
|
||||
- if (waitqueue_active(&devinfo->mbdata_resp_wait)) {
|
||||
- devinfo->mbdata_completed = true;
|
||||
- wake_up(&devinfo->mbdata_resp_wait);
|
||||
- }
|
||||
+ devinfo->mbdata_completed = true;
|
||||
+ wake_up(&devinfo->mbdata_resp_wait);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
From: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Date: Tue, 15 Mar 2016 10:06:10 +0300
|
||||
Subject: [PATCH] brcmfmac: uninitialized "ret" variable
|
||||
|
||||
There is an error path where "ret" isn't initialized.
|
||||
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
|
||||
@@ -250,7 +250,7 @@ static int brcmf_sdiod_request_data(stru
|
||||
u32 addr, u8 regsz, void *data, bool write)
|
||||
{
|
||||
struct sdio_func *func;
|
||||
- int ret;
|
||||
+ int ret = -EINVAL;
|
||||
|
||||
brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
|
||||
write, fn, addr, regsz);
|
|
@ -0,0 +1,24 @@
|
|||
From: Colin Ian King <colin.king@canonical.com>
|
||||
Date: Sun, 20 Mar 2016 17:34:52 +0000
|
||||
Subject: [PATCH] brcmfmac: sdio: remove unused variable retry_limit
|
||||
|
||||
retry_limit has never been used during the life of this driver, so
|
||||
we may as well remove it as it is redundant.
|
||||
|
||||
Signed-off-by: Colin Ian King <colin.king@canonical.com>
|
||||
Reviewed-by: Julian Calaby <julian.calaby@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
@@ -535,9 +535,6 @@ static int qcount[NUMPRIO];
|
||||
|
||||
#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
|
||||
|
||||
-/* Retry count for register access failures */
|
||||
-static const uint retry_limit = 2;
|
||||
-
|
||||
/* Limit on rounding up frames */
|
||||
static const uint max_roundup = 512;
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
From: Markus Elfring <elfring@users.sourceforge.net>
|
||||
Date: Fri, 18 Mar 2016 13:23:24 +1100
|
||||
Subject: [PATCH] brcmfmac: Delete unnecessary variable initialisation
|
||||
|
||||
In brcmf_sdio_download_firmware(), bcmerror is set by the call to
|
||||
brcmf_sdio_download_code_file(), before it's checked in the following
|
||||
line.
|
||||
|
||||
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
|
||||
Acked-by: Arend van Spriel <arend@broadcom.com>
|
||||
[Rewrote commit message]
|
||||
Signed-off-by: Julian Calaby <julian.calaby@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
@@ -3258,7 +3258,7 @@ static int brcmf_sdio_download_firmware(
|
||||
const struct firmware *fw,
|
||||
void *nvram, u32 nvlen)
|
||||
{
|
||||
- int bcmerror = -EFAULT;
|
||||
+ int bcmerror;
|
||||
u32 rstvec;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
|
@ -0,0 +1,27 @@
|
|||
From: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:21 +0200
|
||||
Subject: [PATCH] brcmfmac: clear eventmask array before using it
|
||||
|
||||
When the event_msgs iovar is set an array is used to configure the
|
||||
enabled events. This arrays needs to nulled before configuring
|
||||
otherwise unhandled events will be enabled. This solves a problem
|
||||
where in case of wowl the host got woken by an incorrectly enabled
|
||||
event.
|
||||
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
|
||||
@@ -371,6 +371,7 @@ int brcmf_fweh_activate_events(struct br
|
||||
int i, err;
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
|
||||
+ memset(eventmask, 0, sizeof(eventmask));
|
||||
for (i = 0; i < BRCMF_E_LAST; i++) {
|
||||
if (ifp->drvr->fweh.evt_handler[i]) {
|
||||
brcmf_dbg(EVENT, "enable event %s\n",
|
|
@ -0,0 +1,27 @@
|
|||
From: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:22 +0200
|
||||
Subject: [PATCH] brcmfmac: fix clearing wowl wake indicators
|
||||
|
||||
Newer firmwares require the usage of the wowl wakeind struct as size
|
||||
for the iovar to clear the wake indicators. Older firmwares do not
|
||||
care, so change the used size.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -3608,7 +3608,8 @@ static void brcmf_configure_wowl(struct
|
||||
if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
|
||||
wowl_config |= BRCMF_WOWL_UNASSOC;
|
||||
|
||||
- brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", strlen("clear"));
|
||||
+ brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear",
|
||||
+ sizeof(struct brcmf_wowl_wakeind_le));
|
||||
brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
|
||||
brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
|
||||
brcmf_bus_wowl_config(cfg->pub->bus_if, true);
|
|
@ -0,0 +1,114 @@
|
|||
From: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:23 +0200
|
||||
Subject: [PATCH] brcmfmac: insert default boardrev in nvram data if
|
||||
missing
|
||||
|
||||
Some nvram files/stores come without the boardrev information,
|
||||
but firmware requires this to be set. When not found in nvram then
|
||||
add a default boardrev string to the nvram data.
|
||||
|
||||
Reported-by: Rafal Milecki <zajec5@gmail.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <franky.lin@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
@@ -29,6 +29,7 @@
|
||||
#define BRCMF_FW_MAX_NVRAM_SIZE 64000
|
||||
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
|
||||
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
|
||||
+#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff"
|
||||
|
||||
enum nvram_parser_state {
|
||||
IDLE,
|
||||
@@ -51,6 +52,7 @@ enum nvram_parser_state {
|
||||
* @entry: start position of key,value entry.
|
||||
* @multi_dev_v1: detect pcie multi device v1 (compressed).
|
||||
* @multi_dev_v2: detect pcie multi device v2.
|
||||
+ * @boardrev_found: nvram contains boardrev information.
|
||||
*/
|
||||
struct nvram_parser {
|
||||
enum nvram_parser_state state;
|
||||
@@ -63,6 +65,7 @@ struct nvram_parser {
|
||||
u32 entry;
|
||||
bool multi_dev_v1;
|
||||
bool multi_dev_v2;
|
||||
+ bool boardrev_found;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -125,6 +128,8 @@ static enum nvram_parser_state brcmf_nvr
|
||||
nvp->multi_dev_v1 = true;
|
||||
if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
|
||||
nvp->multi_dev_v2 = true;
|
||||
+ if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0)
|
||||
+ nvp->boardrev_found = true;
|
||||
} else if (!is_nvram_char(c) || c == ' ') {
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
|
||||
nvp->line, nvp->column);
|
||||
@@ -284,6 +289,8 @@ static void brcmf_fw_strip_multi_v1(stru
|
||||
while (i < nvp->nvram_len) {
|
||||
if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) {
|
||||
i += 2;
|
||||
+ if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0)
|
||||
+ nvp->boardrev_found = true;
|
||||
while (nvp->nvram[i] != 0) {
|
||||
nvram[j] = nvp->nvram[i];
|
||||
i++;
|
||||
@@ -335,6 +342,8 @@ static void brcmf_fw_strip_multi_v2(stru
|
||||
while (i < nvp->nvram_len - len) {
|
||||
if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
|
||||
i += len;
|
||||
+ if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0)
|
||||
+ nvp->boardrev_found = true;
|
||||
while (nvp->nvram[i] != 0) {
|
||||
nvram[j] = nvp->nvram[i];
|
||||
i++;
|
||||
@@ -356,6 +365,18 @@ fail:
|
||||
nvp->nvram_len = 0;
|
||||
}
|
||||
|
||||
+static void brcmf_fw_add_defaults(struct nvram_parser *nvp)
|
||||
+{
|
||||
+ if (nvp->boardrev_found)
|
||||
+ return;
|
||||
+
|
||||
+ memcpy(&nvp->nvram[nvp->nvram_len], &BRCMF_FW_DEFAULT_BOARDREV,
|
||||
+ strlen(BRCMF_FW_DEFAULT_BOARDREV));
|
||||
+ nvp->nvram_len += strlen(BRCMF_FW_DEFAULT_BOARDREV);
|
||||
+ nvp->nvram[nvp->nvram_len] = '\0';
|
||||
+ nvp->nvram_len++;
|
||||
+}
|
||||
+
|
||||
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
|
||||
* and ending in a NUL. Removes carriage returns, empty lines, comment lines,
|
||||
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
|
||||
@@ -377,16 +398,21 @@ static void *brcmf_fw_nvram_strip(const
|
||||
if (nvp.state == END)
|
||||
break;
|
||||
}
|
||||
- if (nvp.multi_dev_v1)
|
||||
+ if (nvp.multi_dev_v1) {
|
||||
+ nvp.boardrev_found = false;
|
||||
brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr);
|
||||
- else if (nvp.multi_dev_v2)
|
||||
+ } else if (nvp.multi_dev_v2) {
|
||||
+ nvp.boardrev_found = false;
|
||||
brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr);
|
||||
+ }
|
||||
|
||||
if (nvp.nvram_len == 0) {
|
||||
kfree(nvp.nvram);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ brcmf_fw_add_defaults(&nvp);
|
||||
+
|
||||
pad = nvp.nvram_len;
|
||||
*new_length = roundup(nvp.nvram_len + 1, 4);
|
||||
while (pad != *new_length) {
|
|
@ -0,0 +1,29 @@
|
|||
From: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:24 +0200
|
||||
Subject: [PATCH] brcmfmac: fix p2p scan abort null pointer exception
|
||||
|
||||
When p2p connection setup is performed without having ever done an
|
||||
escan a null pointer exception can occur. This is because the ifp
|
||||
to abort scanning is taken from escan struct while it was never
|
||||
initialized. Fix this by using the primary ifp for scan abort. The
|
||||
abort should still be performed and all scan related commands are
|
||||
performed on primary ifp.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
|
||||
@@ -1266,7 +1266,7 @@ static void
|
||||
brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||
- struct brcmf_if *ifp = cfg->escan_info.ifp;
|
||||
+ struct brcmf_if *ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
||||
|
||||
if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) &&
|
||||
(test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) ||
|
|
@ -0,0 +1,297 @@
|
|||
From: Franky Lin <franky.lin@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:25 +0200
|
||||
Subject: [PATCH] brcmfmac: screening firmware event packet
|
||||
|
||||
Firmware uses asynchronized events as a communication method to the
|
||||
host. The event packets are marked as ETH_P_LINK_CTL protocol type. For
|
||||
SDIO and PCIe bus, this kind of packets are delivered through virtual
|
||||
event channel not data channel. This patch adds a screening logic to
|
||||
make sure the event handler only processes the events coming from the
|
||||
correct channel.
|
||||
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Signed-off-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
||||
@@ -216,7 +216,9 @@ bool brcmf_c_prec_enq(struct device *dev
|
||||
int prec);
|
||||
|
||||
/* Receive frame for delivery to OS. Callee disposes of rxp. */
|
||||
-void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp);
|
||||
+void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_evnt);
|
||||
+/* Receive async event packet from firmware. Callee disposes of rxp. */
|
||||
+void brcmf_rx_event(struct device *dev, struct sk_buff *rxp);
|
||||
|
||||
/* Indication from bus module regarding presence/insertion of dongle. */
|
||||
int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -311,16 +311,17 @@ void brcmf_txflowblock(struct device *de
|
||||
brcmf_fws_bus_blocked(drvr, state);
|
||||
}
|
||||
|
||||
-void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb,
|
||||
+ bool handle_event)
|
||||
{
|
||||
- skb->dev = ifp->ndev;
|
||||
- skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
+ skb->protocol = eth_type_trans(skb, ifp->ndev);
|
||||
|
||||
if (skb->pkt_type == PACKET_MULTICAST)
|
||||
ifp->stats.multicast++;
|
||||
|
||||
/* Process special event packets */
|
||||
- brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
+ if (handle_event)
|
||||
+ brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
|
||||
if (!(ifp->ndev->flags & IFF_UP)) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
@@ -381,7 +382,7 @@ static void brcmf_rxreorder_process_info
|
||||
/* validate flags and flow id */
|
||||
if (flags == 0xFF) {
|
||||
brcmf_err("invalid flags...so ignore this packet\n");
|
||||
- brcmf_netif_rx(ifp, pkt);
|
||||
+ brcmf_netif_rx(ifp, pkt, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -393,7 +394,7 @@ static void brcmf_rxreorder_process_info
|
||||
if (rfi == NULL) {
|
||||
brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
|
||||
flow_id);
|
||||
- brcmf_netif_rx(ifp, pkt);
|
||||
+ brcmf_netif_rx(ifp, pkt, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -418,7 +419,7 @@ static void brcmf_rxreorder_process_info
|
||||
rfi = kzalloc(buf_size, GFP_ATOMIC);
|
||||
if (rfi == NULL) {
|
||||
brcmf_err("failed to alloc buffer\n");
|
||||
- brcmf_netif_rx(ifp, pkt);
|
||||
+ brcmf_netif_rx(ifp, pkt, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -532,11 +533,11 @@ static void brcmf_rxreorder_process_info
|
||||
netif_rx:
|
||||
skb_queue_walk_safe(&reorder_list, pkt, pnext) {
|
||||
__skb_unlink(pkt, &reorder_list);
|
||||
- brcmf_netif_rx(ifp, pkt);
|
||||
+ brcmf_netif_rx(ifp, pkt, false);
|
||||
}
|
||||
}
|
||||
|
||||
-void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
|
||||
+void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
@@ -560,7 +561,32 @@ void brcmf_rx_frame(struct device *dev,
|
||||
if (rd->reorder)
|
||||
brcmf_rxreorder_process_info(ifp, rd->reorder, skb);
|
||||
else
|
||||
- brcmf_netif_rx(ifp, skb);
|
||||
+ brcmf_netif_rx(ifp, skb, handle_evnt);
|
||||
+}
|
||||
+
|
||||
+void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct brcmf_if *ifp;
|
||||
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
+ struct brcmf_pub *drvr = bus_if->drvr;
|
||||
+ int ret;
|
||||
+
|
||||
+ brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
|
||||
+
|
||||
+ /* process and remove protocol-specific header */
|
||||
+ ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
|
||||
+
|
||||
+ if (ret || !ifp || !ifp->ndev) {
|
||||
+ if (ret != -ENODATA && ifp)
|
||||
+ ifp->stats.rx_errors++;
|
||||
+ brcmu_pkt_buf_free_skb(skb);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ skb->protocol = eth_type_trans(skb, ifp->ndev);
|
||||
+
|
||||
+ brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
+ brcmu_pkt_buf_free_skb(skb);
|
||||
}
|
||||
|
||||
void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
@@ -225,7 +225,8 @@ int brcmf_get_next_free_bsscfgidx(struct
|
||||
void brcmf_txflowblock_if(struct brcmf_if *ifp,
|
||||
enum brcmf_netif_stop_reason reason, bool state);
|
||||
void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
|
||||
-void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb,
|
||||
+ bool handle_event);
|
||||
void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
|
||||
int __init brcmf_core_init(void);
|
||||
void __exit brcmf_core_exit(void);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
@@ -1075,28 +1076,13 @@ static void brcmf_msgbuf_rxbuf_event_pos
|
||||
}
|
||||
|
||||
|
||||
-static void
|
||||
-brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb,
|
||||
- u8 ifidx)
|
||||
-{
|
||||
- struct brcmf_if *ifp;
|
||||
-
|
||||
- ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
|
||||
- if (!ifp || !ifp->ndev) {
|
||||
- brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
|
||||
- brcmu_pkt_buf_free_skb(skb);
|
||||
- return;
|
||||
- }
|
||||
- brcmf_netif_rx(ifp, skb);
|
||||
-}
|
||||
-
|
||||
-
|
||||
static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
|
||||
{
|
||||
struct msgbuf_rx_event *event;
|
||||
u32 idx;
|
||||
u16 buflen;
|
||||
struct sk_buff *skb;
|
||||
+ struct brcmf_if *ifp;
|
||||
|
||||
event = (struct msgbuf_rx_event *)buf;
|
||||
idx = le32_to_cpu(event->msg.request_id);
|
||||
@@ -1116,7 +1102,19 @@ static void brcmf_msgbuf_process_event(s
|
||||
|
||||
skb_trim(skb, buflen);
|
||||
|
||||
- brcmf_msgbuf_rx_skb(msgbuf, skb, event->msg.ifidx);
|
||||
+ ifp = brcmf_get_ifp(msgbuf->drvr, event->msg.ifidx);
|
||||
+ if (!ifp || !ifp->ndev) {
|
||||
+ brcmf_err("Received pkt for invalid ifidx %d\n",
|
||||
+ event->msg.ifidx);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ skb->protocol = eth_type_trans(skb, ifp->ndev);
|
||||
+
|
||||
+ brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
+
|
||||
+exit:
|
||||
+ brcmu_pkt_buf_free_skb(skb);
|
||||
}
|
||||
|
||||
|
||||
@@ -1128,6 +1126,7 @@ brcmf_msgbuf_process_rx_complete(struct
|
||||
u16 data_offset;
|
||||
u16 buflen;
|
||||
u32 idx;
|
||||
+ struct brcmf_if *ifp;
|
||||
|
||||
brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1);
|
||||
|
||||
@@ -1148,7 +1147,14 @@ brcmf_msgbuf_process_rx_complete(struct
|
||||
|
||||
skb_trim(skb, buflen);
|
||||
|
||||
- brcmf_msgbuf_rx_skb(msgbuf, skb, rx_complete->msg.ifidx);
|
||||
+ ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
|
||||
+ if (!ifp || !ifp->ndev) {
|
||||
+ brcmf_err("Received pkt for invalid ifidx %d\n",
|
||||
+ rx_complete->msg.ifidx);
|
||||
+ brcmu_pkt_buf_free_skb(skb);
|
||||
+ return;
|
||||
+ }
|
||||
+ brcmf_netif_rx(ifp, skb, false);
|
||||
}
|
||||
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
@@ -1294,6 +1294,17 @@ static inline u8 brcmf_sdio_getdatoffset
|
||||
return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT);
|
||||
}
|
||||
|
||||
+static inline bool brcmf_sdio_fromevntchan(u8 *swheader)
|
||||
+{
|
||||
+ u32 hdrvalue;
|
||||
+ u8 ret;
|
||||
+
|
||||
+ hdrvalue = *(u32 *)swheader;
|
||||
+ ret = (u8)((hdrvalue & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT);
|
||||
+
|
||||
+ return (ret == SDPCM_EVENT_CHANNEL);
|
||||
+}
|
||||
+
|
||||
static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
|
||||
struct brcmf_sdio_hdrinfo *rd,
|
||||
enum brcmf_sdio_frmtype type)
|
||||
@@ -1641,7 +1652,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf
|
||||
pfirst->len, pfirst->next,
|
||||
pfirst->prev);
|
||||
skb_unlink(pfirst, &bus->glom);
|
||||
- brcmf_rx_frame(bus->sdiodev->dev, pfirst);
|
||||
+ if (brcmf_sdio_fromevntchan(pfirst->data))
|
||||
+ brcmf_rx_event(bus->sdiodev->dev, pfirst);
|
||||
+ else
|
||||
+ brcmf_rx_frame(bus->sdiodev->dev, pfirst,
|
||||
+ false);
|
||||
bus->sdcnt.rxglompkts++;
|
||||
}
|
||||
|
||||
@@ -1967,18 +1982,19 @@ static uint brcmf_sdio_readframes(struct
|
||||
__skb_trim(pkt, rd->len);
|
||||
skb_pull(pkt, rd->dat_offset);
|
||||
|
||||
+ if (pkt->len == 0)
|
||||
+ brcmu_pkt_buf_free_skb(pkt);
|
||||
+ else if (rd->channel == SDPCM_EVENT_CHANNEL)
|
||||
+ brcmf_rx_event(bus->sdiodev->dev, pkt);
|
||||
+ else
|
||||
+ brcmf_rx_frame(bus->sdiodev->dev, pkt,
|
||||
+ false);
|
||||
+
|
||||
/* prepare the descriptor for the next read */
|
||||
rd->len = rd->len_nxtfrm << 4;
|
||||
rd->len_nxtfrm = 0;
|
||||
/* treat all packet as event if we don't know */
|
||||
rd->channel = SDPCM_EVENT_CHANNEL;
|
||||
-
|
||||
- if (pkt->len == 0) {
|
||||
- brcmu_pkt_buf_free_skb(pkt);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- brcmf_rx_frame(bus->sdiodev->dev, pkt);
|
||||
}
|
||||
|
||||
rxcount = maxframes - rxleft;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
|
||||
@@ -514,7 +514,7 @@ static void brcmf_usb_rx_complete(struct
|
||||
|
||||
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
|
||||
skb_put(skb, urb->actual_length);
|
||||
- brcmf_rx_frame(devinfo->dev, skb);
|
||||
+ brcmf_rx_frame(devinfo->dev, skb, true);
|
||||
brcmf_usb_rx_refill(devinfo, req);
|
||||
} else {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
|
@ -0,0 +1,585 @@
|
|||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:26 +0200
|
||||
Subject: [PATCH] brcmfmac: cleanup ampdu-rx host reorder code
|
||||
|
||||
The code for ampdu-rx host reorder is related to the firmware signalling
|
||||
supported in BCDC protocol. This change moves the code to fwsignal module.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
|
||||
@@ -351,6 +351,12 @@ brcmf_proto_bcdc_add_tdls_peer(struct br
|
||||
{
|
||||
}
|
||||
|
||||
+static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ brcmf_fws_rxreorder(ifp, skb);
|
||||
+}
|
||||
+
|
||||
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_bcdc *bcdc;
|
||||
@@ -372,6 +378,7 @@ int brcmf_proto_bcdc_attach(struct brcmf
|
||||
drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
|
||||
drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
|
||||
drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
|
||||
+ drvr->proto->rxreorder = brcmf_proto_bcdc_rxreorder;
|
||||
drvr->proto->pd = bcdc;
|
||||
|
||||
drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -40,19 +40,6 @@
|
||||
|
||||
#define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950)
|
||||
|
||||
-/* AMPDU rx reordering definitions */
|
||||
-#define BRCMF_RXREORDER_FLOWID_OFFSET 0
|
||||
-#define BRCMF_RXREORDER_MAXIDX_OFFSET 2
|
||||
-#define BRCMF_RXREORDER_FLAGS_OFFSET 4
|
||||
-#define BRCMF_RXREORDER_CURIDX_OFFSET 6
|
||||
-#define BRCMF_RXREORDER_EXPIDX_OFFSET 8
|
||||
-
|
||||
-#define BRCMF_RXREORDER_DEL_FLOW 0x01
|
||||
-#define BRCMF_RXREORDER_FLUSH_ALL 0x02
|
||||
-#define BRCMF_RXREORDER_CURIDX_VALID 0x04
|
||||
-#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
|
||||
-#define BRCMF_RXREORDER_NEW_HOLE 0x10
|
||||
-
|
||||
#define BRCMF_BSSIDX_INVALID -1
|
||||
|
||||
char *brcmf_ifname(struct brcmf_if *ifp)
|
||||
@@ -342,207 +329,11 @@ void brcmf_netif_rx(struct brcmf_if *ifp
|
||||
netif_rx_ni(skb);
|
||||
}
|
||||
|
||||
-static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
|
||||
- u8 start, u8 end,
|
||||
- struct sk_buff_head *skb_list)
|
||||
-{
|
||||
- /* initialize return list */
|
||||
- __skb_queue_head_init(skb_list);
|
||||
-
|
||||
- if (rfi->pend_pkts == 0) {
|
||||
- brcmf_dbg(INFO, "no packets in reorder queue\n");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- do {
|
||||
- if (rfi->pktslots[start]) {
|
||||
- __skb_queue_tail(skb_list, rfi->pktslots[start]);
|
||||
- rfi->pktslots[start] = NULL;
|
||||
- }
|
||||
- start++;
|
||||
- if (start > rfi->max_idx)
|
||||
- start = 0;
|
||||
- } while (start != end);
|
||||
- rfi->pend_pkts -= skb_queue_len(skb_list);
|
||||
-}
|
||||
-
|
||||
-static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data,
|
||||
- struct sk_buff *pkt)
|
||||
-{
|
||||
- u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
|
||||
- struct brcmf_ampdu_rx_reorder *rfi;
|
||||
- struct sk_buff_head reorder_list;
|
||||
- struct sk_buff *pnext;
|
||||
- u8 flags;
|
||||
- u32 buf_size;
|
||||
-
|
||||
- flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
|
||||
- flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
|
||||
-
|
||||
- /* validate flags and flow id */
|
||||
- if (flags == 0xFF) {
|
||||
- brcmf_err("invalid flags...so ignore this packet\n");
|
||||
- brcmf_netif_rx(ifp, pkt, false);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- rfi = ifp->drvr->reorder_flows[flow_id];
|
||||
- if (flags & BRCMF_RXREORDER_DEL_FLOW) {
|
||||
- brcmf_dbg(INFO, "flow-%d: delete\n",
|
||||
- flow_id);
|
||||
-
|
||||
- if (rfi == NULL) {
|
||||
- brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
|
||||
- flow_id);
|
||||
- brcmf_netif_rx(ifp, pkt, false);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
|
||||
- &reorder_list);
|
||||
- /* add the last packet */
|
||||
- __skb_queue_tail(&reorder_list, pkt);
|
||||
- kfree(rfi);
|
||||
- ifp->drvr->reorder_flows[flow_id] = NULL;
|
||||
- goto netif_rx;
|
||||
- }
|
||||
- /* from here on we need a flow reorder instance */
|
||||
- if (rfi == NULL) {
|
||||
- buf_size = sizeof(*rfi);
|
||||
- max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
|
||||
-
|
||||
- buf_size += (max_idx + 1) * sizeof(pkt);
|
||||
-
|
||||
- /* allocate space for flow reorder info */
|
||||
- brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
|
||||
- flow_id, max_idx);
|
||||
- rfi = kzalloc(buf_size, GFP_ATOMIC);
|
||||
- if (rfi == NULL) {
|
||||
- brcmf_err("failed to alloc buffer\n");
|
||||
- brcmf_netif_rx(ifp, pkt, false);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- ifp->drvr->reorder_flows[flow_id] = rfi;
|
||||
- rfi->pktslots = (struct sk_buff **)(rfi+1);
|
||||
- rfi->max_idx = max_idx;
|
||||
- }
|
||||
- if (flags & BRCMF_RXREORDER_NEW_HOLE) {
|
||||
- if (rfi->pend_pkts) {
|
||||
- brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
|
||||
- rfi->exp_idx,
|
||||
- &reorder_list);
|
||||
- WARN_ON(rfi->pend_pkts);
|
||||
- } else {
|
||||
- __skb_queue_head_init(&reorder_list);
|
||||
- }
|
||||
- rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
|
||||
- rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
- rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
|
||||
- rfi->pktslots[rfi->cur_idx] = pkt;
|
||||
- rfi->pend_pkts++;
|
||||
- brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
|
||||
- flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
|
||||
- } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
|
||||
- cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
|
||||
- exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
-
|
||||
- if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
|
||||
- /* still in the current hole */
|
||||
- /* enqueue the current on the buffer chain */
|
||||
- if (rfi->pktslots[cur_idx] != NULL) {
|
||||
- brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
|
||||
- brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
|
||||
- rfi->pktslots[cur_idx] = NULL;
|
||||
- }
|
||||
- rfi->pktslots[cur_idx] = pkt;
|
||||
- rfi->pend_pkts++;
|
||||
- rfi->cur_idx = cur_idx;
|
||||
- brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
|
||||
- flow_id, cur_idx, exp_idx, rfi->pend_pkts);
|
||||
-
|
||||
- /* can return now as there is no reorder
|
||||
- * list to process.
|
||||
- */
|
||||
- return;
|
||||
- }
|
||||
- if (rfi->exp_idx == cur_idx) {
|
||||
- if (rfi->pktslots[cur_idx] != NULL) {
|
||||
- brcmf_dbg(INFO, "error buffer pending..free it\n");
|
||||
- brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
|
||||
- rfi->pktslots[cur_idx] = NULL;
|
||||
- }
|
||||
- rfi->pktslots[cur_idx] = pkt;
|
||||
- rfi->pend_pkts++;
|
||||
-
|
||||
- /* got the expected one. flush from current to expected
|
||||
- * and update expected
|
||||
- */
|
||||
- brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
|
||||
- flow_id, cur_idx, exp_idx, rfi->pend_pkts);
|
||||
-
|
||||
- rfi->cur_idx = cur_idx;
|
||||
- rfi->exp_idx = exp_idx;
|
||||
-
|
||||
- brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
|
||||
- &reorder_list);
|
||||
- brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
|
||||
- flow_id, skb_queue_len(&reorder_list),
|
||||
- rfi->pend_pkts);
|
||||
- } else {
|
||||
- u8 end_idx;
|
||||
-
|
||||
- brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
|
||||
- flow_id, flags, rfi->cur_idx, rfi->exp_idx,
|
||||
- cur_idx, exp_idx);
|
||||
- if (flags & BRCMF_RXREORDER_FLUSH_ALL)
|
||||
- end_idx = rfi->exp_idx;
|
||||
- else
|
||||
- end_idx = exp_idx;
|
||||
-
|
||||
- /* flush pkts first */
|
||||
- brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
|
||||
- &reorder_list);
|
||||
-
|
||||
- if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
|
||||
- __skb_queue_tail(&reorder_list, pkt);
|
||||
- } else {
|
||||
- rfi->pktslots[cur_idx] = pkt;
|
||||
- rfi->pend_pkts++;
|
||||
- }
|
||||
- rfi->exp_idx = exp_idx;
|
||||
- rfi->cur_idx = cur_idx;
|
||||
- }
|
||||
- } else {
|
||||
- /* explicity window move updating the expected index */
|
||||
- exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
-
|
||||
- brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
|
||||
- flow_id, flags, rfi->exp_idx, exp_idx);
|
||||
- if (flags & BRCMF_RXREORDER_FLUSH_ALL)
|
||||
- end_idx = rfi->exp_idx;
|
||||
- else
|
||||
- end_idx = exp_idx;
|
||||
-
|
||||
- brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
|
||||
- &reorder_list);
|
||||
- __skb_queue_tail(&reorder_list, pkt);
|
||||
- /* set the new expected idx */
|
||||
- rfi->exp_idx = exp_idx;
|
||||
- }
|
||||
-netif_rx:
|
||||
- skb_queue_walk_safe(&reorder_list, pkt, pnext) {
|
||||
- __skb_unlink(pkt, &reorder_list);
|
||||
- brcmf_netif_rx(ifp, pkt, false);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
- struct brcmf_skb_reorder_data *rd;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
|
||||
@@ -557,9 +348,8 @@ void brcmf_rx_frame(struct device *dev,
|
||||
return;
|
||||
}
|
||||
|
||||
- rd = (struct brcmf_skb_reorder_data *)skb->cb;
|
||||
- if (rd->reorder)
|
||||
- brcmf_rxreorder_process_info(ifp, rd->reorder, skb);
|
||||
+ if (brcmf_proto_is_reorder_skb(skb))
|
||||
+ brcmf_proto_rxreorder(ifp, skb);
|
||||
else
|
||||
brcmf_netif_rx(ifp, skb, handle_evnt);
|
||||
}
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
@@ -208,10 +208,6 @@ struct brcmf_if {
|
||||
u8 ipv6addr_idx;
|
||||
};
|
||||
|
||||
-struct brcmf_skb_reorder_data {
|
||||
- u8 *reorder;
|
||||
-};
|
||||
-
|
||||
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
|
||||
|
||||
/* Return pointer to interface name */
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -92,6 +92,19 @@ enum brcmf_fws_tlv_len {
|
||||
};
|
||||
#undef BRCMF_FWS_TLV_DEF
|
||||
|
||||
+/* AMPDU rx reordering definitions */
|
||||
+#define BRCMF_RXREORDER_FLOWID_OFFSET 0
|
||||
+#define BRCMF_RXREORDER_MAXIDX_OFFSET 2
|
||||
+#define BRCMF_RXREORDER_FLAGS_OFFSET 4
|
||||
+#define BRCMF_RXREORDER_CURIDX_OFFSET 6
|
||||
+#define BRCMF_RXREORDER_EXPIDX_OFFSET 8
|
||||
+
|
||||
+#define BRCMF_RXREORDER_DEL_FLOW 0x01
|
||||
+#define BRCMF_RXREORDER_FLUSH_ALL 0x02
|
||||
+#define BRCMF_RXREORDER_CURIDX_VALID 0x04
|
||||
+#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
|
||||
+#define BRCMF_RXREORDER_NEW_HOLE 0x10
|
||||
+
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* brcmf_fws_tlv_names - array of tlv names.
|
||||
@@ -1614,6 +1627,202 @@ static int brcmf_fws_notify_bcmc_credit_
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
|
||||
+ u8 start, u8 end,
|
||||
+ struct sk_buff_head *skb_list)
|
||||
+{
|
||||
+ /* initialize return list */
|
||||
+ __skb_queue_head_init(skb_list);
|
||||
+
|
||||
+ if (rfi->pend_pkts == 0) {
|
||||
+ brcmf_dbg(INFO, "no packets in reorder queue\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ do {
|
||||
+ if (rfi->pktslots[start]) {
|
||||
+ __skb_queue_tail(skb_list, rfi->pktslots[start]);
|
||||
+ rfi->pktslots[start] = NULL;
|
||||
+ }
|
||||
+ start++;
|
||||
+ if (start > rfi->max_idx)
|
||||
+ start = 0;
|
||||
+ } while (start != end);
|
||||
+ rfi->pend_pkts -= skb_queue_len(skb_list);
|
||||
+}
|
||||
+
|
||||
+void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
|
||||
+{
|
||||
+ u8 *reorder_data;
|
||||
+ u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
|
||||
+ struct brcmf_ampdu_rx_reorder *rfi;
|
||||
+ struct sk_buff_head reorder_list;
|
||||
+ struct sk_buff *pnext;
|
||||
+ u8 flags;
|
||||
+ u32 buf_size;
|
||||
+
|
||||
+ reorder_data = ((struct brcmf_skb_reorder_data *)pkt->cb)->reorder;
|
||||
+ flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
|
||||
+ flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
|
||||
+
|
||||
+ /* validate flags and flow id */
|
||||
+ if (flags == 0xFF) {
|
||||
+ brcmf_err("invalid flags...so ignore this packet\n");
|
||||
+ brcmf_netif_rx(ifp, pkt, false);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ rfi = ifp->drvr->reorder_flows[flow_id];
|
||||
+ if (flags & BRCMF_RXREORDER_DEL_FLOW) {
|
||||
+ brcmf_dbg(INFO, "flow-%d: delete\n",
|
||||
+ flow_id);
|
||||
+
|
||||
+ if (rfi == NULL) {
|
||||
+ brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
|
||||
+ flow_id);
|
||||
+ brcmf_netif_rx(ifp, pkt, false);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
|
||||
+ &reorder_list);
|
||||
+ /* add the last packet */
|
||||
+ __skb_queue_tail(&reorder_list, pkt);
|
||||
+ kfree(rfi);
|
||||
+ ifp->drvr->reorder_flows[flow_id] = NULL;
|
||||
+ goto netif_rx;
|
||||
+ }
|
||||
+ /* from here on we need a flow reorder instance */
|
||||
+ if (rfi == NULL) {
|
||||
+ buf_size = sizeof(*rfi);
|
||||
+ max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
|
||||
+
|
||||
+ buf_size += (max_idx + 1) * sizeof(pkt);
|
||||
+
|
||||
+ /* allocate space for flow reorder info */
|
||||
+ brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
|
||||
+ flow_id, max_idx);
|
||||
+ rfi = kzalloc(buf_size, GFP_ATOMIC);
|
||||
+ if (rfi == NULL) {
|
||||
+ brcmf_err("failed to alloc buffer\n");
|
||||
+ brcmf_netif_rx(ifp, pkt, false);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ifp->drvr->reorder_flows[flow_id] = rfi;
|
||||
+ rfi->pktslots = (struct sk_buff **)(rfi + 1);
|
||||
+ rfi->max_idx = max_idx;
|
||||
+ }
|
||||
+ if (flags & BRCMF_RXREORDER_NEW_HOLE) {
|
||||
+ if (rfi->pend_pkts) {
|
||||
+ brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
|
||||
+ rfi->exp_idx,
|
||||
+ &reorder_list);
|
||||
+ WARN_ON(rfi->pend_pkts);
|
||||
+ } else {
|
||||
+ __skb_queue_head_init(&reorder_list);
|
||||
+ }
|
||||
+ rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
|
||||
+ rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
+ rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
|
||||
+ rfi->pktslots[rfi->cur_idx] = pkt;
|
||||
+ rfi->pend_pkts++;
|
||||
+ brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
|
||||
+ flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
|
||||
+ } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
|
||||
+ cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
|
||||
+ exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
+
|
||||
+ if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
|
||||
+ /* still in the current hole */
|
||||
+ /* enqueue the current on the buffer chain */
|
||||
+ if (rfi->pktslots[cur_idx] != NULL) {
|
||||
+ brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
|
||||
+ brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
|
||||
+ rfi->pktslots[cur_idx] = NULL;
|
||||
+ }
|
||||
+ rfi->pktslots[cur_idx] = pkt;
|
||||
+ rfi->pend_pkts++;
|
||||
+ rfi->cur_idx = cur_idx;
|
||||
+ brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
|
||||
+ flow_id, cur_idx, exp_idx, rfi->pend_pkts);
|
||||
+
|
||||
+ /* can return now as there is no reorder
|
||||
+ * list to process.
|
||||
+ */
|
||||
+ return;
|
||||
+ }
|
||||
+ if (rfi->exp_idx == cur_idx) {
|
||||
+ if (rfi->pktslots[cur_idx] != NULL) {
|
||||
+ brcmf_dbg(INFO, "error buffer pending..free it\n");
|
||||
+ brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
|
||||
+ rfi->pktslots[cur_idx] = NULL;
|
||||
+ }
|
||||
+ rfi->pktslots[cur_idx] = pkt;
|
||||
+ rfi->pend_pkts++;
|
||||
+
|
||||
+ /* got the expected one. flush from current to expected
|
||||
+ * and update expected
|
||||
+ */
|
||||
+ brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
|
||||
+ flow_id, cur_idx, exp_idx, rfi->pend_pkts);
|
||||
+
|
||||
+ rfi->cur_idx = cur_idx;
|
||||
+ rfi->exp_idx = exp_idx;
|
||||
+
|
||||
+ brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
|
||||
+ &reorder_list);
|
||||
+ brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
|
||||
+ flow_id, skb_queue_len(&reorder_list),
|
||||
+ rfi->pend_pkts);
|
||||
+ } else {
|
||||
+ u8 end_idx;
|
||||
+
|
||||
+ brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
|
||||
+ flow_id, flags, rfi->cur_idx, rfi->exp_idx,
|
||||
+ cur_idx, exp_idx);
|
||||
+ if (flags & BRCMF_RXREORDER_FLUSH_ALL)
|
||||
+ end_idx = rfi->exp_idx;
|
||||
+ else
|
||||
+ end_idx = exp_idx;
|
||||
+
|
||||
+ /* flush pkts first */
|
||||
+ brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
|
||||
+ &reorder_list);
|
||||
+
|
||||
+ if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
|
||||
+ __skb_queue_tail(&reorder_list, pkt);
|
||||
+ } else {
|
||||
+ rfi->pktslots[cur_idx] = pkt;
|
||||
+ rfi->pend_pkts++;
|
||||
+ }
|
||||
+ rfi->exp_idx = exp_idx;
|
||||
+ rfi->cur_idx = cur_idx;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* explicity window move updating the expected index */
|
||||
+ exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
+
|
||||
+ brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
|
||||
+ flow_id, flags, rfi->exp_idx, exp_idx);
|
||||
+ if (flags & BRCMF_RXREORDER_FLUSH_ALL)
|
||||
+ end_idx = rfi->exp_idx;
|
||||
+ else
|
||||
+ end_idx = exp_idx;
|
||||
+
|
||||
+ brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
|
||||
+ &reorder_list);
|
||||
+ __skb_queue_tail(&reorder_list, pkt);
|
||||
+ /* set the new expected idx */
|
||||
+ rfi->exp_idx = exp_idx;
|
||||
+ }
|
||||
+netif_rx:
|
||||
+ skb_queue_walk_safe(&reorder_list, pkt, pnext) {
|
||||
+ __skb_unlink(pkt, &reorder_list);
|
||||
+ brcmf_netif_rx(ifp, pkt, false);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_skb_reorder_data *rd;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
|
||||
@@ -29,5 +29,6 @@ void brcmf_fws_add_interface(struct brcm
|
||||
void brcmf_fws_del_interface(struct brcmf_if *ifp);
|
||||
void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
|
||||
void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked);
|
||||
+void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
|
||||
#endif /* FWSIGNAL_H_ */
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -527,6 +527,9 @@ static int brcmf_msgbuf_hdrpull(struct b
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
+static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
+{
|
||||
+}
|
||||
|
||||
static void
|
||||
brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid)
|
||||
@@ -1466,6 +1469,7 @@ int brcmf_proto_msgbuf_attach(struct brc
|
||||
drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
|
||||
drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
|
||||
drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
|
||||
+ drvr->proto->rxreorder = brcmf_msgbuf_rxreorder;
|
||||
drvr->proto->pd = msgbuf;
|
||||
|
||||
init_waitqueue_head(&msgbuf->ioctl_resp_wait);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
|
||||
@@ -22,6 +22,9 @@ enum proto_addr_mode {
|
||||
ADDR_DIRECT
|
||||
};
|
||||
|
||||
+struct brcmf_skb_reorder_data {
|
||||
+ u8 *reorder;
|
||||
+};
|
||||
|
||||
struct brcmf_proto {
|
||||
int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
|
||||
@@ -38,6 +41,7 @@ struct brcmf_proto {
|
||||
u8 peer[ETH_ALEN]);
|
||||
void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
|
||||
u8 peer[ETH_ALEN]);
|
||||
+ void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
void *pd;
|
||||
};
|
||||
|
||||
@@ -91,6 +95,18 @@ brcmf_proto_add_tdls_peer(struct brcmf_p
|
||||
{
|
||||
drvr->proto->add_tdls_peer(drvr, ifidx, peer);
|
||||
}
|
||||
+static inline bool brcmf_proto_is_reorder_skb(struct sk_buff *skb)
|
||||
+{
|
||||
+ struct brcmf_skb_reorder_data *rd;
|
||||
+
|
||||
+ rd = (struct brcmf_skb_reorder_data *)skb->cb;
|
||||
+ return !!rd->reorder;
|
||||
+}
|
||||
|
||||
+static inline void
|
||||
+brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
+{
|
||||
+ ifp->drvr->proto->rxreorder(ifp, skb);
|
||||
+}
|
||||
|
||||
#endif /* BRCMFMAC_PROTO_H */
|
|
@ -0,0 +1,139 @@
|
|||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:27 +0200
|
||||
Subject: [PATCH] brcmfmac: revise handling events in receive path
|
||||
|
||||
Move event handling out of brcmf_netif_rx() avoiding the need
|
||||
to pass a flag. This flag is only ever true for USB hosts as
|
||||
other interface use separate brcmf_rx_event() function.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
||||
@@ -216,7 +216,7 @@ bool brcmf_c_prec_enq(struct device *dev
|
||||
int prec);
|
||||
|
||||
/* Receive frame for delivery to OS. Callee disposes of rxp. */
|
||||
-void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_evnt);
|
||||
+void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event);
|
||||
/* Receive async event packet from firmware. Callee disposes of rxp. */
|
||||
void brcmf_rx_event(struct device *dev, struct sk_buff *rxp);
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -298,18 +298,11 @@ void brcmf_txflowblock(struct device *de
|
||||
brcmf_fws_bus_blocked(drvr, state);
|
||||
}
|
||||
|
||||
-void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb,
|
||||
- bool handle_event)
|
||||
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
{
|
||||
- skb->protocol = eth_type_trans(skb, ifp->ndev);
|
||||
-
|
||||
if (skb->pkt_type == PACKET_MULTICAST)
|
||||
ifp->stats.multicast++;
|
||||
|
||||
- /* Process special event packets */
|
||||
- if (handle_event)
|
||||
- brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
-
|
||||
if (!(ifp->ndev->flags & IFF_UP)) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return;
|
||||
@@ -329,7 +322,7 @@ void brcmf_netif_rx(struct brcmf_if *ifp
|
||||
netif_rx_ni(skb);
|
||||
}
|
||||
|
||||
-void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt)
|
||||
+void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
@@ -348,10 +341,17 @@ void brcmf_rx_frame(struct device *dev,
|
||||
return;
|
||||
}
|
||||
|
||||
- if (brcmf_proto_is_reorder_skb(skb))
|
||||
+ skb->protocol = eth_type_trans(skb, ifp->ndev);
|
||||
+
|
||||
+ if (brcmf_proto_is_reorder_skb(skb)) {
|
||||
brcmf_proto_rxreorder(ifp, skb);
|
||||
- else
|
||||
- brcmf_netif_rx(ifp, skb, handle_evnt);
|
||||
+ } else {
|
||||
+ /* Process special event packets */
|
||||
+ if (handle_event)
|
||||
+ brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
+
|
||||
+ brcmf_netif_rx(ifp, skb);
|
||||
+ }
|
||||
}
|
||||
|
||||
void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
@@ -221,8 +221,7 @@ int brcmf_get_next_free_bsscfgidx(struct
|
||||
void brcmf_txflowblock_if(struct brcmf_if *ifp,
|
||||
enum brcmf_netif_stop_reason reason, bool state);
|
||||
void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
|
||||
-void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb,
|
||||
- bool handle_event);
|
||||
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
|
||||
int __init brcmf_core_init(void);
|
||||
void __exit brcmf_core_exit(void);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -1668,7 +1668,7 @@ void brcmf_fws_rxreorder(struct brcmf_if
|
||||
/* validate flags and flow id */
|
||||
if (flags == 0xFF) {
|
||||
brcmf_err("invalid flags...so ignore this packet\n");
|
||||
- brcmf_netif_rx(ifp, pkt, false);
|
||||
+ brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1680,7 +1680,7 @@ void brcmf_fws_rxreorder(struct brcmf_if
|
||||
if (rfi == NULL) {
|
||||
brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
|
||||
flow_id);
|
||||
- brcmf_netif_rx(ifp, pkt, false);
|
||||
+ brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1705,7 +1705,7 @@ void brcmf_fws_rxreorder(struct brcmf_if
|
||||
rfi = kzalloc(buf_size, GFP_ATOMIC);
|
||||
if (rfi == NULL) {
|
||||
brcmf_err("failed to alloc buffer\n");
|
||||
- brcmf_netif_rx(ifp, pkt, false);
|
||||
+ brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1819,7 +1819,7 @@ void brcmf_fws_rxreorder(struct brcmf_if
|
||||
netif_rx:
|
||||
skb_queue_walk_safe(&reorder_list, pkt, pnext) {
|
||||
__skb_unlink(pkt, &reorder_list);
|
||||
- brcmf_netif_rx(ifp, pkt, false);
|
||||
+ brcmf_netif_rx(ifp, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -1157,7 +1157,7 @@ brcmf_msgbuf_process_rx_complete(struct
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return;
|
||||
}
|
||||
- brcmf_netif_rx(ifp, skb, false);
|
||||
+ brcmf_netif_rx(ifp, skb);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Mon, 11 Apr 2016 11:35:28 +0200
|
||||
Subject: [PATCH] brcmfmac: create common function for handling
|
||||
brcmf_proto_hdrpull()
|
||||
|
||||
In receive path brcmf_proto_hdrpull() needs to be called and handled
|
||||
similar in brcmf_rx_frame() and brcmf_rx_event(). Move that duplicated
|
||||
code in separate function.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -322,26 +322,35 @@ void brcmf_netif_rx(struct brcmf_if *ifp
|
||||
netif_rx_ni(skb);
|
||||
}
|
||||
|
||||
-void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
|
||||
+static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
|
||||
+ struct brcmf_if **ifp)
|
||||
{
|
||||
- struct brcmf_if *ifp;
|
||||
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
- struct brcmf_pub *drvr = bus_if->drvr;
|
||||
int ret;
|
||||
|
||||
- brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
|
||||
-
|
||||
/* process and remove protocol-specific header */
|
||||
- ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
|
||||
+ ret = brcmf_proto_hdrpull(drvr, true, skb, ifp);
|
||||
|
||||
- if (ret || !ifp || !ifp->ndev) {
|
||||
+ if (ret || !(*ifp) || !(*ifp)->ndev) {
|
||||
if (ret != -ENODATA && ifp)
|
||||
- ifp->stats.rx_errors++;
|
||||
+ (*ifp)->stats.rx_errors++;
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
- return;
|
||||
+ return -ENODATA;
|
||||
}
|
||||
|
||||
- skb->protocol = eth_type_trans(skb, ifp->ndev);
|
||||
+ skb->protocol = eth_type_trans(skb, (*ifp)->ndev);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
|
||||
+{
|
||||
+ struct brcmf_if *ifp;
|
||||
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
+ struct brcmf_pub *drvr = bus_if->drvr;
|
||||
+
|
||||
+ brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
|
||||
+
|
||||
+ if (brcmf_rx_hdrpull(drvr, skb, &ifp))
|
||||
+ return;
|
||||
|
||||
if (brcmf_proto_is_reorder_skb(skb)) {
|
||||
brcmf_proto_rxreorder(ifp, skb);
|
||||
@@ -359,21 +368,11 @@ void brcmf_rx_event(struct device *dev,
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
- int ret;
|
||||
|
||||
brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
|
||||
|
||||
- /* process and remove protocol-specific header */
|
||||
- ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
|
||||
-
|
||||
- if (ret || !ifp || !ifp->ndev) {
|
||||
- if (ret != -ENODATA && ifp)
|
||||
- ifp->stats.rx_errors++;
|
||||
- brcmu_pkt_buf_free_skb(skb);
|
||||
+ if (brcmf_rx_hdrpull(drvr, skb, &ifp))
|
||||
return;
|
||||
- }
|
||||
-
|
||||
- skb->protocol = eth_type_trans(skb, ifp->ndev);
|
||||
|
||||
brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
brcmu_pkt_buf_free_skb(skb);
|
|
@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -1417,6 +1417,7 @@ int __init brcmf_core_init(void)
|
||||
@@ -1232,6 +1232,7 @@ int __init brcmf_core_init(void)
|
||||
{
|
||||
if (!schedule_work(&brcmf_driver_work))
|
||||
return -EBUSY;
|
||||
|
@ -23,7 +23,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
}
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
@@ -418,6 +418,7 @@ struct brcmf_fw {
|
||||
@@ -444,6 +444,7 @@ struct brcmf_fw {
|
||||
u16 bus_nr;
|
||||
void (*done)(struct device *dev, const struct firmware *fw,
|
||||
void *nvram_image, u32 nvram_len);
|
||||
|
@ -31,7 +31,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
};
|
||||
|
||||
static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
|
||||
@@ -452,6 +453,8 @@ static void brcmf_fw_request_nvram_done(
|
||||
@@ -478,6 +479,8 @@ static void brcmf_fw_request_nvram_done(
|
||||
goto fail;
|
||||
|
||||
fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
|
||||
|
@ -40,7 +40,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
kfree(fwctx);
|
||||
return;
|
||||
|
||||
@@ -459,6 +462,8 @@ fail:
|
||||
@@ -485,6 +488,8 @@ fail:
|
||||
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
|
||||
release_firmware(fwctx->code);
|
||||
device_release_driver(fwctx->dev);
|
||||
|
@ -49,7 +49,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
kfree(fwctx);
|
||||
}
|
||||
|
||||
@@ -474,6 +479,8 @@ static void brcmf_fw_request_code_done(c
|
||||
@@ -500,6 +505,8 @@ static void brcmf_fw_request_code_done(c
|
||||
/* only requested code so done here */
|
||||
if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
|
||||
fwctx->done(fwctx->dev, fw, NULL, 0);
|
||||
|
@ -58,7 +58,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
kfree(fwctx);
|
||||
return;
|
||||
}
|
||||
@@ -491,6 +498,8 @@ static void brcmf_fw_request_code_done(c
|
||||
@@ -517,6 +524,8 @@ static void brcmf_fw_request_code_done(c
|
||||
fail:
|
||||
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
|
||||
device_release_driver(fwctx->dev);
|
||||
|
@ -67,7 +67,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
kfree(fwctx);
|
||||
}
|
||||
|
||||
@@ -502,6 +511,8 @@ int brcmf_fw_get_firmwares_pcie(struct d
|
||||
@@ -528,6 +537,8 @@ int brcmf_fw_get_firmwares_pcie(struct d
|
||||
u16 domain_nr, u16 bus_nr)
|
||||
{
|
||||
struct brcmf_fw *fwctx;
|
||||
|
@ -76,7 +76,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
|
||||
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
|
||||
if (!fw_cb || !code)
|
||||
@@ -522,9 +533,17 @@ int brcmf_fw_get_firmwares_pcie(struct d
|
||||
@@ -548,9 +559,17 @@ int brcmf_fw_get_firmwares_pcie(struct d
|
||||
fwctx->domain_nr = domain_nr;
|
||||
fwctx->bus_nr = bus_nr;
|
||||
|
||||
|
|
Loading…
Reference in a new issue