All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] brcm80211: sdio suspend rework and other fixes
@ 2015-01-25 19:31 Arend van Spriel
  2015-01-25 19:31 ` [PATCH 01/14] brcmfmac: Relax scheduling of msgbuf worker on high throughput Arend van Spriel
                   ` (13 more replies)
  0 siblings, 14 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

This patch series reworks some code in SDIO part of the brcmfmac
driver related to suspend/resume that were found doing stress testing.
In PCIe part scheduling of worker thread needed to be relaxed.
Other changes involve minor fixes and exposing firmware revision
information to user-space, ie. ethtool.

This series is intended for v3.20 and applies to the master branch
of the wireless-drivers-next repository.

Arend van Spriel (9):
  brcmfmac: pass DEAUTH/DISASSOC reason code to user-space
  brcmfmac: wait for driver to go idle during suspend
  brcmfmac: do not load firmware when device is already running
  brcmutil: use define for boardrev string function
  brcmfmac: determine chip info when not provided by bus layer
  brcmfmac: always obtain device revision info upon intialization
  brcmfmac: show firmware release info in ethtool driver info
  brcmfmac: store revinfo retrieval result
  brcmfmac: fix nvram processing

Hante Meuleman (5):
  brcmfmac: Relax scheduling of msgbuf worker on high throughput.
  brcmfmac: prevent possible deadlock on resuming SDIO device.
  brcmfmac: use SDIO DPC for control frames.
  brcmfmac: SDIO: avoid using bus state for private states.
  brcmfmac: Reopen netdev queue on bus state data.

 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |  70 ++++-----
 drivers/net/wireless/brcm80211/brcmfmac/bus.h      |  24 +--
 drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c |  31 +++-
 drivers/net/wireless/brcm80211/brcmfmac/common.c   |  31 +++-
 .../net/wireless/brcm80211/brcmfmac/commonring.h   |   2 +
 drivers/net/wireless/brcm80211/brcmfmac/core.c     |  39 ++++-
 drivers/net/wireless/brcm80211/brcmfmac/core.h     |  30 ++++
 drivers/net/wireless/brcm80211/brcmfmac/firmware.c |   6 +-
 drivers/net/wireless/brcm80211/brcmfmac/fwil.c     |   2 +-
 drivers/net/wireless/brcm80211/brcmfmac/fwil.h     |   1 +
 .../net/wireless/brcm80211/brcmfmac/fwil_types.h   |  41 +++++
 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c   |  30 +++-
 drivers/net/wireless/brcm80211/brcmfmac/pcie.c     |   2 +-
 drivers/net/wireless/brcm80211/brcmfmac/sdio.c     | 168 ++++++++++-----------
 drivers/net/wireless/brcm80211/brcmfmac/sdio.h     |  12 +-
 drivers/net/wireless/brcm80211/brcmfmac/usb.c      |   4 +-
 drivers/net/wireless/brcm80211/brcmsmac/debug.c    |   2 +-
 drivers/net/wireless/brcm80211/brcmutil/utils.c    |  32 +++-
 .../net/wireless/brcm80211/include/brcmu_utils.h   |   4 +
 19 files changed, 348 insertions(+), 183 deletions(-)

-- 
1.9.1


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

* [PATCH 01/14] brcmfmac: Relax scheduling of msgbuf worker on high throughput.
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-29  8:01   ` [01/14] brcmfmac: Relax scheduling of msgbuf worker on highthroughput Kalle Valo
  2015-01-25 19:31 ` [PATCH 02/14] brcmfmac: prevent possible deadlock on resuming SDIO device Arend van Spriel
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <meuleman@broadcom.com>

On every tx the flow worker is triggered. When running high
throughput data this causes an excessive amount of times the worker
gets activated. This patch starts scheduling the worker more relaxed
once outstanding tx has reached a certain depth.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/commonring.h   |  2 ++
 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c   | 30 +++++++++++++++++-----
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
index 002336e..3d40401 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
@@ -37,6 +37,8 @@ struct brcmf_commonring {
 	unsigned long flags;
 	bool inited;
 	bool was_full;
+
+	atomic_t outstanding_tx;
 };
 
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
index ee147f5..6262612 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
@@ -73,6 +73,8 @@
 #define BRCMF_MSGBUF_TX_FLUSH_CNT1		32
 #define BRCMF_MSGBUF_TX_FLUSH_CNT2		96
 
+#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS	64
+#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS	32
 
 struct msgbuf_common_hdr {
 	u8				msgtype;
@@ -749,6 +751,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid)
 		tx_msghdr->metadata_buf_len = 0;
 		tx_msghdr->metadata_buf_addr.high_addr = 0;
 		tx_msghdr->metadata_buf_addr.low_addr = 0;
+		atomic_inc(&commonring->outstanding_tx);
 		if (count >= BRCMF_MSGBUF_TX_FLUSH_CNT2) {
 			brcmf_commonring_write_complete(commonring);
 			count = 0;
@@ -773,10 +776,16 @@ static void brcmf_msgbuf_txflow_worker(struct work_struct *worker)
 }
 
 
-static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid)
+static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,
+					bool force)
 {
+	struct brcmf_commonring *commonring;
+
 	set_bit(flowid, msgbuf->flow_map);
-	queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
+	commonring = msgbuf->flowrings[flowid];
+	if ((force) || (atomic_read(&commonring->outstanding_tx) <
+			BRCMF_MSGBUF_DELAY_TXWORKER_THRS))
+		queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
 
 	return 0;
 }
@@ -797,7 +806,7 @@ static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
 			return -ENOMEM;
 	}
 	brcmf_flowring_enqueue(flow, flowid, skb);
-	brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+	brcmf_msgbuf_schedule_txdata(msgbuf, flowid, false);
 
 	return 0;
 }
@@ -854,6 +863,7 @@ brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf)
 static void
 brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
 {
+	struct brcmf_commonring *commonring;
 	struct msgbuf_tx_status *tx_status;
 	u32 idx;
 	struct sk_buff *skb;
@@ -871,6 +881,8 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
 	}
 
 	set_bit(flowid, msgbuf->txstatus_done_map);
+	commonring = msgbuf->flowrings[flowid];
+	atomic_dec(&commonring->outstanding_tx);
 
 	brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true);
 }
@@ -1181,7 +1193,7 @@ brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf,
 
 	brcmf_flowring_open(msgbuf->flow, flowid);
 
-	brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+	brcmf_msgbuf_schedule_txdata(msgbuf, flowid, true);
 }
 
 
@@ -1280,8 +1292,10 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev)
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 	struct brcmf_pub *drvr = bus_if->drvr;
 	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct brcmf_commonring *commonring;
 	void *buf;
 	u32 flowid;
+	int qlen;
 
 	buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
 	brcmf_msgbuf_process_rx(msgbuf, buf);
@@ -1293,8 +1307,12 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev)
 	for_each_set_bit(flowid, msgbuf->txstatus_done_map,
 			 msgbuf->nrof_flowrings) {
 		clear_bit(flowid, msgbuf->txstatus_done_map);
-		if (brcmf_flowring_qlen(msgbuf->flow, flowid))
-			brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+		commonring = msgbuf->flowrings[flowid];
+		qlen = brcmf_flowring_qlen(msgbuf->flow, flowid);
+		if ((qlen > BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) ||
+		    ((qlen) && (atomic_read(&commonring->outstanding_tx) <
+				BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS)))
+			brcmf_msgbuf_schedule_txdata(msgbuf, flowid, true);
 	}
 
 	return 0;
-- 
1.9.1


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

* [PATCH 02/14] brcmfmac: prevent possible deadlock on resuming SDIO device.
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
  2015-01-25 19:31 ` [PATCH 01/14] brcmfmac: Relax scheduling of msgbuf worker on high throughput Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 03/14] brcmfmac: use SDIO DPC for control frames Arend van Spriel
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <meuleman@broadcom.com>

When the system is resumed a deadlock can occur when DPC gets
entered before resume is complete. This patch fixes this by
properly checking the suspend state outside the claim_host code
block.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 33 ------------------------
 drivers/net/wireless/brcm80211/brcmfmac/sdio.c   | 18 +++++++++++++
 drivers/net/wireless/brcm80211/brcmfmac/sdio.h   |  2 --
 3 files changed, 18 insertions(+), 35 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 00ba90b8..8ba60f6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -97,25 +97,6 @@ static void brcmf_sdiod_dummy_irqhandler(struct sdio_func *func)
 {
 }
 
-static bool brcmf_sdiod_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
-{
-	bool is_err = false;
-#ifdef CONFIG_PM_SLEEP
-	is_err = atomic_read(&sdiodev->suspend);
-#endif
-	return is_err;
-}
-
-static void brcmf_sdiod_pm_resume_wait(struct brcmf_sdio_dev *sdiodev,
-				       wait_queue_head_t *wq)
-{
-#ifdef CONFIG_PM_SLEEP
-	int retry = 0;
-	while (atomic_read(&sdiodev->suspend) && retry++ != 30)
-		wait_event_timeout(*wq, false, HZ/100);
-#endif
-}
-
 int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
 {
 	int ret = 0;
@@ -244,10 +225,6 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
 	brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
 		  write, fn, addr, regsz);
 
-	brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
-	if (brcmf_sdiod_pm_resume_error(sdiodev))
-		return -EIO;
-
 	/* only allow byte access on F0 */
 	if (WARN_ON(regsz > 1 && !fn))
 		return -EINVAL;
@@ -462,10 +439,6 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 	unsigned int req_sz;
 	int err;
 
-	brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
-	if (brcmf_sdiod_pm_resume_error(sdiodev))
-		return -EIO;
-
 	/* Single skb use the standard mmc interface */
 	req_sz = pkt->len + 3;
 	req_sz &= (uint)~3;
@@ -516,10 +489,6 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
 	if (!pktlist->qlen)
 		return -EINVAL;
 
-	brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
-	if (brcmf_sdiod_pm_resume_error(sdiodev))
-		return -EIO;
-
 	target_list = pktlist;
 	/* for host with broken sg support, prepare a page aligned list */
 	__skb_queue_head_init(&local_list);
@@ -1077,8 +1046,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
 #endif
 
 	atomic_set(&sdiodev->suspend, false);
-	init_waitqueue_head(&sdiodev->request_word_wait);
-	init_waitqueue_head(&sdiodev->request_buffer_wait);
 
 	brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
 	err = brcmf_sdiod_probe(sdiodev);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index 99a3776..2c4f0cc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -2609,6 +2609,21 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
 	return ret;
 }
 
+static int brcmf_sdio_pm_resume_wait(struct brcmf_sdio_dev *sdiodev)
+{
+#ifdef CONFIG_PM_SLEEP
+	int retry;
+
+	/* Wait for possible resume to complete */
+	retry = 0;
+	while ((atomic_read(&sdiodev->suspend)) && (retry++ != 50))
+		msleep(20);
+	if (atomic_read(&sdiodev->suspend))
+		return -EIO;
+#endif
+	return 0;
+}
+
 static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
 {
 	u32 newstatus = 0;
@@ -2619,6 +2634,9 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
 
 	brcmf_dbg(TRACE, "Enter\n");
 
+	if (brcmf_sdio_pm_resume_wait(bus->sdiodev))
+		return;
+
 	sdio_claim_host(bus->sdiodev->func[1]);
 
 	/* If waiting for HTAVAIL, check status */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
index 8eb4262..82494df 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
@@ -169,8 +169,6 @@ struct brcmf_sdio_dev {
 	u32 sbwad;			/* Save backplane window address */
 	struct brcmf_sdio *bus;
 	atomic_t suspend;		/* suspend flag */
-	wait_queue_head_t request_word_wait;
-	wait_queue_head_t request_buffer_wait;
 	struct device *dev;
 	struct brcmf_bus *bus_if;
 	struct brcmfmac_sdio_platform_data *pdata;
-- 
1.9.1


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

* [PATCH 03/14] brcmfmac: use SDIO DPC for control frames.
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
  2015-01-25 19:31 ` [PATCH 01/14] brcmfmac: Relax scheduling of msgbuf worker on high throughput Arend van Spriel
  2015-01-25 19:31 ` [PATCH 02/14] brcmfmac: prevent possible deadlock on resuming SDIO device Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 04/14] brcmfmac: pass DEAUTH/DISASSOC reason code to user-space Arend van Spriel
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <meuleman@broadcom.com>

Control frames are normally handled outside DPC, but sometimes
within DPC. To simplify code always handle control within DPC.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/sdio.c | 87 ++++++++++----------------
 1 file changed, 33 insertions(+), 54 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index 2c4f0cc..b4f5fe5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -44,7 +44,8 @@
 #include "chip.h"
 #include "firmware.h"
 
-#define DCMD_RESP_TIMEOUT  2000	/* In milli second */
+#define DCMD_RESP_TIMEOUT	2000	/* In milli second */
+#define CTL_DONE_TIMEOUT	2000	/* In milli second */
 
 #ifdef DEBUG
 
@@ -495,9 +496,9 @@ struct brcmf_sdio {
 	u8 *ctrl_frame_buf;
 	u16 ctrl_frame_len;
 	bool ctrl_frame_stat;
+	int ctrl_frame_err;
 
 	spinlock_t txq_lock;		/* protect bus->txq */
-	struct semaphore tx_seq_lock;	/* protect bus->tx_seq */
 	wait_queue_head_t ctrl_wait;
 	wait_queue_head_t dcmd_resp_wait;
 
@@ -2376,8 +2377,6 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 	/* Send frames until the limit or some other event */
 	for (cnt = 0; (cnt < maxframes) && data_ok(bus);) {
 		pkt_num = 1;
-		if (down_interruptible(&bus->tx_seq_lock))
-			return cnt;
 		if (bus->txglom)
 			pkt_num = min_t(u8, bus->tx_max - bus->tx_seq,
 					bus->sdiodev->txglomsz);
@@ -2393,13 +2392,10 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 			__skb_queue_tail(&pktq, pkt);
 		}
 		spin_unlock_bh(&bus->txq_lock);
-		if (i == 0) {
-			up(&bus->tx_seq_lock);
+		if (i == 0)
 			break;
-		}
 
 		ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL);
-		up(&bus->tx_seq_lock);
 
 		cnt += i;
 
@@ -2743,17 +2739,14 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
 	brcmf_sdio_clrintr(bus);
 
 	if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
-	    (down_interruptible(&bus->tx_seq_lock) == 0)) {
-		if (data_ok(bus)) {
-			sdio_claim_host(bus->sdiodev->func[1]);
-			err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
-						      bus->ctrl_frame_len);
-			sdio_release_host(bus->sdiodev->func[1]);
-
-			bus->ctrl_frame_stat = false;
-			brcmf_sdio_wait_event_wakeup(bus);
-		}
-		up(&bus->tx_seq_lock);
+	    data_ok(bus)) {
+		sdio_claim_host(bus->sdiodev->func[1]);
+		err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
+					      bus->ctrl_frame_len);
+		sdio_release_host(bus->sdiodev->func[1]);
+		bus->ctrl_frame_err = err;
+		bus->ctrl_frame_stat = false;
+		brcmf_sdio_wait_event_wakeup(bus);
 	}
 	/* Send queued frames (limit 1 if rx may still be pending) */
 	if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) &&
@@ -2965,43 +2958,30 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	struct brcmf_sdio *bus = sdiodev->bus;
-	int ret = -1;
+	int ret;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
-	if (down_interruptible(&bus->tx_seq_lock))
-		return -EINTR;
-
-	if (!data_ok(bus)) {
-		brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n",
-			  bus->tx_max, bus->tx_seq);
-		up(&bus->tx_seq_lock);
-		/* Send from dpc */
-		bus->ctrl_frame_buf = msg;
-		bus->ctrl_frame_len = msglen;
-		bus->ctrl_frame_stat = true;
-
-		wait_event_interruptible_timeout(bus->ctrl_wait,
-						 !bus->ctrl_frame_stat,
-						 msecs_to_jiffies(2000));
-
-		if (!bus->ctrl_frame_stat) {
-			brcmf_dbg(SDIO, "ctrl_frame_stat == false\n");
-			ret = 0;
-		} else {
-			brcmf_dbg(SDIO, "ctrl_frame_stat == true\n");
-			bus->ctrl_frame_stat = false;
-			if (down_interruptible(&bus->tx_seq_lock))
-				return -EINTR;
-			ret = -1;
-		}
+	/* Send from dpc */
+	bus->ctrl_frame_buf = msg;
+	bus->ctrl_frame_len = msglen;
+	bus->ctrl_frame_stat = true;
+	if (atomic_read(&bus->dpc_tskcnt) == 0) {
+		atomic_inc(&bus->dpc_tskcnt);
+		queue_work(bus->brcmf_wq, &bus->datawork);
 	}
-	if (ret == -1) {
-		sdio_claim_host(bus->sdiodev->func[1]);
-		brcmf_sdio_bus_sleep(bus, false, false);
-		ret = brcmf_sdio_tx_ctrlframe(bus, msg, msglen);
-		sdio_release_host(bus->sdiodev->func[1]);
-		up(&bus->tx_seq_lock);
+
+	wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat,
+					 msecs_to_jiffies(CTL_DONE_TIMEOUT));
+
+	if (!bus->ctrl_frame_stat) {
+		brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
+			  bus->ctrl_frame_err);
+		ret = bus->ctrl_frame_err;
+	} else {
+		brcmf_dbg(SDIO, "ctrl_frame timeout\n");
+		bus->ctrl_frame_stat = false;
+		ret = -ETIMEDOUT;
 	}
 
 	if (ret)
@@ -3009,7 +2989,7 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 	else
 		bus->sdcnt.tx_ctlpkts++;
 
-	return ret ? -EIO : 0;
+	return ret;
 }
 
 #ifdef DEBUG
@@ -4165,7 +4145,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
 
 	spin_lock_init(&bus->rxctl_lock);
 	spin_lock_init(&bus->txq_lock);
-	sema_init(&bus->tx_seq_lock, 1);
 	init_waitqueue_head(&bus->ctrl_wait);
 	init_waitqueue_head(&bus->dcmd_resp_wait);
 
-- 
1.9.1


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

* [PATCH 04/14] brcmfmac: pass DEAUTH/DISASSOC reason code to user-space
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (2 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 03/14] brcmfmac: use SDIO DPC for control frames Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 05/14] brcmfmac: wait for driver to go idle during suspend Arend van Spriel
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

The driver always called cfg80211_disconnected() with reason parameter
set to zero, ie. unknown. However, firmware does provide a valid
802.11 reason code in DEAUTH and DISASSOC event message to the driver.
This patch passes the reason code to cfg80211_disconnected().

Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 31 +++++++++++++++++-----
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
index 5eba81b..b59b8c6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
@@ -1229,7 +1229,25 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
 	memset(prof, 0, sizeof(*prof));
 }
 
-static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
+static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e)
+{
+	u16 reason;
+
+	switch (e->event_code) {
+	case BRCMF_E_DEAUTH:
+	case BRCMF_E_DEAUTH_IND:
+	case BRCMF_E_DISASSOC_IND:
+		reason = e->reason;
+		break;
+	case BRCMF_E_LINK:
+	default:
+		reason = 0;
+		break;
+	}
+	return reason;
+}
+
+static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
 	s32 err = 0;
@@ -1244,7 +1262,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
 			brcmf_err("WLC_DISASSOC failed (%d)\n", err);
 		}
 		clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
-		cfg80211_disconnected(vif->wdev.netdev, 0, NULL, 0, GFP_KERNEL);
+		cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0,
+				      GFP_KERNEL);
 
 	}
 	clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
@@ -1414,7 +1433,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
 	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
-	brcmf_link_down(ifp->vif);
+	brcmf_link_down(ifp->vif, WLAN_REASON_DEAUTH_LEAVING);
 
 	brcmf_dbg(TRACE, "Exit\n");
 
@@ -3041,7 +3060,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
 			 * disassociate from AP to save power while system is
 			 * in suspended state
 			 */
-			brcmf_link_down(vif);
+			brcmf_link_down(vif, WLAN_REASON_UNSPECIFIED);
 			/* Make sure WPA_Supplicant receives all the event
 			 * generated due to DISASSOC call to the fw to keep
 			 * the state fw and WPA_Supplicant state consistent
@@ -4927,7 +4946,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
 		if (!brcmf_is_ibssmode(ifp->vif)) {
 			brcmf_bss_connect_done(cfg, ndev, e, false);
 		}
-		brcmf_link_down(ifp->vif);
+		brcmf_link_down(ifp->vif, brcmf_map_fw_linkdown_reason(e));
 		brcmf_init_prof(ndev_to_prof(ndev));
 		if (ndev != cfg_to_ndev(cfg))
 			complete(&cfg->vif_disabled);
@@ -5868,7 +5887,7 @@ static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
 	 * from AP to save power
 	 */
 	if (check_vif_up(ifp->vif)) {
-		brcmf_link_down(ifp->vif);
+		brcmf_link_down(ifp->vif, WLAN_REASON_UNSPECIFIED);
 
 		/* Make sure WPA_Supplicant receives all the event
 		   generated due to DISASSOC call to the fw to keep
-- 
1.9.1


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

* [PATCH 05/14] brcmfmac: wait for driver to go idle during suspend
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (3 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 04/14] brcmfmac: pass DEAUTH/DISASSOC reason code to user-space Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 06/14] brcmfmac: SDIO: avoid using bus state for private states Arend van Spriel
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

Before going in suspend state the watchdog thread needs to put the
device in bus sleep state, which assures it can go in deep-sleep
state during D3 state.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 20 +++++++++++++++-----
 drivers/net/wireless/brcm80211/brcmfmac/sdio.c   | 18 ++++++++----------
 drivers/net/wireless/brcm80211/brcmfmac/sdio.h   |  2 ++
 3 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 8ba60f6..9afaeb6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -1045,7 +1045,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
 		bus_if->wowl_supported = true;
 #endif
 
+	sdiodev->sleeping = false;
 	atomic_set(&sdiodev->suspend, false);
+	init_waitqueue_head(&sdiodev->idle_wait);
 
 	brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
 	err = brcmf_sdiod_probe(sdiodev);
@@ -1107,12 +1109,23 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
 #ifdef CONFIG_PM_SLEEP
 static int brcmf_ops_sdio_suspend(struct device *dev)
 {
-	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_bus *bus_if;
+	struct brcmf_sdio_dev *sdiodev;
 	mmc_pm_flag_t sdio_flags;
 
 	brcmf_dbg(SDIO, "Enter\n");
 
+	bus_if = dev_get_drvdata(dev);
+	sdiodev = bus_if->bus_priv.sdio;
+
+	/* wait for watchdog to go idle */
+	if (wait_event_timeout(sdiodev->idle_wait, sdiodev->sleeping,
+			       msecs_to_jiffies(3 * BRCMF_WD_POLL_MS)) == 0) {
+		brcmf_err("bus still active\n");
+		return -EBUSY;
+	}
+	/* disable watchdog */
+	brcmf_sdio_wd_timer(sdiodev->bus, 0);
 	atomic_set(&sdiodev->suspend, true);
 
 	if (sdiodev->wowl_enabled) {
@@ -1124,9 +1137,6 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
 		if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
 			brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
 	}
-
-	brcmf_sdio_wd_timer(sdiodev->bus, 0);
-
 	return 0;
 }
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index b4f5fe5..488a0f6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -515,7 +515,6 @@ struct brcmf_sdio {
 	bool txoff;		/* Transmit flow-controlled */
 	struct brcmf_sdio_count sdcnt;
 	bool sr_enabled; /* SaveRestore enabled */
-	bool sleeping; /* SDIO bus sleeping */
 
 	u8 tx_hdrlen;		/* sdio bus header length for tx packet */
 	bool txglom;		/* host tx glomming enable flag */
@@ -1014,12 +1013,12 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
 
 	brcmf_dbg(SDIO, "Enter: request %s currently %s\n",
 		  (sleep ? "SLEEP" : "WAKE"),
-		  (bus->sleeping ? "SLEEP" : "WAKE"));
+		  (bus->sdiodev->sleeping ? "SLEEP" : "WAKE"));
 
 	/* If SR is enabled control bus state with KSO */
 	if (bus->sr_enabled) {
 		/* Done if we're already in the requested state */
-		if (sleep == bus->sleeping)
+		if (sleep == bus->sdiodev->sleeping)
 			goto end;
 
 		/* Going to sleep */
@@ -1051,12 +1050,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
 			bus->idlecount = 0;
 			err = brcmf_sdio_kso_control(bus, true);
 		}
-		if (!err) {
-			/* Change state */
-			bus->sleeping = sleep;
-			brcmf_dbg(SDIO, "new state %s\n",
-				  (sleep ? "SLEEP" : "WAKE"));
-		} else {
+		if (err) {
 			brcmf_err("error while changing bus sleep state %d\n",
 				  err);
 			goto done;
@@ -1071,6 +1065,11 @@ end:
 	} else {
 		brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok);
 	}
+	bus->sdiodev->sleeping = sleep;
+	if (sleep)
+		wake_up(&bus->sdiodev->idle_wait);
+	brcmf_dbg(SDIO, "new state %s\n",
+		  (sleep ? "SLEEP" : "WAKE"));
 done:
 	brcmf_dbg(SDIO, "Exit: err=%d\n", err);
 	return err;
@@ -4215,7 +4214,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
 	bus->idleclock = BRCMF_IDLE_ACTIVE;
 
 	/* SR state */
-	bus->sleeping = false;
 	bus->sr_enabled = false;
 
 	brcmf_sdio_debugfs_create(bus);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
index 82494df..9c5d42d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
@@ -169,6 +169,8 @@ struct brcmf_sdio_dev {
 	u32 sbwad;			/* Save backplane window address */
 	struct brcmf_sdio *bus;
 	atomic_t suspend;		/* suspend flag */
+	bool sleeping;
+	wait_queue_head_t idle_wait;
 	struct device *dev;
 	struct brcmf_bus *bus_if;
 	struct brcmfmac_sdio_platform_data *pdata;
-- 
1.9.1


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

* [PATCH 06/14] brcmfmac: SDIO: avoid using bus state for private states.
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (4 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 05/14] brcmfmac: wait for driver to go idle during suspend Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 07/14] brcmfmac: Reopen netdev queue on bus state data Arend van Spriel
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <meuleman@broadcom.com>

Each bus driver is maintaing an exported bus state indicating
if upper layers can or cannot send data. SDIO is using this state
also for more private states. This makes handling the states and
state changes complex. This patch minimises the exposed states
and makes SDIO keep track of an internal state where necessary.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 17 +++++----
 drivers/net/wireless/brcm80211/brcmfmac/bus.h    | 14 +-------
 drivers/net/wireless/brcm80211/brcmfmac/core.c   |  6 ++--
 drivers/net/wireless/brcm80211/brcmfmac/fwil.c   |  2 +-
 drivers/net/wireless/brcm80211/brcmfmac/pcie.c   |  2 +-
 drivers/net/wireless/brcm80211/brcmfmac/sdio.c   | 45 +++++++++---------------
 drivers/net/wireless/brcm80211/brcmfmac/sdio.h   |  8 +++++
 drivers/net/wireless/brcm80211/brcmfmac/usb.c    |  2 +-
 8 files changed, 43 insertions(+), 53 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 9afaeb6..7944224 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -269,6 +269,12 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
 	return ret;
 }
 
+static void brcmf_sdiod_nomedium_state(struct brcmf_sdio_dev *sdiodev)
+{
+	sdiodev->state = BRCMF_STATE_NOMEDIUM;
+	brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN);
+}
+
 static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
 				   u8 regsz, void *data, bool write)
 {
@@ -276,7 +282,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
 	s32 retry = 0;
 	int ret;
 
-	if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM)
+	if (sdiodev->state == BRCMF_STATE_NOMEDIUM)
 		return -ENOMEDIUM;
 
 	/*
@@ -302,7 +308,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
 		 retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
 
 	if (ret == -ENOMEDIUM)
-		brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
+		brcmf_sdiod_nomedium_state(sdiodev);
 	else if (ret != 0) {
 		/*
 		 * SleepCSR register access can fail when
@@ -325,7 +331,7 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
 	int err = 0, i;
 	u8 addr[3];
 
-	if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM)
+	if (sdiodev->state == BRCMF_STATE_NOMEDIUM)
 		return -ENOMEDIUM;
 
 	addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
@@ -454,7 +460,7 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 		err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr,
 				  req_sz);
 	if (err == -ENOMEDIUM)
-		brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
+		brcmf_sdiod_nomedium_state(sdiodev);
 	return err;
 }
 
@@ -589,8 +595,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
 
 		ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
 		if (ret == -ENOMEDIUM) {
-			brcmf_bus_change_state(sdiodev->bus_if,
-					       BRCMF_BUS_NOMEDIUM);
+			brcmf_sdiod_nomedium_state(sdiodev);
 			break;
 		} else if (ret != 0) {
 			brcmf_err("CMD53 sg block %s failed %d\n",
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h
index ef344e4..55d36ff 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h
@@ -33,11 +33,8 @@
 
 /* The level of bus communication with the dongle */
 enum brcmf_bus_state {
-	BRCMF_BUS_UNKNOWN,	/* Not determined yet */
-	BRCMF_BUS_NOMEDIUM,	/* No medium access to dongle */
 	BRCMF_BUS_DOWN,		/* Not ready for frame transfers */
-	BRCMF_BUS_LOAD,		/* Download access only (CPU reset) */
-	BRCMF_BUS_DATA		/* Ready for frame transfers */
+	BRCMF_BUS_UP		/* Ready for frame transfers */
 };
 
 /* The level of bus communication with the dongle */
@@ -188,18 +185,9 @@ void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled)
 		bus->ops->wowl_config(bus->dev, enabled);
 }
 
-static inline bool brcmf_bus_ready(struct brcmf_bus *bus)
-{
-	return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA;
-}
-
 static inline void brcmf_bus_change_state(struct brcmf_bus *bus,
 					  enum brcmf_bus_state new_state)
 {
-	/* NOMEDIUM is permanent */
-	if (bus->state == BRCMF_BUS_NOMEDIUM)
-		return;
-
 	brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state);
 	bus->state = new_state;
 }
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index e2a9e33..ff8c97b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -197,7 +197,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
 	brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx);
 
 	/* Can the device send data? */
-	if (drvr->bus_if->state != BRCMF_BUS_DATA) {
+	if (drvr->bus_if->state != BRCMF_BUS_UP) {
 		brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state);
 		netif_stop_queue(ndev);
 		dev_kfree_skb(skb);
@@ -637,7 +637,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
 	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 
 	/* If bus is not ready, can't continue */
-	if (bus_if->state != BRCMF_BUS_DATA) {
+	if (bus_if->state != BRCMF_BUS_UP) {
 		brcmf_err("failed bus is not ready\n");
 		return -EAGAIN;
 	}
@@ -964,7 +964,7 @@ int brcmf_bus_start(struct device *dev)
 		p2p_ifp = NULL;
 
 	/* signal bus ready */
-	brcmf_bus_change_state(bus_if, BRCMF_BUS_DATA);
+	brcmf_bus_change_state(bus_if, BRCMF_BUS_UP);
 
 	/* Bus is ready, do any initialization */
 	ret = brcmf_c_preinit_dcmds(ifp);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
index 03f2c40..dcfa0bb 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
@@ -109,7 +109,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
 	struct brcmf_pub *drvr = ifp->drvr;
 	s32 err;
 
-	if (drvr->bus_if->state != BRCMF_BUS_DATA) {
+	if (drvr->bus_if->state != BRCMF_BUS_UP) {
 		brcmf_err("bus is down. we have nothing to do.\n");
 		return -EIO;
 	}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
index e91fa9a..61c053a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
@@ -1828,7 +1828,7 @@ static int brcmf_pcie_resume(struct pci_dev *pdev)
 				goto cleanup;
 			brcmf_dbg(PCIE, "Hot resume, continue....\n");
 			brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
-			brcmf_bus_change_state(bus, BRCMF_BUS_DATA);
+			brcmf_bus_change_state(bus, BRCMF_BUS_UP);
 			brcmf_pcie_intr_enable(devinfo);
 			return 0;
 		}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index 488a0f6..5e9d208 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -1909,7 +1909,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 	bus->rxpending = true;
 
 	for (rd->seq_num = bus->rx_seq, rxleft = maxframes;
-	     !bus->rxskip && rxleft && brcmf_bus_ready(bus->sdiodev->bus_if);
+	     !bus->rxskip && rxleft && bus->sdiodev->state == BRCMF_STATE_DATA;
 	     rd->seq_num++, rxleft--) {
 
 		/* Handle glomming separately */
@@ -2415,7 +2415,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 	}
 
 	/* Deflow-control stack if needed */
-	if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
+	if ((bus->sdiodev->state == BRCMF_STATE_DATA) &&
 	    bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
 		bus->txoff = false;
 		brcmf_txflowblock(bus->sdiodev->dev, false);
@@ -2503,7 +2503,7 @@ static void brcmf_sdio_bus_stop(struct device *dev)
 		bus->watchdog_tsk = NULL;
 	}
 
-	if (bus_if->state == BRCMF_BUS_DOWN) {
+	if (sdiodev->state != BRCMF_STATE_NOMEDIUM) {
 		sdio_claim_host(sdiodev->func[1]);
 
 		/* Enable clock for device interrupts */
@@ -2756,7 +2756,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
 		brcmf_sdio_sendfromq(bus, framecnt);
 	}
 
-	if (!brcmf_bus_ready(bus->sdiodev->bus_if) || (err != 0)) {
+	if ((bus->sdiodev->state != BRCMF_STATE_DATA) || (err != 0)) {
 		brcmf_err("failed backplane access over SDIO, halting operation\n");
 		atomic_set(&bus->intstatus, 0);
 	} else if (atomic_read(&bus->intstatus) ||
@@ -3411,8 +3411,8 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
 		goto err;
 	}
 
-	/* Allow HT Clock now that the ARM is running. */
-	brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_LOAD);
+	/* Allow full data communication using DPC from now on. */
+	bus->sdiodev->state = BRCMF_STATE_DATA;
 	bcmerror = 0;
 
 err:
@@ -3558,7 +3558,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
 		return;
 	}
 
-	if (!brcmf_bus_ready(bus->sdiodev->bus_if)) {
+	if (bus->sdiodev->state != BRCMF_STATE_DATA) {
 		brcmf_err("bus is down. we have nothing to do\n");
 		return;
 	}
@@ -3581,10 +3581,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
 
 static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
 {
-#ifdef DEBUG
-	struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev);
-#endif	/* DEBUG */
-
 	brcmf_dbg(TIMER, "Enter\n");
 
 	/* Poll period: check device if appropriate. */
@@ -3628,7 +3624,7 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
 	}
 #ifdef DEBUG
 	/* Poll for console output periodically */
-	if (bus_if && bus_if->state == BRCMF_BUS_DATA &&
+	if (bus->sdiodev->state == BRCMF_STATE_DATA &&
 	    bus->console_interval != 0) {
 		bus->console.count += BRCMF_WD_POLL_MS;
 		if (bus->console.count >= bus->console_interval) {
@@ -3869,11 +3865,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 		goto fail;
 	}
 
-	/* SDIO register access works so moving
-	 * state from UNKNOWN to DOWN.
-	 */
-	brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN);
-
 	bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops);
 	if (IS_ERR(bus->ci)) {
 		brcmf_err("brcmf_chip_attach failed!\n");
@@ -4007,18 +3998,16 @@ static void brcmf_sdio_firmware_callback(struct device *dev,
 
 	brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev));
 
-	/* try to download image and nvram to the dongle */
-	if (bus_if->state == BRCMF_BUS_DOWN) {
-		bus->alp_only = true;
-		err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
-		if (err)
-			goto fail;
-		bus->alp_only = false;
-	}
-
 	if (!bus_if->drvr)
 		return;
 
+	/* try to download image and nvram to the dongle */
+	bus->alp_only = true;
+	err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
+	if (err)
+		goto fail;
+	bus->alp_only = false;
+
 	/* Start the watchdog timer */
 	bus->sdcnt.tickcnt = 0;
 	brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
@@ -4254,7 +4243,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
 			destroy_workqueue(bus->brcmf_wq);
 
 		if (bus->ci) {
-			if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
+			if (bus->sdiodev->state != BRCMF_STATE_NOMEDIUM) {
 				sdio_claim_host(bus->sdiodev->func[1]);
 				brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
 				/* Leave the device in state where it is
@@ -4289,7 +4278,7 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick)
 	}
 
 	/* don't start the wd until fw is loaded */
-	if (bus->sdiodev->bus_if->state != BRCMF_BUS_DATA)
+	if (bus->sdiodev->state != BRCMF_STATE_DATA)
 		return;
 
 	if (wdtick) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
index 9c5d42d..ec2586a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
@@ -155,6 +155,13 @@
 /* watchdog polling interval in ms */
 #define BRCMF_WD_POLL_MS	10
 
+/* The state of the bus */
+enum brcmf_sdio_state {
+	BRCMF_STATE_DOWN,	/* Device available, still initialising */
+	BRCMF_STATE_DATA,	/* Ready for data transfers, DPC enabled */
+	BRCMF_STATE_NOMEDIUM	/* No medium access to dongle possible */
+};
+
 struct brcmf_sdreg {
 	int func;
 	int offset;
@@ -187,6 +194,7 @@ struct brcmf_sdio_dev {
 	char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
 	char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
 	bool wowl_enabled;
+	enum brcmf_sdio_state state;
 };
 
 /* sdio core registers */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 4572def..7e0c9e2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -576,7 +576,7 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
 		brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN);
 	} else if (state == BRCMFMAC_USB_STATE_UP) {
 		brcmf_dbg(USB, "DBUS is up\n");
-		brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DATA);
+		brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_UP);
 	} else {
 		brcmf_dbg(USB, "DBUS current state=%d\n", state);
 	}
-- 
1.9.1


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

* [PATCH 07/14] brcmfmac: Reopen netdev queue on bus state data.
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (5 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 06/14] brcmfmac: SDIO: avoid using bus state for private states Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 08/14] brcmfmac: do not load firmware when device is already running Arend van Spriel
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel

From: Hante Meuleman <meuleman@broadcom.com>

During suspend the bus state is put in the down state. When data
is being transmitted during this state then the netdev queue will
be close. This patch will wake the queue on state data if the
queue was closed.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/bus.h  | 10 +++-------
 drivers/net/wireless/brcm80211/brcmfmac/core.c | 21 +++++++++++++++++++++
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h
index 55d36ff..89e6a4d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h
@@ -185,13 +185,6 @@ void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled)
 		bus->ops->wowl_config(bus->dev, enabled);
 }
 
-static inline void brcmf_bus_change_state(struct brcmf_bus *bus,
-					  enum brcmf_bus_state new_state)
-{
-	brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state);
-	bus->state = new_state;
-}
-
 /*
  * interface functions from common layer
  */
@@ -214,6 +207,9 @@ void brcmf_txflowblock(struct device *dev, bool state);
 /* Notify the bus has transferred the tx packet to firmware */
 void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
 
+/* Configure the "global" bus state used by upper layers */
+void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state);
+
 int brcmf_bus_start(struct device *dev);
 s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len);
 void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index ff8c97b..b8520c3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -1106,6 +1106,27 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp)
 	return !err;
 }
 
+void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state)
+{
+	struct brcmf_pub *drvr = bus->drvr;
+	struct net_device *ndev;
+	int ifidx;
+
+	brcmf_dbg(TRACE, "%d -> %d\n", bus->state, state);
+	bus->state = state;
+
+	if (state == BRCMF_BUS_UP) {
+		for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) {
+			if ((drvr->iflist[ifidx]) &&
+			    (drvr->iflist[ifidx]->ndev)) {
+				ndev = drvr->iflist[ifidx]->ndev;
+				if (netif_queue_stopped(ndev))
+					netif_wake_queue(ndev);
+			}
+		}
+	}
+}
+
 static void brcmf_driver_register(struct work_struct *work)
 {
 #ifdef CONFIG_BRCMFMAC_SDIO
-- 
1.9.1


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

* [PATCH 08/14] brcmfmac: do not load firmware when device is already running
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (6 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 07/14] brcmfmac: Reopen netdev queue on bus state data Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 09/14] brcmutil: use define for boardrev string function Arend van Spriel
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

In brcmf_usb_probe_cb() the device is checked to determine whether
it is already running firmware. However, when no firmware download
is needed it still continues to request the firmware files. This
is fixed by returning after successful setup.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/usb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 7e0c9e2..1b95729 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -1263,6 +1263,8 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
 		ret = brcmf_usb_bus_setup(devinfo);
 		if (ret)
 			goto fail;
+		/* we are done */
+		return 0;
 	}
 	bus->chip = bus_pub->devid;
 	bus->chiprev = bus_pub->chiprev;
-- 
1.9.1


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

* [PATCH 09/14] brcmutil: use define for boardrev string function
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (7 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 08/14] brcmfmac: do not load firmware when device is already running Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 10/14] brcmfmac: determine chip info when not provided by bus layer Arend van Spriel
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

Introducing a define that the caller of brcmu_boardrev_str() can
use to allocate enough room for buffer passed to the function.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmsmac/debug.c      | 2 +-
 drivers/net/wireless/brcm80211/brcmutil/utils.c      | 5 +++--
 drivers/net/wireless/brcm80211/include/brcmu_utils.h | 2 ++
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
index c9a8b93..7a1fbb2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
@@ -78,7 +78,7 @@ int brcms_debugfs_hardware_read(struct seq_file *s, void *data)
 	struct brcms_hardware *hw = drvr->wlc->hw;
 	struct bcma_device *core = hw->d11core;
 	struct bcma_bus *bus = core->bus;
-	char boardrev[10];
+	char boardrev[BRCMU_BOARDREV_LEN];
 
 	seq_printf(s, "chipnum 0x%x\n"
 		   "chiprev 0x%x\n"
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index 906e89d..34937d8 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -267,10 +267,11 @@ char *brcmu_boardrev_str(u32 brev, char *buf)
 	char c;
 
 	if (brev < 0x100) {
-		snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
+		snprintf(buf, BRCMU_BOARDREV_LEN, "%d.%d",
+			 (brev & 0xf0) >> 4, brev & 0xf);
 	} else {
 		c = (brev & 0xf000) == 0x1000 ? 'P' : 'A';
-		snprintf(buf, 8, "%c%03x", c, brev & 0xfff);
+		snprintf(buf, BRCMU_BOARDREV_LEN, "%c%03x", c, brev & 0xfff);
 	}
 	return buf;
 }
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index a043e29..197317b 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -218,6 +218,8 @@ void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...)
 }
 #endif
 
+#define BRCMU_BOARDREV_LEN	8
+
 char *brcmu_boardrev_str(u32 brev, char *buf);
 
 #endif				/* _BRCMU_UTILS_H_ */
-- 
1.9.1


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

* [PATCH 10/14] brcmfmac: determine chip info when not provided by bus layer
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (8 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 09/14] brcmutil: use define for boardrev string function Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 11/14] brcmfmac: always obtain device revision info upon intialization Arend van Spriel
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

In some scenarios the chip number and revision may not be provided
by the bus layer. If the chip number is not filled, the common
layer will ask the firmware for this information.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/core.c     | 15 ++++++++
 drivers/net/wireless/brcm80211/brcmfmac/fwil.h     |  1 +
 .../net/wireless/brcm80211/brcmfmac/fwil_types.h   | 41 ++++++++++++++++++++++
 3 files changed, 57 insertions(+)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index b8520c3..5f16a7e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -948,6 +948,7 @@ int brcmf_bus_start(struct device *dev)
 	struct brcmf_pub *drvr = bus_if->drvr;
 	struct brcmf_if *ifp;
 	struct brcmf_if *p2p_ifp;
+	struct brcmf_rev_info_le revinfo;
 
 	brcmf_dbg(TRACE, "\n");
 
@@ -971,6 +972,20 @@ int brcmf_bus_start(struct device *dev)
 	if (ret < 0)
 		goto fail;
 
+	/* assure we have chipid before feature attach */
+	if (!bus_if->chip) {
+		ret = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO, &revinfo,
+					     sizeof(revinfo));
+		if (ret < 0) {
+			brcmf_err("no chipid determined - device may malfunction\n");
+		} else {
+			bus_if->chip = le32_to_cpu(revinfo.chipnum);
+			bus_if->chiprev = le32_to_cpu(revinfo.chiprev);
+			brcmf_dbg(INFO, "firmware revinfo: chip %x (%d) rev %d\n",
+				  bus_if->chip, bus_if->chip,
+				  bus_if->chiprev);
+		}
+	}
 	brcmf_feat_attach(drvr);
 
 	ret = brcmf_fws_init(drvr);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
index 37345e7..5434dcf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
@@ -59,6 +59,7 @@
 #define BRCMF_C_SET_COUNTRY			84
 #define BRCMF_C_GET_PM				85
 #define BRCMF_C_SET_PM				86
+#define BRCMF_C_GET_REVINFO			98
 #define BRCMF_C_GET_CURR_RATESET		114
 #define BRCMF_C_GET_AP				117
 #define BRCMF_C_SET_AP				118
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
index 619669b..3749209 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
@@ -539,4 +539,45 @@ struct brcmf_fil_country_le {
 	char ccode[BRCMF_COUNTRY_BUF_SZ];
 };
 
+/**
+ * struct brcmf_rev_info_le - device revision info.
+ *
+ * @vendorid: PCI vendor id.
+ * @deviceid: device id of chip.
+ * @radiorev: radio revision.
+ * @chiprev: chip revision.
+ * @corerev: core revision.
+ * @boardid: board identifier (usu. PCI sub-device id).
+ * @boardvendor: board vendor (usu. PCI sub-vendor id).
+ * @boardrev: board revision.
+ * @driverrev: driver version.
+ * @ucoderev: microcode version.
+ * @bus: bus type.
+ * @chipnum: chip number.
+ * @phytype: phy type.
+ * @phyrev: phy revision.
+ * @anarev: anacore rev.
+ * @chippkg: chip package info.
+ * @nvramrev: nvram revision number.
+ */
+struct brcmf_rev_info_le {
+	__le32 vendorid;
+	__le32 deviceid;
+	__le32 radiorev;
+	__le32 chiprev;
+	__le32 corerev;
+	__le32 boardid;
+	__le32 boardvendor;
+	__le32 boardrev;
+	__le32 driverrev;
+	__le32 ucoderev;
+	__le32 bus;
+	__le32 chipnum;
+	__le32 phytype;
+	__le32 phyrev;
+	__le32 anarev;
+	__le32 chippkg;
+	__le32 nvramrev;
+};
+
 #endif /* FWIL_TYPES_H_ */
-- 
1.9.1


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

* [PATCH 11/14] brcmfmac: always obtain device revision info upon intialization
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (9 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 10/14] brcmfmac: determine chip info when not provided by bus layer Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 12/14] brcmfmac: show firmware release info in ethtool driver info Arend van Spriel
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

Obtain device revision information and store it.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/common.c | 30 ++++++++++++++++++++++--
 drivers/net/wireless/brcm80211/brcmfmac/core.c   | 16 ++++---------
 drivers/net/wireless/brcm80211/brcmfmac/core.h   | 22 +++++++++++++++++
 3 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.c b/drivers/net/wireless/brcm80211/brcmfmac/common.c
index ddf05af..91213a6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/common.c
@@ -41,6 +41,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
 	u8 buf[BRCMF_DCMD_SMLEN];
 	struct brcmf_join_pref_params join_pref_params[2];
+	struct brcmf_rev_info_le revinfo;
+	struct brcmf_rev_info *ri;
 	char *ptr;
 	s32 err;
 
@@ -48,12 +50,36 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 	err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
 				       sizeof(ifp->mac_addr));
 	if (err < 0) {
-		brcmf_err("Retreiving cur_etheraddr failed, %d\n",
-			  err);
+		brcmf_err("Retreiving cur_etheraddr failed, %d\n", err);
 		goto done;
 	}
 	memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
 
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO,
+				     &revinfo, sizeof(revinfo));
+	if (err < 0) {
+		brcmf_err("retrieving revision info failed, %d\n", err);
+	} else {
+		ri = &ifp->drvr->revinfo;
+		ri->vendorid = le32_to_cpu(revinfo.vendorid);
+		ri->deviceid = le32_to_cpu(revinfo.deviceid);
+		ri->radiorev = le32_to_cpu(revinfo.radiorev);
+		ri->chiprev = le32_to_cpu(revinfo.chiprev);
+		ri->corerev = le32_to_cpu(revinfo.corerev);
+		ri->boardid = le32_to_cpu(revinfo.boardid);
+		ri->boardvendor = le32_to_cpu(revinfo.boardvendor);
+		ri->boardrev = le32_to_cpu(revinfo.boardrev);
+		ri->driverrev = le32_to_cpu(revinfo.driverrev);
+		ri->ucoderev = le32_to_cpu(revinfo.ucoderev);
+		ri->bus = le32_to_cpu(revinfo.bus);
+		ri->chipnum = le32_to_cpu(revinfo.chipnum);
+		ri->phytype = le32_to_cpu(revinfo.phytype);
+		ri->phyrev = le32_to_cpu(revinfo.phyrev);
+		ri->anarev = le32_to_cpu(revinfo.anarev);
+		ri->chippkg = le32_to_cpu(revinfo.chippkg);
+		ri->nvramrev = le32_to_cpu(revinfo.nvramrev);
+	}
+
 	/* query for 'ver' to get version info from firmware */
 	memset(buf, 0, sizeof(buf));
 	strcpy(buf, "ver");
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index 5f16a7e..6406f95 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -948,7 +948,6 @@ int brcmf_bus_start(struct device *dev)
 	struct brcmf_pub *drvr = bus_if->drvr;
 	struct brcmf_if *ifp;
 	struct brcmf_if *p2p_ifp;
-	struct brcmf_rev_info_le revinfo;
 
 	brcmf_dbg(TRACE, "\n");
 
@@ -974,17 +973,10 @@ int brcmf_bus_start(struct device *dev)
 
 	/* assure we have chipid before feature attach */
 	if (!bus_if->chip) {
-		ret = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO, &revinfo,
-					     sizeof(revinfo));
-		if (ret < 0) {
-			brcmf_err("no chipid determined - device may malfunction\n");
-		} else {
-			bus_if->chip = le32_to_cpu(revinfo.chipnum);
-			bus_if->chiprev = le32_to_cpu(revinfo.chiprev);
-			brcmf_dbg(INFO, "firmware revinfo: chip %x (%d) rev %d\n",
-				  bus_if->chip, bus_if->chip,
-				  bus_if->chiprev);
-		}
+		bus_if->chip = drvr->revinfo.chipnum;
+		bus_if->chiprev = drvr->revinfo.chiprev;
+		brcmf_dbg(INFO, "firmware revinfo: chip %x (%d) rev %d\n",
+			  bus_if->chip, bus_if->chip, bus_if->chiprev);
 	}
 	brcmf_feat_attach(drvr);
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h
index f2f7d3d..db7f35f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
@@ -71,6 +71,27 @@ struct brcmf_proto;	/* device communication protocol info */
 struct brcmf_cfg80211_dev; /* cfg80211 device info */
 struct brcmf_fws_info; /* firmware signalling info */
 
+/* see struct brcmf_rev_info_le in fwil_types.h */
+struct brcmf_rev_info {
+	u32 vendorid;
+	u32 deviceid;
+	u32 radiorev;
+	u32 chiprev;
+	u32 corerev;
+	u32 boardid;
+	u32 boardvendor;
+	u32 boardrev;
+	u32 driverrev;
+	u32 ucoderev;
+	u32 bus;
+	u32 chipnum;
+	u32 phytype;
+	u32 phyrev;
+	u32 anarev;
+	u32 chippkg;
+	u32 nvramrev;
+};
+
 /* Common structure for module and instance linkage */
 struct brcmf_pub {
 	/* Linkage ponters */
@@ -104,6 +125,7 @@ struct brcmf_pub {
 	u32 feat_flags;
 	u32 chip_quirks;
 
+	struct brcmf_rev_info revinfo;
 #ifdef DEBUG
 	struct dentry *dbgfs_dir;
 #endif
-- 
1.9.1


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

* [PATCH 12/14] brcmfmac: show firmware release info in ethtool driver info
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (10 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 11/14] brcmfmac: always obtain device revision info upon intialization Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 13/14] brcmfmac: store revinfo retrieval result Arend van Spriel
  2015-01-25 19:31 ` [PATCH 14/14] brcmfmac: fix nvram processing Arend van Spriel
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

The ethtool driver info already contained the unique firmware
identifier. This patch adds the firmware release version.

   $ ethtool -i wlan4
   driver: brcmfmac
   version: 6.10.224.22
   firmware-version: 01-32bd010f

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/core.c     |  4 +++-
 drivers/net/wireless/brcm80211/brcmutil/utils.c    | 27 ++++++++++++++++++++++
 .../net/wireless/brcm80211/include/brcmu_utils.h   |  2 ++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index 6406f95..8d03588 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -601,9 +601,11 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_pub *drvr = ifp->drvr;
+	char drev[BRCMU_DOTREV_LEN];
 
 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-	snprintf(info->version, sizeof(info->version), "n/a");
+	strlcpy(info->version, brcmu_dotrev_str(drvr->revinfo.driverrev, drev),
+		sizeof(info->version));
 	strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version));
 	strlcpy(info->bus_info, dev_name(drvr->bus_if->dev),
 		sizeof(info->bus_info));
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index 34937d8..0543607 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -277,6 +277,33 @@ char *brcmu_boardrev_str(u32 brev, char *buf)
 }
 EXPORT_SYMBOL(brcmu_boardrev_str);
 
+char *brcmu_dotrev_str(u32 dotrev, char *buf)
+{
+	u8 dotval[4];
+
+	if (!dotrev) {
+		snprintf(buf, BRCMU_DOTREV_LEN, "unknown");
+		return buf;
+	}
+	dotval[0] = (dotrev >> 24) & 0xFF;
+	dotval[1] = (dotrev >> 16) & 0xFF;
+	dotval[2] = (dotrev >> 8) & 0xFF;
+	dotval[3] = dotrev & 0xFF;
+
+	if (dotval[3])
+		snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d.%d", dotval[0],
+			dotval[1], dotval[2], dotval[3]);
+	else if (dotval[2])
+		snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d", dotval[0],
+			dotval[1], dotval[2]);
+	else
+		snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d", dotval[0],
+			dotval[1]);
+
+	return buf;
+}
+EXPORT_SYMBOL(brcmu_dotrev_str);
+
 #if defined(DEBUG)
 /* pretty hex print a pkt buffer chain */
 void brcmu_prpkt(const char *msg, struct sk_buff *p0)
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index 197317b..4196952 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -219,7 +219,9 @@ void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...)
 #endif
 
 #define BRCMU_BOARDREV_LEN	8
+#define BRCMU_DOTREV_LEN	16
 
 char *brcmu_boardrev_str(u32 brev, char *buf);
+char *brcmu_dotrev_str(u32 dotrev, char *buf);
 
 #endif				/* _BRCMU_UTILS_H_ */
-- 
1.9.1


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

* [PATCH 13/14] brcmfmac: store revinfo retrieval result
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (11 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 12/14] brcmfmac: show firmware release info in ethtool driver info Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  2015-01-25 19:31 ` [PATCH 14/14] brcmfmac: fix nvram processing Arend van Spriel
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

When revinfo retrieval fails we can not show the firmware version
in ethtool driver info. Store the result to be used when handling
ethtool driver info callback.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/common.c |  3 ++-
 drivers/net/wireless/brcm80211/brcmfmac/core.c   |  7 ++++---
 drivers/net/wireless/brcm80211/brcmfmac/core.h   | 10 +++++++++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.c b/drivers/net/wireless/brcm80211/brcmfmac/common.c
index 91213a6..fe54844 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/common.c
@@ -57,10 +57,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 
 	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO,
 				     &revinfo, sizeof(revinfo));
+	ri = &ifp->drvr->revinfo;
 	if (err < 0) {
 		brcmf_err("retrieving revision info failed, %d\n", err);
 	} else {
-		ri = &ifp->drvr->revinfo;
 		ri->vendorid = le32_to_cpu(revinfo.vendorid);
 		ri->deviceid = le32_to_cpu(revinfo.deviceid);
 		ri->radiorev = le32_to_cpu(revinfo.radiorev);
@@ -79,6 +79,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 		ri->chippkg = le32_to_cpu(revinfo.chippkg);
 		ri->nvramrev = le32_to_cpu(revinfo.nvramrev);
 	}
+	ri->result = err;
 
 	/* query for 'ver' to get version info from firmware */
 	memset(buf, 0, sizeof(buf));
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index 8d03588..2d6e2cc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -601,11 +601,12 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_pub *drvr = ifp->drvr;
-	char drev[BRCMU_DOTREV_LEN];
+	char drev[BRCMU_DOTREV_LEN] = "n/a";
 
+	if (drvr->revinfo.result == 0)
+		brcmu_dotrev_str(drvr->revinfo.driverrev, drev);
 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-	strlcpy(info->version, brcmu_dotrev_str(drvr->revinfo.driverrev, drev),
-		sizeof(info->version));
+	strlcpy(info->version, drev, sizeof(info->version));
 	strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version));
 	strlcpy(info->bus_info, dev_name(drvr->bus_if->dev),
 		sizeof(info->bus_info));
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h
index db7f35f..fd74a9c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
@@ -71,8 +71,16 @@ struct brcmf_proto;	/* device communication protocol info */
 struct brcmf_cfg80211_dev; /* cfg80211 device info */
 struct brcmf_fws_info; /* firmware signalling info */
 
-/* see struct brcmf_rev_info_le in fwil_types.h */
+/*
+ * struct brcmf_rev_info
+ *
+ * The result field stores the error code of the
+ * revision info request from firmware. For the
+ * other fields see struct brcmf_rev_info_le in
+ * fwil_types.h
+ */
 struct brcmf_rev_info {
+	int result;
 	u32 vendorid;
 	u32 deviceid;
 	u32 radiorev;
-- 
1.9.1


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

* [PATCH 14/14] brcmfmac: fix nvram processing
  2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
                   ` (12 preceding siblings ...)
  2015-01-25 19:31 ` [PATCH 13/14] brcmfmac: store revinfo retrieval result Arend van Spriel
@ 2015-01-25 19:31 ` Arend van Spriel
  13 siblings, 0 replies; 16+ messages in thread
From: Arend van Spriel @ 2015-01-25 19:31 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Arend van Spriel

The nvram file can hold a key=value combination in which the value
may have spaces, ie. 'RAW1=80 02 fe ff'. The parsing functionality
did not deal with this so it gives an error message:

[621746.311635] brcmfmac: brcmf_nvram_handle_key
	warning: ln=90:col=11: '=' expected, skip invalid key entry

because RAW1=80 is being considerd as key=value pair and it expects
'=' sign after '02' for next key=value pair. This entry can be
completely ignored as firmware does not need it.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/firmware.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
index 1ff787d..9cb9915 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -103,7 +103,11 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
 
 	c = nvp->fwnv->data[nvp->pos];
 	if (c == '=') {
-		st = VALUE;
+		/* ignore RAW1 by treating as comment */
+		if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0)
+			st = COMMENT;
+		else
+			st = VALUE;
 	} else if (!is_nvram_char(c)) {
 		brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
 			  nvp->line, nvp->column);
-- 
1.9.1


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

* Re: [01/14] brcmfmac: Relax scheduling of msgbuf worker on highthroughput.
  2015-01-25 19:31 ` [PATCH 01/14] brcmfmac: Relax scheduling of msgbuf worker on high throughput Arend van Spriel
@ 2015-01-29  8:01   ` Kalle Valo
  0 siblings, 0 replies; 16+ messages in thread
From: Kalle Valo @ 2015-01-29  8:01 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel


> From: Hante Meuleman <meuleman@broadcom.com>
> 
> On every tx the flow worker is triggered. When running high
> throughput data this causes an excessive amount of times the worker
> gets activated. This patch starts scheduling the worker more relaxed
> once outstanding tx has reached a certain depth.
> 
> Reviewed-by: Arend Van Spriel <arend@broadcom.com>
> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
> Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
> Signed-off-by: Arend van Spriel <arend@broadcom.com>

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

5ef1e604194e brcmfmac: Relax scheduling of msgbuf worker on high throughput.
69d03ee0b709 brcmfmac: prevent possible deadlock on resuming SDIO device.
4dd8b26a40ac brcmfmac: use SDIO DPC for control frames.
9b7a0ddc6073 brcmfmac: pass DEAUTH/DISASSOC reason code to user-space
8982cd40ace9 brcmfmac: wait for driver to go idle during suspend
a1cee865c3e7 brcmfmac: SDIO: avoid using bus state for private states.
649f38ae9e48 brcmfmac: Reopen netdev queue on bus state data.
86fec35e17c1 brcmfmac: do not load firmware when device is already running
31fc436f184d brcmutil: use define for boardrev string function
9b1933a3bd7c brcmfmac: determine chip info when not provided by bus layer
4862290319ad brcmfmac: always obtain device revision info upon intialization
e749c7d49c20 brcmfmac: show firmware release info in ethtool driver info
7f52c81d02a2 brcmfmac: store revinfo retrieval result
4165fe9a9287 brcmfmac: fix nvram processing

Kalle Valo

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

end of thread, other threads:[~2015-01-29  8:01 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-25 19:31 [PATCH 00/14] brcm80211: sdio suspend rework and other fixes Arend van Spriel
2015-01-25 19:31 ` [PATCH 01/14] brcmfmac: Relax scheduling of msgbuf worker on high throughput Arend van Spriel
2015-01-29  8:01   ` [01/14] brcmfmac: Relax scheduling of msgbuf worker on highthroughput Kalle Valo
2015-01-25 19:31 ` [PATCH 02/14] brcmfmac: prevent possible deadlock on resuming SDIO device Arend van Spriel
2015-01-25 19:31 ` [PATCH 03/14] brcmfmac: use SDIO DPC for control frames Arend van Spriel
2015-01-25 19:31 ` [PATCH 04/14] brcmfmac: pass DEAUTH/DISASSOC reason code to user-space Arend van Spriel
2015-01-25 19:31 ` [PATCH 05/14] brcmfmac: wait for driver to go idle during suspend Arend van Spriel
2015-01-25 19:31 ` [PATCH 06/14] brcmfmac: SDIO: avoid using bus state for private states Arend van Spriel
2015-01-25 19:31 ` [PATCH 07/14] brcmfmac: Reopen netdev queue on bus state data Arend van Spriel
2015-01-25 19:31 ` [PATCH 08/14] brcmfmac: do not load firmware when device is already running Arend van Spriel
2015-01-25 19:31 ` [PATCH 09/14] brcmutil: use define for boardrev string function Arend van Spriel
2015-01-25 19:31 ` [PATCH 10/14] brcmfmac: determine chip info when not provided by bus layer Arend van Spriel
2015-01-25 19:31 ` [PATCH 11/14] brcmfmac: always obtain device revision info upon intialization Arend van Spriel
2015-01-25 19:31 ` [PATCH 12/14] brcmfmac: show firmware release info in ethtool driver info Arend van Spriel
2015-01-25 19:31 ` [PATCH 13/14] brcmfmac: store revinfo retrieval result Arend van Spriel
2015-01-25 19:31 ` [PATCH 14/14] brcmfmac: fix nvram processing Arend van Spriel

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.