Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2 2/2] ath10k: fix scheduling while atomic bug
From: Michal Kazior @ 2013-10-04  8:17 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1380874630-14280-1-git-send-email-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>
---
 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 7e06e75..378d868 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1238,7 +1238,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,
@@ -1439,6 +1439,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);
@@ -1447,8 +1471,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;
@@ -1460,21 +1482,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)
@@ -2010,6 +2025,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;
@@ -2065,7 +2082,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);
 
@@ -2133,6 +2150,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);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 0/2] ath10k: wep & ampdu fix
From: Michal Kazior @ 2013-10-04  8:17 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <to=1380292567-2363-1-git-send-email-michal.kazior@tieto.com>

Hi,

One throughput fix and one bug fix.

The bug fix addresses my oversight when reworking
HTC/WMI. I haven't seen the error yet but I'm
quite certain this should be fixed.

v2:
 * A-MPDU patch contains a workaround for
   Netgear/Linksys 11ac APs
   (Kalle, can you kindly test this, please?)
 * patchset cover mail title changed to avoid
   confusion (too many patchsets named the same
   way..)


Michal Kazior (1):
  ath10k: fix scheduling while atomic bug

Sujith Manoharan (1):
  ath10k: Fix bug in max. VHT A-MPDU size

 drivers/net/wireless/ath/ath10k/core.h |    4 +-
 drivers/net/wireless/ath/ath10k/mac.c  |   67 +++++++++++++++++++++++---------
 2 files changed, 52 insertions(+), 19 deletions(-)

-- 
1.7.9.5


^ permalink raw reply

* [PATCH v2 1/2] ath10k: Fix bug in max. VHT A-MPDU size
From: Michal Kazior @ 2013-10-04  8:17 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Sujith Manoharan, Michal Kazior
In-Reply-To: <1380874630-14280-1-git-send-email-michal.kazior@tieto.com>

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

For VHT peers, the maximum A-MPDU size has to be calculated
from the VHT capabilities element and not the HT-cap. The formula
is the same, but a higher value is used in VHT, allowing larger
aggregates to be transmitted.

The patch contains a workaround for some Netgear/Linksys APs that
report Rx A-MPDU factor incorrectly.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 8684e03..7e06e75 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1033,14 +1033,26 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
 				    struct wmi_peer_assoc_complete_arg *arg)
 {
 	const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
+	u8 ampdu_factor;
 
 	if (!vht_cap->vht_supported)
 		return;
 
 	arg->peer_flags |= WMI_PEER_VHT;
-
 	arg->peer_vht_caps = vht_cap->cap;
 
+	ampdu_factor =
+		(vht_cap->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
+		IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+
+	/* Workaround: Some Netgear/Linksys 11ac APs set Rx A-MPDU factor to
+	 * zero in VHT IE. Using it would result in degraded throughput.
+	 * arg->peer_max_mpdu at this point contains HT max_mpdu so keep
+	 * it if VHT max_mpdu is smaller. */
+	arg->peer_max_mpdu = max(arg->peer_max_mpdu,
+				 (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+					ampdu_factor)) - 1);
+
 	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
 		arg->peer_flags |= WMI_PEER_80MHZ;
 
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH] wcn36xx: mac80211 driver for Qualcomm WCN3660/WCN3680 hardware
From: Eugene Krasnikov @ 2013-10-04  7:55 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: John W. Linville, linux-wireless, wcn36xx
In-Reply-To: <524E72B7.5000102@broadcom.com>

Hi Arend,

Yes, i am building it as a module. Let me try to build it into the
kernel, may be that is the reason why build fails.

2013/10/4 Arend van Spriel <arend@broadcom.com>:
> On 10/03/2013 11:22 PM, Eugene Krasnikov wrote:
>>
>> Hm, weird... do not see this problem myself. Let me try to sync latest
>> wireless-next and will try to apply latest patch from this mailthread
>> on top.
>
>
> Hi Eugene,
>
> Do you build the driver as module. John is building it built-in then kernel.
>
> Gr. AvS
>
>
>> P.S. If somebody esle can try to apply this patch and build that would
>> be useful to know if problem is visible on others PCs as well.
>>
>> 2013/10/3 John W. Linville <linville@tuxdriver.com>:
>>>
>>> On Thu, Sep 26, 2013 at 11:25:18PM +0100, Eugene Krasnikov wrote:
>>>>
>>>> Hi John,
>>>>
>>>> This is the latest version of wcn36xx driver on top of current
>>>> wireless-next tree. Please let me know if you have any problems with
>>>> applying it.
>>>>
>>>> 2013/9/26 Eugene Krasnikov <k.eugene.e@gmail.com>:
>>>>>
>>>>> This is a mac80211 driver for Qualcomm WCN3660/WCN3680 devices. So
>>>>> far WCN3660/WCN3680 is available only on MSM platform.
>>>>>
>>>>> Firmware can be found here:
>>>>>
>>>>> https://www.codeaurora.org/cgit/external/hisense/platform/vendor/qcom-opensource/wlan/prima/tree/firmware_bin?h=8130_CS
>>>>>
>>>>> Wiki page is available here:
>>>>> http://wireless.kernel.org/en/users/Drivers/wcn36xx
>>>>>
>>>>> A lot people made a contribution to this driver. Here is the list in
>>>>> alphabetical order:
>>>>>
>>>>> Eugene Krasnikov <k.eugene.e@gmail.com>
>>>>> Kalle Valo <kvalo@qca.qualcomm.com>
>>>>> Olof Johansson <dev@skyshaper.net>
>>>>> Pontus Fuchs <pontus.fuchs@gmail.com>
>>>>> Yanbo Li <yanbol@qti.qualcomm.com>
>>>>>
>>>>> Signed-off-by: Eugene Krasnikov <k.eugene.e@gmail.com>
>>>
>>>
>>> 'make allyesconfig' yield this:
>>>
>>>    LD      drivers/net/wireless/ath/ath.o
>>>    LD      drivers/net/wireless/ath/built-in.o
>>> drivers/net/wireless/ath/wcn36xx/built-in.o: In function
>>> `_GLOBAL__sub_I_65535_0_wcn36xx_set_default_rates':
>>>
>>> /home/linville/git/wireless-next/drivers/net/wireless/ath/wcn36xx/main.c:302:
>>> multiple definition of `debug_mask'
>>>
>>> drivers/net/wireless/ath/ath6kl/built-in.o:/home/linville/git/wireless-next/drivers/net/wireless/ath/ath6kl/cfg80211.c:1208:
>>> first defined here
>>> make[2]: *** [drivers/net/wireless/ath/built-in.o] Error 1
>>> make[1]: *** [drivers/net/wireless/ath] Error 2
>>> make: *** [drivers/net/wireless/] Error 2
>>>
>>> --
>>> John W. Linville                Someday the world will need a hero, and
>>> you
>>> linville@tuxdriver.com                  might be all we have.  Be ready.
>>
>>
>>
>>
>
>



-- 
Best regards,
Eugene

^ permalink raw reply

* Re: [PATCH] wcn36xx: mac80211 driver for Qualcomm WCN3660/WCN3680 hardware
From: Arend van Spriel @ 2013-10-04  7:48 UTC (permalink / raw)
  To: Eugene Krasnikov, John W. Linville; +Cc: linux-wireless, wcn36xx
In-Reply-To: <CAFSJ42ZwJzd46UXE2crzuaMVRLzre9SVm_vFcQ-KAVY6Q9c3QQ@mail.gmail.com>

On 10/03/2013 11:22 PM, Eugene Krasnikov wrote:
> Hm, weird... do not see this problem myself. Let me try to sync latest
> wireless-next and will try to apply latest patch from this mailthread
> on top.

Hi Eugene,

Do you build the driver as module. John is building it built-in then kernel.

Gr. AvS

> P.S. If somebody esle can try to apply this patch and build that would
> be useful to know if problem is visible on others PCs as well.
>
> 2013/10/3 John W. Linville <linville@tuxdriver.com>:
>> On Thu, Sep 26, 2013 at 11:25:18PM +0100, Eugene Krasnikov wrote:
>>> Hi John,
>>>
>>> This is the latest version of wcn36xx driver on top of current
>>> wireless-next tree. Please let me know if you have any problems with
>>> applying it.
>>>
>>> 2013/9/26 Eugene Krasnikov <k.eugene.e@gmail.com>:
>>>> This is a mac80211 driver for Qualcomm WCN3660/WCN3680 devices. So
>>>> far WCN3660/WCN3680 is available only on MSM platform.
>>>>
>>>> Firmware can be found here:
>>>> https://www.codeaurora.org/cgit/external/hisense/platform/vendor/qcom-opensource/wlan/prima/tree/firmware_bin?h=8130_CS
>>>>
>>>> Wiki page is available here:
>>>> http://wireless.kernel.org/en/users/Drivers/wcn36xx
>>>>
>>>> A lot people made a contribution to this driver. Here is the list in
>>>> alphabetical order:
>>>>
>>>> Eugene Krasnikov <k.eugene.e@gmail.com>
>>>> Kalle Valo <kvalo@qca.qualcomm.com>
>>>> Olof Johansson <dev@skyshaper.net>
>>>> Pontus Fuchs <pontus.fuchs@gmail.com>
>>>> Yanbo Li <yanbol@qti.qualcomm.com>
>>>>
>>>> Signed-off-by: Eugene Krasnikov <k.eugene.e@gmail.com>
>>
>> 'make allyesconfig' yield this:
>>
>>    LD      drivers/net/wireless/ath/ath.o
>>    LD      drivers/net/wireless/ath/built-in.o
>> drivers/net/wireless/ath/wcn36xx/built-in.o: In function `_GLOBAL__sub_I_65535_0_wcn36xx_set_default_rates':
>> /home/linville/git/wireless-next/drivers/net/wireless/ath/wcn36xx/main.c:302: multiple definition of `debug_mask'
>> drivers/net/wireless/ath/ath6kl/built-in.o:/home/linville/git/wireless-next/drivers/net/wireless/ath/ath6kl/cfg80211.c:1208: first defined here
>> make[2]: *** [drivers/net/wireless/ath/built-in.o] Error 1
>> make[1]: *** [drivers/net/wireless/ath] Error 2
>> make: *** [drivers/net/wireless/] Error 2
>>
>> --
>> 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 2/2] ath10k: fix scheduling while atomic bug
From: Kalle Valo @ 2013-10-04  6:37 UTC (permalink / raw)
  To: Michal Kazior; +Cc: ath10k, linux-wireless
In-Reply-To: <CA+BoTQnjG9MnbPsLM-RtAwuGNp_ZAfbvwvR_zg1Ks0ZmUxAtrQ@mail.gmail.com>

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

> On 1 October 2013 18:35, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
>> Michal Kazior <michal.kazior@tieto.com> writes:
>>
>>> Recent WMI/HTC changes broke WEP with multiple
>>> keys. If WMI had no HTC TX credits to submit
>>> command for default wep index update it would
>>> trigger a bug.
>>>
>>> This simply moves the wep key index update to a
>>> worker.
>>>
>>> The key update may happen some time after first
>>> frame with a different wep key has been sent (i.e.
>>> some frames will be sent with old key). This was
>>> the case before too as WMI commands were
>>> asynchronous.
>>>
>>> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
>>
>> This looks problematic. Basically you just delay sending the WMI
>> command, but there's no guarantee that we actually have free credits at
>> the time of transmission. So to me it looks like this fixes the issue
>> just by luck.
>
> One thing at a time.
>
> This patch fixes 'scheduling while atomic' bug that was introduced
> with recent HTC/WMI changes.

Ah, that's what you mean with "triggers a bug" in the commit log? Ok,
even though I consider this very ugly I guess it's alright as a short
term fix. But please describe the bug in more detail in the commit log,
at least mention that we are sleeping in an atomic context (or something
like that).


-- 
Kalle Valo

^ permalink raw reply

* [PATCH 2/2] ath10k: fix possible memory leak in new FW loading
From: Michal Kazior @ 2013-10-04  6:13 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1380867200-19714-1-git-send-email-michal.kazior@tieto.com>

Some failpaths did `return` instead of a `goto`
leaking requested firmware.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index bf85d34..5acb404 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -404,12 +404,14 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 	if (len < magic_len) {
 		ath10k_err("firmware image too small to contain magic: %zu\n",
 			   len);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err;
 	}
 
 	if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
 		ath10k_err("Invalid firmware magic\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err;
 	}
 
 	/* jump over the padding */
@@ -431,7 +433,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 		if (len < ie_len) {
 			ath10k_err("Invalid length for FW IE %d (%zu < %zu)\n",
 				   ie_id, len, ie_len);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto err;
 		}
 
 		switch (ie_id) {
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 0/2] ath10k: minor fixes
From: Michal Kazior @ 2013-10-04  6:13 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior

Hi,

The patchset fixes a compilation warning and a
memory leak in FW loading code.

Michal Kazior (2):
  ath10k: fix printf format string
  ath10k: fix possible memory leak in new FW loading

 drivers/net/wireless/ath/ath10k/core.c |   13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

-- 
1.7.9.5


^ permalink raw reply

* [PATCH 1/2] ath10k: fix printf format string
From: Michal Kazior @ 2013-10-04  6:13 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1380867200-19714-1-git-send-email-michal.kazior@tieto.com>

size_t corresponds to %zu not %d. Compiler was
complaining about it.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 7b5dd09..bf85d34 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -402,7 +402,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 	magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
 
 	if (len < magic_len) {
-		ath10k_err("firmware image too small to contain magic: %d\n",
+		ath10k_err("firmware image too small to contain magic: %zu\n",
 			   len);
 		return -EINVAL;
 	}
@@ -429,7 +429,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 		data += sizeof(*hdr);
 
 		if (len < ie_len) {
-			ath10k_err("Invalid length for FW IE %d (%d < %d)\n",
+			ath10k_err("Invalid length for FW IE %d (%zu < %zu)\n",
 				   ie_id, len, ie_len);
 			return -EINVAL;
 		}
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH/RFT v2 3/4] ath10k: fix scheduling while atomic config bug
From: Michal Kazior @ 2013-10-04  5:43 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1380865425-3791-1-git-send-email-michal.kazior@tieto.com>

Recent HTC/WMI changes introduced the bug. ath10k
was using _atomic iteration function with
sleepable functions.

mac80211 provides another iteration function but
it cannot be safely called in hw_config() callback
due to local->iflist_mtx being possibly acquired
already.

The patch uses internal vif list for iteration
purposes and removes/refactors no longer necessary
_iter functions.

Reported-By: Kalle Valo <kvalo@qca.qualcomm.com>
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
v2:
 * fix kbuild test robot warning
   (uninitialized `ret`)

 drivers/net/wireless/ath/ath10k/mac.c |  146 ++++++++++++++-------------------
 1 file changed, 62 insertions(+), 84 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 292e5cd..583f065 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -723,35 +723,30 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
 /*
  * Review this when mac80211 gains per-interface powersave support.
  */
-static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
 {
-	struct ath10k_generic_iter *ar_iter = data;
-	struct ieee80211_conf *conf = &ar_iter->ar->hw->conf;
-	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+	struct ath10k *ar = arvif->ar;
+	struct ieee80211_conf *conf = &ar->hw->conf;
 	enum wmi_sta_powersave_param param;
 	enum wmi_sta_ps_mode psmode;
 	int ret;
 
 	lockdep_assert_held(&arvif->ar->conf_mutex);
 
-	if (vif->type != NL80211_IFTYPE_STATION)
-		return;
+	if (arvif->vif->type != NL80211_IFTYPE_STATION)
+		return 0;
 
 	if (conf->flags & IEEE80211_CONF_PS) {
 		psmode = WMI_STA_PS_MODE_ENABLED;
 		param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
 
-		ret = ath10k_wmi_set_sta_ps_param(ar_iter->ar,
-						  arvif->vdev_id,
-						  param,
+		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
 						  conf->dynamic_ps_timeout);
 		if (ret) {
 			ath10k_warn("Failed to set inactivity time for VDEV: %d\n",
 				    arvif->vdev_id);
-			return;
+			return ret;
 		}
-
-		ar_iter->ret = ret;
 	} else {
 		psmode = WMI_STA_PS_MODE_DISABLED;
 	}
@@ -759,11 +754,14 @@ static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d psmode %s\n",
 		   arvif->vdev_id, psmode ? "enable" : "disable");
 
-	ar_iter->ret = ath10k_wmi_set_psmode(ar_iter->ar, arvif->vdev_id,
-					     psmode);
-	if (ar_iter->ret)
+	ret = ath10k_wmi_set_psmode(ar, arvif->vdev_id, psmode);
+	if (ret) {
 		ath10k_warn("Failed to set PS Mode: %d for VDEV: %d\n",
 			    psmode, arvif->vdev_id);
+		return ret;
+	}
+
+	return 0;
 }
 
 /**********************/
@@ -1919,9 +1917,10 @@ static void ath10k_stop(struct ieee80211_hw *hw)
 	cancel_work_sync(&ar->restart_work);
 }
 
-static void ath10k_config_ps(struct ath10k *ar)
+static int ath10k_config_ps(struct ath10k *ar)
 {
-	struct ath10k_generic_iter ar_iter;
+	struct ath10k_vif *arvif;
+	int ret = 0;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -1930,17 +1929,17 @@ static void ath10k_config_ps(struct ath10k *ar)
 	 * vdevs at this point we must not iterate over this interface list.
 	 * This setting will be updated upon add_interface(). */
 	if (ar->state == ATH10K_STATE_RESTARTED)
-		return;
-
-	memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter));
-	ar_iter.ar = ar;
+		return 0;
 
-	ieee80211_iterate_active_interfaces_atomic(
-		ar->hw, IEEE80211_IFACE_ITER_NORMAL,
-		ath10k_ps_iter, &ar_iter);
+	list_for_each_entry(arvif, &ar->arvifs, list) {
+		ret = ath10k_mac_vif_setup_ps(arvif);
+		if (ret) {
+			ath10k_warn("could not setup powersave (%d)\n", ret);
+			break;
+		}
+	}
 
-	if (ar_iter.ret)
-		ath10k_warn("failed to set ps config (%d)\n", ar_iter.ret);
+	return ret;
 }
 
 static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
@@ -2834,86 +2833,65 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw)
  * Both RTS and Fragmentation threshold are interface-specific
  * in ath10k, but device-specific in mac80211.
  */
-static void ath10k_set_rts_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath10k_generic_iter *ar_iter = data;
-	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-	u32 rts = ar_iter->ar->hw->wiphy->rts_threshold;
 
-	lockdep_assert_held(&arvif->ar->conf_mutex);
+static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+	struct ath10k *ar = hw->priv;
+	struct ath10k_vif *arvif;
+	int ret = 0;
 
 	/* During HW reconfiguration mac80211 reports all interfaces that were
 	 * running until reconfiguration was started. Since FW doesn't have any
 	 * vdevs at this point we must not iterate over this interface list.
 	 * This setting will be updated upon add_interface(). */
-	if (ar_iter->ar->state == ATH10K_STATE_RESTARTED)
-		return;
-
-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d rts_threshold %d\n",
-		   arvif->vdev_id, rts);
-
-	ar_iter->ret = ath10k_mac_set_rts(arvif, rts);
-	if (ar_iter->ret)
-		ath10k_warn("Failed to set RTS threshold for VDEV: %d\n",
-			    arvif->vdev_id);
-}
-
-static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-{
-	struct ath10k_generic_iter ar_iter;
-	struct ath10k *ar = hw->priv;
-
-	memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter));
-	ar_iter.ar = ar;
+	if (ar->state == ATH10K_STATE_RESTARTED)
+		return 0;
 
 	mutex_lock(&ar->conf_mutex);
-	ieee80211_iterate_active_interfaces_atomic(
-		hw, IEEE80211_IFACE_ITER_NORMAL,
-		ath10k_set_rts_iter, &ar_iter);
+	list_for_each_entry(arvif, &ar->arvifs, list) {
+		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d rts threshold %d\n",
+			   arvif->vdev_id, value);
+
+		ret = ath10k_mac_set_rts(arvif, value);
+		if (ret) {
+			ath10k_warn("could not set rts threshold for vdev %d (%d)\n",
+				    arvif->vdev_id, ret);
+			break;
+		}
+	}
 	mutex_unlock(&ar->conf_mutex);
 
-	return ar_iter.ret;
+	return ret;
 }
 
-static void ath10k_set_frag_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
 {
-	struct ath10k_generic_iter *ar_iter = data;
-	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-	u32 frag = ar_iter->ar->hw->wiphy->frag_threshold;
-
-	lockdep_assert_held(&arvif->ar->conf_mutex);
+	struct ath10k *ar = hw->priv;
+	struct ath10k_vif *arvif;
+	int ret = 0;
 
 	/* During HW reconfiguration mac80211 reports all interfaces that were
 	 * running until reconfiguration was started. Since FW doesn't have any
 	 * vdevs at this point we must not iterate over this interface list.
 	 * This setting will be updated upon add_interface(). */
-	if (ar_iter->ar->state == ATH10K_STATE_RESTARTED)
-		return;
-
-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d fragmentation_threshold %d\n",
-		   arvif->vdev_id, frag);
-
-	ar_iter->ret = ath10k_mac_set_frag(arvif, frag);
-	if (ar_iter->ret)
-		ath10k_warn("Failed to set frag threshold for VDEV: %d\n",
-			    arvif->vdev_id);
-}
-
-static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
-{
-	struct ath10k_generic_iter ar_iter;
-	struct ath10k *ar = hw->priv;
-
-	memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter));
-	ar_iter.ar = ar;
+	if (ar->state == ATH10K_STATE_RESTARTED)
+		return 0;
 
 	mutex_lock(&ar->conf_mutex);
-	ieee80211_iterate_active_interfaces_atomic(
-		hw, IEEE80211_IFACE_ITER_NORMAL,
-		ath10k_set_frag_iter, &ar_iter);
+	list_for_each_entry(arvif, &ar->arvifs, list) {
+		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n",
+			   arvif->vdev_id, value);
+
+		ret = ath10k_mac_set_rts(arvif, value);
+		if (ret) {
+			ath10k_warn("could not set fragmentation threshold for vdev %d (%d)\n",
+				    arvif->vdev_id, ret);
+			break;
+		}
+	}
 	mutex_unlock(&ar->conf_mutex);
 
-	return ar_iter.ret;
+	return ret;
 }
 
 static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH/RFT v2 4/4] ath10k: remove unnecessary checks
From: Michal Kazior @ 2013-10-04  5:43 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1380865425-3791-1-git-send-email-michal.kazior@tieto.com>

mac80211 interface iteration functions that were
used originally iterated over interfaces that
weren't re-added to the driver during recovery.

Since internal vif list is now used it's safe to
remove the safe-guard as internal vif list is
based on add/remove_interface function which
guarantees that vdev is created in FW before it is
iterated over.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c |   21 ---------------------
 1 file changed, 21 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 583f065..7567db0 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1924,13 +1924,6 @@ static int ath10k_config_ps(struct ath10k *ar)
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	/* During HW reconfiguration mac80211 reports all interfaces that were
-	 * running until reconfiguration was started. Since FW doesn't have any
-	 * vdevs at this point we must not iterate over this interface list.
-	 * This setting will be updated upon add_interface(). */
-	if (ar->state == ATH10K_STATE_RESTARTED)
-		return 0;
-
 	list_for_each_entry(arvif, &ar->arvifs, list) {
 		ret = ath10k_mac_vif_setup_ps(arvif);
 		if (ret) {
@@ -2840,13 +2833,6 @@ static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 	struct ath10k_vif *arvif;
 	int ret = 0;
 
-	/* During HW reconfiguration mac80211 reports all interfaces that were
-	 * running until reconfiguration was started. Since FW doesn't have any
-	 * vdevs at this point we must not iterate over this interface list.
-	 * This setting will be updated upon add_interface(). */
-	if (ar->state == ATH10K_STATE_RESTARTED)
-		return 0;
-
 	mutex_lock(&ar->conf_mutex);
 	list_for_each_entry(arvif, &ar->arvifs, list) {
 		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d rts threshold %d\n",
@@ -2870,13 +2856,6 @@ static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
 	struct ath10k_vif *arvif;
 	int ret = 0;
 
-	/* During HW reconfiguration mac80211 reports all interfaces that were
-	 * running until reconfiguration was started. Since FW doesn't have any
-	 * vdevs at this point we must not iterate over this interface list.
-	 * This setting will be updated upon add_interface(). */
-	if (ar->state == ATH10K_STATE_RESTARTED)
-		return 0;
-
 	mutex_lock(&ar->conf_mutex);
 	list_for_each_entry(arvif, &ar->arvifs, list) {
 		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n",
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH/RFT v2 2/4] ath10k: track vif list internally
From: Michal Kazior @ 2013-10-04  5:43 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1380865425-3791-1-git-send-email-michal.kazior@tieto.com>

mac80211 interface interations functions have
peculiar locking issues. This patch introduces
internal (to ath10k) vif list that will be used
for vif iteration purposes.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.c |    2 ++
 drivers/net/wireless/ath/ath10k/core.h |    3 +++
 drivers/net/wireless/ath/ath10k/mac.c  |    3 +++
 3 files changed, 8 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 7b5dd09..4d04dc8 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -710,6 +710,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 	mutex_init(&ar->conf_mutex);
 	spin_lock_init(&ar->data_lock);
 
+	INIT_LIST_HEAD(&ar->arvifs);
 	INIT_LIST_HEAD(&ar->peers);
 	init_waitqueue_head(&ar->peer_mapping_wq);
 
@@ -817,6 +818,7 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err_disconnect_htc;
 
 	ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
+	INIT_LIST_HEAD(&ar->arvifs);
 
 	return 0;
 
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index ce36daa..de20ac0 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -205,6 +205,8 @@ struct ath10k_peer {
 #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
 
 struct ath10k_vif {
+	struct list_head list;
+
 	u32 vdev_id;
 	enum wmi_vdev_type vdev_type;
 	enum wmi_vdev_subtype vdev_subtype;
@@ -402,6 +404,7 @@ struct ath10k {
 	/* protects shared structure data */
 	spinlock_t data_lock;
 
+	struct list_head arvifs;
 	struct list_head peers;
 	wait_queue_head_t peer_mapping_wq;
 
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 7f8b258..292e5cd 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2051,6 +2051,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 	}
 
 	ar->free_vdev_map &= ~BIT(arvif->vdev_id);
+	list_add(&arvif->list, &ar->arvifs);
 
 	vdev_param = ar->wmi.vdev_param->def_keyid;
 	ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param,
@@ -2131,6 +2132,7 @@ err_peer_delete:
 err_vdev_delete:
 	ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
 	ar->free_vdev_map &= ~BIT(arvif->vdev_id);
+	list_del(&arvif->list);
 err:
 	mutex_unlock(&ar->conf_mutex);
 	return ret;
@@ -2153,6 +2155,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 	spin_unlock_bh(&ar->data_lock);
 
 	ar->free_vdev_map |= 1 << (arvif->vdev_id);
+	list_del(&arvif->list);
 
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
 		ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH/RFT v2 1/4] ath10k: fix add_interface failure handling
From: Michal Kazior @ 2013-10-04  5:43 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1380865425-3791-1-git-send-email-michal.kazior@tieto.com>

If something failed along add_interface() setup it
was possible to leak a vdev id, vdev and peer.

This could end up with leaked FW state or FW crash
(assuming add_interface() failure wasn't a result of
a crash).

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c |   50 ++++++++++++++++++++++++---------
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 8684e03..7f8b258 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2001,18 +2001,17 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 	if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) {
 		ath10k_warn("Only one monitor interface allowed\n");
 		ret = -EBUSY;
-		goto exit;
+		goto err;
 	}
 
 	bit = ffs(ar->free_vdev_map);
 	if (bit == 0) {
 		ret = -EBUSY;
-		goto exit;
+		goto err;
 	}
 
 	arvif->vdev_id = bit - 1;
 	arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
-	ar->free_vdev_map &= ~(1 << arvif->vdev_id);
 
 	if (ar->p2p)
 		arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
@@ -2048,26 +2047,32 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 				     arvif->vdev_subtype, vif->addr);
 	if (ret) {
 		ath10k_warn("WMI vdev create failed: ret %d\n", ret);
-		goto exit;
+		goto err;
 	}
 
+	ar->free_vdev_map &= ~BIT(arvif->vdev_id);
+
 	vdev_param = ar->wmi.vdev_param->def_keyid;
 	ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param,
 					arvif->def_wep_key_index);
-	if (ret)
+	if (ret) {
 		ath10k_warn("Failed to set default keyid: %d\n", ret);
+		goto err_vdev_delete;
+	}
 
 	vdev_param = ar->wmi.vdev_param->tx_encap_type;
 	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
 					ATH10K_HW_TXRX_NATIVE_WIFI);
-	if (ret)
+	if (ret) {
 		ath10k_warn("Failed to set TX encap: %d\n", ret);
+		goto err_vdev_delete;
+	}
 
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
 		ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr);
 		if (ret) {
 			ath10k_warn("Failed to create peer for AP: %d\n", ret);
-			goto exit;
+			goto err_vdev_delete;
 		}
 	}
 
@@ -2076,38 +2081,57 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
 		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
 						  param, value);
-		if (ret)
+		if (ret) {
 			ath10k_warn("Failed to set RX wake policy: %d\n", ret);
+			goto err_peer_delete;
+		}
 
 		param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
 		value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
 		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
 						  param, value);
-		if (ret)
+		if (ret) {
 			ath10k_warn("Failed to set TX wake thresh: %d\n", ret);
+			goto err_peer_delete;
+		}
 
 		param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
 		value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
 		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
 						  param, value);
-		if (ret)
+		if (ret) {
 			ath10k_warn("Failed to set PSPOLL count: %d\n", ret);
+			goto err_peer_delete;
+		}
 	}
 
 	ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold);
-	if (ret)
+	if (ret) {
 		ath10k_warn("failed to set rts threshold for vdev %d (%d)\n",
 			    arvif->vdev_id, ret);
+		goto err_peer_delete;
+	}
 
 	ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold);
-	if (ret)
+	if (ret) {
 		ath10k_warn("failed to set frag threshold for vdev %d (%d)\n",
 			    arvif->vdev_id, ret);
+		goto err_peer_delete;
+	}
 
 	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
 		ar->monitor_present = true;
 
-exit:
+	mutex_unlock(&ar->conf_mutex);
+	return 0;
+
+err_peer_delete:
+	if (arvif->vdev_type == WMI_VDEV_TYPE_AP)
+		ath10k_wmi_peer_delete(ar, arvif->vdev_id, vif->addr);
+err_vdev_delete:
+	ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
+	ar->free_vdev_map &= ~BIT(arvif->vdev_id);
+err:
 	mutex_unlock(&ar->conf_mutex);
 	return ret;
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH/RFT v2 0/4] ath10k: fixes
From: Michal Kazior @ 2013-10-04  5:43 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1380805765-31521-1-git-send-email-michal.kazior@tieto.com>

Hi,

This patchset addresses recently spotted issue
with (yet another) scheduling while atomic bug
(the other being WEP key index setting). This one
is related to hw_config() and powersave settings.
This comes from recent changes I've done to
HTC/WMI. WMI commands can block now so it's
illegal to call them in an atomic context anymore.

ath10k needs to setup some settings per-vdev (i.e.
per-interface) such as powersave, rts, fragmentation.
Until now mac80211 iteration functions were used.
However using non-atomic iteration function variant
doesn't solve the problem as it introduces an
issue with iflist_mtx deadlock in some cases.

I briefly tried to reproduce the issue Kalle
reported but was unsuccessful thus the "/RFT".

v2:
 * fix kbuild test robot warning
   (uninitialized `ret`)
 * add patch #4 that removes code that becomes
   unnecessary after patch #3


Michal Kazior (4):
  ath10k: fix add_interface failure handling
  ath10k: track vif list internally
  ath10k: fix scheduling while atomic config bug
  ath10k: remove unnecessary checks

 drivers/net/wireless/ath/ath10k/core.c |    2 +
 drivers/net/wireless/ath/ath10k/core.h |    3 +
 drivers/net/wireless/ath/ath10k/mac.c  |  200 +++++++++++++++-----------------
 3 files changed, 97 insertions(+), 108 deletions(-)

-- 
1.7.9.5


^ permalink raw reply

* Re: [PATCH] net: wireless: wl1251: update firmware path
From: Luca Coelho @ 2013-10-04  5:18 UTC (permalink / raw)
  To: Felipe Balbi; +Cc: linux-wireless, Linux Kernel Mailing List
In-Reply-To: <1380718848-26634-1-git-send-email-balbi@ti.com>

On Wed, 2013-10-02 at 08:00 -0500, Felipe Balbi wrote:
> TI firmwares are located under ti-connectivity
> directory. Update path to make sure driver can
> find and load firmware blob.
> 
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> ---

Applied, thanks Felipe!

--
Luca.


^ permalink raw reply

* Re: [PATCH v2 01/11] wlcore: ROC on AP channel before auth reply
From: Luca Coelho @ 2013-10-04  5:10 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless
In-Reply-To: <1379432490-22157-1-git-send-email-eliad@wizery.com>

Hi,

I think I forgot to say, but I already applied all this series and John
has already pulled it.  Just for the record.

--
Luca.

On Tue, 2013-09-17 at 18:41 +0300, Eliad Peller wrote:
> From: Arik Nemtsov <arik@wizery.com>
> 
> Start a ROC on the AP channel beforing sending the authentication reply
> to a connecting STA. This ROC is held up to 1 second via a timer. If the
> station is authorized and added by mac80211, the ROC is extended until
> the station is fully authorized.
> We make sure not to ROC twice when several stations are connecting in
> parallel and to only release the ROC when both the pending-reply timer
> and the STA-state callbacks do not require it.
> 
> Signed-off-by: Arik Nemtsov <arik@wizery.com>
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
>  drivers/net/wireless/ti/wlcore/main.c     | 101 +++++++++++++++++++++++++-----
>  drivers/net/wireless/ti/wlcore/tx.c       |  25 ++++++--
>  drivers/net/wireless/ti/wlcore/tx.h       |   3 +
>  drivers/net/wireless/ti/wlcore/wlcore.h   |   2 +
>  drivers/net/wireless/ti/wlcore/wlcore_i.h |   9 +++
>  5 files changed, 120 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
> index 38995f9..b64b465 100644
> --- a/drivers/net/wireless/ti/wlcore/main.c
> +++ b/drivers/net/wireless/ti/wlcore/main.c
> @@ -2008,6 +2008,47 @@ out:
>  	mutex_unlock(&wl->mutex);
>  }
>  
> +static void wlcore_pending_auth_complete_work(struct work_struct *work)
> +{
> +	struct delayed_work *dwork;
> +	struct wl1271 *wl;
> +	struct wl12xx_vif *wlvif;
> +	unsigned long time_spare;
> +	int ret;
> +
> +	dwork = container_of(work, struct delayed_work, work);
> +	wlvif = container_of(dwork, struct wl12xx_vif,
> +			     pending_auth_complete_work);
> +	wl = wlvif->wl;
> +
> +	mutex_lock(&wl->mutex);
> +
> +	if (unlikely(wl->state != WLCORE_STATE_ON))
> +		goto out;
> +
> +	/*
> +	 * Make sure a second really passed since the last auth reply. Maybe
> +	 * a second auth reply arrived while we were stuck on the mutex.
> +	 * Check for a little less than the timeout to protect from scheduler
> +	 * irregularities.
> +	 */
> +	time_spare = jiffies +
> +			msecs_to_jiffies(WLCORE_PEND_AUTH_ROC_TIMEOUT - 50);
> +	if (!time_after(time_spare, wlvif->pending_auth_reply_time))
> +		goto out;
> +
> +	ret = wl1271_ps_elp_wakeup(wl);
> +	if (ret < 0)
> +		goto out;
> +
> +	/* cancel the ROC if active */
> +	wlcore_update_inconn_sta(wl, wlvif, NULL, false);
> +
> +	wl1271_ps_elp_sleep(wl);
> +out:
> +	mutex_unlock(&wl->mutex);
> +}
> +
>  static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx)
>  {
>  	u8 policy = find_first_zero_bit(wl->rate_policies_map,
> @@ -2159,6 +2200,8 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
>  			  wlcore_channel_switch_work);
>  	INIT_DELAYED_WORK(&wlvif->connection_loss_work,
>  			  wlcore_connection_loss_work);
> +	INIT_DELAYED_WORK(&wlvif->pending_auth_complete_work,
> +			  wlcore_pending_auth_complete_work);
>  	INIT_LIST_HEAD(&wlvif->list);
>  
>  	setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer,
> @@ -2590,6 +2633,7 @@ unlock:
>  	cancel_work_sync(&wlvif->rx_streaming_disable_work);
>  	cancel_delayed_work_sync(&wlvif->connection_loss_work);
>  	cancel_delayed_work_sync(&wlvif->channel_switch_work);
> +	cancel_delayed_work_sync(&wlvif->pending_auth_complete_work);
>  
>  	mutex_lock(&wl->mutex);
>  }
> @@ -3969,6 +4013,13 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
>  			}
>  		} else {
>  			if (test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) {
> +				/*
> +				 * AP might be in ROC in case we have just
> +				 * sent auth reply. handle it.
> +				 */
> +				if (test_bit(wlvif->role_id, wl->roc_map))
> +					wl12xx_croc(wl, wlvif->role_id);
> +
>  				ret = wl12xx_cmd_role_stop_ap(wl, wlvif);
>  				if (ret < 0)
>  					goto out;
> @@ -4656,29 +4707,49 @@ static void wlcore_roc_if_possible(struct wl1271 *wl,
>  	wl12xx_roc(wl, wlvif, wlvif->role_id, wlvif->band, wlvif->channel);
>  }
>  
> -static void wlcore_update_inconn_sta(struct wl1271 *wl,
> -				     struct wl12xx_vif *wlvif,
> -				     struct wl1271_station *wl_sta,
> -				     bool in_connection)
> +/*
> + * when wl_sta is NULL, we treat this call as if coming from a
> + * pending auth reply.
> + * wl->mutex must be taken and the FW must be awake when the call
> + * takes place.
> + */
> +void wlcore_update_inconn_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif,
> +			      struct wl1271_station *wl_sta, bool in_conn)
>  {
> -	if (in_connection) {
> -		if (WARN_ON(wl_sta->in_connection))
> +	if (in_conn) {
> +		if (WARN_ON(wl_sta && wl_sta->in_connection))
>  			return;
> -		wl_sta->in_connection = true;
> -		if (!wlvif->inconn_count++)
> +
> +		if (!wlvif->ap_pending_auth_reply &&
> +		    !wlvif->inconn_count)
>  			wlcore_roc_if_possible(wl, wlvif);
> +
> +		if (wl_sta) {
> +			wl_sta->in_connection = true;
> +			wlvif->inconn_count++;
> +		} else {
> +			wlvif->ap_pending_auth_reply = true;
> +		}
>  	} else {
> -		if (!wl_sta->in_connection)
> +		if (wl_sta && !wl_sta->in_connection)
> +			return;
> +
> +		if (WARN_ON(!wl_sta && !wlvif->ap_pending_auth_reply))
>  			return;
>  
> -		wl_sta->in_connection = false;
> -		wlvif->inconn_count--;
> -		if (WARN_ON(wlvif->inconn_count < 0))
> +		if (WARN_ON(wl_sta && !wlvif->inconn_count))
>  			return;
>  
> -		if (!wlvif->inconn_count)
> -			if (test_bit(wlvif->role_id, wl->roc_map))
> -				wl12xx_croc(wl, wlvif->role_id);
> +		if (wl_sta) {
> +			wl_sta->in_connection = false;
> +			wlvif->inconn_count--;
> +		} else {
> +			wlvif->ap_pending_auth_reply = false;
> +		}
> +
> +		if (!wlvif->inconn_count && !wlvif->ap_pending_auth_reply &&
> +		    test_bit(wlvif->role_id, wl->roc_map))
> +			wl12xx_croc(wl, wlvif->role_id);
>  	}
>  }
>  
> diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
> index 7e93fe6..03249da 100644
> --- a/drivers/net/wireless/ti/wlcore/tx.c
> +++ b/drivers/net/wireless/ti/wlcore/tx.c
> @@ -86,19 +86,34 @@ void wl1271_free_tx_id(struct wl1271 *wl, int id)
>  EXPORT_SYMBOL(wl1271_free_tx_id);
>  
>  static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
> +						 struct wl12xx_vif *wlvif,
>  						 struct sk_buff *skb)
>  {
>  	struct ieee80211_hdr *hdr;
>  
> +	hdr = (struct ieee80211_hdr *)(skb->data +
> +				       sizeof(struct wl1271_tx_hw_descr));
> +	if (!ieee80211_is_auth(hdr->frame_control))
> +		return;
> +
>  	/*
>  	 * add the station to the known list before transmitting the
>  	 * authentication response. this way it won't get de-authed by FW
>  	 * when transmitting too soon.
>  	 */
> -	hdr = (struct ieee80211_hdr *)(skb->data +
> -				       sizeof(struct wl1271_tx_hw_descr));
> -	if (ieee80211_is_auth(hdr->frame_control))
> -		wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
> +	wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
> +
> +	/*
> +	 * ROC for 1 second on the AP channel for completing the connection.
> +	 * Note the ROC will be continued by the update_sta_state callbacks
> +	 * once the station reaches the associated state.
> +	 */
> +	wlcore_update_inconn_sta(wl, wlvif, NULL, true);
> +	wlvif->pending_auth_reply_time = jiffies;
> +	cancel_delayed_work(&wlvif->pending_auth_complete_work);
> +	ieee80211_queue_delayed_work(wl->hw,
> +				&wlvif->pending_auth_complete_work,
> +				msecs_to_jiffies(WLCORE_PEND_AUTH_ROC_TIMEOUT));
>  }
>  
>  static void wl1271_tx_regulate_link(struct wl1271 *wl,
> @@ -404,7 +419,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
>  	wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid);
>  
>  	if (!is_dummy && wlvif && wlvif->bss_type == BSS_TYPE_AP_BSS) {
> -		wl1271_tx_ap_update_inconnection_sta(wl, skb);
> +		wl1271_tx_ap_update_inconnection_sta(wl, wlvif, skb);
>  		wl1271_tx_regulate_link(wl, wlvif, hlid);
>  	}
>  
> diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h
> index 55aa4ac..35489c3 100644
> --- a/drivers/net/wireless/ti/wlcore/tx.h
> +++ b/drivers/net/wireless/ti/wlcore/tx.h
> @@ -56,6 +56,9 @@
>  /* Used for management frames and dummy packets */
>  #define WL1271_TID_MGMT 7
>  
> +/* stop a ROC for pending authentication reply after this time (ms) */
> +#define WLCORE_PEND_AUTH_ROC_TIMEOUT     1000
> +
>  struct wl127x_tx_mem {
>  	/*
>  	 * Number of extra memory blocks to allocate for this packet
> diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
> index 0034979..54ce5d5 100644
> --- a/drivers/net/wireless/ti/wlcore/wlcore.h
> +++ b/drivers/net/wireless/ti/wlcore/wlcore.h
> @@ -481,6 +481,8 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
>  		   struct ieee80211_sta *sta,
>  		   struct ieee80211_key_conf *key_conf);
>  void wlcore_regdomain_config(struct wl1271 *wl);
> +void wlcore_update_inconn_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif,
> +			      struct wl1271_station *wl_sta, bool in_conn);
>  
>  static inline void
>  wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band,
> diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
> index e5e1464..14fd111 100644
> --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
> +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
> @@ -456,6 +456,15 @@ struct wl12xx_vif {
>  	 */
>  	int hw_queue_base;
>  
> +	/* do we have a pending auth reply? (and ROC) */
> +	bool ap_pending_auth_reply;
> +
> +	/* time when we sent the pending auth reply */
> +	unsigned long pending_auth_reply_time;
> +
> +	/* work for canceling ROC after pending auth reply */
> +	struct delayed_work pending_auth_complete_work;
> +
>  	/*
>  	 * This struct must be last!
>  	 * data that has to be saved acrossed reconfigs (e.g. recovery)



^ permalink raw reply

* Re: [GIT PULL] firmware: wl1251 firmware binary
From: Luca Coelho @ 2013-10-04  5:01 UTC (permalink / raw)
  To: balbi; +Cc: dwmw2, ben, Linux Kernel Mailing List, linux-wireless,
	Pavel Machek
In-Reply-To: <20131002125535.GL1476@radagast>

Hi Felipe,

On Wed, 2013-10-02 at 07:55 -0500, Felipe Balbi wrote:
> Hi,
> 
> here's a pull request for wl4 firmware. I'll send a patch for wl1251
> driver updating firmware load path.
> 
> The following changes since commit b8ac7c7e27dcd13fa3c843aaf62457e9c57ea4db:
> 
>   linux-firmware: Add Brocade FC/FCOE Adapter firmware files (2013-09-30 04:53:32 +0100)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/balbi/linux-firmware.git wilink4
> 
> for you to fetch changes up to d726804dbc8dad88587b6be17716714cd91ed86c:
> 
>   ti-connectivity: add wl1251 firmware and license (2013-10-02 06:55:39 -0500)
> 
> ----------------------------------------------------------------
> Felipe Balbi (1):
>       ti-connectivity: add wl1251 firmware and license
> 
>  LICENCE.wl1251                 |  59 +++++++++++++++++++++++++++++++++++++++++
>  WHENCE                         |  18 +++++++++++++
>  ti-connectivity/wl1251-fw.bin  | Bin 0 -> 194180 bytes
>  ti-connectivity/wl1251-nvs.bin | Bin 0 -> 752 bytes
>  4 files changed, 77 insertions(+)
>  create mode 100644 LICENCE.wl1251
>  create mode 100644 ti-connectivity/wl1251-fw.bin
>  create mode 100644 ti-connectivity/wl1251-nvs.bin

Since you didn't send v2 of the patch, you could have used the -p option
with git request-pull so we could see the changes you made here...

--
Cheers,
Luca.



^ permalink raw reply

* Re: [PATCH] rt2x00: rt2800lib: remove duplicate rf_vals for RF3053.
From: Kevin Lo @ 2013-10-04  1:41 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: John Linville, linux-wireless, users
In-Reply-To: <524D5DCE.80601@openwrt.org>

Gabor Juhos wrote:
> 2013.10.03. 9:48 keltezéssel, Kevin Lo írta:
>> We already have rf_vals_3x with same values.  Hence rf_vals_3053 is removed
>> in this patch.
>>
>> Signed-off-by: Kevin Lo <kevlo@kevlo.org>
> For completeness, the comment of rf_vals_3x should be updated to indicate that
> it also supports RF3053. Otherwise the patch is fine.

Ok, I'll send an updated patch, thanks.

>
> -Gabor
>

     Kevin

^ permalink raw reply

* [PATCH v2] rt2x00: rt2800lib: remove duplicate rf_vals for RF3053
From: Kevin Lo @ 2013-10-04  1:41 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, users

We already have rf_vals_3x with same values.  Hence rf_vals_3053 is removed
in this patch.

Signed-off-by: Kevin Lo <kevlo@kevlo.org>
Acked-by: Paul Menzel <paulepanter@users.sourceforge.net>
---
Changes since v1:
   - update comment of rf_vals_3x to indicate that it also supports RF3053
   - add Paul's Acked-by tag
---

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c 
b/drivers/net/wireless/rt2x00/rt2800lib.c
index 25aaa5e..78ce749 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7224,7 +7224,7 @@ static const struct rf_channel rf_vals[] = {

  /*
   * RF value list for rt3xxx
- * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052)
+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052 & RF3053)
   */
  static const struct rf_channel rf_vals_3x[] = {
         {1,  241, 2, 2 },
@@ -7420,72 +7420,6 @@ static const struct rf_channel 
rf_vals_5592_xtal40[] = {
         {196, 83, 0, 12, 1},
  };

-static const struct rf_channel rf_vals_3053[] = {
-       /* Channel, N, R, K */
-       {1, 241, 2, 2},
-       {2, 241, 2, 7},
-       {3, 242, 2, 2},
-       {4, 242, 2, 7},
-       {5, 243, 2, 2},
-       {6, 243, 2, 7},
-       {7, 244, 2, 2},
-       {8, 244, 2, 7},
-       {9, 245, 2, 2},
-       {10, 245, 2, 7},
-       {11, 246, 2, 2},
-       {12, 246, 2, 7},
-       {13, 247, 2, 2},
-       {14, 248, 2, 4},
-
-       {36, 0x56, 0, 4},
-       {38, 0x56, 0, 6},
-       {40, 0x56, 0, 8},
-       {44, 0x57, 0, 0},
-       {46, 0x57, 0, 2},
-       {48, 0x57, 0, 4},
-       {52, 0x57, 0, 8},
-       {54, 0x57, 0, 10},
-       {56, 0x58, 0, 0},
-       {60, 0x58, 0, 4},
-       {62, 0x58, 0, 6},
-       {64, 0x58, 0, 8},
-
-       {100, 0x5B, 0, 8},
-       {102, 0x5B, 0, 10},
-       {104, 0x5C, 0, 0},
-       {108, 0x5C, 0, 4},
-       {110, 0x5C, 0, 6},
-       {112, 0x5C, 0, 8},
-
-       /* NOTE: Channel 114 has been removed intentionally.
-        * The EEPROM contains no TX power values for that,
-        * and it is disabled in the vendor driver as well.
-        */
-
-       {116, 0x5D, 0, 0},
-       {118, 0x5D, 0, 2},
-       {120, 0x5D, 0, 4},
-       {124, 0x5D, 0, 8},
-       {126, 0x5D, 0, 10},
-       {128, 0x5E, 0, 0},
-       {132, 0x5E, 0, 4},
-       {134, 0x5E, 0, 6},
-       {136, 0x5E, 0, 8},
-       {140, 0x5F, 0, 0},
-
-       {149, 0x5F, 0, 9},
-       {151, 0x5F, 0, 11},
-       {153, 0x60, 0, 1},
-       {157, 0x60, 0, 5},
-       {159, 0x60, 0, 7},
-       {161, 0x60, 0, 9},
-       {165, 0x61, 0, 1},
-       {167, 0x61, 0, 3},
-       {169, 0x61, 0, 5},
-       {171, 0x61, 0, 7},
-       {173, 0x61, 0, 9},
-};
-
  static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
  {
         struct hw_mode_spec *spec = &rt2x00dev->spec;
@@ -7575,14 +7509,11 @@ static int rt2800_probe_hw_mode(struct 
rt2x00_dev *rt2x00dev)
                    rt2x00_rf(rt2x00dev, RF5392)) {
                 spec->num_channels = 14;
                 spec->channels = rf_vals_3x;
-       } else if (rt2x00_rf(rt2x00dev, RF3052)) {
+       } else if (rt2x00_rf(rt2x00dev, RF3052) ||
+                  rt2x00_rf(rt2x00dev, RF3053)) {
                 spec->supported_bands |= SUPPORT_BAND_5GHZ;
                 spec->num_channels = ARRAY_SIZE(rf_vals_3x);
                 spec->channels = rf_vals_3x;
-       } else if (rt2x00_rf(rt2x00dev, RF3053)) {
-               spec->supported_bands |= SUPPORT_BAND_5GHZ;
-               spec->num_channels = ARRAY_SIZE(rf_vals_3053);
-               spec->channels = rf_vals_3053;
         } else if (rt2x00_rf(rt2x00dev, RF5592)) {
                 spec->supported_bands |= SUPPORT_BAND_5GHZ;



^ permalink raw reply related

* Re: [PATCH] Bluetooth: btmrvl: operate on 16-bit opcodes instead of ogf/ocf
From: Anderson Lizardo @ 2013-10-03 23:26 UTC (permalink / raw)
  To: Bing Zhao
  Cc: BlueZ development, Marcel Holtmann, Gustavo Padovan,
	Johan Hedberg, linux-wireless@vger.kernel.org, Amitkumar Karwar
In-Reply-To: <477F20668A386D41ADCC57781B1F70430F451FB266@SC-VEXCH1.marvell.com>

Hi Bing,

On Thu, Oct 3, 2013 at 5:06 PM, Bing Zhao <bzhao@marvell.com> wrote:
>> >         hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
>> > -       hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
>> > +       hdr->opcode = cpu_to_le16(opcode);
>>
>> Are you sure the callers of btmrvl_send_sync_cmd() do not need to be
>> changed to pass an opcode instead of just the OCF?
>
> Previously we pass the cmd_no which is the OCF bits to the function, and the function packs it to opcode.
>
> Now I changed the macros of the cmd_no from OCF to opcode as shown below, so no change to the callers.
>
> -/* Bluetooth commands  */
> -#define BT_CMD_AUTO_SLEEP_MODE         0x23
> -#define BT_CMD_HOST_SLEEP_CONFIG       0x59
> -#define BT_CMD_HOST_SLEEP_ENABLE       0x5A
> -#define BT_CMD_MODULE_CFG_REQ          0x5B
> -#define BT_CMD_LOAD_CONFIG_DATA                0x61
> +/* Vendor specific Bluetooth commands */
> +#define BT_CMD_AUTO_SLEEP_MODE         0xFC23
> +#define BT_CMD_HOST_SLEEP_CONFIG       0xFC59
> +#define BT_CMD_HOST_SLEEP_ENABLE       0xFC5A
> +#define BT_CMD_MODULE_CFG_REQ          0xFC5B
> +#define BT_CMD_LOAD_CONFIG_DATA                0xFC61

Now I got it :)

Best Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* Re: Ideas on why using WPA2 encryption speeds up many TCP connections?
From: Ben Greear @ 2013-10-03 23:19 UTC (permalink / raw)
  To: Rick Jones; +Cc: netdev, linux-wireless@vger.kernel.org
In-Reply-To: <524DC2B8.905@candelatech.com>

I was seeing an un-expectedly bad wifi train rates, so I changed to ath9k-rate-control,
rebooted, and re-ran the tests.  Throughput is much improved.  I really hope it wasn't just
a reboot that fixed it, but too burned out to do more tests today.

I still see better TCP throughput with WPA2 when using 25-200 stations/streams.

For anyone who wants to wade through some big automated reports, see the links
near the top of this page (suggestions for improving those reports are welcome):

http://www.candelatech.com/lf_wifi_examples.php

(The 600 station reports are a bit dated and were done in a fairly busy
  wifi environment.  We'll re-run those sometime soon-ish.)

Thanks,
Ben

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


^ permalink raw reply

* Re: [PATCH] wcn36xx: mac80211 driver for Qualcomm WCN3660/WCN3680 hardware
From: Eugene Krasnikov @ 2013-10-03 21:22 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, wcn36xx
In-Reply-To: <20131003205710.GH3142@tuxdriver.com>

Hm, weird... do not see this problem myself. Let me try to sync latest
wireless-next and will try to apply latest patch from this mailthread
on top.

P.S. If somebody esle can try to apply this patch and build that would
be useful to know if problem is visible on others PCs as well.

2013/10/3 John W. Linville <linville@tuxdriver.com>:
> On Thu, Sep 26, 2013 at 11:25:18PM +0100, Eugene Krasnikov wrote:
>> Hi John,
>>
>> This is the latest version of wcn36xx driver on top of current
>> wireless-next tree. Please let me know if you have any problems with
>> applying it.
>>
>> 2013/9/26 Eugene Krasnikov <k.eugene.e@gmail.com>:
>> > This is a mac80211 driver for Qualcomm WCN3660/WCN3680 devices. So
>> > far WCN3660/WCN3680 is available only on MSM platform.
>> >
>> > Firmware can be found here:
>> > https://www.codeaurora.org/cgit/external/hisense/platform/vendor/qcom-opensource/wlan/prima/tree/firmware_bin?h=8130_CS
>> >
>> > Wiki page is available here:
>> > http://wireless.kernel.org/en/users/Drivers/wcn36xx
>> >
>> > A lot people made a contribution to this driver. Here is the list in
>> > alphabetical order:
>> >
>> > Eugene Krasnikov <k.eugene.e@gmail.com>
>> > Kalle Valo <kvalo@qca.qualcomm.com>
>> > Olof Johansson <dev@skyshaper.net>
>> > Pontus Fuchs <pontus.fuchs@gmail.com>
>> > Yanbo Li <yanbol@qti.qualcomm.com>
>> >
>> > Signed-off-by: Eugene Krasnikov <k.eugene.e@gmail.com>
>
> 'make allyesconfig' yield this:
>
>   LD      drivers/net/wireless/ath/ath.o
>   LD      drivers/net/wireless/ath/built-in.o
> drivers/net/wireless/ath/wcn36xx/built-in.o: In function `_GLOBAL__sub_I_65535_0_wcn36xx_set_default_rates':
> /home/linville/git/wireless-next/drivers/net/wireless/ath/wcn36xx/main.c:302: multiple definition of `debug_mask'
> drivers/net/wireless/ath/ath6kl/built-in.o:/home/linville/git/wireless-next/drivers/net/wireless/ath/ath6kl/cfg80211.c:1208: first defined here
> make[2]: *** [drivers/net/wireless/ath/built-in.o] Error 1
> make[1]: *** [drivers/net/wireless/ath] Error 2
> make: *** [drivers/net/wireless/] Error 2
>
> --
> John W. Linville                Someday the world will need a hero, and you
> linville@tuxdriver.com                  might be all we have.  Be ready.



-- 
Best regards,
Eugene

^ permalink raw reply

* [PATCH v2] Bluetooth: btmrvl: operate on 16-bit opcodes instead of ogf/ocf
From: Bing Zhao @ 2013-10-03 21:19 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Anderson Lizardo,
	linux-wireless, Amitkumar Karwar, Bing Zhao

Replace ogf/ocf and its packing with 16-bit opcodes.

Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
v2: Use hci_opcode_ogf() to make code more readable. (Anderson Lizardo)

 drivers/bluetooth/btmrvl_drv.h  | 19 +++++++++++--------
 drivers/bluetooth/btmrvl_main.c | 21 +++++++++------------
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index f9d1833..e3b49c6 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -90,12 +90,12 @@ struct btmrvl_private {
 
 #define MRVL_VENDOR_PKT			0xFE
 
-/* Bluetooth commands  */
-#define BT_CMD_AUTO_SLEEP_MODE		0x23
-#define BT_CMD_HOST_SLEEP_CONFIG	0x59
-#define BT_CMD_HOST_SLEEP_ENABLE	0x5A
-#define BT_CMD_MODULE_CFG_REQ		0x5B
-#define BT_CMD_LOAD_CONFIG_DATA		0x61
+/* Vendor specific Bluetooth commands */
+#define BT_CMD_AUTO_SLEEP_MODE		0xFC23
+#define BT_CMD_HOST_SLEEP_CONFIG	0xFC59
+#define BT_CMD_HOST_SLEEP_ENABLE	0xFC5A
+#define BT_CMD_MODULE_CFG_REQ		0xFC5B
+#define BT_CMD_LOAD_CONFIG_DATA		0xFC61
 
 /* Sub-commands: Module Bringup/Shutdown Request/Response */
 #define MODULE_BRINGUP_REQ		0xF1
@@ -104,6 +104,11 @@ struct btmrvl_private {
 
 #define MODULE_SHUTDOWN_REQ		0xF2
 
+/* Vendor specific Bluetooth events */
+#define BT_EVENT_AUTO_SLEEP_MODE	0x23
+#define BT_EVENT_HOST_SLEEP_CONFIG	0x59
+#define BT_EVENT_HOST_SLEEP_ENABLE	0x5A
+#define BT_EVENT_MODULE_CFG_REQ		0x5B
 #define BT_EVENT_POWER_STATE		0x20
 
 /* Bluetooth Power States */
@@ -111,8 +116,6 @@ struct btmrvl_private {
 #define BT_PS_DISABLE			0x03
 #define BT_PS_SLEEP			0x01
 
-#define OGF				0x3F
-
 /* Host Sleep states */
 #define HS_ACTIVATED			0x01
 #define HS_DEACTIVATED			0x00
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 6e7bd4e..ffec74e 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -50,12 +50,10 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
 
 	if (hdr->evt == HCI_EV_CMD_COMPLETE) {
 		struct hci_ev_cmd_complete *ec;
-		u16 opcode, ocf, ogf;
+		u16 opcode;
 
 		ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
 		opcode = __le16_to_cpu(ec->opcode);
-		ocf = hci_opcode_ocf(opcode);
-		ogf = hci_opcode_ogf(opcode);
 
 		if (priv->btmrvl_dev.sendcmdflag) {
 			priv->btmrvl_dev.sendcmdflag = false;
@@ -63,9 +61,8 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
 			wake_up_interruptible(&priv->adapter->cmd_wait_q);
 		}
 
-		if (ogf == OGF) {
-			BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x",
-			       ogf, ocf);
+		if (hci_opcode_ogf(opcode) == 0x3F) {
+			BT_DBG("vendor event skipped: opcode=%#4.4x", opcode);
 			kfree_skb(skb);
 			return false;
 		}
@@ -89,7 +86,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
 	}
 
 	switch (event->data[0]) {
-	case BT_CMD_AUTO_SLEEP_MODE:
+	case BT_EVENT_AUTO_SLEEP_MODE:
 		if (!event->data[2]) {
 			if (event->data[1] == BT_PS_ENABLE)
 				adapter->psmode = 1;
@@ -102,7 +99,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
 		}
 		break;
 
-	case BT_CMD_HOST_SLEEP_CONFIG:
+	case BT_EVENT_HOST_SLEEP_CONFIG:
 		if (!event->data[3])
 			BT_DBG("gpio=%x, gap=%x", event->data[1],
 							event->data[2]);
@@ -110,7 +107,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
 			BT_DBG("HSCFG command failed");
 		break;
 
-	case BT_CMD_HOST_SLEEP_ENABLE:
+	case BT_EVENT_HOST_SLEEP_ENABLE:
 		if (!event->data[1]) {
 			adapter->hs_state = HS_ACTIVATED;
 			if (adapter->psmode)
@@ -121,7 +118,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
 		}
 		break;
 
-	case BT_CMD_MODULE_CFG_REQ:
+	case BT_EVENT_MODULE_CFG_REQ:
 		if (priv->btmrvl_dev.sendcmdflag &&
 				event->data[1] == MODULE_BRINGUP_REQ) {
 			BT_DBG("EVENT:%s",
@@ -166,7 +163,7 @@ exit:
 }
 EXPORT_SYMBOL_GPL(btmrvl_process_event);
 
-static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
+static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
 				const void *param, u8 len)
 {
 	struct sk_buff *skb;
@@ -179,7 +176,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
 	}
 
 	hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
-	hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
+	hdr->opcode = cpu_to_le16(opcode);
 	hdr->plen = len;
 
 	if (len)
-- 
1.8.0


^ permalink raw reply related

* RE: [PATCH] Bluetooth: btmrvl: operate on 16-bit opcodes instead of ogf/ocf
From: Bing Zhao @ 2013-10-03 21:06 UTC (permalink / raw)
  To: Anderson Lizardo
  Cc: BlueZ development, Marcel Holtmann, Gustavo Padovan,
	Johan Hedberg, linux-wireless@vger.kernel.org, Amitkumar Karwar
In-Reply-To: <CAJdJm_N1=a7URKmU8xOsOzOaYHKQdNXiR7VryeOc4+i2uf7RqQ@mail.gmail.com>

Hi Anderson,

Thanks for your comments.

> > -               if (ogf == OGF) {
> > -                       BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x",
> > -                              ogf, ocf);
> > +               if ((opcode & 0xfc00) == 0xfc00) {
> > +                       BT_DBG("vendor event skipped: opcode=%#4.4x", opcode);
> 
> I think you could use "if (hci_opcode_ogf(opcode) == 0x3F)" to make it
> more readable.

Sure, I will make that change in v2.

> > @@ -179,7 +176,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
> >         }
> >
> >         hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
> > -       hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
> > +       hdr->opcode = cpu_to_le16(opcode);
> 
> Are you sure the callers of btmrvl_send_sync_cmd() do not need to be
> changed to pass an opcode instead of just the OCF?

Previously we pass the cmd_no which is the OCF bits to the function, and the function packs it to opcode.

Now I changed the macros of the cmd_no from OCF to opcode as shown below, so no change to the callers.

-/* Bluetooth commands  */
-#define BT_CMD_AUTO_SLEEP_MODE		0x23
-#define BT_CMD_HOST_SLEEP_CONFIG	0x59
-#define BT_CMD_HOST_SLEEP_ENABLE	0x5A
-#define BT_CMD_MODULE_CFG_REQ		0x5B
-#define BT_CMD_LOAD_CONFIG_DATA		0x61
+/* Vendor specific Bluetooth commands */
+#define BT_CMD_AUTO_SLEEP_MODE		0xFC23
+#define BT_CMD_HOST_SLEEP_CONFIG	0xFC59
+#define BT_CMD_HOST_SLEEP_ENABLE	0xFC5A
+#define BT_CMD_MODULE_CFG_REQ		0xFC5B
+#define BT_CMD_LOAD_CONFIG_DATA		0xFC61

Thanks,
Bing

^ permalink raw reply

* Re: [PATCH] wcn36xx: mac80211 driver for Qualcomm WCN3660/WCN3680 hardware
From: John W. Linville @ 2013-10-03 20:57 UTC (permalink / raw)
  To: Eugene Krasnikov; +Cc: linux-wireless, wcn36xx
In-Reply-To: <CAFSJ42bybEGtkzJ99fZHrcPs=gTnvJVHxM7d8anJvn1VOs7V7A@mail.gmail.com>

On Thu, Sep 26, 2013 at 11:25:18PM +0100, Eugene Krasnikov wrote:
> Hi John,
> 
> This is the latest version of wcn36xx driver on top of current
> wireless-next tree. Please let me know if you have any problems with
> applying it.
> 
> 2013/9/26 Eugene Krasnikov <k.eugene.e@gmail.com>:
> > This is a mac80211 driver for Qualcomm WCN3660/WCN3680 devices. So
> > far WCN3660/WCN3680 is available only on MSM platform.
> >
> > Firmware can be found here:
> > https://www.codeaurora.org/cgit/external/hisense/platform/vendor/qcom-opensource/wlan/prima/tree/firmware_bin?h=8130_CS
> >
> > Wiki page is available here:
> > http://wireless.kernel.org/en/users/Drivers/wcn36xx
> >
> > A lot people made a contribution to this driver. Here is the list in
> > alphabetical order:
> >
> > Eugene Krasnikov <k.eugene.e@gmail.com>
> > Kalle Valo <kvalo@qca.qualcomm.com>
> > Olof Johansson <dev@skyshaper.net>
> > Pontus Fuchs <pontus.fuchs@gmail.com>
> > Yanbo Li <yanbol@qti.qualcomm.com>
> >
> > Signed-off-by: Eugene Krasnikov <k.eugene.e@gmail.com>

'make allyesconfig' yield this:

  LD      drivers/net/wireless/ath/ath.o
  LD      drivers/net/wireless/ath/built-in.o
drivers/net/wireless/ath/wcn36xx/built-in.o: In function `_GLOBAL__sub_I_65535_0_wcn36xx_set_default_rates':
/home/linville/git/wireless-next/drivers/net/wireless/ath/wcn36xx/main.c:302: multiple definition of `debug_mask'
drivers/net/wireless/ath/ath6kl/built-in.o:/home/linville/git/wireless-next/drivers/net/wireless/ath/ath6kl/cfg80211.c:1208: first defined here
make[2]: *** [drivers/net/wireless/ath/built-in.o] Error 1
make[1]: *** [drivers/net/wireless/ath] Error 2
make: *** [drivers/net/wireless/] Error 2

-- 
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


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