* [RFC PATCH v3 06/12] mac80211_hwsim: Ext Key ID support (NATIVE)
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Driver is not supporting hardware encryption and therefore fully
compatible with Extended Key ID.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
drivers/net/wireless/mac80211_hwsim.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 87be2b18063a..306583316f5d 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2799,6 +2799,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
ieee80211_hw_set(hw, SIGNAL_DBM);
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, TDLS_WIDER_BW);
+ ieee80211_hw_set(hw, EXT_KEY_ID_NATIVE);
if (rctbl)
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 08/12] iwlwifi: dvm - EXT_KEY_ID A-MPDU API update
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
When using Extended Key ID mac80211 drops @IEEE80211_TX_CTL_AMPDU for
the last packet which can be added to a A-MPDU in preparation.
Don't throw a warning and just handle the frame as if
@IEEE80211_TX_CTL_AMPDU would have been set.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
I cold not figure out so far how to make sure the card will not mix
A-MPDU frames. Looks like that is handled fully in the HW and I didn't
find any interface to influence it. (It even may work already, I have
some problems to capture A-MPDU frames with A-MPDU information intact
and the topic was pretty low on the list so far. After all it works...)
This patch is therefore basically just using aggregation when it's
enabled and ignores the key border signal from mac80211.
drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
index 4ff323a3a4e5..478f8e1c3e52 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
@@ -420,7 +420,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
hdr->seq_ctrl |= cpu_to_le16(seq_number);
seq_number += 0x10;
- if (info->flags & IEEE80211_TX_CTL_AMPDU)
+ if (tid_data->agg.state == IWL_AGG_ON)
is_agg = true;
is_data_qos = true;
}
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 02/12] nl80211/cfg80211: Extended Key ID support
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Add support for IEEE 802.11-2016 "Extended Key ID for Individually
Addressed Frames".
Extends cfg80211 and nl80211 to allow pairwise keys to be installed Rx
only, switch Tx over separately and to use keyidx 1 for pairwise keys.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 23 ++++++++++++++++++++++-
net/wireless/nl80211.c | 32 ++++++++++++++++++++++++++++----
net/wireless/rdev-ops.h | 3 ++-
net/wireless/trace.h | 31 ++++++++++++++++++++++++++-----
net/wireless/util.c | 20 ++++++++++++++------
6 files changed, 94 insertions(+), 17 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7f2739a90bdb..71ebb3492e21 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -485,6 +485,7 @@ struct vif_params {
* with the get_key() callback, must be in little endian,
* length given by @seq_len.
* @seq_len: length of @seq.
+ * @install_mode: key install mode (Rx/Tx, Rx only or set Tx)
*/
struct key_params {
const u8 *key;
@@ -492,6 +493,7 @@ struct key_params {
int key_len;
int seq_len;
u32 cipher;
+ enum nl80211_key_install_mode install_mode;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index dd4f86ee286e..8ccede541913 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4134,6 +4134,21 @@ enum nl80211_channel_type {
NL80211_CHAN_HT40PLUS
};
+/**
+ * enum nl80211_key_install_mode - Key install mode
+ *
+ * @NL80211_KEY_RX_TX: Key must be installed for Rx and Tx
+ * @NL80211_KEY_RX_ONLY: Allowed in combination with @NL80211_CMD_NEW_KEY:
+ * Unicast key has to be installed for Rx only.
+ * @NL80211_KEY_SWITCH_TX: Allowed in combination with @NL80211_CMD_SET_KEY:
+ * Switch Tx to a Rx only, referenced by sta mac and idx.
+ */
+enum nl80211_key_install_mode {
+ NL80211_KEY_RX_TX,
+ NL80211_KEY_RX_ONLY,
+ NL80211_KEY_SWITCH_TX
+};
+
/**
* enum nl80211_chan_width - channel width definitions
*
@@ -4377,6 +4392,9 @@ enum nl80211_key_default_types {
* @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags
* attributes, specifying what a key should be set as default as.
* See &enum nl80211_key_default_types.
+ * @NL80211_KEY_INSTALL_MODE: the install mode from
+ * enum nl80211_key_install_mode. Defaults to @NL80211_KEY_RX_TX.
+ *
* @__NL80211_KEY_AFTER_LAST: internal
* @NL80211_KEY_MAX: highest key attribute
*/
@@ -4390,6 +4408,7 @@ enum nl80211_key_attributes {
NL80211_KEY_DEFAULT_MGMT,
NL80211_KEY_TYPE,
NL80211_KEY_DEFAULT_TYPES,
+ NL80211_KEY_INSTALL_MODE,
/* keep last */
__NL80211_KEY_AFTER_LAST,
@@ -5330,11 +5349,12 @@ enum nl80211_feature_flags {
* by the %NL80211_SCAN_FLAG_MIN_PREQ_CONTENT flag.
* @NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER: Driver supports enabling fine
* timing measurement responder role.
- *
* @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0: Driver/device confirm that they are
* able to rekey an in-use key correctly. Userspace must not rekey PTK keys
* if this flag is not set. Ignoring this can leak clear text packets and/or
* freeze the connection.
+ * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for
+ * Individually Addressed Frames" from IEEE802.11-2016.
*
* @NL80211_EXT_FEATURE_AIRTIME_FAIRNESS: Driver supports getting airtime
* fairness for transmitted packets and has enabled airtime fairness
@@ -5384,6 +5404,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+ NL80211_EXT_FEATURE_EXT_KEY_ID,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a3cc039b9f55..2a076b99737e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -565,6 +565,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
[NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
[NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
+ [NL80211_KEY_INSTALL_MODE] = { .type = NLA_U8 },
};
/* policy for the key default flags */
@@ -970,6 +971,9 @@ static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
}
+ if (tb[NL80211_KEY_INSTALL_MODE])
+ k->p.install_mode = nla_get_u8(tb[NL80211_KEY_INSTALL_MODE]);
+
return 0;
}
@@ -3646,8 +3650,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
if (key.idx < 0)
return -EINVAL;
- /* only support setting default key */
- if (!key.def && !key.defmgmt)
+ /* Only support setting default key and
+ * Extended Key ID action @NL80211_KEY_SWITCH_TX.
+ */
+ if (!key.def && !key.defmgmt &&
+ !(key.p.install_mode == NL80211_KEY_SWITCH_TX))
return -EINVAL;
wdev_lock(dev->ieee80211_ptr);
@@ -3671,7 +3678,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_CFG80211_WEXT
dev->ieee80211_ptr->wext.default_key = key.idx;
#endif
- } else {
+ } else if (key.defmgmt) {
if (key.def_uni || !key.def_multi) {
err = -EINVAL;
goto out;
@@ -3693,8 +3700,25 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_CFG80211_WEXT
dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
#endif
- }
+ } else if (key.p.install_mode == NL80211_KEY_SWITCH_TX &&
+ wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_EXT_KEY_ID)) {
+ u8 *mac_addr = NULL;
+ if (info->attrs[NL80211_ATTR_MAC])
+ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+
+ if (!mac_addr || key.idx < 0 || key.idx > 1) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = rdev_add_key(rdev, dev, key.idx,
+ NL80211_KEYTYPE_PAIRWISE,
+ mac_addr, &key.p);
+ } else {
+ err = -EINVAL;
+ }
out:
wdev_unlock(dev->ieee80211_ptr);
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 5cb48d135fab..4bf4e3774825 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -77,7 +77,8 @@ static inline int rdev_add_key(struct cfg80211_registered_device *rdev,
struct key_params *params)
{
int ret;
- trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
+ trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise,
+ mac_addr, params->install_mode);
ret = rdev->ops->add_key(&rdev->wiphy, netdev, key_index, pairwise,
mac_addr, params);
trace_rdev_return_int(&rdev->wiphy, ret);
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 44b2ce1bb13a..b5c9e6729ff1 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -430,22 +430,43 @@ DECLARE_EVENT_CLASS(key_handle,
BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
);
-DEFINE_EVENT(key_handle, rdev_add_key,
+DEFINE_EVENT(key_handle, rdev_get_key,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
bool pairwise, const u8 *mac_addr),
TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
);
-DEFINE_EVENT(key_handle, rdev_get_key,
+DEFINE_EVENT(key_handle, rdev_del_key,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
bool pairwise, const u8 *mac_addr),
TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
);
-DEFINE_EVENT(key_handle, rdev_del_key,
+TRACE_EVENT(rdev_add_key,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
- bool pairwise, const u8 *mac_addr),
- TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+ bool pairwise, const u8 *mac_addr, u8 install_mode),
+ TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr, install_mode),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(mac_addr)
+ __field(u8, key_index)
+ __field(bool, pairwise)
+ __field(u8, install_mode)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(mac_addr, mac_addr);
+ __entry->key_index = key_index;
+ __entry->pairwise = pairwise;
+ __entry->install_mode = install_mode;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, "
+ "install_mode: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
+ __entry->install_mode, BOOL_TO_STR(__entry->pairwise),
+ MAC_PR_ARG(mac_addr))
);
TRACE_EVENT(rdev_set_default_key,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index cd48cdd582c0..a3338e611190 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -236,14 +236,22 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
- /* Disallow pairwise keys with non-zero index unless it's WEP
- * or a vendor specific cipher (because current deployments use
- * pairwise WEP keys with non-zero indices and for vendor
- * specific ciphers this should be validated in the driver or
- * hardware level - but 802.11i clearly specifies to use zero)
+ /* IEEE802.11-2016 allows only 0 and - when using Extended Key
+ * ID - 1 as index for pairwise keys.
+ * @NL80211_KEY_RX_ONLY is only allowed for pairwise keys when
+ * the driver supports Extended Key ID.
+ * @NL80211_KEY_SWITCH_TX must not be set when validating a key.
*/
- if (pairwise && key_idx)
+ if (params->install_mode == NL80211_KEY_RX_ONLY) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_EXT_KEY_ID))
+ return -EINVAL;
+ else if (!pairwise || key_idx < 0 || key_idx > 1)
+ return -EINVAL;
+ } else if ((pairwise && key_idx) ||
+ params->install_mode == NL80211_KEY_SWITCH_TX) {
return -EINVAL;
+ }
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 04/12] mac80211: Compatibility Extended Key ID support
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Allow drivers to support Extended Key ID when they are not able to
handle two unicast keys per station for Rx by falling back to software
decryption when replacing keys.
Rx HW decryption activation is delayed till we either get the first MPDU
encrypted with the new key or for max 10s.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
Most drivers with the exception of ath10k should be able to support this
mode even without firmware updates from the vendors. (ath10k seems to be
a no-go without some firmware update, but that's not for discussion
here.)
Biggest downside are - besides the added complexity - potential severe
CPU peaks. (Imagine an rebooted AP with hundred of clients using
it with rekeying enabled and a weak CPU.)
Also noteworthy is, that using HW Rx decryption here at all is kind of
breaking the standard: As soon as one Rx key is offloaded to the
hardware we are/may no longer be able to decrypt packets with the "other"
valid keyid. (The hardware may have tried to decrypt it with the wrong
key and then hands over the decryption failure instead of the original
data.) So this will only work correctly as long as the remote sta is
switching to the new keyid at a time within 10s and not mixing old and
new keyids for a while. If that assumption breaks, mac80211 will not be
able to decrypt mangled packets.
That said it seems unlikely that this could be much more than some
retransmits and I get perfect looking rekeys in my test setup with max a
few dozen packets decrypted in software.
include/net/mac80211.h | 46 ++++++++++++++++++++++++++++
net/mac80211/debugfs.c | 1 +
net/mac80211/key.c | 67 +++++++++++++++++++++++++++++++++++++++--
net/mac80211/key.h | 4 +++
net/mac80211/main.c | 3 +-
net/mac80211/rx.c | 7 +++++
net/mac80211/sta_info.c | 3 ++
net/mac80211/sta_info.h | 2 ++
8 files changed, 129 insertions(+), 4 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e16bc7623dc0..eafad5eb8953 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1814,12 +1814,16 @@ struct ieee80211_cipher_scheme {
* @EXT_SET_KEY: a new key must be set but is only valid for decryption
* @EXT_KEY_RX_TX: a key installed with @EXT_SET_KEY is becoming the
* designated Rx/Tx key for the station
+ * @EXT_DISABLE_KEY_RX: installed key must switch to to software decryption
+ * while not altering Tx encryption. Command only required when driver
+ * is using EXT_KEY_ID_COMPAT for Extended Key ID support.
*/
enum set_key_cmd {
SET_KEY,
DISABLE_KEY,
EXT_SET_KEY,
EXT_KEY_RX_TX,
+ EXT_DISABLE_KEY_RX,
};
/**
@@ -2231,6 +2235,10 @@ struct ieee80211_txq {
* @IEEE80211_HW_EXT_KEY_ID_NATIVE: Driver and hardware are supporting Extended
* Key ID and can handle two unicast keys per station for Rx and Tx.
*
+ * @IEEE80211_HW_EXT_KEY_ID_COMPAT: Driver and hardware support Extended Key ID
+ * when mac80211 handles Rx decryption during transition from one keyid to
+ * the next.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2281,6 +2289,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_STA_MMPDU_TXQ,
IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN,
IEEE80211_HW_EXT_KEY_ID_NATIVE,
+ IEEE80211_HW_EXT_KEY_ID_COMPAT,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
@@ -2641,6 +2650,43 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
Mac80211 will not queue any new frames for a deleted key to the driver.
*/
+/**
+ * DOC: Extended Key ID support
+ *
+ * Mac80211 can support "Extended Key ID" from IEEE 802.11-2016, allowing to
+ * rekey the in-use unicast key with ideally zero impact for ongoing
+ * transmissions.
+ *
+ * There are two options for a driver to support Extended Key ID:
+ * 1) Native:
+ * The "Native" Extended Key ID mode is using the key commands
+ * %EXT_SET_KEY, %EXT_KEY_RX_TX and %DISABLE_KEY.
+ * Drivers/cards fully compatible can set @IEEE80211_HW_EXT_KEY_ID_NATIVE,
+ * allowing mac80211 to install two unicast keys per station to the driver.
+ * Mac80211 will then inform the driver via %EXT_SET_KEY when a key must be
+ * added for Rx decryption and again with %EXT_KEY_RX_TX when the driver has
+ * to switch Tx to a new key. When the driver returns any other code than 0
+ * for those two commands the key install is aborted and reported as failed.
+ *
+ * 2) Compatibility
+ * This mode is for Drivers and cards which are not able to handle two
+ * unicast key for a station on Rx, but are fine with it for Tx and can
+ * pass trough the still encrypted MPDUs to mac80211.
+ * The "Compatibility" Extended Key ID mode is using the key commands
+ * %EXT_SET_KEY, %EXT_KEY_RX_TX, %EXT_DISABLE_KEY_RX and %DISABLE_KEY.
+ * A driver setting @IEEE80211_HW_EXT_KEY_ID_COMPAT must
+ * - implement %EXT_DISABLE_KEY_RX to switch a running key to Rx software
+ * decryption without changing Tx handling for the key.
+ * - Add a new key for Tx when called with %EXT_SET_KEY for the same station
+ * with another keyid (to have a key ready allowing Tx)
+ * - Optionally activate Rx decryption when called with %EXT_KEY_RX_TX
+ * Only the command %EXT_KEY_RX_TX is allowed to return a value not 0, any
+ * other command failing will abort the key install.
+ *
+ * Additionally any driver/card setting @IEEE80211_HW_EXT_KEY_ID_NATIVE or
+ * @IEEE80211_HW_EXT_KEY_ID_COMPAT must allow keyid 0 and 1 to for unicast keys.
+ */
+
/**
* DOC: Powersave support
*
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 334a9883894f..01849b093287 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -220,6 +220,7 @@ static const char *hw_flag_names[] = {
FLAG(STA_MMPDU_TXQ),
FLAG(TX_STATUS_NO_AMPDU_LEN),
FLAG(EXT_KEY_ID_NATIVE),
+ FLAG(EXT_KEY_ID_COMPAT),
#undef FLAG
};
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index d91503de1e1d..7f673887ec50 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -184,10 +184,32 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
}
}
- if (rx_only)
+ if (rx_only) {
+ /* EXT_KEY_ID_COMPAT drivers may scramble the payload when
+ * using the wrong HW key for decryption. Therefore only use SW
+ * decryption for the critical window.
+ */
+ if (sta && pairwise && !ext_native && !local->wowlan &&
+ sta->ptk_idx != key->conf.keyidx) {
+ struct ieee80211_key *old;
+
+ old = key_mtx_dereference(local,
+ sta->ptk[sta->ptk_idx]);
+ if (old) {
+ if (drv_set_key(local, EXT_DISABLE_KEY_RX,
+ sdata, &sta->sta, &old->conf))
+ return -EINVAL;
+ }
+ }
+
+ /* Install the key to hardware. EXT_KEY_ID_NATIVE drivers can
+ * use it for decryption but EXT_KEY_ID_COMPAT drivers must
+ * prepare it as a not yet used Tx only key.
+ */
cmd = EXT_SET_KEY;
- else
+ } else {
cmd = SET_KEY;
+ }
ret = drv_set_key(local, cmd, sdata,
sta ? &sta->sta : NULL, &key->conf);
@@ -282,6 +304,7 @@ int ieee80211_key_activate_tx(struct ieee80211_key *key)
struct sta_info *sta = key->sta;
struct ieee80211_local *local = key->local;
struct ieee80211_key *old;
+ bool ext_native = ieee80211_hw_check(&local->hw, EXT_KEY_ID_NATIVE);
int ret;
assert_key_lock(local);
@@ -294,7 +317,7 @@ int ieee80211_key_activate_tx(struct ieee80211_key *key)
IEEE80211_KEY_FLAG_RESERVE_TAILROOM))
increment_tailroom_need_count(sdata);
- if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+ if (ext_native && key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
ret = drv_set_key(local, EXT_KEY_RX_TX, sdata,
&sta->sta, &key->conf);
if (ret) {
@@ -309,6 +332,13 @@ int ieee80211_key_activate_tx(struct ieee80211_key *key)
sta->ptk_idx = key->conf.keyidx;
ieee80211_check_fast_xmit(sta);
+ if (!ext_native && key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+ key->flags |= KEY_FLAG_RX_SW_CRYPTO;
+ /* Activate Rx crypto offload after max 10s when idle */
+ ieee80211_queue_delayed_work(&local->hw, &sta->ext_key_compat_wk,
+ round_jiffies_relative(HZ * 10));
+ }
+
if (old) {
old->flags |= KEY_FLAG_RX_ONLY;
@@ -1109,6 +1139,37 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
mutex_unlock(&local->key_mtx);
}
+/* EXT_KEY_ID_COMPAT support can't install PTK keys to the card/driver for
+ * hardware decryption as long as the remote sta may use both keyids. Those
+ * cards are not aware that the keyid must be checked and try to decrypt the
+ * payload with the wrong key, which would effectively scrambling it. This
+ * worker is therefore used to activate Rx hardware decryption when we assume
+ * there will be only packets for the new key.
+ */
+void ext_key_compat_rx_offload_work(struct work_struct *wk)
+{
+ struct sta_info *sta;
+ struct ieee80211_local *local;
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_key *key;
+
+ sta = container_of(wk, struct sta_info, ext_key_compat_wk.work);
+ local = sta->local;
+ sdata = sta->sdata;
+
+ mutex_lock(&local->key_mtx);
+ key = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
+
+ if (key->flags & KEY_FLAG_RX_SW_CRYPTO)
+ key->flags &= ~KEY_FLAG_RX_SW_CRYPTO;
+
+ if (drv_set_key(local, EXT_KEY_RX_TX, sdata, &sta->sta, &key->conf)) {
+ sdata_info(sdata, "Could not switch Rx to HW crypto (%d, %pM)\n",
+ key->conf.keyidx, sta->sta.addr);
+ }
+ mutex_unlock(&local->key_mtx);
+}
+
void ieee80211_delayed_tailroom_dec(struct work_struct *wk)
{
struct ieee80211_sub_if_data *sdata;
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 1a3da999e0c4..d74c8c36491a 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -32,12 +32,15 @@ struct sta_info;
* @KEY_FLAG_TAINTED: Key is tainted and packets should be dropped.
* @KEY_FLAG_CIPHER_SCHEME: This key is for a hardware cipher scheme
* @KEY_FLAG_RX_ONLY: Pairwise key only allowed to be used on Rx.
+ * @KEY_FLAG_RX_SW_CRYPTO: This key is using Rx SW decryption to work around HW
+ * limitations. Flag can only set when using EXT_KEY_COMPAT for max 10s.
*/
enum ieee80211_internal_key_flags {
KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
KEY_FLAG_TAINTED = BIT(1),
KEY_FLAG_CIPHER_SCHEME = BIT(2),
KEY_FLAG_RX_ONLY = BIT(3),
+ KEY_FLAG_RX_SW_CRYPTO = BIT(4),
};
enum ieee80211_internal_tkip_state {
@@ -167,5 +170,6 @@ void ieee80211_reset_crypto_tx_tailroom(struct ieee80211_sub_if_data *sdata);
rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
void ieee80211_delayed_tailroom_dec(struct work_struct *wk);
+void ext_key_compat_rx_offload_work(struct work_struct *wk);
#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ea34544985f3..dbabfa58c4c9 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1052,7 +1052,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
}
/* mac80211 supports Extended Key ID when driver does */
- if (ieee80211_hw_check(&local->hw, EXT_KEY_ID_NATIVE))
+ if (ieee80211_hw_check(&local->hw, EXT_KEY_ID_COMPAT) ||
+ ieee80211_hw_check(&local->hw, EXT_KEY_ID_NATIVE))
wiphy_ext_feature_set(local->hw.wiphy,
NL80211_EXT_FEATURE_EXT_KEY_ID);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ce786311baf4..95c13f4c7e4a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2015,6 +2015,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
if (unlikely(rx->key->flags & KEY_FLAG_TAINTED))
return RX_DROP_MONITOR;
+ if (unlikely(rx->key->flags & KEY_FLAG_RX_SW_CRYPTO)) {
+ rx->key->flags &= ~KEY_FLAG_RX_SW_CRYPTO;
+ cancel_delayed_work(&rx->sta->ext_key_compat_wk);
+ ieee80211_queue_delayed_work(&rx->local->hw,
+ &rx->sta->ext_key_compat_wk, 0);
+ }
+
/* TODO: add threshold stuff again */
} else {
return RX_DROP_MONITOR;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 09c69955c6e3..a20e05439173 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -132,6 +132,7 @@ static void __cleanup_single_sta(struct sta_info *sta)
if (ieee80211_vif_is_mesh(&sdata->vif))
mesh_sta_cleanup(sta);
+ cancel_delayed_work_sync(&sta->ext_key_compat_wk);
cancel_work_sync(&sta->drv_deliver_wk);
/*
@@ -326,6 +327,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
spin_lock_init(&sta->ps_lock);
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
+ INIT_DELAYED_WORK(&sta->ext_key_compat_wk,
+ ext_key_compat_rx_offload_work);
mutex_init(&sta->ampdu_mlme.mtx);
#ifdef CONFIG_MAC80211_MESH
if (ieee80211_vif_is_mesh(&sdata->vif)) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 304a7ea24757..1fd1a349a875 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -450,6 +450,7 @@ struct ieee80211_sta_rx_stats {
* @sdata: virtual interface this station belongs to
* @ptk: peer keys negotiated with this station, if any
* @ptk_idx: peer key index to use for transmissions
+ * @ext_key_compat_wk: supports PTK key installs when using EXT_KEY_ID_COMPAT
* @gtk: group keys negotiated with this station, if any
* @rate_ctrl: rate control algorithm reference
* @rate_ctrl_lock: spinlock used to protect rate control data
@@ -530,6 +531,7 @@ struct sta_info {
struct ieee80211_sub_if_data *sdata;
struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
+ struct delayed_work ext_key_compat_wk;
u8 ptk_idx;
struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv;
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 05/12] mac80211: Mark A-MPDU keyid borders for drivers
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
IEEE 802.11-2016 "9.7.3 A-MPDU contents" forbids aggregating MPDUs with
different keyids.
Extended Key ID support breaks the assumption that all unicast MPDUs for
one station can always be aggregated.
Inform the drivers about a keyid border by dropping the
@IEEE80211_TX_CTL_AMPDU flag for the last MPDU using the current keyid.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
This patch here is totally unnecessary when we decide that IEEE 802.11 -
2016 is not meaning what is referenced in the commit message above:-)
The exact wording in the standard is:
"All protected MPDUs within an A-MPDU have the same Key ID."
The intent of the wording was probably written without considering
Extended Key IDs. At least it makes no sense for me to forbid mixing
MPDUs using keyid 0 and 1 in one A-MPDU. Nevertheless it says what it
says and there may now be cards/drivers depending on that and e.g. only
check it for the first MPDU. The lost MPDUs would then be our fault, for
aggregating together what according to the standard must not.
But even with that view we still don't need the patch:
A-MPDU aggregation is the job for the driver. We simply can offload the
problem to the drivers.
On the other side mac80211 is in what I consider a better position to
determine and mark the MPDU keyid border, saving the driver the effort
to parse the MPDUs again and keep track of the "current" keyid. It also
allows the driver to terminate a running A-MPDU frame when it gets the
last packet for the old key instead one frame later.
To get around what looked like a nightmare of synchronisation problems
this patch puts the Tx key switch into the Tx path. Handling idle
connections when we don't want to accept that the first packet of a
rekey may still use the key-before-current makes it more complex.
The code is assuming that the driver is not aggregating MPDUs more than
5s apart. We probably don't have wait nearly so long but I'm not sure
what is the minimum time.
The patch also brought up a interesting problem: We are out of sta_info
flags and skb CB also has no room left to add new ones. I worked around
that by redefining how IEEE80211_TX_CTL_AMPDU has to be handled for
Extended Key ID A-MPDU sessions. If you think that puts too much stain
on the API I would need a pointer what would be considered an acceptable
solution to the problem.
But I also fully understand when you think this patch goes too far and
want it thrown out and want it handled somehow else:-).
net/mac80211/key.c | 10 +++++--
net/mac80211/key.h | 1 +
net/mac80211/sta_info.c | 1 +
net/mac80211/sta_info.h | 2 ++
net/mac80211/tx.c | 64 +++++++++++++++++++++++++++++++++++------
5 files changed, 68 insertions(+), 10 deletions(-)
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 7f673887ec50..dee18f61fe33 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -309,6 +309,10 @@ int ieee80211_key_activate_tx(struct ieee80211_key *key)
assert_key_lock(local);
+ /* Two key activations must not overlap */
+ if (WARN_ON(sta->ptk_idx_next != INVALID_PTK_KEYIDX))
+ return -EOPNOTSUPP;
+
key->flags &= ~KEY_FLAG_RX_ONLY;
if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
@@ -329,8 +333,9 @@ int ieee80211_key_activate_tx(struct ieee80211_key *key)
}
old = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
- sta->ptk_idx = key->conf.keyidx;
- ieee80211_check_fast_xmit(sta);
+
+ sta->ptk_idx_next = key->conf.keyidx;
+ key->force_use_after = jiffies + 5 * HZ;
if (!ext_native && key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
key->flags |= KEY_FLAG_RX_SW_CRYPTO;
@@ -577,6 +582,7 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
*/
key->conf.flags = 0;
key->flags = 0;
+ key->force_use_after = 0;
key->conf.cipher = cipher;
key->conf.keyidx = idx;
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index d74c8c36491a..48975d56e792 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -65,6 +65,7 @@ struct ieee80211_key {
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
+ unsigned long force_use_after;
/* for sdata list */
struct list_head list;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a20e05439173..6fe40844f485 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -358,6 +358,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
*/
BUILD_BUG_ON(ARRAY_SIZE(sta->ptk) <= INVALID_PTK_KEYIDX);
sta->ptk_idx = INVALID_PTK_KEYIDX;
+ sta->ptk_idx_next = INVALID_PTK_KEYIDX;
sta->local = local;
sta->sdata = sdata;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 1fd1a349a875..6eff946bc55a 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -450,6 +450,7 @@ struct ieee80211_sta_rx_stats {
* @sdata: virtual interface this station belongs to
* @ptk: peer keys negotiated with this station, if any
* @ptk_idx: peer key index to use for transmissions
+ * @ptk_idx_next: peer key index in activation (Extended Key ID only)
* @ext_key_compat_wk: supports PTK key installs when using EXT_KEY_ID_COMPAT
* @gtk: group keys negotiated with this station, if any
* @rate_ctrl: rate control algorithm reference
@@ -533,6 +534,7 @@ struct sta_info {
struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
struct delayed_work ext_key_compat_wk;
u8 ptk_idx;
+ u8 ptk_idx_next;
struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv;
spinlock_t rate_ctrl_lock;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 111bd6c490a6..d3825eca9e64 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -586,6 +586,51 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
return TX_CONTINUE;
}
+static struct ieee80211_key debug_noinline
+*ieee80211_select_sta_key(struct ieee80211_tx_data *tx)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+ struct sta_info *sta = tx->sta;
+ struct ieee80211_key *key;
+ struct ieee80211_key *next_key;
+
+ key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]);
+
+ if (likely(sta->ptk_idx_next == INVALID_PTK_KEYIDX))
+ return key;
+
+ /* Only when using Extended Key ID the code below can be executed */
+
+ if (!ieee80211_is_data_present(hdr->frame_control))
+ return key;
+
+ if (sta->ptk_idx_next == sta->ptk_idx) {
+ /* First packet using new key with A-MPDU active*/
+ sta->ptk_idx_next = INVALID_PTK_KEYIDX;
+ ieee80211_check_fast_xmit(tx->sta);
+ return key;
+ }
+
+ next_key = rcu_dereference(sta->ptk[sta->ptk_idx_next]);
+ if (!key || !(info->flags & IEEE80211_TX_CTL_AMPDU) ||
+ (next_key->force_use_after &&
+ time_is_before_jiffies(next_key->force_use_after))) {
+ /* nothing special to do, just start using the new key */
+ sta->ptk_idx = sta->ptk_idx_next;
+ sta->ptk_idx_next = INVALID_PTK_KEYIDX;
+ next_key->force_use_after = 0;
+ ieee80211_check_fast_xmit(tx->sta);
+ return next_key;
+ }
+
+ /* Last packet with old key with A-MPDU active */
+ sta->ptk_idx = sta->ptk_idx_next;
+ next_key->force_use_after = 0;
+ info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+ return key;
+}
+
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
{
@@ -595,9 +640,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
tx->key = NULL;
- else if (tx->sta &&
- (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
- tx->key = key;
+ else if (tx->sta)
+ tx->key = ieee80211_select_sta_key(tx);
else if (ieee80211_is_group_privacy_action(tx->skb) &&
(key = rcu_dereference(tx->sdata->default_multicast_key)))
tx->key = key;
@@ -3414,6 +3458,10 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
return false;
+ /* ieee80211_key_activate_tx() requests to change key */
+ if (unlikely(sta->ptk_idx_next != INVALID_PTK_KEYIDX))
+ return false;
+
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
@@ -3556,6 +3604,11 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
if (txq->sta)
tx.sta = container_of(txq->sta, struct sta_info, sta);
+ if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
+ info->flags |= IEEE80211_TX_CTL_AMPDU;
+ else
+ info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+
/*
* The key can be removed while the packet was queued, so need to call
* this here to get the current key.
@@ -3566,11 +3619,6 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
goto begin;
}
- if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
- info->flags |= IEEE80211_TX_CTL_AMPDU;
- else
- info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
struct sta_info *sta = container_of(txq->sta, struct sta_info,
sta);
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 09/12] ath: Basic Extended Key ID support (COMPAT+NATIVE)
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Extend the shared ath key cache code to support Extended Key ID.
The key cache code has to accept unicast keys to use key idx 1 and allow
drivers to enable/disable hardware Rx decryption for a key independent
from Tx.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
I know this is the wrong audience to discuss ath drivers. It's only
included here as an example and POC that the Compatibility Extended Key
ID means for drivers.
This has so far only got the minimal attention needed to get it working
for my AP used for tests. The idea is, to discuss that with the proper
audience once we know what mac80211 Extended Key ID support will look
like.
drivers/net/wireless/ath/ath.h | 7 ++++++-
drivers/net/wireless/ath/key.c | 35 +++++++++++++++++++++++++++++-----
2 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index cc45ccfea5af..465629448fdf 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -202,8 +202,13 @@ void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key);
int ath_key_config(struct ath_common *common,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key);
+ struct ieee80211_key_conf *key,
+ bool rx_accel);
bool ath_hw_keyreset(struct ath_common *common, u16 entry);
+bool ath_hw_rx_crypt(struct ath_common *common,
+ struct ieee80211_key_conf *key,
+ struct ieee80211_sta *sta,
+ bool rx_accel);
void ath_hw_cycle_counters_update(struct ath_common *common);
int32_t ath_hw_get_listen_time(struct ath_common *common);
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c
index 689fab9acf10..ced1c89102ad 100644
--- a/drivers/net/wireless/ath/key.c
+++ b/drivers/net/wireless/ath/key.c
@@ -126,6 +126,23 @@ static bool ath_hw_keysetmac(struct ath_common *common,
return true;
}
+bool ath_hw_rx_crypt(struct ath_common *common,
+ struct ieee80211_key_conf *key,
+ struct ieee80211_sta *sta,
+ bool rx_accel)
+{
+ const u8 *mac = NULL;
+
+ if (!sta || !test_bit(key->hw_key_idx, common->keymap))
+ return false;
+
+ if (rx_accel)
+ mac = sta->addr;
+
+ return ath_hw_keysetmac(common, key->hw_key_idx, mac);
+}
+EXPORT_SYMBOL(ath_hw_rx_crypt);
+
static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
const struct ath_keyval *k,
const u8 *mac)
@@ -473,7 +490,8 @@ static int ath_reserve_key_cache_slot(struct ath_common *common,
int ath_key_config(struct ath_common *common,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
+ struct ieee80211_key_conf *key,
+ bool rx_accel)
{
struct ath_keyval hk;
const u8 *mac = NULL;
@@ -527,21 +545,28 @@ int ath_key_config(struct ath_common *common,
idx = key->keyidx;
break;
}
- } else if (key->keyidx) {
+ } else if (key->keyidx > 1) {
if (WARN_ON(!sta))
return -EOPNOTSUPP;
mac = sta->addr;
if (vif->type != NL80211_IFTYPE_AP) {
- /* Only keyidx 0 should be used with unicast key, but
- * allow this for client mode for now. */
+ /* Only keyidx 0 and when using Extended Key ID 1 should
+ * be used with a unicast key. But allow this for client
+ * mode for now.
+ */
idx = key->keyidx;
} else
return -EIO;
} else {
if (WARN_ON(!sta))
return -EOPNOTSUPP;
- mac = sta->addr;
+
+ /* Handle sta Tx only keys like GTK keys for now */
+ if (rx_accel)
+ mac = sta->addr;
+ else
+ mac = NULL;
idx = ath_reserve_key_cache_slot(common, key->cipher);
}
--
2.20.1
^ permalink raw reply related
* [RFC PATCH v3 01/12] mac80211: Optimize tailroom_needed update checks
From: Alexander Wetzel @ 2019-02-10 21:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190210210620.31181-1-alexander@wetzel-home.de>
Optimize/cleanup the delay tailroom checks and adds one missing tailroom
update.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
It may make sense to write a small macro for support here.
This is only a small tweak/fix of the existing code to fit to how it's
handled in the Extended Key ID patches.
net/mac80211/key.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 37e372896230..b9f2bfc00263 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -140,6 +140,12 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
* so clear that flag now to avoid trying to remove
* it again later.
*/
+ if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
+ !(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
+ increment_tailroom_need_count(sdata);
+
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
return -EINVAL;
}
@@ -179,9 +185,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
if (!ret) {
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
- if (!((key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
- IEEE80211_KEY_FLAG_PUT_MIC_SPACE)) ||
- (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
+ if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
decrease_tailroom_need_count(sdata, 1);
WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
@@ -242,9 +248,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
sta = key->sta;
sdata = key->sdata;
- if (!((key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
- IEEE80211_KEY_FLAG_PUT_MIC_SPACE)) ||
- (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
+ if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
increment_tailroom_need_count(sdata);
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
@@ -1187,9 +1193,9 @@ void ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
- if (!((key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
- IEEE80211_KEY_FLAG_PUT_MIC_SPACE)) ||
- (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
+ if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
+ IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
+ IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
increment_tailroom_need_count(key->sdata);
}
--
2.20.1
^ permalink raw reply related
* linux-next: Signed-off-by missing for commit in the wireless-drivers-next tree
From: Stephen Rothwell @ 2019-02-10 20:28 UTC (permalink / raw)
To: Kalle Valo, Wireless
Cc: Linux Next Mailing List, Linux Kernel Mailing List, Govind Singh
[-- Attachment #1: Type: text/plain, Size: 165 bytes --]
Hi all,
Commit
768ec4c012ac ("ath10k: update HOST capability qmi message")
is missing a Signed-off-by from its author.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH 0/3] libertas_tf: fix setting the hardware address
From: Lubomir Rintel @ 2019-02-10 19:52 UTC (permalink / raw)
To: Kalle Valo; +Cc: David S. Miller, linux-wireless, linux-kernel
Hi,
this short patchset addresses a problem with libertas_tf driver, where
the driver registers the interface without having the MAC address set,
only setting it when the interface is brought up. That is generally too
late, and it confuses NetworkManager.
Some restructuring is needed first, done in first two patches.
Tested on an OLPC XO laptop.
Cheers,
Lubo
^ permalink raw reply
* [PATCH 1/3] libertas_tf: move hardware callbacks to a separate structure
From: Lubomir Rintel @ 2019-02-10 19:52 UTC (permalink / raw)
To: Kalle Valo; +Cc: David S. Miller, linux-wireless, linux-kernel, Lubomir Rintel
In-Reply-To: <20190210195217.18817-1-lkundrak@v3.sk>
We'll need to talk to the firmware to get a hardware address before
device is registered with ieee80211 subsystem at the end of
lbtf_add_card(). Hooking the callbacks after that is too late.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/net/wireless/marvell/libertas_tf/cmd.c | 2 +-
.../net/wireless/marvell/libertas_tf/if_usb.c | 12 +++++++-----
.../wireless/marvell/libertas_tf/libertas_tf.h | 17 +++++++++++------
drivers/net/wireless/marvell/libertas_tf/main.c | 10 ++++++----
4 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c
index 64b147dd2432..130f578daafd 100644
--- a/drivers/net/wireless/marvell/libertas_tf/cmd.c
+++ b/drivers/net/wireless/marvell/libertas_tf/cmd.c
@@ -256,7 +256,7 @@ static void lbtf_submit_command(struct lbtf_private *priv,
command, le16_to_cpu(cmd->seqnum), cmdsize);
lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
- ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
+ ret = priv->ops->hw_host_to_card(priv, MVMS_CMD, (u8 *)cmd, cmdsize);
spin_unlock_irqrestore(&priv->driver_lock, flags);
if (ret) {
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
index 6ede6168bd85..7a5a1a85dcf7 100644
--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
@@ -131,6 +131,12 @@ static void if_usb_fw_timeo(struct timer_list *t)
lbtf_deb_leave(LBTF_DEB_USB);
}
+static const struct lbtf_ops if_usb_ops = {
+ .hw_host_to_card = if_usb_host_to_card,
+ .hw_prog_firmware = if_usb_prog_firmware,
+ .hw_reset_device = if_usb_reset_device,
+};
+
/**
* if_usb_probe - sets the configuration values
*
@@ -216,15 +222,11 @@ static int if_usb_probe(struct usb_interface *intf,
goto dealloc;
}
- priv = lbtf_add_card(cardp, &udev->dev);
+ priv = lbtf_add_card(cardp, &udev->dev, &if_usb_ops);
if (!priv)
goto dealloc;
cardp->priv = priv;
-
- priv->hw_host_to_card = if_usb_host_to_card;
- priv->hw_prog_firmware = if_usb_prog_firmware;
- priv->hw_reset_device = if_usb_reset_device;
cardp->boot2_version = udev->descriptor.bcdDevice;
usb_get_dev(udev);
diff --git a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
index ad77b92d0b41..11d5ff68bc5e 100644
--- a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
+++ b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
@@ -173,10 +173,19 @@ struct channel_range {
struct if_usb_card;
+struct lbtf_ops {
+ /** Hardware access */
+ int (*hw_host_to_card)(struct lbtf_private *priv, u8 type,
+ u8 *payload, u16 nb);
+ int (*hw_prog_firmware)(struct if_usb_card *cardp);
+ int (*hw_reset_device)(struct if_usb_card *cardp);
+};
+
/** Private structure for the MV device */
struct lbtf_private {
void *card;
struct ieee80211_hw *hw;
+ const struct lbtf_ops *ops;
/* Command response buffer */
u8 cmd_resp_buff[LBS_UPLD_SIZE];
@@ -188,11 +197,6 @@ struct lbtf_private {
struct work_struct cmd_work;
struct work_struct tx_work;
- /** Hardware access */
- int (*hw_host_to_card) (struct lbtf_private *priv, u8 type, u8 *payload, u16 nb);
- int (*hw_prog_firmware) (struct if_usb_card *cardp);
- int (*hw_reset_device) (struct if_usb_card *cardp);
-
/** Wlan adapter data structure*/
/** STATUS variables */
@@ -486,7 +490,8 @@ void lbtf_cmd_response_rx(struct lbtf_private *priv);
/* main.c */
struct chan_freq_power *lbtf_get_region_cfp_table(u8 region,
int *cfp_no);
-struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev);
+struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
+ const struct lbtf_ops *ops);
int lbtf_remove_card(struct lbtf_private *priv);
int lbtf_start_card(struct lbtf_private *priv);
int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb);
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index f93b400db949..8ed3cd158cf5 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -281,7 +281,7 @@ static void lbtf_tx_work(struct work_struct *work)
BUG_ON(priv->tx_skb);
spin_lock_irq(&priv->driver_lock);
priv->tx_skb = skb;
- err = priv->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len);
+ err = priv->ops->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len);
spin_unlock_irq(&priv->driver_lock);
if (err) {
dev_kfree_skb_any(skb);
@@ -301,7 +301,7 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
if (!priv->fw_ready)
/* Upload firmware */
- if (priv->hw_prog_firmware(card))
+ if (priv->ops->hw_prog_firmware(card))
goto err_prog_firmware;
/* poke the firmware */
@@ -322,7 +322,7 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
return 0;
err_prog_firmware:
- priv->hw_reset_device(card);
+ priv->ops->hw_reset_device(card);
lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret);
return ret;
}
@@ -605,7 +605,8 @@ EXPORT_SYMBOL_GPL(lbtf_rx);
*
* Returns: pointer to struct lbtf_priv.
*/
-struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
+struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
+ const struct lbtf_ops *ops)
{
struct ieee80211_hw *hw;
struct lbtf_private *priv = NULL;
@@ -622,6 +623,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
priv->hw = hw;
priv->card = card;
+ priv->ops = ops;
priv->tx_skb = NULL;
hw->queues = 1;
--
2.20.1
^ permalink raw reply related
* [PATCH 3/3] libertas_tf: get the MAC address before registering the device
From: Lubomir Rintel @ 2019-02-10 19:52 UTC (permalink / raw)
To: Kalle Valo; +Cc: David S. Miller, linux-wireless, linux-kernel, Lubomir Rintel
In-Reply-To: <20190210195217.18817-1-lkundrak@v3.sk>
The start() callback is too late for this: NetworkManager would already
have seen the hardware, thinking 00:00:00:00:00:00 is its permanent
address.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
.../net/wireless/marvell/libertas_tf/main.c | 57 ++++---------------
1 file changed, 11 insertions(+), 46 deletions(-)
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index b4bd3047eb4e..da53da71987e 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -125,37 +125,6 @@ static void lbtf_cmd_work(struct work_struct *work)
lbtf_deb_leave(LBTF_DEB_CMD);
}
-/**
- * lbtf_setup_firmware: initialize firmware.
- *
- * @priv A pointer to struct lbtf_private structure
- *
- * Returns: 0 on success.
- */
-static int lbtf_setup_firmware(struct lbtf_private *priv)
-{
- int ret = -1;
-
- lbtf_deb_enter(LBTF_DEB_FW);
- /*
- * Read priv address from HW
- */
- eth_broadcast_addr(priv->current_addr);
- ret = lbtf_update_hw_spec(priv);
- if (ret) {
- ret = -1;
- goto done;
- }
-
- lbtf_set_mac_control(priv);
- lbtf_set_radio_control(priv);
-
- ret = 0;
-done:
- lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret);
- return ret;
-}
-
/**
* This function handles the timeout of command sending.
* It will re-send the same command again.
@@ -289,30 +258,17 @@ static void lbtf_tx_work(struct work_struct *work)
static int lbtf_op_start(struct ieee80211_hw *hw)
{
struct lbtf_private *priv = hw->priv;
- int ret = -1;
lbtf_deb_enter(LBTF_DEB_MACOPS);
- /* poke the firmware */
priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
priv->radioon = RADIO_ON;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
- ret = lbtf_setup_firmware(priv);
- if (ret)
- goto err_setup_firmware;
-
- if ((priv->fwrelease < LBTF_FW_VER_MIN) ||
- (priv->fwrelease > LBTF_FW_VER_MAX)) {
- ret = -1;
- goto err_setup_firmware;
- }
+ lbtf_set_mac_control(priv);
+ lbtf_set_radio_control(priv);
lbtf_deb_leave(LBTF_DEB_MACOPS);
return 0;
-
-err_setup_firmware:
- lbtf_deb_leave_args(LBTF_DEB_MACOPS, "fw setup error; ret=%d", ret);
- return ret;
}
static void lbtf_op_stop(struct ieee80211_hw *hw)
@@ -649,6 +605,15 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
goto err_init_adapter;
}
+ eth_broadcast_addr(priv->current_addr);
+ if (lbtf_update_hw_spec(priv))
+ goto err_init_adapter;
+
+ if (priv->fwrelease < LBTF_FW_VER_MIN ||
+ priv->fwrelease > LBTF_FW_VER_MAX) {
+ goto err_init_adapter;
+ }
+
/* The firmware seems to start with the radio enabled. Turn it
* off before an actual mac80211 start callback is invoked.
*/
--
2.20.1
^ permalink raw reply related
* [PATCH 2/3] libertas_tf: don't defer firmware loading until start()
From: Lubomir Rintel @ 2019-02-10 19:52 UTC (permalink / raw)
To: Kalle Valo; +Cc: David S. Miller, linux-wireless, linux-kernel, Lubomir Rintel
In-Reply-To: <20190210195217.18817-1-lkundrak@v3.sk>
In order to be able to get a MAC address before we register the device
with ieee80211 we'll need to load the firmware way earlier.
There seems to be one problem with this: the device seems to start
with radio enabled and starts sending in frames right after the firmware
load finishes. This might be a firmware bug. Disable the radio as soon
as possible.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
.../net/wireless/marvell/libertas_tf/if_usb.c | 24 +++++------
.../marvell/libertas_tf/libertas_tf.h | 5 +--
.../net/wireless/marvell/libertas_tf/main.c | 41 +++++++++++--------
3 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
index 7a5a1a85dcf7..a4b9ede70705 100644
--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
@@ -42,14 +42,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_prog_firmware(struct if_usb_card *cardp);
+static int if_usb_prog_firmware(struct lbtf_private *priv);
static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
uint16_t nb, u8 data);
static void if_usb_free(struct if_usb_card *cardp);
static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
-static int if_usb_reset_device(struct if_usb_card *cardp);
+static int if_usb_reset_device(struct lbtf_private *priv);
/**
* if_usb_wrike_bulk_callback - call back to handle URB status
@@ -222,13 +222,11 @@ static int if_usb_probe(struct usb_interface *intf,
goto dealloc;
}
+ cardp->boot2_version = udev->descriptor.bcdDevice;
priv = lbtf_add_card(cardp, &udev->dev, &if_usb_ops);
if (!priv)
goto dealloc;
- cardp->priv = priv;
- cardp->boot2_version = udev->descriptor.bcdDevice;
-
usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
@@ -253,7 +251,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
lbtf_deb_enter(LBTF_DEB_MAIN);
- if_usb_reset_device(cardp);
+ if_usb_reset_device(priv);
if (priv)
lbtf_remove_card(priv);
@@ -336,8 +334,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
return 0;
}
-static int if_usb_reset_device(struct if_usb_card *cardp)
+static int if_usb_reset_device(struct lbtf_private *priv)
{
+ struct if_usb_card *cardp = priv->card;
struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
int ret;
@@ -808,14 +807,17 @@ static int check_fwfile_format(const u8 *data, u32 totlen)
}
-static int if_usb_prog_firmware(struct if_usb_card *cardp)
+static int if_usb_prog_firmware(struct lbtf_private *priv)
{
+ struct if_usb_card *cardp = priv->card;
int i = 0;
static int reset_count = 10;
int ret = 0;
lbtf_deb_enter(LBTF_DEB_USB);
+ cardp->priv = priv;
+
kernel_param_lock(THIS_MODULE);
ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
if (ret < 0) {
@@ -851,7 +853,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
if (cardp->bootcmdresp <= 0) {
if (--reset_count >= 0) {
- if_usb_reset_device(cardp);
+ if_usb_reset_device(priv);
goto restart;
}
return -1;
@@ -880,7 +882,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
if (!cardp->fwdnldover) {
pr_info("failed to load fw, resetting device!\n");
if (--reset_count >= 0) {
- if_usb_reset_device(cardp);
+ if_usb_reset_device(priv);
goto restart;
}
@@ -889,8 +891,6 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
goto release_fw;
}
- cardp->priv->fw_ready = 1;
-
release_fw:
release_firmware(cardp->fw);
cardp->fw = NULL;
diff --git a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
index 11d5ff68bc5e..3ed1fbe28798 100644
--- a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
+++ b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h
@@ -177,8 +177,8 @@ struct lbtf_ops {
/** Hardware access */
int (*hw_host_to_card)(struct lbtf_private *priv, u8 type,
u8 *payload, u16 nb);
- int (*hw_prog_firmware)(struct if_usb_card *cardp);
- int (*hw_reset_device)(struct if_usb_card *cardp);
+ int (*hw_prog_firmware)(struct lbtf_private *priv);
+ int (*hw_reset_device)(struct lbtf_private *priv);
};
/** Private structure for the MV device */
@@ -254,7 +254,6 @@ struct lbtf_private {
struct ieee80211_supported_band band;
struct lbtf_offset_value offsetvalue;
- u8 fw_ready;
u8 surpriseremoved;
struct sk_buff_head bc_ps_buf;
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index 8ed3cd158cf5..b4bd3047eb4e 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -118,11 +118,6 @@ static void lbtf_cmd_work(struct work_struct *work)
priv->cmd_timed_out = 0;
spin_unlock_irq(&priv->driver_lock);
- if (!priv->fw_ready) {
- lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready");
- return;
- }
-
/* Execute the next command */
if (!priv->cur_cmd)
lbtf_execute_next_command(priv);
@@ -294,36 +289,29 @@ static void lbtf_tx_work(struct work_struct *work)
static int lbtf_op_start(struct ieee80211_hw *hw)
{
struct lbtf_private *priv = hw->priv;
- void *card = priv->card;
int ret = -1;
lbtf_deb_enter(LBTF_DEB_MACOPS);
- if (!priv->fw_ready)
- /* Upload firmware */
- if (priv->ops->hw_prog_firmware(card))
- goto err_prog_firmware;
-
/* poke the firmware */
priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
priv->radioon = RADIO_ON;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
ret = lbtf_setup_firmware(priv);
if (ret)
- goto err_prog_firmware;
+ goto err_setup_firmware;
if ((priv->fwrelease < LBTF_FW_VER_MIN) ||
(priv->fwrelease > LBTF_FW_VER_MAX)) {
ret = -1;
- goto err_prog_firmware;
+ goto err_setup_firmware;
}
lbtf_deb_leave(LBTF_DEB_MACOPS);
return 0;
-err_prog_firmware:
- priv->ops->hw_reset_device(card);
- lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret);
+err_setup_firmware:
+ lbtf_deb_leave_args(LBTF_DEB_MACOPS, "fw setup error; ret=%d", ret);
return ret;
}
@@ -555,6 +543,11 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
lbtf_deb_enter(LBTF_DEB_RX);
+ if (priv->radioon != RADIO_ON) {
+ lbtf_deb_rx("rx before we turned on the radio");
+ goto done;
+ }
+
prxpd = (struct rxpd *) skb->data;
memset(&stats, 0, sizeof(stats));
@@ -593,13 +586,14 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
ieee80211_rx_irqsafe(priv->hw, skb);
+done:
lbtf_deb_leave(LBTF_DEB_RX);
return 0;
}
EXPORT_SYMBOL_GPL(lbtf_rx);
/**
- * lbtf_add_card: Add and initialize the card, no fw upload yet.
+ * lbtf_add_card: Add and initialize the card.
*
* @card A pointer to card
*
@@ -648,6 +642,19 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev,
INIT_WORK(&priv->cmd_work, lbtf_cmd_work);
INIT_WORK(&priv->tx_work, lbtf_tx_work);
+
+ if (priv->ops->hw_prog_firmware(priv)) {
+ lbtf_deb_usbd(&udev->dev, "Error programming the firmware\n");
+ priv->ops->hw_reset_device(priv);
+ goto err_init_adapter;
+ }
+
+ /* The firmware seems to start with the radio enabled. Turn it
+ * off before an actual mac80211 start callback is invoked.
+ */
+ priv->radioon = RADIO_OFF;
+ lbtf_set_radio_control(priv);
+
if (ieee80211_register_hw(hw))
goto err_init_adapter;
--
2.20.1
^ permalink raw reply related
* [PATCH] libertas_tf: fix signal reporting
From: Lubomir Rintel @ 2019-02-10 19:48 UTC (permalink / raw)
To: Kalle Valo; +Cc: David S. Miller, linux-wireless, linux-kernel, Lubomir Rintel
Instead of exposing the signal-to-noise ration, calculate the actual signal
level taking the noise floor into account.
Also, flip the SIGNAL_DBM bit on, so that mac80211 exposes the signal
level along with the station info in scan results. This fills
NetworkManager's "nmcli d wifi output" output with colors, bars and joy.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/net/wireless/marvell/libertas_tf/main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index c71ad87cdc44..f93b400db949 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -562,7 +562,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
stats.flag |= RX_FLAG_FAILED_FCS_CRC;
stats.freq = priv->cur_freq;
stats.band = NL80211_BAND_2GHZ;
- stats.signal = prxpd->snr;
+ stats.signal = prxpd->snr - prxpd->nf;
priv->noise = prxpd->nf;
/* Marvell rate index has a hole at value 4 */
if (prxpd->rx_rate > 4)
@@ -626,6 +626,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
hw->queues = 1;
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
+ ieee80211_hw_set(hw, SIGNAL_DBM);
hw->extra_tx_headroom = sizeof(struct txpd);
memcpy(priv->channels, lbtf_channels, sizeof(lbtf_channels));
memcpy(priv->rates, lbtf_rates, sizeof(lbtf_rates));
--
2.20.1
^ permalink raw reply related
* [PATCH] libertas_tf: move the banner to a more appropriate place
From: Lubomir Rintel @ 2019-02-10 19:48 UTC (permalink / raw)
To: Kalle Valo; +Cc: David S. Miller, linux-wireless, linux-kernel, Lubomir Rintel
Also, turn it to a dev_info() to make checkpatch.pl happy.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/net/wireless/marvell/libertas_tf/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index 1d45da187b9b..c71ad87cdc44 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -318,7 +318,6 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
goto err_prog_firmware;
}
- printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
lbtf_deb_leave(LBTF_DEB_MACOPS);
return 0;
@@ -649,6 +648,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
if (ieee80211_register_hw(hw))
goto err_init_adapter;
+ dev_info(dmdev, "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
goto done;
err_init_adapter:
--
2.20.1
^ permalink raw reply related
* [PATCH] libertas_tf: don't set URB_ZERO_PACKET on IN USB transfer
From: Lubomir Rintel @ 2019-02-10 19:47 UTC (permalink / raw)
To: Kalle Valo
Cc: David S. Miller, linux-wireless, linux-kernel, Lubomir Rintel,
stable
It doesn't make sense and the USB core warns on each submit of such
URB, easily flooding the message buffer with tracebacks.
Analogous issue was fixed in regular libertas driver in commit 6528d8804780
("libertas: don't set URB_ZERO_PACKET on IN USB transfer").
Cc: stable@vger.kernel.org
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/net/wireless/marvell/libertas_tf/if_usb.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
index 789337ea676a..6ede6168bd85 100644
--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
@@ -433,8 +433,6 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
skb_tail_pointer(skb),
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp);
- cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
-
lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n",
cardp->rx_urb);
ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC);
--
2.20.1
^ permalink raw reply related
* [PATCH] libertas_tf: lower the debug level of command trace
From: Lubomir Rintel @ 2019-02-10 19:47 UTC (permalink / raw)
To: Kalle Valo; +Cc: David S. Miller, linux-wireless, linux-kernel, Lubomir Rintel
Logging each and every command response is way too much for INFO level.
Silence this, unless CONFIG_LIBERTAS_THINFIRM_DEBUG has been enabled.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/net/wireless/marvell/libertas_tf/cmd.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c
index 909ac3685010..64b147dd2432 100644
--- a/drivers/net/wireless/marvell/libertas_tf/cmd.c
+++ b/drivers/net/wireless/marvell/libertas_tf/cmd.c
@@ -737,10 +737,9 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
respcmd = le16_to_cpu(resp->command);
result = le16_to_cpu(resp->result);
- if (net_ratelimit())
- pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",
- respcmd, le16_to_cpu(resp->seqnum),
- le16_to_cpu(resp->size));
+ lbtf_deb_cmd("libertastf: cmd response 0x%04x, seq %d, size %d\n",
+ respcmd, le16_to_cpu(resp->seqnum),
+ le16_to_cpu(resp->size));
if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
spin_unlock_irqrestore(&priv->driver_lock, flags);
--
2.20.1
^ permalink raw reply related
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Lorenzo Bianconi @ 2019-02-10 17:39 UTC (permalink / raw)
To: Stefan Wahren
Cc: Stanislaw Gruszka, Felix Fietkau, Doug Anderson,
Minas Harutyunyan, linux-wireless, linux-usb
In-Reply-To: <CAJ0CqmXL_PXf0LuFOnshbYZb=j_KEHyfmV5wpHHW5HXcexhDJA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1062 bytes --]
> > sorry for all the confusion (i never tested the foundation kernel). I made my functional tests with arm/multi_v7_defconfig which doesn't need any patches to work.
> >
> > Here the current results for next-2019-02-08:
> >
> > arm/multi_v7_defconfig w/o any patches -> wlan0 online
> > arm64/defconfig w/o any patches -> timeout during firmware upload
> > arm64/defconfig w Lorenzo's series -> driver probe, but dhcp doesn't work (could be a problem in my arm64 rootfs)
> > arm/multi_v7_defconfig w Stanislaw's patch -> NULL pointer dereference
> >
Hi Stefan,
Could you please try the following patch? It should fix the NULL
pointer dereference crash.
Anyway in order to enable mt76x0u on rpi3 we will need the RFC series
Regards,
Lorenzo
>
> I am looking at this issue, it is not related to Stanislaw's patch,
> there is a bug in the error code path.
> Anyway we will need to avoid SG since dwc_otg controller does not support it
>
> Regards,
> Lorenzo
>
> > I will test linux-4.19 and linux-5.0-rc5 to get a better picture ...
> >
> > >
> > > Stanislaw
[-- Attachment #2: 0001-mt76-fix-NULL-pointer-dereference-in-mt76u_mcu_deini.patch --]
[-- Type: text/x-patch, Size: 2319 bytes --]
From 181a696adeeb77bc4ac05190763240735234fdbb Mon Sep 17 00:00:00 2001
Message-Id: <181a696adeeb77bc4ac05190763240735234fdbb.1549820280.git.me@lorenzobianconi.net>
In-Reply-To: <cover.1549820280.git.me@lorenzobianconi.net>
References: <cover.1549820280.git.me@lorenzobianconi.net>
From: Lorenzo Bianconi <me@lorenzobianconi.net>
Date: Sun, 10 Feb 2019 18:37:38 +0100
Subject: [PATCH] mt76: fix NULL pointer dereference in mt76u_mcu_deinit
Signed-off-by: Lorenzo Bianconi <me@lorenzobianconi.net>
---
drivers/net/wireless/mediatek/mt76/usb.c | 15 ++++-----------
drivers/net/wireless/mediatek/mt76/usb_mcu.c | 8 +++++---
2 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index b061263453d4..15ef1a8754ab 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -765,8 +765,7 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
if (!q->entry)
return -ENOMEM;
- q->ndesc = MT_NUM_TX_ENTRIES;
- for (j = 0; j < q->ndesc; j++) {
+ for (j = 0; j < MT_NUM_TX_ENTRIES; j++) {
buf = &q->entry[j].ubuf;
buf->dev = dev;
@@ -778,6 +777,7 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
if (!buf->urb->sg)
return -ENOMEM;
}
+ q->ndesc = MT_NUM_TX_ENTRIES;
}
return 0;
}
@@ -838,16 +838,9 @@ int mt76u_alloc_queues(struct mt76_dev *dev)
err = mt76u_alloc_rx(dev);
if (err < 0)
- goto err;
-
- err = mt76u_alloc_tx(dev);
- if (err < 0)
- goto err;
+ return err;
- return 0;
-err:
- mt76u_queues_deinit(dev);
- return err;
+ return mt76u_alloc_tx(dev);
}
EXPORT_SYMBOL_GPL(mt76u_alloc_queues);
diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
index 036be4163e69..9527e1216f3d 100644
--- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
@@ -48,9 +48,11 @@ EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx);
void mt76u_mcu_deinit(struct mt76_dev *dev)
{
- struct mt76_usb *usb = &dev->usb;
+ struct mt76u_buf *buf = &dev->usb.mcu.res;
- usb_kill_urb(usb->mcu.res.urb);
- mt76u_buf_free(&usb->mcu.res);
+ if (buf->urb) {
+ usb_kill_urb(buf->urb);
+ mt76u_buf_free(buf);
+ }
}
EXPORT_SYMBOL_GPL(mt76u_mcu_deinit);
--
2.20.1
^ permalink raw reply related
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Lorenzo Bianconi @ 2019-02-10 16:52 UTC (permalink / raw)
To: Stefan Wahren
Cc: Stanislaw Gruszka, Felix Fietkau, Doug Anderson,
Minas Harutyunyan, linux-wireless, linux-usb
In-Reply-To: <307601671.418864.1549816737996@email.ionos.de>
>
> Hi,
>
> > Stanislaw Gruszka <sgruszka@redhat.com> hat am 10. Februar 2019 um 10:29 geschrieben:
> >
> >
> > On Sat, Feb 09, 2019 at 07:46:37PM +0100, Lorenzo Bianconi wrote:
> > > > as already reported here [1], that there are probing issues of mt76 using TP-Link Archer T2UH (wifi USB dongle) on Raspberry Pi 3 B+.
> > > >
> > > > I retested it with recent linux-next 20190208 (aarch64 defconfig + enabling mt76 driver) and got the following output after plugin the wifi dongle:
> > > >
> > > > [ 29.778524] usb 1-1.3: new high-speed USB device number 6 using dwc2
> > > > [ 31.794581] usb 1-1.3: reset high-speed USB device number 6 using dwc2
> > > > [ 31.919916] mt76x0u 1-1.3:1.0: ASIC revision: 76100002 MAC revision: 76502000
> > > > [ 32.304412] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > > [ 32.325724] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > > [ 32.346866] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > > [ 33.410559] mt76x0u 1-1.3:1.0: firmware upload timed out
> > > > [ 33.435458] mt76x0u: probe of 1-1.3:1.0 failed with error -110
> > > > [ 33.454829] usbcore: registered new interface driver mt76x0u
> > > >
> > > > I took the firmware files from here [2].
> > > >
> > > > Btw there is another issue, if i disconnect the wifi dongle during probe i'm getting a endless flood of the following output:
> > > >
> > > > mt76x0u 1.1.3:1.0: rx urb failed: -71
> > > >
> > > > Any chance to narrow down these issues?
> > >
> > > Hi Stefan,
> > >
> > > could you please test the following series:
> > > https://patchwork.kernel.org/cover/10764453/
> > > Applying this series I am able to connect to my home AP using an Asus
> > > USB-AC51 (mt76x0u) connected to a Raspberry Pi 3 B+.
> > > I am running rpi-5.0.y branch of https://github.com/raspberrypi/linux.git
> >
> > How the patch series fixed the issue since it was reported before that
> > it does not work on 4.19.x which do not use scatter gatter I/O ?
> >
> > Or it is regression ? 4.19.x driver works with rasperrypi/linux but -next
> > does not ?
>
> sorry for all the confusion (i never tested the foundation kernel). I made my functional tests with arm/multi_v7_defconfig which doesn't need any patches to work.
>
> Here the current results for next-2019-02-08:
>
> arm/multi_v7_defconfig w/o any patches -> wlan0 online
> arm64/defconfig w/o any patches -> timeout during firmware upload
> arm64/defconfig w Lorenzo's series -> driver probe, but dhcp doesn't work (could be a problem in my arm64 rootfs)
> arm/multi_v7_defconfig w Stanislaw's patch -> NULL pointer dereference
>
I am looking at this issue, it is not related to Stanislaw's patch,
there is a bug in the error code path.
Anyway we will need to avoid SG since dwc_otg controller does not support it
Regards,
Lorenzo
> I will test linux-4.19 and linux-5.0-rc5 to get a better picture ...
>
> >
> > Stanislaw
^ permalink raw reply
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Stefan Wahren @ 2019-02-10 16:38 UTC (permalink / raw)
To: Stanislaw Gruszka, Lorenzo Bianconi
Cc: Felix Fietkau, Doug Anderson, Minas Harutyunyan, linux-wireless,
linux-usb
In-Reply-To: <20190210092943.GA2913@redhat.com>
Hi,
> Stanislaw Gruszka <sgruszka@redhat.com> hat am 10. Februar 2019 um 10:29 geschrieben:
>
>
> On Sat, Feb 09, 2019 at 07:46:37PM +0100, Lorenzo Bianconi wrote:
> > > as already reported here [1], that there are probing issues of mt76 using TP-Link Archer T2UH (wifi USB dongle) on Raspberry Pi 3 B+.
> > >
> > > I retested it with recent linux-next 20190208 (aarch64 defconfig + enabling mt76 driver) and got the following output after plugin the wifi dongle:
> > >
> > > [ 29.778524] usb 1-1.3: new high-speed USB device number 6 using dwc2
> > > [ 31.794581] usb 1-1.3: reset high-speed USB device number 6 using dwc2
> > > [ 31.919916] mt76x0u 1-1.3:1.0: ASIC revision: 76100002 MAC revision: 76502000
> > > [ 32.304412] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > [ 32.325724] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > [ 32.346866] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > [ 33.410559] mt76x0u 1-1.3:1.0: firmware upload timed out
> > > [ 33.435458] mt76x0u: probe of 1-1.3:1.0 failed with error -110
> > > [ 33.454829] usbcore: registered new interface driver mt76x0u
> > >
> > > I took the firmware files from here [2].
> > >
> > > Btw there is another issue, if i disconnect the wifi dongle during probe i'm getting a endless flood of the following output:
> > >
> > > mt76x0u 1.1.3:1.0: rx urb failed: -71
> > >
> > > Any chance to narrow down these issues?
> >
> > Hi Stefan,
> >
> > could you please test the following series:
> > https://patchwork.kernel.org/cover/10764453/
> > Applying this series I am able to connect to my home AP using an Asus
> > USB-AC51 (mt76x0u) connected to a Raspberry Pi 3 B+.
> > I am running rpi-5.0.y branch of https://github.com/raspberrypi/linux.git
>
> How the patch series fixed the issue since it was reported before that
> it does not work on 4.19.x which do not use scatter gatter I/O ?
>
> Or it is regression ? 4.19.x driver works with rasperrypi/linux but -next
> does not ?
sorry for all the confusion (i never tested the foundation kernel). I made my functional tests with arm/multi_v7_defconfig which doesn't need any patches to work.
Here the current results for next-2019-02-08:
arm/multi_v7_defconfig w/o any patches -> wlan0 online
arm64/defconfig w/o any patches -> timeout during firmware upload
arm64/defconfig w Lorenzo's series -> driver probe, but dhcp doesn't work (could be a problem in my arm64 rootfs)
arm/multi_v7_defconfig w Stanislaw's patch -> NULL pointer dereference
I will test linux-4.19 and linux-5.0-rc5 to get a better picture ...
>
> Stanislaw
^ permalink raw reply
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Lorenzo Bianconi @ 2019-02-10 10:22 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: Stefan Wahren, Felix Fietkau, Doug Anderson, Minas Harutyunyan,
linux-wireless, linux-usb
In-Reply-To: <20190210094123.GB2913@redhat.com>
> On Sat, Feb 09, 2019 at 09:29:05PM +0100, Stefan Wahren wrote:
> > > could you please test the following series:
> > > https://patchwork.kernel.org/cover/10764453/
> >
> > yeah this fixed the probing timeout and the driver will probe successful. AFAIK the dwc2 host mode doesn't support scatter-gather yet.
>
> So this is either dwc2 scatter-gather problem which should be addressed in
> this driver or mt76x0u does something wrong when configuring SG.
>
> Disabling SG is just workaround, which do not address actual problem.
>
> I think I found mt76x0u issue that could cause this USB probe error
> (and possibly also address AMD IOMMU issue). We seems do not correctly
> set URB transfer length smaller than sg buffer length. Attached patch
> should correct that.
Hi Stanislaw,
I think 'sg[0].length' is already set in mt76u_fill_rx_sg().
Moreover applying this patch I got the following crash (rpi-5.0.y):
[ 38.856623] mt76x0u 1-1.2:1.0: ASIC revision: 76100002 MAC
revision: 76502000
[ 38.865999] ------------[ cut here ]------------
[ 38.871817] WARNING: CPU: 3 PID: 751 at lib/refcount.c:187
refcount_sub_and_test_checked+0xa4/0xb8
[ 38.883277] refcount_t: underflow; use-after-free.
[ 38.889358] Modules linked in: mt76x0u(+) mt76x0_common mt76x02_usb
mt76_usb mt76x02_lib mt76 mac80211 bnep hci_uart btbcm serdev
bluetooth ecdh_generic spidev brcmfmac brcmutil sha256_generic
cfg80211 rfkill raspberrypi_hwmon hwmon b
cm2835_v4l2(C) i2c_bcm2835 v4l2_common videobuf2_vmalloc
videobuf2_memops snd_bcm2835(C) spi_bcm2835 videobuf2_v4l2
videobuf2_common snd_pcm videodev snd_timer media snd uio_pdrv_genirq
uio fixed i2c_dev ip_tables x_tables ipv6
[ 38.938953] CPU: 3 PID: 751 Comm: systemd-udevd Tainted: G
C 5.0.0-rc5-v7+ #1
[ 38.950574] Hardware name: BCM2835
[ 38.955503] Backtrace:
[ 38.959410] [<8010c91c>] (dump_backtrace) from [<8010cc00>]
(show_stack+0x20/0x24)
[ 38.969952] r6:60000013 r5:ffffffff r4:00000000 r3:a50bade6
[ 38.977198] [<8010cbe0>] (show_stack) from [<807ca5f4>]
(dump_stack+0xc8/0x114)
[ 38.986183] [<807ca52c>] (dump_stack) from [<8011e65c>]
(__warn+0xf4/0x120)
[ 38.994804] r9:000000bb r8:804d0138 r7:00000009 r6:8099dc84
r5:00000000 r4:b9631b58
[ 39.005708] [<8011e568>] (__warn) from [<8011e6d0>]
(warn_slowpath_fmt+0x48/0x50)
[ 39.016372] r9:7f652128 r8:80d1419c r7:80c0bac4 r6:b34a2044
r5:b6096780 r4:00000000
[ 39.027368] [<8011e68c>] (warn_slowpath_fmt) from [<804d0138>]
(refcount_sub_and_test_checked+0xa4/0xb8)
[ 39.040150] r3:80c91c25 r2:8099dc94
[ 39.045296] r4:00000000
[ 39.049320] [<804d0094>] (refcount_sub_and_test_checked) from
[<804d0164>] (refcount_dec_and_test_checked+0x18/0x1c)
[ 39.062966] r4:b6096780 r3:00000001
[ 39.068043] [<804d014c>] (refcount_dec_and_test_checked) from
[<805db49c>] (usb_free_urb+0x20/0x4c)
[ 39.080279] [<805db47c>] (usb_free_urb) from [<7f62d804>]
(mt76u_buf_free+0x98/0xac [mt76_usb])
[ 39.092224] r4:00000001 r3:00000001
[ 39.097386] [<7f62d76c>] (mt76u_buf_free [mt76_usb]) from
[<7f62def8>] (mt76u_queues_deinit+0x44/0x100 [mt76_usb])
[ 39.111016] r8:b791f600 r7:b3628480 r6:b3628e20 r5:00000001
r4:00000000 r3:00000080
[ 39.122039] [<7f62deb4>] (mt76u_queues_deinit [mt76_usb]) from
[<7f650040>] (mt76x0u_cleanup+0x40/0x4c [mt76x0u])
[ 39.135636] r7:b3628480 r6:b791f600 r5:ffffffea r4:b3628e20
[ 39.142968] [<7f650000>] (mt76x0u_cleanup [mt76x0u]) from
[<7f650564>] (mt76x0u_probe+0x1f0/0x354 [mt76x0u])
[ 39.156063] r4:b3628e20 r3:00000000
[ 39.161202] [<7f650374>] (mt76x0u_probe [mt76x0u]) from
[<805e0b6c>] (usb_probe_interface+0x104/0x240)
[ 39.173805] r7:00000000 r6:7f652034 r5:b6299000 r4:b791f620
[ 39.181165] [<805e0a68>] (usb_probe_interface) from [<8056a8bc>]
(really_probe+0x224/0x2f8)
[ 39.192856] r10:b626d800 r9:00000019 r8:7f652034 r7:80d3e124
r6:00000000 r5:80d3e120
[ 39.204057] r4:b791f620 r3:805e0a68
[ 39.209269] [<8056a698>] (really_probe) from [<8056ab60>]
(driver_probe_device+0x6c/0x180)
[ 39.220854] r10:b626d800 r9:7f6522c0 r8:b791f620 r7:00000000
r6:7f652034 r5:7f652034
[ 39.232057] r4:b791f620 r3:00000000
[ 39.237265] [<8056aaf4>] (driver_probe_device) from [<8056ad54>]
(__driver_attach+0xe0/0xe4)
[ 39.248982] r9:7f6522c0 r8:7f65122c r7:00000000 r6:b791f654
r5:7f652034 r4:b791f620
[ 39.260002] [<8056ac74>] (__driver_attach) from [<8056880c>]
(bus_for_each_dev+0x68/0xa0)
[ 39.271498] r6:8056ac74 r5:7f652034 r4:00000000 r3:00000027
[ 39.278885] [<805687a4>] (bus_for_each_dev) from [<8056a1cc>]
(driver_attach+0x28/0x30)
[ 39.290252] r6:80c6ddc8 r5:b6096a00 r4:7f652034
[ 39.296557] [<8056a1a4>] (driver_attach) from [<80569c24>]
(bus_add_driver+0x194/0x21c)
[ 39.307899] [<80569a90>] (bus_add_driver) from [<8056b504>]
(driver_register+0x8c/0x124)
[ 39.319328] r7:80c6ddc8 r6:7f652034 r5:00000000 r4:7f652034
[ 39.326730] [<8056b478>] (driver_register) from [<805df510>]
(usb_register_driver+0x74/0x140)
[ 39.338655] r5:00000000 r4:7f652000
[ 39.343880] [<805df49c>] (usb_register_driver) from [<7f655024>]
(mt76x0_driver_init+0x24/0x1000 [mt76x0u])
[ 39.357002] r9:00000001 r8:7f652308 r7:00000000 r6:80c08d48
r5:7f655000 r4:7f6522c0
[ 39.368143] [<7f655000>] (mt76x0_driver_init [mt76x0u]) from
[<80102f6c>] (do_one_initcall+0x4c/0x210)
[ 39.380894] [<80102f20>] (do_one_initcall) from [<801ae63c>]
(do_init_module+0x6c/0x21c)
[ 39.392392] r8:7f652308 r7:80c08d48 r6:b6116880 r5:7f6522c0
r4:7f6522c0
[ 39.400876] [<801ae5d0>] (do_init_module) from [<801ad68c>]
(load_module+0x1d10/0x2304)
Moreover for mt76x0u SG is 'already' disabled since we use just one
buffer so from performance point of view I do not see any difference
of using a standard usb buffer.
This patch has been tested in multiple scenarios and seems to fix
reported issues (for usb2.0).
Are you concerned about increasing code complexity?
Regards,
Lorenzo
>
> Stanislaw
^ permalink raw reply
* Re: [PATCH v2 3/3] rt2x00: do not print error when queue is full
From: Stanislaw Gruszka @ 2019-02-10 9:57 UTC (permalink / raw)
To: Tom Psyborg
Cc: linux-wireless, Randy Oostdyk, Daniel Golle, Felix Fietkau,
Mathias Kresin
In-Reply-To: <CAKR_QVJtQdRcbRMV+WDKw=N2CxLhUSo6hE8mUME2orD6JEMAmQ@mail.gmail.com>
On Sat, Feb 09, 2019 at 01:28:32PM +0100, Tom Psyborg wrote:
> On 09/02/2019, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> > On Sat, Feb 09, 2019 at 12:11:03PM +0100, Tom Psyborg wrote:
> >> Can you reproduce interface freeze with this patch if you enable debug
> >> options to print all dbg messages?
> >
> > Haven't tried that, but I expect enabling debug messages will
> > cause troubles at hardware where printk make CPU hog.
> >
> > Stanislaw
> >
>
> Take a look at my comment from 23.01.2019. on this link:
> https://bugs.openwrt.org/index.php?do=details&task_id=2018
> There might be a chance dbg printks do not cause problems.
I'm sure printk cause problems on some hardware i.e. Wt3020 .
There is hypothesis that is because kernel try to emit
messages by misconfigured 56k serial line, but who knows.
This should be debugged and fixed but I have not idea how to do this.
Another issue not related with printk is tx queue hung, when
queue is full but we do not get any TX status interrupt. This was
mitigated in my previous set that caused throughput regression and
should be now fixed by latest RFC/RTF set.
But there are other issues, that could cause troubles.
Stanislaw
^ permalink raw reply
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Stanislaw Gruszka @ 2019-02-10 9:41 UTC (permalink / raw)
To: Stefan Wahren
Cc: Lorenzo Bianconi, Felix Fietkau, Doug Anderson, Minas Harutyunyan,
linux-wireless, linux-usb
In-Reply-To: <165515185.283024.1549744145982@email.ionos.de>
[-- Attachment #1: Type: text/plain, Size: 755 bytes --]
On Sat, Feb 09, 2019 at 09:29:05PM +0100, Stefan Wahren wrote:
> > could you please test the following series:
> > https://patchwork.kernel.org/cover/10764453/
>
> yeah this fixed the probing timeout and the driver will probe successful. AFAIK the dwc2 host mode doesn't support scatter-gather yet.
So this is either dwc2 scatter-gather problem which should be addressed in
this driver or mt76x0u does something wrong when configuring SG.
Disabling SG is just workaround, which do not address actual problem.
I think I found mt76x0u issue that could cause this USB probe error
(and possibly also address AMD IOMMU issue). We seems do not correctly
set URB transfer length smaller than sg buffer length. Attached patch
should correct that.
Stanislaw
[-- Attachment #2: 0001-mt76x02-usb-mcu-limit-sg-length.patch --]
[-- Type: text/plain, Size: 1161 bytes --]
From bc09bc7fa604019a5ef90184390e7c2a3899869d Mon Sep 17 00:00:00 2001
From: Stanislaw Gruszka <sgruszka@redhat.com>
Date: Sun, 10 Feb 2019 08:09:48 +0100
Subject: [PATCH] mt76x02: usb_mcu: limit sg length
When sending fw data we limting urb transfer length by changing buf->len,
while keeping segment length at max_payload value. That may confuse
underlying drivers responsible for DMA.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
index da299b8a1334..cfa14506eca6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
@@ -287,6 +287,7 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
MT_FCE_DMA_LEN, len << 16);
buf->len = MT_CMD_HDR_LEN + len + sizeof(info);
+ buf->urb->sg[0].length = buf->len;
err = mt76u_submit_buf(&dev->mt76, USB_DIR_OUT,
MT_EP_OUT_INBAND_CMD,
buf, GFP_KERNEL,
--
2.19.2
^ permalink raw reply related
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Stanislaw Gruszka @ 2019-02-10 9:29 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Stefan Wahren, Felix Fietkau, Doug Anderson, Minas Harutyunyan,
linux-wireless, linux-usb
In-Reply-To: <CAJ0CqmXSuNQ_tQOatyKwO9O2KsxqD5NZRQnngOme5PURssiv5Q@mail.gmail.com>
On Sat, Feb 09, 2019 at 07:46:37PM +0100, Lorenzo Bianconi wrote:
> > as already reported here [1], that there are probing issues of mt76 using TP-Link Archer T2UH (wifi USB dongle) on Raspberry Pi 3 B+.
> >
> > I retested it with recent linux-next 20190208 (aarch64 defconfig + enabling mt76 driver) and got the following output after plugin the wifi dongle:
> >
> > [ 29.778524] usb 1-1.3: new high-speed USB device number 6 using dwc2
> > [ 31.794581] usb 1-1.3: reset high-speed USB device number 6 using dwc2
> > [ 31.919916] mt76x0u 1-1.3:1.0: ASIC revision: 76100002 MAC revision: 76502000
> > [ 32.304412] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > [ 32.325724] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > [ 32.346866] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > [ 33.410559] mt76x0u 1-1.3:1.0: firmware upload timed out
> > [ 33.435458] mt76x0u: probe of 1-1.3:1.0 failed with error -110
> > [ 33.454829] usbcore: registered new interface driver mt76x0u
> >
> > I took the firmware files from here [2].
> >
> > Btw there is another issue, if i disconnect the wifi dongle during probe i'm getting a endless flood of the following output:
> >
> > mt76x0u 1.1.3:1.0: rx urb failed: -71
> >
> > Any chance to narrow down these issues?
>
> Hi Stefan,
>
> could you please test the following series:
> https://patchwork.kernel.org/cover/10764453/
> Applying this series I am able to connect to my home AP using an Asus
> USB-AC51 (mt76x0u) connected to a Raspberry Pi 3 B+.
> I am running rpi-5.0.y branch of https://github.com/raspberrypi/linux.git
How the patch series fixed the issue since it was reported before that
it does not work on 4.19.x which do not use scatter gatter I/O ?
Or it is regression ? 4.19.x driver works with rasperrypi/linux but -next
does not ?
Stanislaw
^ permalink raw reply
* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Stefan Wahren @ 2019-02-09 22:47 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Felix Fietkau, Stanislaw Gruszka, Doug Anderson,
Minas Harutyunyan, linux-wireless, linux-usb
In-Reply-To: <CAJ0CqmXhPRh8L3QkKDEJZffPOKV0TgMg27sdP7UX9PRvEy-eQg@mail.gmail.com>
Hi Lorenzo,
> Lorenzo Bianconi <lorenzo.bianconi@redhat.com> hat am 9. Februar 2019 um 21:33 geschrieben:
>
>
> >
> > Hi Lorenzo,
> >
> > > Lorenzo Bianconi <lorenzo.bianconi@redhat.com> hat am 9. Februar 2019 um 19:46 geschrieben:
> > >
> > >
> > > >
> > > > Hi,
> > > >
> > > > as already reported here [1], that there are probing issues of mt76 using TP-Link Archer T2UH (wifi USB dongle) on Raspberry Pi 3 B+.
> > > >
> > > > I retested it with recent linux-next 20190208 (aarch64 defconfig + enabling mt76 driver) and got the following output after plugin the wifi dongle:
> > > >
> > > > [ 29.778524] usb 1-1.3: new high-speed USB device number 6 using dwc2
> > > > [ 31.794581] usb 1-1.3: reset high-speed USB device number 6 using dwc2
> > > > [ 31.919916] mt76x0u 1-1.3:1.0: ASIC revision: 76100002 MAC revision: 76502000
> > > > [ 32.304412] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > > [ 32.325724] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > > [ 32.346866] dwc2 3f980000.usb: dwc2_update_urb_state(): trimming xfer length
> > > > [ 33.410559] mt76x0u 1-1.3:1.0: firmware upload timed out
> > > > [ 33.435458] mt76x0u: probe of 1-1.3:1.0 failed with error -110
> > > > [ 33.454829] usbcore: registered new interface driver mt76x0u
> > > >
> > > > I took the firmware files from here [2].
> > > >
> > > > Btw there is another issue, if i disconnect the wifi dongle during probe i'm getting a endless flood of the following output:
> > > >
> > > > mt76x0u 1.1.3:1.0: rx urb failed: -71
> > > >
> > > > Any chance to narrow down these issues?
> > >
> > > Hi Stefan,
> > >
> > > could you please test the following series:
> > > https://patchwork.kernel.org/cover/10764453/
> >
> > yeah this fixed the probing timeout and the driver will probe successful. AFAIK the dwc2 host mode doesn't support scatter-gather yet.
> >
>
> Hi Stefan,
>
> is the dongle working properly now? Are you able to connect to your AP?
i successful tested STA mode with 2.4 GHz and 5 GHz.
>
> > > Applying this series I am able to connect to my home AP using an Asus
> > > USB-AC51 (mt76x0u) connected to a Raspberry Pi 3 B+.
> > > I am running rpi-5.0.y branch of https://github.com/raspberrypi/linux.git
> >
> > The foundation kernel uses a different USB driver called dwc-otg which make use of FIQ.
> >
> > Okay, now we only need to find a solution for the "rx urb failed" flood ;-)
>
> Does it happen just if you remove the dongle during probe?
I also see those messages while disconnecting after a successful probe but in this case the messages stopps after a few seconds. In case of a disconnect while probing the flood never ends. It looks like the rx tasklet is triggered forever.
Stefan
>
> Regards,
> Lorenzo
>
^ permalink raw reply
* Re: [PATCH 00/13] rtlwifi: Replace old-style license info with SPDX form
From: Larry Finger @ 2019-02-09 21:03 UTC (permalink / raw)
To: Joe Perches, kvalo; +Cc: linux-wireless, pkshih
In-Reply-To: <50b60844f3ac435a41ff99a3043ee10133e30870.camel@perches.com>
On 2/8/19 9:00 PM, Joe Perches wrote:
> On Fri, 2019-02-08 at 11:21 -0600, Larry Finger wrote:
>> These patches change all the license information from the old-stype format
>> to the newer SPDX format. There are no code changes.
>
> About some of the removals:
>
>> Copyright(c) 2009-2012 Realtek Corporation.
>
> I believe these copyright markings should _not_ be removed.
I thought I did keep the Copyright information. I have now checked twice to
verify that it was done correctly, and that the original dates were kept. If I
missed any, I have not found that instance. Please let me know which ones you saw.
>
>> - * Contact Information:
>> - * wlanfae <wlanfae@realtek.com
>> - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
>> - * Hsinchu 300, Taiwan.
>
> Why take out the contact information? Is it invalid?
Realtek no longer supplies that info with their latest drivers, thus I removed
it here. That E-mail address is a dummy that people report is never answered - I
have not personally tried it.
Larry
>
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox