Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] mac80211: make mpath path fixing more robust
From: Thomas Pedersen @ 2016-09-06 18:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg, Thomas Pedersen

A fixed mpath was not quite being treated as such:

1) if a PERR frame was received, a fixed mpath was
   deactivated.

2) queued path discovery for fixed mpath was potentially
   being considered, changing mpath state.

3) other mpath flags were potentially being inherited when
   fixing the mpath. Just assign PATH_FIXED and SN_VALID.

This solves several issues when fixing a mesh path in one
direction. The reverse direction mpath should probably
also be fixed, or root announcements at least be enabled.

Signed-off-by: Thomas Pedersen <twp@qca.qualcomm.com>
---
 net/mac80211/mesh_hwmp.c    | 3 ++-
 net/mac80211/mesh_pathtbl.c | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index fa7d37c..b747c96 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -757,6 +757,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
 		sta = next_hop_deref_protected(mpath);
 		if (mpath->flags & MESH_PATH_ACTIVE &&
 		    ether_addr_equal(ta, sta->sta.addr) &&
+		    !(mpath->flags & MESH_PATH_FIXED) &&
 		    (!(mpath->flags & MESH_PATH_SN_VALID) ||
 		    SN_GT(target_sn, mpath->sn)  || target_sn == 0)) {
 			mpath->flags &= ~MESH_PATH_ACTIVE;
@@ -1023,7 +1024,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
 		goto enddiscovery;
 
 	spin_lock_bh(&mpath->state_lock);
-	if (mpath->flags & MESH_PATH_DELETED) {
+	if (mpath->flags & (MESH_PATH_DELETED | MESH_PATH_FIXED)) {
 		spin_unlock_bh(&mpath->state_lock);
 		goto enddiscovery;
 	}
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 6db2ddf..8e3d2d1 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -826,7 +826,7 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop)
 	mpath->metric = 0;
 	mpath->hop_count = 0;
 	mpath->exp_time = 0;
-	mpath->flags |= MESH_PATH_FIXED;
+	mpath->flags = (MESH_PATH_FIXED | MESH_PATH_SN_VALID);
 	mesh_path_activate(mpath);
 	spin_unlock_bh(&mpath->state_lock);
 	mesh_path_tx_pending(mpath);
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH] ath10k: ensure pdev sta kickout threshold is set.
From: Ben Greear @ 2016-09-06 17:26 UTC (permalink / raw)
  To: Rajkumar Manoharan; +Cc: Manoharan, Rajkumar, ath10k, linux-wireless
In-Reply-To: <258eb1b46e360aeae1cddfa9185ab1ce@codeaurora.org>

On 09/06/2016 10:16 AM, Rajkumar Manoharan wrote:
> On 2016-09-06 18:42, Ben Greear wrote:
>> On 09/06/2016 12:39 AM, Manoharan, Rajkumar wrote:
>>> [...]
>>>
>>>> +int ath10k_mac_set_pdev_kickout(struct ath10k *ar)
>>>> +{
>>>> +       u32 param = ar->wmi.pdev_param->sta_kickout_th;
>>>> +       int rv;
>>>> +
>>>> +       rv = ath10k_wmi_pdev_set_param(ar, param,
>>>> +                                      ar->sta_xretry_kickout_thresh);
>>>> +       if (rv) {
>>>> +               ath10k_warn(ar, "failed to set sta kickout threshold to %d: %d\n",
>>>> +                           ar->sta_xretry_kickout_thresh, rv);
>>>> +       }
>>>> +       return rv;
>>>> +}
>>>>
>>> Ben,
>>>
>>> I plan to get rid of setting station kickout threshold from host. Each firmware revision (i.e qca988x, qca99x0, ipq4019)  follows different logic based on hw
>>> capability for station kickout and follows different default paramters. So configuring common threshold will affect firmware logic. Better to get rid of
>>> these configuration from host driver and let firmware to work with default parameters.
>>>
>>> Also I could not find out sta_xretry_kickout_thresh definition in upstream driver. Have you posted any changes for the same?
>>
>> Hmm, maybe that last bit is something I added in another patch.  Probably my
>> patch to enable firmware config on a per radio basis (fwcfg in my
>> tree).  Those patches are
>> larger and probably will never make it upstream.
>>
>> I need a way to configure this kickout, since firmware is kicking out
>> stations when it should
>> not.
>>
>
> Could you please explain the scenario?

A customer reported issues when having a bunch of android tablets connected to
a QCA9880 NIC running my 10.1 CT firmware in AP mode.

It is not clear exactly why the peers suddenly cannot ack packets,
but disabling the logic that kicks out stations due to low acks appears
to resolve the issue.

To turn the question around:  Is there any benefit to having the
firmware handle this keep-alive stuff?

I can see maybe it is useful in station only mode for power-saving reasons,
but not in AP mode.

>> Instead of removing the capability, you should instead make it configurable
>> through debugfs or something like my fwcfg patches, and/or disable the
>> kickout entirely.
>> Since mac80211 can deal with kicking out stations already, the stuff
>> in the firmware just makes
>> things less stable in poor RF environments and/or with stations with
>> flaky power-save and
>> off-channel roaming.
>>
> I plan to get rid of hardcoded value and fix this through proper netlink interface instead of debugfs. While ago, I posted a change for configuring low ack
> threshold. It is still pending in my TODO list.
>
> http://comments.gmane.org/gmane.linux.kernel.wireless.general/137645

That sounds nice.  I would hope that setting the value to 0 would
disable as much firmware keep-alive logic as possible.

Thanks,
Ben

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

^ permalink raw reply

* Re: [PATCH] ath10k:  ensure pdev sta kickout threshold is set.
From: Rajkumar Manoharan @ 2016-09-06 17:16 UTC (permalink / raw)
  To: Ben Greear; +Cc: Manoharan, Rajkumar, ath10k, linux-wireless
In-Reply-To: <57CEC0A4.8020808@candelatech.com>

On 2016-09-06 18:42, Ben Greear wrote:
> On 09/06/2016 12:39 AM, Manoharan, Rajkumar wrote:
>> [...]
>> 
>>> +int ath10k_mac_set_pdev_kickout(struct ath10k *ar)
>>> +{
>>> +       u32 param = ar->wmi.pdev_param->sta_kickout_th;
>>> +       int rv;
>>> +
>>> +       rv = ath10k_wmi_pdev_set_param(ar, param,
>>> +                                      
>>> ar->sta_xretry_kickout_thresh);
>>> +       if (rv) {
>>> +               ath10k_warn(ar, "failed to set sta kickout threshold 
>>> to %d: %d\n",
>>> +                           ar->sta_xretry_kickout_thresh, rv);
>>> +       }
>>> +       return rv;
>>> +}
>>> 
>> Ben,
>> 
>> I plan to get rid of setting station kickout threshold from host. Each 
>> firmware revision (i.e qca988x, qca99x0, ipq4019)  follows different 
>> logic based on hw capability for station kickout and follows different 
>> default paramters. So configuring common threshold will affect 
>> firmware logic. Better to get rid of these configuration from host 
>> driver and let firmware to work with default parameters.
>> 
>> Also I could not find out sta_xretry_kickout_thresh definition in 
>> upstream driver. Have you posted any changes for the same?
> 
> Hmm, maybe that last bit is something I added in another patch.  
> Probably my
> patch to enable firmware config on a per radio basis (fwcfg in my
> tree).  Those patches are
> larger and probably will never make it upstream.
> 
> I need a way to configure this kickout, since firmware is kicking out
> stations when it should
> not.
> 

Could you please explain the scenario?

> Instead of removing the capability, you should instead make it 
> configurable
> through debugfs or something like my fwcfg patches, and/or disable the
> kickout entirely.
> Since mac80211 can deal with kicking out stations already, the stuff
> in the firmware just makes
> things less stable in poor RF environments and/or with stations with
> flaky power-save and
> off-channel roaming.
> 
I plan to get rid of hardcoded value and fix this through proper netlink 
interface instead of debugfs. While ago, I posted a change for 
configuring low ack threshold. It is still pending in my TODO list.

http://comments.gmane.org/gmane.linux.kernel.wireless.general/137645

-Rajkumar

^ permalink raw reply

* [PATCH v3 1/6] staging: rtl8723au: remove unimplemented functions declaration
From: Luca Ceresoli @ 2016-09-06 16:36 UTC (permalink / raw)
  To: devel
  Cc: Luca Ceresoli, Larry Finger, Jes Sorensen, Greg Kroah-Hartman,
	linux-wireless, linux-kernel

These functions have been declared without any implementation since
the first commit (364e30ebd2dbaccba430c603da03e68746eb932a) and there
has been no mention of them in following commits.

Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Jes Sorensen <Jes.Sorensen@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-wireless@vger.kernel.org
Cc: devel@driverdev.osuosl.org
Cc: linux-kernel@vger.kernel.org

---

Changes v2 -> v3:
- add "staging: " prefix to commit message title.

Changes v1 -> v2:
- improve the commit message.
---
 drivers/staging/rtl8723au/include/recv_osdep.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/staging/rtl8723au/include/recv_osdep.h b/drivers/staging/rtl8723au/include/recv_osdep.h
index c2d3f1b..c159dbc 100644
--- a/drivers/staging/rtl8723au/include/recv_osdep.h
+++ b/drivers/staging/rtl8723au/include/recv_osdep.h
@@ -26,9 +26,6 @@ int rtw_recv_indicatepkt23a(struct rtw_adapter *adapter, struct recv_frame *prec
 
 void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup);
 
-int	rtw_init_recv_priv(struct recv_priv *precvpriv, struct rtw_adapter *padapter);
-void rtw_free_recv_priv (struct recv_priv *precvpriv);
-
 int rtw_os_recv_resource_init(struct recv_priv *precvpriv, struct rtw_adapter *padapter);
 
 void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl);
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH 0/5] Some cleanup patches for drivers/staging/rtl8723au/core/rtw_mlme.c
From: Jes Sorensen @ 2016-09-06 16:11 UTC (permalink / raw)
  To: Joe Perches
  Cc: Matthias Beyer, gregkh, Larry Finger, Manuel Messner,
	Geliang Tang, Cihangir Akturk, linux-wireless, devel,
	linux-kernel
In-Reply-To: <1473178128.8300.8.camel@perches.com>

Joe Perches <joe@perches.com> writes:
> On Tue, 2016-09-06 at 12:00 -0400, Jes Sorensen wrote:
>
>> Nothing wrong with these patches, however I intend to post a patch to
>> remove this driver soon, so it's kind of a waste of your time to spend
>> too many cycles on it.
>
> It might be useful to mark any drivers you're
> planning on removing as "Obsolete" in MAINTAINERS.
>
> checkpatch will then emit a "don't waste your time"
> message if anyone scans an obsolete driver/file.

I see, wasn't aware of that. I did add a printk to it for 4.6 notifying
users that the driver was going to go away.

Jes

^ permalink raw reply

* Re: [PATCH 0/5] Some cleanup patches for drivers/staging/rtl8723au/core/rtw_mlme.c
From: Joe Perches @ 2016-09-06 16:08 UTC (permalink / raw)
  To: Jes Sorensen, Matthias Beyer
  Cc: gregkh, Larry Finger, Manuel Messner, Geliang Tang,
	Cihangir Akturk, linux-wireless, devel, linux-kernel
In-Reply-To: <wrfjshtdyq56.fsf@redhat.com>

On Tue, 2016-09-06 at 12:00 -0400, Jes Sorensen wrote:

> Nothing wrong with these patches, however I intend to post a patch to
> remove this driver soon, so it's kind of a waste of your time to spend
> too many cycles on it.

It might be useful to mark any drivers you're
planning on removing as "Obsolete" in MAINTAINERS.

checkpatch will then emit a "don't waste your time"
message if anyone scans an obsolete driver/file.

^ permalink raw reply

* Re: [PATCH 0/5] Some cleanup patches for drivers/staging/rtl8723au/core/rtw_mlme.c
From: Jes Sorensen @ 2016-09-06 16:00 UTC (permalink / raw)
  To: Matthias Beyer
  Cc: gregkh, Larry Finger, Manuel Messner, Geliang Tang,
	Cihangir Akturk, linux-wireless, devel, linux-kernel
In-Reply-To: <20160904192626.17197-1-mail@beyermatthias.de>

Matthias Beyer <mail@beyermatthias.de> writes:
> This patchset fixes some errors and warnings reported by checkpatch.pl.
>
> Matthias Beyer (5):
>   drivers: staging: rtl8723au: core: Fix checkpatch.pl errors
>   drivers: staging: rtl8723au: core: simplify if-break-else
>   drivers: staging: rtl8723au: core: Refactor pointless branching
>   drivers: staging: rtl8723au: core: Fix "space prohibited" warning
>   drivers: staging: rtl8723au: core: Fix indentation
>
>  drivers/staging/rtl8723au/core/rtw_mlme.c | 72 ++++++++++++++-----------------
>  1 file changed, 33 insertions(+), 39 deletions(-)

Nothing wrong with these patches, however I intend to post a patch to
remove this driver soon, so it's kind of a waste of your time to spend
too many cycles on it.

Best regards,
Jes

^ permalink raw reply

* Re: Debugging RTL8192CU firmware loading on 3.12 powerpc
From: Larry Finger @ 2016-09-06 13:29 UTC (permalink / raw)
  To: Sven Eckelmann
  Cc: Simon Wunderlich, linux-wireless, Pannirselvam Kanagaratnam
In-Reply-To: <2186338.AojtHidiB8@bentobox>

On 09/06/2016 08:09 AM, Sven Eckelmann wrote:
> On Dienstag, 6. September 2016 09:40:41 CEST Sven Eckelmann wrote:
>> On Freitag, 2. September 2016 12:53:28 CEST Larry Finger wrote:
>> [...]
>>
>>> The patch I included in my previous E-mail, and attached here,  does get
>>> the firmware loaded correctly. There is still a problem that prevents
>>> authentication. I'm still looking for that issue.
>>
>> Thanks for the fast update. I am currently testing your patch. It looks like
>> the initial error is now gone. The hostapd also starts but beaconing
>> doesn't seem to work at all (no error from the kernel/hostapd but the
>> device is not sending anything). I am currently checking how beaconing is
>> supposed to work in your driver. Maybe I will spot something useful.
>
> Yes, found something similar in the checksumming algorithm. See the attached
> patch for details.

Just for the record, this is not "my" driver. It was provided by Realtek. My 
contribution has only been to clean it up.

Thanks for the patch. I too had found that checksum code, but I had not sent it 
as there are still problems on BE machines. These difficulties are running the 
NIC in STA mode. I have not tried AP mode. Scan data seem to be read OK, but it 
never authenticates. I do not know if there are further errors in setting up the 
transmit buffer, or if the problem is in the encryption/decryption code. I'm 
still looking.

Larry

^ permalink raw reply

* Re: [PATCH] ath10k:  ensure pdev sta kickout threshold is set.
From: Ben Greear @ 2016-09-06 13:12 UTC (permalink / raw)
  To: Manoharan, Rajkumar, ath10k@lists.infradead.org,
	Rajkumar Manoharan
  Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1473147582638.99419@qti.qualcomm.com>



On 09/06/2016 12:39 AM, Manoharan, Rajkumar wrote:
> [...]
>
>> +int ath10k_mac_set_pdev_kickout(struct ath10k *ar)
>> +{
>> +       u32 param = ar->wmi.pdev_param->sta_kickout_th;
>> +       int rv;
>> +
>> +       rv = ath10k_wmi_pdev_set_param(ar, param,
>> +                                      ar->sta_xretry_kickout_thresh);
>> +       if (rv) {
>> +               ath10k_warn(ar, "failed to set sta kickout threshold to %d: %d\n",
>> +                           ar->sta_xretry_kickout_thresh, rv);
>> +       }
>> +       return rv;
>> +}
>>
> Ben,
>
> I plan to get rid of setting station kickout threshold from host. Each firmware revision (i.e qca988x, qca99x0, ipq4019)  follows different logic based on hw capability for station kickout and follows different default paramters. So configuring common threshold will affect firmware logic. Better to get rid of these configuration from host driver and let firmware to work with default parameters.
>
> Also I could not find out sta_xretry_kickout_thresh definition in upstream driver. Have you posted any changes for the same?

Hmm, maybe that last bit is something I added in another patch.  Probably my
patch to enable firmware config on a per radio basis (fwcfg in my tree).  Those patches are
larger and probably will never make it upstream.

I need a way to configure this kickout, since firmware is kicking out stations when it should
not.

Instead of removing the capability, you should instead make it configurable
through debugfs or something like my fwcfg patches, and/or disable the kickout entirely.
Since mac80211 can deal with kicking out stations already, the stuff in the firmware just makes
things less stable in poor RF environments and/or with stations with flaky power-save and
off-channel roaming.

Thanks,
Ben


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

^ permalink raw reply

* Re: Debugging RTL8192CU firmware loading on 3.12 powerpc
From: Sven Eckelmann @ 2016-09-06 13:09 UTC (permalink / raw)
  To: Larry Finger; +Cc: Simon Wunderlich, linux-wireless, Pannirselvam Kanagaratnam
In-Reply-To: <2747159.ja51ucCDFk@bentobox>


[-- Attachment #1.1: Type: text/plain, Size: 839 bytes --]

On Dienstag, 6. September 2016 09:40:41 CEST Sven Eckelmann wrote:
> On Freitag, 2. September 2016 12:53:28 CEST Larry Finger wrote:
> [...]
> 
> > The patch I included in my previous E-mail, and attached here,  does get
> > the firmware loaded correctly. There is still a problem that prevents
> > authentication. I'm still looking for that issue.
> 
> Thanks for the fast update. I am currently testing your patch. It looks like
> the initial error is now gone. The hostapd also starts but beaconing
> doesn't seem to work at all (no error from the kernel/hostapd but the
> device is not sending anything). I am currently checking how beaconing is
> supposed to work in your driver. Maybe I will spot something useful.

Yes, found something similar in the checksumming algorithm. See the attached 
patch for details.

Kind regards,
	Sven

[-- Attachment #1.2: 0001-rtl8192c-Fix-byteorder-of-loaded-firmware.patch --]
[-- Type: text/x-patch, Size: 1622 bytes --]

From: Larry Finger <Larry.Finger@lwfinger.net>
Date: Mon, 5 Sep 2016 11:03:44 +0200
Subject: [PATCH] rtl8192c: Fix byteorder of loaded firmware

The firmware is read in as an array of bytes, thus it is effectively in
little-endian order. When it is written back to the device in routine
_rtl92c_fw_block_write(), the data output uses 32-bit writes. Of course,
all data supplied in all 2- and 4-byte writes is assumed to be in CPU
order. As the device needs the data to be little-endian, it will be byte
swapped on BE machines. As a result, the firmware is written out in the
wrong byte order
---
 drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
index 43fcb25..7c5fc85 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
@@ -74,16 +74,18 @@ static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 blocksize = sizeof(u32);
 	u8 *bufferptr = (u8 *)buffer;
-	u32 *pu4byteptr = (u32 *)buffer;
+	__le32 *pu4byteptr = (__le32 *)buffer;
 	u32 i, offset, blockcount, remainsize;
+	u32 data;
 
 	blockcount = size / blocksize;
 	remainsize = size % blocksize;
 
 	for (i = 0; i < blockcount; i++) {
 		offset = i * blocksize;
+		data = le32_to_cpu(*(pu4byteptr + i));
 		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
-				*(pu4byteptr + i));
+				data);
 	}
 
 	if (remainsize) {

[-- Attachment #1.3: 0002-Fix-TX-checksum-on-big-endian-systems.patch --]
[-- Type: text/x-patch, Size: 994 bytes --]

From: Sven Eckelmann <sven@narfation.org>
Date: Tue, 6 Sep 2016 15:00:27 +0200
Subject: [PATCH] Fix TX checksum on big endian systems
---
 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index 95880fe..6cb46ba 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -481,14 +481,14 @@ static void _rtl_fill_usb_tx_desc(u8 *txdesc)
  */
 static void _rtl_tx_desc_checksum(u8 *txdesc)
 {
-	u16 *ptr = (u16 *)txdesc;
+	__le16 *ptr = (__le16 *)txdesc;
 	u16	checksum = 0;
 	u32 index;
 
 	/* Clear first */
 	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0);
 	for (index = 0; index < 16; index++)
-		checksum = checksum ^ (*(ptr + index));
+		checksum = checksum ^ le16_to_cpu(*(ptr + index));
 	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum);
 }
 

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply related

* [PATCH 2/3] ath10k: use devm_reset_control_get() instead of reset_control_get()
From: Masahiro Yamada @ 2016-09-06 12:39 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Luis R. Rodriguez, Masahiro Yamada, Kalle Valo,
	netdev, linux-kernel, ath10k
In-Reply-To: <1473165598-28683-1-git-send-email-yamada.masahiro@socionext.com>

Use the managed variant of reset_control_get() to simplify the
failure path and the .remove callback.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/net/wireless/ath/ath10k/ahb.c | 56 +++++++----------------------------
 1 file changed, 10 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index 8a55c0c..6b355ee 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -191,92 +191,56 @@ static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar)
 {
 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
 	struct device *dev;
-	int ret;
 
 	dev = &ar_ahb->pdev->dev;
 
-	ar_ahb->core_cold_rst = reset_control_get(dev, "wifi_core_cold");
+	ar_ahb->core_cold_rst = devm_reset_control_get(dev, "wifi_core_cold");
 	if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) {
 		ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->core_cold_rst));
-		ret = ar_ahb->core_cold_rst ?
+		return ar_ahb->core_cold_rst ?
 			PTR_ERR(ar_ahb->core_cold_rst) : -ENODEV;
-		goto out;
 	}
 
-	ar_ahb->radio_cold_rst = reset_control_get(dev, "wifi_radio_cold");
+	ar_ahb->radio_cold_rst = devm_reset_control_get(dev, "wifi_radio_cold");
 	if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) {
 		ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->radio_cold_rst));
-		ret = ar_ahb->radio_cold_rst ?
+		return ar_ahb->radio_cold_rst ?
 			PTR_ERR(ar_ahb->radio_cold_rst) : -ENODEV;
-		goto err_core_cold_rst_put;
 	}
 
-	ar_ahb->radio_warm_rst = reset_control_get(dev, "wifi_radio_warm");
+	ar_ahb->radio_warm_rst = devm_reset_control_get(dev, "wifi_radio_warm");
 	if (IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) {
 		ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->radio_warm_rst));
-		ret = ar_ahb->radio_warm_rst ?
+		return ar_ahb->radio_warm_rst ?
 			PTR_ERR(ar_ahb->radio_warm_rst) : -ENODEV;
-		goto err_radio_cold_rst_put;
 	}
 
-	ar_ahb->radio_srif_rst = reset_control_get(dev, "wifi_radio_srif");
+	ar_ahb->radio_srif_rst = devm_reset_control_get(dev, "wifi_radio_srif");
 	if (IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) {
 		ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->radio_srif_rst));
-		ret = ar_ahb->radio_srif_rst ?
+		return ar_ahb->radio_srif_rst ?
 			PTR_ERR(ar_ahb->radio_srif_rst) : -ENODEV;
-		goto err_radio_warm_rst_put;
 	}
 
-	ar_ahb->cpu_init_rst = reset_control_get(dev, "wifi_cpu_init");
+	ar_ahb->cpu_init_rst = devm_reset_control_get(dev, "wifi_cpu_init");
 	if (IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {
 		ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->cpu_init_rst));
-		ret = ar_ahb->cpu_init_rst ?
+		return ar_ahb->cpu_init_rst ?
 			PTR_ERR(ar_ahb->cpu_init_rst) : -ENODEV;
-		goto err_radio_srif_rst_put;
 	}
 
 	return 0;
-
-err_radio_srif_rst_put:
-	reset_control_put(ar_ahb->radio_srif_rst);
-
-err_radio_warm_rst_put:
-	reset_control_put(ar_ahb->radio_warm_rst);
-
-err_radio_cold_rst_put:
-	reset_control_put(ar_ahb->radio_cold_rst);
-
-err_core_cold_rst_put:
-	reset_control_put(ar_ahb->core_cold_rst);
-
-out:
-	return ret;
 }
 
 static void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar)
 {
 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
 
-	if (!IS_ERR_OR_NULL(ar_ahb->core_cold_rst))
-		reset_control_put(ar_ahb->core_cold_rst);
-
-	if (!IS_ERR_OR_NULL(ar_ahb->radio_cold_rst))
-		reset_control_put(ar_ahb->radio_cold_rst);
-
-	if (!IS_ERR_OR_NULL(ar_ahb->radio_warm_rst))
-		reset_control_put(ar_ahb->radio_warm_rst);
-
-	if (!IS_ERR_OR_NULL(ar_ahb->radio_srif_rst))
-		reset_control_put(ar_ahb->radio_srif_rst);
-
-	if (!IS_ERR_OR_NULL(ar_ahb->cpu_init_rst))
-		reset_control_put(ar_ahb->cpu_init_rst);
-
 	ar_ahb->core_cold_rst = NULL;
 	ar_ahb->radio_cold_rst = NULL;
 	ar_ahb->radio_warm_rst = NULL;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 3/3] ath10k: do not check if reset is NULL
From: Masahiro Yamada @ 2016-09-06 12:39 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Luis R. Rodriguez, Masahiro Yamada, Kalle Valo,
	netdev, linux-kernel, ath10k
In-Reply-To: <1473165598-28683-1-git-send-email-yamada.masahiro@socionext.com>

Since reset_control_get() never returns NULL, we can use IS_ERR()
instead of IS_ERR_OR_NULL().  The return statements can be simpler
as well.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/net/wireless/ath/ath10k/ahb.c | 25 ++++++++++---------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index 6b355ee..b29dc4d 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -195,43 +195,38 @@ static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar)
 	dev = &ar_ahb->pdev->dev;
 
 	ar_ahb->core_cold_rst = devm_reset_control_get(dev, "wifi_core_cold");
-	if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) {
+	if (IS_ERR(ar_ahb->core_cold_rst)) {
 		ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->core_cold_rst));
-		return ar_ahb->core_cold_rst ?
-			PTR_ERR(ar_ahb->core_cold_rst) : -ENODEV;
+		return PTR_ERR(ar_ahb->core_cold_rst);
 	}
 
 	ar_ahb->radio_cold_rst = devm_reset_control_get(dev, "wifi_radio_cold");
-	if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) {
+	if (IS_ERR(ar_ahb->radio_cold_rst)) {
 		ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->radio_cold_rst));
-		return ar_ahb->radio_cold_rst ?
-			PTR_ERR(ar_ahb->radio_cold_rst) : -ENODEV;
+		return PTR_ERR(ar_ahb->radio_cold_rst);
 	}
 
 	ar_ahb->radio_warm_rst = devm_reset_control_get(dev, "wifi_radio_warm");
-	if (IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) {
+	if (IS_ERR(ar_ahb->radio_warm_rst)) {
 		ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->radio_warm_rst));
-		return ar_ahb->radio_warm_rst ?
-			PTR_ERR(ar_ahb->radio_warm_rst) : -ENODEV;
+		return PTR_ERR(ar_ahb->radio_warm_rst);
 	}
 
 	ar_ahb->radio_srif_rst = devm_reset_control_get(dev, "wifi_radio_srif");
-	if (IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) {
+	if (IS_ERR(ar_ahb->radio_srif_rst)) {
 		ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->radio_srif_rst));
-		return ar_ahb->radio_srif_rst ?
-			PTR_ERR(ar_ahb->radio_srif_rst) : -ENODEV;
+		return PTR_ERR(ar_ahb->radio_srif_rst);
 	}
 
 	ar_ahb->cpu_init_rst = devm_reset_control_get(dev, "wifi_cpu_init");
-	if (IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {
+	if (IS_ERR(ar_ahb->cpu_init_rst)) {
 		ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n",
 			   PTR_ERR(ar_ahb->cpu_init_rst));
-		return ar_ahb->cpu_init_rst ?
-			PTR_ERR(ar_ahb->cpu_init_rst) : -ENODEV;
+		return PTR_ERR(ar_ahb->cpu_init_rst);
 	}
 
 	return 0;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/3] ath10k: use devm_clk_get() instead of clk_get()
From: Masahiro Yamada @ 2016-09-06 12:39 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Luis R. Rodriguez, Masahiro Yamada, Kalle Valo,
	netdev, linux-kernel, ath10k
In-Reply-To: <1473165598-28683-1-git-send-email-yamada.masahiro@socionext.com>

Use the managed variant of clk_get() to simplify the failure path
and the .remove callback.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/net/wireless/ath/ath10k/ahb.c | 34 ++++++----------------------------
 1 file changed, 6 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index acec16b..8a55c0c 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -91,59 +91,37 @@ static int ath10k_ahb_clock_init(struct ath10k *ar)
 {
 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
 	struct device *dev;
-	int ret;
 
 	dev = &ar_ahb->pdev->dev;
 
-	ar_ahb->cmd_clk = clk_get(dev, "wifi_wcss_cmd");
+	ar_ahb->cmd_clk = devm_clk_get(dev, "wifi_wcss_cmd");
 	if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) {
 		ath10k_err(ar, "failed to get cmd clk: %ld\n",
 			   PTR_ERR(ar_ahb->cmd_clk));
-		ret = ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV;
-		goto out;
+		return ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV;
 	}
 
-	ar_ahb->ref_clk = clk_get(dev, "wifi_wcss_ref");
+	ar_ahb->ref_clk = devm_clk_get(dev, "wifi_wcss_ref");
 	if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) {
 		ath10k_err(ar, "failed to get ref clk: %ld\n",
 			   PTR_ERR(ar_ahb->ref_clk));
-		ret = ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV;
-		goto err_cmd_clk_put;
+		return ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV;
 	}
 
-	ar_ahb->rtc_clk = clk_get(dev, "wifi_wcss_rtc");
+	ar_ahb->rtc_clk = devm_clk_get(dev, "wifi_wcss_rtc");
 	if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
 		ath10k_err(ar, "failed to get rtc clk: %ld\n",
 			   PTR_ERR(ar_ahb->rtc_clk));
-		ret = ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV;
-		goto err_ref_clk_put;
+		return ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV;
 	}
 
 	return 0;
-
-err_ref_clk_put:
-	clk_put(ar_ahb->ref_clk);
-
-err_cmd_clk_put:
-	clk_put(ar_ahb->cmd_clk);
-
-out:
-	return ret;
 }
 
 static void ath10k_ahb_clock_deinit(struct ath10k *ar)
 {
 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
 
-	if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk))
-		clk_put(ar_ahb->cmd_clk);
-
-	if (!IS_ERR_OR_NULL(ar_ahb->ref_clk))
-		clk_put(ar_ahb->ref_clk);
-
-	if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk))
-		clk_put(ar_ahb->rtc_clk);
-
 	ar_ahb->cmd_clk = NULL;
 	ar_ahb->ref_clk = NULL;
 	ar_ahb->rtc_clk = NULL;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 0/3] ath10k: a little bit clean-up of ATH10K driver
From: Masahiro Yamada @ 2016-09-06 12:39 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Luis R. Rodriguez, Masahiro Yamada, Kalle Valo,
	netdev, linux-kernel, ath10k


Clean-up code with devm_clk_get() and devm_reset_control_get().

I know devm_reset_control_get() should be replaced with
either devm_reset_control_get_exclusive() or
devm_reset_control_get_shared().

My best guess is devm_reset_control_get_shared() for this case,
but I am not 100% sure, so I am leaving it to other developers.



Masahiro Yamada (3):
  ath10k: use devm_clk_get() instead of clk_get()
  ath10k: use devm_reset_control_get() instead of reset_control_get()
  ath10k: do not check if reset is NULL

 drivers/net/wireless/ath/ath10k/ahb.c | 105 +++++++---------------------------
 1 file changed, 21 insertions(+), 84 deletions(-)

-- 
1.9.1

^ permalink raw reply

* Re: mwifiex: propagate error if IRQ request fails in mwifiex_sdio_of()
From: Javier Martinez Canillas @ 2016-09-06 12:12 UTC (permalink / raw)
  To: Kalle Valo
  Cc: linux-kernel, Amitkumar Karwar, netdev, linux-wireless,
	Nishant Sarmukadam, Arend van Spriel
In-Reply-To: <20160903103520.8C69C6201B@smtp.codeaurora.org>

Hello Kalle,

On 09/03/2016 12:35 PM, Kalle Valo wrote:
> Javier Martinez Canillas <javier@osg.samsung.com> wrote:
>> If request_irq() fails in mwifiex_sdio_probe_of(), only an error message
>> is printed but the actual error is not propagated to the caller function.
>>
>> Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
> 
> What's the conclusion with this patch? Should I drop it or take it?
> 
> (The discussion is available from the patchwork link in the signature.)
> 

My understanding is that Arend agrees with the patch and that the question
raised was caused by looking at an older kernel version. IOW, the patch is
OK and should be picked.

I'm adding Arend to cc, so can comment in case I misunderstood him though.

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America

^ permalink raw reply

* Re: [PATCH v7] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-09-06 11:45 UTC (permalink / raw)
  To: make-wifi-fast; +Cc: linux-wireless
In-Reply-To: <20160906114311.24522-1-toke@toke.dk>

Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk> writes:

> The TXQ intermediate queues can cause packet reordering when more than
> one flow is active to a single station. Since some of the wifi-specific
> packet handling (notably sequence number and encryption handling) is
> sensitive to re-ordering, things break if they are applied before the
> TXQ.
>
> This splits up the TX handlers and fast_xmit logic into two parts: An
> early part and a late part. The former is applied before TXQ enqueue,
> and the latter after dequeue. The non-TXQ path just applies both parts
> at once.
>
> Because fragments shouldn't be split up or reordered, the fragmentation
> handler is run after dequeue. Any fragments are then kept in the TXQ and
> on subsequent dequeues they take precedence over dequeueing from the FQ
> structure.
>
> This approach avoids having to scatter special cases for when TXQ is
> enabled, at the cost of making the fast_xmit and TX handler code
> slightly more complex.
>
> Signed-off-by: Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk>

Sorry for sending this again; meant to send v8. :/

-Toke

^ permalink raw reply

* [PATCH v8] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-09-06 11:44 UTC (permalink / raw)
  To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen
In-Reply-To: <20160905113042.22271-1-toke@toke.dk>

The TXQ intermediate queues can cause packet reordering when more than
one flow is active to a single station. Since some of the wifi-specific
packet handling (notably sequence number and encryption handling) is
sensitive to re-ordering, things break if they are applied before the
TXQ.

This splits up the TX handlers and fast_xmit logic into two parts: An
early part and a late part. The former is applied before TXQ enqueue,
and the latter after dequeue. The non-TXQ path just applies both parts
at once.

Because fragments shouldn't be split up or reordered, the fragmentation
handler is run after dequeue. Any fragments are then kept in the TXQ and
on subsequent dequeues they take precedence over dequeueing from the FQ
structure.

This approach avoids having to scatter special cases for when TXQ is
enabled, at the cost of making the fast_xmit and TX handler code
slightly more complex.

Signed-off-by: Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk>
---
Changes since v8:
- Don't rely on the fast_tx pointer on TXQ dequeue; it can go away while
  the packet was queued, and we don't actually need it, since we can get
  the key configuration and offset from the packet info.

 include/net/mac80211.h     |   2 +
 net/mac80211/ieee80211_i.h |   2 +
 net/mac80211/tx.c          | 255 +++++++++++++++++++++++++++++++++------=
------
 3 files changed, 195 insertions(+), 64 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cca510a..9a6a3e9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -715,6 +715,7 @@ enum mac80211_tx_info_flags {
  *	frame (PS-Poll or uAPSD).
  * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate info=
rmation
  * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
+ * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xm=
it path
  *
  * These flags are used in tx_info->control.flags.
  */
@@ -723,6 +724,7 @@ enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTRL_PS_RESPONSE		=3D BIT(1),
 	IEEE80211_TX_CTRL_RATE_INJECT		=3D BIT(2),
 	IEEE80211_TX_CTRL_AMSDU			=3D BIT(3),
+	IEEE80211_TX_CTRL_FAST_XMIT		=3D BIT(4),
 };
=20
 /*
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9211cce..d36f3b1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -813,11 +813,13 @@ enum txq_info_flags {
  * @def_flow: used as a fallback flow when a packet destined to @tin has=
hes to
  *	a fq_flow which is already owned by a different tin
  * @def_cvars: codel vars for @def_flow
+ * @frags: used to keep fragments created after dequeue
  */
 struct txq_info {
 	struct fq_tin tin;
 	struct fq_flow def_flow;
 	struct codel_vars def_cvars;
+	struct sk_buff_head frags;
 	unsigned long flags;
=20
 	/* keep last! */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index efc38e7..f8eec60 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -38,6 +38,12 @@
 #include "wme.h"
 #include "rate.h"
=20
+static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx);
+static bool ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sda=
ta,
+				       struct sta_info *sta, u8 pn_offs,
+				       struct ieee80211_key_conf *key_conf,
+				       struct sk_buff *skb);
+
 /* misc utils */
=20
 static inline void ieee80211_tx_stats(struct net_device *dev, u32 len)
@@ -853,8 +859,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
 	tid =3D *qc & IEEE80211_QOS_CTL_TID_MASK;
 	tx->sta->tx_stats.msdu[tid]++;
=20
-	if (!tx->sta->sta.txq[0])
-		hdr->seq_ctrl =3D ieee80211_tx_next_seq(tx->sta, tid);
+	hdr->seq_ctrl =3D ieee80211_tx_next_seq(tx->sta, tid);
=20
 	return TX_CONTINUE;
 }
@@ -1403,6 +1408,7 @@ void ieee80211_txq_init(struct ieee80211_sub_if_dat=
a *sdata,
 	fq_tin_init(&txqi->tin);
 	fq_flow_init(&txqi->def_flow);
 	codel_vars_init(&txqi->def_cvars);
+	__skb_queue_head_init(&txqi->frags);
=20
 	txqi->txq.vif =3D &sdata->vif;
=20
@@ -1425,6 +1431,7 @@ void ieee80211_txq_purge(struct ieee80211_local *lo=
cal,
 	struct fq_tin *tin =3D &txqi->tin;
=20
 	fq_tin_reset(fq, tin, fq_skb_free_func);
+	ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
 }
=20
 int ieee80211_txq_setup_flows(struct ieee80211_local *local)
@@ -1485,12 +1492,19 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee8=
0211_hw *hw,
 	struct sk_buff *skb =3D NULL;
 	struct fq *fq =3D &local->fq;
 	struct fq_tin *tin =3D &txqi->tin;
+	struct ieee80211_tx_info *info;
=20
 	spin_lock_bh(&fq->lock);
=20
 	if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags))
 		goto out;
=20
+	/* Make sure fragments stay together. */
+	skb =3D __skb_dequeue(&txqi->frags);
+	if (skb)
+		goto out;
+
+begin:
 	skb =3D fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
 	if (!skb)
 		goto out;
@@ -1498,16 +1512,37 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee8=
0211_hw *hw,
 	ieee80211_set_skb_vif(skb, txqi);
=20
 	hdr =3D (struct ieee80211_hdr *)skb->data;
-	if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) {
+	info =3D IEEE80211_SKB_CB(skb);
+	if (txq->sta && info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
 		struct sta_info *sta =3D container_of(txq->sta, struct sta_info,
 						    sta);
-		struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+		u8 pn_offs =3D 0;
=20
-		hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, txq->tid);
-		if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
-			info->flags |=3D IEEE80211_TX_CTL_AMPDU;
-		else
-			info->flags &=3D ~IEEE80211_TX_CTL_AMPDU;
+		if (info->control.hw_key)
+			pn_offs =3D ieee80211_hdrlen(hdr->frame_control);
+
+		ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs,
+					   info->control.hw_key, skb);
+	} else {
+		struct ieee80211_tx_data tx =3D { };
+
+		__skb_queue_head_init(&tx.skbs);
+		tx.local =3D local;
+		tx.skb =3D skb;
+		if (txq->sta) {
+			tx.sta =3D container_of(txq->sta, struct sta_info, sta);
+			tx.sdata =3D tx.sta->sdata;
+		} else {
+			tx.sdata =3D vif_to_sdata(info->control.vif);
+		}
+
+		if (invoke_tx_handlers_late(&tx))
+			goto begin;
+
+		skb =3D __skb_dequeue(&tx.skbs);
+
+		if (!skb_queue_empty(&tx.skbs))
+			skb_queue_splice_tail(&tx.skbs, &txqi->frags);
 	}
=20
 out:
@@ -1521,6 +1556,47 @@ out:
 }
 EXPORT_SYMBOL(ieee80211_tx_dequeue);
=20
+static bool ieee80211_queue_skb(struct ieee80211_local *local,
+				struct ieee80211_sub_if_data *sdata,
+				struct sta_info *sta,
+				struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+	struct fq *fq =3D &local->fq;
+	struct ieee80211_vif *vif;
+	struct txq_info *txqi;
+	struct ieee80211_sta *pubsta;
+
+	if (!local->ops->wake_tx_queue ||
+	    sdata->vif.type =3D=3D NL80211_IFTYPE_MONITOR)
+		return false;
+
+	if (sta && sta->uploaded)
+		pubsta =3D &sta->sta;
+	else
+		pubsta =3D NULL;
+
+	if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
+		sdata =3D container_of(sdata->bss,
+				     struct ieee80211_sub_if_data, u.ap);
+
+	vif =3D &sdata->vif;
+	txqi =3D ieee80211_get_txq(local, vif, pubsta, skb);
+
+	if (!txqi)
+		return false;
+
+	info->control.vif =3D vif;
+
+	spin_lock_bh(&fq->lock);
+	ieee80211_txq_enqueue(local, txqi, skb);
+	spin_unlock_bh(&fq->lock);
+
+	drv_wake_tx_queue(local, txqi);
+
+	return true;
+}
+
 static bool ieee80211_tx_frags(struct ieee80211_local *local,
 			       struct ieee80211_vif *vif,
 			       struct ieee80211_sta *sta,
@@ -1528,9 +1604,7 @@ static bool ieee80211_tx_frags(struct ieee80211_loc=
al *local,
 			       bool txpending)
 {
 	struct ieee80211_tx_control control =3D {};
-	struct fq *fq =3D &local->fq;
 	struct sk_buff *skb, *tmp;
-	struct txq_info *txqi;
 	unsigned long flags;
=20
 	skb_queue_walk_safe(skbs, skb, tmp) {
@@ -1545,21 +1619,6 @@ static bool ieee80211_tx_frags(struct ieee80211_lo=
cal *local,
 		}
 #endif
=20
-		txqi =3D ieee80211_get_txq(local, vif, sta, skb);
-		if (txqi) {
-			info->control.vif =3D vif;
-
-			__skb_unlink(skb, skbs);
-
-			spin_lock_bh(&fq->lock);
-			ieee80211_txq_enqueue(local, txqi, skb);
-			spin_unlock_bh(&fq->lock);
-
-			drv_wake_tx_queue(local, txqi);
-
-			continue;
-		}
-
 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 		if (local->queue_stop_reasons[q] ||
 		    (!txpending && !skb_queue_empty(&local->pending[q]))) {
@@ -1680,10 +1739,13 @@ static bool __ieee80211_tx(struct ieee80211_local=
 *local,
 /*
  * Invoke TX handlers, return 0 on success and non-zero if the
  * frame was dropped or queued.
+ *
+ * The handlers are split into an early and late part. The latter is eve=
rything
+ * that can be sensitive to reordering, and will be deferred to after pa=
ckets
+ * are dequeued from the intermediate queues (when they are enabled).
  */
-static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
+static int invoke_tx_handlers_early(struct ieee80211_tx_data *tx)
 {
-	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(tx->skb);
 	ieee80211_tx_result res =3D TX_DROP;
=20
 #define CALL_TXH(txh) \
@@ -1697,16 +1759,42 @@ static int invoke_tx_handlers(struct ieee80211_tx=
_data *tx)
 	CALL_TXH(ieee80211_tx_h_check_assoc);
 	CALL_TXH(ieee80211_tx_h_ps_buf);
 	CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
-	CALL_TXH(ieee80211_tx_h_select_key);
+
 	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
 		CALL_TXH(ieee80211_tx_h_rate_ctrl);
=20
+ txh_done:
+	if (unlikely(res =3D=3D TX_DROP)) {
+		I802_DEBUG_INC(tx->local->tx_handlers_drop);
+		if (tx->skb)
+			ieee80211_free_txskb(&tx->local->hw, tx->skb);
+		else
+			ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
+		return -1;
+	} else if (unlikely(res =3D=3D TX_QUEUED)) {
+		I802_DEBUG_INC(tx->local->tx_handlers_queued);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Late handlers can be called while the sta lock is held. Handlers that=
 can
+ * cause packets to be generated will cause deadlock!
+ */
+static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
+{
+	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(tx->skb);
+	ieee80211_tx_result res =3D TX_CONTINUE;
+
 	if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
 		__skb_queue_tail(&tx->skbs, tx->skb);
 		tx->skb =3D NULL;
 		goto txh_done;
 	}
=20
+	CALL_TXH(ieee80211_tx_h_select_key);
 	CALL_TXH(ieee80211_tx_h_michael_mic_add);
 	CALL_TXH(ieee80211_tx_h_sequence);
 	CALL_TXH(ieee80211_tx_h_fragment);
@@ -1733,6 +1821,15 @@ static int invoke_tx_handlers(struct ieee80211_tx_=
data *tx)
 	return 0;
 }
=20
+static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
+{
+	int r =3D invoke_tx_handlers_early(tx);
+
+	if (r)
+		return r;
+	return invoke_tx_handlers_late(tx);
+}
+
 bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif, struct sk_buff *skb,
 			      int band, struct ieee80211_sta **sta)
@@ -1807,7 +1904,13 @@ static bool ieee80211_tx(struct ieee80211_sub_if_d=
ata *sdata,
 		info->hw_queue =3D
 			sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
=20
-	if (!invoke_tx_handlers(&tx))
+	if (invoke_tx_handlers_early(&tx))
+		return false;
+
+	if (ieee80211_queue_skb(local, sdata, tx.sta, tx.skb))
+		return true;
+
+	if (!invoke_tx_handlers_late(&tx))
 		result =3D __ieee80211_tx(local, &tx.skbs, led_len,
 					tx.sta, txpending);
=20
@@ -3159,7 +3262,7 @@ out:
 }
=20
 static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
-				struct net_device *dev, struct sta_info *sta,
+				struct sta_info *sta,
 				struct ieee80211_fast_tx *fast_tx,
 				struct sk_buff *skb)
 {
@@ -3170,9 +3273,9 @@ static bool ieee80211_xmit_fast(struct ieee80211_su=
b_if_data *sdata,
 	struct ethhdr eth;
 	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr =3D (void *)fast_tx->hdr;
-	struct ieee80211_tx_data tx;
-	ieee80211_tx_result r;
 	struct tid_ampdu_tx *tid_tx =3D NULL;
+	ieee80211_tx_result r;
+	struct ieee80211_tx_data tx;
 	u8 tid =3D IEEE80211_NUM_TIDS;
=20
 	/* control port protocol needs a lot of special handling */
@@ -3210,8 +3313,6 @@ static bool ieee80211_xmit_fast(struct ieee80211_su=
b_if_data *sdata,
 			return true;
 	}
=20
-	ieee80211_tx_stats(dev, skb->len + extra_head);
-
 	if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
 	    ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb))
 		return true;
@@ -3240,24 +3341,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_s=
ub_if_data *sdata,
 	info->flags =3D IEEE80211_TX_CTL_FIRST_FRAGMENT |
 		      IEEE80211_TX_CTL_DONTFRAG |
 		      (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
-
-	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
-		*ieee80211_get_qos_ctl(hdr) =3D tid;
-		if (!sta->sta.txq[0])
-			hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, tid);
-	} else {
-		info->flags |=3D IEEE80211_TX_CTL_ASSIGN_SEQ;
-		hdr->seq_ctrl =3D cpu_to_le16(sdata->sequence_number);
-		sdata->sequence_number +=3D 0x10;
-	}
-
-	if (skb_shinfo(skb)->gso_size)
-		sta->tx_stats.msdu[tid] +=3D
-			DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size);
-	else
-		sta->tx_stats.msdu[tid]++;
-
-	info->hw_queue =3D sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
+	info->control.flags =3D IEEE80211_TX_CTRL_FAST_XMIT;
=20
 	__skb_queue_head_init(&tx.skbs);
=20
@@ -3283,22 +3367,71 @@ static bool ieee80211_xmit_fast(struct ieee80211_=
sub_if_data *sdata,
 		}
 	}
=20
+	if (ieee80211_queue_skb(local, sdata, sta, skb))
+		return true;
+
+	ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs,
+				   &fast_tx->key->conf, skb);
+
+	if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
+		sdata =3D container_of(sdata->bss,
+				     struct ieee80211_sub_if_data, u.ap);
+
+	__skb_queue_tail(&tx.skbs, skb);
+	ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
+
+	return true;
+}
+
+/*
+ * Can be called while the sta lock is held. Anything that can cause pac=
kets to
+ * be generated will cause deadlock!
+ */
+static bool ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sda=
ta,
+				       struct sta_info *sta, u8 pn_offs,
+				       struct ieee80211_key_conf *key_conf,
+				       struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr =3D (void *)skb->data;
+	u8 tid =3D IEEE80211_NUM_TIDS;
+
+	ieee80211_tx_stats(skb->dev, skb->len);
+
+	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
+		tid =3D skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+		*ieee80211_get_qos_ctl(hdr) =3D tid;
+		hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, tid);
+	} else {
+		info->flags |=3D IEEE80211_TX_CTL_ASSIGN_SEQ;
+		hdr->seq_ctrl =3D cpu_to_le16(sdata->sequence_number);
+		sdata->sequence_number +=3D 0x10;
+	}
+
+	if (skb_shinfo(skb)->gso_size)
+		sta->tx_stats.msdu[tid] +=3D
+			DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size);
+	else
+		sta->tx_stats.msdu[tid]++;
+
+	info->hw_queue =3D sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
+
 	/* statistics normally done by ieee80211_tx_h_stats (but that
 	 * has to consider fragmentation, so is more complex)
 	 */
 	sta->tx_stats.bytes[skb_get_queue_mapping(skb)] +=3D skb->len;
 	sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
=20
-	if (fast_tx->pn_offs) {
+	if (pn_offs) {
 		u64 pn;
-		u8 *crypto_hdr =3D skb->data + fast_tx->pn_offs;
+		u8 *crypto_hdr =3D skb->data + pn_offs;
=20
-		switch (fast_tx->key->conf.cipher) {
+		switch (key_conf->cipher) {
 		case WLAN_CIPHER_SUITE_CCMP:
 		case WLAN_CIPHER_SUITE_CCMP_256:
 		case WLAN_CIPHER_SUITE_GCMP:
 		case WLAN_CIPHER_SUITE_GCMP_256:
-			pn =3D atomic64_inc_return(&fast_tx->key->conf.tx_pn);
+			pn =3D atomic64_inc_return(&key_conf->tx_pn);
 			crypto_hdr[0] =3D pn;
 			crypto_hdr[1] =3D pn >> 8;
 			crypto_hdr[4] =3D pn >> 16;
@@ -3309,12 +3442,6 @@ static bool ieee80211_xmit_fast(struct ieee80211_s=
ub_if_data *sdata,
 		}
 	}
=20
-	if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
-		sdata =3D container_of(sdata->bss,
-				     struct ieee80211_sub_if_data, u.ap);
-
-	__skb_queue_tail(&tx.skbs, skb);
-	ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
 	return true;
 }
=20
@@ -3342,7 +3469,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *s=
kb,
 		fast_tx =3D rcu_dereference(sta->fast_tx);
=20
 		if (fast_tx &&
-		    ieee80211_xmit_fast(sdata, dev, sta, fast_tx, skb))
+		    ieee80211_xmit_fast(sdata, sta, fast_tx, skb))
 			goto out;
 	}
=20
--=20
2.9.3

^ permalink raw reply related

* [PATCH v7] mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue.
From: Toke Høiland-Jørgensen @ 2016-09-06 11:43 UTC (permalink / raw)
  To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen
In-Reply-To: <20160905113042.22271-1-toke@toke.dk>

The TXQ intermediate queues can cause packet reordering when more than
one flow is active to a single station. Since some of the wifi-specific
packet handling (notably sequence number and encryption handling) is
sensitive to re-ordering, things break if they are applied before the
TXQ.

This splits up the TX handlers and fast_xmit logic into two parts: An
early part and a late part. The former is applied before TXQ enqueue,
and the latter after dequeue. The non-TXQ path just applies both parts
at once.

Because fragments shouldn't be split up or reordered, the fragmentation
handler is run after dequeue. Any fragments are then kept in the TXQ and
on subsequent dequeues they take precedence over dequeueing from the FQ
structure.

This approach avoids having to scatter special cases for when TXQ is
enabled, at the cost of making the fast_xmit and TX handler code
slightly more complex.

Signed-off-by: Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk>
---
Changes since v6:
  - Invoking the rate control handler can cause packets to be generated
    (for establishing a BA session). This can cause a deadlock because
    dequeue can happen while sta->lock is held. So this version moves
    the rate control handler back before the intermediate queue step.
  - Fix sequence number allocation on the slow path.
 =20
 include/net/mac80211.h     |   2 +
 net/mac80211/ieee80211_i.h |   2 +
 net/mac80211/tx.c          | 250 ++++++++++++++++++++++++++++++++++-----=
------
 3 files changed, 192 insertions(+), 62 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cca510a..9a6a3e9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -715,6 +715,7 @@ enum mac80211_tx_info_flags {
  *	frame (PS-Poll or uAPSD).
  * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate info=
rmation
  * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
+ * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xm=
it path
  *
  * These flags are used in tx_info->control.flags.
  */
@@ -723,6 +724,7 @@ enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTRL_PS_RESPONSE		=3D BIT(1),
 	IEEE80211_TX_CTRL_RATE_INJECT		=3D BIT(2),
 	IEEE80211_TX_CTRL_AMSDU			=3D BIT(3),
+	IEEE80211_TX_CTRL_FAST_XMIT		=3D BIT(4),
 };
=20
 /*
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9211cce..d36f3b1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -813,11 +813,13 @@ enum txq_info_flags {
  * @def_flow: used as a fallback flow when a packet destined to @tin has=
hes to
  *	a fq_flow which is already owned by a different tin
  * @def_cvars: codel vars for @def_flow
+ * @frags: used to keep fragments created after dequeue
  */
 struct txq_info {
 	struct fq_tin tin;
 	struct fq_flow def_flow;
 	struct codel_vars def_cvars;
+	struct sk_buff_head frags;
 	unsigned long flags;
=20
 	/* keep last! */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index efc38e7..94f38cc 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -38,6 +38,12 @@
 #include "wme.h"
 #include "rate.h"
=20
+static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx);
+static bool ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sda=
ta,
+				       struct sta_info *sta,
+				       struct ieee80211_fast_tx *fast_tx,
+				       struct sk_buff *skb);
+
 /* misc utils */
=20
 static inline void ieee80211_tx_stats(struct net_device *dev, u32 len)
@@ -853,8 +859,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
 	tid =3D *qc & IEEE80211_QOS_CTL_TID_MASK;
 	tx->sta->tx_stats.msdu[tid]++;
=20
-	if (!tx->sta->sta.txq[0])
-		hdr->seq_ctrl =3D ieee80211_tx_next_seq(tx->sta, tid);
+	hdr->seq_ctrl =3D ieee80211_tx_next_seq(tx->sta, tid);
=20
 	return TX_CONTINUE;
 }
@@ -1403,6 +1408,7 @@ void ieee80211_txq_init(struct ieee80211_sub_if_dat=
a *sdata,
 	fq_tin_init(&txqi->tin);
 	fq_flow_init(&txqi->def_flow);
 	codel_vars_init(&txqi->def_cvars);
+	__skb_queue_head_init(&txqi->frags);
=20
 	txqi->txq.vif =3D &sdata->vif;
=20
@@ -1425,6 +1431,7 @@ void ieee80211_txq_purge(struct ieee80211_local *lo=
cal,
 	struct fq_tin *tin =3D &txqi->tin;
=20
 	fq_tin_reset(fq, tin, fq_skb_free_func);
+	ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
 }
=20
 int ieee80211_txq_setup_flows(struct ieee80211_local *local)
@@ -1481,33 +1488,61 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee8=
0211_hw *hw,
 {
 	struct ieee80211_local *local =3D hw_to_local(hw);
 	struct txq_info *txqi =3D container_of(txq, struct txq_info, txq);
-	struct ieee80211_hdr *hdr;
 	struct sk_buff *skb =3D NULL;
 	struct fq *fq =3D &local->fq;
 	struct fq_tin *tin =3D &txqi->tin;
+	struct ieee80211_tx_info *info;
=20
 	spin_lock_bh(&fq->lock);
=20
 	if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags))
 		goto out;
=20
+	/* Make sure fragments stay together. */
+	skb =3D __skb_dequeue(&txqi->frags);
+	if (skb)
+		goto out;
+
+begin:
 	skb =3D fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
 	if (!skb)
 		goto out;
=20
 	ieee80211_set_skb_vif(skb, txqi);
=20
-	hdr =3D (struct ieee80211_hdr *)skb->data;
-	if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) {
+	info =3D IEEE80211_SKB_CB(skb);
+	if (txq->sta && info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
 		struct sta_info *sta =3D container_of(txq->sta, struct sta_info,
 						    sta);
-		struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+		struct ieee80211_fast_tx *fast_tx;
=20
-		hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, txq->tid);
-		if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
-			info->flags |=3D IEEE80211_TX_CTL_AMPDU;
-		else
-			info->flags &=3D ~IEEE80211_TX_CTL_AMPDU;
+		fast_tx =3D rcu_dereference(sta->fast_tx);
+		if (WARN_ON(!fast_tx)) {
+			/* lost fast_tx pointer while the packet was queued */
+			ieee80211_free_txskb(hw, skb);
+			goto begin;
+		}
+		ieee80211_xmit_fast_finish(sta->sdata, sta, fast_tx, skb);
+	} else {
+		struct ieee80211_tx_data tx =3D { };
+
+		__skb_queue_head_init(&tx.skbs);
+		tx.local =3D local;
+		tx.skb =3D skb;
+		if (txq->sta) {
+			tx.sta =3D container_of(txq->sta, struct sta_info, sta);
+			tx.sdata =3D tx.sta->sdata;
+		} else {
+			tx.sdata =3D vif_to_sdata(info->control.vif);
+		}
+
+		if (invoke_tx_handlers_late(&tx))
+			goto begin;
+
+		skb =3D __skb_dequeue(&tx.skbs);
+
+		if (!skb_queue_empty(&tx.skbs))
+			skb_queue_splice_tail(&tx.skbs, &txqi->frags);
 	}
=20
 out:
@@ -1521,6 +1556,47 @@ out:
 }
 EXPORT_SYMBOL(ieee80211_tx_dequeue);
=20
+static bool ieee80211_queue_skb(struct ieee80211_local *local,
+				struct ieee80211_sub_if_data *sdata,
+				struct sta_info *sta,
+				struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+	struct fq *fq =3D &local->fq;
+	struct ieee80211_vif *vif;
+	struct txq_info *txqi;
+	struct ieee80211_sta *pubsta;
+
+	if (!local->ops->wake_tx_queue ||
+	    sdata->vif.type =3D=3D NL80211_IFTYPE_MONITOR)
+		return false;
+
+	if (sta && sta->uploaded)
+		pubsta =3D &sta->sta;
+	else
+		pubsta =3D NULL;
+
+	if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
+		sdata =3D container_of(sdata->bss,
+				     struct ieee80211_sub_if_data, u.ap);
+
+	vif =3D &sdata->vif;
+	txqi =3D ieee80211_get_txq(local, vif, pubsta, skb);
+
+	if (!txqi)
+		return false;
+
+	info->control.vif =3D vif;
+
+	spin_lock_bh(&fq->lock);
+	ieee80211_txq_enqueue(local, txqi, skb);
+	spin_unlock_bh(&fq->lock);
+
+	drv_wake_tx_queue(local, txqi);
+
+	return true;
+}
+
 static bool ieee80211_tx_frags(struct ieee80211_local *local,
 			       struct ieee80211_vif *vif,
 			       struct ieee80211_sta *sta,
@@ -1528,9 +1604,7 @@ static bool ieee80211_tx_frags(struct ieee80211_loc=
al *local,
 			       bool txpending)
 {
 	struct ieee80211_tx_control control =3D {};
-	struct fq *fq =3D &local->fq;
 	struct sk_buff *skb, *tmp;
-	struct txq_info *txqi;
 	unsigned long flags;
=20
 	skb_queue_walk_safe(skbs, skb, tmp) {
@@ -1545,21 +1619,6 @@ static bool ieee80211_tx_frags(struct ieee80211_lo=
cal *local,
 		}
 #endif
=20
-		txqi =3D ieee80211_get_txq(local, vif, sta, skb);
-		if (txqi) {
-			info->control.vif =3D vif;
-
-			__skb_unlink(skb, skbs);
-
-			spin_lock_bh(&fq->lock);
-			ieee80211_txq_enqueue(local, txqi, skb);
-			spin_unlock_bh(&fq->lock);
-
-			drv_wake_tx_queue(local, txqi);
-
-			continue;
-		}
-
 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 		if (local->queue_stop_reasons[q] ||
 		    (!txpending && !skb_queue_empty(&local->pending[q]))) {
@@ -1680,10 +1739,13 @@ static bool __ieee80211_tx(struct ieee80211_local=
 *local,
 /*
  * Invoke TX handlers, return 0 on success and non-zero if the
  * frame was dropped or queued.
+ *
+ * The handlers are split into an early and late part. The latter is eve=
rything
+ * that can be sensitive to reordering, and will be deferred to after pa=
ckets
+ * are dequeued from the intermediate queues (when they are enabled).
  */
-static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
+static int invoke_tx_handlers_early(struct ieee80211_tx_data *tx)
 {
-	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(tx->skb);
 	ieee80211_tx_result res =3D TX_DROP;
=20
 #define CALL_TXH(txh) \
@@ -1697,16 +1759,42 @@ static int invoke_tx_handlers(struct ieee80211_tx=
_data *tx)
 	CALL_TXH(ieee80211_tx_h_check_assoc);
 	CALL_TXH(ieee80211_tx_h_ps_buf);
 	CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
-	CALL_TXH(ieee80211_tx_h_select_key);
+
 	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
 		CALL_TXH(ieee80211_tx_h_rate_ctrl);
=20
+ txh_done:
+	if (unlikely(res =3D=3D TX_DROP)) {
+		I802_DEBUG_INC(tx->local->tx_handlers_drop);
+		if (tx->skb)
+			ieee80211_free_txskb(&tx->local->hw, tx->skb);
+		else
+			ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
+		return -1;
+	} else if (unlikely(res =3D=3D TX_QUEUED)) {
+		I802_DEBUG_INC(tx->local->tx_handlers_queued);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Late handlers can be called while the sta lock is held. Handlers that=
 can
+ * cause packets to be generated will cause deadlock!
+ */
+static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
+{
+	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(tx->skb);
+	ieee80211_tx_result res =3D TX_CONTINUE;
+
 	if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
 		__skb_queue_tail(&tx->skbs, tx->skb);
 		tx->skb =3D NULL;
 		goto txh_done;
 	}
=20
+	CALL_TXH(ieee80211_tx_h_select_key);
 	CALL_TXH(ieee80211_tx_h_michael_mic_add);
 	CALL_TXH(ieee80211_tx_h_sequence);
 	CALL_TXH(ieee80211_tx_h_fragment);
@@ -1733,6 +1821,15 @@ static int invoke_tx_handlers(struct ieee80211_tx_=
data *tx)
 	return 0;
 }
=20
+static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
+{
+	int r =3D invoke_tx_handlers_early(tx);
+	if (r)
+		return r;
+
+	return invoke_tx_handlers_late(tx);
+}
+
 bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif, struct sk_buff *skb,
 			      int band, struct ieee80211_sta **sta)
@@ -1807,7 +1904,13 @@ static bool ieee80211_tx(struct ieee80211_sub_if_d=
ata *sdata,
 		info->hw_queue =3D
 			sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
=20
-	if (!invoke_tx_handlers(&tx))
+	if (invoke_tx_handlers_early(&tx))
+		return false;
+
+	if (ieee80211_queue_skb(local, sdata, tx.sta, tx.skb))
+		return true;
+
+	if (!invoke_tx_handlers_late(&tx))
 		result =3D __ieee80211_tx(local, &tx.skbs, led_len,
 					tx.sta, txpending);
=20
@@ -3159,7 +3262,7 @@ out:
 }
=20
 static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
-				struct net_device *dev, struct sta_info *sta,
+				struct sta_info *sta,
 				struct ieee80211_fast_tx *fast_tx,
 				struct sk_buff *skb)
 {
@@ -3170,9 +3273,9 @@ static bool ieee80211_xmit_fast(struct ieee80211_su=
b_if_data *sdata,
 	struct ethhdr eth;
 	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr =3D (void *)fast_tx->hdr;
-	struct ieee80211_tx_data tx;
-	ieee80211_tx_result r;
 	struct tid_ampdu_tx *tid_tx =3D NULL;
+	ieee80211_tx_result r;
+	struct ieee80211_tx_data tx;
 	u8 tid =3D IEEE80211_NUM_TIDS;
=20
 	/* control port protocol needs a lot of special handling */
@@ -3210,8 +3313,6 @@ static bool ieee80211_xmit_fast(struct ieee80211_su=
b_if_data *sdata,
 			return true;
 	}
=20
-	ieee80211_tx_stats(dev, skb->len + extra_head);
-
 	if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
 	    ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb))
 		return true;
@@ -3240,24 +3341,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_s=
ub_if_data *sdata,
 	info->flags =3D IEEE80211_TX_CTL_FIRST_FRAGMENT |
 		      IEEE80211_TX_CTL_DONTFRAG |
 		      (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
-
-	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
-		*ieee80211_get_qos_ctl(hdr) =3D tid;
-		if (!sta->sta.txq[0])
-			hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, tid);
-	} else {
-		info->flags |=3D IEEE80211_TX_CTL_ASSIGN_SEQ;
-		hdr->seq_ctrl =3D cpu_to_le16(sdata->sequence_number);
-		sdata->sequence_number +=3D 0x10;
-	}
-
-	if (skb_shinfo(skb)->gso_size)
-		sta->tx_stats.msdu[tid] +=3D
-			DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size);
-	else
-		sta->tx_stats.msdu[tid]++;
-
-	info->hw_queue =3D sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
+	info->control.flags =3D IEEE80211_TX_CTRL_FAST_XMIT;
=20
 	__skb_queue_head_init(&tx.skbs);
=20
@@ -3283,6 +3367,54 @@ static bool ieee80211_xmit_fast(struct ieee80211_s=
ub_if_data *sdata,
 		}
 	}
=20
+	if (ieee80211_queue_skb(local, sdata, sta, skb))
+		return true;
+
+	ieee80211_xmit_fast_finish(sdata, sta, fast_tx, skb);
+
+	if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
+		sdata =3D container_of(sdata->bss,
+				     struct ieee80211_sub_if_data, u.ap);
+
+	__skb_queue_tail(&tx.skbs, skb);
+	ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
+
+	return true;
+}
+
+/*
+ * Can be called while the sta lock is held. Anything that can cause pac=
kets to
+ * be generated will cause deadlock!
+ */
+static bool ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sda=
ta,
+				       struct sta_info *sta,
+				       struct ieee80211_fast_tx *fast_tx,
+				       struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr =3D (void *)skb->data;
+	u8 tid =3D IEEE80211_NUM_TIDS;
+
+	ieee80211_tx_stats(skb->dev, skb->len);
+
+	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
+		tid =3D skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+		*ieee80211_get_qos_ctl(hdr) =3D tid;
+		hdr->seq_ctrl =3D ieee80211_tx_next_seq(sta, tid);
+	} else {
+		info->flags |=3D IEEE80211_TX_CTL_ASSIGN_SEQ;
+		hdr->seq_ctrl =3D cpu_to_le16(sdata->sequence_number);
+		sdata->sequence_number +=3D 0x10;
+	}
+
+	if (skb_shinfo(skb)->gso_size)
+		sta->tx_stats.msdu[tid] +=3D
+			DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size);
+	else
+		sta->tx_stats.msdu[tid]++;
+
+	info->hw_queue =3D sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
+
 	/* statistics normally done by ieee80211_tx_h_stats (but that
 	 * has to consider fragmentation, so is more complex)
 	 */
@@ -3309,12 +3441,6 @@ static bool ieee80211_xmit_fast(struct ieee80211_s=
ub_if_data *sdata,
 		}
 	}
=20
-	if (sdata->vif.type =3D=3D NL80211_IFTYPE_AP_VLAN)
-		sdata =3D container_of(sdata->bss,
-				     struct ieee80211_sub_if_data, u.ap);
-
-	__skb_queue_tail(&tx.skbs, skb);
-	ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
 	return true;
 }
=20
@@ -3342,7 +3468,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *s=
kb,
 		fast_tx =3D rcu_dereference(sta->fast_tx);
=20
 		if (fast_tx &&
-		    ieee80211_xmit_fast(sdata, dev, sta, fast_tx, skb))
+		    ieee80211_xmit_fast(sdata, sta, fast_tx, skb))
 			goto out;
 	}
=20
--=20
2.9.3

^ permalink raw reply related

* Re: [PATCH v2] bcma: use of_dma_configure() to set initial dma mask
From: Arnd Bergmann @ 2016-09-06  9:34 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Kalle Valo, Hauke Mehrtens, linux-wireless@vger.kernel.org,
	Linux Kernel Mailing List
In-Reply-To: <CACna6rza3U+X=cNXqvjB8fe1s+hP234cu405m3ObJBB=wQUcOQ@mail.gmail.com>

On Monday, September 5, 2016 11:34:14 PM CEST Rafał Miłecki wrote:
> On 17 March 2016 at 10:39, Arnd Bergmann <arnd@arndb.de> wrote:
> > While fixing another bug, I noticed that bcma manually sets up
> > a dma_mask pointer for its child devices. We have a generic
> > helper for that now, which should be able to cope better with
> > any variations that might be needed to deal with cache coherency,
> > unusual DMA address offsets, iommus, or limited DMA masks, none
> > of which are currently handled here.
> >
> > This changes the core to use the of_dma_configure(), like
> > we do for platform devices that are probed directly from
> > DT.
> >
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> I applied this patch and tested on BCM47081 based device. I still got
> bgmac working which surely uses DMA.

Thanks!

> There is only 1 ARM wireless SoC
> using bcma (BCM47198) but its WiFi core isn't supported by b43.
> 
> Any tips what else to test? SPI core/driver doesn't use DMA. Maybe
> NAND core does, but we don't use it.
> 

If there is nothing else using this, then the patch won't cause
a regression ;-)

	Arnd

^ permalink raw reply

* Re: [PATCH] ath10k: advertize hardware packet loss mechanism
From: kbuild test robot @ 2016-09-06  8:18 UTC (permalink / raw)
  To: Rajkumar Manoharan
  Cc: kbuild-all, ath10k, linux-wireless, rmanohar, Rajkumar Manoharan
In-Reply-To: <20160906070841.4266-1-rmanohar@qti.qualcomm.com>

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

Hi Rajkumar,

[auto build test ERROR on ath6kl/ath-next]
[also build test ERROR on v4.8-rc5 next-20160906]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url:    https://github.com/0day-ci/linux/commits/Rajkumar-Manoharan/ath10k-advertize-hardware-packet-loss-mechanism/20160906-151148
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git ath-next
config: i386-randconfig-x008-201636 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   In file included from drivers/net/wireless/ath/ath10k/mac.h:21:0,
                    from drivers/net/wireless/ath/ath10k/mac.c:18:
   drivers/net/wireless/ath/ath10k/mac.c: In function 'ath10k_mac_register':
>> include/net/mac80211.h:2206:57: error: 'IEEE80211_HW_REPORTS_LOW_ACK' undeclared (first use in this function)
    #define ieee80211_hw_set(hw, flg) _ieee80211_hw_set(hw, IEEE80211_HW_##flg)
                                                            ^
>> drivers/net/wireless/ath/ath10k/mac.c:7884:2: note: in expansion of macro 'ieee80211_hw_set'
     ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
     ^~~~~~~~~~~~~~~~
   include/net/mac80211.h:2206:57: note: each undeclared identifier is reported only once for each function it appears in
    #define ieee80211_hw_set(hw, flg) _ieee80211_hw_set(hw, IEEE80211_HW_##flg)
                                                            ^
>> drivers/net/wireless/ath/ath10k/mac.c:7884:2: note: in expansion of macro 'ieee80211_hw_set'
     ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
     ^~~~~~~~~~~~~~~~

vim +/ieee80211_hw_set +7884 drivers/net/wireless/ath/ath10k/mac.c

  7868				BIT(NL80211_IFTYPE_P2P_GO);
  7869	
  7870		ieee80211_hw_set(ar->hw, SIGNAL_DBM);
  7871		ieee80211_hw_set(ar->hw, SUPPORTS_PS);
  7872		ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);
  7873		ieee80211_hw_set(ar->hw, MFP_CAPABLE);
  7874		ieee80211_hw_set(ar->hw, REPORTS_TX_ACK_STATUS);
  7875		ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
  7876		ieee80211_hw_set(ar->hw, AP_LINK_PS);
  7877		ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
  7878		ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
  7879		ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
  7880		ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
  7881		ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF);
  7882		ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
  7883		ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
> 7884		ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
  7885	
  7886		if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
  7887			ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
  7888	
  7889		ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
  7890		ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
  7891	
  7892		if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 32929 bytes --]

^ permalink raw reply

* Re: [v2] bcma: use of_dma_configure() to set initial dma mask
From: Kalle Valo @ 2016-09-06  7:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Rafał Miłecki, Hauke Mehrtens, linux-wireless,
	linux-kernel
In-Reply-To: <6123998.NAlOfyAp5F@wuerfel>

Arnd Bergmann <arnd@arndb.de> writes:

> On Saturday, September 3, 2016 2:08:19 PM CEST Kalle Valo wrote:
>> Arnd Bergmann <arnd@arndb.de> wrote:
>> > While fixing another bug, I noticed that bcma manually sets up
>> > a dma_mask pointer for its child devices. We have a generic
>> > helper for that now, which should be able to cope better with
>> > any variations that might be needed to deal with cache coherency,
>> > unusual DMA address offsets, iommus, or limited DMA masks, none
>> > of which are currently handled here.
>> > 
>> > This changes the core to use the of_dma_configure(), like
>> > we do for platform devices that are probed directly from
>> > DT.
>> > 
>> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>> 
>> Nobody tested this, so I'll drop the patch.
>
> Should I resend it? I think it's still required.

Sorry, I misunderstood your comments then. No need to resend, I readded
this to my queue:

https://patchwork.kernel.org/patch/8608751/

-- 
Kalle Valo

^ permalink raw reply

* Re: Debugging RTL8192CU firmware loading on 3.12 powerpc
From: Sven Eckelmann @ 2016-09-06  7:40 UTC (permalink / raw)
  To: Larry Finger; +Cc: Simon Wunderlich, linux-wireless, Pannirselvam Kanagaratnam
In-Reply-To: <d6f2b558-167b-cb48-e924-7bac815817b1@lwfinger.net>

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

On Freitag, 2. September 2016 12:53:28 CEST Larry Finger wrote:
[...]
> The patch I included in my previous E-mail, and attached here,  does get the
> firmware loaded correctly. There is still a problem that prevents
> authentication. I'm still looking for that issue.

Thanks for the fast update. I am currently testing your patch. It looks like 
the initial error is now gone. The hostapd also starts but beaconing doesn't 
seem to work at all (no error from the kernel/hostapd but the device is not 
sending anything). I am currently checking how beaconing is supposed to work 
in your driver. Maybe I will spot something useful.

Kind regards,
	Sven

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH] ath10k:  ensure pdev sta kickout threshold is set.
From: Manoharan, Rajkumar @ 2016-09-06  7:39 UTC (permalink / raw)
  To: greearb@candelatech.com, ath10k@lists.infradead.org,
	Rajkumar Manoharan
  Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1472843202-12428-1-git-send-email-greearb@candelatech.com>

[...]=0A=
=0A=
> +int ath10k_mac_set_pdev_kickout(struct ath10k *ar)=0A=
> +{=0A=
> +       u32 param =3D ar->wmi.pdev_param->sta_kickout_th;=0A=
> +       int rv;=0A=
> +=0A=
> +       rv =3D ath10k_wmi_pdev_set_param(ar, param,=0A=
> +                                      ar->sta_xretry_kickout_thresh);=0A=
> +       if (rv) {=0A=
> +               ath10k_warn(ar, "failed to set sta kickout threshold to %=
d: %d\n",=0A=
> +                           ar->sta_xretry_kickout_thresh, rv);=0A=
> +       }=0A=
> +       return rv;=0A=
> +}=0A=
>=0A=
Ben,=0A=
=0A=
I plan to get rid of setting station kickout threshold from host. Each firm=
ware revision (i.e qca988x, qca99x0, ipq4019)  follows different logic base=
d on hw capability for station kickout and follows different default paramt=
ers. So configuring common threshold will affect firmware logic. Better to =
get rid of these configuration from host driver and let firmware to work wi=
th default parameters.=0A=
=0A=
Also I could not find out sta_xretry_kickout_thresh definition in upstream =
driver. Have you posted any changes for the same?=0A=
=0A=
-Rajkumar=

^ permalink raw reply

* [NetDev] [ANNOUNCE] Netdev 1.2 weekly updates (6th September, 2016)
From: Hajime Tazaki @ 2016-09-06  7:19 UTC (permalink / raw)
  To: netdev, netfilter-devel, linux-wireless, netdev-conference


Hello folks,

Tokyo is still being in a hot weather but it'll start
comfortable autumn very soon.

Here is an weekly update of Netdev 1.2 Tokyo.

We again extended the deadline of early bird registration.
Please don't miss the discount ticket - and your early
registration will be definitely helpful to prepare the
conference.

http://netdevconf.org/1.2/registration.html


== Newly accepted sessions ==

Here is newly accepted sessions in the last week.  We're
going to announce keynote talks once we confirmed so, stay
tune for a while.

Full list of accepted sessions is available here.

http://netdevconf.org/1.2/accepted-sessions.html

* Workshop

- nftables workshop
  by Pablo Neira Ayuso

* Talk

- Data center networking stack
  by Tom Herbert

- Single Virtual function driver for current and future Intel Network devices
  by Anjali Singhai Jain, Mitch Williams, Jesse Brandeburg

- Stacked Vlan: Performance Improvement and Challenges
  by Toshiaki Makita

- eBPF/XDP hardware offload to SmartNICs
  by Jakub Kicinski, Nic Viljoen

- Using SR-IOV offload with application like openVswitch
  by Rony Efraim, Or Gerlitz

* BoF

- Accelerating container network with channel based IO
  by Rony Efraim, Or Gerlitz


== Our sponsors ==

- Platinum
Verizon, Facebook, Cumulus Networks
- Gold
Mojatatu Networks, VMWare, Google, NTT, LinkedIn
- Silver
NetApp, IIJ, Netronome, SolarFlare, Mellanox, Sophos
- Bronze
Zen Load Balancer

Twitter: https://twitter.com/netdev01
Web: http://netdevconf.org/1.2/

== Others ==

Be prepared for your travel ! Hotel and travel information
are available on the web pages.

http://netdevconf.org/1.2/travel.html
http://netdevconf.org/1.2/hotel.html


Looking forward to seeing you in Tokyo very soon.

-- Hajime

^ permalink raw reply

* [PATCH] ath10k: advertize hardware packet loss mechanism
From: Rajkumar Manoharan @ 2016-09-06  7:08 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, rmanohar, Rajkumar Manoharan

Indicate hardware (or firmware) supports that CQM packet-loss report
will be generated based on station kickout algorithm. As of now mac80211
tracks connection loss by missing msdu counts (50) whereas ath10k
firmware tracks them by missing ppdus (+ BAR tries). While firmware is
trying to adapt its rate table, mac80211 might send out low_ack event to
hostapd. This is causing frequent connect and disconnect iteration under
noisy environment or when station is roaming around.

Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 79525f769db6..bae7662e7207 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7865,6 +7865,7 @@ int ath10k_mac_register(struct ath10k *ar)
 	ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF);
 	ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
 	ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
+	ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
 
 	if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
 		ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
-- 
2.9.3

^ permalink raw reply related


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