All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] brcmfmac: event handling and other fixes
@ 2016-04-11  9:35 Arend van Spriel
  2016-04-11  9:35 ` [PATCH 1/8] brcmfmac: clear eventmask array before using it Arend van Spriel
                   ` (8 more replies)
  0 siblings, 9 replies; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

This series provides the following:

* avoid unexpected firmware events.
* allow passing events explicitly for PCIe and SDIO devices.
* fix issue with boardrev entry in nvram.
* fix for wowl.
* fix possible null pointer access upon aborting p2p scan.

The series is intended for v4.7 kernel and applies to the master
branch of the wireless-drivers-next repository.

Arend van Spriel (3):
  brcmfmac: cleanup ampdu-rx host reorder code
  brcmfmac: revise handling events in receive path
  brcmfmac: create common function for handling brcmf_proto_hdrpull()

Franky Lin (1):
  brcmfmac: screening firmware event packet

Hante Meuleman (4):
  brcmfmac: clear eventmask array before using it
  brcmfmac: fix clearing wowl wake indicators
  brcmfmac: insert default boardrev in nvram data if missing
  brcmfmac: fix p2p scan abort null pointer exception

 .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c    |   7 +
 .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h |   4 +-
 .../broadcom/brcm80211/brcmfmac/cfg80211.c         |   3 +-
 .../wireless/broadcom/brcm80211/brcmfmac/core.c    | 247 +++------------------
 .../wireless/broadcom/brcm80211/brcmfmac/core.h    |   4 -
 .../broadcom/brcm80211/brcmfmac/firmware.c         |  30 ++-
 .../wireless/broadcom/brcm80211/brcmfmac/fweh.c    |   1 +
 .../broadcom/brcm80211/brcmfmac/fwsignal.c         | 209 +++++++++++++++++
 .../broadcom/brcm80211/brcmfmac/fwsignal.h         |   1 +
 .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  |  46 ++--
 .../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c |   2 +-
 .../wireless/broadcom/brcm80211/brcmfmac/proto.h   |  16 ++
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    |  32 ++-
 .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c |   2 +-
 14 files changed, 352 insertions(+), 252 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/8] brcmfmac: clear eventmask array before using it
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
@ 2016-04-11  9:35 ` Arend van Spriel
  2016-04-14 13:01   ` [1/8] " Kalle Valo
  2016-04-11  9:35 ` [PATCH 2/8] brcmfmac: fix clearing wowl wake indicators Arend van Spriel
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <hante.meuleman@broadcom.com>

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>
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
index d414fbb..b390561 100644
--- 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 brcmf_if *ifp)
 	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",
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/8] brcmfmac: fix clearing wowl wake indicators
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
  2016-04-11  9:35 ` [PATCH 1/8] brcmfmac: clear eventmask array before using it Arend van Spriel
@ 2016-04-11  9:35 ` Arend van Spriel
  2016-04-11  9:35 ` [PATCH 3/8] brcmfmac: insert default boardrev in nvram data if missing Arend van Spriel
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <hante.meuleman@broadcom.com>

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>
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index d5c2a27..7486925 100644
--- 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 brcmf_cfg80211_info *cfg,
 	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);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/8] brcmfmac: insert default boardrev in nvram data if missing
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
  2016-04-11  9:35 ` [PATCH 1/8] brcmfmac: clear eventmask array before using it Arend van Spriel
  2016-04-11  9:35 ` [PATCH 2/8] brcmfmac: fix clearing wowl wake indicators Arend van Spriel
@ 2016-04-11  9:35 ` Arend van Spriel
  2016-04-16  8:15   ` Rafał Miłecki
  2016-04-11  9:35 ` [PATCH 4/8] brcmfmac: fix p2p scan abort null pointer exception Arend van Spriel
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <hante.meuleman@broadcom.com>

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>
---
 .../broadcom/brcm80211/brcmfmac/firmware.c         | 30 ++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index 7269056..c7c1e99 100644
--- 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_nvram_handle_key(struct nvram_parser *nvp)
 			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(struct nvram_parser *nvp, u16 domain_nr,
 	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(struct nvram_parser *nvp, u16 domain_nr,
 	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 u8 *data, size_t data_len,
 		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) {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/8] brcmfmac: fix p2p scan abort null pointer exception
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
                   ` (2 preceding siblings ...)
  2016-04-11  9:35 ` [PATCH 3/8] brcmfmac: insert default boardrev in nvram data if missing Arend van Spriel
@ 2016-04-11  9:35 ` Arend van Spriel
  2016-04-11  9:35 ` [PATCH 5/8] brcmfmac: screening firmware event packet Arend van Spriel
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <hante.meuleman@broadcom.com>

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>
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index b5a49e5..9408717 100644
--- 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) ||
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 5/8] brcmfmac: screening firmware event packet
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
                   ` (3 preceding siblings ...)
  2016-04-11  9:35 ` [PATCH 4/8] brcmfmac: fix p2p scan abort null pointer exception Arend van Spriel
@ 2016-04-11  9:35 ` Arend van Spriel
  2016-04-11  9:35 ` [PATCH 6/8] brcmfmac: cleanup ampdu-rx host reorder code Arend van Spriel
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Franky Lin, Arend van Spriel

From: Franky Lin <franky.lin@broadcom.com>

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>
---
 .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h |  4 +-
 .../wireless/broadcom/brcm80211/brcmfmac/core.c    | 46 +++++++++++++++++-----
 .../wireless/broadcom/brcm80211/brcmfmac/core.h    |  3 +-
 .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  | 42 +++++++++++---------
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    | 32 +++++++++++----
 .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c |  2 +-
 6 files changed, 90 insertions(+), 39 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index 8e02a47..31856eb 100644
--- 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, struct pktq *q, struct sk_buff *pkt,
 		      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);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index ff825cd..8a91a517 100644
--- 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 *dev, bool state)
 	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(struct brcmf_if *ifp, u8 *reorder_data,
 	/* 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(struct brcmf_if *ifp, u8 *reorder_data,
 		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(struct brcmf_if *ifp, u8 *reorder_data,
 		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(struct brcmf_if *ifp, u8 *reorder_data,
 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, struct sk_buff *skb)
 	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)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 7bdb6fef..d3497e8 100644
--- 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 brcmf_pub *drvr);
 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);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 9229667..3795354 100644
--- 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_post(struct brcmf_msgbuf *msgbuf)
 }
 
 
-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(struct brcmf_msgbuf *msgbuf, void *buf)
 
 	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 brcmf_msgbuf *msgbuf, void *buf)
 	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 brcmf_msgbuf *msgbuf, void *buf)
 
 	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);
 }
 
 
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 48d7467..4252fa8 100644
--- 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(u8 *swheader)
 	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_sdio *bus, u8 rxseq)
 					   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 brcmf_sdio *bus, uint maxframes)
 		__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;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 869eb82..aa0b2a1 100644
--- 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 urb *urb)
 
 	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);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/8] brcmfmac: cleanup ampdu-rx host reorder code
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
                   ` (4 preceding siblings ...)
  2016-04-11  9:35 ` [PATCH 5/8] brcmfmac: screening firmware event packet Arend van Spriel
@ 2016-04-11  9:35 ` Arend van Spriel
  2016-04-11  9:35 ` [PATCH 7/8] brcmfmac: revise handling events in receive path Arend van Spriel
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

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>
---
 .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c    |   7 +
 .../wireless/broadcom/brcm80211/brcmfmac/core.c    | 214 +--------------------
 .../wireless/broadcom/brcm80211/brcmfmac/core.h    |   4 -
 .../broadcom/brcm80211/brcmfmac/fwsignal.c         | 209 ++++++++++++++++++++
 .../broadcom/brcm80211/brcmfmac/fwsignal.h         |   1 +
 .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  |   4 +
 .../wireless/broadcom/brcm80211/brcmfmac/proto.h   |  16 ++
 7 files changed, 239 insertions(+), 216 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
index 6af658e..288fe90 100644
--- 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 brcmf_pub *drvr, int ifidx,
 {
 }
 
+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_pub *drvr)
 	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;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 8a91a517..a30841b 100644
--- 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, struct sk_buff *skb,
 		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, struct sk_buff *skb, bool handle_evnt)
 		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);
 }
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index d3497e8..394ae05 100644
--- 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 */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index f82c9ab..8a07687 100644
--- 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_support(struct brcmf_if *ifp,
 	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;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
index a36bac1..ef0ad85 100644
--- 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 brcmf_if *ifp);
 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_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 3795354..8c064ab 100644
--- 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 brcmf_pub *drvr, bool do_fws,
 	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 brcmf_pub *drvr)
 	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);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
index d55119d..57531f4 100644
--- 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_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
 {
 	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 */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 7/8] brcmfmac: revise handling events in receive path
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
                   ` (5 preceding siblings ...)
  2016-04-11  9:35 ` [PATCH 6/8] brcmfmac: cleanup ampdu-rx host reorder code Arend van Spriel
@ 2016-04-11  9:35 ` Arend van Spriel
  2016-04-25 10:00   ` Rafał Miłecki
  2016-04-25 10:40   ` Rafał Miłecki
  2016-04-11  9:35 ` [PATCH 8/8] brcmfmac: create common function for handling brcmf_proto_hdrpull() Arend van Spriel
  2016-04-11 11:20 ` [PATCH 0/8] brcmfmac: event handling and other fixes Rafał Miłecki
  8 siblings, 2 replies; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

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>
---
 .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h |  2 +-
 .../wireless/broadcom/brcm80211/brcmfmac/core.c    | 24 +++++++++++-----------
 .../wireless/broadcom/brcm80211/brcmfmac/core.h    |  3 +--
 .../broadcom/brcm80211/brcmfmac/fwsignal.c         |  8 ++++----
 .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  |  2 +-
 5 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index 31856eb..2b24654 100644
--- 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, struct pktq *q, struct sk_buff *pkt,
 		      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);
 
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index a30841b..9b53555 100644
--- 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 *dev, bool state)
 	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, struct sk_buff *skb,
 		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, struct sk_buff *skb, bool handle_evnt)
 		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)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 394ae05..241ee8d 100644
--- 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 brcmf_pub *drvr);
 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);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index 8a07687..5b30922 100644
--- 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 *ifp, struct sk_buff *pkt)
 	/* 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 *ifp, struct sk_buff *pkt)
 		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 *ifp, struct sk_buff *pkt)
 		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 *ifp, struct sk_buff *pkt)
 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);
 	}
 }
 
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 8c064ab..68f1ce0 100644
--- 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 brcmf_msgbuf *msgbuf, void *buf)
 		brcmu_pkt_buf_free_skb(skb);
 		return;
 	}
-	brcmf_netif_rx(ifp, skb, false);
+	brcmf_netif_rx(ifp, skb);
 }
 
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 8/8] brcmfmac: create common function for handling brcmf_proto_hdrpull()
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
                   ` (6 preceding siblings ...)
  2016-04-11  9:35 ` [PATCH 7/8] brcmfmac: revise handling events in receive path Arend van Spriel
@ 2016-04-11  9:35 ` Arend van Spriel
  2016-04-11 11:20 ` [PATCH 0/8] brcmfmac: event handling and other fixes Rafał Miłecki
  8 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2016-04-11  9:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

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>
---
 .../wireless/broadcom/brcm80211/brcmfmac/core.c    | 43 +++++++++++-----------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 9b53555..1b476d1 100644
--- 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, struct sk_buff *skb)
 		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 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);
+	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);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/8] brcmfmac: event handling and other fixes
  2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
                   ` (7 preceding siblings ...)
  2016-04-11  9:35 ` [PATCH 8/8] brcmfmac: create common function for handling brcmf_proto_hdrpull() Arend van Spriel
@ 2016-04-11 11:20 ` Rafał Miłecki
  2016-04-12  8:55   ` Arend van Spriel
  8 siblings, 1 reply; 16+ messages in thread
From: Rafał Miłecki @ 2016-04-11 11:20 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: Kalle Valo, linux-wireless

On 11 April 2016 at 11:35, Arend van Spriel <arend@broadcom.com> wrote:
> This series provides the following:
>
> * avoid unexpected firmware events.
> * allow passing events explicitly for PCIe and SDIO devices.
> * fix issue with boardrev entry in nvram.
> * fix for wowl.
> * fix possible null pointer access upon aborting p2p scan.
>
> The series is intended for v4.7 kernel and applies to the master
> branch of the wireless-drivers-next repository.

Hey Arend,

Unfortunately I'm finding all your recent messages in spam :( It seems
GMail doesn't like something about the Broadcom server:
"Why is this message in Spam? It has a from address in broadcom.com
but has failed broadcom.com's required tests for authentication. Learn
more"
Quoted "Learn more" text links to the:
https://support.google.com/mail/answer/1366858?hl=en-GB&expand=5

Do you think you can point it to sb at Broadcom?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/8] brcmfmac: event handling and other fixes
  2016-04-11 11:20 ` [PATCH 0/8] brcmfmac: event handling and other fixes Rafał Miłecki
@ 2016-04-12  8:55   ` Arend van Spriel
  2016-04-12 11:49     ` Julian Calaby
  0 siblings, 1 reply; 16+ messages in thread
From: Arend van Spriel @ 2016-04-12  8:55 UTC (permalink / raw)
  To: Rafał Miłecki, Arend van Spriel; +Cc: Kalle Valo, linux-wireless

On 11-04-16 13:20, Rafał Miłecki wrote:
> On 11 April 2016 at 11:35, Arend van Spriel <arend@broadcom.com> wrote:
>> This series provides the following:
>>
>> * avoid unexpected firmware events.
>> * allow passing events explicitly for PCIe and SDIO devices.
>> * fix issue with boardrev entry in nvram.
>> * fix for wowl.
>> * fix possible null pointer access upon aborting p2p scan.
>>
>> The series is intended for v4.7 kernel and applies to the master
>> branch of the wireless-drivers-next repository.
> 
> Hey Arend,
> 
> Unfortunately I'm finding all your recent messages in spam :( It seems
> GMail doesn't like something about the Broadcom server:
> "Why is this message in Spam? It has a from address in broadcom.com
> but has failed broadcom.com's required tests for authentication. Learn
> more"
> Quoted "Learn more" text links to the:
> https://support.google.com/mail/answer/1366858?hl=en-GB&expand=5
> 
> Do you think you can point it to sb at Broadcom?

sb? Help me understand this and I may have an appropriate answer :-p

Broadcom actually moved to Google Apps. I am still using my old email
address and smtp server for submitting patches. Maybe that is the issue
here.

Regards,
Arend

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/8] brcmfmac: event handling and other fixes
  2016-04-12  8:55   ` Arend van Spriel
@ 2016-04-12 11:49     ` Julian Calaby
  0 siblings, 0 replies; 16+ messages in thread
From: Julian Calaby @ 2016-04-12 11:49 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: Rafał Miłecki, Arend van Spriel, Kalle Valo, linux-wireless

Hi Arend,

On Tue, Apr 12, 2016 at 6:55 PM, Arend van Spriel
<arend.vanspriel@broadcom.com> wrote:
> On 11-04-16 13:20, Rafał Miłecki wrote:
>> On 11 April 2016 at 11:35, Arend van Spriel <arend@broadcom.com> wrote:
>>> This series provides the following:
>>>
>>> * avoid unexpected firmware events.
>>> * allow passing events explicitly for PCIe and SDIO devices.
>>> * fix issue with boardrev entry in nvram.
>>> * fix for wowl.
>>> * fix possible null pointer access upon aborting p2p scan.
>>>
>>> The series is intended for v4.7 kernel and applies to the master
>>> branch of the wireless-drivers-next repository.
>>
>> Hey Arend,
>>
>> Unfortunately I'm finding all your recent messages in spam :( It seems
>> GMail doesn't like something about the Broadcom server:
>> "Why is this message in Spam? It has a from address in broadcom.com
>> but has failed broadcom.com's required tests for authentication. Learn
>> more"
>> Quoted "Learn more" text links to the:
>> https://support.google.com/mail/answer/1366858?hl=en-GB&expand=5
>>
>> Do you think you can point it to sb at Broadcom?
>
> sb? Help me understand this and I may have an appropriate answer :-p
>
> Broadcom actually moved to Google Apps. I am still using my old email
> address and smtp server for submitting patches. Maybe that is the issue
> here.

That's the issue. IIRC this happens because the emails are missing
some header that authenticates them as actually being from
broadcom.com. (I get this all the time when sending Debian bug reports
through my personal SMTP server.)

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [1/8] brcmfmac: clear eventmask array before using it
  2016-04-11  9:35 ` [PATCH 1/8] brcmfmac: clear eventmask array before using it Arend van Spriel
@ 2016-04-14 13:01   ` Kalle Valo
  0 siblings, 0 replies; 16+ messages in thread
From: Kalle Valo @ 2016-04-14 13:01 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel


> From: Hante Meuleman <hante.meuleman@broadcom.com>
> 
> 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>

Thanks, 8 patches applied to wireless-drivers-next.git:

7fde010d473d brcmfmac: clear eventmask array before using it
28b285a6129d brcmfmac: fix clearing wowl wake indicators
46f2b38a91b0 brcmfmac: insert default boardrev in nvram data if missing
2aec2c9d42aa brcmfmac: fix p2p scan abort null pointer exception
c56caa9db8ab brcmfmac: screening firmware event packet
bbd1f932e7c4 brcmfmac: cleanup ampdu-rx host reorder code
9c349892ccc9 brcmfmac: revise handling events in receive path
c462ebcdfe42 brcmfmac: create common function for handling brcmf_proto_hdrpull()

Kalle Valo

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/8] brcmfmac: insert default boardrev in nvram data if missing
  2016-04-11  9:35 ` [PATCH 3/8] brcmfmac: insert default boardrev in nvram data if missing Arend van Spriel
@ 2016-04-16  8:15   ` Rafał Miłecki
  0 siblings, 0 replies; 16+ messages in thread
From: Rafał Miłecki @ 2016-04-16  8:15 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: Kalle Valo, linux-wireless, Hante Meuleman

On 11 April 2016 at 11:35, Arend van Spriel <arend@broadcom.com> wrote:
> From: Hante Meuleman <hante.meuleman@broadcom.com>
>
> 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>

I needed to wait for a weekend to give it a try. It fixed my problem,
nice work, thanks!
Tested-by: Rafal Milecki <zajec5@gmail.com>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 7/8] brcmfmac: revise handling events in receive path
  2016-04-11  9:35 ` [PATCH 7/8] brcmfmac: revise handling events in receive path Arend van Spriel
@ 2016-04-25 10:00   ` Rafał Miłecki
  2016-04-25 10:40   ` Rafał Miłecki
  1 sibling, 0 replies; 16+ messages in thread
From: Rafał Miłecki @ 2016-04-25 10:00 UTC (permalink / raw)
  To: Arend van Spriel, Hante Meuleman, Pieter-Paul Giesberts, Franky Lin
  Cc: Kalle Valo, linux-wireless, brcm80211 development

[-- Attachment #1: Type: text/plain, Size: 702 bytes --]

On 11 April 2016 at 11:35, Arend van Spriel <arend@broadcom.com> wrote:
> 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>

With this patch applied I'm getting:
Unable to handle kernel NULL pointer dereference at virtual address 000001fc
on the first brcmf_netif_rx call.

I'm using D-Link DIR-885L with 14e4:4365 (BCM4366).

[-- Attachment #2: brcmfmac-null-pointer-dereference.txt --]
[-- Type: text/plain, Size: 13005 bytes --]

[   44.086579] Unable to handle kernel NULL pointer dereference at virtual address 000001fc
[   44.094706] pgd = c0004000
[   44.097415] [000001fc] *pgd=00000000
[   44.101019] Internal error: Oops: 17 [#1] SMP ARM
[   44.105726] Modules linked in: pppoe ppp_async iptable_nat brcmfmac b43 pppox ppp_generic nf_nat_ipv4 nf_conntrack_ipv6 nf_conntrack_ipv4 mac80211 ipt_REJECT ipt_MASQUERADE cfg80211 xt_time xt_tcpudp xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_id xt_conntn
[   44.168765] CPU: 0 PID: 632 Comm: irq/32-brcmf_pc Not tainted 4.4.7 #6
[   44.175305] Hardware name: BCM5301X
[   44.178799] task: c7a16400 ti: c73de000 task.ti: c73de000
[   44.184215] PC is at get_rps_cpu+0x24/0x330
[   44.188410] LR is at netif_rx_internal+0x8c/0xbc
[   44.193038] pc : [<c0251284>]    lr : [<c0253ff8>]    psr: 60000013
[   44.193038] sp : c73dfdc8  ip : c73dfe18  fp : c73dfe14
[   44.204543] r10: 00000000  r9 : c8ce5000  r8 : c8ce5000
[   44.209774] r7 : c7a08e80  r6 : 00000000  r5 : c047c848  r4 : c797a3c0
[   44.216311] r3 : 00000000  r2 : c73dfe24  r1 : c797a3c0  r0 : 00000000
[   44.222849] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[   44.229995] Control: 10c5387d  Table: 073d004a  DAC: 00000051
[   44.235748] Process irq/32-brcmf_pc (pid: 632, stack limit = 0xc73de190)
[   44.242459] Stack: (0xc73dfdc8 to 0xc73e0000)
[   44.246821] fdc0:                   c6ec8320 00000000 c73dfe14 c73dfe24 c0019c3c c009c93c
[   44.255012] fde0: c047ecc4 c04bd550 c7a08e00 c797a3c0 c047c848 c797a3c0 c7a08e80 c8ce5000
[   44.263211] fe00: c8ce5000 00000000 c73dfe44 c73dfe18 c0253ff8 c025126c c000acf4 c73dfe3c
[   44.271401] fe20: c001a760 c73dfe28 c71d8410 c71d8000 c797a3c0 00000000 c73dfe5c c73dfe48
[   44.279592] fe40: c0254074 c0253f78 c797a3c0 00000000 c73dfe74 c73dfe60 bf21f40c c0254070
[   44.287791] fe60: c712a9c0 00000000 c73dfebc c73dfe78 bf224ea4 bf21f36c c7a16400 c6dd1840
[   44.295981] fe80: 00000000 00000014 c0477840 00019e7c c73dfebc c712a9c0 00010000 c787e3c0
[   44.304172] fea0: c0057bb0 c719c1e4 c047f842 00000000 c73dfedc c73dfec0 bf224f8c bf224a38
[   44.312372] fec0: c7ad7000 00010000 c787e3c0 c0057bb0 c73dff04 c73dfee0 bf229608 bf224f6c
[   44.320570] fee0: c719c1c0 c719c1c0 c787e3c0 c0057bb0 c719c1e4 c047f842 c73dff24 c73dff08
[   44.328761] ff00: c0057bd4 bf229450 c787e3c0 c719c1c0 c73de000 c0057bb0 c73dff5c c73dff28
[   44.336951] ff20: c0057eb8 c0057bbc 00000000 c0057d0c 00000000 c7244d80 00000000 c719c1c0
[   44.345141] ff40: c0057dc0 00000000 00000000 00000000 c73dffac c73dff60 c00393a4 c0057dcc
[   44.353332] ff60: c73dff8c 00000000 c00228cc c719c1c0 00000000 00000000 c73dff78 c73dff78
[   44.361522] ff80: 00000000 00000000 c73dff88 c73dff88 c7244d80 c00392c4 00000000 00000000
[   44.369712] ffa0: 00000000 c73dffb0 c00097b8 c00392d0 00000000 00000000 00000000 00000000
[   44.377903] ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   44.386094] ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 c73dfff4 00000000
[   44.394281] Backtrace: 
[   44.396743] [<c0251260>] (get_rps_cpu) from [<c0253ff8>] (netif_rx_internal+0x8c/0xbc)
[   44.404674]  r10:00000000 r9:c8ce5000 r8:c8ce5000 r7:c7a08e80 r6:c797a3c0 r5:c047c848
[   44.412559]  r4:c797a3c0
[   44.415106] [<c0253f6c>] (netif_rx_internal) from [<c0254074>] (netif_rx_ni+0x10/0x44)
[   44.423039]  r5:00000000 r4:c797a3c0
[   44.426665] [<c0254064>] (netif_rx_ni) from [<bf21f40c>] (brcmf_netif_rx+0xac/0xbc [brcmfmac])
[   44.435294]  r5:00000000 r4:c797a3c0
[   44.438909] [<bf21f360>] (brcmf_netif_rx [brcmfmac]) from [<bf224ea4>] (brcmf_msgbuf_txdata+0x5c0/0x67c [brcmfmac])
[   44.449360]  r5:00000000 r4:c712a9c0
[   44.452973] [<bf224a2c>] (brcmf_msgbuf_txdata [brcmfmac]) from [<bf224f8c>] (brcmf_proto_msgbuf_rx_trigger+0x2c/0xd0 [brcmfmac])
[   44.464557]  r10:00000000 r9:c047f842 r8:c719c1e4 r7:c0057bb0 r6:c787e3c0 r5:00010000
[   44.472443]  r4:c712a9c0
[   44.475002] [<bf224f60>] (brcmf_proto_msgbuf_rx_trigger [brcmfmac]) from [<bf229608>] (brcmf_pcie_isr_thread+0x1c4/0x238 [brcmfmac])
[   44.486935]  r7:c0057bb0 r6:c787e3c0 r5:00010000 r4:c7ad7000
[   44.492648] [<bf229444>] (brcmf_pcie_isr_thread [brcmfmac]) from [<c0057bd4>] (irq_thread_fn+0x24/0x3c)
[   44.502054]  r9:c047f842 r8:c719c1e4 r7:c0057bb0 r6:c787e3c0 r5:c719c1c0 r4:c719c1c0
[   44.509857] [<c0057bb0>] (irq_thread_fn) from [<c0057eb8>] (irq_thread+0xf8/0x1e4)
[   44.517442]  r7:c0057bb0 r6:c73de000 r5:c719c1c0 r4:c787e3c0
[   44.523150] [<c0057dc0>] (irq_thread) from [<c00393a4>] (kthread+0xe0/0xf4)
[   44.530124]  r10:00000000 r9:00000000 r8:00000000 r7:c0057dc0 r6:c719c1c0 r5:00000000
[   44.538010]  r4:c7244d80
[   44.540557] [<c00392c4>] (kthread) from [<c00097b8>] (ret_from_fork+0x14/0x3c)
[   44.547793]  r7:00000000 r6:00000000 r5:c00392c4 r4:c7244d80
[   44.553498] Code: e50b2040 e1a06000 e3530000 e1a04001 (e59021fc) 
[   44.559625] ---[ end trace fbc5940e895b0890 ]---
[   44.564276] Unable to handle kernel paging request at virtual address ffffffec
[   44.571526] pgd = c0004000
[   44.574237] [ffffffec] *pgd=07fff841, *pte=00000000, *ppte=00000000
[   44.580550] Internal error: Oops: 27 [#2] SMP ARM
[   44.585264] Modules linked in: pppoe ppp_async iptable_nat brcmfmac b43 pppox ppp_generic nf_nat_ipv4 nf_conntrack_ipv6 nf_conntrack_ipv4 mac80211 ipt_REJECT ipt_MASQUERADE cfg80211 xt_time xt_tcpudp xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_id xt_conntn
[   44.648302] CPU: 0 PID: 632 Comm: irq/32-brcmf_pc Tainted: G      D         4.4.7 #6
[   44.656062] Hardware name: BCM5301X
[   44.659554] task: c7a16400 ti: c73de000 task.ti: c73de000
[   44.664962] PC is at kthread_data+0x10/0x18
[   44.669155] LR is at irq_thread_dtor+0x58/0xb4
[   44.673603] pc : [<c0039844>]    lr : [<c0057d64>]    psr: 20000113
[   44.673603] sp : c73dfbd0  ip : c73dfbe0  fp : c73dfbdc
[   44.685109] r10: 00000000  r9 : c0480878  r8 : c73dfc18
[   44.690340] r7 : c7a16400  r6 : 00000000  r5 : c7a16400  r4 : c7a16400
[   44.696876] r3 : 00000000  r2 : 0000007c  r1 : 00000000  r0 : c7a16400
[   44.703414] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[   44.710559] Control: 10c5387d  Table: 073d004a  DAC: 00000051
[   44.716313] Process irq/32-brcmf_pc (pid: 632, stack limit = 0xc73de190)
[   44.723023] Stack: (0xc73dfbd0 to 0xc73e0000)
[   44.727386] fbc0:                                     c73dfbf4 c73dfbe0 c0057d64 c0039840
[   44.735586] fbe0: c7a16400 c04940dc c73dfc14 c73dfbf8 c0037ca8 c0057d18 c7a16400 00000000
[   44.743785] fc00: c04935ec c7a16400 c73dfc34 c73dfc18 c002248c c0037c14 c73dfc34 c73dfc28
[   44.751985] fc20: c0021538 c7a16400 c73dfc74 c73dfc38 c00174a8 c002213c c73de190 0000000b
[   44.760183] fc40: c001ab84 60000113 c040ca10 000001fc c73dfd78 00000017 00000000 c7a16400
[   44.768383] fc60: 00000000 00000017 c73dfc8c c73dfc78 c001ad04 c001725c 00000017 000001fc
[   44.776582] fc80: c73dfccc c73dfc90 c001afa0 c001acb4 00000001 00000000 c73dfc94 00000003
[   44.784772] fca0: c73dfcd4 00000017 000001fc c0480d58 c73dfd78 c8ce5000 c8ce5000 00000000
[   44.792972] fcc0: c73dfd74 c73dfcd0 c00092ec c001ad30 c0088290 c0086198 00000141 c6dd1840
[   44.801170] fce0: c73dfd14 00000104 c047f780 c047ee04 fffffff8 00000000 00000008 ffffffff
[   44.809361] fd00: 40000093 00000001 c6edf580 00000000 00000000 00000000 c047f788 020b5220
[   44.817551] fd20: c73dfdac c047f780 00000003 02095220 c6acc000 c6acc000 00000001 a0000013
[   44.825751] fd40: c73dfdcc c73dfd50 00000740 80100008 c7a049c0 c7a049c0 c0251284 60000013
[   44.833949] fd60: ffffffff c73dfdac c73dfe14 c73dfd78 c000a000 c00092bc 00000000 c797a3c0
[   44.842140] fd80: c73dfe24 00000000 c797a3c0 c047c848 00000000 c7a08e80 c8ce5000 c8ce5000
[   44.850330] fda0: 00000000 c73dfe14 c73dfe18 c73dfdc8 c0253ff8 c0251284 60000013 ffffffff
[   44.858521] fdc0: 00000051 00000800 c6ec8320 00000000 c73dfe14 c73dfe24 c0019c3c c009c93c
[   44.866711] fde0: c047ecc4 c04bd550 c7a08e00 c797a3c0 c047c848 c797a3c0 c7a08e80 c8ce5000
[   44.874902] fe00: c8ce5000 00000000 c73dfe44 c73dfe18 c0253ff8 c025126c c000acf4 c73dfe3c
[   44.883102] fe20: c001a760 c73dfe28 c71d8410 c71d8000 c797a3c0 00000000 c73dfe5c c73dfe48
[   44.891300] fe40: c0254074 c0253f78 c797a3c0 00000000 c73dfe74 c73dfe60 bf21f40c c0254070
[   44.899491] fe60: c712a9c0 00000000 c73dfebc c73dfe78 bf224ea4 bf21f36c c7a16400 c6dd1840
[   44.907681] fe80: 00000000 00000014 c0477840 00019e7c c73dfebc c712a9c0 00010000 c787e3c0
[   44.915881] fea0: c0057bb0 c719c1e4 c047f842 00000000 c73dfedc c73dfec0 bf224f8c bf224a38
[   44.924079] fec0: c7ad7000 00010000 c787e3c0 c0057bb0 c73dff04 c73dfee0 bf229608 bf224f6c
[   44.932270] fee0: c719c1c0 c719c1c0 c787e3c0 c0057bb0 c719c1e4 c047f842 c73dff24 c73dff08
[   44.940470] ff00: c0057bd4 bf229450 c787e3c0 c719c1c0 c73de000 c0057bb0 c73dff5c c73dff28
[   44.948668] ff20: c0057eb8 c0057bbc 00000000 c0057d0c 00000000 c7244d80 00000000 c719c1c0
[   44.956858] ff40: c0057dc0 00000000 00000000 00000000 c73dffac c73dff60 c00393a4 c0057dcc
[   44.965049] ff60: c73dff8c 00000000 c00228cc c719c1c0 00000000 00000000 c73dff78 c73dff78
[   44.973240] ff80: 00000001 00010001 c73dff88 c73dff88 c7244d80 c00392c4 00000000 00000000
[   44.981438] ffa0: 00000000 c73dffb0 c00097b8 c00392d0 00000000 00000000 00000000 00000000
[   44.989629] ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   44.997828] ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 c73dfff4 00000000
[   45.006024] Backtrace: 
[   45.008483] [<c0039834>] (kthread_data) from [<c0057d64>] (irq_thread_dtor+0x58/0xb4)
[   45.016344] [<c0057d0c>] (irq_thread_dtor) from [<c0037ca8>] (task_work_run+0xa0/0xb4)
[   45.024277]  r5:c04940dc r4:c7a16400
[   45.027877] [<c0037c08>] (task_work_run) from [<c002248c>] (do_exit+0x35c/0x7cc)
[   45.035287]  r7:c7a16400 r6:c04935ec r5:00000000 r4:c7a16400
[   45.041003] [<c0022130>] (do_exit) from [<c00174a8>] (die+0x258/0x2dc)
[   45.047542]  r7:c7a16400
[   45.050093] [<c0017250>] (die) from [<c001ad04>] (__do_kernel_fault.part.0+0x5c/0x7c)
[   45.057935]  r10:00000017 r9:00000000 r8:c7a16400 r7:00000000 r6:00000017 r5:c73dfd78
[   45.065820]  r4:000001fc
[   45.068366] [<c001aca8>] (__do_kernel_fault.part.0) from [<c001afa0>] (do_page_fault+0x27c/0x294)
[   45.077257]  r7:000001fc r4:00000017
[   45.080856] [<c001ad24>] (do_page_fault) from [<c00092ec>] (do_DataAbort+0x3c/0xbc)
[   45.088529]  r10:00000000 r9:c8ce5000 r8:c8ce5000 r7:c73dfd78 r6:c0480d58 r5:000001fc
[   45.096415]  r4:00000017
[   45.098961] [<c00092b0>] (do_DataAbort) from [<c000a000>] (__dabt_svc+0x40/0x60)
[   45.106373] Exception stack(0xc73dfd78 to 0xc73dfdc0)
[   45.111431] fd60:                                                       00000000 c797a3c0
[   45.119624] fd80: c73dfe24 00000000 c797a3c0 c047c848 00000000 c7a08e80 c8ce5000 c8ce5000
[   45.127822] fda0: 00000000 c73dfe14 c73dfe18 c73dfdc8 c0253ff8 c0251284 60000013 ffffffff
[   45.136009]  r7:c73dfdac r6:ffffffff r5:60000013 r4:c0251284
[   45.141724] [<c0251260>] (get_rps_cpu) from [<c0253ff8>] (netif_rx_internal+0x8c/0xbc)
[   45.149658]  r10:00000000 r9:c8ce5000 r8:c8ce5000 r7:c7a08e80 r6:c797a3c0 r5:c047c848
[   45.157543]  r4:c797a3c0
[   45.160089] [<c0253f6c>] (netif_rx_internal) from [<c0254074>] (netif_rx_ni+0x10/0x44)
[   45.168023]  r5:00000000 r4:c797a3c0
[   45.171645] [<c0254064>] (netif_rx_ni) from [<bf21f40c>] (brcmf_netif_rx+0xac/0xbc [brcmfmac])
[   45.180270]  r5:00000000 r4:c797a3c0
[   45.183884] [<bf21f360>] (brcmf_netif_rx [brcmfmac]) from [<bf224ea4>] (brcmf_msgbuf_txdata+0x5c0/0x67c [brcmfmac])
[   45.194334]  r5:00000000 r4:c712a9c0
[   45.197947] [<bf224a2c>] (brcmf_msgbuf_txdata [brcmfmac]) from [<bf224f8c>] (brcmf_proto_msgbuf_rx_trigger+0x2c/0xd0 [brcmfmac])
[   45.209532]  r10:00000000 r9:c047f842 r8:c719c1e4 r7:c0057bb0 r6:c787e3c0 r5:00010000
[   45.217418]  r4:c712a9c0
[   45.219977] [<bf224f60>] (brcmf_proto_msgbuf_rx_trigger [brcmfmac]) from [<bf229608>] (brcmf_pcie_isr_thread+0x1c4/0x238 [brcmfmac])
[   45.231910]  r7:c0057bb0 r6:c787e3c0 r5:00010000 r4:c7ad7000
[   45.237622] [<bf229444>] (brcmf_pcie_isr_thread [brcmfmac]) from [<c0057bd4>] (irq_thread_fn+0x24/0x3c)
[   45.247028]  r9:c047f842 r8:c719c1e4 r7:c0057bb0 r6:c787e3c0 r5:c719c1c0 r4:c719c1c0
[   45.254831] [<c0057bb0>] (irq_thread_fn) from [<c0057eb8>] (irq_thread+0xf8/0x1e4)
[   45.262408]  r7:c0057bb0 r6:c73de000 r5:c719c1c0 r4:c787e3c0
[   45.268115] [<c0057dc0>] (irq_thread) from [<c00393a4>] (kthread+0xe0/0xf4)
[   45.275091]  r10:00000000 r9:00000000 r8:00000000 r7:c0057dc0 r6:c719c1c0 r5:00000000
[   45.282976]  r4:c7244d80
[   45.285522] [<c00392c4>] (kthread) from [<c00097b8>] (ret_from_fork+0x14/0x3c)
[   45.292760]  r7:00000000 r6:00000000 r5:c00392c4 r4:c7244d80
[   45.298464] Code: e1a0c00d e92dd800 e24cb004 e590325c (e5130014) 
[   45.304595] ---[ end trace fbc5940e895b0891 ]---
[   45.309242] Fixing recursive fault but reboot is needed!

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 7/8] brcmfmac: revise handling events in receive path
  2016-04-11  9:35 ` [PATCH 7/8] brcmfmac: revise handling events in receive path Arend van Spriel
  2016-04-25 10:00   ` Rafał Miłecki
@ 2016-04-25 10:40   ` Rafał Miłecki
  1 sibling, 0 replies; 16+ messages in thread
From: Rafał Miłecki @ 2016-04-25 10:40 UTC (permalink / raw)
  To: Arend van Spriel, Hante Meuleman, Pieter-Paul Giesberts, Franky Lin
  Cc: Kalle Valo, linux-wireless, brcm80211 development

On 11 April 2016 at 11:35, Arend van Spriel <arend@broadcom.com> wrote:
> @@ -298,18 +298,11 @@ void brcmf_txflowblock(struct device *dev, bool state)
>         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);

With this change every brcmf_netif_rx caller has to call
eth_type_trans on its own.


> @@ -348,10 +341,17 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt)
>                 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);
> +       }
>  }

You added a call to eth_type_trans in brcmf_rx_frame which is used by
USB and SDIO. My guess it you wanted to avoid having duplicated
eth_type_trans call in brcmf_proto_rxreorder.
However you forgot about calling eth_type_trans from
brcmf_msgbuf_process_rx_complete (used by PCI). So to fix this
regression you'll need another call to eth_type_trans anyway.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2016-04-25 10:40 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-11  9:35 [PATCH 0/8] brcmfmac: event handling and other fixes Arend van Spriel
2016-04-11  9:35 ` [PATCH 1/8] brcmfmac: clear eventmask array before using it Arend van Spriel
2016-04-14 13:01   ` [1/8] " Kalle Valo
2016-04-11  9:35 ` [PATCH 2/8] brcmfmac: fix clearing wowl wake indicators Arend van Spriel
2016-04-11  9:35 ` [PATCH 3/8] brcmfmac: insert default boardrev in nvram data if missing Arend van Spriel
2016-04-16  8:15   ` Rafał Miłecki
2016-04-11  9:35 ` [PATCH 4/8] brcmfmac: fix p2p scan abort null pointer exception Arend van Spriel
2016-04-11  9:35 ` [PATCH 5/8] brcmfmac: screening firmware event packet Arend van Spriel
2016-04-11  9:35 ` [PATCH 6/8] brcmfmac: cleanup ampdu-rx host reorder code Arend van Spriel
2016-04-11  9:35 ` [PATCH 7/8] brcmfmac: revise handling events in receive path Arend van Spriel
2016-04-25 10:00   ` Rafał Miłecki
2016-04-25 10:40   ` Rafał Miłecki
2016-04-11  9:35 ` [PATCH 8/8] brcmfmac: create common function for handling brcmf_proto_hdrpull() Arend van Spriel
2016-04-11 11:20 ` [PATCH 0/8] brcmfmac: event handling and other fixes Rafał Miłecki
2016-04-12  8:55   ` Arend van Spriel
2016-04-12 11:49     ` Julian Calaby

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.