Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH 3.12] mwifiex: fix SDIO interrupt lost issue
From: John W. Linville @ 2013-10-15 16:59 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Bing Zhao, linux-wireless, Sven Neumann, Andreas Fenkart,
	Dylan Reid, Paul Stewart, Amitkumar Karwar
In-Reply-To: <525D1B3A.8090805@gmail.com>

On Tue, Oct 15, 2013 at 12:38:50PM +0200, Daniel Mack wrote: > On 27.09.2013 19:55, Bing Zhao wrote:
> > From: Amitkumar Karwar <akarwar@marvell.com>
> > 
> > 601216e "mwifiex: process RX packets in SDIO IRQ thread directly"
> > introduced a command timeout issue which can be reproduced easily on
> > an AM33xx platform using a test application written by Daniel Mack:
> > 
> > https://gist.github.com/zonque/6579314
> > 
> > mwifiex_main_process() is called from both the SDIO handler and
> > the workqueue. In case an interrupt occurs right after the
> > int_status check, but before updating the mwifiex_processing flag,
> > this interrupt gets lost, resulting in a command timeout and
> > consequently a card reset.
> > 
> > Let main_proc_lock protect both int_status and mwifiex_processing
> > flag. This fixes the interrupt lost issue.
> 
> John, could you take this patch trough your tree?

I already did, and it is already in Dave's tree too...

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH 02/18] net: use wrapper functions of net_ratelimit() to simplify code
From: Joe Perches @ 2013-10-15 16:24 UTC (permalink / raw)
  To: Kefeng Wang
  Cc: linux-kernel, Greg Kroah-Hartman, David S. Miller,
	Pablo Neira Ayuso, Stephen Hemminger, Johannes Berg,
	John W. Linville, Stanislaw Gruszka, Johannes Berg,
	Francois Romieu, Ben Hutchings, Chas Williams, Marc Kleine-Budde,
	Samuel Ortiz, Paul Mackerras, Oliver Neukum,
	Konrad Rzeszutek Wilk, Boris Ostrovsky, David Vrabel,
	Rusty Russell, Michael S. Tsirkin, netfilter, netdev,
	linux-wireless, guohanjun
In-Reply-To: <1381837514-50660-3-git-send-email-wangkefeng.wang@huawei.com>

On Tue, 2013-10-15 at 19:44 +0800, Kefeng Wang wrote:
> Wrapper functions net_ratelimited_function() and net_XXX_ratelimited()
> are called to simplify code.
[]
> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
[]
> @@ -465,10 +465,8 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
>  	if (likely(fdb)) {
>  		/* attempt to update an entry for a local interface */
>  		if (unlikely(fdb->is_local)) {
> -			if (net_ratelimit())
> -				br_warn(br, "received packet on %s with "
> -					"own address as source address\n",
> -					source->dev->name);
> +			net_ratelimited_function(br_warn, br, "received packet on %s "
> +				"with own address as source address\n", source->dev->name);

Hello Kefeng.

When these types of lines are changed, please coalesce the
fragmented format pieces into a single string.

It makes grep a bit easier and 80 columns limits don't
apply to formats.

I think using net_ratelimited_function is not particularly
clarifying here.

Maybe net_ratelimited_function should be removed instead
of its use sites expanded.

Perhaps adding macros like #define br_warn_ratelimited()
would be better.

This comment applies to the whole series.


^ permalink raw reply

* [GIT] [3.13] NFC updates
From: Samuel Ortiz @ 2013-10-15 16:19 UTC (permalink / raw)
  To: John W. Linville; +Cc: Linux Wireless, Linux NFC

Hi John,

This is the first NFC pull request for the 3.13 kernel.

It's a fairly big one, with the following highlights:

- NFC digital layer implementation: Most NFC chipsets implement the NFC
  digital layer in firmware, but others have more basic functionalities
  and expect the host to implement the digital layer. This layer sits
  below the NFC core.

- Sony's port100 support: This is "soft" NFC USB dongle that expects the
  digital layer to be implemented on the host. This is the first user of
  our NFC digital stack implementation.

- Secure element API: We now provide a netlink API for enabling,
  disabling and discovering NFC attached (embedded or UICC ones) secure
  elements. With some userspace help, this allows us to support NFC
  payments.
  Only the pn544 driver currently supports that API.

- NCI SPI fixes and improvements: In order to support NCI devices over
  SPI, we fixed and improved our NCI/SPI implementation. The currently
  most deployed NFC NCI chipset, Broadcom's bcm2079x, supports that mode
  and we're planning to use our NCI/SPI framework to implement a
  driver for it.

- pn533 fragmentation support in target mode: This was the only missing
  feature from our pn533 impementation. We now support fragmentation in
  both Tx and Rx modes, in target mode.

The following changes since commit b75ff5e84bb6c2d43a8ec39b240c80f0543821f0:

  Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (2013-09-19 13:57:28 -0500)

are available in the git repository at:


  git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next.git tags/nfc-next-3.13-1

for you to fetch changes up to ddc1a70b5f2a07a932ed31f989d63937bb813439:

  NFC: Fix SE API related sparse warning (2013-10-07 14:18:44 +0200)

----------------------------------------------------------------
Arron Wang (3):
      NFC: pn544: Add SE discover operation
      NFC: Export nfc_find_se()
      NFC: pn544: Add SE enable/disable operation

Eric Lapuyade (8):
      NFC: NCI: Fix wrong allocation size in nci_spi_allocate_device()
      NFC: NCI: Rename spi ndev -> nsdev and nci_dev -> ndev for consistency
      NFC: Move struct nfc_phy_ops out of HCI up to nfc core level
      NFC: NCI: Simplify NCI SPI to become a simple framing/checking layer
      NFC: NCI: Store the spi device pointer from the spi instance
      NFC: NCI: zero struct spi_transfer variables before usage
      NFC: NCI: nci_spi_recv_frame() now returns (not forward) the read frame
      NFC: NCI: Modify NCI SPI to implement CS/INT handshake per the spec

Fengguang Wu (1):
      NFC: digital: digital_tg_send_sensf_res() can be static

Joe Perches (3):
      NFC: Replace nfc_dev_dbg with dev_dbg
      NFC: Convert nfc_dev_info and nfc_dev_err to nfc_<level>
      NFC: Standardize logging style

Olivier Guiter (3):
      NFC: pn533: Add MI/TG bits only when in Initiator mode
      NFC: pn533: Add support for incoming fragmented frame in target mode
      NFC: pn533: Target mode Tx fragmentation support

Sachin Kamat (2):
      NFC: nfcwilink: Remove redundant dev_set_drvdata
      NFC: pn533: Staticize local symbols

Samuel Ortiz (9):
      NFC: Set active target upon DEP up event reception
      NFC: pn533: Send ATR_REQ directly for active device detection
      NFC: pn533: Start listen timer from start_poll
      NFC: digital: Remove PR_ERR and PR_DBG macros
      NFC: digital: Add newline to pr_* calls
      NFC: Document NFC targets sens_res field
      NFC: Define secure element IO API and commands
      NFC: netlink: SE API implementation
      NFC: Fix SE API related sparse warning

Thierry Escande (12):
      NFC: Digital Protocol stack implementation
      NFC Digital: Implement driver commands mechanism
      NFC Digital: Add NFC-A technology support
      NFC Digital: Add NFC-F technology support
      NFC Digital: Add initiator NFC-DEP support
      NFC Digital: Add target NFC-DEP support
      NFC: rawsock: Fix a memory leak
      NFC: digital: Fix sens_res endiannes handling
      NFC: Sony Port-100 Series driver
      NFC: port100: Commands mechanism implementation
      NFC: port100: Add initiator mode support
      NFC: port100: Add target mode support

 drivers/nfc/Kconfig               |   10 +
 drivers/nfc/Makefile              |    1 +
 drivers/nfc/mei_phy.c             |    6 +-
 drivers/nfc/microread/i2c.c       |   32 +-
 drivers/nfc/microread/mei.c       |    4 +-
 drivers/nfc/microread/microread.c |    7 +-
 drivers/nfc/nfcsim.c              |   38 +-
 drivers/nfc/nfcwilink.c           |   97 +--
 drivers/nfc/pn533.c               |  604 ++++++++++-----
 drivers/nfc/pn544/i2c.c           |   42 +-
 drivers/nfc/pn544/pn544.c         |  129 +++-
 drivers/nfc/port100.c             | 1529 +++++++++++++++++++++++++++++++++++++
 include/net/nfc/digital.h         |  227 ++++++
 include/net/nfc/hci.h             |    6 -
 include/net/nfc/nci.h             |    4 +
 include/net/nfc/nci_core.h        |   46 +-
 include/net/nfc/nfc.h             |   25 +-
 include/uapi/linux/nfc.h          |    4 +
 net/nfc/Kconfig                   |   14 +
 net/nfc/Makefile                  |    2 +
 net/nfc/core.c                    |   22 +-
 net/nfc/digital.h                 |  170 +++++
 net/nfc/digital_core.c            |  737 ++++++++++++++++++
 net/nfc/digital_dep.c             |  729 ++++++++++++++++++
 net/nfc/digital_technology.c      |  770 +++++++++++++++++++
 net/nfc/nci/spi.c                 |  239 +++---
 net/nfc/netlink.c                 |   91 +++
 net/nfc/rawsock.c                 |    7 +-
 28 files changed, 5065 insertions(+), 527 deletions(-)
 create mode 100644 drivers/nfc/port100.c
 create mode 100644 include/net/nfc/digital.h
 create mode 100644 net/nfc/digital.h
 create mode 100644 net/nfc/digital_core.c
 create mode 100644 net/nfc/digital_dep.c
 create mode 100644 net/nfc/digital_technology.c
-- 
Intel Open Source Technology Centre
http://oss.intel.com/

^ permalink raw reply

* Re: [PATCH 1/7] ath10k: fix scheduling while atomic bug
From: Kalle Valo @ 2013-10-15 16:16 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <20131015161434.21869.51150.stgit@localhost6.localdomain6>

Kalle Valo <kvalo@qca.qualcomm.com> writes:

> From: Michal Kazior <michal.kazior@tieto.com>
>
> Recent WMI/HTC changes made it possible for WMI
> commands to sleep (if there's not enough HTC TX
> credits to submit a command). TX path is in an
> atomic context so calling WMI commands in it is
> wrong.
>
> This simply moves WEP key index update to a worker
> and fixes the 'scheduling while atomic' bug.
>
> This still leaves multiple WEP key handling laggy,
> i.e. some frames may be TXed with an old/different
> key (although recipient should still be able to RX
> them).
>
> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>

Please ignore, I sent this accidentally too early.

-- 
Kalle Valo

^ permalink raw reply

* [PATCH 1/7] ath10k: fix scheduling while atomic bug
From: Kalle Valo @ 2013-10-15 16:14 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless

From: Michal Kazior <michal.kazior@tieto.com>

Recent WMI/HTC changes made it possible for WMI
commands to sleep (if there's not enough HTC TX
credits to submit a command). TX path is in an
atomic context so calling WMI commands in it is
wrong.

This simply moves WEP key index update to a worker
and fixes the 'scheduling while atomic' bug.

This still leaves multiple WEP key handling laggy,
i.e. some frames may be TXed with an old/different
key (although recipient should still be able to RX
them).

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/core.h |    4 ++
 drivers/net/wireless/ath/ath10k/mac.c  |   53 ++++++++++++++++++++++----------
 2 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index ce36daa..cef5455 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -215,8 +215,10 @@ struct ath10k_vif {
 	struct ath10k *ar;
 	struct ieee80211_vif *vif;
 
+	struct work_struct wep_key_work;
 	struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1];
-	u8 def_wep_key_index;
+	u8 def_wep_key_idx;
+	u8 def_wep_key_newidx;
 
 	u16 tx_seq_no;
 
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 97d7111..bc0e17b 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1239,7 +1239,7 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
 	/* FIXME: why don't we print error if wmi call fails? */
 	ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
 
-	arvif->def_wep_key_index = 0;
+	arvif->def_wep_key_idx = 0;
 }
 
 static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
@@ -1467,6 +1467,30 @@ static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw,
 	skb_pull(skb, IEEE80211_QOS_CTL_LEN);
 }
 
+static void ath10k_tx_wep_key_work(struct work_struct *work)
+{
+	struct ath10k_vif *arvif = container_of(work, struct ath10k_vif,
+						wep_key_work);
+	int ret, keyidx = arvif->def_wep_key_newidx;
+
+	if (arvif->def_wep_key_idx == keyidx)
+		return;
+
+	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n",
+		   arvif->vdev_id, keyidx);
+
+	ret = ath10k_wmi_vdev_set_param(arvif->ar,
+					arvif->vdev_id,
+					arvif->ar->wmi.vdev_param->def_keyid,
+					keyidx);
+	if (ret) {
+		ath10k_warn("could not update wep keyidx (%d)\n", ret);
+		return;
+	}
+
+	arvif->def_wep_key_idx = keyidx;
+}
+
 static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1475,8 +1499,6 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
 	struct ath10k *ar = arvif->ar;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_key_conf *key = info->control.hw_key;
-	u32 vdev_param;
-	int ret;
 
 	if (!ieee80211_has_protected(hdr->frame_control))
 		return;
@@ -1488,21 +1510,14 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
 	    key->cipher != WLAN_CIPHER_SUITE_WEP104)
 		return;
 
-	if (key->keyidx == arvif->def_wep_key_index)
-		return;
-
-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d keyidx %d\n",
-		   arvif->vdev_id, key->keyidx);
-
-	vdev_param = ar->wmi.vdev_param->def_keyid;
-	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-					key->keyidx);
-	if (ret) {
-		ath10k_warn("could not update wep keyidx (%d)\n", ret);
+	if (key->keyidx == arvif->def_wep_key_idx)
 		return;
-	}
 
-	arvif->def_wep_key_index = key->keyidx;
+	/* FIXME: Most likely a few frames will be TXed with an old key. Simply
+	 * queueing frames until key index is updated is not an option because
+	 * sk_buff may need more processing to be done, e.g. offchannel */
+	arvif->def_wep_key_newidx = key->keyidx;
+	ieee80211_queue_work(ar->hw, &arvif->wep_key_work);
 }
 
 static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb)
@@ -2023,6 +2038,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 	arvif->ar = ar;
 	arvif->vif = vif;
 
+	INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work);
+
 	if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) {
 		ath10k_warn("Only one monitor interface allowed\n");
 		ret = -EBUSY;
@@ -2078,7 +2095,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 
 	vdev_param = ar->wmi.vdev_param->def_keyid;
 	ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param,
-					arvif->def_wep_key_index);
+					arvif->def_wep_key_idx);
 	if (ret)
 		ath10k_warn("Failed to set default keyid: %d\n", ret);
 
@@ -2147,6 +2164,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 
 	mutex_lock(&ar->conf_mutex);
 
+	cancel_work_sync(&arvif->wep_key_work);
+
 	spin_lock_bh(&ar->data_lock);
 	if (arvif->beacon) {
 		dev_kfree_skb_any(arvif->beacon);


^ permalink raw reply related

* [PATCH 12/12] brcmfmac: fix brcmf_sdcard_recv_chain() for host without sg support
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

If the SDIO host controller does not support scatter-gather the glom
superframe must be transfered from the device and the data for each
packet in the queue must be extracted from it.

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c   |   21 ++++++++++++++++++--
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |    2 +-
 .../net/wireless/brcm80211/brcmfmac/sdio_host.h    |    2 +-
 3 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 1103dc1..3e10b80 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -569,8 +569,10 @@ done:
 }
 
 int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-			    uint flags, struct sk_buff_head *pktq)
+			    uint flags, struct sk_buff_head *pktq, uint totlen)
 {
+	struct sk_buff *glom_skb;
+	struct sk_buff *skb;
 	uint width;
 	int err = 0;
 
@@ -582,7 +584,22 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	if (err)
 		goto done;
 
-	err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
+	if (pktq->qlen == 1)
+		err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq->next);
+	else if (!sdiodev->sg_support) {
+		glom_skb = brcmu_pkt_buf_get_skb(totlen);
+		if (!glom_skb)
+			return -ENOMEM;
+		err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, glom_skb);
+		if (err)
+			goto done;
+
+		skb_queue_walk(pktq, skb) {
+			memcpy(skb->data, glom_skb->data, skb->len);
+			skb_pull(glom_skb, skb->len);
+		}
+	} else
+		err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
 
 done:
 	return err;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index c927701..b02953c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1392,7 +1392,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 		sdio_claim_host(bus->sdiodev->func[1]);
 		errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
 				bus->sdiodev->sbwad,
-				SDIO_FUNC_2, F2SYNC, &bus->glom);
+				SDIO_FUNC_2, F2SYNC, &bus->glom, dlen);
 		sdio_release_host(bus->sdiodev->func[1]);
 		bus->sdcnt.f2rxdata++;
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 59c456f..1b034ea 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -225,7 +225,7 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		      uint flags, u8 *buf, uint nbytes);
 extern int
 brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
-			uint flags, struct sk_buff_head *pktq);
+			uint flags, struct sk_buff_head *pktq, uint totlen);
 
 /* Flags bits */
 
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 09/12] brcmfmac: remove stale code from brcmf_sdcard_recv_chain()
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

The function brcmf_sdcard_recv_chain() has been reworked with
commit "brcmfmac: add sdio sg list support", but the incr_fix
variable is only assigned but not used so removing it now.

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index c88e267..92818d79 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -571,7 +571,6 @@ done:
 int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 			    uint flags, struct sk_buff_head *pktq)
 {
-	uint incr_fix;
 	uint width;
 	int err = 0;
 
@@ -583,7 +582,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	if (err)
 		goto done;
 
-	incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
 	err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
 
 done:
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 08/12] brcmfmac: verify result of brcmf_sdio_addrprep() calls
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

Not all calls to the function brcmf_sdio_addrprep() check
the return value, but it may fail so better verify it.

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c |   15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index da02816..c88e267 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -238,7 +238,9 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
 		func_num = SDIO_FUNC_1;
 		reg_size = 4;
 
-		brcmf_sdio_addrprep(sdiodev, reg_size, &addr);
+		ret = brcmf_sdio_addrprep(sdiodev, reg_size, &addr);
+		if (ret)
+			goto done;
 	}
 
 	do {
@@ -254,6 +256,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
 						       func_num, addr, data, 4);
 	} while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
 
+done:
 	if (ret != 0)
 		brcmf_err("failed with %d\n", ret);
 
@@ -605,9 +608,10 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	memcpy(mypkt->data, buf, nbytes);
 
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	brcmf_sdio_addrprep(sdiodev, width, &addr);
+	err = brcmf_sdio_addrprep(sdiodev, width, &addr);
 
-	err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt);
+	if (!err)
+		err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt);
 
 	brcmu_pkt_buf_free_skb(mypkt);
 	return err;
@@ -619,12 +623,15 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		      uint flags, struct sk_buff_head *pktq)
 {
 	uint width;
+	int err;
 
 	brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pktq->qlen);
 
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	brcmf_sdio_addrprep(sdiodev, width, &addr);
+	err = brcmf_sdio_addrprep(sdiodev, width, &addr);
+	if (err)
+		return err;
 
 	if (pktq->qlen == 1)
 		return brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq->next);
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 03/12] brcmfmac: rename variable max_seg_sz to max_seg_cnt for clarity
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

The variable max_seg_sz in brcmf_sdio_buffrw() respresents the maximum
number of buffers that can be sent in one MMC transfer request. Rename
it to max_seg_cnt to avoid confusion.

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index e13b1a6..5dfc96c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -332,7 +332,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 {
 	unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
 	unsigned int max_blks, max_req_sz, orig_offset, dst_offset;
-	unsigned short max_seg_sz, seg_sz;
+	unsigned short max_seg_cnt, seg_sz;
 	unsigned char *pkt_data, *orig_data, *dst_data;
 	struct sk_buff *pkt_next = NULL, *local_pkt_next;
 	struct sk_buff_head local_list, *target_list;
@@ -406,13 +406,14 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 	max_blks = min_t(unsigned int, host->max_blk_count, 511u);
 	max_req_sz = min_t(unsigned int, host->max_req_size,
 			   max_blks * func_blk_sz);
-	max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC);
-	max_seg_sz = min_t(unsigned short, max_seg_sz, target_list->qlen);
+	max_seg_cnt = min_t(unsigned short, host->max_segs,
+			    SG_MAX_SINGLE_ALLOC);
+	max_seg_cnt = min_t(unsigned short, max_seg_cnt, target_list->qlen);
 	seg_sz = target_list->qlen;
 	pkt_offset = 0;
 	pkt_next = target_list->next;
 
-	if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) {
+	if (sg_alloc_table(&st, max_seg_cnt, GFP_KERNEL)) {
 		ret = -ENOMEM;
 		goto exit;
 	}
@@ -444,7 +445,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 				pkt_next = pkt_next->next;
 			}
 
-			if (req_sz >= max_req_sz || sg_cnt >= max_seg_sz)
+			if (req_sz >= max_req_sz || sg_cnt >= max_seg_cnt)
 				break;
 		}
 		seg_sz -= sg_cnt;
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 07/12] brcmfmac: rework single packet transfers
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

The function brcmf_sdio_sglist_rw() does a different code path
when packet queue length is 1. Move this to a separate function
reducing overhead in the calling context.

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c |   81 +++++++++++-----------
 1 file changed, 40 insertions(+), 41 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 344b2d2..da02816 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -314,6 +314,34 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
 		*ret = retval;
 }
 
+static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
+			     bool write, u32 addr, struct sk_buff *pkt)
+{
+	unsigned int req_sz;
+
+	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
+	if (brcmf_pm_resume_error(sdiodev))
+		return -EIO;
+
+	/* Single skb use the standard mmc interface */
+	req_sz = pkt->len + 3;
+	req_sz &= (uint)~3;
+
+	if (write)
+		return sdio_memcpy_toio(sdiodev->func[fn], addr,
+					((u8 *)(pkt->data)),
+					req_sz);
+	else if (fn == 1)
+		return sdio_memcpy_fromio(sdiodev->func[fn],
+					  ((u8 *)(pkt->data)),
+					  addr, req_sz);
+	else
+		/* function 2 read is FIFO operation */
+		return sdio_readsb(sdiodev->func[fn],
+				   ((u8 *)(pkt->data)), addr,
+				   req_sz);
+}
+
 /**
  * brcmf_sdio_sglist_rw - SDIO interface function for block data access
  * @sdiodev: brcmfmac sdio device
@@ -350,27 +378,6 @@ static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
 	if (brcmf_pm_resume_error(sdiodev))
 		return -EIO;
 
-	/* Single skb use the standard mmc interface */
-	if (pktlist->qlen == 1) {
-		pkt_next = pktlist->next;
-		req_sz = pkt_next->len + 3;
-		req_sz &= (uint)~3;
-
-		if (write)
-			return sdio_memcpy_toio(sdiodev->func[fn], addr,
-						((u8 *)(pkt_next->data)),
-						req_sz);
-		else if (fn == 1)
-			return sdio_memcpy_fromio(sdiodev->func[fn],
-						  ((u8 *)(pkt_next->data)),
-						  addr, req_sz);
-		else
-			/* function 2 read is FIFO operation */
-			return sdio_readsb(sdiodev->func[fn],
-					   ((u8 *)(pkt_next->data)), addr,
-					   req_sz);
-	}
-
 	target_list = pktlist;
 	/* for host with broken sg support, prepare a page aligned list */
 	__skb_queue_head_init(&local_list);
@@ -543,7 +550,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 {
 	uint width;
 	int err = 0;
-	struct sk_buff_head pkt_list;
 
 	brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pkt->len);
@@ -553,10 +559,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	if (err)
 		goto done;
 
-	skb_queue_head_init(&pkt_list);
-	skb_queue_tail(&pkt_list, pkt);
-	err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, &pkt_list);
-	skb_dequeue_tail(&pkt_list);
+	err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt);
 
 done:
 	return err;
@@ -589,7 +592,7 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		      uint flags, u8 *buf, uint nbytes)
 {
 	struct sk_buff *mypkt;
-	struct sk_buff_head pktq;
+	uint width;
 	int err;
 
 	mypkt = brcmu_pkt_buf_get_skb(nbytes);
@@ -600,10 +603,11 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	}
 
 	memcpy(mypkt->data, buf, nbytes);
-	__skb_queue_head_init(&pktq);
-	__skb_queue_tail(&pktq, mypkt);
-	err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, &pktq);
-	__skb_dequeue_tail(&pktq);
+
+	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
+	brcmf_sdio_addrprep(sdiodev, width, &addr);
+
+	err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt);
 
 	brcmu_pkt_buf_free_skb(mypkt);
 	return err;
@@ -615,7 +619,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		      uint flags, struct sk_buff_head *pktq)
 {
 	uint width;
-	int err = 0;
 
 	brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pktq->qlen);
@@ -623,9 +626,9 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
 	brcmf_sdio_addrprep(sdiodev, width, &addr);
 
-	err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
-
-	return err;
+	if (pktq->qlen == 1)
+		return brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq->next);
+	return brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
 }
 
 int
@@ -636,7 +639,6 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
 	struct sk_buff *pkt;
 	u32 sdaddr;
 	uint dsize;
-	struct sk_buff_head pkt_list;
 
 	dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
 	pkt = dev_alloc_skb(dsize);
@@ -645,7 +647,6 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
 		return -EIO;
 	}
 	pkt->priority = 0;
-	skb_queue_head_init(&pkt_list);
 
 	/* Determine initial transfer parameters */
 	sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
@@ -673,10 +674,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
 		skb_put(pkt, dsize);
 		if (write)
 			memcpy(pkt->data, data, dsize);
-		skb_queue_tail(&pkt_list, pkt);
-		bcmerror = brcmf_sdio_sglist_rw(sdiodev, SDIO_FUNC_1, write,
-						sdaddr, &pkt_list);
-		skb_dequeue_tail(&pkt_list);
+		bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
+					     sdaddr, pkt);
 		if (bcmerror) {
 			brcmf_err("membytes transfer failed\n");
 			break;
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 10/12] brcmfmac: fix brcmf_sdcard_send_pkt() for host without sg support
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

If the host does not support scatter-gather transmit the packets
in the pktq individually using brcmf_sdio_buffrw().

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c |   14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 92818d79..1103dc1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -620,6 +620,7 @@ int
 brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		      uint flags, struct sk_buff_head *pktq)
 {
+	struct sk_buff *skb;
 	uint width;
 	int err;
 
@@ -631,9 +632,16 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	if (err)
 		return err;
 
-	if (pktq->qlen == 1)
-		return brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq->next);
-	return brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
+	if (pktq->qlen == 1 || !sdiodev->sg_support)
+		skb_queue_walk(pktq, skb) {
+			err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, skb);
+			if (err)
+				break;
+		}
+	else
+		err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
+
+	return err;
 }
 
 int
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 06/12] brcmfmac: rename brcmf_sdio_buffrw()
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

The function brcmf_sdio_buffrw() is intended to be used for
transfering list of packets using scatter-gather functionality.
Rename function to brcmf_sdio_sglist_rw() to clarify this.

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c |   17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index ea716a4..344b2d2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -315,7 +315,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
 }
 
 /**
- * brcmf_sdio_buffrw - SDIO interface function for block data access
+ * brcmf_sdio_sglist_rw - SDIO interface function for block data access
  * @sdiodev: brcmfmac sdio device
  * @fn: SDIO function number
  * @write: direction flag
@@ -326,8 +326,9 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
  * stack for block data access. It assumes that the skb passed down by the
  * caller has already been padded and aligned.
  */
-static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
-			     bool write, u32 addr, struct sk_buff_head *pktlist)
+static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
+				bool write, u32 addr,
+				struct sk_buff_head *pktlist)
 {
 	unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
 	unsigned int max_req_sz, orig_offset, dst_offset;
@@ -554,7 +555,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 
 	skb_queue_head_init(&pkt_list);
 	skb_queue_tail(&pkt_list, pkt);
-	err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, &pkt_list);
+	err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, &pkt_list);
 	skb_dequeue_tail(&pkt_list);
 
 done:
@@ -577,7 +578,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		goto done;
 
 	incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
-	err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq);
+	err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
 
 done:
 	return err;
@@ -622,7 +623,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
 	brcmf_sdio_addrprep(sdiodev, width, &addr);
 
-	err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq);
+	err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
 
 	return err;
 }
@@ -673,8 +674,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
 		if (write)
 			memcpy(pkt->data, data, dsize);
 		skb_queue_tail(&pkt_list, pkt);
-		bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
-					     sdaddr, &pkt_list);
+		bcmerror = brcmf_sdio_sglist_rw(sdiodev, SDIO_FUNC_1, write,
+						sdaddr, &pkt_list);
 		skb_dequeue_tail(&pkt_list);
 		if (bcmerror) {
 			brcmf_err("membytes transfer failed\n");
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 01/12] brcmfmac: store address in trace_brcmf_hexdump()
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

The trace function trace_brcmf_hexdump() stores the length, but
having the address of the buffer being dumped helps putting it
in context.

Reviewed-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
index bc29171..4605a1d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
@@ -78,13 +78,15 @@ TRACE_EVENT(brcmf_hexdump,
 	TP_ARGS(data, len),
 	TP_STRUCT__entry(
 		__field(unsigned long, len)
+		__field(unsigned long, addr)
 		__dynamic_array(u8, hdata, len)
 	),
 	TP_fast_assign(
 		__entry->len = len;
+		__entry->addr = (unsigned long)data;
 		memcpy(__get_dynamic_array(hdata), data, len);
 	),
-	TP_printk("hexdump [length=%lu]", __entry->len)
+	TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len)
 );
 
 TRACE_EVENT(brcmf_bdchdr,
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel

On our internal test setups it turned out that the MMC host controller
did not support scatterlists (struct mmc_host::max_segs == 1). It took
a number of patches to cleanup and support this. While at it some debug
trace functions were modified and added.

Arend van Spriel (12):
  brcmfmac: store address in trace_brcmf_hexdump()
  brcmfmac: add tracepoint for capturing the SDPCM header
  brcmfmac: rename variable max_seg_sz to max_seg_cnt for clarity
  brcmfmac: determine host controller related variables during probe
  brcmfmac: rework scatter-gather code in brcmf_sdio_buffrw()
  brcmfmac: rename brcmf_sdio_buffrw()
  brcmfmac: rework single packet transfers
  brcmfmac: verify result of brcmf_sdio_addrprep() calls
  brcmfmac: remove stale code from brcmf_sdcard_recv_chain()
  brcmfmac: fix brcmf_sdcard_send_pkt() for host without sg support
  brcmfmac: fix brcmf_sdio_txpkt_prep() for host without sg support
  brcmfmac: fix brcmf_sdcard_recv_chain() for host without sg support

 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |  186 +++++++++++---------
 .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |   17 ++
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |  111 +++++++-----
 .../net/wireless/brcm80211/brcmfmac/sdio_host.h    |    6 +-
 .../net/wireless/brcm80211/brcmfmac/tracepoint.h   |   21 ++-
 5 files changed, 216 insertions(+), 125 deletions(-)

-- 
1.7.10.4



^ permalink raw reply

* [PATCH 02/12] brcmfmac: add tracepoint for capturing the SDPCM header
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

Having the SDPCM header information in the traces is a valuable
piece of information.

Reviewed-by: Franky Lin <frankyl@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/dhd_sdio.c   |    3 +++
 drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h |   17 +++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 67f05db..ab1c919 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1147,6 +1147,8 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
 	u8 rx_seq, fc, tx_seq_max;
 	u32 swheader;
 
+	trace_brcmf_sdpcm_hdr(false, header);
+
 	/* hw header */
 	len = get_unaligned_le16(header);
 	checksum = get_unaligned_le16(header + sizeof(u16));
@@ -1269,6 +1271,7 @@ static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header,
 		     SDPCM_DOFFSET_MASK;
 	*(((__le32 *)header) + 1) = cpu_to_le32(sw_header);
 	*(((__le32 *)header) + 2) = 0;
+	trace_brcmf_sdpcm_hdr(true, header);
 }
 
 static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
index 4605a1d..3c67529 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
@@ -110,6 +110,23 @@ TRACE_EVENT(brcmf_bdchdr,
 	TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen)
 );
 
+TRACE_EVENT(brcmf_sdpcm_hdr,
+	TP_PROTO(bool tx, void *data),
+	TP_ARGS(tx, data),
+	TP_STRUCT__entry(
+		__field(u8, tx)
+		__field(u16, len)
+		__array(u8, hdr, 12)
+	),
+	TP_fast_assign(
+		memcpy(__entry->hdr, data, 12);
+		__entry->len = __entry->hdr[0] | (__entry->hdr[1] << 8);
+		__entry->tx = tx ? 1 : 0;
+	),
+	TP_printk("sdpcm: %s len %u, seq %d", __entry->tx ? "TX" : "RX",
+		  __entry->len, __entry->hdr[4])
+);
+
 #ifdef CONFIG_BRCM_TRACING
 
 #undef TRACE_INCLUDE_PATH
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 11/12] brcmfmac: fix brcmf_sdio_txpkt_prep() for host without sg support
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

When running on a host controller that does not support scatter-gather
transfers the function brcmf_sdio_txpkt_prep() should not add tail
padding buffers.

Reviewed-by: Franky Lin <frankyl@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/dhd_sdio.c |  106 ++++++++++++--------
 1 file changed, 64 insertions(+), 42 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index ab1c919..c927701 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1880,6 +1880,56 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
 /* bit mask of data length chopped from the previous packet */
 #define ALIGN_SKB_CHOP_LEN_MASK	0x7fff
 
+static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev,
+				    struct sk_buff_head *pktq,
+				    struct sk_buff *pkt, uint chan)
+{
+	struct sk_buff *pkt_pad;
+	u16 tail_pad, tail_chop, sg_align;
+	unsigned int blksize;
+	u8 *dat_buf;
+	int ntail;
+
+	blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize;
+	sg_align = 4;
+	if (sdiodev->pdata && sdiodev->pdata->sd_sgentry_align > 4)
+		sg_align = sdiodev->pdata->sd_sgentry_align;
+	/* sg entry alignment should be a divisor of block size */
+	WARN_ON(blksize % sg_align);
+
+	/* Check tail padding */
+	pkt_pad = NULL;
+	tail_chop = pkt->len % sg_align;
+	tail_pad = sg_align - tail_chop;
+	tail_pad += blksize - (pkt->len + tail_pad) % blksize;
+	if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) {
+		pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
+		if (pkt_pad == NULL)
+			return -ENOMEM;
+		memcpy(pkt_pad->data,
+		       pkt->data + pkt->len - tail_chop,
+		       tail_chop);
+		*(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
+		skb_trim(pkt, pkt->len - tail_chop);
+		__skb_queue_after(pktq, pkt, pkt_pad);
+	} else {
+		ntail = pkt->data_len + tail_pad -
+			(pkt->end - pkt->tail);
+		if (skb_cloned(pkt) || ntail > 0)
+			if (pskb_expand_head(pkt, 0, ntail, GFP_ATOMIC))
+				return -ENOMEM;
+		if (skb_linearize(pkt))
+			return -ENOMEM;
+		dat_buf = (u8 *)(pkt->data);
+		__skb_put(pkt, tail_pad);
+	}
+
+	if (pkt_pad)
+		return pkt->len + tail_chop;
+	else
+		return pkt->len - tail_pad;
+}
+
 /**
  * brcmf_sdio_txpkt_prep - packet preparation for transmit
  * @bus: brcmf_sdio structure pointer
@@ -1896,24 +1946,16 @@ static int
 brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
 		      uint chan)
 {
-	u16 head_pad, tail_pad, tail_chop, head_align, sg_align;
-	int ntail;
-	struct sk_buff *pkt_next, *pkt_new;
+	u16 head_pad, head_align;
+	struct sk_buff *pkt_next;
 	u8 *dat_buf;
-	unsigned blksize = bus->sdiodev->func[SDIO_FUNC_2]->cur_blksize;
+	int err;
 	struct brcmf_sdio_hdrinfo hd_info = {0};
 
 	/* SDIO ADMA requires at least 32 bit alignment */
 	head_align = 4;
-	sg_align = 4;
-	if (bus->sdiodev->pdata) {
-		head_align = bus->sdiodev->pdata->sd_head_align > 4 ?
-			     bus->sdiodev->pdata->sd_head_align : 4;
-		sg_align = bus->sdiodev->pdata->sd_sgentry_align > 4 ?
-			   bus->sdiodev->pdata->sd_sgentry_align : 4;
-	}
-	/* sg entry alignment should be a divisor of block size */
-	WARN_ON(blksize % sg_align);
+	if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4)
+		head_align = bus->sdiodev->pdata->sd_head_align;
 
 	pkt_next = pktq->next;
 	dat_buf = (u8 *)(pkt_next->data);
@@ -1932,40 +1974,20 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
 		memset(dat_buf, 0, head_pad + bus->tx_hdrlen);
 	}
 
-	/* Check tail padding */
-	pkt_new = NULL;
-	tail_chop = pkt_next->len % sg_align;
-	tail_pad = sg_align - tail_chop;
-	tail_pad += blksize - (pkt_next->len + tail_pad) % blksize;
-	if (skb_tailroom(pkt_next) < tail_pad && pkt_next->len > blksize) {
-		pkt_new = brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
-		if (pkt_new == NULL)
-			return -ENOMEM;
-		memcpy(pkt_new->data,
-		       pkt_next->data + pkt_next->len - tail_chop,
-		       tail_chop);
-		*(u32 *)(pkt_new->cb) = ALIGN_SKB_FLAG + tail_chop;
-		skb_trim(pkt_next, pkt_next->len - tail_chop);
-		__skb_queue_after(pktq, pkt_next, pkt_new);
+	if (bus->sdiodev->sg_support && pktq->qlen > 1) {
+		err = brcmf_sdio_txpkt_prep_sg(bus->sdiodev, pktq,
+					       pkt_next, chan);
+		if (err < 0)
+			return err;
+		hd_info.len = (u16)err;
 	} else {
-		ntail = pkt_next->data_len + tail_pad -
-			(pkt_next->end - pkt_next->tail);
-		if (skb_cloned(pkt_next) || ntail > 0)
-			if (pskb_expand_head(pkt_next, 0, ntail, GFP_ATOMIC))
-				return -ENOMEM;
-		if (skb_linearize(pkt_next))
-			return -ENOMEM;
-		dat_buf = (u8 *)(pkt_next->data);
-		__skb_put(pkt_next, tail_pad);
+		hd_info.len = pkt_next->len;
 	}
 
-	/* Now prep the header */
-	if (pkt_new)
-		hd_info.len = pkt_next->len + tail_chop;
-	else
-		hd_info.len = pkt_next->len - tail_pad;
 	hd_info.channel = chan;
 	hd_info.dat_offset = head_pad + bus->tx_hdrlen;
+
+	/* Now fill the header */
 	brcmf_sdio_hdpack(bus, dat_buf, &hd_info);
 
 	if (BRCMF_BYTES_ON() &&
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 05/12] brcmfmac: rework scatter-gather code in brcmf_sdio_buffrw()
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

Moving a number of assignments outside of the loop as they are
the same for each request.

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c |   34 ++++++++++++----------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 8c4b506..ea716a4 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -409,12 +409,26 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 		goto exit;
 	}
 
+	memset(&mmc_req, 0, sizeof(struct mmc_request));
+	memset(&mmc_cmd, 0, sizeof(struct mmc_command));
+	memset(&mmc_dat, 0, sizeof(struct mmc_data));
+
+	mmc_dat.sg = st.sgl;
+	mmc_dat.blksz = func_blk_sz;
+	mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+	mmc_cmd.opcode = SD_IO_RW_EXTENDED;
+	mmc_cmd.arg = write ? 1<<31 : 0;	/* write flag  */
+	mmc_cmd.arg |= (fn & 0x7) << 28;	/* SDIO func num */
+	mmc_cmd.arg |= 1<<27;			/* block mode */
+	/* for function 1 the addr will be incremented */
+	mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
+	mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+	mmc_req.cmd = &mmc_cmd;
+	mmc_req.data = &mmc_dat;
+
 	while (seg_sz) {
 		req_sz = 0;
 		sg_cnt = 0;
-		memset(&mmc_req, 0, sizeof(struct mmc_request));
-		memset(&mmc_cmd, 0, sizeof(struct mmc_command));
-		memset(&mmc_dat, 0, sizeof(struct mmc_data));
 		sgl = st.sgl;
 		/* prep sg table */
 		while (pkt_next != (struct sk_buff *)target_list) {
@@ -447,22 +461,12 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 			ret = -ENOTBLK;
 			goto exit;
 		}
-		mmc_dat.sg = st.sgl;
+
 		mmc_dat.sg_len = sg_cnt;
-		mmc_dat.blksz = func_blk_sz;
 		mmc_dat.blocks = req_sz / func_blk_sz;
-		mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
-		mmc_cmd.opcode = SD_IO_RW_EXTENDED;
-		mmc_cmd.arg = write ? 1<<31 : 0;	/* write flag  */
-		mmc_cmd.arg |= (fn & 0x7) << 28;	/* SDIO func num */
-		mmc_cmd.arg |= 1<<27;			/* block mode */
-		/* incrementing addr for function 1 */
-		mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
 		mmc_cmd.arg |= (addr & 0x1FFFF) << 9;	/* address */
 		mmc_cmd.arg |= mmc_dat.blocks & 0x1FF;	/* block count */
-		mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
-		mmc_req.cmd = &mmc_cmd;
-		mmc_req.data = &mmc_dat;
+		/* incrementing addr for function 1 */
 		if (fn == 1)
 			addr += req_sz;
 
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 04/12] brcmfmac: determine host controller related variables during probe
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1381844697-24881-1-git-send-email-arend@broadcom.com>

Instead of determining the limits for scatter-gather MMC transfer
request upon each transmit it is now determined during the probe
of the SDIO function.

Reviewed-by: Franky Lin <frankyl@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/bcmsdh.c   |   23 ++++++--------------
 .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |   17 +++++++++++++++
 .../net/wireless/brcm80211/brcmfmac/sdio_host.h    |    4 ++++
 3 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 5dfc96c..8c4b506 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -26,7 +26,6 @@
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
 #include <linux/platform_data/brcmfmac-sdio.h>
 
 #include <defs.h>
@@ -331,7 +330,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 			     bool write, u32 addr, struct sk_buff_head *pktlist)
 {
 	unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
-	unsigned int max_blks, max_req_sz, orig_offset, dst_offset;
+	unsigned int max_req_sz, orig_offset, dst_offset;
 	unsigned short max_seg_cnt, seg_sz;
 	unsigned char *pkt_data, *orig_data, *dst_data;
 	struct sk_buff *pkt_next = NULL, *local_pkt_next;
@@ -341,7 +340,6 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 	struct mmc_data mmc_dat;
 	struct sg_table st;
 	struct scatterlist *sgl;
-	struct mmc_host *host;
 	int ret = 0;
 
 	if (!pktlist->qlen)
@@ -398,17 +396,10 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 		target_list = &local_list;
 	}
 
-	host = sdiodev->func[fn]->card->host;
 	func_blk_sz = sdiodev->func[fn]->cur_blksize;
-	/* Blocks per command is limited by host count, host transfer
-	 * size and the maximum for IO_RW_EXTENDED of 511 blocks.
-	 */
-	max_blks = min_t(unsigned int, host->max_blk_count, 511u);
-	max_req_sz = min_t(unsigned int, host->max_req_size,
-			   max_blks * func_blk_sz);
-	max_seg_cnt = min_t(unsigned short, host->max_segs,
-			    SG_MAX_SINGLE_ALLOC);
-	max_seg_cnt = min_t(unsigned short, max_seg_cnt, target_list->qlen);
+	max_req_sz = sdiodev->max_request_size;
+	max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count,
+			    target_list->qlen);
 	seg_sz = target_list->qlen;
 	pkt_offset = 0;
 	pkt_next = target_list->next;
@@ -429,8 +420,8 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 		while (pkt_next != (struct sk_buff *)target_list) {
 			pkt_data = pkt_next->data + pkt_offset;
 			sg_data_sz = pkt_next->len - pkt_offset;
-			if (sg_data_sz > host->max_seg_size)
-				sg_data_sz = host->max_seg_size;
+			if (sg_data_sz > sdiodev->max_segment_size)
+				sg_data_sz = sdiodev->max_segment_size;
 			if (sg_data_sz > max_req_sz - req_sz)
 				sg_data_sz = max_req_sz - req_sz;
 
@@ -476,7 +467,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 			addr += req_sz;
 
 		mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card);
-		mmc_wait_for_req(host, &mmc_req);
+		mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req);
 
 		ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
 		if (ret != 0) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 2a23bf2..905704e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -21,6 +21,7 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
 #include <linux/suspend.h>
 #include <linux/errno.h>
 #include <linux/sched.h>	/* request_irq() */
@@ -315,6 +316,8 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
 	int err;
 	struct brcmf_sdio_dev *sdiodev;
 	struct brcmf_bus *bus_if;
+	struct mmc_host *host;
+	uint max_blocks;
 
 	brcmf_dbg(SDIO, "Enter\n");
 	brcmf_dbg(SDIO, "Class=%x\n", func->class);
@@ -361,6 +364,20 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
 		brcmf_err("F2 error, probe failed %d...\n", err);
 		goto fail;
 	}
+
+	/*
+	 * determine host related variables after brcmf_sdio_probe()
+	 * as func->cur_blksize is properly set and F2 init has been
+	 * completed successfully.
+	 */
+	host = func->card->host;
+	sdiodev->sg_support = host->max_segs > 1;
+	max_blocks = min_t(uint, host->max_blk_count, 511u);
+	sdiodev->max_request_size = min_t(uint, host->max_req_size,
+					  max_blocks * func->cur_blksize);
+	sdiodev->max_segment_count = min_t(uint, host->max_segs,
+					   SG_MAX_SINGLE_ALLOC);
+	sdiodev->max_segment_size = host->max_seg_size;
 	brcmf_dbg(SDIO, "F2 init completed...\n");
 	return 0;
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 2b5407f..59c456f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -178,6 +178,10 @@ struct brcmf_sdio_dev {
 	bool irq_en;			/* irq enable flags */
 	spinlock_t irq_en_lock;
 	bool irq_wake;			/* irq wake enable flags */
+	bool sg_support;
+	uint max_request_size;
+	ushort max_segment_count;
+	uint max_segment_size;
 };
 
 /* Register/deregister interrupt handler. */
-- 
1.7.10.4



^ permalink raw reply related

* RE: [Ilw] drivers/net/wireless/iwlwifi/dvm/tx.c:456 iwlagn_tx_skb+0x6c5/0x883()
From: Grumbach, Emmanuel @ 2013-10-15 13:35 UTC (permalink / raw)
  To: Sander Eikelenboom
  Cc: John W. Linville, Berg, Johannes, ilw@linux.intel.com,
	netdev@vger.kernel.org, linux-wireless@vger.kernel.org
In-Reply-To: <1127865420.20131015151054@eikelenboom.it>

Please apply this:
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index d131f85..5968f19 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -457,8 +457,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
        WARN_ON_ONCE(is_agg &&
                     priv->queue_to_mac80211[txq_id] != info->hw_queue);
 
-       IWL_DEBUG_TX(priv, "TX to [%d|%d] Q:%d - seq: 0x%x\n", sta_id, tid,
-                    txq_id, seq_number);
+       IWL_DEBUG_TX(priv, "TX to [%d|%d] Q:%d info Q %d - seq: 0x%x\n", sta_id, tid,
+                    txq_id, info->hw_queue, seq_number);
 
        if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id))
                goto drop_unlock_sta;

and send the output back to me

Thanks.

> 
> >>
> >> Hi,
> >>
> >> I'm having a:
> >>
> >> 02:00.0 Network controller: Intel Corporation Centrino Advanced-N 6235
> (rev
> >> 24)
> >>
> >> And i'm running into this warning on boot with a 3.11.2 and 3.12-rc5
> kernel.
> >>
> >> [   23.904950] ------------[ cut here ]------------
> >> [   23.904957] WARNING: CPU: 0 PID: 2531 at
> >> drivers/net/wireless/iwlwifi/dvm/tx.c:456 iwlagn_tx_skb+0x6c5/0x883()
> 
> > Can you reproduce easily?
> > If yes, please reproduce with debug parameters:
> > modprobe iwlwifi debug=0xC0800000
> 
> > Also, please enable MAC80211_HT_DEBUG
> 
> > Thanks
> 
> It happens when starting hostapd:
> 
> [    7.101116] iwlwifi 0000:02:00.0: L1 Disabled; Enabling L0S
> [    7.110722] iwlwifi 0000:02:00.0: Radio type=0x2-0x1-0x0
> [    7.154478] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 9 on FIFO 7 WrPtr: 0
> [    7.157691] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 0 on FIFO 3 WrPtr: 0
> [    7.160812] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 1 on FIFO 2 WrPtr: 0
> [    7.164900] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 2 on FIFO 1 WrPtr: 0
> [    7.165019] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 3 on FIFO 0 WrPtr: 0
> [    7.165139] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 4 on FIFO 0 WrPtr: 0
> [    7.165258] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 5 on FIFO 4 WrPtr: 0
> [    7.165377] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 6 on FIFO 2 WrPtr: 0
> [    7.165495] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 7 on FIFO 5 WrPtr: 0
> [    7.165614] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 8 on FIFO 4 WrPtr: 0
> [    7.165733] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 10 on FIFO 5 WrPtr: 0
> [    7.404295] iwlwifi 0000:02:00.0: L1 Disabled; Enabling L0S
> [    7.415368] iwlwifi 0000:02:00.0: Radio type=0x2-0x1-0x0
> [    7.462417] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 9 on FIFO 7 WrPtr: 0
> [    7.466588] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 0 on FIFO 3 WrPtr: 0
> [    7.470415] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 1 on FIFO 2 WrPtr: 0
> [    7.474144] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 2 on FIFO 1 WrPtr: 0
> [    7.477514] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 3 on FIFO 0 WrPtr: 0
> [    7.480843] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 4 on FIFO 0 WrPtr: 0
> [    7.484148] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 5 on FIFO 4 WrPtr: 0
> [    7.487432] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 6 on FIFO 2 WrPtr: 0
> [    7.490496] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 7 on FIFO 5 WrPtr: 0
> [    7.493534] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 8 on FIFO 4 WrPtr: 0
> [    7.496562] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate
> queue 10 on FIFO 5 WrPtr: 0
> [    7.542143] device wlan0 entered promiscuous mode
> [    7.544749] xen_bridge: port 2(wlan0) entered forwarding state
> [    7.546915] xen_bridge: port 2(wlan0) entered forwarding state
> [    7.548825] cfg80211: Pending regulatory request, waiting for it to be
> processed...
> [    7.552798] ------------[ cut here ]------------
> [    7.554821] WARNING: CPU: 1 PID: 2445 at
> drivers/net/wireless/iwlwifi/dvm/tx.c:456 iwlagn_tx_skb+0x776/0x979()
> [    7.554824] Modules linked in: acpi_cpufreq
> [    7.554827] CPU: 1 PID: 2445 Comm: hostapd Not tainted 3.12.0-rc5+ #1
> [    7.554828] Hardware name:                  /D53427RKE, BIOS
> RKPPT10H.86A.0017.2013.0425.1251 04/25/2013
> [    7.554831]  0000000000000000 0000000000000009 ffffffff818a8082
> 0000000000000000
> [    7.554833]  ffffffff8105a4f2 0000000000000000 ffffffff815f440a
> ffff8800d6df1c80
> [    7.554835]  ffff8800d6cb1790 ffff8800d6df1c80 0000000000000007
> 0000000000000000
> [    7.554835] Call Trace:
> [    7.554842]  [<ffffffff818a8082>] ? dump_stack+0x41/0x51
> [    7.554845]  [<ffffffff8105a4f2>] ? warn_slowpath_common+0x78/0x90
> [    7.554850]  [<ffffffff815f440a>] ? iwlagn_tx_skb+0x776/0x979
> [    7.554852]  [<ffffffff815f440a>] ? iwlagn_tx_skb+0x776/0x979
> [    7.554855]  [<ffffffff815f2407>] ? iwlagn_mac_tx+0x19/0x30
> [    7.554858]  [<ffffffff8187a259>] ? __ieee80211_tx+0x226/0x29b
> [    7.554860]  [<ffffffff8187bcd1>] ? ieee80211_tx+0xa6/0xb5
> [    7.554865]  [<ffffffff8187bf9f>] ?
> ieee80211_monitor_start_xmit+0x1e9/0x204
> [    7.554867]  [<ffffffff8172e1eb>] ? dev_hard_start_xmit+0x271/0x3ec
> [    7.554871]  [<ffffffff81746538>] ? sch_direct_xmit+0x66/0x164
> [    7.554873]  [<ffffffff8172e54b>] ? dev_queue_xmit+0x1e5/0x3c8
> [    7.554876]  [<ffffffff8180bfe6>] ? packet_sendmsg+0xac5/0xb3d
> [    7.554881]  [<ffffffff8171ad95>] ? sock_sendmsg+0x37/0x52
> [    7.554884]  [<ffffffff810f9e0c>] ? __do_fault+0x338/0x36b
> [    7.554886]  [<ffffffff81724bac>] ? verify_iovec+0x44/0x94
> [    7.554889]  [<ffffffff8171b1ef>] ? ___sys_sendmsg+0x1f1/0x283
> [    7.554893]  [<ffffffff81140a73>] ? __inode_wait_for_writeback+0x67/0xae
> [    7.554895]  [<ffffffff8111735e>] ? __cache_free.isra.46+0x178/0x187
> [    7.554897]  [<ffffffff811173b1>] ? kmem_cache_free+0x44/0x84
> [    7.554900]  [<ffffffff81132c22>] ? dentry_kill+0x13d/0x149
> [    7.554902]  [<ffffffff81132f6f>] ? dput+0xe5/0xef
> [    7.554905]  [<ffffffff81136e04>] ? fget_light+0x2e/0x7c
> [    7.554908]  [<ffffffff8171c1ee>] ? __sys_sendmsg+0x39/0x57
> [    7.554911]  [<ffffffff818b5e39>] ? system_call_fastpath+0x16/0x1b
> [    7.554912] ---[ end trace beb2b581b91027a7 ]---
> [    7.554917] iwlwifi 0000:02:00.0: I iwlagn_tx_skb TX to [14|8] Q:7 - seq: 0x0
> [    7.555036] device wlan0 left promiscuous mode
> [    7.555042] xen_bridge: port 2(wlan0) entered disabled state
> [    7.557861] iwlwifi 0000:02:00.0: I iwl_trans_pcie_reclaim [Q 7] 0 -> 1 (1)
> [    7.557865] iwlwifi 0000:02:00.0: I iwlagn_rx_reply_tx TXQ 7 status SUCCESS
> (0x00000201)
> [    7.557867] iwlwifi 0000:02:00.0: I iwlagn_rx_reply_tx
> initial_rate 0x820a retries 0, idx=0 ssn=1 seq_ctl=0x0
> [    7.626274] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x23
> [    7.670694] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x24
> [    7.673864] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x25
> [    7.677083] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x26
> [    7.681410] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x27
> [    7.684761] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x28
> [    7.686906] iwlwifi 0000:02:00.0: I iwl_pcie_txq_unmap Q 9 Free 39


^ permalink raw reply related

* Re: Lower throughput in Ad-hoc than in Infrastructure mode?
From: Felix Fietkau @ 2013-10-15 13:29 UTC (permalink / raw)
  To: Floris Van den Abeele, linux-wireless
In-Reply-To: <525CEE98.3010300@intec.ugent.be>

On 2013-10-15 9:28 AM, Floris Van den Abeele wrote:
> While running throughput experiments using iperf I noticed that UDP
> throughput in ad-hoc mode was considerably lower than in Infrastructure
> mode. The setups I'm comparing is a 802.11a ad-hoc network consisting of
> two clients vs a 802.11a infrastructure network consisting of an access
> point and a client (11a because the tests were run in the 5GHz band).
> 
> For ad-hoc mode I'm consistenly seeing a lower throughput than for
> infrastructure mode: i.e. 22.4 Mbits/sec vs 28.2 Mbits/sec. Note that
> while sniffing the medium radiotap headers report a PHY data rate of
> 54Mbit/s in both cases. There is no other traffic on the Wi-Fi channel
> in question (44). Considering the medium access for both setups is
> similair I would expect to find similair throughputs. Is this a known
> issue with the linux wireless/mac80211/ath9k driver stack or is this
> behaviour conform the 802.11 standard (based on my knowledge I would say
> no to the latter)? My test specs are below.
> 
> For testing I'm using Sparklan WPEA-111N NIC's (AR9280). The nodes are
> running OpenWrt attitude adjusment on r32482 (from 2012-06-21) with the
> REGD patch enabled. I believe that this build of OpenWRT uses the
> compat-wireless-2012-06-14.tar.bz2 drivers.
I'd suggest that you try a recent version of OpenWrt before
investigating further.

- Felix


^ permalink raw reply

* [PATCH 3.12 3/3] mac80211: sanity check WMM/QoS parameters
From: Johannes Berg @ 2013-10-15 13:17 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <1381843030-12260-1-git-send-email-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Check for invalid WMM parameters (AIFSN < 2 or CWmax < CWmin)
and try to set them to usable values in this case.

Notably the Sitecom WL-153 v1 with firmware 1.45 is sending
AIFSN, ECWmin and ECWmax as all zero.

Reported-and-tested-by: Antonio Quartulli <antonio@meshcoding.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mlme.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 86e4ad5..058ae1c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1598,6 +1598,7 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
 	int count;
 	const u8 *pos;
 	u8 uapsd_queues = 0;
+	static const u8 default_aifs[] = { 2, 2, 3, 7 };
 
 	if (!local->ops->conf_tx)
 		return false;
@@ -1664,8 +1665,12 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
 		}
 
 		params.aifs = pos[0] & 0x0f;
+		if (params.aifs < 2)
+			params.aifs = default_aifs[queue];
 		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
 		params.cw_min = ecw2cw(pos[1] & 0x0f);
+		if (params.cw_max < params.cw_min)
+			params.cw_max = params.cw_min;
 		params.txop = get_unaligned_le16(pos + 2);
 		params.acm = acm;
 		params.uapsd = uapsd;
-- 
1.8.4.rc3


^ permalink raw reply related

* [PATCH 3.12 2/3] mac80211: respect rate mask in TX
From: Johannes Berg @ 2013-10-15 13:17 UTC (permalink / raw)
  To: linux-wireless; +Cc: Andrei Otcheretianski
In-Reply-To: <1381843030-12260-1-git-send-email-johannes@sipsolutions.net>

From: Andrei Otcheretianski <andrei.otcheretianski@intel.com>

Bitrate mask were not respected in transmissions, causing (for
example) P2P GO/client to use CCK rates for auth and assoc frames.
Fix it by considering the rate mask in __rate_control_send_low().

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/rate.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 7f7ce11..22b223f 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -235,7 +235,8 @@ static void rc_send_low_basicrate(s8 *idx, u32 basic_rates,
 static void __rate_control_send_low(struct ieee80211_hw *hw,
 				    struct ieee80211_supported_band *sband,
 				    struct ieee80211_sta *sta,
-				    struct ieee80211_tx_info *info)
+				    struct ieee80211_tx_info *info,
+				    u32 rate_mask)
 {
 	int i;
 	u32 rate_flags =
@@ -247,6 +248,9 @@ static void __rate_control_send_low(struct ieee80211_hw *hw,
 
 	info->control.rates[0].idx = 0;
 	for (i = 0; i < sband->n_bitrates; i++) {
+		if (!(rate_mask & BIT(i)))
+			continue;
+
 		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
 			continue;
 
@@ -277,7 +281,8 @@ bool rate_control_send_low(struct ieee80211_sta *pubsta,
 	bool use_basicrate = false;
 
 	if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) {
-		__rate_control_send_low(txrc->hw, sband, pubsta, info);
+		__rate_control_send_low(txrc->hw, sband, pubsta, info,
+					txrc->rate_idx_mask);
 
 		if (!pubsta && txrc->bss) {
 			mcast_rate = txrc->bss_conf->mcast_rate[sband->band];
@@ -659,7 +664,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
 		rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates);
 
 	if (dest[0].idx < 0)
-		__rate_control_send_low(&sdata->local->hw, sband, sta, info);
+		__rate_control_send_low(&sdata->local->hw, sband, sta, info,
+					sdata->rc_rateidx_mask[info->band]);
 
 	if (sta)
 		rate_fixup_ratelist(vif, sband, info, dest, max_rates);
-- 
1.8.4.rc3


^ permalink raw reply related

* [PATCH 3.12 1/3] mac80211: fix honouring rate flags in low-rate transmit
From: Johannes Berg @ 2013-10-15 13:17 UTC (permalink / raw)
  To: linux-wireless; +Cc: Andrei Otcheretianski

From: Andrei Otcheretianski <andrei.otcheretianski@intel.com>

Transmissions with the IEEE80211_TX_CTL_NO_CCK_RATE flag set
(which can come from userspace) were no longer guaranteed to
be transmitted with allowed rates since commit 2103dec14792b
("mac80211: select and adjust bitrates according to channel
mode") due to a missing rate_flags check in that commit. The
commit also introduced the need to check the 5/10 MHz flags
but accidentally didn't. Fix it by adding the missing check.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/rate.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index e126605..7f7ce11 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -247,6 +247,9 @@ static void __rate_control_send_low(struct ieee80211_hw *hw,
 
 	info->control.rates[0].idx = 0;
 	for (i = 0; i < sband->n_bitrates; i++) {
+		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+			continue;
+
 		if (!rate_supported(sta, sband->band, i))
 			continue;
 
-- 
1.8.4.rc3


^ permalink raw reply related

* Re: [Ilw] drivers/net/wireless/iwlwifi/dvm/tx.c:456 iwlagn_tx_skb+0x6c5/0x883()
From: Sander Eikelenboom @ 2013-10-15 13:10 UTC (permalink / raw)
  To: Grumbach, Emmanuel
  Cc: John W. Linville, Berg, Johannes, ilw@linux.intel.com,
	netdev@vger.kernel.org, linux-wireless@vger.kernel.org
In-Reply-To: <0BA3FCBA62E2DC44AF3030971E174FB301DC46E5@HASMSX103.ger.corp.intel.com>


Tuesday, October 15, 2013, 12:52:04 PM, you wrote:

>> 
>> Hi,
>> 
>> I'm having a:
>> 
>> 02:00.0 Network controller: Intel Corporation Centrino Advanced-N 6235 (rev
>> 24)
>> 
>> And i'm running into this warning on boot with a 3.11.2 and 3.12-rc5 kernel.
>> 
>> [   23.904950] ------------[ cut here ]------------
>> [   23.904957] WARNING: CPU: 0 PID: 2531 at
>> drivers/net/wireless/iwlwifi/dvm/tx.c:456 iwlagn_tx_skb+0x6c5/0x883()

> Can you reproduce easily?
> If yes, please reproduce with debug parameters:
> modprobe iwlwifi debug=0xC0800000

> Also, please enable MAC80211_HT_DEBUG

> Thanks

It happens when starting hostapd:

[    7.101116] iwlwifi 0000:02:00.0: L1 Disabled; Enabling L0S
[    7.110722] iwlwifi 0000:02:00.0: Radio type=0x2-0x1-0x0
[    7.154478] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 9 on FIFO 7 WrPtr: 0
[    7.157691] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 0 on FIFO 3 WrPtr: 0
[    7.160812] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 1 on FIFO 2 WrPtr: 0
[    7.164900] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 2 on FIFO 1 WrPtr: 0
[    7.165019] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 3 on FIFO 0 WrPtr: 0
[    7.165139] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 4 on FIFO 0 WrPtr: 0
[    7.165258] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 5 on FIFO 4 WrPtr: 0
[    7.165377] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 6 on FIFO 2 WrPtr: 0
[    7.165495] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 7 on FIFO 5 WrPtr: 0
[    7.165614] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 8 on FIFO 4 WrPtr: 0
[    7.165733] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 10 on FIFO 5 WrPtr: 0
[    7.404295] iwlwifi 0000:02:00.0: L1 Disabled; Enabling L0S
[    7.415368] iwlwifi 0000:02:00.0: Radio type=0x2-0x1-0x0
[    7.462417] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 9 on FIFO 7 WrPtr: 0
[    7.466588] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 0 on FIFO 3 WrPtr: 0
[    7.470415] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 1 on FIFO 2 WrPtr: 0
[    7.474144] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 2 on FIFO 1 WrPtr: 0
[    7.477514] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 3 on FIFO 0 WrPtr: 0
[    7.480843] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 4 on FIFO 0 WrPtr: 0
[    7.484148] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 5 on FIFO 4 WrPtr: 0
[    7.487432] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 6 on FIFO 2 WrPtr: 0
[    7.490496] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 7 on FIFO 5 WrPtr: 0
[    7.493534] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 8 on FIFO 4 WrPtr: 0
[    7.496562] iwlwifi 0000:02:00.0: U iwl_trans_pcie_txq_enable Activate queue 10 on FIFO 5 WrPtr: 0
[    7.542143] device wlan0 entered promiscuous mode
[    7.544749] xen_bridge: port 2(wlan0) entered forwarding state
[    7.546915] xen_bridge: port 2(wlan0) entered forwarding state
[    7.548825] cfg80211: Pending regulatory request, waiting for it to be processed...
[    7.552798] ------------[ cut here ]------------
[    7.554821] WARNING: CPU: 1 PID: 2445 at drivers/net/wireless/iwlwifi/dvm/tx.c:456 iwlagn_tx_skb+0x776/0x979()
[    7.554824] Modules linked in: acpi_cpufreq
[    7.554827] CPU: 1 PID: 2445 Comm: hostapd Not tainted 3.12.0-rc5+ #1
[    7.554828] Hardware name:                  /D53427RKE, BIOS RKPPT10H.86A.0017.2013.0425.1251 04/25/2013
[    7.554831]  0000000000000000 0000000000000009 ffffffff818a8082 0000000000000000
[    7.554833]  ffffffff8105a4f2 0000000000000000 ffffffff815f440a ffff8800d6df1c80
[    7.554835]  ffff8800d6cb1790 ffff8800d6df1c80 0000000000000007 0000000000000000
[    7.554835] Call Trace:
[    7.554842]  [<ffffffff818a8082>] ? dump_stack+0x41/0x51
[    7.554845]  [<ffffffff8105a4f2>] ? warn_slowpath_common+0x78/0x90
[    7.554850]  [<ffffffff815f440a>] ? iwlagn_tx_skb+0x776/0x979
[    7.554852]  [<ffffffff815f440a>] ? iwlagn_tx_skb+0x776/0x979
[    7.554855]  [<ffffffff815f2407>] ? iwlagn_mac_tx+0x19/0x30
[    7.554858]  [<ffffffff8187a259>] ? __ieee80211_tx+0x226/0x29b
[    7.554860]  [<ffffffff8187bcd1>] ? ieee80211_tx+0xa6/0xb5
[    7.554865]  [<ffffffff8187bf9f>] ? ieee80211_monitor_start_xmit+0x1e9/0x204
[    7.554867]  [<ffffffff8172e1eb>] ? dev_hard_start_xmit+0x271/0x3ec
[    7.554871]  [<ffffffff81746538>] ? sch_direct_xmit+0x66/0x164
[    7.554873]  [<ffffffff8172e54b>] ? dev_queue_xmit+0x1e5/0x3c8
[    7.554876]  [<ffffffff8180bfe6>] ? packet_sendmsg+0xac5/0xb3d
[    7.554881]  [<ffffffff8171ad95>] ? sock_sendmsg+0x37/0x52
[    7.554884]  [<ffffffff810f9e0c>] ? __do_fault+0x338/0x36b
[    7.554886]  [<ffffffff81724bac>] ? verify_iovec+0x44/0x94
[    7.554889]  [<ffffffff8171b1ef>] ? ___sys_sendmsg+0x1f1/0x283
[    7.554893]  [<ffffffff81140a73>] ? __inode_wait_for_writeback+0x67/0xae
[    7.554895]  [<ffffffff8111735e>] ? __cache_free.isra.46+0x178/0x187
[    7.554897]  [<ffffffff811173b1>] ? kmem_cache_free+0x44/0x84
[    7.554900]  [<ffffffff81132c22>] ? dentry_kill+0x13d/0x149
[    7.554902]  [<ffffffff81132f6f>] ? dput+0xe5/0xef
[    7.554905]  [<ffffffff81136e04>] ? fget_light+0x2e/0x7c
[    7.554908]  [<ffffffff8171c1ee>] ? __sys_sendmsg+0x39/0x57
[    7.554911]  [<ffffffff818b5e39>] ? system_call_fastpath+0x16/0x1b
[    7.554912] ---[ end trace beb2b581b91027a7 ]---
[    7.554917] iwlwifi 0000:02:00.0: I iwlagn_tx_skb TX to [14|8] Q:7 - seq: 0x0
[    7.555036] device wlan0 left promiscuous mode
[    7.555042] xen_bridge: port 2(wlan0) entered disabled state
[    7.557861] iwlwifi 0000:02:00.0: I iwl_trans_pcie_reclaim [Q 7] 0 -> 1 (1)
[    7.557865] iwlwifi 0000:02:00.0: I iwlagn_rx_reply_tx TXQ 7 status SUCCESS (0x00000201)
[    7.557867] iwlwifi 0000:02:00.0: I iwlagn_rx_reply_tx                               initial_rate 0x820a retries 0, idx=0 ssn=1 seq_ctl=0x0
[    7.626274] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x23
[    7.670694] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x24
[    7.673864] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x25
[    7.677083] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x26
[    7.681410] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x27
[    7.684761] iwlwifi 0000:02:00.0: I iwl_pcie_txq_inc_wr_ptr Q:9 WR: 0x28
[    7.686906] iwlwifi 0000:02:00.0: I iwl_pcie_txq_unmap Q 9 Free 39


^ permalink raw reply

* Re: [PATCH 3.12] rt2x00: check if device is still available on rt2x00mac_flush()
From: Helmut Schaa @ 2013-10-15 13:00 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: linux-wireless, rt2x00 Users List
In-Reply-To: <20131015123112.GB6417@localhost.localdomain>

On Tue, Oct 15, 2013 at 2:31 PM, Stanislaw Gruszka <stf_xl@wp.pl> wrote:
> Fix random kernel panic with below messages when remove dongle.
>
> [ 2212.355447] BUG: unable to handle kernel NULL pointer dereference at 0000000000000250
> [ 2212.355527] IP: [<ffffffffa02667f2>] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb]
> [ 2212.355599] PGD 0
> [ 2212.355626] Oops: 0000 [#1] SMP
> [ 2212.355664] Modules linked in: rt2800usb rt2x00usb rt2800lib crc_ccitt rt2x00lib mac80211 cfg80211 tun arc4 fuse rfcomm bnep snd_hda_codec_realtek snd_hda_intel snd_hda_codec btusb uvcvideo bluetooth snd_hwdep x86_pkg_temp_thermal snd_seq coretemp aesni_intel aes_x86_64 snd_seq_device glue_helper snd_pcm ablk_helper videobuf2_vmalloc sdhci_pci videobuf2_memops videobuf2_core sdhci videodev mmc_core serio_raw snd_page_alloc microcode i2c_i801 snd_timer hid_multitouch thinkpad_acpi lpc_ich mfd_core snd tpm_tis wmi tpm tpm_bios soundcore acpi_cpufreq i915 i2c_algo_bit drm_kms_helper drm i2c_core video [last unloaded: cfg80211]
> [ 2212.356224] CPU: 0 PID: 34 Comm: khubd Not tainted 3.12.0-rc3-wl+ #3
> [ 2212.356268] Hardware name: LENOVO 3444CUU/3444CUU, BIOS G6ET93WW (2.53 ) 02/04/2013
> [ 2212.356319] task: ffff880212f687c0 ti: ffff880212f66000 task.ti: ffff880212f66000
> [ 2212.356392] RIP: 0010:[<ffffffffa02667f2>]  [<ffffffffa02667f2>] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb]
> [ 2212.356481] RSP: 0018:ffff880212f67750  EFLAGS: 00010202
> [ 2212.356519] RAX: 000000000000000c RBX: 000000000000000c RCX: 0000000000000293
> [ 2212.356568] RDX: ffff8801f4dc219a RSI: 0000000000000000 RDI: 0000000000000240
> [ 2212.356617] RBP: ffff880212f67778 R08: ffffffffa02667e0 R09: 0000000000000002
> [ 2212.356665] R10: 0001f95254ab4b40 R11: ffff880212f675be R12: ffff8801f4dc2150
> [ 2212.356712] R13: 0000000000000000 R14: ffffffffa02667e0 R15: 000000000000000d
> [ 2212.356761] FS:  0000000000000000(0000) GS:ffff88021e200000(0000) knlGS:0000000000000000
> [ 2212.356813] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 2212.356852] CR2: 0000000000000250 CR3: 0000000001a0c000 CR4: 00000000001407f0
> [ 2212.356899] Stack:
> [ 2212.356917]  000000000000000c ffff8801f4dc2150 0000000000000000 ffffffffa02667e0
> [ 2212.356980]  000000000000000d ffff880212f677b8 ffffffffa03a31ad ffff8801f4dc219a
> [ 2212.357038]  ffff8801f4dc2150 0000000000000000 ffff8800b93217a0 ffff8801f49bc800
> [ 2212.357099] Call Trace:
> [ 2212.357122]  [<ffffffffa02667e0>] ? rt2x00usb_interrupt_txdone+0x90/0x90 [rt2x00usb]
> [ 2212.357174]  [<ffffffffa03a31ad>] rt2x00queue_for_each_entry+0xed/0x170 [rt2x00lib]
> [ 2212.357244]  [<ffffffffa026701c>] rt2x00usb_kick_queue+0x5c/0x60 [rt2x00usb]
> [ 2212.357314]  [<ffffffffa03a3682>] rt2x00queue_flush_queue+0x62/0xa0 [rt2x00lib]
> [ 2212.357386]  [<ffffffffa03a2930>] rt2x00mac_flush+0x30/0x70 [rt2x00lib]
> [ 2212.357470]  [<ffffffffa04edded>] ieee80211_flush_queues+0xbd/0x140 [mac80211]
> [ 2212.357555]  [<ffffffffa0502e52>] ieee80211_set_disassoc+0x2d2/0x3d0 [mac80211]
> [ 2212.357645]  [<ffffffffa0506da3>] ieee80211_mgd_deauth+0x1d3/0x240 [mac80211]
> [ 2212.357718]  [<ffffffff8108b17c>] ? try_to_wake_up+0xec/0x290
> [ 2212.357788]  [<ffffffffa04dbd18>] ieee80211_deauth+0x18/0x20 [mac80211]
> [ 2212.357872]  [<ffffffffa0418ddc>] cfg80211_mlme_deauth+0x9c/0x140 [cfg80211]
> [ 2212.357913]  [<ffffffffa041907c>] cfg80211_mlme_down+0x5c/0x60 [cfg80211]
> [ 2212.357962]  [<ffffffffa041cd18>] cfg80211_disconnect+0x188/0x1a0 [cfg80211]
> [ 2212.358014]  [<ffffffffa04013bc>] ? __cfg80211_stop_sched_scan+0x1c/0x130 [cfg80211]
> [ 2212.358067]  [<ffffffffa03f8954>] cfg80211_leave+0xc4/0xe0 [cfg80211]
> [ 2212.358124]  [<ffffffffa03f8d1b>] cfg80211_netdev_notifier_call+0x3ab/0x5e0 [cfg80211]
> [ 2212.358177]  [<ffffffff815140f8>] ? inetdev_event+0x38/0x510
> [ 2212.358217]  [<ffffffff81085a94>] ? __wake_up+0x44/0x50
> [ 2212.358254]  [<ffffffff8155995c>] notifier_call_chain+0x4c/0x70
> [ 2212.358293]  [<ffffffff81081156>] raw_notifier_call_chain+0x16/0x20
> [ 2212.358361]  [<ffffffff814b6dd5>] call_netdevice_notifiers_info+0x35/0x60
> [ 2212.358429]  [<ffffffff814b6ec9>] __dev_close_many+0x49/0xd0
> [ 2212.358487]  [<ffffffff814b7028>] dev_close_many+0x88/0x100
> [ 2212.358546]  [<ffffffff814b8150>] rollback_registered_many+0xb0/0x220
> [ 2212.358612]  [<ffffffff814b8319>] unregister_netdevice_many+0x19/0x60
> [ 2212.358694]  [<ffffffffa04d8eb2>] ieee80211_remove_interfaces+0x112/0x190 [mac80211]
> [ 2212.358791]  [<ffffffffa04c585f>] ieee80211_unregister_hw+0x4f/0x100 [mac80211]
> [ 2212.361994]  [<ffffffffa03a1221>] rt2x00lib_remove_dev+0x161/0x1a0 [rt2x00lib]
> [ 2212.365240]  [<ffffffffa0266e2e>] rt2x00usb_disconnect+0x2e/0x70 [rt2x00usb]
> [ 2212.368470]  [<ffffffff81419ce4>] usb_unbind_interface+0x64/0x1c0
> [ 2212.371734]  [<ffffffff813b446f>] __device_release_driver+0x7f/0xf0
> [ 2212.374999]  [<ffffffff813b4503>] device_release_driver+0x23/0x30
> [ 2212.378131]  [<ffffffff813b3c98>] bus_remove_device+0x108/0x180
> [ 2212.381358]  [<ffffffff813b0565>] device_del+0x135/0x1d0
> [ 2212.384454]  [<ffffffff81417760>] usb_disable_device+0xb0/0x270
> [ 2212.387451]  [<ffffffff8140d9cd>] usb_disconnect+0xad/0x1d0
> [ 2212.390294]  [<ffffffff8140f6cd>] hub_thread+0x63d/0x1660
> [ 2212.393034]  [<ffffffff8107c860>] ? wake_up_atomic_t+0x30/0x30
> [ 2212.395728]  [<ffffffff8140f090>] ? hub_port_debounce+0x130/0x130
> [ 2212.398412]  [<ffffffff8107baa0>] kthread+0xc0/0xd0
> [ 2212.401058]  [<ffffffff8107b9e0>] ? insert_kthread_work+0x40/0x40
> [ 2212.403639]  [<ffffffff8155de3c>] ret_from_fork+0x7c/0xb0
> [ 2212.406193]  [<ffffffff8107b9e0>] ? insert_kthread_work+0x40/0x40
> [ 2212.408732] Code: 24 58 08 00 00 bf 80 00 00 00 e8 3a c3 e0 e0 5b 41 5c 5d c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 53 <48> 8b 47 10 48 89 fb 4c 8b 6f 28 4c 8b 20 49 8b 04 24 4c 8b 30
> [ 2212.414671] RIP  [<ffffffffa02667f2>] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb]
> [ 2212.417646]  RSP <ffff880212f67750>
> [ 2212.420547] CR2: 0000000000000250
> [ 2212.441024] ---[ end trace 5442918f33832bce ]---
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>

Good catch Stanislaw! Fix looks good to me.

Acked-by: Helmut Schaa <helmut.schaa@googlemail.com>

> ---
>  drivers/net/wireless/rt2x00/rt2x00mac.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
> index 51f17cf..7c15785 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00mac.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
> @@ -754,6 +754,9 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
>         struct rt2x00_dev *rt2x00dev = hw->priv;
>         struct data_queue *queue;
>
> +       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
> +               return;
> +
>         tx_queue_for_each(rt2x00dev, queue)
>                 rt2x00queue_flush_queue(queue, drop);
>  }
> --
> 1.7.4.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox