Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: pull-request: mac80211 2016-08-05
From: David Miller @ 2016-08-07  7:24 UTC (permalink / raw)
  To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <1470400329-23256-1-git-send-email-johannes@sipsolutions.net>

From: Johannes Berg <johannes@sipsolutions.net>
Date: Fri,  5 Aug 2016 14:32:08 +0200

> Here's a first set of fixes for the current cycle. See the tag message
> for more information.
> 
> I'll probably have a follow-up fix for the real problem in mac80211
> that caused the crash later, but for now we have this patch and it
> makes sense and fixes the crash, even if the behaviour isn't quite
> right (afaict.)
> 
> Let me know if there's any problem.

Pulled, thanks.

^ permalink raw reply

* Re: pull request: iwlwifi 2016-04-12
From: Emmanuel Grumbach @ 2016-08-07  4:38 UTC (permalink / raw)
  To: Grumbach, Emmanuel; +Cc: kvalo@codeaurora.org, linux-wireless@vger.kernel.org
In-Reply-To: <1460448559.2630.8.camel@intel.com>

On Sun, Aug 7, 2016 at 7:35 AM, Grumbach, Emmanuel
<emmanuel.grumbach@intel.com> wrote:
>
> Hi Kalle,
>
> Here is a pull request for 4.6. I have here a patch that was merged to
> -next already, but clearly, it should have been routed through the
> current cycle's trees. Sorry about that.
> The patch is:


Wow.. I knew evolution was sometimes stupid, but this is new to me..
Obviously you should ignore that.
Sorry...

>
> commit cd49727e1a2bccc4ff008dde24c2f8430dd9e368
> Author: Ayala Beker <ayala.beker@intel.com>
> Date:   Wed Feb 3 15:36:52 2016 +0200
>
>     iwlwifi: mvm: avoid to WARN about gscan capabilities
>
>     Gscan capabilities were updated with new capabilities supported
>     by the device. Update GSCAN capabilities TLV and avoid to WARN
>     if the firmware does not have the new capabilities.
>
> It appears in -next as:
>
> commit a0b09f13036cedfd67c9cb4b9d05138e7022723d
> Author: Ayala Beker <ayala.beker@intel.com>
> Date:   Wed Feb 3 15:36:52 2016 +0200
>
>     iwlwifi: mvm: update GSCAN capabilities
>
>     Gscan capabilities were updated with new capabilities supported
>     by the device. Update GSCAN capabilities TLV.
>
> The commit message wasn't good enough for the current cycle, so I
> rewrote it. Besides that one, all is fairly normal.
> Let me know if you have issues!
>
> Thanks.
>
>
> The following changes since commit 7fdf9663261cc77a516396fec82cee8a8ea07e76:
>
>   iwlwifi: mvm: fix memory leak in paging (2016-03-20 23:01:54 +0200)
>
> are available in the git repository at:
>
>   https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes.git tags/iwlwifi-for-kalle-2016-04-12
>
> for you to fetch changes up to 2d25fb8b3a138706b63bd26ad72a95c58029954a:
>
>   iwlwifi: mvm: fix accessing Null pointer during fw dump collection (2016-04-12 10:03:17 +0300)
>
> ----------------------------------------------------------------
> * add new device IDs for 8265
> * fix a NULL pointer dereference when paging firmware asserts
> * remove a WARNING on gscan capabilities
> * fix MODULE_FIRMWARE for 8260
>
> ----------------------------------------------------------------
> Ayala Beker (1):
>       iwlwifi: mvm: avoid to WARN about gscan capabilities
>
> Matti Gottlieb (1):
>       iwlwifi: mvm: fix accessing Null pointer during fw dump collection
>
> Oren Givon (1):
>       iwlwifi: add device IDs for the 8265 device
>
> Sara Sharon (1):
>       iwlwifi: 8000: fix MODULE_FIRMWARE input
>
>  drivers/net/wireless/intel/iwlwifi/iwl-8000.c   |  2 +-
>  drivers/net/wireless/intel/iwlwifi/iwl-drv.c    | 26 ++++++++++----------------
>  drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c |  6 ++++--
>  drivers/net/wireless/intel/iwlwifi/mvm/fw.c     |  2 ++
>  drivers/net/wireless/intel/iwlwifi/pcie/drv.c   | 10 ++++++++++
>  5 files changed, 27 insertions(+), 19 deletions(-)

^ permalink raw reply

* pull request: iwlwifi 2016-04-12
From: Grumbach, Emmanuel @ 2016-08-07  4:35 UTC (permalink / raw)
  To: kvalo@codeaurora.org; +Cc: linux-wireless@vger.kernel.org

SGkgS2FsbGUsDQoNCkhlcmUgaXMgYSBwdWxsIHJlcXVlc3QgZm9yIDQuNi4gSSBoYXZlIGhlcmUg
YSBwYXRjaCB0aGF0IHdhcyBtZXJnZWQgdG8gDQotbmV4dCBhbHJlYWR5LCBidXQgY2xlYXJseSwg
aXQgc2hvdWxkIGhhdmUgYmVlbiByb3V0ZWQgdGhyb3VnaCB0aGUNCmN1cnJlbnQgY3ljbGUncyB0
cmVlcy4gU29ycnkgYWJvdXQgdGhhdC4NClRoZSBwYXRjaCBpczoNCg0KY29tbWl0IGNkNDk3Mjdl
MWEyYmNjYzRmZjAwOGRkZTI0YzJmODQzMGRkOWUzNjgNCkF1dGhvcjogQXlhbGEgQmVrZXIgPGF5
YWxhLmJla2VyQGludGVsLmNvbT4NCkRhdGU6ICAgV2VkIEZlYiAzIDE1OjM2OjUyIDIwMTYgKzAy
MDANCg0KICAgIGl3bHdpZmk6IG12bTogYXZvaWQgdG8gV0FSTiBhYm91dCBnc2NhbiBjYXBhYmls
aXRpZXMNCiAgICANCiAgICBHc2NhbiBjYXBhYmlsaXRpZXMgd2VyZSB1cGRhdGVkIHdpdGggbmV3
IGNhcGFiaWxpdGllcyBzdXBwb3J0ZWQNCiAgICBieSB0aGUgZGV2aWNlLiBVcGRhdGUgR1NDQU4g
Y2FwYWJpbGl0aWVzIFRMViBhbmQgYXZvaWQgdG8gV0FSTg0KICAgIGlmIHRoZSBmaXJtd2FyZSBk
b2VzIG5vdCBoYXZlIHRoZSBuZXcgY2FwYWJpbGl0aWVzLg0KDQpJdCBhcHBlYXJzIGluIC1uZXh0
IGFzOg0KDQpjb21taXQgYTBiMDlmMTMwMzZjZWRmZDY3YzljYjRiOWQwNTEzOGU3MDIyNzIzZA0K
QXV0aG9yOiBBeWFsYSBCZWtlciA8YXlhbGEuYmVrZXJAaW50ZWwuY29tPg0KRGF0ZTogICBXZWQg
RmViIDMgMTU6MzY6NTIgMjAxNiArMDIwMA0KDQogICAgaXdsd2lmaTogbXZtOiB1cGRhdGUgR1ND
QU4gY2FwYWJpbGl0aWVzDQogICAgDQogICAgR3NjYW4gY2FwYWJpbGl0aWVzIHdlcmUgdXBkYXRl
ZCB3aXRoIG5ldyBjYXBhYmlsaXRpZXMgc3VwcG9ydGVkDQogICAgYnkgdGhlIGRldmljZS4gVXBk
YXRlIEdTQ0FOIGNhcGFiaWxpdGllcyBUTFYuDQoNClRoZSBjb21taXQgbWVzc2FnZSB3YXNuJ3Qg
Z29vZCBlbm91Z2ggZm9yIHRoZSBjdXJyZW50IGN5Y2xlLCBzbyBJDQpyZXdyb3RlIGl0LiBCZXNp
ZGVzIHRoYXQgb25lLCBhbGwgaXMgZmFpcmx5IG5vcm1hbC4NCkxldCBtZSBrbm93IGlmIHlvdSBo
YXZlIGlzc3VlcyENCg0KVGhhbmtzLg0KDQoNClRoZSBmb2xsb3dpbmcgY2hhbmdlcyBzaW5jZSBj
b21taXQgN2ZkZjk2NjMyNjFjYzc3YTUxNjM5NmZlYzgyY2VlOGE4ZWEwN2U3NjoNCg0KICBpd2x3
aWZpOiBtdm06IGZpeCBtZW1vcnkgbGVhayBpbiBwYWdpbmcgKDIwMTYtMDMtMjAgMjM6MDE6NTQg
KzAyMDApDQoNCmFyZSBhdmFpbGFibGUgaW4gdGhlIGdpdCByZXBvc2l0b3J5IGF0Og0KDQogIGh0
dHBzOi8vZ2l0Lmtlcm5lbC5vcmcvcHViL3NjbS9saW51eC9rZXJuZWwvZ2l0L2l3bHdpZmkvaXds
d2lmaS1maXhlcy5naXQgdGFncy9pd2x3aWZpLWZvci1rYWxsZS0yMDE2LTA0LTEyDQoNCmZvciB5
b3UgdG8gZmV0Y2ggY2hhbmdlcyB1cCB0byAyZDI1ZmI4YjNhMTM4NzA2YjYzYmQyNmFkNzJhOTVj
NTgwMjk5NTRhOg0KDQogIGl3bHdpZmk6IG12bTogZml4IGFjY2Vzc2luZyBOdWxsIHBvaW50ZXIg
ZHVyaW5nIGZ3IGR1bXAgY29sbGVjdGlvbiAoMjAxNi0wNC0xMiAxMDowMzoxNyArMDMwMCkNCg0K
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLQ0KKiBhZGQgbmV3IGRldmljZSBJRHMgZm9yIDgyNjUNCiogZml4IGEgTlVMTCBwb2lu
dGVyIGRlcmVmZXJlbmNlIHdoZW4gcGFnaW5nIGZpcm13YXJlIGFzc2VydHMNCiogcmVtb3ZlIGEg
V0FSTklORyBvbiBnc2NhbiBjYXBhYmlsaXRpZXMNCiogZml4IE1PRFVMRV9GSVJNV0FSRSBmb3Ig
ODI2MA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tDQpBeWFsYSBCZWtlciAoMSk6DQogICAgICBpd2x3aWZpOiBtdm06IGF2
b2lkIHRvIFdBUk4gYWJvdXQgZ3NjYW4gY2FwYWJpbGl0aWVzDQoNCk1hdHRpIEdvdHRsaWViICgx
KToNCiAgICAgIGl3bHdpZmk6IG12bTogZml4IGFjY2Vzc2luZyBOdWxsIHBvaW50ZXIgZHVyaW5n
IGZ3IGR1bXAgY29sbGVjdGlvbg0KDQpPcmVuIEdpdm9uICgxKToNCiAgICAgIGl3bHdpZmk6IGFk
ZCBkZXZpY2UgSURzIGZvciB0aGUgODI2NSBkZXZpY2UNCg0KU2FyYSBTaGFyb24gKDEpOg0KICAg
ICAgaXdsd2lmaTogODAwMDogZml4IE1PRFVMRV9GSVJNV0FSRSBpbnB1dA0KDQogZHJpdmVycy9u
ZXQvd2lyZWxlc3MvaW50ZWwvaXdsd2lmaS9pd2wtODAwMC5jICAgfCAgMiArLQ0KIGRyaXZlcnMv
bmV0L3dpcmVsZXNzL2ludGVsL2l3bHdpZmkvaXdsLWRydi5jICAgIHwgMjYgKysrKysrKysrKy0t
LS0tLS0tLS0tLS0tLS0NCiBkcml2ZXJzL25ldC93aXJlbGVzcy9pbnRlbC9pd2x3aWZpL212bS9m
dy1kYmcuYyB8ICA2ICsrKystLQ0KIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2ludGVsL2l3bHdpZmkv
bXZtL2Z3LmMgICAgIHwgIDIgKysNCiBkcml2ZXJzL25ldC93aXJlbGVzcy9pbnRlbC9pd2x3aWZp
L3BjaWUvZHJ2LmMgICB8IDEwICsrKysrKysrKysNCiA1IGZpbGVzIGNoYW5nZWQsIDI3IGluc2Vy
dGlvbnMoKyksIDE5IGRlbGV0aW9ucygtKQ==

^ permalink raw reply

* RE: [PATCH] cfg80211: Add support for user configurable beacon data rate
From: Undekari, Sunil Dutt @ 2016-08-06  4:38 UTC (permalink / raw)
  To: Johannes Berg, Kushwaha, Purushottam
  Cc: linux-wireless@vger.kernel.org, Malinen, Jouni,
	Kondabattini, Ganesh, Kalikot Veetil, Mahesh Kumar,
	Hullur Subramanyam, Amarnath
In-Reply-To: <1470387784.2977.30.camel@sipsolutions.net>

PiBEb2Vzbid0IHRoaXMgaGF2ZSB0byBjaGVjayB0aGF0IGl0IGFjdHVhbGx5IGdvdCBpbmZvcm1h
dGlvbiBmb3IgdGhlIHJpZ2h0IGJhbmQ/DQpIaSBKb2hhbm5lcyAsDQpubDgwMjExX3BhcnNlX3R4
X2JpdHJhdGVfbWFzayAoIGEgbmV3IHdyYXBwZXIgdG8gdGhlIGV4aXN0aW5nIGZ1bmN0aW9uYWxp
dHkgaW4gbmw4MDIxMV9zZXRfdHhfYml0cmF0ZV9tYXNrICkgZG9lcyB0aGlzICwgaXNuJ3QgPyAN
Cg0KUmVnYXJkcywNClN1bmlsDQoNCg0KDQotLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KRnJv
bTogSm9oYW5uZXMgQmVyZyBbbWFpbHRvOmpvaGFubmVzQHNpcHNvbHV0aW9ucy5uZXRdIA0KU2Vu
dDogRnJpZGF5LCBBdWd1c3QgNSwgMjAxNiAyOjMzIFBNDQpUbzogS3VzaHdhaGEsIFB1cnVzaG90
dGFtIDxwa3VzaHdhaEBxdGkucXVhbGNvbW0uY29tPg0KQ2M6IGxpbnV4LXdpcmVsZXNzQHZnZXIu
a2VybmVsLm9yZzsgTWFsaW5lbiwgSm91bmkgPGpvdW5pQHFjYS5xdWFsY29tbS5jb20+OyBVbmRl
a2FyaSwgU3VuaWwgRHV0dCA8dXNkdXR0QHF0aS5xdWFsY29tbS5jb20+OyBLb25kYWJhdHRpbmks
IEdhbmVzaCA8Z2FuZXNoa0BxdGkucXVhbGNvbW0uY29tPjsgS2FsaWtvdCBWZWV0aWwsIE1haGVz
aCBLdW1hciA8bWthbGlrb3RAcWNhLnF1YWxjb21tLmNvbT47IEh1bGx1ciBTdWJyYW1hbnlhbSwg
QW1hcm5hdGggPGFtYXJuYXRoQHFjYS5xdWFsY29tbS5jb20+DQpTdWJqZWN0OiBSZTogW1BBVENI
XSBjZmc4MDIxMTogQWRkIHN1cHBvcnQgZm9yIHVzZXIgY29uZmlndXJhYmxlIGJlYWNvbiBkYXRh
IHJhdGUNCg0KT24gRnJpLCAyMDE2LTA4LTA1IGF0IDEwOjA1ICswNTMwLCBQdXJ1c2hvdHRhbSBL
dXNod2FoYSB3cm90ZToNCj7CoA0KPiArc3RhdGljIGludCBubDgwMjExX3BhcnNlX3R4X2JpdHJh
dGVfbWFzayhzdHJ1Y3QgZ2VubF9pbmZvICppbmZvLA0KPiArCQkJCQnCoHN0cnVjdCBjZmc4MDIx
MV9iaXRyYXRlX21hc2sgKm1hc2spOw0KDQpJIHRoaW5rIHlvdSBzaG91bGQgbW92ZSB0aGUgZnVu
Y3Rpb24gaW5zdGVhZC4NCg0KPiBAQCAtMzQ1Nyw2ICszNDU5LDExIEBAIHN0YXRpYyBpbnQgbmw4
MDIxMV9zdGFydF9hcChzdHJ1Y3Qgc2tfYnVmZiANCj4gKnNrYiwgc3RydWN0IGdlbmxfaW5mbyAq
aW5mbykNCj4gwqAJZXJyID0gY2ZnODAyMTFfdmFsaWRhdGVfYmVhY29uX2ludChyZGV2LA0KPiBw
YXJhbXMuYmVhY29uX2ludGVydmFsKTsNCj4gwqAJaWYgKGVycikNCj4gwqAJCXJldHVybiBlcnI7
DQo+ICsJaWYgKGluZm8tPmF0dHJzW05MODAyMTFfQVRUUl9UWF9SQVRFU10pIHsNCj4gKwkJZXJy
ID0gbmw4MDIxMV9wYXJzZV90eF9iaXRyYXRlX21hc2soaW5mbywNCj4gJnBhcmFtcy5iZWFjb25f
cmF0ZSk7DQo+ICsJCWlmIChlcnIpDQo+ICsJCQlyZXR1cm4gZXJyOw0KPiArCX0NCg0KRG9lc24n
dCB0aGlzIGhhdmUgdG8gY2hlY2sgdGhhdCBpdCBhY3R1YWxseSBnb3QgaW5mb3JtYXRpb24gZm9y
IHRoZSByaWdodCBiYW5kPw0KDQpqb2hhbm5lcw0K

^ permalink raw reply

* [PATCH] ath10k: fix group privacy action frame decryption for qca4019
From: Rajkumar Manoharan @ 2016-08-06  4:19 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, rmanohar, Rajkumar Manoharan

Recent commit 'mac80211: Encrypt "Group addressed privacy" action frames'
encrypts group privacy action frames. But qca99x0 family chipset delivers
broadcast/multicast management frames as encrypted and it should be
decrypted by mac80211. Setting RX_FLAG_DECRYPTED stats for those frames
is breaking mesh connection establishment.

Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/core.c |  4 ++++
 drivers/net/wireless/ath/ath10k/core.h |  5 +++++
 drivers/net/wireless/ath/ath10k/wmi.c  | 30 +++++++++++++++++++++++++-----
 3 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 0ca58cf0ffea..c4d1a5ba216e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -182,6 +182,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 			.board_size = QCA99X0_BOARD_DATA_SZ,
 			.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
 		},
+		.sw_decrypt_mcast_mgmt = true,
 	},
 	{
 		.id = QCA9984_HW_1_0_DEV_VERSION,
@@ -205,6 +206,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 			.board_size = QCA99X0_BOARD_DATA_SZ,
 			.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
 		},
+		.sw_decrypt_mcast_mgmt = true,
 	},
 	{
 		.id = QCA9888_HW_2_0_DEV_VERSION,
@@ -227,6 +229,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 			.board_size = QCA99X0_BOARD_DATA_SZ,
 			.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
 		},
+		.sw_decrypt_mcast_mgmt = true,
 	},
 	{
 		.id = QCA9377_HW_1_0_DEV_VERSION,
@@ -285,6 +288,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 			.board_size = QCA4019_BOARD_DATA_SZ,
 			.board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,
 		},
+		.sw_decrypt_mcast_mgmt = true,
 	},
 };
 
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index f36c2b274ee5..7254bd3e7c82 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -765,6 +765,11 @@ struct ath10k {
 			size_t board_size;
 			size_t board_ext_size;
 		} fw;
+
+		/* qca99x0 family chips deliver broadcast/multicast management
+		 * frames encrypted and expect software do decryption.
+		 */
+		bool sw_decrypt_mcast_mgmt;
 	} hw_params;
 
 	/* contains the firmware images used with ATH10K_FIRMWARE_MODE_NORMAL */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 169cd2e783eb..bced8ac7ed94 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2240,6 +2240,30 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar,
 	return 0;
 }
 
+static bool ath10k_wmi_rx_is_decrypted(struct ath10k *ar,
+				       struct ieee80211_hdr *hdr)
+{
+	if (!ieee80211_has_protected(hdr->frame_control))
+		return false;
+
+	/* FW delivers WEP Shared Auth frame with Protected Bit set and
+	 * encrypted payload. However in case of PMF it delivers decrypted
+	 * frames with Protected Bit set.
+	 */
+	if (ieee80211_is_auth(hdr->frame_control))
+		return false;
+
+	/* qca99x0 based FW delivers broadcast or multicast management frames
+	 * (ex: group privacy action frames in mesh) as encrypted payload.
+	 */
+	if ((is_broadcast_ether_addr(ieee80211_get_DA(hdr)) ||
+	     is_multicast_ether_addr(ieee80211_get_DA(hdr))) &&
+	    ar->hw_params.sw_decrypt_mcast_mgmt)
+		return false;
+
+	return true;
+}
+
 int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_mgmt_rx_ev_arg arg = {};
@@ -2326,11 +2350,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
 
 	ath10k_wmi_handle_wep_reauth(ar, skb, status);
 
-	/* FW delivers WEP Shared Auth frame with Protected Bit set and
-	 * encrypted payload. However in case of PMF it delivers decrypted
-	 * frames with Protected Bit set. */
-	if (ieee80211_has_protected(hdr->frame_control) &&
-	    !ieee80211_is_auth(hdr->frame_control)) {
+	if (ath10k_wmi_rx_is_decrypted(ar, hdr)) {
 		status->flag |= RX_FLAG_DECRYPTED;
 
 		if (!ieee80211_is_action(hdr->frame_control) &&
-- 
2.9.2


^ permalink raw reply related

* Re: TCP data throughput for BCM43362
From: Jörg Krause @ 2016-08-06 14:12 UTC (permalink / raw)
  To: Franky Lin
  Cc: Arend Van Spriel, Brett Rudley, brcm80211-dev-list,
	Hante Meuleman, Franky Lin, linux-wireless, Arend van Spriel
In-Reply-To: <CA+8PC_f7VQMwBfQmZZ_vUtYtNJKVYzmFmxziAwoG8-iRUeW9Jw@mail.gmail.com>

Hi all,

On Fr, 2016-08-05 at 17:56 -0700, Franky Lin wrote:

On Fri, Aug 5, 2016 at 2:29 PM, Jörg Krause <joerg.krause@embedded.ro
cks>
wrote:





Am 5. August 2016 23:01:10 MESZ, schrieb Arend Van Spriel <
arend.vanspriel@broadcom.com>:


Op 5 aug. 2016 22:46 schreef "Jörg Krause"
<joerg.krause@embedded.rocks>:



Hi,

I'm using a custom ARM board with an BCM43362 wifi chip from

Broadcom.


The wifi chip is attached via SDIO to the controller with a
clock of
48MHz. Linux kernel version is 4.7.

When measuring the network bandwidth with iperf3 I get a
bandwith of
only around 5 Mbps. I found a similar thread at the Broadcom

community


[1] where the test was done with a M4 CPU + BCM43362 and an
average
result of 3.3 Mbps.

Interestingly, a BCM43362 Wi-Fi Dev Kit [2] notes a TCP data

throughput


greater than 20 Mbps.

Why is the throughput I measured much lower? Note that I
measured
several times with almost no neighbor devices or networks.

This is a test sample measured with iperf3:

    $ iperf3 -c 192.168.2.1 -i 1 -t 10
    Connecting to host 192.168.2.1, port 5201
    [  4] local 192.168.2.155 port 36442 connected to
192.168.2.1

port


    5201
    [ ID]
Interval           Transfer     Bandwidth       Retr  Cwnd
    [  4]   0.00-1.00   sec   615 KBytes  5.04
Mbits/sec    0   56.6
    KBytes
    [  4]   1.00-2.00   sec   622 KBytes  5.10
Mbits/sec    0   84.8
    KBytes
    [  4]   2.00-3.00   sec   625 KBytes  5.12
Mbits/sec    0    113
    KBytes
    [  4]   3.00-4.00   sec   571 KBytes  4.68
Mbits/sec    0    140
    KBytes
    [  4]   4.00-5.00   sec   594 KBytes  4.87
Mbits/sec    0    167
    KBytes
    [  4]   5.00-6.00   sec   628 KBytes  5.14
Mbits/sec    0    195
    KBytes
    [  4]   6.00-7.00   sec   619 KBytes  5.07
Mbits/sec    0    202
    KBytes
    [  4]   7.00-8.00   sec   608 KBytes  4.98
Mbits/sec    0    202
    KBytes
    [  4]   8.00-9.00   sec   602 KBytes  4.93
Mbits/sec    0    202
    KBytes
    [  4]   9.00-10.00  sec   537 KBytes  4.40
Mbits/sec    0    202
    KBytes
    - - - - - - - - - - - - - - - - - - - - - - - - -
    [ ID] Interval           Transfer     Bandwidth       Retr
    [  4]   0.00-10.00  sec  5.88 MBytes  4.93
    Mbits/sec    0             sender
    [  4]   0.00-10.00  sec  5.68 MBytes  4.76
    Mbits/sec                  receiver


Not overly familiar with iperf3. Do these lines mean you are
doing
bidirectional test, ie. upstream and downstream at the same time.
Another
thing affecting tput could be power-save.


No, iperf3 does not support bidrectional test. Power-save is turned
off.

What does iw link say?

 


I compared the results with a Cubietruck I have:

# iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.178.46, port 42906
[  5] local 192.168.178.38 port 5201 connected to 192.168.178.46 port
42908
[ ID] Interval           Transfer     Bandwidth
[  5]   0.00-1.00   sec  2.29 MBytes  19.2 Mbits/sec                  
[  5]   1.00-2.00   sec  2.21 MBytes  18.5 Mbits/sec                  
[  5]   2.00-3.00   sec  2.17 MBytes  18.2 Mbits/sec                  
[  5]   3.00-4.00   sec  2.09 MBytes  17.6 Mbits/sec                  
[  5]   4.00-5.00   sec  2.20 MBytes  18.5 Mbits/sec                  
[  5]   5.00-6.00   sec  2.64 MBytes  22.1 Mbits/sec                  
[  5]   6.00-7.00   sec  2.67 MBytes  22.4 Mbits/sec                  
[  5]   7.00-8.00   sec  2.62 MBytes  22.0 Mbits/sec                  
[  5]   8.00-9.00   sec  2.35 MBytes  19.8 Mbits/sec                  
[  5]   9.00-10.00  sec  2.30 MBytes  19.3 Mbits/sec                  
[  5]  10.00-10.03  sec  83.4 KBytes  23.5 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  5]   0.00-10.03  sec  23.9 MBytes  20.0
Mbits/sec    0             sender
[  5]   0.00-10.03  sec  23.6 MBytes  19.8
Mbits/sec                  receiver

# iw dev wlan0 link
Connected to xx:xx:xx:xx:xx (on wlan0)
	SSID: xxx
	freq: 2437
	tx bitrate: 65.0 MBit/s

	bss flags:	short-preamble short-slot-time
	dtim period:	1
	beacon int:	100

The Cubietruck works also with the brcmfmac driver.

May it depend on the NVRAM file?

Best regards
Jörg Krause

^ permalink raw reply

* brcmfmac43430-sdio.bin in linux-firmware
From: Fabio Estevam @ 2016-08-06 15:15 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-wireless, brcm80211-dev-list, Hante Meuleman

Hi,

I managed to get Wifi working on a imx7 warp board, which has a BCM43430 device.

I used the firmware from the RaspberryPi repository:
https://github.com/RPi-Distro/firmware-nonfree/tree/master/brcm80211/brcm

Are there any plans to make brcmfmac43430-sdio.bin available in the
official linux-firmware repository?

Thanks,

Fabio Estevam

^ permalink raw reply

* Re: [patch] ath9k: indent an if statement
From: Julian Calaby @ 2016-08-06 14:57 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: QCA ath9k Development, Benjamin Berg, Kalle Valo, linux-wireless,
	ath9k-devel, kernel-janitors
In-Reply-To: <20160803184339.GB775@mwanda>

Hi All,

On Thu, Aug 4, 2016 at 4:43 AM, Dan Carpenter <dan.carpenter@oracle.com> wrote:
> It looks like this code is correct, but it just needs to be indented a
> bit.
>
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Looks right to me.

Reviewed-by: Julian Calaby <julian.calaby@gmail.com>

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

^ permalink raw reply

* Re: [PATCH] cfg80211: Add support for user configurable beacon data rate
From: Johannes Berg @ 2016-08-06 19:57 UTC (permalink / raw)
  To: Undekari, Sunil Dutt, Kushwaha, Purushottam
  Cc: linux-wireless@vger.kernel.org, Malinen, Jouni,
	Kondabattini, Ganesh, Kalikot Veetil, Mahesh Kumar,
	Hullur Subramanyam, Amarnath
In-Reply-To: <92b06d4df5984e6ea91081126e096a96@aphydexm01f.ap.qualcomm.com>

On Sat, 2016-08-06 at 04:38 +0000, Undekari, Sunil Dutt wrote:
> > 
> > Doesn't this have to check that it actually got information for the
> > right band?
> Hi Johannes ,
> nl80211_parse_tx_bitrate_mask ( a new wrapper to the existing
> functionality in nl80211_set_tx_bitrate_mask ) does this , isn't ? 
> 
It checks that everything matches up with capabilities, but it doesn't
check that if you specified NL80211_ATTR_TX_RATES you didn't do
something stupid like specifying it for 2.4GHz while your AP is
starting up on 5GHz.

It also doesn't check that you specified exactly one rate, but it's not
clear how else this would work?

johannes

^ permalink raw reply

* Re: TCP data throughput for BCM43362
From: Jörg Krause @ 2016-08-06  8:07 UTC (permalink / raw)
  To: Franky Lin
  Cc: Arend Van Spriel, Brett Rudley, brcm80211-dev-list,
	Hante Meuleman, Franky Lin, linux-wireless, Arend van Spriel
In-Reply-To: <CA+8PC_f7VQMwBfQmZZ_vUtYtNJKVYzmFmxziAwoG8-iRUeW9Jw@mail.gmail.com>

Hi Franky,

On Fr, 2016-08-05 at 17:56 -0700, Franky Lin wrote:
> On Fri, Aug 5, 2016 at 2:29 PM, Jörg Krause <joerg.krause@embedded.ro
> cks>
> wrote:
> 
> > 
> > 
> > 
> > Am 5. August 2016 23:01:10 MESZ, schrieb Arend Van Spriel <
> > arend.vanspriel@broadcom.com>:
> > > 
> > > Op 5 aug. 2016 22:46 schreef "Jörg Krause"
> > > <joerg.krause@embedded.rocks>:
> > > > 
> > > > 
> > > > Hi,
> > > > 
> > > > I'm using a custom ARM board with an BCM43362 wifi chip from
> > > Broadcom.
> > > > 
> > > > The wifi chip is attached via SDIO to the controller with a
> > > > clock of
> > > > 48MHz. Linux kernel version is 4.7.
> > > > 
> > > > When measuring the network bandwidth with iperf3 I get a
> > > > bandwith of
> > > > only around 5 Mbps. I found a similar thread at the Broadcom
> > > community
> > > > 
> > > > [1] where the test was done with a M4 CPU + BCM43362 and an
> > > > average
> > > > result of 3.3 Mbps.
> > > > 
> > > > Interestingly, a BCM43362 Wi-Fi Dev Kit [2] notes a TCP data
> > > throughput
> > > > 
> > > > greater than 20 Mbps.
> > > > 
> > > > Why is the throughput I measured much lower? Note that I
> > > > measured
> > > > several times with almost no neighbor devices or networks.
> > > > 
> > > > This is a test sample measured with iperf3:
> > > > 
> > > >     $ iperf3 -c 192.168.2.1 -i 1 -t 10
> > > >     Connecting to host 192.168.2.1, port 5201
> > > >     [  4] local 192.168.2.155 port 36442 connected to
> > > > 192.168.2.1
> > > port
> > > > 
> > > >     5201
> > > >     [ ID]
> > > > Interval           Transfer     Bandwidth       Retr  Cwnd
> > > >     [  4]   0.00-1.00   sec   615 KBytes  5.04
> > > > Mbits/sec    0   56.6
> > > >     KBytes
> > > >     [  4]   1.00-2.00   sec   622 KBytes  5.10
> > > > Mbits/sec    0   84.8
> > > >     KBytes
> > > >     [  4]   2.00-3.00   sec   625 KBytes  5.12
> > > > Mbits/sec    0    113
> > > >     KBytes
> > > >     [  4]   3.00-4.00   sec   571 KBytes  4.68
> > > > Mbits/sec    0    140
> > > >     KBytes
> > > >     [  4]   4.00-5.00   sec   594 KBytes  4.87
> > > > Mbits/sec    0    167
> > > >     KBytes
> > > >     [  4]   5.00-6.00   sec   628 KBytes  5.14
> > > > Mbits/sec    0    195
> > > >     KBytes
> > > >     [  4]   6.00-7.00   sec   619 KBytes  5.07
> > > > Mbits/sec    0    202
> > > >     KBytes
> > > >     [  4]   7.00-8.00   sec   608 KBytes  4.98
> > > > Mbits/sec    0    202
> > > >     KBytes
> > > >     [  4]   8.00-9.00   sec   602 KBytes  4.93
> > > > Mbits/sec    0    202
> > > >     KBytes
> > > >     [  4]   9.00-10.00  sec   537 KBytes  4.40
> > > > Mbits/sec    0    202
> > > >     KBytes
> > > >     - - - - - - - - - - - - - - - - - - - - - - - - -
> > > >     [ ID] Interval           Transfer     Bandwidth       Retr
> > > >     [  4]   0.00-10.00  sec  5.88 MBytes  4.93
> > > >     Mbits/sec    0             sender
> > > >     [  4]   0.00-10.00  sec  5.68 MBytes  4.76
> > > >     Mbits/sec                  receiver
> > > 
> > > Not overly familiar with iperf3. Do these lines mean you are
> > > doing
> > > bidirectional test, ie. upstream and downstream at the same time.
> > > Another
> > > thing affecting tput could be power-save.
> > 
> > No, iperf3 does not support bidrectional test. Power-save is turned
> > off.
> > 
> > What does iw link say?

It says:

# iw dev wlan0 link
Connected to xx:xx:xx:xx:xx (on wlan0)
	SSID: xxx
	freq: 2437
	signal: -60 dBm
	tx bitrate: 58.5 MBit/s

	bss flags:	short-preamble short-slot-time
	dtim period:	1
	beacon int:	100

Best regards
Jörg Krause

^ permalink raw reply

* Re: [RFC][PATCH] RANDOM: ATH9K RNG delivers zero bits of entropy
From: Jason Cooper @ 2016-08-06 20:16 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Ted Tso, herbert, linux-kernel, linux-crypto, ath9k-devel,
	linux-wireless, ath9k-devel, Kalle Valo
In-Reply-To: <6481670.KeU7RXkv1k@myon.chronox.de>

Hi Stephan,

On Sat, Aug 06, 2016 at 10:03:58PM +0200, Stephan Mueller wrote:
> Am Samstag, 6. August 2016, 19:45:51 CEST schrieb Jason Cooper:
> > On Fri, Aug 05, 2016 at 05:08:14PM +0200, Stephan Mueller wrote:
...
> > > diff --git a/drivers/net/wireless/ath/ath9k/rng.c
> > > b/drivers/net/wireless/ath/ath9k/rng.c index d38e50f..d63dc48 100644
> > > --- a/drivers/net/wireless/ath/ath9k/rng.c
> > > +++ b/drivers/net/wireless/ath/ath9k/rng.c
> > > @@ -92,8 +92,7 @@ static int ath9k_rng_kthread(void *data)
> > > 
> > >  		fail_stats = 0;
> > >  		
> > >  		/* sleep until entropy bits under write_wakeup_threshold */
> > > 
> > > -		add_hwgenerator_randomness((void *)rng_buf, bytes_read,
> > > -					   ATH9K_RNG_ENTROPY(bytes_read));
> > 
> > This is the only use of this macro.  I'd remove the #define on line 25
> > as well.
> 
> My idea for leaving it was that folks who would bring the RNG into the 
> hwrandom framework could reuse the ideas from the original authors.
> 
> What about commenting it out with #if 0 ?

#if 0 is frowned upon.  If that calculation is documented somewhere,
then it can be redone from the spec.  If it isn't, then I'd be curious
to know where it came from.

Perhaps one of the ath9k devs can point to a document containing the
formula?  We could put the reference in a comment.

thx,

Jason.

^ permalink raw reply

* Re: [RFC][PATCH] RANDOM: ATH9K RNG delivers zero bits of entropy
From: Stephan Mueller @ 2016-08-06 20:03 UTC (permalink / raw)
  To: Jason Cooper
  Cc: Ted Tso, herbert, linux-kernel, linux-crypto, ath9k-devel,
	linux-wireless, ath9k-devel, Kalle Valo
In-Reply-To: <20160806194551.GA4511@io.lakedaemon.net>

Am Samstag, 6. August 2016, 19:45:51 CEST schrieb Jason Cooper:

Hi Jason,

> Hi Stephan,
> 
> On Fri, Aug 05, 2016 at 05:08:14PM +0200, Stephan Mueller wrote:
> > Hi Ted, Herbert,
> > 
> > I sent a question to the ATH9K RNG some time ago to the developers.
> > See
> > https://www.mail-archive.com/linux-crypto@vger.kernel.org/msg19115.html
> > 
> > I have not yet received a word and I think this issue should be resolved.
> > 
> > Thanks
> > Stephan
> > 
> > ---8<---
> 
> If the above text is placed below the three dashes, "---", below ...
> 
> > The ATH9K driver implements an RNG which is completely bypassing the
> > standard Linux HW generator logic.
> > 
> > The RNG may or may not deliver entropy. Considering the conservative
> > approach in treating entropy with respect to non-auditable sources, this
> > patch changes the delivered entropy value to zero. The RNG still feeds
> > data into the input_pool but it is assumed to have no entropy.
> > 
> > When the ATH9K RNG changes to use the HW RNG framework, it may re-enable
> > the entropy estimation considering that a user can change that value at
> > boot and runtime.
> > 
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> 
> here, then the mail can be applied directly without editing.

Thank you for the hint. I will resend the patch that can be applied.
> 
> >  drivers/net/wireless/ath/ath9k/rng.c | 3 +--
> >  1 file changed, 1 insertion(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/wireless/ath/ath9k/rng.c
> > b/drivers/net/wireless/ath/ath9k/rng.c index d38e50f..d63dc48 100644
> > --- a/drivers/net/wireless/ath/ath9k/rng.c
> > +++ b/drivers/net/wireless/ath/ath9k/rng.c
> > @@ -92,8 +92,7 @@ static int ath9k_rng_kthread(void *data)
> > 
> >  		fail_stats = 0;
> >  		
> >  		/* sleep until entropy bits under write_wakeup_threshold */
> > 
> > -		add_hwgenerator_randomness((void *)rng_buf, bytes_read,
> > -					   ATH9K_RNG_ENTROPY(bytes_read));
> 
> This is the only use of this macro.  I'd remove the #define on line 25
> as well.

My idea for leaving it was that folks who would bring the RNG into the 
hwrandom framework could reuse the ideas from the original authors.

What about commenting it out with #if 0 ?
> 
> > +		add_hwgenerator_randomness((void *)rng_buf, bytes_read, 0);
> > 
> >  	}
> >  	
> >  	kfree(rng_buf);
> 
> Other than that,
> 
> Reviewed-by: Jason Cooper <jason@lakedaemon.net>

Thank you.
> 
> thx,
> 
> Jason.



-- 
Ciao
Stephan

^ permalink raw reply

* Re: [RFC][PATCH] RANDOM: ATH9K RNG delivers zero bits of entropy
From: Jason Cooper @ 2016-08-06 19:45 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Ted Tso, herbert, linux-kernel, linux-crypto, ath9k-devel,
	linux-wireless, ath9k-devel, Kalle Valo
In-Reply-To: <34197429.2CvoIfft9B@positron.chronox.de>

Hi Stephan,

On Fri, Aug 05, 2016 at 05:08:14PM +0200, Stephan Mueller wrote:
> Hi Ted, Herbert,
> 
> I sent a question to the ATH9K RNG some time ago to the developers.
> See https://www.mail-archive.com/linux-crypto@vger.kernel.org/msg19115.html
> 
> I have not yet received a word and I think this issue should be resolved.
> 
> Thanks
> Stephan
> 
> ---8<---

If the above text is placed below the three dashes, "---", below ...

> The ATH9K driver implements an RNG which is completely bypassing the
> standard Linux HW generator logic.
> 
> The RNG may or may not deliver entropy. Considering the conservative
> approach in treating entropy with respect to non-auditable sources, this
> patch changes the delivered entropy value to zero. The RNG still feeds
> data into the input_pool but it is assumed to have no entropy.
> 
> When the ATH9K RNG changes to use the HW RNG framework, it may re-enable
> the entropy estimation considering that a user can change that value at
> boot and runtime.
> 
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---

here, then the mail can be applied directly without editing.

>  drivers/net/wireless/ath/ath9k/rng.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c
> index d38e50f..d63dc48 100644
> --- a/drivers/net/wireless/ath/ath9k/rng.c
> +++ b/drivers/net/wireless/ath/ath9k/rng.c
> @@ -92,8 +92,7 @@ static int ath9k_rng_kthread(void *data)
>  		fail_stats = 0;
>  
>  		/* sleep until entropy bits under write_wakeup_threshold */
> -		add_hwgenerator_randomness((void *)rng_buf, bytes_read,
> -					   ATH9K_RNG_ENTROPY(bytes_read));

This is the only use of this macro.  I'd remove the #define on line 25
as well.

> +		add_hwgenerator_randomness((void *)rng_buf, bytes_read, 0);
>  	}
>  
>  	kfree(rng_buf);

Other than that,

Reviewed-by: Jason Cooper <jason@lakedaemon.net>

thx,

Jason.

^ permalink raw reply

* Re: TCP data throughput for BCM43362
From: Jörg Krause @ 2016-08-05 21:29 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Brett Rudley, brcm80211-dev-list, Hante Meuleman, Franky Lin,
	linux-wireless, Arend van Spriel
In-Reply-To: <CAF7Mx6o+WuQqtzuApMWQ8YAkLSX7xQ_H06xmO--RxFdwHwzLdQ@mail.gmail.com>



Am 5. August 2016 23:01:10 MESZ, schrieb Arend Van Spriel <arend.vanspriel@broadcom.com>:
>Op 5 aug. 2016 22:46 schreef "Jörg Krause"
><joerg.krause@embedded.rocks>:
>>
>> Hi,
>>
>> I'm using a custom ARM board with an BCM43362 wifi chip from
>Broadcom.
>> The wifi chip is attached via SDIO to the controller with a clock of
>> 48MHz. Linux kernel version is 4.7.
>>
>> When measuring the network bandwidth with iperf3 I get a bandwith of
>> only around 5 Mbps. I found a similar thread at the Broadcom
>community
>> [1] where the test was done with a M4 CPU + BCM43362 and an average
>> result of 3.3 Mbps.
>>
>> Interestingly, a BCM43362 Wi-Fi Dev Kit [2] notes a TCP data
>throughput
>> greater than 20 Mbps.
>>
>> Why is the throughput I measured much lower? Note that I measured
>> several times with almost no neighbor devices or networks.
>>
>> This is a test sample measured with iperf3:
>>
>>     $ iperf3 -c 192.168.2.1 -i 1 -t 10
>>     Connecting to host 192.168.2.1, port 5201
>>     [  4] local 192.168.2.155 port 36442 connected to 192.168.2.1
>port
>>     5201
>>     [ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
>>     [  4]   0.00-1.00   sec   615 KBytes  5.04 Mbits/sec    0   56.6
>>     KBytes
>>     [  4]   1.00-2.00   sec   622 KBytes  5.10 Mbits/sec    0   84.8
>>     KBytes
>>     [  4]   2.00-3.00   sec   625 KBytes  5.12 Mbits/sec    0    113
>>     KBytes
>>     [  4]   3.00-4.00   sec   571 KBytes  4.68 Mbits/sec    0    140
>>     KBytes
>>     [  4]   4.00-5.00   sec   594 KBytes  4.87 Mbits/sec    0    167
>>     KBytes
>>     [  4]   5.00-6.00   sec   628 KBytes  5.14 Mbits/sec    0    195
>>     KBytes
>>     [  4]   6.00-7.00   sec   619 KBytes  5.07 Mbits/sec    0    202
>>     KBytes
>>     [  4]   7.00-8.00   sec   608 KBytes  4.98 Mbits/sec    0    202
>>     KBytes
>>     [  4]   8.00-9.00   sec   602 KBytes  4.93 Mbits/sec    0    202
>>     KBytes
>>     [  4]   9.00-10.00  sec   537 KBytes  4.40 Mbits/sec    0    202
>>     KBytes
>>     - - - - - - - - - - - - - - - - - - - - - - - - -
>>     [ ID] Interval           Transfer     Bandwidth       Retr
>>     [  4]   0.00-10.00  sec  5.88 MBytes  4.93
>>     Mbits/sec    0             sender
>>     [  4]   0.00-10.00  sec  5.68 MBytes  4.76
>>     Mbits/sec                  receiver
>
>Not overly familiar with iperf3. Do these lines mean you are doing
>bidirectional test, ie. upstream and downstream at the same time.
>Another
>thing affecting tput could be power-save.

No, iperf3 does not support bidrectional test. Power-save is turned off.


^ permalink raw reply

* TCP data throughput for BCM43362
From: Jörg Krause @ 2016-08-05 20:46 UTC (permalink / raw)
  To: linux-wireless
  Cc: brcm80211-dev-list, Brett Rudley, Arend van Spriel, Franky Lin,
	Hante Meuleman

Hi,

I'm using a custom ARM board with an BCM43362 wifi chip from Broadcom.
The wifi chip is attached via SDIO to the controller with a clock of
48MHz. Linux kernel version is 4.7.

When measuring the network bandwidth with iperf3 I get a bandwith of
only around 5 Mbps. I found a similar thread at the Broadcom community
[1] where the test was done with a M4 CPU + BCM43362 and an average
result of 3.3 Mbps.

Interestingly, a BCM43362 Wi-Fi Dev Kit [2] notes a TCP data throughput
greater than 20 Mbps.

Why is the throughput I measured much lower? Note that I measured
several times with almost no neighbor devices or networks.

This is a test sample measured with iperf3:

    $ iperf3 -c 192.168.2.1 -i 1 -t 10
    Connecting to host 192.168.2.1, port 5201
    [  4] local 192.168.2.155 port 36442 connected to 192.168.2.1 port
    5201
    [ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
    [  4]   0.00-1.00   sec   615 KBytes  5.04 Mbits/sec    0   56.6
    KBytes       
    [  4]   1.00-2.00   sec   622 KBytes  5.10 Mbits/sec    0   84.8
    KBytes       
    [  4]   2.00-3.00   sec   625 KBytes  5.12 Mbits/sec    0    113
    KBytes       
    [  4]   3.00-4.00   sec   571 KBytes  4.68 Mbits/sec    0    140
    KBytes       
    [  4]   4.00-5.00   sec   594 KBytes  4.87 Mbits/sec    0    167
    KBytes       
    [  4]   5.00-6.00   sec   628 KBytes  5.14 Mbits/sec    0    195
    KBytes       
    [  4]   6.00-7.00   sec   619 KBytes  5.07 Mbits/sec    0    202
    KBytes       
    [  4]   7.00-8.00   sec   608 KBytes  4.98 Mbits/sec    0    202
    KBytes       
    [  4]   8.00-9.00   sec   602 KBytes  4.93 Mbits/sec    0    202
    KBytes       
    [  4]   9.00-10.00  sec   537 KBytes  4.40 Mbits/sec    0    202
    KBytes       
    - - - - - - - - - - - - - - - - - - - - - - - - -
    [ ID] Interval           Transfer     Bandwidth       Retr
    [  4]   0.00-10.00  sec  5.88 MBytes  4.93
    Mbits/sec    0             sender
    [  4]   0.00-10.00  sec  5.68 MBytes  4.76
    Mbits/sec                  receiver

[1] https://community.broadcom.com/thread/3978
[2] http://www.mouser.de/new/broadcom/broadcom-bcm943362wcd4/

Best regards
Jörg Krause

^ permalink raw reply

* [PATCH 1/1] brcmfmac: fix pmksa->bssid usage
From: Nicolas Iooss @ 2016-08-05 20:34 UTC (permalink / raw)
  To: Arend van Spriel, Franky Lin, Hante Meuleman, linux-wireless,
	brcm80211-dev-list.pdl
  Cc: netdev, linux-kernel, Nicolas Iooss

The struct cfg80211_pmksa defines its bssid field as:

    const u8 *bssid;

contrary to struct brcmf_pmksa, which uses:

    u8 bssid[ETH_ALEN];

Therefore in brcmf_cfg80211_del_pmksa(), &pmksa->bssid takes the address
of this field (of type u8**), not the one of its content (which would be
u8*).  Remove the & operator to make brcmf_dbg("%pM") and memcmp()
behave as expected.

This bug have been found using a custom static checker (which checks the
usage of %p... attributes at build time).  It has been introduced in
commit 6c404f34f2bd ("brcmfmac: Cleanup pmksa cache handling code"),
which replaced pmksa->bssid by &pmksa->bssid while refactoring the code,
without modifying struct cfg80211_pmksa definition.

Fixes: 6c404f34f2bd ("brcmfmac: Cleanup pmksa cache handling code")
Cc: stable@ger.kernel.org
Signed-off-by: Nicolas Iooss <nicolas.iooss_linux@m4x.org>
---

scripts/checkpatch.pl reports a warning: "Prefer ether_addr_equal() or
ether_addr_equal_unaligned() over memcmp()".  Because some files in
drivers/net/wireless/broadcom/brcm80211/brcmfmac/ still use memcmp()
to compare addresses and because I do not know whether pmksa->bssid is
always aligned, I did not follow this warning.

 drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 2628d5e12c64..aceab77cd95a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -3884,11 +3884,11 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
 	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
-	brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", &pmksa->bssid);
+	brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", pmksa->bssid);
 
 	npmk = le32_to_cpu(cfg->pmk_list.npmk);
 	for (i = 0; i < npmk; i++)
-		if (!memcmp(&pmksa->bssid, &pmk[i].bssid, ETH_ALEN))
+		if (!memcmp(pmksa->bssid, &pmk[i].bssid, ETH_ALEN))
 			break;
 
 	if ((npmk > 0) && (i < npmk)) {
-- 
2.9.2


^ permalink raw reply related

* [PATCH] Staging: rtl8723au: rtw_ieee80211: Fixed operators spacing style issues
From: Shiva Kerdel @ 2016-08-05 20:14 UTC (permalink / raw)
  To: Larry.Finger
  Cc: Jes.Sorensen, gregkh, amsfield22, linux-wireless, devel,
	linux-kernel, Shiva Kerdel

Fixed spaces around operators to fix their coding style issues.

Signed-off-by: Shiva Kerdel <shiva@exdev.nl>
---
 drivers/staging/rtl8723au/core/rtw_ieee80211.c | 80 +++++++++++++-------------
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
index 07a6490..9fa0ef1 100644
--- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
@@ -65,7 +65,7 @@ static u8 WIFI_OFDMRATES[] = {
 
 int rtw_get_bit_value_from_ieee_value23a(u8 val)
 {
-	unsigned char dot11_rate_table[]=
+	unsigned char dot11_rate_table[] =
 		{2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0};
 
 	int i = 0;
@@ -140,7 +140,7 @@ u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen)
 	return pbuf + len + 2;
 }
 
-inline u8 *rtw_set_ie23a_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode,
+inline u8 *rtw_set_ie23a_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode,
 				u8 new_ch, u8 ch_switch_cnt)
 {
 	u8 ie_data[3];
@@ -230,14 +230,14 @@ u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len,
 
 	while (cnt < in_len) {
 		if (eid == in_ie[cnt] &&
-		    (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) {
+		    (!oui || !memcmp(&in_ie[cnt + 2], oui, oui_len))) {
 			target_ie = &in_ie[cnt];
 
 			if (ie)
-				memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2);
+				memcpy(ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
 
 			if (ielen)
-				*ielen = in_ie[cnt+1]+2;
+				*ielen = in_ie[cnt + 1] + 2;
 			break;
 		} else {
 			cnt += in_ie[cnt + 1] + 2; /* goto next */
@@ -331,7 +331,7 @@ uint rtw_get_rateset_len23a(u8 *rateset)
 {
 	uint i = 0;
 
-	while(1) {
+	while (1) {
 		if (rateset[i] == 0)
 			break;
 
@@ -378,7 +378,7 @@ int rtw_generate_ie23a(struct registry_priv *pregistrypriv)
 		wireless_mode = pregistrypriv->wireless_mode;
 	}
 
-	rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode) ;
+	rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode);
 
 	rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates);
 
@@ -533,7 +533,7 @@ int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
 		return _FAIL;
 	}
 
-	if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie+1) != (u8)(rsn_ie_len - 2)) {
+	if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie + 1) != (u8)(rsn_ie_len - 2)) {
 		return _FAIL;
 	}
 
@@ -791,64 +791,64 @@ u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40,
 
 	if (rf_type == RF_1T1R) {
 		if (mcs->rx_mask[0] & BIT(7))
-			max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):
-				((short_GI_20)?722:650);
+			max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) :
+				((short_GI_20) ? 722 : 650);
 		else if (mcs->rx_mask[0] & BIT(6))
-			max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):
-				((short_GI_20)?650:585);
+			max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) :
+				((short_GI_20) ? 650 : 585);
 		else if (mcs->rx_mask[0] & BIT(5))
-			max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):
-				((short_GI_20)?578:520);
+			max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) :
+				((short_GI_20) ? 578 : 520);
 		else if (mcs->rx_mask[0] & BIT(4))
-			max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):
-				((short_GI_20)?433:390);
+			max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) :
+				((short_GI_20) ? 433 : 390);
 		else if (mcs->rx_mask[0] & BIT(3))
-			max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):
-				((short_GI_20)?289:260);
+			max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) :
+				((short_GI_20) ? 289 : 260);
 		else if (mcs->rx_mask[0] & BIT(2))
-			max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):
-				((short_GI_20)?217:195);
+			max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) :
+				((short_GI_20) ? 217 : 195);
 		else if (mcs->rx_mask[0] & BIT(1))
-			max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):
-				((short_GI_20)?144:130);
+			max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) :
+				((short_GI_20) ? 144 : 130);
 		else if (mcs->rx_mask[0] & BIT(0))
-			max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):
-				((short_GI_20)?72:65);
+			max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) :
+				((short_GI_20) ? 72 : 65);
 	} else {
 		if (mcs->rx_mask[1]) {
 			if (mcs->rx_mask[1] & BIT(7))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 3000 : 2700) : ((short_GI_20) ? 1444 : 1300);
 			else if (mcs->rx_mask[1] & BIT(6))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 2700 : 2430) : ((short_GI_20) ? 1300 : 1170);
 			else if (mcs->rx_mask[1] & BIT(5))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 2400 : 2160) : ((short_GI_20) ? 1156 : 1040);
 			else if (mcs->rx_mask[1] & BIT(4))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 1800 : 1620) : ((short_GI_20) ? 867 : 780);
 			else if (mcs->rx_mask[1] & BIT(3))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
 			else if (mcs->rx_mask[1] & BIT(2))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
 			else if (mcs->rx_mask[1] & BIT(1))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
 			else if (mcs->rx_mask[1] & BIT(0))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
 		} else {
 			if (mcs->rx_mask[0] & BIT(7))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
 			else if (mcs->rx_mask[0] & BIT(6))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
 			else if (mcs->rx_mask[0] & BIT(5))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
 			else if (mcs->rx_mask[0] & BIT(4))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
 			else if (mcs->rx_mask[0] & BIT(3))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
 			else if (mcs->rx_mask[0] & BIT(2))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
 			else if (mcs->rx_mask[0] & BIT(1))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
 			else if (mcs->rx_mask[0] & BIT(0))
-				max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65);
+				max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
 		}
 	}
 	return max_rate;
-- 
2.9.2


^ permalink raw reply related

* Re: [PATCH] ath10k: hide kernel addresses from logs using %pK format specifier
From: Joe Perches @ 2016-08-05 17:57 UTC (permalink / raw)
  To: c_mkenna, ath10k, Andrew Morton; +Cc: linux-wireless, mkenna, Kees Cook, LKML
In-Reply-To: <1470318711-28986-1-git-send-email-c_mkenna@qti.qualcomm.com>

On Thu, 2016-08-04 at 19:21 +0530, c_mkenna@qti.qualcomm.com wrote:
> From: Maharaja Kennadyrajan <c_mkenna@qti.qualcomm.com>
> 
> With the %pK format specifier we hide the kernel addresses
> with the help of kptr_restrict sysctl.
> In this patch, %p is changed to %pK in the driver code.
> 
> The sysctl is documented in Documentation/sysctl/kernel.txt.

Maybe %p should follow %pK and only show kernel .text addresses
by default and any other address as 0 unless the sysctl is set.


^ permalink raw reply

* [PATCH v4] ath9k: Switch to using mac80211 intermediate software queues.
From: Toke Høiland-Jørgensen @ 2016-08-05 16:03 UTC (permalink / raw)
  To: linux-wireless, make-wifi-fast, ath9k-devel
  Cc: Toke Høiland-Jørgensen, Tim Shepard, Felix Fietkau
In-Reply-To: <20160706193417.13080-1-toke@toke.dk>

This switches ath9k over to using the mac80211 intermediate software
queueing mechanism for data packets. It removes the queueing inside the
driver, except for the retry queue, and instead pulls from mac80211 when
a packet is needed. The retry queue is used to store a packet that was
pulled but can't be sent immediately.

The old code path in ath_tx_start that would queue packets has been
removed completely, as has the qlen limit tunables (since there's no
longer a queue in the driver to limit).

Based on Tim's original patch set, but reworked quite thoroughly.

Cc: Tim Shepard <shep@alum.mit.edu>
Cc: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
Changes since v3 (most due to Felix; thanks!):
  - Correctly notify mac80211 when there are packets in the retry queue
    on powersave start/stop.
  - Get rid of ath_tx_aggr_resume().
  - Some readability changes and additional WARN_ON/BUG_ON in
    appropriate places.
    
 drivers/net/wireless/ath/ath9k/ath9k.h     |  27 ++-
 drivers/net/wireless/ath/ath9k/channel.c   |   2 -
 drivers/net/wireless/ath/ath9k/debug.c     |  14 +-
 drivers/net/wireless/ath/ath9k/debug.h     |   2 -
 drivers/net/wireless/ath/ath9k/debug_sta.c |   4 +-
 drivers/net/wireless/ath/ath9k/init.c      |   2 +-
 drivers/net/wireless/ath/ath9k/main.c      |   9 +-
 drivers/net/wireless/ath/ath9k/xmit.c      | 332 +++++++++++------------------
 8 files changed, 157 insertions(+), 235 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 5294595..7e0a976 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -91,7 +91,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 #define ATH_RXBUF               512
 #define ATH_TXBUF               512
 #define ATH_TXBUF_RESERVE       5
-#define ATH_MAX_QDEPTH          (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
 #define ATH_TXMAXTRY            13
 #define ATH_MAX_SW_RETRIES      30
 
@@ -145,7 +144,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 #define BAW_WITHIN(_start, _bawsz, _seqno) \
 	((((_seqno) - (_start)) & 4095) < (_bawsz))
 
-#define ATH_AN_2_TID(_an, _tidno)  (&(_an)->tid[(_tidno)])
+#define ATH_AN_2_TID(_an, _tidno) ath_node_to_tid(_an, _tidno)
 
 #define IS_HT_RATE(rate)   (rate & 0x80)
 #define IS_CCK_RATE(rate)  ((rate >= 0x18) && (rate <= 0x1e))
@@ -164,7 +163,6 @@ struct ath_txq {
 	spinlock_t axq_lock;
 	u32 axq_depth;
 	u32 axq_ampdu_depth;
-	bool stopped;
 	bool axq_tx_inprogress;
 	struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
 	u8 txq_headidx;
@@ -232,7 +230,6 @@ struct ath_buf {
 
 struct ath_atx_tid {
 	struct list_head list;
-	struct sk_buff_head buf_q;
 	struct sk_buff_head retry_q;
 	struct ath_node *an;
 	struct ath_txq *txq;
@@ -247,13 +244,13 @@ struct ath_atx_tid {
 	s8 bar_index;
 	bool active;
 	bool clear_ps_filter;
+	bool has_queued;
 };
 
 struct ath_node {
 	struct ath_softc *sc;
 	struct ieee80211_sta *sta; /* station struct we're part of */
 	struct ieee80211_vif *vif; /* interface with which we're associated */
-	struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
 
 	u16 maxampdu;
 	u8 mpdudensity;
@@ -276,7 +273,6 @@ struct ath_tx_control {
 	struct ath_node *an;
 	struct ieee80211_sta *sta;
 	u8 paprd;
-	bool force_channel;
 };
 
 
@@ -293,7 +289,6 @@ struct ath_tx {
 	struct ath_descdma txdma;
 	struct ath_txq *txq_map[IEEE80211_NUM_ACS];
 	struct ath_txq *uapsdq;
-	u32 txq_max_pending[IEEE80211_NUM_ACS];
 	u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32];
 };
 
@@ -421,6 +416,22 @@ struct ath_offchannel {
 	int duration;
 };
 
+static inline struct ath_atx_tid *
+ath_node_to_tid(struct ath_node *an, u8 tidno)
+{
+	struct ieee80211_sta *sta = an->sta;
+	struct ieee80211_vif *vif = an->vif;
+	struct ieee80211_txq *txq;
+
+	BUG_ON(!vif);
+	if (sta)
+		txq = sta->txq[tidno % ARRAY_SIZE(sta->txq)];
+	else
+		txq = vif->txq;
+
+	return (struct ath_atx_tid *) txq->drv_priv;
+}
+
 #define case_rtn_string(val) case val: return #val
 
 #define ath_for_each_chanctx(_sc, _ctx)                             \
@@ -575,7 +586,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc);
 int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
 		      u16 tid, u16 *ssn);
 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
 
 void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
 void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
@@ -585,6 +595,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
 				   u16 tids, int nframes,
 				   enum ieee80211_frame_release_type reason,
 				   bool more_data);
+void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue);
 
 /********/
 /* VIFs */
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 319cb5f..a5ce016 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -1007,7 +1007,6 @@ static void ath_scan_send_probe(struct ath_softc *sc,
 		goto error;
 
 	txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
-	txctl.force_channel = true;
 	if (ath_tx_start(sc->hw, skb, &txctl))
 		goto error;
 
@@ -1130,7 +1129,6 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
 	memset(&txctl, 0, sizeof(txctl));
 	txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
 	txctl.sta = sta;
-	txctl.force_channel = true;
 	if (ath_tx_start(sc->hw, skb, &txctl)) {
 		ieee80211_free_txskb(sc->hw, skb);
 		return false;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 6de64cf..48b181d 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -600,7 +600,6 @@ static int read_file_xmit(struct seq_file *file, void *data)
 	PR("MPDUs XRetried:  ", xretries);
 	PR("Aggregates:      ", a_aggr);
 	PR("AMPDUs Queued HW:", a_queued_hw);
-	PR("AMPDUs Queued SW:", a_queued_sw);
 	PR("AMPDUs Completed:", a_completed);
 	PR("AMPDUs Retried:  ", a_retries);
 	PR("AMPDUs XRetried: ", a_xretries);
@@ -629,8 +628,7 @@ static void print_queue(struct ath_softc *sc, struct ath_txq *txq,
 	seq_printf(file, "%s: %d ", "qnum", txq->axq_qnum);
 	seq_printf(file, "%s: %2d ", "qdepth", txq->axq_depth);
 	seq_printf(file, "%s: %2d ", "ampdu-depth", txq->axq_ampdu_depth);
-	seq_printf(file, "%s: %3d ", "pending", txq->pending_frames);
-	seq_printf(file, "%s: %d\n", "stopped", txq->stopped);
+	seq_printf(file, "%s: %3d\n", "pending", txq->pending_frames);
 
 	ath_txq_unlock(sc, txq);
 }
@@ -1190,7 +1188,6 @@ static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = {
 	AMKSTR(d_tx_mpdu_xretries),
 	AMKSTR(d_tx_aggregates),
 	AMKSTR(d_tx_ampdus_queued_hw),
-	AMKSTR(d_tx_ampdus_queued_sw),
 	AMKSTR(d_tx_ampdus_completed),
 	AMKSTR(d_tx_ampdu_retries),
 	AMKSTR(d_tx_ampdu_xretries),
@@ -1270,7 +1267,6 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
 	AWDATA(xretries);
 	AWDATA(a_aggr);
 	AWDATA(a_queued_hw);
-	AWDATA(a_queued_sw);
 	AWDATA(a_completed);
 	AWDATA(a_retries);
 	AWDATA(a_xretries);
@@ -1328,14 +1324,6 @@ int ath9k_init_debug(struct ath_hw *ah)
 				    read_file_xmit);
 	debugfs_create_devm_seqfile(sc->dev, "queues", sc->debug.debugfs_phy,
 				    read_file_queues);
-	debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-			   &sc->tx.txq_max_pending[IEEE80211_AC_BK]);
-	debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-			   &sc->tx.txq_max_pending[IEEE80211_AC_BE]);
-	debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-			   &sc->tx.txq_max_pending[IEEE80211_AC_VI]);
-	debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-			   &sc->tx.txq_max_pending[IEEE80211_AC_VO]);
 	debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy,
 				    read_file_misc);
 	debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index cd68c5f..a078cdd 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -147,7 +147,6 @@ struct ath_interrupt_stats {
  * @completed: Total MPDUs (non-aggr) completed
  * @a_aggr: Total no. of aggregates queued
  * @a_queued_hw: Total AMPDUs queued to hardware
- * @a_queued_sw: Total AMPDUs queued to software queues
  * @a_completed: Total AMPDUs completed
  * @a_retries: No. of AMPDUs retried (SW)
  * @a_xretries: No. of AMPDUs dropped due to xretries
@@ -174,7 +173,6 @@ struct ath_tx_stats {
 	u32 xretries;
 	u32 a_aggr;
 	u32 a_queued_hw;
-	u32 a_queued_sw;
 	u32 a_completed;
 	u32 a_retries;
 	u32 a_xretries;
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c
index c2ca57a..2e8371a 100644
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
@@ -52,8 +52,8 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
 			 "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
 			 "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
 
-	for (tidno = 0, tid = &an->tid[tidno];
-	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
+	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+		tid = ath_node_to_tid(an, tidno);
 		txq = tid->txq;
 		ath_txq_lock(sc, txq);
 		if (tid->active) {
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 1c226d6..752cacb 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -354,7 +354,6 @@ static int ath9k_init_queues(struct ath_softc *sc)
 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
 		sc->tx.txq_map[i]->mac80211_qnum = i;
-		sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH;
 	}
 	return 0;
 }
@@ -867,6 +866,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 	hw->max_rate_tries = 10;
 	hw->sta_data_size = sizeof(struct ath_node);
 	hw->vif_data_size = sizeof(struct ath_vif);
+	hw->txq_data_size = sizeof(struct ath_atx_tid);
 	hw->extra_tx_headroom = 4;
 
 	hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 3aed43a..eb48f91 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1874,9 +1874,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 	bool flush = false;
 	int ret = 0;
 	struct ieee80211_sta *sta = params->sta;
+	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 	enum ieee80211_ampdu_mlme_action action = params->action;
 	u16 tid = params->tid;
 	u16 *ssn = &params->ssn;
+	struct ath_atx_tid *atid;
 
 	mutex_lock(&sc->mutex);
 
@@ -1909,9 +1911,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 		ath9k_ps_restore(sc);
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		ath9k_ps_wakeup(sc);
-		ath_tx_aggr_resume(sc, sta, tid);
-		ath9k_ps_restore(sc);
+		atid = ath_node_to_tid(an, tid);
+		atid->baw_size = IEEE80211_MIN_AMPDU_BUF <<
+			        sta->ht_cap.ampdu_factor;
 		break;
 	default:
 		ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n");
@@ -2673,4 +2675,5 @@ struct ieee80211_ops ath9k_ops = {
 	.sw_scan_start	    = ath9k_sw_scan_start,
 	.sw_scan_complete   = ath9k_sw_scan_complete,
 	.get_txpower        = ath9k_get_txpower,
+	.wake_tx_queue      = ath9k_wake_tx_queue,
 };
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index fe795fc..8103954 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -65,6 +65,8 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
 					   struct ath_txq *txq,
 					   struct ath_atx_tid *tid,
 					   struct sk_buff *skb);
+static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb,
+			  struct ath_tx_control *txctl);
 
 enum {
 	MCS_HT20,
@@ -118,6 +120,26 @@ static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
 		list_add_tail(&tid->list, list);
 }
 
+void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_atx_tid *tid = (struct ath_atx_tid *) queue->drv_priv;
+	struct ath_txq *txq = tid->txq;
+
+	ath_dbg(common, QUEUE, "Waking TX queue: %pM (%d)\n",
+		queue->sta ? queue->sta->addr : queue->vif->addr,
+		tid->tidno);
+
+	ath_txq_lock(sc, txq);
+
+	tid->has_queued = true;
+	ath_tx_queue_tid(sc, txq, tid);
+	ath_txq_schedule(sc, txq);
+
+	ath_txq_unlock(sc, txq);
+}
+
 static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -145,7 +167,6 @@ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
 static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
 			     struct sk_buff *skb)
 {
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ath_frame_info *fi = get_frame_info(skb);
 	int q = fi->txq;
 
@@ -156,14 +177,6 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
 	if (WARN_ON(--txq->pending_frames < 0))
 		txq->pending_frames = 0;
 
-	if (txq->stopped &&
-	    txq->pending_frames < sc->tx.txq_max_pending[q]) {
-		if (ath9k_is_chanctx_enabled())
-			ieee80211_wake_queue(sc->hw, info->hw_queue);
-		else
-			ieee80211_wake_queue(sc->hw, q);
-		txq->stopped = false;
-	}
 }
 
 static struct ath_atx_tid *
@@ -173,9 +186,48 @@ ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb)
 	return ATH_AN_2_TID(an, tidno);
 }
 
+static struct sk_buff *
+ath_tid_pull(struct ath_atx_tid *tid)
+{
+	struct ieee80211_txq *txq = container_of((void*)tid, struct ieee80211_txq, drv_priv);
+	struct ath_softc *sc = tid->an->sc;
+	struct ieee80211_hw *hw = sc->hw;
+	struct ath_tx_control txctl = {
+		.txq = tid->txq,
+		.sta = tid->an->sta,
+	};
+	struct sk_buff *skb;
+	struct ath_frame_info *fi;
+	int q;
+
+	if (!tid->has_queued)
+		return NULL;
+
+	skb = ieee80211_tx_dequeue(hw, txq);
+	if (!skb) {
+		tid->has_queued = false;
+		return NULL;
+	}
+
+	if (ath_tx_prepare(hw, skb, &txctl)) {
+		ieee80211_free_txskb(hw, skb);
+		return NULL;
+	}
+
+	q = skb_get_queue_mapping(skb);
+	if (tid->txq == sc->tx.txq_map[q]) {
+		fi = get_frame_info(skb);
+		fi->txq = q;
+		++tid->txq->pending_frames;
+	}
+
+	return skb;
+ }
+
+
 static bool ath_tid_has_buffered(struct ath_atx_tid *tid)
 {
-	return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q);
+	return !skb_queue_empty(&tid->retry_q) || tid->has_queued;
 }
 
 static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
@@ -184,46 +236,11 @@ static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
 
 	skb = __skb_dequeue(&tid->retry_q);
 	if (!skb)
-		skb = __skb_dequeue(&tid->buf_q);
+		skb = ath_tid_pull(tid);
 
 	return skb;
 }
 
-/*
- * ath_tx_tid_change_state:
- * - clears a-mpdu flag of previous session
- * - force sequence number allocation to fix next BlockAck Window
- */
-static void
-ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
-	struct ath_txq *txq = tid->txq;
-	struct ieee80211_tx_info *tx_info;
-	struct sk_buff *skb, *tskb;
-	struct ath_buf *bf;
-	struct ath_frame_info *fi;
-
-	skb_queue_walk_safe(&tid->buf_q, skb, tskb) {
-		fi = get_frame_info(skb);
-		bf = fi->bf;
-
-		tx_info = IEEE80211_SKB_CB(skb);
-		tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-
-		if (bf)
-			continue;
-
-		bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-		if (!bf) {
-			__skb_unlink(skb, &tid->buf_q);
-			ath_txq_skb_done(sc, txq, skb);
-			ieee80211_free_txskb(sc->hw, skb);
-			continue;
-		}
-	}
-
-}
-
 static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
 	struct ath_txq *txq = tid->txq;
@@ -858,20 +875,16 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
 
 static struct ath_buf *
 ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
-			struct ath_atx_tid *tid, struct sk_buff_head **q)
+			struct ath_atx_tid *tid)
 {
 	struct ieee80211_tx_info *tx_info;
 	struct ath_frame_info *fi;
-	struct sk_buff *skb;
+	struct sk_buff *skb, *first_skb = NULL;
 	struct ath_buf *bf;
 	u16 seqno;
 
 	while (1) {
-		*q = &tid->retry_q;
-		if (skb_queue_empty(*q))
-			*q = &tid->buf_q;
-
-		skb = skb_peek(*q);
+		skb = ath_tid_dequeue(tid);
 		if (!skb)
 			break;
 
@@ -883,7 +896,6 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
 			bf->bf_state.stale = false;
 
 		if (!bf) {
-			__skb_unlink(skb, *q);
 			ath_txq_skb_done(sc, txq, skb);
 			ieee80211_free_txskb(sc->hw, skb);
 			continue;
@@ -912,8 +924,20 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
 		seqno = bf->bf_state.seqno;
 
 		/* do not step over block-ack window */
-		if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno))
+		if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
+			__skb_queue_tail(&tid->retry_q, skb);
+
+			/* If there are other skbs in the retry q, they are
+			 * probably within the BAW, so loop immediately to get
+			 * one of them. Otherwise the queue can get stuck. */
+			if (!skb_queue_is_first(&tid->retry_q, skb) &&
+			    !WARN_ON(skb == first_skb)) {
+				if(!first_skb) /* infinite loop prevention */
+					first_skb = skb;
+				continue;
+			}
 			break;
+		}
 
 		if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
 			struct ath_tx_status ts = {};
@@ -921,7 +945,6 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
 
 			INIT_LIST_HEAD(&bf_head);
 			list_add(&bf->list, &bf_head);
-			__skb_unlink(skb, *q);
 			ath_tx_update_baw(sc, tid, seqno);
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
 			continue;
@@ -933,11 +956,10 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
 	return NULL;
 }
 
-static bool
+static int
 ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
 		 struct ath_atx_tid *tid, struct list_head *bf_q,
-		 struct ath_buf *bf_first, struct sk_buff_head *tid_q,
-		 int *aggr_len)
+		 struct ath_buf *bf_first)
 {
 #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
 	struct ath_buf *bf = bf_first, *bf_prev = NULL;
@@ -947,12 +969,13 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	struct ieee80211_tx_info *tx_info;
 	struct ath_frame_info *fi;
 	struct sk_buff *skb;
-	bool closed = false;
+
 
 	bf = bf_first;
 	aggr_limit = ath_lookup_rate(sc, bf, tid);
 
-	do {
+	while (bf)
+	{
 		skb = bf->bf_mpdu;
 		fi = get_frame_info(skb);
 
@@ -961,12 +984,12 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
 		if (nframes) {
 			if (aggr_limit < al + bpad + al_delta ||
 			    ath_lookup_legacy(bf) || nframes >= h_baw)
-				break;
+				goto stop;
 
 			tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
 			if ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
 			    !(tx_info->flags & IEEE80211_TX_CTL_AMPDU))
-				break;
+				goto stop;
 		}
 
 		/* add padding for previous frame to aggregation length */
@@ -988,20 +1011,18 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
 			ath_tx_addto_baw(sc, tid, bf);
 		bf->bf_state.ndelim = ndelim;
 
-		__skb_unlink(skb, tid_q);
 		list_add_tail(&bf->list, bf_q);
 		if (bf_prev)
 			bf_prev->bf_next = bf;
 
 		bf_prev = bf;
 
-		bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
-		if (!bf) {
-			closed = true;
-			break;
-		}
-	} while (ath_tid_has_buffered(tid));
-
+		bf = ath_tx_get_tid_subframe(sc, txq, tid);
+	}
+	goto finish;
+stop:
+	__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
+finish:
 	bf = bf_first;
 	bf->bf_lastbf = bf_prev;
 
@@ -1012,9 +1033,7 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
 		TX_STAT_INC(txq->axq_qnum, a_aggr);
 	}
 
-	*aggr_len = al;
-
-	return closed;
+	return al;
 #undef PADBYTES
 }
 
@@ -1391,18 +1410,15 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
 static void
 ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
 		  struct ath_atx_tid *tid, struct list_head *bf_q,
-		  struct ath_buf *bf_first, struct sk_buff_head *tid_q)
+		  struct ath_buf *bf_first)
 {
 	struct ath_buf *bf = bf_first, *bf_prev = NULL;
-	struct sk_buff *skb;
 	int nframes = 0;
 
 	do {
 		struct ieee80211_tx_info *tx_info;
-		skb = bf->bf_mpdu;
 
 		nframes++;
-		__skb_unlink(skb, tid_q);
 		list_add_tail(&bf->list, bf_q);
 		if (bf_prev)
 			bf_prev->bf_next = bf;
@@ -1411,13 +1427,15 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
 		if (nframes >= 2)
 			break;
 
-		bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
+		bf = ath_tx_get_tid_subframe(sc, txq, tid);
 		if (!bf)
 			break;
 
 		tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+			__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
 			break;
+		}
 
 		ath_set_rates(tid->an->vif, tid->an->sta, bf);
 	} while (1);
@@ -1428,34 +1446,33 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
 {
 	struct ath_buf *bf;
 	struct ieee80211_tx_info *tx_info;
-	struct sk_buff_head *tid_q;
 	struct list_head bf_q;
 	int aggr_len = 0;
-	bool aggr, last = true;
+	bool aggr;
 
 	if (!ath_tid_has_buffered(tid))
 		return false;
 
 	INIT_LIST_HEAD(&bf_q);
 
-	bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
+	bf = ath_tx_get_tid_subframe(sc, txq, tid);
 	if (!bf)
 		return false;
 
 	tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
 	aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
 	if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
-		(!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
+	    (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
+		__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
 		*stop = true;
 		return false;
 	}
 
 	ath_set_rates(tid->an->vif, tid->an->sta, bf);
 	if (aggr)
-		last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
-					tid_q, &aggr_len);
+		aggr_len = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf);
 	else
-		ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q);
+		ath_tx_form_burst(sc, txq, tid, &bf_q, bf);
 
 	if (list_empty(&bf_q))
 		return false;
@@ -1498,9 +1515,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
 		an->mpdudensity = density;
 	}
 
-	/* force sequence number allocation for pending frames */
-	ath_tx_tid_change_state(sc, txtid);
-
 	txtid->active = true;
 	*ssn = txtid->seq_start = txtid->seq_next;
 	txtid->bar_index = -1;
@@ -1525,7 +1539,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
 	ath_txq_lock(sc, txq);
 	txtid->active = false;
 	ath_tx_flush_tid(sc, txtid);
-	ath_tx_tid_change_state(sc, txtid);
 	ath_txq_unlock_complete(sc, txq);
 }
 
@@ -1535,14 +1548,12 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_atx_tid *tid;
 	struct ath_txq *txq;
-	bool buffered;
 	int tidno;
 
 	ath_dbg(common, XMIT, "%s called\n", __func__);
 
-	for (tidno = 0, tid = &an->tid[tidno];
-	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
-
+	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+		tid = ath_node_to_tid(an, tidno);
 		txq = tid->txq;
 
 		ath_txq_lock(sc, txq);
@@ -1552,13 +1563,12 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
 			continue;
 		}
 
-		buffered = ath_tid_has_buffered(tid);
+		if (!skb_queue_empty(&tid->retry_q))
+			ieee80211_sta_set_buffered(sta, tid->tidno, true);
 
 		list_del_init(&tid->list);
 
 		ath_txq_unlock(sc, txq);
-
-		ieee80211_sta_set_buffered(sta, tidno, buffered);
 	}
 }
 
@@ -1571,49 +1581,20 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
 
 	ath_dbg(common, XMIT, "%s called\n", __func__);
 
-	for (tidno = 0, tid = &an->tid[tidno];
-	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
-
+	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+		tid = ath_node_to_tid(an, tidno);
 		txq = tid->txq;
 
 		ath_txq_lock(sc, txq);
 		tid->clear_ps_filter = true;
-
 		if (ath_tid_has_buffered(tid)) {
 			ath_tx_queue_tid(sc, txq, tid);
 			ath_txq_schedule(sc, txq);
 		}
-
 		ath_txq_unlock_complete(sc, txq);
 	}
 }
 
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
-			u16 tidno)
-{
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_atx_tid *tid;
-	struct ath_node *an;
-	struct ath_txq *txq;
-
-	ath_dbg(common, XMIT, "%s called\n", __func__);
-
-	an = (struct ath_node *)sta->drv_priv;
-	tid = ATH_AN_2_TID(an, tidno);
-	txq = tid->txq;
-
-	ath_txq_lock(sc, txq);
-
-	tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
-
-	if (ath_tid_has_buffered(tid)) {
-		ath_tx_queue_tid(sc, txq, tid);
-		ath_txq_schedule(sc, txq);
-	}
-
-	ath_txq_unlock_complete(sc, txq);
-}
-
 void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
 				   struct ieee80211_sta *sta,
 				   u16 tids, int nframes,
@@ -1626,7 +1607,6 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
 	struct ieee80211_tx_info *info;
 	struct list_head bf_q;
 	struct ath_buf *bf_tail = NULL, *bf;
-	struct sk_buff_head *tid_q;
 	int sent = 0;
 	int i;
 
@@ -1641,11 +1621,10 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
 
 		ath_txq_lock(sc, tid->txq);
 		while (nframes > 0) {
-			bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q);
+			bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid);
 			if (!bf)
 				break;
 
-			__skb_unlink(bf->bf_mpdu, tid_q);
 			list_add_tail(&bf->list, &bf_q);
 			ath_set_rates(tid->an->vif, tid->an->sta, bf);
 			if (bf_isampdu(bf)) {
@@ -1660,7 +1639,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
 			sent++;
 			TX_STAT_INC(txq->axq_qnum, a_queued_hw);
 
-			if (an->sta && !ath_tid_has_buffered(tid))
+			if (an->sta && skb_queue_empty(&tid->retry_q))
 				ieee80211_sta_set_buffered(an->sta, i, false);
 		}
 		ath_txq_unlock_complete(sc, tid->txq);
@@ -1887,13 +1866,7 @@ bool ath_drain_all_txq(struct ath_softc *sc)
 		if (!ATH_TXQ_SETUP(sc, i))
 			continue;
 
-		/*
-		 * The caller will resume queues with ieee80211_wake_queues.
-		 * Mark the queue as not stopped to prevent ath_tx_complete
-		 * from waking the queue too early.
-		 */
 		txq = &sc->tx.txq[i];
-		txq->stopped = false;
 		ath_draintxq(sc, txq);
 	}
 
@@ -2293,15 +2266,12 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 	struct ath_txq *txq = txctl->txq;
 	struct ath_atx_tid *tid = NULL;
 	struct ath_buf *bf;
-	bool queue, skip_uapsd = false, ps_resp;
+	bool ps_resp;
 	int q, ret;
 
 	if (vif)
 		avp = (void *)vif->drv_priv;
 
-	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
-		txctl->force_channel = true;
-
 	ps_resp = !!(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE);
 
 	ret = ath_tx_prepare(hw, skb, txctl);
@@ -2316,63 +2286,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 
 	q = skb_get_queue_mapping(skb);
 
+	if (ps_resp)
+		txq = sc->tx.uapsdq;
+
 	ath_txq_lock(sc, txq);
 	if (txq == sc->tx.txq_map[q]) {
 		fi->txq = q;
-		if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
-		    !txq->stopped) {
-			if (ath9k_is_chanctx_enabled())
-				ieee80211_stop_queue(sc->hw, info->hw_queue);
-			else
-				ieee80211_stop_queue(sc->hw, q);
-			txq->stopped = true;
-		}
-	}
-
-	queue = ieee80211_is_data_present(hdr->frame_control);
-
-	/* If chanctx, queue all null frames while NOA could be there */
-	if (ath9k_is_chanctx_enabled() &&
-	    ieee80211_is_nullfunc(hdr->frame_control) &&
-	    !txctl->force_channel)
-		queue = true;
-
-	/* Force queueing of all frames that belong to a virtual interface on
-	 * a different channel context, to ensure that they are sent on the
-	 * correct channel.
-	 */
-	if (((avp && avp->chanctx != sc->cur_chan) ||
-	     sc->cur_chan->stopped) && !txctl->force_channel) {
-		if (!txctl->an)
-			txctl->an = &avp->mcast_node;
-		queue = true;
-		skip_uapsd = true;
-	}
-
-	if (txctl->an && queue)
-		tid = ath_get_skb_tid(sc, txctl->an, skb);
-
-	if (!skip_uapsd && ps_resp) {
-		ath_txq_unlock(sc, txq);
-		txq = sc->tx.uapsdq;
-		ath_txq_lock(sc, txq);
-	} else if (txctl->an && queue) {
-		WARN_ON(tid->txq != txctl->txq);
-
-		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
-			tid->clear_ps_filter = true;
-
-		/*
-		 * Add this frame to software queue for scheduling later
-		 * for aggregation.
-		 */
-		TX_STAT_INC(txq->axq_qnum, a_queued_sw);
-		__skb_queue_tail(&tid->buf_q, skb);
-		if (!txctl->an->sleeping)
-			ath_tx_queue_tid(sc, txq, tid);
-
-		ath_txq_schedule(sc, txq);
-		goto out;
+		++txq->pending_frames;
 	}
 
 	bf = ath_tx_setup_buffer(sc, txq, tid, skb);
@@ -2856,9 +2776,8 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
 	struct ath_atx_tid *tid;
 	int tidno, acno;
 
-	for (tidno = 0, tid = &an->tid[tidno];
-	     tidno < IEEE80211_NUM_TIDS;
-	     tidno++, tid++) {
+	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+		tid = ath_node_to_tid(an, tidno);
 		tid->an        = an;
 		tid->tidno     = tidno;
 		tid->seq_start = tid->seq_next = 0;
@@ -2866,11 +2785,14 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
 		tid->baw_head  = tid->baw_tail = 0;
 		tid->active	   = false;
 		tid->clear_ps_filter = true;
-		__skb_queue_head_init(&tid->buf_q);
+		tid->has_queued  = false;
 		__skb_queue_head_init(&tid->retry_q);
 		INIT_LIST_HEAD(&tid->list);
 		acno = TID_TO_WME_AC(tidno);
 		tid->txq = sc->tx.txq_map[acno];
+
+		if (!an->sta)
+			break; /* just one multicast ath_atx_tid */
 	}
 }
 
@@ -2880,9 +2802,8 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
 	struct ath_txq *txq;
 	int tidno;
 
-	for (tidno = 0, tid = &an->tid[tidno];
-	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
-
+	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+		tid = ath_node_to_tid(an, tidno);
 		txq = tid->txq;
 
 		ath_txq_lock(sc, txq);
@@ -2894,6 +2815,9 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
 		tid->active = false;
 
 		ath_txq_unlock(sc, txq);
+
+		if (!an->sta)
+			break; /* just one multicast ath_atx_tid */
 	}
 }
 
-- 
2.9.2

^ permalink raw reply related

* [RFC][PATCH] RANDOM: ATH9K RNG delivers zero bits of entropy
From: Stephan Mueller @ 2016-08-05 15:08 UTC (permalink / raw)
  To: Ted Tso, herbert
  Cc: linux-kernel, linux-crypto, ath9k-devel, linux-wireless,
	ath9k-devel, Kalle Valo

Hi Ted, Herbert,

I sent a question to the ATH9K RNG some time ago to the developers.
See https://www.mail-archive.com/linux-crypto@vger.kernel.org/msg19115.html

I have not yet received a word and I think this issue should be resolved.

Thanks
Stephan

---8<---

The ATH9K driver implements an RNG which is completely bypassing the
standard Linux HW generator logic.

The RNG may or may not deliver entropy. Considering the conservative
approach in treating entropy with respect to non-auditable sources, this
patch changes the delivered entropy value to zero. The RNG still feeds
data into the input_pool but it is assumed to have no entropy.

When the ATH9K RNG changes to use the HW RNG framework, it may re-enable
the entropy estimation considering that a user can change that value at
boot and runtime.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/net/wireless/ath/ath9k/rng.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c
index d38e50f..d63dc48 100644
--- a/drivers/net/wireless/ath/ath9k/rng.c
+++ b/drivers/net/wireless/ath/ath9k/rng.c
@@ -92,8 +92,7 @@ static int ath9k_rng_kthread(void *data)
 		fail_stats = 0;
 
 		/* sleep until entropy bits under write_wakeup_threshold */
-		add_hwgenerator_randomness((void *)rng_buf, bytes_read,
-					   ATH9K_RNG_ENTROPY(bytes_read));
+		add_hwgenerator_randomness((void *)rng_buf, bytes_read, 0);
 	}
 
 	kfree(rng_buf);
-- 
2.7.4



^ permalink raw reply related

* RE: [v5.1] ucc_fast: Fix to avoid IS_ERR_VALUE abuses and dead code on 64bit systems.
From: David Laight @ 2016-08-05 13:04 UTC (permalink / raw)
  To: 'Arvind Yadav', zajec5@gmail.com, leoli@freescale.com
  Cc: qiang.zhao@freescale.com, arnd@arndb.de, viresh.kumar@linaro.org,
	linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	scottwood@freescale.com, akpm@linux-foundation.org,
	linuxppc-dev@lists.ozlabs.org, linux@roeck-us.net
In-Reply-To: <1470329563-5464-1-git-send-email-arvind.yadav.cs@gmail.com>

From: Arvind Yadav
> Sent: 04 August 2016 17:53
> IS_ERR_VALUE() assumes that parameter is an unsigned long.
> It can not be used to check if 'unsigned int' is passed insted.
> Which tends to reflect an error.
> In 64bit architectures sizeof (int) == 4 && sizeof (long) == 8.
> IS_ERR_VALUE(x) is ((x) >= (unsigned long)-4095).
> IS_ERR_VALUE() of 'unsigned int' is always false because the 32bit
> value is zero extended to 64 bits.
> 
> Now Problem In UCC fast protocols -: drivers/soc/fsl/qe/ucc_fast.c
> 
>         /* Allocate memory for Tx Virtual Fifo */
>         uccf->ucc_fast_tx_virtual_fifo_base_offset =
>           qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
>         if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
>                 printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n",
>                         __func__);
>                 uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
>                 ucc_fast_free(uccf);
>                 return -ENOMEM;
>         }
> 
>         /* Allocate memory for Rx Virtual Fifo */
>         uccf->ucc_fast_rx_virtual_fifo_base_offset =
>            qe_muram_alloc(uf_info->urfs +
>                            UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
>                            UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
>         if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
>                 printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n",
>                         __func__);
>                 uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
>                 ucc_fast_free(uccf);
>                 return -ENOMEM;
>         }
> 
> qe_muram_alloc (a.k.a. cpm_muram_alloc) returns unsigned long.
> Return value store in a u32 (ucc_fast_tx_virtual_fifo_base_offset
> and ucc_fast_rx_virtual_fifo_base_offset).If qe_muram_alloc will
> return any error, Then IS_ERR_VALUE will always return 0. it'll not
> call ucc_fast_free for any failure. Inside 'if code' will be a dead
> code on 64bit.
> This patch is to avoid this problem on 64bit machine.

That is really far too wordy for a commit message.

My suspicion is that qe_muram_alloc() always returns a value that is much
less than 2^32 - even though the return type is 'long'.

Looking further all this code is a bag of worms.

The 'fail' return value from qe_muram_alloc() (aka cpm_muram_alloc()) is
never returned to an outer level.
It might be better to return a constant CPM_MURAL_ALLOC_FAIL (say 0x7fffffff)
and have the callers check that (via a #define).

That is only the start of the problems...

It looks very likely that cpm_muram_free() will be called in tidy up paths
when cpm_muram_alloc() either failed, or hasn't been called.
Since 0 is a valid return value, and there is no check for -ENOMEM it is
all an 'accident waiting to happen'.

>From my quick scan (grep -B2 -A6) I'm not at all sure most of the error paths
at best leak memory.

	David


^ permalink raw reply

* pull-request: mac80211 2016-08-05
From: Johannes Berg @ 2016-08-05 12:32 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-wireless

Hi Dave,

Here's a first set of fixes for the current cycle. See the tag message
for more information.

I'll probably have a follow-up fix for the real problem in mac80211
that caused the crash later, but for now we have this patch and it
makes sense and fixes the crash, even if the behaviour isn't quite
right (afaict.)

Let me know if there's any problem.

Thanks,
johannes



The following changes since commit ecd5a32318280133e8ae93f10ea693293a04a786:

  phy/micrel: Change phy_id_mask for KSZ8721 (2016-07-31 20:37:12 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git tags/mac80211-for-davem-2016-08-05

for you to fetch changes up to 2439ca0402091badb24415e1b073ba12b34ba423:

  mac80211: Add ieee80211_hw pointer to get_expected_throughput (2016-08-05 14:23:25 +0200)

----------------------------------------------------------------
First set of fixes for the current cycle:
 * fix 80+80 bandwidth warning
 * fix powersave with mac80211 TXQ implementation
 * use correct way to free SKBs from multicast buffering
 * mesh: fix operation ordering to work with all drivers
 * mesh: end service period even when peer goes away
 * mesh: correct HT opmode validity checks
 * pass hw pointer from mac80211 to driver in TPT method,
   fixing a bug (in a bit the wrong way, but that's what
   we have right now)

----------------------------------------------------------------
Colin Ian King (1):
      cfg80211: fix missing break in NL8211_CHAN_WIDTH_80P80 case

Felix Fietkau (2):
      mac80211: fix check for buffered powersave frames with txq
      mac80211: fix purging multicast PS buffer queue

Maital Hahn (1):
      mac80211: mesh: flush stations before beacons are stopped

Masashi Honma (2):
      mac80211: End the MPSP even if EOSP frame was not acked
      nl80211: correct checks for NL80211_MESHCONF_HT_OPMODE value

Maxim Altshul (1):
      mac80211: Add ieee80211_hw pointer to get_expected_throughput

 drivers/net/wireless/ti/wlcore/main.c |  5 +++--
 include/net/mac80211.h                |  3 ++-
 net/mac80211/cfg.c                    |  2 +-
 net/mac80211/driver-ops.h             |  2 +-
 net/mac80211/mesh.c                   | 10 ++++++----
 net/mac80211/rx.c                     |  2 +-
 net/mac80211/status.c                 | 14 +++++++-------
 net/mac80211/tx.c                     |  6 +++---
 net/wireless/chan.c                   |  1 +
 net/wireless/nl80211.c                | 34 +++++++++++++++++++++++++++++++---
 10 files changed, 56 insertions(+), 23 deletions(-)

^ permalink raw reply

* Re: [PATCH v3] nl80211: Receive correct value for NL80211_MESHCONF_HT_OPMODE command
From: Johannes Berg @ 2016-08-05 12:15 UTC (permalink / raw)
  To: Masashi Honma; +Cc: linux-wireless, j, me
In-Reply-To: <1470186464-4224-1-git-send-email-masashi.honma@gmail.com>

On Wed, 2016-08-03 at 10:07 +0900, Masashi Honma wrote:
> Previously, NL80211_MESHCONF_HT_OPMODE rejected correct flag
> combination, ex) IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED |
> IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT.
> 
> This was caused by simple comparison with value 16. This causes
> setting
> non-existent flag (like 0x08) and invalid flag combinations. So this
> commit implements some checks based on IEEE 802.11 2012 8.4.2.59 HT
> Operation element.
> 
Applied, with some minor changes.

johannes

^ permalink raw reply

* Re: Buggy rhashtable walking
From: Ben Greear @ 2016-08-05 11:46 UTC (permalink / raw)
  To: Johannes Berg, Herbert Xu
  Cc: David S. Miller, netdev, linux-wireless, Thomas Graf, tom
In-Reply-To: <1470394233.2977.37.camel@sipsolutions.net>



On 08/05/2016 03:50 AM, Johannes Berg wrote:
> On Fri, 2016-08-05 at 18:48 +0800, Herbert Xu wrote:
>> On Fri, Aug 05, 2016 at 08:16:53AM +0200, Johannes Berg wrote:
>>>
>>> Hm. Would you rather allocate a separate head entry for the
>>> hashtable,
>>> or chain the entries?
>>
>> My plan is to build support for this directly into rhashtable.
>> So I'm adding a struct rhlist_head that would be used in place
>> of rhash_head for these cases and it'll carry an extra pointer
>> for the list of identical entries.
>>
>> I will then add an additional layer of insert/lookup interfaces
>> for rhlist_head.

Herbert, thank you for fixing this!

It would not be fun to have to revert to the old way of hashing
stations in mac80211...

I'll be happy to test the patches when you have them ready.

Ben


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

^ permalink raw reply

* Re: Buggy rhashtable walking
From: Johannes Berg @ 2016-08-05 10:50 UTC (permalink / raw)
  To: Herbert Xu; +Cc: David S. Miller, netdev, linux-wireless, Thomas Graf, tom
In-Reply-To: <20160805104858.GA9297@gondor.apana.org.au>

On Fri, 2016-08-05 at 18:48 +0800, Herbert Xu wrote:
> On Fri, Aug 05, 2016 at 08:16:53AM +0200, Johannes Berg wrote:
> > 
> > Hm. Would you rather allocate a separate head entry for the
> > hashtable,
> > or chain the entries?
> 
> My plan is to build support for this directly into rhashtable.
> So I'm adding a struct rhlist_head that would be used in place
> of rhash_head for these cases and it'll carry an extra pointer
> for the list of identical entries.
> 
> I will then add an additional layer of insert/lookup interfaces
> for rhlist_head.

Oh, ok.

> So bottom-line is that if you have no identical entries that you
> only incur an extra 8 bytes per-object.
> 
Right.

Thanks!

johannes

^ 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