Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 1/7] wil6210: 'length' in Tx/Rx descriptors is little endian
From: Vladimir Kondratiev @ 2013-05-12 11:43 UTC (permalink / raw)
  To: John W . Linville; +Cc: Vladimir Kondratiev, linux-wireless, Luis R . Rodriguez
In-Reply-To: <1368359018-20870-1-git-send-email-qca_vkondrat@qca.qualcomm.com>

Hardware uses little endian for the Tx/Rx descriptors field 'length',
do appropriate conversions

Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
---
 drivers/net/wireless/ath/wil6210/debugfs.c |  8 +++++++-
 drivers/net/wireless/ath/wil6210/txrx.c    | 33 +++++++++++++++++++-----------
 drivers/net/wireless/ath/wil6210/txrx.h    |  4 ++--
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 4be07f5..b32c58e 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -418,9 +418,15 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
 		if (skb) {
 			unsigned char printbuf[16 * 3 + 2];
 			int i = 0;
-			int len = skb_headlen(skb);
+			int len = le16_to_cpu(d->dma.length);
 			void *p = skb->data;
 
+			if (len != skb_headlen(skb)) {
+				seq_printf(s, "!!! len: desc = %d skb = %d\n",
+					   len, skb_headlen(skb));
+				len = min_t(int, len, skb_headlen(skb));
+			}
+
 			seq_printf(s, "    len = %d\n", len);
 
 			while (i < len) {
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 91454a4..b9cac7d 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -108,19 +108,21 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
 	size_t sz = vring->size * sizeof(vring->va[0]);
 
 	while (!wil_vring_is_empty(vring)) {
+		u16 dmalen;
 		if (tx) {
 			volatile struct vring_tx_desc *d =
 					&vring->va[vring->swtail].tx;
 			dma_addr_t pa = d->dma.addr_low |
 					((u64)d->dma.addr_high << 32);
 			struct sk_buff *skb = vring->ctx[vring->swtail];
+			dmalen = le16_to_cpu(d->dma.length);
 			if (skb) {
-				dma_unmap_single(dev, pa, d->dma.length,
+				dma_unmap_single(dev, pa, dmalen,
 						 DMA_TO_DEVICE);
 				dev_kfree_skb_any(skb);
 				vring->ctx[vring->swtail] = NULL;
 			} else {
-				dma_unmap_page(dev, pa, d->dma.length,
+				dma_unmap_page(dev, pa, dmalen,
 					       DMA_TO_DEVICE);
 			}
 			vring->swtail = wil_vring_next_tail(vring);
@@ -130,8 +132,8 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
 			dma_addr_t pa = d->dma.addr_low |
 					((u64)d->dma.addr_high << 32);
 			struct sk_buff *skb = vring->ctx[vring->swhead];
-			dma_unmap_single(dev, pa, d->dma.length,
-					 DMA_FROM_DEVICE);
+			dmalen = le16_to_cpu(d->dma.length);
+			dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE);
 			kfree_skb(skb);
 			wil_vring_advance_head(vring, 1);
 		}
@@ -177,7 +179,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
 	/* b11 don't care */
 	/* error don't care */
 	d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
-	d->dma.length = sz;
+	d->dma.length = cpu_to_le16(sz);
 	vring->ctx[i] = skb;
 
 	return 0;
@@ -328,6 +330,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
 	struct sk_buff *skb;
 	dma_addr_t pa;
 	unsigned int sz = RX_BUF_LEN;
+	u16 dmalen;
 	u8 ftype;
 	u8 ds_bits;
 
@@ -345,10 +348,11 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
 	pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
 	skb = vring->ctx[vring->swhead];
 	dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
-	skb_trim(skb, d->dma.length);
 
 	d1 = wil_skb_rxdesc(skb);
 	*d1 = *d;
+	dmalen = le16_to_cpu(d1->dma.length);
+	skb_trim(skb, dmalen);
 
 	wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1);
 
@@ -612,7 +616,7 @@ static int wil_tx_desc_map(volatile struct vring_tx_desc *d,
 	d->dma.b11 = 0/*14 | BIT(7)*/;
 	d->dma.error = 0;
 	d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
-	d->dma.length = len;
+	d->dma.length = cpu_to_le16((u16)len);
 	d->dma.d0 = 0;
 	d->mac.d[0] = 0;
 	d->mac.d[1] = 0;
@@ -707,14 +711,17 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	/* unmap what we have mapped */
 	/* Note: increment @f to operate with positive index */
 	for (f++; f > 0; f--) {
+		u16 dmalen;
+
 		i = (swhead + f) % vring->size;
 		d = &(vring->va[i].tx);
 		d->dma.status = TX_DMA_STATUS_DU;
 		pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
+		dmalen = le16_to_cpu(d->dma.length);
 		if (vring->ctx[i])
-			dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
+			dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
 		else
-			dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
+			dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
 	}
 
 	return -EINVAL;
@@ -794,15 +801,17 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
 		struct vring_tx_desc dd, *d = &dd;
 		dma_addr_t pa;
 		struct sk_buff *skb;
+		u16 dmalen;
 
 		dd = *d1;
 
 		if (!(d->dma.status & TX_DMA_STATUS_DU))
 			break;
 
+		dmalen = le16_to_cpu(d->dma.length);
 		wil_dbg_txrx(wil,
 			     "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n",
-			     vring->swtail, d->dma.length, d->dma.status,
+			     vring->swtail, dmalen, d->dma.status,
 			     d->dma.error);
 		wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4,
 				  (const void *)d, sizeof(*d), false);
@@ -817,11 +826,11 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
 				ndev->stats.tx_errors++;
 			}
 
-			dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
+			dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
 			dev_kfree_skb_any(skb);
 			vring->ctx[vring->swtail] = NULL;
 		} else {
-			dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
+			dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
 		}
 		d->dma.addr_low = 0;
 		d->dma.addr_high = 0;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index adef12f..a40aa0b 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -222,7 +222,7 @@ struct vring_tx_dma {
 	u8  b11;       /* 0..6: mac_length; 7:ip_version */
 	u8  error;     /* 0..2: err; 3..7: reserved; */
 	u8  status;    /* 0: used; 1..7; reserved */
-	u16 length;
+	__le16 length;
 } __packed;
 
 /*
@@ -321,7 +321,7 @@ struct vring_rx_dma {
 	u8  b11;
 	u8  error;
 	u8  status;
-	u16 length;
+	__le16 length;
 } __packed;
 
 struct vring_tx_desc {
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 0/7] wil6210 patches
From: Vladimir Kondratiev @ 2013-05-12 11:43 UTC (permalink / raw)
  To: John W . Linville; +Cc: Vladimir Kondratiev, linux-wireless, Luis R . Rodriguez

Next bunch of patches.

This time it is all about data path, save for trace support.

Vladimir Kondratiev (7):
  wil6210: 'length' in Tx/Rx descriptors is little endian
  wil6210: Sanity check for reported DMA length
  wil6210: debug dump packet content right after DMA
  wil6210: trace support
  wil6210: use NAPI
  wil6210: fix remaining use of non-cached copy of tx/rx descriptors
  wil6210: do not stop Tx queue on packet drop

 drivers/net/wireless/ath/wil6210/Kconfig     |  12 ++
 drivers/net/wireless/ath/wil6210/Makefile    |  21 ++-
 drivers/net/wireless/ath/wil6210/debug.c     |  70 ++++++++
 drivers/net/wireless/ath/wil6210/debugfs.c   |   8 +-
 drivers/net/wireless/ath/wil6210/interrupt.c |  29 ++--
 drivers/net/wireless/ath/wil6210/main.c      |   6 +
 drivers/net/wireless/ath/wil6210/netdev.c    |  54 ++++++
 drivers/net/wireless/ath/wil6210/trace.c     |  20 +++
 drivers/net/wireless/ath/wil6210/trace.h     | 235 +++++++++++++++++++++++++++
 drivers/net/wireless/ath/wil6210/txrx.c      | 175 ++++++++++++--------
 drivers/net/wireless/ath/wil6210/txrx.h      |  32 +++-
 drivers/net/wireless/ath/wil6210/wil6210.h   |  26 ++-
 drivers/net/wireless/ath/wil6210/wmi.c       |   8 +-
 13 files changed, 589 insertions(+), 107 deletions(-)
 create mode 100644 drivers/net/wireless/ath/wil6210/debug.c
 create mode 100644 drivers/net/wireless/ath/wil6210/trace.c
 create mode 100644 drivers/net/wireless/ath/wil6210/trace.h

-- 
1.8.1.2


^ permalink raw reply

* Re: Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: Arend van Spriel @ 2013-05-12 10:34 UTC (permalink / raw)
  To: JoSH Lehan; +Cc: Adrian Chadd, linux-wireless, Luis R. Rodriguez
In-Reply-To: <CAJ-VmonOuhBgXa3-LkspaCgAAh8Y9Jxejn-McVourzgE-ajHTw@mail.gmail.com>

On 05/12/2013 02:46 AM, Adrian Chadd wrote:
> Hi,
>
> On 11 May 2013 15:54, JoSH Lehan <krellan@gmail.com> wrote:
>
>> Thanks!  So, I'll need to maintain two sets of mac80211/cfg80211
>> modules: one for drivers that were compiled along with the kernel, and
>> another for drivers that were compiled as part of the compat-drivers
>> package.
>
> No, you or the vendor should forward port it to linux-next, then you
> can just pick up the whole driver/framework set from compat-wireless.

That is indeed the approach. So integrate your vendor provided driver 
into your local linux-next tree and create you own compat-drivers 
package using that tree (see [1]). You have to tinker the framework to 
include that driver.

Regards,
Arend

[1] 
https://backports.wiki.kernel.org/index.php/Documentation/compat-drivers/hacking



^ permalink raw reply

* [PATCH 4/4] wlcore: fix occasional AP TX stop after recovery
From: Eliad Peller @ 2013-05-12  9:35 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1368351331-6914-1-git-send-email-eliad@wizery.com>

From: Victor Goldenshtein <victorg@ti.com>

The fw_status wasn't zeroed during allocation, resulting
in uninitialized var usage, and finally causing AP
traffic stop after recovery.

The wrong value in fw_status_2->counters.tx_lnk_free_pkts
led to a bad lnk->allocated_pkts calculation in
wlcore_fw_status(), causing wl18xx_lnk_low_prio() to return
FALSE (lnk->allocated_pkts > thold).
This eventually blocked the link in wlcore_tx_work_locked(),
as wl1271_skb_dequeue() continuously returned NULL.

Fix it by zeroing wl->fw_status_1/2 during allocation.

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/ti/wlcore/main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index ecbbd38..2537391 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -970,7 +970,7 @@ static int wlcore_fw_wakeup(struct wl1271 *wl)
 
 static int wl1271_setup(struct wl1271 *wl)
 {
-	wl->fw_status_1 = kmalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
+	wl->fw_status_1 = kzalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
 				  sizeof(*wl->fw_status_2) +
 				  wl->fw_status_priv_len, GFP_KERNEL);
 	if (!wl->fw_status_1)
@@ -980,7 +980,7 @@ static int wl1271_setup(struct wl1271 *wl)
 				(((u8 *) wl->fw_status_1) +
 				WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc));
 
-	wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
+	wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
 	if (!wl->tx_res_if) {
 		kfree(wl->fw_status_1);
 		return -ENOMEM;
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 3/4] wlcore: hold jiffies in unsigned long
From: Eliad Peller @ 2013-05-12  9:35 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1368351331-6914-1-git-send-email-eliad@wizery.com>

From: Arik Nemtsov <arik@wizery.com>

u32 can be incorrect (too small) for some architectures.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/ti/wlcore/ps.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c
index 9654577..98066d4 100644
--- a/drivers/net/wireless/ti/wlcore/ps.c
+++ b/drivers/net/wireless/ti/wlcore/ps.c
@@ -110,7 +110,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
 	DECLARE_COMPLETION_ONSTACK(compl);
 	unsigned long flags;
 	int ret;
-	u32 start_time = jiffies;
+	unsigned long start_time = jiffies;
 	bool pending = false;
 
 	/*
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 2/4] wlcore: cancel channel switch work on interface removal
From: Eliad Peller @ 2013-05-12  9:35 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1368351331-6914-1-git-send-email-eliad@wizery.com>

From: Arik Nemtsov <arik@wizery.com>

Otherwise, if the work is pending, we might get
a bad dereference after the interface is removed.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/ti/wlcore/main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index c384bad..ecbbd38 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2589,6 +2589,7 @@ unlock:
 	cancel_work_sync(&wlvif->rx_streaming_enable_work);
 	cancel_work_sync(&wlvif->rx_streaming_disable_work);
 	cancel_delayed_work_sync(&wlvif->connection_loss_work);
+	cancel_delayed_work_sync(&wlvif->channel_switch_work);
 
 	mutex_lock(&wl->mutex);
 }
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 1/4] wlcore: set default_wep_key when configured
From: Eliad Peller @ 2013-05-12  9:35 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Yoni Divinsky <yoni.divinsky@ti.com>

When associating to an AP with WEP set the
default key upon association by implementing
the set_deafult_key_idx op.

Fixes auto-arp sent with wrong key_idx bug.

Signed-off-by: Yoni Divinsky <yoni.divinsky@ti.com>
Signed-off-by: Eyal Shapira <eyal@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/ti/wlcore/main.c | 49 +++++++++++++++++++++++++++++------
 drivers/net/wireless/ti/wlcore/tx.c   |  2 +-
 2 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index a018221..c384bad 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -3196,14 +3196,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 		if (ret < 0)
 			return ret;
 
-		/* the default WEP key needs to be configured at least once */
-		if (key_type == KEY_WEP) {
-			ret = wl12xx_cmd_set_default_wep_key(wl,
-							wlvif->default_key,
-							wlvif->sta.hlid);
-			if (ret < 0)
-				return ret;
-		}
 	}
 
 	return 0;
@@ -3360,6 +3352,46 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
 }
 EXPORT_SYMBOL_GPL(wlcore_set_key);
 
+static void wl1271_op_set_default_key_idx(struct ieee80211_hw *hw,
+					  struct ieee80211_vif *vif,
+					  int key_idx)
+{
+	struct wl1271 *wl = hw->priv;
+	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+	int ret;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 set default key idx %d",
+		     key_idx);
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state != WLCORE_STATE_ON)) {
+		ret = -EAGAIN;
+		goto out_unlock;
+	}
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out_unlock;
+
+	wlvif->default_key = key_idx;
+
+	/* the default WEP key needs to be configured at least once */
+	if (wlvif->encryption_type == KEY_WEP) {
+		ret = wl12xx_cmd_set_default_wep_key(wl,
+				key_idx,
+				wlvif->sta.hlid);
+		if (ret < 0)
+			goto out_sleep;
+	}
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+
+out_unlock:
+	mutex_unlock(&wl->mutex);
+}
+
 void wlcore_regdomain_config(struct wl1271 *wl)
 {
 	int ret;
@@ -5352,6 +5384,7 @@ static const struct ieee80211_ops wl1271_ops = {
 	.ampdu_action = wl1271_op_ampdu_action,
 	.tx_frames_pending = wl1271_tx_frames_pending,
 	.set_bitrate_mask = wl12xx_set_bitrate_mask,
+	.set_default_unicast_key = wl1271_op_set_default_key_idx,
 	.channel_switch = wl12xx_op_channel_switch,
 	.flush = wlcore_op_flush,
 	.remain_on_channel = wlcore_op_remain_on_channel,
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 004d02e..7e93fe6 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -386,7 +386,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 		is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) ||
 			 (cipher == WLAN_CIPHER_SUITE_WEP104);
 
-		if (unlikely(is_wep && wlvif->default_key != idx)) {
+		if (WARN_ON(is_wep && wlvif->default_key != idx)) {
 			ret = wl1271_set_default_wep_key(wl, wlvif, idx);
 			if (ret < 0)
 				return ret;
-- 
1.8.1.2


^ permalink raw reply related

* Re: Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: Adrian Chadd @ 2013-05-12  0:46 UTC (permalink / raw)
  To: JoSH Lehan; +Cc: Arend van Spriel, linux-wireless, Luis R. Rodriguez
In-Reply-To: <518ECC39.9090401@gmail.com>

Hi,

On 11 May 2013 15:54, JoSH Lehan <krellan@gmail.com> wrote:

> Thanks!  So, I'll need to maintain two sets of mac80211/cfg80211
> modules: one for drivers that were compiled along with the kernel, and
> another for drivers that were compiled as part of the compat-drivers
> package.

No, you or the vendor should forward port it to linux-next, then you
can just pick up the whole driver/framework set from compat-wireless.



Adrian

^ permalink raw reply

* Re: [PATCH 05/12] net/wireless: ATH9K should depend on HAS_DMA
From: David Miller @ 2013-05-11 23:29 UTC (permalink / raw)
  To: geert; +Cc: linux-kernel, mcgrof, linville, linux-wireless, netdev
In-Reply-To: <1368133494-22198-5-git-send-email-geert@linux-m68k.org>

From: Geert Uytterhoeven <geert@linux-m68k.org>
Date: Thu,  9 May 2013 23:04:47 +0200

> If NO_DMA=y:
 ...
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>

Applied.

^ permalink raw reply

* Re: Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: JoSH Lehan @ 2013-05-11 23:21 UTC (permalink / raw)
  To: Larry Finger; +Cc: Arend van Spriel, linux-wireless, Luis R. Rodriguez
In-Reply-To: <518ECFDA.20208@lwfinger.net>

On 05/11/2013 04:10 PM, Larry Finger wrote:
> Neither driver r8712u, which has been in the kernel since 2.6.37, nor
> the equivalent vendor driver depends on anything from mac80211 or
> cfg80211. If it did, the kernel version would be in the
> drivers/net/wireless tree rather than in staging. I suspect the same is
> true for other wireless drivers from staging, which includes vt6656.

Interesting.  I'll have to investigate more.  I'm using kernel 2.6.32
for this system, so can't use the r8712u driver from the later kernel.

When I ran the vendor rtl8712 driver, it worked well enough with the
modules from the kernel, however, when I added compat-drivers to the
build (which replaced the mac80211/cfg80211 modules that were already
there), it crashed with an oops.  More investigation is needed to know
why this happens, but it must have something to do with compat-drivers,
because that is the only difference.  I removed compat-drivers from the
build, and it went back to being fully working.  Something must be
interacting in a bad way.

Josh Lehan

^ permalink raw reply

* Re: Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: JoSH Lehan @ 2013-05-11 23:10 UTC (permalink / raw)
  To: Hauke Mehrtens; +Cc: Arend van Spriel, linux-wireless, Luis R. Rodriguez
In-Reply-To: <518E0CD6.3040501@hauke-m.de>

On 05/11/2013 02:18 AM, Hauke Mehrtens wrote:
> You can only use mac80211/cfg80211 from compat-driver *or* the kernel.
> There was a plan to rename all exported symbols and make it possible to
> use both at the same time, but no one fully implemented it. The API
> between mac80211/cfg80211 is not stable and changing very often to
> implement new features so it is not possible to use new drivers with an
> older version of mac80211/cfg80211 or the other way around.

OK, thanks, that's probably why it crashes then.  The ABI is different,
even though the symbols are the same.  That would explain why it
compiles and links OK, but gets very confused at runtime.

Is my workaround acceptable: maintain two different sets of
mac80211/cfg80211 modules, one from the kernel compilation and another
from the compat-drivers compilation, then, based on which driver is
detected at runtime, make sure I load the correct set?  I have a fairly
light embedded system, that lacks modern user features such as udev, so
I do module loading/detection based on a fairly simple hotplug script
that I wrote.  It just takes the USB vendor/device ID and looks that up
in the modules.alias file, and loads that module with modprobe.  So, I
can easily extend that to select the correct mac80211/cfg80211 set, and
make sure that's loaded first.

> compat.ko is not a glue it is more a module containing all the functions
> not available in the kernel comopat-drivers was compiled against, but
> needed by some drivers or frameworks like mac80211.

Thanks for the clarification.  At first, I thought the compat.ko module
was only for the individual wireless device drivers, not for the entire
mac80211/cfg80211 stack, now I know.

> You should take all wireless drivers using mac80211/cfg80211 from
> compat-drivers and not use the in kernel versions any more.

Unfortunately some of my drivers (such as vt6656 and rtl8712) are from
tarballs that come from the vendor, and they exist outside the kernel
directory, but use it as a reference when compiling for that kernel.
It's similar to how compat-drivers is built.  This means they don't see
each other, unfortunately, even though they are eventually being
compiled for the same kernel.  I could not find a way to make these
vendor tarballs compatible with compat-drivers, given this setup.

I wonder if the compat-drivers tree can be copied into the kernel
directory itself, to replace what's already there, so that I can build
the kernel and it would contain the compat-drivers flavor of
mac80211/cfg80211 instead of the original kernel flavor of
mac80211/cfg80211?  Then, I could compile the vendor tarballs against
that, which would seem to neatly solve my problem, if it were possible.
 Does compat-drivers have an option to integrate into the kernel build
instead of being compiled outside of it?

Josh Lehan

^ permalink raw reply

* Re: Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: Larry Finger @ 2013-05-11 23:10 UTC (permalink / raw)
  To: JoSH Lehan; +Cc: Arend van Spriel, linux-wireless, Luis R. Rodriguez
In-Reply-To: <518ECC39.9090401@gmail.com>

On 05/11/2013 05:54 PM, JoSH Lehan wrote:
> Yes.  It's an embedded system, however, it has an exposed USB port and
> the user is free (within reason) to plug in a USB device.  I'm trying to
> add support for as many USB wireless adapters that I can find.  For some
> adapters (such as vt6656 and rtl8712), I use the vendor's tarball (which
> compiles directly against the kernel).  So, this is why I need to mix
> and match drivers compiled against the kernel's mac80211/cfg80211 with
> drivers compiled against the mac80211/cfg80211 from compat.
>

Neither driver r8712u, which has been in the kernel since 2.6.37, nor the 
equivalent vendor driver depends on anything from mac80211 or cfg80211. If it 
did, the kernel version would be in the drivers/net/wireless tree rather than in 
staging. I suspect the same is true for other wireless drivers from staging, 
which includes vt6656.

Larry




^ permalink raw reply

* Re: Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: JoSH Lehan @ 2013-05-11 22:54 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <518DF4B1.3020706@broadcom.com>

On 05/11/2013 12:35 AM, Arend van Spriel wrote:
> On 05/11/2013 02:52 AM, JoSH Lehan wrote:
> Luis may correct me, but I think you are correct. compat-drivers
> provides a compat.ko which is the glue between new drivers and your
> kernel. With the new drivers you get new features provided you have new
> mac80211/cfg80211 as well. Hence the glue is between wireless modules
> (including mac80211/cfg80211) and rest of your kernel. On a non-embedded
> system the compat-driver modules are installed in a separate folder
> /lib/modules/<your_kernel_version/updates. depmod is run during the
> install in which this folder takes precedence.

Thanks!  So, I'll need to maintain two sets of mac80211/cfg80211
modules: one for drivers that were compiled along with the kernel, and
another for drivers that were compiled as part of the compat-drivers
package.

> Not sure what your use-case is. You have a system in which different
> wireless devices may be plugged in or ...?

Yes.  It's an embedded system, however, it has an exposed USB port and
the user is free (within reason) to plug in a USB device.  I'm trying to
add support for as many USB wireless adapters that I can find.  For some
adapters (such as vt6656 and rtl8712), I use the vendor's tarball (which
compiles directly against the kernel).  So, this is why I need to mix
and match drivers compiled against the kernel's mac80211/cfg80211 with
drivers compiled against the mac80211/cfg80211 from compat.

> Probably not, provided you build it for your kernel version.

Thanks.  Everything's being built for the same version, which is good.
It all compiles and loads OK.  The problem is when the drivers are
actually used, then they oops.

> Depends what you call an embedded system. We used it to run our driver
> on Android. Just cross-compiling it and install it on the system is what
> we did. Recently, there have been a number of people walking that path
> and contacting us. It may be an idea to have a compat-drivers feature to
> generate Android tarballs as it is always running a few kernel versions
> behind mainline.

I'm just running the upstream Linux from kernel.org, not Android.  Good
to see you supporting Android, though.  Thanks for your help!

Josh Lehan

^ permalink raw reply

* Re: is L1 really disabled in iwlwifi
From: Matthew Garrett @ 2013-05-11 20:22 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Bjorn Helgaas, Emmanuel Grumbach, Stanislaw Gruszka,
	linux-pci@vger.kernel.org, linux-wireless, John Linville,
	Roman Yepishev, Guy, Wey-Yi, Mike Miller, iss_storagedev@hp.com,
	Guo-Fu Tseng, netdev@vger.kernel.org, Francois Romieu,
	nic_swsd@realtek.com, aacraid@adaptec.com,
	linux-kernel@vger.kernel.org
In-Reply-To: <1725435.3DlCxYF2FV@vostro.rjw.lan>

T24gU2F0LCAyMDEzLTA1LTExIGF0IDIyOjI2ICswMjAwLCBSYWZhZWwgSi4gV3lzb2NraSB3cm90
ZToNCj4gT24gRnJpZGF5LCBNYXkgMTAsIDIwMTMgMDQ6NTI6NTcgUE0gQmpvcm4gSGVsZ2FhcyB3
cm90ZToNCj4gPiBJIHByb3Bvc2UgdGhlIGZvbGxvd2luZyBwYXRjaC4gIEFueSBjb21tZW50cz8N
Cj4gDQo+IEluIG15IG9waW5pb24gdGhpcyBpcyBkYW5nZXJvdXMsIGJlY2F1c2UgaXQgb3BlbnMg
dXMgdG8gYnVncyB0aGF0IHJpZ2h0IG5vdw0KPiBhcmUgcHJldmVudGVkIGZyb20gaGFwcGVuaW5n
IGR1ZSB0byB0aGUgd2F5IHRoZSBjb2RlIHdvcmtzLg0KDQpSaWdodCwgSSdtIGFsc28gbm90IGVu
dGlyZWx5IGNvbWZvcnRhYmxlIHdpdGggdGhpcy4gVGhlIGN1cnJlbnQNCmJlaGF2aW91ciBtYXkg
YmUgY29uZnVzaW5nLCBidXQgd2UgY291bGQgcmVkdWNlIHRoYXQgYnkgcmVuYW1pbmcgdGhlDQpm
dW5jdGlvbnMuIEknbSBzdGlsbCBub3QgY2xlYXIgb24gd2hldGhlciBhbnlvbmUncyBhY3R1YWxs
eSBzZWVpbmcNCnByb2JsZW1zIGNhdXNlZCBieSB0aGUgZXhpc3RpbmcgYmVoYXZpb3VyLg0KDQot
LSANCk1hdHRoZXcgR2FycmV0dCB8IG1qZzU5QHNyY2YudWNhbS5vcmcNCg==


^ permalink raw reply

* Re: is L1 really disabled in iwlwifi
From: Rafael J. Wysocki @ 2013-05-11 20:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Emmanuel Grumbach, Matthew Garrett, Stanislaw Gruszka,
	linux-pci@vger.kernel.org, linux-wireless, John Linville,
	Roman Yepishev, Guy, Wey-Yi, Mike Miller, iss_storagedev,
	Guo-Fu Tseng, netdev, Francois Romieu, nic_swsd, aacraid,
	linux-kernel
In-Reply-To: <20130510225257.GA10847@google.com>

On Friday, May 10, 2013 04:52:57 PM Bjorn Helgaas wrote:
> [+cc Rafael, other pci_disable_link_state() users]
> 
> On Wed, May 01, 2013 at 11:13:15AM -0600, Bjorn Helgaas wrote:
> > On Wed, May 1, 2013 at 2:31 AM, Emmanuel Grumbach <egrumbach@gmail.com> wrote:
> > > [from Bjorn's mail]
> > >> In Emmanuel's case, we don't get _OSC control, so
> > >> pci_disable_link_state() does nothing.
> > >
> > > Right, but this is true with the specific log I sent to you. Is it
> > > possible that another platform  / BIOS, we *will* get _OSC control and
> > > that pci_disable_link_state() will actually do something?  In that case
> > > I would prefer not to remove the call to pcie_disable_link_state().
> > 
> > Yes, absolutely, on many platforms we will get _OSC control, and
> > pci_disable_link_state() will work as expected.  The problem is that
> > the driver doesn't have a good way to know whether pci_disable_link()
> > did anything or not.
> > 
> > Today I think we have:
> > 
> > 1) If the BIOS grants the OS permission to control PCIe services via
> > _OSC, pci_disable_link_state() works and L1 will be disabled.
> > 
> > 2) If the BIOS does not grant permission, pci_disable_link_state()
> > does nothing and L1 may be enabled or not depending on what
> > configuration the BIOS did.
> > 
> > If the device really doesn't work reliably when L1 is enabled, we're
> > currently at the mercy of the BIOS -- if the BIOS enables L1 but
> > doesn't grant us permission via _OSC, L1 will remain enabled (as it is
> > on your system).
> 
> I propose the following patch.  Any comments?

In my opinion this is dangerous, because it opens us to bugs that right now
are prevented from happening due to the way the code works.

Thanks,
Rafael


> commit cd11e3f87c4d2777cf8921c0454500c9baa54b46
> Author: Bjorn Helgaas <bhelgaas@google.com>
> Date:   Fri May 10 15:54:35 2013 -0600
> 
>     PCI/ASPM: Allow drivers to disable ASPM unconditionally
>     
>     Some devices have hardware problems related to using ASPM.  Drivers for
>     these devices use pci_disable_link_state() to prevent their device from
>     entering L0s or L1.  But on platforms where the OS doesn't have permission
>     to manage ASPM, pci_disable_link_state() does nothing, and the driver has
>     no way to know this.
>     
>     Therefore, if the BIOS enables ASPM but declines (either via the FADT
>     ACPI_FADT_NO_ASPM bit or the _OSC method) to allow the OS to manage it,
>     the device can still use ASPM and trip over the hardware issue.
>     
>     This patch makes pci_disable_link_state() disable ASPM unconditionally,
>     regardless of whether the OS has permission to manage ASPM in general.
>     
>     Reported-by: Emmanuel Grumbach <egrumbach@gmail.com>
>     Reference: https://lkml.kernel.org/r/CANUX_P3F5YhbZX3WGU-j1AGpbXb_T9Bis2ErhvKkFMtDvzatVQ@mail.gmail.com
>     Reference: https://bugzilla.kernel.org/show_bug.cgi?id=57331
>     Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> 
> diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
> index d320df6..9ef4ab8 100644
> --- a/drivers/pci/pcie/aspm.c
> +++ b/drivers/pci/pcie/aspm.c
> @@ -718,15 +718,11 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
>   * pci_disable_link_state - disable pci device's link state, so the link will
>   * never enter specific states
>   */
> -static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
> -				     bool force)
> +static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
>  {
>  	struct pci_dev *parent = pdev->bus->self;
>  	struct pcie_link_state *link;
>  
> -	if (aspm_disabled && !force)
> -		return;
> -
>  	if (!pci_is_pcie(pdev))
>  		return;
>  
> @@ -757,13 +753,13 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
>  
>  void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
>  {
> -	__pci_disable_link_state(pdev, state, false, false);
> +	__pci_disable_link_state(pdev, state, false);
>  }
>  EXPORT_SYMBOL(pci_disable_link_state_locked);
>  
>  void pci_disable_link_state(struct pci_dev *pdev, int state)
>  {
> -	__pci_disable_link_state(pdev, state, true, false);
> +	__pci_disable_link_state(pdev, state, true);
>  }
>  EXPORT_SYMBOL(pci_disable_link_state);
>  
> @@ -781,7 +777,7 @@ void pcie_clear_aspm(struct pci_bus *bus)
>  		__pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
>  					 PCIE_LINK_STATE_L1 |
>  					 PCIE_LINK_STATE_CLKPM,
> -					 false, true);
> +					 false);
>  	}
>  }
>  
-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply

* Re: [RFC 4/4] cfg80211/mac80211: use cfg80211 wdev mutex in mac80211
From: Arend van Spriel @ 2013-05-11 16:19 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, greearb
In-Reply-To: <1368188814.8390.15.camel@jlt4.sipsolutions.net>

On 05/10/2013 02:26 PM, Johannes Berg wrote:
> On Fri, 2013-05-10 at 14:22 +0200, Arend van Spriel wrote:
>> On 05/10/2013 02:08 PM, Johannes Berg wrote:
>>> From: Johannes Berg <johannes.berg@intel.com>
>>>
>>> Using separate locks in cfg80211 and mac80211 has always
>>> caused issues, for example having to unlock in places in
>>> mac80211 to call cfg80211, which even needed a framework
>>> to make cfg80211 calls after some functions returned etc.
>>>
>>> Additionally, I suspect some issues people have reported
>>> with the cfg80211 state getting confused could be due to
>>> such issues, when cfg80211 is asking mac80211 to change
>>> state but mac80211 is in the process of telling cfg80211
>>> that the state changed (in another way.)
>>
>> I guess this change affects fullmac drivers like brcmfmac, right?
>
> I don't think so.

I am asking because I noticed the following documentation change:

- * @mtx: mutex used to lock data in this struct
+ * @mtx: mutex used to lock data in this struct, may be used by drivers
+ *	and some API functions require it held

I did not look at the individual API functions, but I guess to be sure I 
should check whether we are using any of them.

Gr. AvS


^ permalink raw reply

* Re: Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: Hauke Mehrtens @ 2013-05-11  9:18 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: JoSH Lehan, linux-wireless, Luis R. Rodriguez
In-Reply-To: <518DF4B1.3020706@broadcom.com>

On 05/11/2013 09:35 AM, Arend van Spriel wrote:
> On 05/11/2013 02:52 AM, JoSH Lehan wrote:
>> It seems I can choose to use the mac80211/cfg80211 that came with the
>> kernel,*or*, the mac80211/cfg80211 that come with compat-drivers.  Is
>> this correct?  I'll have to maintain these two mac80211/cfg80211
>> drivers in separate directories, since they have the same name, and it
>> will complicate my detection/loading script, but if there's no other
>> way, then this is what needs to be done.
> 
> Luis may correct me, but I think you are correct. compat-drivers
> provides a compat.ko which is the glue between new drivers and your
> kernel. With the new drivers you get new features provided you have new
> mac80211/cfg80211 as well. Hence the glue is between wireless modules
> (including mac80211/cfg80211) and rest of your kernel. On a non-embedded
> system the compat-driver modules are installed in a separate folder
> /lib/modules/<your_kernel_version/updates. depmod is run during the
> install in which this folder takes precedence.
> 
> Not sure what your use-case is. You have a system in which different
> wireless devices may be plugged in or ...?

You can only use mac80211/cfg80211 from compat-driver *or* the kernel.
There was a plan to rename all exported symbols and make it possible to
use both at the same time, but no one fully implemented it. The API
between mac80211/cfg80211 is not stable and changing very often to
implement new features so it is not possible to use new drivers with an
older version of mac80211/cfg80211 or the other way around.

compat.ko is not a glue it is more a module containing all the functions
not available in the kernel comopat-drivers was compiled against, but
needed by some drivers or frameworks like mac80211.

You should take all wireless drivers using mac80211/cfg80211 from
compat-drivers and not use the in kernel versions any more.

>> Could it be because I cross-compile compat-drivers?  Looking at the
>> installation scripts, it's clearly intended to be ran by the end user
>> to replace the drivers in their distribution with updated drivers, and
>> it could be that I missed something when tweaking it to cross-compile
>> the drivers and not install them locally.
> 
> Probably not, provided you build it for your kernel version.
> 
>> Has anybody else tried to use compat-drivers to build for an embedded
>> system?  If so, what's the recommended solution?  How to solve the
>> mac80211/cfg80211 problem, where the kernel-compiled mac80211/cfg80211
>> modules conflict with their equivalent compat-drivers modules?
> 
> Depends what you call an embedded system. We used it to run our driver
> on Android. Just cross-compiling it and install it on the system is what
> we did. Recently, there have been a number of people walking that path
> and contacting us. It may be an idea to have a compat-drivers feature to
> generate Android tarballs as it is always running a few kernel versions
> behind mainline.
> 
> Regards,
> Arend


^ permalink raw reply

* Re: Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: Arend van Spriel @ 2013-05-11  7:35 UTC (permalink / raw)
  To: JoSH Lehan; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <CALOB5QZCeC7OTqkw5go6E_KUajVe5GDuCsSsc68cpZqE2YVfRQ@mail.gmail.com>

On 05/11/2013 02:52 AM, JoSH Lehan wrote:
> It seems I can choose to use the mac80211/cfg80211 that came with the
> kernel,*or*, the mac80211/cfg80211 that come with compat-drivers.  Is
> this correct?  I'll have to maintain these two mac80211/cfg80211
> drivers in separate directories, since they have the same name, and it
> will complicate my detection/loading script, but if there's no other
> way, then this is what needs to be done.

Luis may correct me, but I think you are correct. compat-drivers 
provides a compat.ko which is the glue between new drivers and your 
kernel. With the new drivers you get new features provided you have new 
mac80211/cfg80211 as well. Hence the glue is between wireless modules 
(including mac80211/cfg80211) and rest of your kernel. On a non-embedded 
system the compat-driver modules are installed in a separate folder 
/lib/modules/<your_kernel_version/updates. depmod is run during the 
install in which this folder takes precedence.

Not sure what your use-case is. You have a system in which different 
wireless devices may be plugged in or ...?

> Could it be because I cross-compile compat-drivers?  Looking at the
> installation scripts, it's clearly intended to be ran by the end user
> to replace the drivers in their distribution with updated drivers, and
> it could be that I missed something when tweaking it to cross-compile
> the drivers and not install them locally.

Probably not, provided you build it for your kernel version.

> Has anybody else tried to use compat-drivers to build for an embedded
> system?  If so, what's the recommended solution?  How to solve the
> mac80211/cfg80211 problem, where the kernel-compiled mac80211/cfg80211
> modules conflict with their equivalent compat-drivers modules?

Depends what you call an embedded system. We used it to run our driver 
on Android. Just cross-compiling it and install it on the system is what 
we did. Recently, there have been a number of people walking that path 
and contacting us. It may be an idea to have a compat-drivers feature to 
generate Android tarballs as it is always running a few kernel versions 
behind mainline.

Regards,
Arend


^ permalink raw reply

* Using compat-drivers conflicts with kernel mac80211 and cfg80211
From: JoSH Lehan @ 2013-05-11  0:52 UTC (permalink / raw)
  To: linux-wireless

Hello there.  I have an embedded system with the 2.6.32 kernel (I
agree that this is rather old, but it's stable on this board, and I'm
hesitant to change it as it's undergone and passed many tests).

The kernel works fine, the drivers included with the kernel work fine,
some additional drivers that I've added work fine (they are out of
kernel, but build against the built kernel).

The problem is with compat-drivers.  I need to get some new wireless
drivers for newly supported hardware, however, compat-drivers insists
on compiling its own mac80211 and cfg80211 drivers, as it compiles the
stack of drivers.  These clash with the mac80211 and cfg80211 drivers
that were compiled along with the kernel.  The module sizes are very
different, it's clear they're not compatible, it's not a small change.
 I couldn't find a way to disable this, and tell compat-drivers to use
mac80211/cfg80211 from my kernel instead of trying to compile its own.

if I load the mac80211 and cfg80211 from compat-drivers, and then load
a driver that was compiled against the kernel, there's no missing
symbols, but it crashes with an oops when it tries to register itself
with the mac80211/cfg80211 stack.

The vice versa also happens.  If I load mac80211/cfg80211 from the
kernel, then load a driver from compat-drivers, I get an oops during
initialization.

It seems I can choose to use the mac80211/cfg80211 that came with the
kernel, *or*, the mac80211/cfg80211 that come with compat-drivers.  Is
this correct?  I'll have to maintain these two mac80211/cfg80211
drivers in separate directories, since they have the same name, and it
will complicate my detection/loading script, but if there's no other
way, then this is what needs to be done.

Could it be because I cross-compile compat-drivers?  Looking at the
installation scripts, it's clearly intended to be ran by the end user
to replace the drivers in their distribution with updated drivers, and
it could be that I missed something when tweaking it to cross-compile
the drivers and not install them locally.

Has anybody else tried to use compat-drivers to build for an embedded
system?  If so, what's the recommended solution?  How to solve the
mac80211/cfg80211 problem, where the kernel-compiled mac80211/cfg80211
modules conflict with their equivalent compat-drivers modules?

Thanks!  Any help would be appreciated.

Josh Lehan

^ permalink raw reply

* [PATCH] iw: Allow basic rates to be configured when joining mesh
From: Ashok Nagarajan @ 2013-05-11  0:52 UTC (permalink / raw)
  To: linux-wireless; +Cc: javier, johannes, devel, ashok

This patch adds option to configure basic rates during mesh join

Signed-off-by: Ashok Nagarajan <ashok@cozybit.com>
---
 mesh.c |   37 +++++++++++++++++++++++++++++++++++--
 1 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/mesh.c b/mesh.c
index 5a09b62..c6aa9ce 100644
--- a/mesh.c
+++ b/mesh.c
@@ -431,8 +431,11 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb,
 {
 	struct nlattr *container;
 	float rate;
+	unsigned char rates[NL80211_MAX_SUPP_RATES];
+	int n_rates = 0;
 	int bintval, dtim_period;
 	char *end;
+	char *value = NULL, *sptr = NULL;
 
 	if (argc < 1)
 		return 1;
@@ -441,6 +444,34 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb,
 	argc--;
 	argv++;
 
+	/* basic rates */
+	if (argc > 1 && strcmp(argv[0], "basic-rates") == 0) {
+		argv++;
+		argc--;
+
+		value = strtok_r(argv[0], ",", &sptr);
+
+		while (value && n_rates < NL80211_MAX_SUPP_RATES) {
+			rate = strtod(value, &end);
+			rates[n_rates] = rate * 2;
+
+			/* filter out suspicious values  */
+			if (*end != '\0' || !rates[n_rates] ||
+			    rate*2 != rates[n_rates])
+				return 1;
+
+			n_rates++;
+			value = strtok_r(NULL, ",", &sptr);
+		}
+
+		NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, n_rates, rates);
+
+		argv++;
+		argc--;
+	}
+
+	/* multicast rate */
+
 	if (argc > 1 && strcmp(argv[0], "mcast-rate") == 0) {
 		argv++;
 		argc--;
@@ -506,11 +537,13 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb,
  nla_put_failure:
 	return -ENOBUFS;
 }
-COMMAND(mesh, join, "<mesh ID> [mcast-rate <rate in Mbps>]"
+COMMAND(mesh, join, "<mesh ID> [basic-rates <rate in Mbps,rate2,...>]"
+	"[mcast-rate <rate in Mbps>]"
 	" [beacon-interval <time in TUs>] [dtim-period <value>]"
 	" [vendor_sync on|off] [<param>=<value>]*",
 	NL80211_CMD_JOIN_MESH, 0, CIB_NETDEV, join_mesh,
-	"Join a mesh with the given mesh ID with mcast-rate and mesh parameters.");
+	"Join a mesh with the given mesh ID with basic-rates, "
+	"mcast-rate and mesh parameters.");
 
 static int leave_mesh(struct nl80211_state *state, struct nl_cb *cb,
 		      struct nl_msg *msg, int argc, char **argv,
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH 3/3] {nl,mac,cfg}80211: Allow user to configure basic rates for mesh
From: Ashok Nagarajan @ 2013-05-11  0:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: linville, johannes, devel, ashok
In-Reply-To: <1368233453-10581-1-git-send-email-ashok@cozybit.com>

Currently mesh uses mandatory rates as the default basic rates. Allow basic
rates to be configured during mesh join.

Signed-off-by: Ashok Nagarajan <ashok@cozybit.com>
---
 include/net/cfg80211.h |    2 ++
 net/mac80211/cfg.c     |    2 ++
 net/mac80211/mesh.c    |    4 ----
 net/wireless/mesh.c    |   11 +++++++++++
 net/wireless/nl80211.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fcb7764..06780d1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1155,6 +1155,7 @@ struct mesh_config {
  * @dtim_period: DTIM period to use
  * @beacon_interval: beacon interval to use
  * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
+ * @basic_rates: per-band bitmap of basic rates to use when creating the mesh
  *
  * These parameters are fixed when the mesh is created.
  */
@@ -1173,6 +1174,7 @@ struct mesh_setup {
 	u8 dtim_period;
 	u16 beacon_interval;
 	int mcast_rate[IEEE80211_NUM_BANDS];
+	u32 basic_rates[IEEE80211_NUM_BANDS];
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1a89c80..2d4131f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1744,6 +1744,8 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
 	/* mcast rate setting in Mesh Node */
 	memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate,
 						sizeof(setup->mcast_rate));
+	sdata->vif.bss_conf.basic_rates =
+				setup->basic_rates[setup->chandef.chan->band];
 
 	sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
 	sdata->vif.bss_conf.dtim_period = setup->dtim_period;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 5a37f95..7e4fce9 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -740,9 +740,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 		      BSS_CHANGED_HT |
 		      BSS_CHANGED_BASIC_RATES |
 		      BSS_CHANGED_BEACON_INT;
-	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
-	struct ieee80211_supported_band *sband =
-					sdata->local->hw.wiphy->bands[band];
 
 	local->fif_other_bss++;
 	/* mesh ifaces must set allmulti to forward mcast traffic */
@@ -761,7 +758,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 	sdata->vif.bss_conf.ht_operation_mode =
 				ifmsh->mshcfg.ht_opmode;
 	sdata->vif.bss_conf.enable_beacon = true;
-	sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sband);
 
 	changed |= ieee80211_mps_local_status_update(sdata);
 
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 0bb93f3..9133942 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -159,6 +159,17 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
 		setup->chandef.center_freq1 = setup->chandef.chan->center_freq;
 	}
 
+	/*
+	 * we now know the operating band, so check if basic rates are
+	 * available for this band otherwise use mandatory rates as basic rates
+	 */
+	if (!setup->basic_rates[setup->chandef.chan->band]) {
+		enum ieee80211_band band = setup->chandef.chan->band;
+		struct ieee80211_supported_band *sband =
+							rdev->wiphy.bands[band];
+		setup->basic_rates[band] = ieee80211_mandatory_rates(sband);
+	}
+
 	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
 		return -EINVAL;
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index afa2838..65a1e95 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6232,6 +6232,33 @@ nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
 	return found;
 }
 
+static int nl80211_parse_basic_rates(struct cfg80211_registered_device *rdev,
+				     const u8 *rates, unsigned int n_rates,
+				     u32 mask[IEEE80211_NUM_BANDS])
+{
+	struct wiphy *wiphy = &rdev->wiphy;
+	bool found = false;
+	int band, err;
+	struct ieee80211_supported_band *sband;
+
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		err = 0;
+		sband = wiphy->bands[band];
+
+		if (!sband)
+			continue;
+
+		err = ieee80211_get_ratemask(sband, rates, n_rates,
+					     &mask[band]);
+		if (!err)
+			found = true;
+	}
+
+	if (!found)
+		return -EINVAL;
+	return 0;
+}
+
 static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -7460,6 +7487,22 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
 			    nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
 			return -EINVAL;
 
+	if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
+		u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+		int n_rates =
+			     nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+
+		/*
+		 * since we may or may not have an operating band yet, verify
+		 * given basic rates are supported for all available bands
+		 */
+
+		err = nl80211_parse_basic_rates(rdev, rates, n_rates,
+						setup.basic_rates);
+		if (err)
+			return err;
+	}
+
 	if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
 		setup.beacon_interval =
 			nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH 2/3] cfg80211: Allow ieee80211g mandatory rate sets in 2.4GHz band
From: Ashok Nagarajan @ 2013-05-11  0:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: linville, johannes, devel, ashok
In-Reply-To: <1368233453-10581-1-git-send-email-ashok@cozybit.com>

With the current logic of ieee80211_mandatory_rates(), only 11b mandatory rates
are returned when operating in 2.4GHz band. 802.11g mandatory rates are not
fetched even if the operating mode is 11g. This patch assumes 11g support
implies a 11g operation and returns the appropriate mandatory rates.

Signed-off-by: Ashok Nagarajan <ashok@cozybit.com>
---
 net/wireless/util.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index d6727f2..d4e3dfa 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -43,12 +43,19 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband)
 	if (WARN_ON(!sband))
 		return 1;
 
-	if (sband->band == IEEE80211_BAND_2GHZ)
-		mandatory_flag = IEEE80211_RATE_MANDATORY_B;
-	else
+	bitrates = sband->bitrates;
+	if (sband->band == IEEE80211_BAND_5GHZ)
 		mandatory_flag = IEEE80211_RATE_MANDATORY_A;
+	else {
+		mandatory_flag = IEEE80211_RATE_MANDATORY_B;
+		for (i = 0; i < sband->n_bitrates; i++)
+			if (bitrates[i].bitrate > 110) {
+				mandatory_flag =
+					IEEE80211_RATE_MANDATORY_G;
+				break;
+			}
+	}
 
-	bitrates = sband->bitrates;
 	for (i = 0; i < sband->n_bitrates; i++)
 		if (bitrates[i].flags & mandatory_flag)
 			mandatory_rates |= BIT(i);
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH 1/3] {cfg,mac}80211: move mandatory rates calculation to cfg80211
From: Ashok Nagarajan @ 2013-05-11  0:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: linville, johannes, devel, ashok

Move mandatory rates calculation to cfg80211, shared with non mac80211 drivers.

Signed-off-by: Ashok Nagarajan <ashok@cozybit.com>
---
 include/net/cfg80211.h     |    8 ++++++++
 net/mac80211/ibss.c        |   10 +++++++---
 net/mac80211/ieee80211_i.h |    3 ---
 net/mac80211/mesh.c        |    5 +++--
 net/mac80211/util.c        |   26 --------------------------
 net/wireless/util.c        |   23 +++++++++++++++++++++++
 6 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 26b5b69..fcb7764 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2989,6 +2989,14 @@ struct ieee80211_rate *
 ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
 			    u32 basic_rates, int bitrate);
 
+/**
+ * ieee80211_mandatory_rates - get mandatory rates for a given band
+ * @sband: the band to look for rates in
+ *
+ * This function returns the mandatory rates for the given band
+ */
+u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband);
+
 /*
  * Radiotap parsing functions -- for controlled injection support
  *
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 170f9a7..956ba63 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -341,6 +341,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
 	struct ieee80211_chanctx_conf *chanctx_conf;
+	struct ieee80211_supported_band *sband;
 	int band;
 
 	/*
@@ -380,8 +381,9 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
 	sta->last_rx = jiffies;
 
 	/* make sure mandatory rates are always added */
+	sband = local->hw.wiphy->bands[band];
 	sta->sta.supp_rates[band] = supp_rates |
-			ieee80211_mandatory_rates(local, band);
+			ieee80211_mandatory_rates(sband);
 
 	return ieee80211_ibss_finish_sta(sta, auth);
 }
@@ -492,7 +494,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 				prev_rates = sta->sta.supp_rates[band];
 				/* make sure mandatory rates are always added */
 				sta->sta.supp_rates[band] = supp_rates |
-					ieee80211_mandatory_rates(local, band);
+					ieee80211_mandatory_rates(sband);
 
 				if (sta->sta.supp_rates[band] != prev_rates) {
 					ibss_dbg(sdata,
@@ -624,6 +626,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
 	struct ieee80211_chanctx_conf *chanctx_conf;
+	struct ieee80211_supported_band *sband;
 	int band;
 
 	/*
@@ -658,8 +661,9 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
 	sta->last_rx = jiffies;
 
 	/* make sure mandatory rates are always added */
+	sband = local->hw.wiphy->bands[band];
 	sta->sta.supp_rates[band] = supp_rates |
-			ieee80211_mandatory_rates(local, band);
+			ieee80211_mandatory_rates(sband);
 
 	spin_lock(&ifibss->incomplete_lock);
 	list_add(&sta->list, &ifibss->incomplete_stations);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 158e6eb..b7cbd4e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1505,9 +1505,6 @@ static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
 	ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
 }
 
-u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
-			      enum ieee80211_band band);
-
 void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
 void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
 void ieee80211_dynamic_ps_timer(unsigned long data);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6952760..5a37f95 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -741,6 +741,8 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 		      BSS_CHANGED_BASIC_RATES |
 		      BSS_CHANGED_BEACON_INT;
 	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
+	struct ieee80211_supported_band *sband =
+					sdata->local->hw.wiphy->bands[band];
 
 	local->fif_other_bss++;
 	/* mesh ifaces must set allmulti to forward mcast traffic */
@@ -759,8 +761,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 	sdata->vif.bss_conf.ht_operation_mode =
 				ifmsh->mshcfg.ht_opmode;
 	sdata->vif.bss_conf.enable_beacon = true;
-	sdata->vif.bss_conf.basic_rates =
-		ieee80211_mandatory_rates(local, band);
+	sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sband);
 
 	changed |= ieee80211_mps_local_status_update(sdata);
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 3f87fa4..707953f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1072,32 +1072,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
 	ieee80211_set_wmm_default(sdata, true);
 }
 
-u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
-			      enum ieee80211_band band)
-{
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_rate *bitrates;
-	u32 mandatory_rates;
-	enum ieee80211_rate_flags mandatory_flag;
-	int i;
-
-	sband = local->hw.wiphy->bands[band];
-	if (WARN_ON(!sband))
-		return 1;
-
-	if (band == IEEE80211_BAND_2GHZ)
-		mandatory_flag = IEEE80211_RATE_MANDATORY_B;
-	else
-		mandatory_flag = IEEE80211_RATE_MANDATORY_A;
-
-	bitrates = sband->bitrates;
-	mandatory_rates = 0;
-	for (i = 0; i < sband->n_bitrates; i++)
-		if (bitrates[i].flags & mandatory_flag)
-			mandatory_rates |= BIT(i);
-	return mandatory_rates;
-}
-
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
 			 u16 transaction, u16 auth_alg, u16 status,
 			 const u8 *extra, size_t extra_len, const u8 *da,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index a7046a4..d6727f2 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -33,6 +33,29 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
 }
 EXPORT_SYMBOL(ieee80211_get_response_rate);
 
+u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband)
+{
+	struct ieee80211_rate *bitrates;
+	u32 mandatory_rates = 0;
+	enum ieee80211_rate_flags mandatory_flag;
+	int i;
+
+	if (WARN_ON(!sband))
+		return 1;
+
+	if (sband->band == IEEE80211_BAND_2GHZ)
+		mandatory_flag = IEEE80211_RATE_MANDATORY_B;
+	else
+		mandatory_flag = IEEE80211_RATE_MANDATORY_A;
+
+	bitrates = sband->bitrates;
+	for (i = 0; i < sband->n_bitrates; i++)
+		if (bitrates[i].flags & mandatory_flag)
+			mandatory_rates |= BIT(i);
+	return mandatory_rates;
+}
+EXPORT_SYMBOL(ieee80211_mandatory_rates);
+
 int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
 {
 	/* see 802.11 17.3.8.3.2 and Annex J
-- 
1.7.5.4


^ permalink raw reply related

* Re: is L1 really disabled in iwlwifi
From: Bjorn Helgaas @ 2013-05-10 22:52 UTC (permalink / raw)
  To: Emmanuel Grumbach
  Cc: Matthew Garrett, Stanislaw Gruszka, linux-pci@vger.kernel.org,
	linux-wireless, John Linville, Roman Yepishev, Guy, Wey-Yi,
	Mike Miller, iss_storagedev, Guo-Fu Tseng, netdev,
	Francois Romieu, nic_swsd, aacraid, Rafael J. Wysocki,
	linux-kernel
In-Reply-To: <CAErSpo6OCyTy19u6Xaf=xr0TSDriwCD3n-oMc7eJyLzuJ9d60g@mail.gmail.com>

[+cc Rafael, other pci_disable_link_state() users]

On Wed, May 01, 2013 at 11:13:15AM -0600, Bjorn Helgaas wrote:
> On Wed, May 1, 2013 at 2:31 AM, Emmanuel Grumbach <egrumbach@gmail.com> wrote:
> > [from Bjorn's mail]
> >> In Emmanuel's case, we don't get _OSC control, so
> >> pci_disable_link_state() does nothing.
> >
> > Right, but this is true with the specific log I sent to you. Is it
> > possible that another platform  / BIOS, we *will* get _OSC control and
> > that pci_disable_link_state() will actually do something?  In that case
> > I would prefer not to remove the call to pcie_disable_link_state().
> 
> Yes, absolutely, on many platforms we will get _OSC control, and
> pci_disable_link_state() will work as expected.  The problem is that
> the driver doesn't have a good way to know whether pci_disable_link()
> did anything or not.
> 
> Today I think we have:
> 
> 1) If the BIOS grants the OS permission to control PCIe services via
> _OSC, pci_disable_link_state() works and L1 will be disabled.
> 
> 2) If the BIOS does not grant permission, pci_disable_link_state()
> does nothing and L1 may be enabled or not depending on what
> configuration the BIOS did.
> 
> If the device really doesn't work reliably when L1 is enabled, we're
> currently at the mercy of the BIOS -- if the BIOS enables L1 but
> doesn't grant us permission via _OSC, L1 will remain enabled (as it is
> on your system).

I propose the following patch.  Any comments?


commit cd11e3f87c4d2777cf8921c0454500c9baa54b46
Author: Bjorn Helgaas <bhelgaas@google.com>
Date:   Fri May 10 15:54:35 2013 -0600

    PCI/ASPM: Allow drivers to disable ASPM unconditionally
    
    Some devices have hardware problems related to using ASPM.  Drivers for
    these devices use pci_disable_link_state() to prevent their device from
    entering L0s or L1.  But on platforms where the OS doesn't have permission
    to manage ASPM, pci_disable_link_state() does nothing, and the driver has
    no way to know this.
    
    Therefore, if the BIOS enables ASPM but declines (either via the FADT
    ACPI_FADT_NO_ASPM bit or the _OSC method) to allow the OS to manage it,
    the device can still use ASPM and trip over the hardware issue.
    
    This patch makes pci_disable_link_state() disable ASPM unconditionally,
    regardless of whether the OS has permission to manage ASPM in general.
    
    Reported-by: Emmanuel Grumbach <egrumbach@gmail.com>
    Reference: https://lkml.kernel.org/r/CANUX_P3F5YhbZX3WGU-j1AGpbXb_T9Bis2ErhvKkFMtDvzatVQ@mail.gmail.com
    Reference: https://bugzilla.kernel.org/show_bug.cgi?id=57331
    Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index d320df6..9ef4ab8 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -718,15 +718,11 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
  * pci_disable_link_state - disable pci device's link state, so the link will
  * never enter specific states
  */
-static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
-				     bool force)
+static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
 {
 	struct pci_dev *parent = pdev->bus->self;
 	struct pcie_link_state *link;
 
-	if (aspm_disabled && !force)
-		return;
-
 	if (!pci_is_pcie(pdev))
 		return;
 
@@ -757,13 +753,13 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
 
 void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
 {
-	__pci_disable_link_state(pdev, state, false, false);
+	__pci_disable_link_state(pdev, state, false);
 }
 EXPORT_SYMBOL(pci_disable_link_state_locked);
 
 void pci_disable_link_state(struct pci_dev *pdev, int state)
 {
-	__pci_disable_link_state(pdev, state, true, false);
+	__pci_disable_link_state(pdev, state, true);
 }
 EXPORT_SYMBOL(pci_disable_link_state);
 
@@ -781,7 +777,7 @@ void pcie_clear_aspm(struct pci_bus *bus)
 		__pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
 					 PCIE_LINK_STATE_L1 |
 					 PCIE_LINK_STATE_CLKPM,
-					 false, true);
+					 false);
 	}
 }
 

^ permalink raw reply related

* Re: mac80211:  3.9.0+:  Invalid WDS/flush state and non-connecting station.
From: Ben Greear @ 2013-05-10 21:33 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1368221128.8390.47.camel@jlt4.sipsolutions.net>

On 05/10/2013 02:25 PM, Johannes Berg wrote:
> On Fri, 2013-05-10 at 14:21 -0700, Ben Greear wrote:
>
>> void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
>> 			struct net_device *dev)
>> {
>> 	struct wireless_dev *wdev = dev->ieee80211_ptr;
>> 	struct cfg80211_deauth_request req;
>> 	u8 bssid[ETH_ALEN];
>>
>> 	ASSERT_WDEV_LOCK(wdev);
>>
>> 	printk("mlme_down: %s: type: %i  sme_state: %i current-bss: %p\n",
>>                  dev->name, (int)(wdev->iftype), (int)(wdev->sme_state),
>> 	       wdev->current_bss);
>>
>> I see this printout for the stuck station (this is dmesg | grep sta74,
>> so it skips errors about other interfaces that are also hung).
>>
>> I am guessing we should never be calling mlme_down with state
>> of CFG80211_SME_CONNECTED when bss is NULL?
>
> We should _never_ be in a state where current_bss is NULL but the state
> is != IDLE. The question I can't seem to find an answer for is how we
> got into that state, that we're in the state in down() is really less
> interesting.
>
> Since you seem to be able to reproduce this, maybe it'd help to mark all
> state transitions and current_bss assignments, and then backtrack them
> after the fact.

I'll work on instrumenting all of those assignments.  I plan to use
a helper macro to assign them and print out call sites..

Thanks,
Ben


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ 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