Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH v2 3/3] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
From: Arend Van Spriel @ 2019-06-07 13:32 UTC (permalink / raw)
  To: Adrian Hunter, Doug Anderson
  Cc: Ulf Hansson, Kalle Valo, brcm80211-dev-list.pdl,
	open list:ARM/Rockchip SoC..., Double Lo, Brian Norris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, Matthias Kaehlcke,
	Wright Feng, Chi-Hsien Lin, netdev, brcm80211-dev-list,
	David S. Miller, Franky Lin, LKML, Hante Meuleman, YueHaibing,
	Michael Trimarchi
In-Reply-To: <ff0e7b7a-6a58-8bec-b182-944a8b64236d@intel.com>

On June 7, 2019 2:40:04 PM Adrian Hunter <adrian.hunter@intel.com> wrote:

> On 7/06/19 8:12 AM, Arend Van Spriel wrote:
>> On June 6, 2019 11:37:22 PM Doug Anderson <dianders@chromium.org> wrote:
>>>
>>> In the case of dw_mmc, which I'm most familiar with, we don't have any
>>> sort of automated or timed-based retuning.  ...so we'll only re-tune
>>> when we see the CRC error.  If I'm understanding things correctly then
>>> that for dw_mmc my solution and yours behave the same.  That means the
>>> difference is how we deal with other retuning requests, either ones
>>> that come about because of an interrupt that the host controller
>>> provided or because of a timer.  Did I get that right?
>> 
>> Right.
>> 
>>> ...and I guess the reason we have to deal specially with these cases
>>> is because any time that SDIO card is "sleeping" we don't want to
>>> retune because it won't work.  Right?  NOTE: the solution that would
>>> come to my mind first to solve this would be to hold the retuning for
>>> the whole time that the card was sleeping and then release it once the
>>> card was awake again.  ...but I guess we don't truly need to do that
>>> because tuning only happens as a side effect of sending a command to
>>> the card and the only command we send to the card is the "wake up"
>>> command.  That's why your solution to hold tuning while sending the
>>> "wake up" command works, right?
>> 
>> Yup.
>> 
>>> ---
>>>
>>> OK, so assuming all the above is correct, I feel like we're actually
>>> solving two problems and in fact I believe we actually need both our
>>> approaches to solve everything correctly.  With just your patch in
>>> place there's a problem because we will clobber any external retuning
>>> requests that happened while we were waking up the card.  AKA, imagine
>>> this:
>>>
>>> A) brcmf_sdio_kso_control(on=True) gets called; need_retune starts as 0
>>>
>>> B) We call sdio_retune_hold_now()
>>>
>>> C) A retuning timer goes off or the SD Host controller tells us to retune
>>>
>>> D) We get to the end of brcmf_sdio_kso_control() and clear the "retune
>>> needed" since need_retune was 0 at the start.
>>>
>>> ...so we dropped the retuning request from C), right?
>>>
>>>
>>> What we truly need is:
>>>
>>> 1. CRC errors shouldn't trigger a retuning request when we're in
>>> brcmf_sdio_kso_control()
>>>
>>> 2. A separate patch that holds any retuning requests while the SDIO
>>> card is off.  This patch _shouldn't_ do any clearing of retuning
>>> requests, just defer them.
>>>
>>>
>>> Does that make sense to you?  If so, I can try to code it up...
>> 
>> FWIW it does make sense to me. However, I am still not sure if our sdio
>> hardware supports retuning. Have to track down an asic designer who can tell
>> or dive into vhdl myself.
>
> The card supports re-tuning if is handles CMD19, which it does.  It is not
> the card that does any tuning, only the host.  The card just helps by
> providing a known data pattern in response to CMD19.  It can be that a card
> provides good enough signals that the host should not need to re-tune.  I
> don't know if that can be affected by the board design though.

Right. I know it supports initial tuning, but I'm not sure about subsequent 
retuning initiated by the host controller.

Regards,
Arend



^ permalink raw reply

* [RFC PATCH 0/3] move WEP implementation to skcipher interface
From: Ard Biesheuvel @ 2019-06-07 14:49 UTC (permalink / raw)
  To: linux-crypto
  Cc: herbert, ebiggers, johannes, linux-wireless, davem,
	Ard Biesheuvel

One of the issues that I would like to see addressed in the crypto API
is they way the cipher abstraction is used. In general, a cipher should
never be used directly, and so it would be much better to clean up the
existing uses of ciphers outside of the crypto subsystem itself, so that
we can make the cipher abstraction part of the internal API, only to
be used by templates or crypto drivers that require them as a callback.

As a first step, this series moves all users of the 'arc4' cipher to
the ecb(arc4) skcipher, which happens to be implemented by the same
driver, and is already a stream cipher, given that ARC4_BLOCK_SIZE
actually evaluates to 1.

Next step would be to switch the users of the 'des' and 'aes' ciphers
to other interfaces that are more appropriate, either ecb(...) or a
library interface, which may be more appropriate in some cases. In any
case, the end result should be that ciphers are no longer used outside
of crypto/ and drivers/crypto/

This series is presented as an RFC, since I am mostly interested in
discussing the above, but I prefer to do so in the context of actual
patches rather than an abstract discussion.

Ard Biesheuvel (3):
  net/mac80211: switch to skcipher interface for arc4
  lib80211/tkip: switch to skcipher interface for arc4
  lib80211/wep: switch to skcipher interface for arc4

 net/mac80211/ieee80211_i.h         |  6 +-
 net/mac80211/key.h                 |  1 +
 net/mac80211/tkip.c                |  8 +-
 net/mac80211/tkip.h                |  4 +-
 net/mac80211/wep.c                 | 81 +++++++++++++++-----
 net/mac80211/wep.h                 |  4 +-
 net/mac80211/wpa.c                 |  4 +-
 net/wireless/lib80211_crypt_tkip.c | 61 ++++++++++-----
 net/wireless/lib80211_crypt_wep.c  | 52 +++++++++----
 9 files changed, 153 insertions(+), 68 deletions(-)

-- 
2.20.1


^ permalink raw reply

* [RFC PATCH 1/3] net/mac80211: switch to skcipher interface for arc4
From: Ard Biesheuvel @ 2019-06-07 14:49 UTC (permalink / raw)
  To: linux-crypto
  Cc: herbert, ebiggers, johannes, linux-wireless, davem,
	Ard Biesheuvel
In-Reply-To: <20190607144944.13485-1-ard.biesheuvel@linaro.org>

The mac80211 WEP code uses the cipher interface, and invokes it byte
by byte. This is rather inefficient, and since the cipher interface in
general is not really suitable for use outside of the crypto subsystem,
move this code to use the skcipher interface instead.

Given that the only driver that provides a RC4 cipher also provides
a skcipher implementation, this is guaranteed to work. (Note that
ARC4_BLOCK_SIZE is #define'd as 1 so ecb(arc4) behaves as a stream
cipher, as is required in this case)

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 net/mac80211/ieee80211_i.h |  6 +-
 net/mac80211/key.h         |  1 +
 net/mac80211/tkip.c        |  8 +-
 net/mac80211/tkip.h        |  4 +-
 net/mac80211/wep.c         | 81 +++++++++++++++-----
 net/mac80211/wep.h         |  4 +-
 net/mac80211/wpa.c         |  4 +-
 7 files changed, 75 insertions(+), 33 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 073a8235ae1b..c0773cf685b6 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1258,8 +1258,10 @@ struct ieee80211_local {
 
 	struct rate_control_ref *rate_ctrl;
 
-	struct crypto_cipher *wep_tx_tfm;
-	struct crypto_cipher *wep_rx_tfm;
+	struct crypto_skcipher *wep_tx_tfm;
+	struct crypto_skcipher *wep_rx_tfm;
+	struct skcipher_request *wep_tx_req;
+	struct skcipher_request *wep_rx_req;
 	u32 wep_iv;
 
 	/* see iface.c */
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index f06fbd03d235..ee5e7f30a1f1 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -13,6 +13,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/crypto.h>
+#include <crypto/skcipher.h>
 #include <linux/rcupdate.h>
 #include <net/mac80211.h>
 
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
index b3622823bad2..23dd962633fe 100644
--- a/net/mac80211/tkip.c
+++ b/net/mac80211/tkip.c
@@ -222,7 +222,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
  * @payload_len is the length of payload (_not_ including IV/ICV length).
  * @ta is the transmitter addresses.
  */
-int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
+int ieee80211_tkip_encrypt_data(struct skcipher_request *req,
 				struct ieee80211_key *key,
 				struct sk_buff *skb,
 				u8 *payload, size_t payload_len)
@@ -231,7 +231,7 @@ int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
 
 	ieee80211_get_tkip_p2k(&key->conf, skb, rc4key);
 
-	return ieee80211_wep_encrypt_data(tfm, rc4key, 16,
+	return ieee80211_wep_encrypt_data(req, rc4key, 16,
 					  payload, payload_len);
 }
 
@@ -239,7 +239,7 @@ int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
  * beginning of the buffer containing IEEE 802.11 header payload, i.e.,
  * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
  * length of payload, including IV, Ext. IV, MIC, ICV.  */
-int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
+int ieee80211_tkip_decrypt_data(struct skcipher_request *req,
 				struct ieee80211_key *key,
 				u8 *payload, size_t payload_len, u8 *ta,
 				u8 *ra, int only_iv, int queue,
@@ -297,7 +297,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
 
 	tkip_mixing_phase2(tk, &rx_ctx->ctx, iv16, rc4key);
 
-	res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
+	res = ieee80211_wep_decrypt_data(req, rc4key, 16, pos, payload_len - 12);
  done:
 	if (res == TKIP_DECRYPT_OK) {
 		/*
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h
index a1bcbfbefe7c..e66aac448786 100644
--- a/net/mac80211/tkip.h
+++ b/net/mac80211/tkip.h
@@ -13,7 +13,7 @@
 #include <linux/crypto.h>
 #include "key.h"
 
-int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
+int ieee80211_tkip_encrypt_data(struct skcipher_request *req,
 				struct ieee80211_key *key,
 				struct sk_buff *skb,
 				u8 *payload, size_t payload_len);
@@ -24,7 +24,7 @@ enum {
 	TKIP_DECRYPT_INVALID_KEYIDX = -2,
 	TKIP_DECRYPT_REPLAY = -3,
 };
-int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
+int ieee80211_tkip_decrypt_data(struct skcipher_request *req,
 				struct ieee80211_key *key,
 				u8 *payload, size_t payload_len, u8 *ta,
 				u8 *ra, int only_iv, int queue,
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index bfe9ed9f4c48..0336afb70c2b 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -27,31 +27,64 @@
 
 int ieee80211_wep_init(struct ieee80211_local *local)
 {
+	int err;
+
 	/* start WEP IV from a random value */
 	get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
 
-	local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, 0);
+	local->wep_tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0,
+						  CRYPTO_ALG_ASYNC);
 	if (IS_ERR(local->wep_tx_tfm)) {
 		local->wep_rx_tfm = ERR_PTR(-EINVAL);
 		return PTR_ERR(local->wep_tx_tfm);
 	}
 
-	local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, 0);
+	local->wep_rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0,
+						  CRYPTO_ALG_ASYNC);
 	if (IS_ERR(local->wep_rx_tfm)) {
-		crypto_free_cipher(local->wep_tx_tfm);
-		local->wep_tx_tfm = ERR_PTR(-EINVAL);
-		return PTR_ERR(local->wep_rx_tfm);
+		err = PTR_ERR(local->wep_rx_tfm);
+		goto free_tx_tfm;
+	}
+
+	local->wep_tx_req = skcipher_request_alloc(local->wep_tx_tfm,
+						   GFP_KERNEL);
+	if (!local->wep_tx_req) {
+		err = -ENOMEM;
+		goto free_rx_tfm;
+	}
+
+	local->wep_rx_req = skcipher_request_alloc(local->wep_rx_tfm,
+						   GFP_KERNEL);
+	if (!local->wep_rx_req) {
+		err = -ENOMEM;
+		goto free_tx_req;
 	}
 
 	return 0;
+
+free_tx_req:
+	skcipher_request_free(local->wep_tx_req);
+	local->wep_tx_req = NULL;
+free_rx_tfm:
+	crypto_free_skcipher(local->wep_rx_tfm);
+	local->wep_rx_tfm = ERR_PTR(-EINVAL);
+free_tx_tfm:
+	crypto_free_skcipher(local->wep_tx_tfm);
+	local->wep_tx_tfm = ERR_PTR(-EINVAL);
+
+	return err;
 }
 
 void ieee80211_wep_free(struct ieee80211_local *local)
 {
+	if (local->wep_tx_req)
+		skcipher_request_free(local->wep_tx_req);
+	if (local->wep_rx_req)
+		skcipher_request_free(local->wep_rx_req);
 	if (!IS_ERR(local->wep_tx_tfm))
-		crypto_free_cipher(local->wep_tx_tfm);
+		crypto_free_skcipher(local->wep_tx_tfm);
 	if (!IS_ERR(local->wep_rx_tfm))
-		crypto_free_cipher(local->wep_rx_tfm);
+		crypto_free_skcipher(local->wep_rx_tfm);
 }
 
 static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
@@ -131,21 +164,24 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local,
 /* Perform WEP encryption using given key. data buffer must have tailroom
  * for 4-byte ICV. data_len must not include this ICV. Note: this function
  * does _not_ add IV. data = RC4(data | CRC32(data)) */
-int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+int ieee80211_wep_encrypt_data(struct skcipher_request *req, u8 *rc4key,
 			       size_t klen, u8 *data, size_t data_len)
 {
+	struct scatterlist sg;
 	__le32 icv;
-	int i;
 
-	if (IS_ERR(tfm))
+	if (!req)
 		return -1;
 
 	icv = cpu_to_le32(~crc32_le(~0, data, data_len));
 	put_unaligned(icv, (__le32 *)(data + data_len));
 
-	crypto_cipher_setkey(tfm, rc4key, klen);
-	for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
-		crypto_cipher_encrypt_one(tfm, data + i, data + i);
+	crypto_skcipher_setkey(crypto_skcipher_reqtfm(req), rc4key, klen);
+	sg_init_one(&sg, data, data_len + IEEE80211_WEP_ICV_LEN);
+	skcipher_request_set_crypt(req, &sg, &sg,
+				   data_len + IEEE80211_WEP_ICV_LEN, NULL);
+	if (crypto_skcipher_encrypt(req) < 0)
+		return -1;
 
 	return 0;
 }
@@ -184,7 +220,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
 	/* Add room for ICV */
 	skb_put(skb, IEEE80211_WEP_ICV_LEN);
 
-	return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
+	return ieee80211_wep_encrypt_data(local->wep_tx_req, rc4key, keylen + 3,
 					  iv + IEEE80211_WEP_IV_LEN, len);
 }
 
@@ -192,18 +228,21 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
 /* Perform WEP decryption using given key. data buffer includes encrypted
  * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV.
  * Return 0 on success and -1 on ICV mismatch. */
-int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+int ieee80211_wep_decrypt_data(struct skcipher_request *req, u8 *rc4key,
 			       size_t klen, u8 *data, size_t data_len)
 {
+	struct scatterlist sg;
 	__le32 crc;
-	int i;
 
-	if (IS_ERR(tfm))
+	if (!req)
 		return -1;
 
-	crypto_cipher_setkey(tfm, rc4key, klen);
-	for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
-		crypto_cipher_decrypt_one(tfm, data + i, data + i);
+	crypto_skcipher_setkey(crypto_skcipher_reqtfm(req), rc4key, klen);
+	sg_init_one(&sg, data, data_len + IEEE80211_WEP_ICV_LEN);
+	skcipher_request_set_crypt(req, &sg, &sg,
+				   data_len + IEEE80211_WEP_ICV_LEN, NULL);
+	if (crypto_skcipher_decrypt(req) < 0)
+		return -1;
 
 	crc = cpu_to_le32(~crc32_le(~0, data, data_len));
 	if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0)
@@ -256,7 +295,7 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
 	/* Copy rest of the WEP key (the secret part) */
 	memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
 
-	if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
+	if (ieee80211_wep_decrypt_data(local->wep_rx_req, rc4key, klen,
 				       skb->data + hdrlen +
 				       IEEE80211_WEP_IV_LEN, len))
 		ret = -1;
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
index 9615749d1f65..6a392b1ed4b7 100644
--- a/net/mac80211/wep.h
+++ b/net/mac80211/wep.h
@@ -18,12 +18,12 @@
 
 int ieee80211_wep_init(struct ieee80211_local *local);
 void ieee80211_wep_free(struct ieee80211_local *local);
-int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+int ieee80211_wep_encrypt_data(struct skcipher_request *req, u8 *rc4key,
 				size_t klen, u8 *data, size_t data_len);
 int ieee80211_wep_encrypt(struct ieee80211_local *local,
 			  struct sk_buff *skb,
 			  const u8 *key, int keylen, int keyidx);
-int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+int ieee80211_wep_decrypt_data(struct skcipher_request *req, u8 *rc4key,
 			       size_t klen, u8 *data, size_t data_len);
 
 ieee80211_rx_result
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 58d0b258b684..a7870ec67a26 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -242,7 +242,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	/* Add room for ICV */
 	skb_put(skb, IEEE80211_TKIP_ICV_LEN);
 
-	return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
+	return ieee80211_tkip_encrypt_data(tx->local->wep_tx_req,
 					   key, skb, pos, len);
 }
 
@@ -293,7 +293,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
 	if (status->flag & RX_FLAG_DECRYPTED)
 		hwaccel = 1;
 
-	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
+	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_req,
 					  key, skb->data + hdrlen,
 					  skb->len - hdrlen, rx->sta->sta.addr,
 					  hdr->addr1, hwaccel, rx->security_idx,
-- 
2.20.1


^ permalink raw reply related

* [RFC PATCH 3/3] lib80211/wep: switch to skcipher interface for arc4
From: Ard Biesheuvel @ 2019-06-07 14:49 UTC (permalink / raw)
  To: linux-crypto
  Cc: herbert, ebiggers, johannes, linux-wireless, davem,
	Ard Biesheuvel
In-Reply-To: <20190607144944.13485-1-ard.biesheuvel@linaro.org>

The WEP code uses the arc4 cipher interface, and invokes it byte by
byte. This is rather inefficient, and since the cipher interface in
general is not really suitable for use outside of the crypto subsystem,
move this code to use the skcipher interface instead.

Given that the only driver that provides a RC4 cipher also provides
a skcipher implementation, this is guaranteed to work. (Note that
ARC4_BLOCK_SIZE is #define'd as 1 so ecb(arc4) behaves as a stream
cipher, as is required in this case)

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 net/wireless/lib80211_crypt_wep.c | 52 ++++++++++++++------
 1 file changed, 36 insertions(+), 16 deletions(-)

diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c
index 20c1ad63ad44..461f94afe6e9 100644
--- a/net/wireless/lib80211_crypt_wep.c
+++ b/net/wireless/lib80211_crypt_wep.c
@@ -23,6 +23,7 @@
 #include <net/lib80211.h>
 
 #include <linux/crypto.h>
+#include <crypto/skcipher.h>
 #include <linux/crc32.h>
 
 MODULE_AUTHOR("Jouni Malinen");
@@ -35,8 +36,10 @@ struct lib80211_wep_data {
 	u8 key[WEP_KEY_LEN + 1];
 	u8 key_len;
 	u8 key_idx;
-	struct crypto_cipher *tx_tfm;
-	struct crypto_cipher *rx_tfm;
+	struct crypto_skcipher *tx_tfm;
+	struct crypto_skcipher *rx_tfm;
+	struct skcipher_request *tx_req;
+	struct skcipher_request *rx_req;
 };
 
 static void *lib80211_wep_init(int keyidx)
@@ -48,17 +51,26 @@ static void *lib80211_wep_init(int keyidx)
 		goto fail;
 	priv->key_idx = keyidx;
 
-	priv->tx_tfm = crypto_alloc_cipher("arc4", 0, 0);
+	priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, 0);
 	if (IS_ERR(priv->tx_tfm)) {
 		priv->tx_tfm = NULL;
 		goto fail;
 	}
 
-	priv->rx_tfm = crypto_alloc_cipher("arc4", 0, 0);
+	priv->rx_tfm = crypto_alloc_skcipher("arc4", 0, 0);
 	if (IS_ERR(priv->rx_tfm)) {
 		priv->rx_tfm = NULL;
 		goto fail;
 	}
+
+	priv->tx_req = skcipher_request_alloc(priv->tx_tfm, GFP_KERNEL);
+	if (!priv->tx_req)
+		goto fail;
+
+	priv->rx_req = skcipher_request_alloc(priv->rx_tfm, GFP_KERNEL);
+	if (!priv->tx_req)
+		goto fail;
+
 	/* start WEP IV from a random value */
 	get_random_bytes(&priv->iv, 4);
 
@@ -66,8 +78,10 @@ static void *lib80211_wep_init(int keyidx)
 
       fail:
 	if (priv) {
-		crypto_free_cipher(priv->tx_tfm);
-		crypto_free_cipher(priv->rx_tfm);
+		skcipher_request_free(priv->tx_req);
+		skcipher_request_free(priv->rx_req);
+		crypto_free_skcipher(priv->tx_tfm);
+		crypto_free_skcipher(priv->rx_tfm);
 		kfree(priv);
 	}
 	return NULL;
@@ -77,8 +91,10 @@ static void lib80211_wep_deinit(void *priv)
 {
 	struct lib80211_wep_data *_priv = priv;
 	if (_priv) {
-		crypto_free_cipher(_priv->tx_tfm);
-		crypto_free_cipher(_priv->rx_tfm);
+		skcipher_request_free(_priv->tx_req);
+		skcipher_request_free(_priv->rx_req);
+		crypto_free_skcipher(_priv->tx_tfm);
+		crypto_free_skcipher(_priv->rx_tfm);
 	}
 	kfree(priv);
 }
@@ -129,10 +145,10 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len,
 static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct lib80211_wep_data *wep = priv;
+	struct scatterlist sg;
 	u32 crc, klen, len;
 	u8 *pos, *icv;
 	u8 key[WEP_KEY_LEN + 3];
-	int i;
 
 	/* other checks are in lib80211_wep_build_iv */
 	if (skb_tailroom(skb) < 4)
@@ -160,10 +176,11 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	icv[2] = crc >> 16;
 	icv[3] = crc >> 24;
 
-	crypto_cipher_setkey(wep->tx_tfm, key, klen);
-
-	for (i = 0; i < len + 4; i++)
-		crypto_cipher_encrypt_one(wep->tx_tfm, pos + i, pos + i);
+	crypto_skcipher_setkey(wep->tx_tfm, key, klen);
+	sg_init_one(&sg, pos, len + 4);
+	skcipher_request_set_crypt(wep->tx_req, &sg, &sg, len + 4, NULL);
+	if (crypto_skcipher_encrypt(wep->tx_req) < 0)
+		return -1;
 
 	return 0;
 }
@@ -178,6 +195,7 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct lib80211_wep_data *wep = priv;
+	struct scatterlist sg;
 	u32 crc, klen, plen;
 	u8 key[WEP_KEY_LEN + 3];
 	u8 keyidx, *pos, icv[4];
@@ -202,9 +220,11 @@ static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	/* Apply RC4 to data and compute CRC32 over decrypted data */
 	plen = skb->len - hdr_len - 8;
 
-	crypto_cipher_setkey(wep->rx_tfm, key, klen);
-	for (i = 0; i < plen + 4; i++)
-		crypto_cipher_decrypt_one(wep->rx_tfm, pos + i, pos + i);
+	crypto_skcipher_setkey(wep->rx_tfm, key, klen);
+	sg_init_one(&sg, pos, plen + 4);
+	skcipher_request_set_crypt(wep->rx_req, &sg, &sg, plen + 4, NULL);
+	if (crypto_skcipher_decrypt(wep->rx_req) < 0)
+		return -1;
 
 	crc = ~crc32_le(~0, pos, plen);
 	icv[0] = crc;
-- 
2.20.1


^ permalink raw reply related

* [RFC PATCH 2/3] lib80211/tkip: switch to skcipher interface for arc4
From: Ard Biesheuvel @ 2019-06-07 14:49 UTC (permalink / raw)
  To: linux-crypto
  Cc: herbert, ebiggers, johannes, linux-wireless, davem,
	Ard Biesheuvel
In-Reply-To: <20190607144944.13485-1-ard.biesheuvel@linaro.org>

The TKIP code uses the arc4 cipher interface, and invokes it byte by
byte. This is rather inefficient, and since the cipher interface in
general is not really suitable for use outside of the crypto subsystem,
move this code to use the skcipher interface instead.

Given that the only driver that provides a RC4 cipher also provides
a skcipher implementation, this is guaranteed to work. (Note that
ARC4_BLOCK_SIZE is #define'd as 1 so ecb(arc4) behaves as a stream
cipher, as is required in this case)

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 net/wireless/lib80211_crypt_tkip.c | 61 ++++++++++++++------
 1 file changed, 42 insertions(+), 19 deletions(-)

diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
index 11eaa5956f00..456c85b03b32 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -30,6 +30,7 @@
 #include <net/iw_handler.h>
 
 #include <crypto/hash.h>
+#include <crypto/skcipher.h>
 #include <linux/crypto.h>
 #include <linux/crc32.h>
 
@@ -64,9 +65,11 @@ struct lib80211_tkip_data {
 
 	int key_idx;
 
-	struct crypto_cipher *rx_tfm_arc4;
+	struct crypto_skcipher *rx_tfm_arc4;
+	struct skcipher_request *rx_req_arc4;
 	struct crypto_shash *rx_tfm_michael;
-	struct crypto_cipher *tx_tfm_arc4;
+	struct crypto_skcipher *tx_tfm_arc4;
+	struct skcipher_request *tx_req_arc4;
 	struct crypto_shash *tx_tfm_michael;
 
 	/* scratch buffers for virt_to_page() (crypto API) */
@@ -99,7 +102,8 @@ static void *lib80211_tkip_init(int key_idx)
 
 	priv->key_idx = key_idx;
 
-	priv->tx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, 0);
+	priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0,
+						  CRYPTO_ALG_ASYNC);
 	if (IS_ERR(priv->tx_tfm_arc4)) {
 		priv->tx_tfm_arc4 = NULL;
 		goto fail;
@@ -111,7 +115,8 @@ static void *lib80211_tkip_init(int key_idx)
 		goto fail;
 	}
 
-	priv->rx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, 0);
+	priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0,
+						  CRYPTO_ALG_ASYNC);
 	if (IS_ERR(priv->rx_tfm_arc4)) {
 		priv->rx_tfm_arc4 = NULL;
 		goto fail;
@@ -123,14 +128,26 @@ static void *lib80211_tkip_init(int key_idx)
 		goto fail;
 	}
 
+	priv->tx_req_arc4 = skcipher_request_alloc(priv->tx_tfm_arc4,
+						   GFP_KERNEL);
+	if (!priv->tx_req_arc4)
+		goto fail;
+
+	priv->rx_req_arc4 = skcipher_request_alloc(priv->rx_tfm_arc4,
+						   GFP_KERNEL);
+	if (!priv->rx_req_arc4)
+		goto fail;
+
 	return priv;
 
       fail:
 	if (priv) {
+		skcipher_request_free(priv->tx_req_arc4);
+		skcipher_request_free(priv->rx_req_arc4);
 		crypto_free_shash(priv->tx_tfm_michael);
-		crypto_free_cipher(priv->tx_tfm_arc4);
+		crypto_free_skcipher(priv->tx_tfm_arc4);
 		crypto_free_shash(priv->rx_tfm_michael);
-		crypto_free_cipher(priv->rx_tfm_arc4);
+		crypto_free_skcipher(priv->rx_tfm_arc4);
 		kfree(priv);
 	}
 
@@ -141,10 +158,12 @@ static void lib80211_tkip_deinit(void *priv)
 {
 	struct lib80211_tkip_data *_priv = priv;
 	if (_priv) {
+		skcipher_request_free(_priv->tx_req_arc4);
+		skcipher_request_free(_priv->rx_req_arc4);
 		crypto_free_shash(_priv->tx_tfm_michael);
-		crypto_free_cipher(_priv->tx_tfm_arc4);
+		crypto_free_skcipher(_priv->tx_tfm_arc4);
 		crypto_free_shash(_priv->rx_tfm_michael);
-		crypto_free_cipher(_priv->rx_tfm_arc4);
+		crypto_free_skcipher(_priv->rx_tfm_arc4);
 	}
 	kfree(priv);
 }
@@ -342,10 +361,10 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
 static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct lib80211_tkip_data *tkey = priv;
+	struct scatterlist sg;
 	int len;
 	u8 rc4key[16], *pos, *icv;
 	u32 crc;
-	int i;
 
 	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
 		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -370,10 +389,11 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	icv[2] = crc >> 16;
 	icv[3] = crc >> 24;
 
-	crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
-	for (i = 0; i < len + 4; i++)
-		crypto_cipher_encrypt_one(tkey->tx_tfm_arc4, pos + i, pos + i);
-	return 0;
+	crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
+	sg_init_one(&sg, pos, len + 4);
+	skcipher_request_set_crypt(tkey->tx_req_arc4, &sg, &sg, len + 4, NULL);
+
+	return crypto_skcipher_encrypt(tkey->tx_req_arc4);
 }
 
 /*
@@ -392,6 +412,7 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
 static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct lib80211_tkip_data *tkey = priv;
+	struct scatterlist sg;
 	u8 rc4key[16];
 	u8 keyidx, *pos;
 	u32 iv32;
@@ -400,7 +421,6 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	u8 icv[4];
 	u32 crc;
 	int plen;
-	int i;
 
 	hdr = (struct ieee80211_hdr *)skb->data;
 
@@ -453,9 +473,12 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
 	plen = skb->len - hdr_len - 12;
 
-	crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
-	for (i = 0; i < plen + 4; i++)
-		crypto_cipher_decrypt_one(tkey->rx_tfm_arc4, pos + i, pos + i);
+	crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
+	sg_init_one(&sg, pos, plen + 4);
+	skcipher_request_set_crypt(tkey->rx_req_arc4, &sg, &sg, plen + 4, NULL);
+
+	if (crypto_skcipher_decrypt(tkey->rx_req_arc4))
+		return -7;
 
 	crc = ~crc32_le(~0, pos, plen);
 	icv[0] = crc;
@@ -640,9 +663,9 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
 	struct lib80211_tkip_data *tkey = priv;
 	int keyidx;
 	struct crypto_shash *tfm = tkey->tx_tfm_michael;
-	struct crypto_cipher *tfm2 = tkey->tx_tfm_arc4;
+	struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4;
 	struct crypto_shash *tfm3 = tkey->rx_tfm_michael;
-	struct crypto_cipher *tfm4 = tkey->rx_tfm_arc4;
+	struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4;
 
 	keyidx = tkey->key_idx;
 	memset(tkey, 0, sizeof(*tkey));
-- 
2.20.1


^ permalink raw reply related

* Re: [PATCH v2 4/4] mt76: mt76x02: run mt76x02_edcca_init atomically in mt76_edcca_set
From: Felix Fietkau @ 2019-06-07 16:27 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, sgruszka
In-Reply-To: <fde3fda80e04bc1957f98ec48bb33485bb60e3c2.1557587336.git.lorenzo@kernel.org>

On 2019-05-11 17:30, Lorenzo Bianconi wrote:
> Run mt76x02_edcca_init atomically in mt76_edcca_set since it runs
> concurrently with calibration work and mt76x2_set_channel.
> Moreover perform phy calibration atomically
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH v2] mt76: mt7603: add debugfs knob to enable/disable edcca
From: Felix Fietkau @ 2019-06-07 16:32 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless
In-Reply-To: <95b37b61ae24afe3bd3da2fb3fb0b14169dee05c.1557739809.git.lorenzo@kernel.org>

On 2019-05-13 12:19, Lorenzo Bianconi wrote:
> Introduce a knob in mt7603 debugfs in order to enable/disable
> energy detection based on CCA thresholds
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH] mt76: mt76x02: fix edcca file permission
From: Felix Fietkau @ 2019-06-07 16:32 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, sgruszka
In-Reply-To: <0e4f22246404d095de2a7e28ddf7572ff71bdb05.1557742856.git.lorenzo@kernel.org>

On 2019-05-13 12:23, Lorenzo Bianconi wrote:
> Use 0600 as edcca file permission in mt76x02 debugfs
> 
> Fixes: 643749d4a82b ("mt76: mt76x02: disable ED/CCA by default")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH] mt76: mt7615: do not process rx packets if the device is not initialized
From: Felix Fietkau @ 2019-06-07 16:33 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo
In-Reply-To: <f3117ed5577bdcc2b0bf98c20d07e81f0f52476e.1557825294.git.lorenzo@kernel.org>

On 2019-05-14 11:18, Lorenzo Bianconi wrote:
> Fix following crash that occurs when the driver is processing rx packets
> while the device is not initialized yet
> 
> $ rmmod mt7615e
> [   67.210261] mt7615e 0000:01:00.0: Message -239 (seq 2) timeout
> $ modprobe mt7615e
> [   72.406937] bus=0x1, slot = 0x0, irq=0x16
> [   72.436590] CPU 0 Unable to handle kernel paging request at virtual address 00000004, epc == 8eec4240, ra == 8eec41e0
> [   72.450291] mt7615e 0000:01:00.0: Firmware is not ready for download
> [   72.457724] Oops[#1]:
> [   72.470494] mt7615e: probe of 0000:01:00.0 failed with error -5
> [   72.474829] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.14.114 #0
> [   72.498702] task: 805769e0 task.stack: 80564000
> [   72.507709] $ 0   : 00000000 00000001 00000000 00000001
> [   72.518106] $ 4   : 8f704dbc 00000000 00000000 8f7046c0
> [   72.528500] $ 8   : 00000024 8045e98c 81210008 11000000
> [   72.538895] $12   : 8fc09f60 00000008 00000019 00000033
> [   72.549289] $16   : 8f704d80 e00000ff 8f0c7800 3c182406
> [   72.559684] $20   : 00000006 8ee615a0 4e000108 00000000
> [   72.570078] $24   : 0000004c 8000cf94
> [   72.580474] $28   : 80564000 8fc09e38 00000001 8eec41e0
> [   72.590869] Hi    : 00000001
> [   72.596582] Lo    : 00000000
> [   72.602319] epc   : 8eec4240 mt7615_mac_fill_rx+0xac/0x494 [mt7615e]
> [   72.614953] ra    : 8eec41e0 mt7615_mac_fill_rx+0x4c/0x494 [mt7615e]
> [   72.627580] Status: 11008403 KERNEL EXL IE
> [   72.635899] Cause : 40800008 (ExcCode 02)
> [   72.643860] BadVA : 00000004
> [   72.649573] PrId  : 0001992f (MIPS 1004Kc)
> [   72.657704] Modules linked in: mt7615e pppoe ppp_async pppox ppp_generic nf_conntrack_ipv6 mt76x2e mt76x2_common mt76x02_lib mt7603e mt76 mac80211 iptable_nat ipt_REJECT ipt_MASQUERADE cfg80211 xt_time xt_tcpudp xt_state xt_nat xt_mu]
> [   72.792717] Process swapper/0 (pid: 0, threadinfo=80564000, task=805769e0, tls=00000000)
> [   72.808799] Stack : 8f0c7800 00000800 8f0c7800 8032b874 00000000 40000000 8f704d80 8ee615a0
> [   72.825428]         8dc88010 00000001 8ee615e0 8eec09b0 8dc88010 8032b914 8f3aee80 80567d20
> [   72.842055]         00000000 8ee615e0 40000000 8f0c7800 00000108 8eec9944 00000000 00000000
> [   72.858682]         80508f10 80510000 00000001 80567d20 8ee615a0 00000000 00000000 8ee61c00
> [   72.875308]         8ee61c40 00000040 80610000 80580000 00000000 8ee615dc 8ee61a68 00000001
> [   72.891936]         ...
> [   72.896793] Call Trace:
> [   72.901649] [<8eec4240>] mt7615_mac_fill_rx+0xac/0x494 [mt7615e]
> [   72.913602] [<8eec09b0>] mt7615_queue_rx_skb+0xe4/0x12c [mt7615e]
> [   72.925734] [<8eec9944>] mt76_dma_cleanup+0x390/0x42c [mt76]
> [   72.936988] Code: ae020018  8ea20004  24030001 <94420004> a602002a  8ea20004  90420000  14430003  a2020034
> [   72.956390]
> [   72.959676] ---[ end trace f176967739edb19f ]---
> 
> Fixes: 04b8e65922f6 ("mt76: add mac80211 driver for MT7615 PCIe-based chipsets")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH] mt76: mt7615: stop mcu first in mt7615_unregister_device
From: Felix Fietkau @ 2019-06-07 16:34 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo
In-Reply-To: <e145d9f42b1cfcf525300d583c99773132381c34.1557836235.git.lorenzo@kernel.org>

On 2019-05-14 14:20, Lorenzo Bianconi wrote:
> Stop mcu engine and then dma one in mt7615_unregister_device
> in order to avoid a mcu hang in mt7615_unregister_device
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> This patch ca be squashed with 'mt76: mt7615: rearrange cleanup operations in
> mt7615_unregister_device' since it is not upstream yet

Applied, thanks.

- Felix

^ permalink raw reply

* [PATCH 2/4] mt76: fix setting chan->max_power
From: Felix Fietkau @ 2019-06-07 16:43 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20190607164355.51876-1-nbd@nbd.name>

When setting chan->max_power after registering the wiphy, chan->max_reg_power
needs to be used as a limit

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt7603/init.c | 2 +-
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 5 +++--
 drivers/net/wireless/mediatek/mt76/mt76x2/init.c | 9 +++++----
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
index 2238e3daedc6..bce51997ff3b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
@@ -494,7 +494,7 @@ mt7603_init_txpower(struct mt7603_dev *dev,
 
 	for (i = 0; i < sband->n_channels; i++) {
 		chan = &sband->channels[i];
-		chan->max_power = target_power;
+		chan->max_power = min_t(int, chan->max_reg_power, target_power);
 		chan->orig_mpwr = target_power;
 	}
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 57e46d57b449..d67401f895ca 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -279,8 +279,9 @@ mt76x0_init_txpower(struct mt76x02_dev *dev,
 		mt76x0_get_tx_power_per_rate(dev, chan, &t);
 		mt76x0_get_power_info(dev, chan, &tp);
 
-		chan->max_power = (mt76x02_get_max_rate_power(&t) + tp) / 2;
-		chan->orig_mpwr = chan->max_power;
+		chan->orig_mpwr = (mt76x02_get_max_rate_power(&t) + tp) / 2;
+		chan->max_power = min_t(int, chan->max_reg_power,
+					chan->orig_mpwr);
 	}
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c
index c6078e90ca43..97c3543eed8a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c
@@ -173,13 +173,14 @@ void mt76x2_init_txpower(struct mt76x02_dev *dev,
 		mt76x2_get_power_info(dev, &txp, chan);
 		mt76x2_get_rate_power(dev, &t, chan);
 
-		chan->max_power = mt76x02_get_max_rate_power(&t) +
+		chan->orig_mpwr = mt76x02_get_max_rate_power(&t) +
 				  txp.target_power;
-		chan->max_power = DIV_ROUND_UP(chan->max_power, 2);
+		chan->orig_mpwr = DIV_ROUND_UP(chan->orig_mpwr, 2);
 
 		/* convert to combined output power on 2x2 devices */
-		chan->max_power += 3;
-		chan->orig_mpwr = chan->max_power;
+		chan->orig_mpwr += 3;
+		chan->max_power = min_t(int, chan->max_reg_power,
+					chan->orig_mpwr);
 	}
 }
 EXPORT_SYMBOL_GPL(mt76x2_init_txpower);
-- 
2.17.0


^ permalink raw reply related

* [PATCH 4/4] mt76: mt76x02: fix tx reordering on rate control probing without a-mpdu
From: Felix Fietkau @ 2019-06-07 16:43 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20190607164355.51876-1-nbd@nbd.name>

To avoid aggregating rate control probing packets with other traffic, and to
ensure that the probing rate gets used, probing packets get assigned a different
internal queueing priority.
This causes packets to be transmitted in a different order, which is compensated
by the receiver side reordering.
However, if A-MPDU is disabled, this reordering can become visible to upper
layers on the receiver side. Disable the priority change if A-MPDU is disabled.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c     | 3 ++-
 drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
index 95c73049a68b..9f1c4e085380 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
@@ -154,6 +154,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
 	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
 	struct mt76x02_txwi *txwi = txwi_ptr;
+	bool ampdu = IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU;
 	int hdrlen, len, pid, qsel = MT_QSEL_EDCA;
 
 	if (qid == MT_TXQ_PSD && wcid && wcid->idx < 128)
@@ -171,7 +172,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
 
 	txwi->pktid = pid;
 
-	if (mt76_is_skb_pktid(pid))
+	if (mt76_is_skb_pktid(pid) && ampdu)
 		qsel = MT_QSEL_MGMT;
 
 	tx_info->info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 2436f14ca24a..04bfc923ac71 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -79,6 +79,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
 	int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid].q->hw_idx);
 	struct mt76x02_txwi *txwi;
+	bool ampdu = IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU;
 	enum mt76_qsel qsel;
 	u32 flags;
 
@@ -96,7 +97,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 
 	txwi->pktid = pid;
 
-	if (mt76_is_skb_pktid(pid) || ep == MT_EP_OUT_HCCA)
+	if ((mt76_is_skb_pktid(pid) && ampdu) || ep == MT_EP_OUT_HCCA)
 		qsel = MT_QSEL_MGMT;
 	else
 		qsel = MT_QSEL_EDCA;
-- 
2.17.0


^ permalink raw reply related

* [PATCH 3/4] mt76: mt76x02: fix tx status reporting issues
From: Felix Fietkau @ 2019-06-07 16:43 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20190607164355.51876-1-nbd@nbd.name>

When the hardware falls back to lower rates for a transmit attempt, only the
first status report will show the number of retries correctly. The frames
that follow will report the correct final rate, but number of retries set to 0.
This can cause the rate control module to vastly underestimate the number of
retransmissions per rate.

To fix this, we need to keep track of the initial requested tx rate per packet
and pass it to the status information.
For frames with tx status requested, this is simple: use the rate configured
in info->control.rates[0] as reference.
For no-skb tx status information, we have to encode the requested tx rate in
the packet id (and make it possible to distinguish it from real packet ids).

To do that, reduce the packet id field size by one bit, and use that bit to
indicate packet id vs rate.

This change also improves reporting by filling the status rate array with
rates from first rate to final rate, taking the same steps as the hardware
fallback table. This matters in corner cases like MCS8 on HT, where the
fallback target is MCS0, not MCS7.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt76.h     | 11 ++-
 .../net/wireless/mediatek/mt76/mt76x02_mac.c  | 88 ++++++++++++++++---
 .../net/wireless/mediatek/mt76/mt76x02_txrx.c |  7 +-
 .../wireless/mediatek/mt76/mt76x02_usb_core.c |  7 +-
 4 files changed, 97 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index fc4169c83e76..907bec9d5e4c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -258,10 +258,11 @@ struct mt76_rx_tid {
 #define MT_TX_CB_TXS_DONE		BIT(1)
 #define MT_TX_CB_TXS_FAILED		BIT(2)
 
-#define MT_PACKET_ID_MASK		GENMASK(7, 0)
+#define MT_PACKET_ID_MASK		GENMASK(6, 0)
 #define MT_PACKET_ID_NO_ACK		0
 #define MT_PACKET_ID_NO_SKB		1
 #define MT_PACKET_ID_FIRST		2
+#define MT_PACKET_ID_HAS_RATE		BIT(7)
 
 #define MT_TX_STATUS_SKB_TIMEOUT	HZ
 
@@ -689,6 +690,14 @@ static inline void mt76_insert_hdr_pad(struct sk_buff *skb)
 	skb->data[len + 1] = 0;
 }
 
+static inline bool mt76_is_skb_pktid(u8 pktid)
+{
+	if (pktid & MT_PACKET_ID_HAS_RATE)
+		return false;
+
+	return pktid >= MT_PACKET_ID_FIRST;
+}
+
 void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb);
 void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
 	     struct mt76_wcid *wcid, struct sk_buff *skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index ee4a86971be7..dd711bacc869 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -419,31 +419,87 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
 }
 EXPORT_SYMBOL_GPL(mt76x02_mac_write_txwi);
 
+static void
+mt76x02_tx_rate_fallback(struct ieee80211_tx_rate *rates, int idx, int phy)
+{
+	u8 mcs, nss;
+
+	if (!idx)
+		return;
+
+	rates += idx - 1;
+	rates[1] = rates[0];
+	switch (phy) {
+	case MT_PHY_TYPE_VHT:
+		mcs = ieee80211_rate_get_vht_mcs(rates);
+		nss = ieee80211_rate_get_vht_nss(rates);
+
+		if (mcs == 0)
+			nss = max_t(int, nss - 1, 1);
+		else
+			mcs--;
+
+		ieee80211_rate_set_vht(rates + 1, mcs, nss);
+		break;
+	case MT_PHY_TYPE_HT_GF:
+	case MT_PHY_TYPE_HT:
+		/* MCS 8 falls back to MCS 0 */
+		if (rates[0].idx == 8) {
+		    rates[1].idx = 0;
+		    break;
+		}
+		/* fall through */
+	default:
+		rates[1].idx = max_t(int, rates[0].idx - 1, 0);
+		break;
+	}
+}
+
 static void
 mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev,
 			   struct ieee80211_tx_info *info,
 			   struct mt76x02_tx_status *st, int n_frames)
 {
 	struct ieee80211_tx_rate *rate = info->status.rates;
-	int cur_idx, last_rate;
+	struct ieee80211_tx_rate last_rate;
+	u16 first_rate;
+	int retry = st->retry;
+	int phy;
 	int i;
 
 	if (!n_frames)
 		return;
 
-	last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1);
-	mt76x02_mac_process_tx_rate(&rate[last_rate], st->rate,
+	phy = FIELD_GET(MT_RXWI_RATE_PHY, st->rate);
+
+	if (st->pktid & MT_PACKET_ID_HAS_RATE) {
+		first_rate = st->rate & ~MT_RXWI_RATE_INDEX;
+		first_rate |= st->pktid & MT_RXWI_RATE_INDEX;
+
+		mt76x02_mac_process_tx_rate(&rate[0], first_rate,
+					    dev->mt76.chandef.chan->band);
+	}
+
+	mt76x02_mac_process_tx_rate(&last_rate, st->rate,
 				    dev->mt76.chandef.chan->band);
-	if (last_rate < IEEE80211_TX_MAX_RATES - 1)
-		rate[last_rate + 1].idx = -1;
-
-	cur_idx = rate[last_rate].idx + last_rate;
-	for (i = 0; i <= last_rate; i++) {
-		rate[i].flags = rate[last_rate].flags;
-		rate[i].idx = max_t(int, 0, cur_idx - i);
-		rate[i].count = 1;
+
+	for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) {
+		retry--;
+		if (i + 1 == ARRAY_SIZE(info->status.rates)) {
+			info->status.rates[i] = last_rate;
+			info->status.rates[i].count = max_t(int, retry, 1);
+			break;
+		}
+
+		mt76x02_tx_rate_fallback(info->status.rates, i, phy);
+		if (info->status.rates[i].idx == last_rate.idx)
+			break;
+	}
+
+	if (i + 1 < ARRAY_SIZE(info->status.rates)) {
+		info->status.rates[i + 1].idx = -1;
+		info->status.rates[i + 1].count = 0;
 	}
-	rate[last_rate].count = st->retry + 1 - last_rate;
 
 	info->status.ampdu_len = n_frames;
 	info->status.ampdu_ack_len = st->success ? n_frames : 0;
@@ -489,13 +545,19 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
 	mt76_tx_status_lock(mdev, &list);
 
 	if (wcid) {
-		if (stat->pktid >= MT_PACKET_ID_FIRST)
+		if (mt76_is_skb_pktid(stat->pktid))
 			status.skb = mt76_tx_status_skb_get(mdev, wcid,
 							    stat->pktid, &list);
 		if (status.skb)
 			status.info = IEEE80211_SKB_CB(status.skb);
 	}
 
+	if (!status.skb && !(stat->pktid & MT_PACKET_ID_HAS_RATE)) {
+		mt76_tx_status_unlock(mdev, &list);
+		rcu_read_unlock();
+		return;
+	}
+
 	if (msta && stat->aggr && !status.skb) {
 		u32 stat_val, stat_cache;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
index cf7abd9b7d2e..95c73049a68b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
@@ -164,9 +164,14 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
 	mt76x02_mac_write_txwi(dev, txwi, tx_info->skb, wcid, sta, len);
 
 	pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
+
+	/* encode packet rate for no-skb packet id to fix up status reporting */
+	if (pid == MT_PACKET_ID_NO_SKB)
+		pid = MT_PACKET_ID_HAS_RATE | (txwi->rate & MT_RXWI_RATE_INDEX);
+
 	txwi->pktid = pid;
 
-	if (pid >= MT_PACKET_ID_FIRST)
+	if (mt76_is_skb_pktid(pid))
 		qsel = MT_QSEL_MGMT;
 
 	tx_info->info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 6b89f7eab26c..2436f14ca24a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -89,9 +89,14 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 	skb_push(tx_info->skb, sizeof(*txwi));
 
 	pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
+
+	/* encode packet rate for no-skb packet id to fix up status reporting */
+	if (pid == MT_PACKET_ID_NO_SKB)
+		pid = MT_PACKET_ID_HAS_RATE | (txwi->rate & MT_RXWI_RATE_INDEX);
+
 	txwi->pktid = pid;
 
-	if (pid >= MT_PACKET_ID_FIRST || ep == MT_EP_OUT_HCCA)
+	if (mt76_is_skb_pktid(pid) || ep == MT_EP_OUT_HCCA)
 		qsel = MT_QSEL_MGMT;
 	else
 		qsel = MT_QSEL_EDCA;
-- 
2.17.0


^ permalink raw reply related

* [PATCH 1/4] mt7603: fix reading target tx power from eeprom
From: Felix Fietkau @ 2019-06-07 16:43 UTC (permalink / raw)
  To: linux-wireless

For the external PA (TSSI OFF) case, the target power needs to be read
from a different location in EEPROM

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h | 2 ++
 drivers/net/wireless/mediatek/mt76/mt7603/init.c   | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h
index f27b99b7e359..b893facfba48 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h
@@ -69,6 +69,8 @@ enum mt7603_eeprom_field {
 
 	MT_EE_CP_FT_VERSION =			0x0f0,
 
+	MT_EE_TX_POWER_TSSI_OFF =		0x0f2,
+
 	MT_EE_XTAL_FREQ_OFFSET =		0x0f4,
 	MT_EE_XTAL_TRIM_2_COMP =		0x0f5,
 	MT_EE_XTAL_TRIM_3_COMP =		0x0f6,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
index 4e269044f8a4..2238e3daedc6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
@@ -465,9 +465,13 @@ mt7603_init_txpower(struct mt7603_dev *dev,
 	u8 *eeprom = (u8 *)dev->mt76.eeprom.data;
 	int target_power = eeprom[MT_EE_TX_POWER_0_START_2G + 2] & ~BIT(7);
 	u8 *rate_power = &eeprom[MT_EE_TX_POWER_CCK];
+	bool ext_pa = eeprom[MT_EE_NIC_CONF_0 + 1] & BIT(1);
 	int max_offset, cur_offset;
 	int i;
 
+	if (ext_pa)
+		target_power = eeprom[MT_EE_TX_POWER_TSSI_OFF] & ~BIT(7);
+
 	if (target_power & BIT(6))
 		target_power = -(target_power & GENMASK(5, 0));
 
-- 
2.17.0


^ permalink raw reply related

* Re: [PATCH] mt76: move mt76_insert_ccmp_hdr in mt76-module
From: Felix Fietkau @ 2019-06-07 16:55 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo
In-Reply-To: <99370eaa04916a871b6cc2413ae00e1370e09292.1557838049.git.lorenzo@kernel.org>

On 2019-05-14 14:48, Lorenzo Bianconi wrote:
> Move mt7615_insert_ccmp_hdr in mac80211.c and rename it in
> mt76_insert_ccmp_hdr since it is shared between mt7603 and mt7615
> drivers
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH v2] mt76: mt7615: add support for mtd eeprom parsing
From: Felix Fietkau @ 2019-06-07 16:55 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo
In-Reply-To: <12c5ae00296007af2da0021cc0872dac9b6960dc.1558074163.git.lorenzo@kernel.org>

On 2019-05-17 08:26, Lorenzo Bianconi wrote:
> Calibration data are often available on a specific mtd partition on
> embedded devices. Take into account eeprom calibration data if
> available.
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> Changes since v1:
> - remove TODO comment
> - take into account mtd partition even if otp one is empty

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH] mt76: mt7615: select wifi band according to eeprom
From: Felix Fietkau @ 2019-06-07 16:56 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo
In-Reply-To: <38aa977df45a92f60d78d9cb7e575289ccbaeef6.1558127930.git.lorenzo@kernel.org>

On 2019-05-17 23:32, Lorenzo Bianconi wrote:
> Select supported band according to the value read from
> eeprom mtd/otp partition
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH 0/4] add tx power configuration support to mt7615 driver
From: Felix Fietkau @ 2019-06-07 16:56 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo
In-Reply-To: <cover.1558879234.git.lorenzo@kernel.org>

On 2019-05-26 16:05, Lorenzo Bianconi wrote:
> Cap tx power according to the value configured by the user.
> Initialize get_txpower mac80211 callback in order to report the
> configured tx power to mac80211
> 
> Lorenzo Bianconi (4):
>   mt76: generalize mt76_get_txpower for 4x4:4 devices
>   mt76: mt7615: add the capability to configure tx power
>   mt76: mt7615: init get_txpower mac80211 callback
>   mt76: mt7615: rearrange locking in mt7615_config

Applied, thanks.

- Felix


^ permalink raw reply

* Re: [PATCH] mt76: move mt76_get_rate in mt76-module
From: Felix Fietkau @ 2019-06-07 17:01 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo
In-Reply-To: <d6b2de1b739a394d5dcdd686a7dff198a743669e.1559118081.git.lorenzo@kernel.org>

On 2019-05-29 10:25, Lorenzo Bianconi wrote:
> Move mt7603_get_rate in mac80211.c and rename it to mt76_get_rate
> since it is shared between mt7603 and mt7615 drivers
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> This patch is based on 'mt76: move mt76_insert_ccmp_hdr in mt76-module'
> https://patchwork.kernel.org/patch/10942973/

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH] mt76: Remove set but not used variables 'pid' and 'final_mpdu'
From: Felix Fietkau @ 2019-06-07 17:01 UTC (permalink / raw)
  To: YueHaibing, lorenzo.bianconi83, ryder.lee, royluo, kvalo,
	matthias.bgg, sgruszka
  Cc: linux-kernel, netdev, linux-wireless, linux-arm-kernel,
	linux-mediatek, davem
In-Reply-To: <20190529145356.13872-1-yuehaibing@huawei.com>

On 2019-05-29 16:53, YueHaibing wrote:
> Fixes gcc '-Wunused-but-set-variable' warnings:
> 
> drivers/net/wireless/mediatek/mt76/mt7603/mac.c: In function mt7603_fill_txs:
> drivers/net/wireless/mediatek/mt76/mt7603/mac.c:969:5: warning: variable pid set but not used [-Wunused-but-set-variable]
> drivers/net/wireless/mediatek/mt76/mt7603/mac.c:961:7: warning: variable final_mpdu set but not used [-Wunused-but-set-variable]
> drivers/net/wireless/mediatek/mt76/mt7615/mac.c: In function mt7615_fill_txs:
> drivers/net/wireless/mediatek/mt76/mt7615/mac.c:555:5: warning: variable pid set but not used [-Wunused-but-set-variable]
> drivers/net/wireless/mediatek/mt76/mt7615/mac.c:552:19: warning: variable final_mpdu set but not used [-Wunused-but-set-variable]
> 
> They are never used, so can be removed.
> 
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH v3 2/2] mt76: mt7615: fix slow performance when enable encryption
From: Felix Fietkau @ 2019-06-07 17:02 UTC (permalink / raw)
  To: Ryder Lee, Lorenzo Bianconi
  Cc: Roy Luo, YF Luo, Yiwei Chung, Sean Wang, Chih-Min Chen,
	linux-wireless, linux-mediatek, linux-kernel
In-Reply-To: <429cf8c1421017b4030b8b6e4fa9e5cbea953d3c.1559541944.git.ryder.lee@mediatek.com>

On 2019-06-03 08:08, Ryder Lee wrote:
> Fix wrong WCID assignment and add RKV (RX Key of this entry is valid)
> flag to check if peer uses the same configuration with previous
> handshaking.
> 
> If the configuration is mismatch, WTBL indicates a “cipher mismatch”
> to stop SEC decryption to prevent the packet from damage.
> 
> Suggested-by: YF Luo <yf.luo@mediatek.com>
> Suggested-by: Yiwei Chung <yiwei.chung@mediatek.com>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH] mt76: mt7615: remove unused variable in mt7615_mcu_set_bcn
From: Felix Fietkau @ 2019-06-07 17:02 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: linux-wireless, lorenzo.bianconi, ryder.lee, royluo
In-Reply-To: <d2b9a68b797fbbd67fe8f3be0fe851113eaa1488.1559641771.git.lorenzo@kernel.org>

On 2019-06-04 12:06, Lorenzo Bianconi wrote:
> Remove tim_len in mt7615_mcu_set_bcn since it is not actually used
> and ieee80211_beacon_get_tim checks if tim_length is NULL
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH] mt76: mt7615: remove key check in mt7615_mcu_set_wtbl_key
From: Felix Fietkau @ 2019-06-07 17:02 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, ryder.lee, royluo
In-Reply-To: <51396ab29d290f95caecbb7fd817c654b74b36dc.1559686202.git.lorenzo@kernel.org>

On 2019-06-05 00:12, Lorenzo Bianconi wrote:
> Do not check key pointer in mt7615_mcu_set_wtbl_key since if set_key_cmd
> is SET_KEY, key will be always not NULL. This patch will address a false
> positive reported by Coverity-Scan
> 
> Addresses-Coverity-ID: 1445463 ("Dereference after null check")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>

Applied, thanks.

- Felix

^ permalink raw reply

* Re: [PATCH v2 0/2] mt7601u: do not schedule {rx,tx}_tasklet when the device has been disconnected
From: Jakub Kicinski @ 2019-06-07 17:07 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: linux-wireless, lorenzo.bianconi
In-Reply-To: <cover.1559906499.git.lorenzo@kernel.org>

On Fri,  7 Jun 2019 13:48:08 +0200, Lorenzo Bianconi wrote:
> Do not schedule {tx,rx}_tasklet when the usb dongle is disconnected in order to fix
> {TX,RX} urb mismatch warning
> Fix possible memory leak when the device is disconnected while passing traffic.

Acked-by: Jakub Kicinski <kubakici@wp.pl>

Thanks Lorenzo!

^ permalink raw reply

* Re: [BISECTED REGRESSION] b43legacy broken on G4 PowerBook
From: Larry Finger @ 2019-06-07 17:25 UTC (permalink / raw)
  To: Aaro Koskinen, Christoph Hellwig, Christian Zigotzky,
	Michael Ellerman
  Cc: linux-kernel, linux-wireless, linuxppc-dev
In-Reply-To: <20190605225059.GA9953@darkstar.musicnaut.iki.fi>

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

On 6/5/19 5:50 PM, Aaro Koskinen wrote:
> Hi,
> 
> When upgrading from v5.0 -> v5.1 on G4 PowerBook, I noticed WLAN does
> not work anymore:
> 
> [   42.004303] b43legacy-phy0: Loading firmware version 0x127, patch level 14 (2005-04-18 02:36:27)
> [   42.184837] b43legacy-phy0 debug: Chip initialized
> [   42.184873] b43legacy-phy0 ERROR: The machine/kernel does not support the required 30-bit DMA mask
> 
> The same happens with the current mainline.
> 
> Bisected to:
> 
> 	commit 65a21b71f948406201e4f62e41f06513350ca390
> 	Author: Christoph Hellwig <hch@lst.de>
> 	Date:   Wed Feb 13 08:01:26 2019 +0100
> 
> 	    powerpc/dma: remove dma_nommu_dma_supported
> 
> 	    This function is largely identical to the generic version used
> 	    everywhere else.  Replace it with the generic version.
> 
> 	    Signed-off-by: Christoph Hellwig <hch@lst.de>
> 	    Tested-by: Christian Zigotzky <chzigotzky@xenosoft.de>
> 	    Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

Aaro,

Please try the attached patch. I'm not really pleased with it and I will 
continue to determine why the fallback to a 30-bit mask fails, but at least this 
one works for me.

Larry



[-- Attachment #2: 0001-b43legacy-Fix-DMA-breakage-from-commit-commit-65a21b.patch --]
[-- Type: text/x-patch, Size: 2674 bytes --]

From 25e2f50273e785598b6bd9a8aee28cf825d3fe9f Mon Sep 17 00:00:00 2001
From: Larry Finger <Larry.Finger@lwfinger.net>
Date: Fri, 7 Jun 2019 12:04:16 -0500
Subject: [PATCH] b43legacy: Fix DMA breakage from commit commit 65a21b71f948
To: kvalo@codeaurora.org
Cc: linux-wireless@vger.kernel.org,
    pkshih@realtek.com

Following commit 65a21b71f948 ("powerpc/dma: remove dma_nommu_dma_supported"),
this driver errors with a message that "The machine/kernel does not
support the required 30-bit DMA mask." Indeed, the hardware only allows
31-bit masks. This solution is to change the fallback mask from 30-
to 31-bits for 32-bit PPC systems.

Fixes: 65a21b71f948 ("powerpc/dma: remove dma_nommu_dma_supported")
Reported-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 drivers/net/wireless/broadcom/b43legacy/dma.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/broadcom/b43legacy/dma.c b/drivers/net/wireless/broadcom/b43legacy/dma.c
index 1cc25f44dd9a..75613f516e50 100644
--- a/drivers/net/wireless/broadcom/b43legacy/dma.c
+++ b/drivers/net/wireless/broadcom/b43legacy/dma.c
@@ -27,6 +27,15 @@
 #include <linux/slab.h>
 #include <net/dst.h>
 
+/* Special handling for PPC32 - The maximum DMA mask is 31 bits, and
+ * the fallback to 30 bits fails. Set the fallback at 31.
+ */
+#ifdef CONFIG_PPC32
+#define FB_DMA	31
+#else
+#define FB_DMA	30
+#endif
+
 /* 32bit DMA ops. */
 static
 struct b43legacy_dmadesc32 *op32_idx2desc(struct b43legacy_dmaring *ring,
@@ -418,7 +427,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
 
 	switch (ring->type) {
 	case B43legacy_DMA_30BIT:
-		if ((u64)addr + buffersize > (1ULL << 30))
+		if ((u64)addr + buffersize > (1ULL << FB_DMA))
 			goto address_error;
 		break;
 	case B43legacy_DMA_32BIT:
@@ -617,12 +626,12 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev)
 	if (tmp & B43legacy_DMA32_TXADDREXT_MASK)
 		return DMA_BIT_MASK(32);
 
-	return DMA_BIT_MASK(30);
+	return DMA_BIT_MASK(FB_DMA);
 }
 
 static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask)
 {
-	if (dmamask == DMA_BIT_MASK(30))
+	if (dmamask == DMA_BIT_MASK(FB_DMA))
 		return B43legacy_DMA_30BIT;
 	if (dmamask == DMA_BIT_MASK(32))
 		return B43legacy_DMA_32BIT;
@@ -802,7 +811,7 @@ static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask)
 			continue;
 		}
 		if (mask == DMA_BIT_MASK(32)) {
-			mask = DMA_BIT_MASK(30);
+			mask = DMA_BIT_MASK(FB_DMA);
 			fallback = true;
 			continue;
 		}
-- 
2.21.0


^ 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