* [PATCH v2 3/4] mac80211: Compatibility Extended Key ID support
From: Alexander Wetzel @ 2019-03-19 20:34 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
In-Reply-To: <20190319203410.25145-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.
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
include/net/mac80211.h | 48 +++++++++++++++++++++++++++++-
net/mac80211/debugfs.c | 1 +
net/mac80211/key.c | 65 ++++++++++++++++++++++++++++++++++++-----
net/mac80211/key.h | 5 ++++
net/mac80211/main.c | 6 ++--
net/mac80211/rx.c | 6 ++++
net/mac80211/sta_info.c | 2 ++
net/mac80211/sta_info.h | 3 ++
8 files changed, 126 insertions(+), 10 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c10abca55fde..56b1c1ca39a6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1829,9 +1829,17 @@ struct ieee80211_cipher_scheme {
*
* @SET_KEY: a key is set
* @DISABLE_KEY: a key must be disabled
+ *
+ * Additional driver commands for COMPAT Extended Key ID support:
+ *
+ * @ENABLE_KEY_RX: Rx acceleration can be activated for a key
+ * @DISABLE_KEY_RX: Rx acceleration must be deactivated for a key
*/
enum set_key_cmd {
- SET_KEY, DISABLE_KEY,
+ SET_KEY,
+ DISABLE_KEY,
+ ENABLE_KEY_RX,
+ DISABLE_KEY_RX,
};
/**
@@ -2248,6 +2256,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 {
@@ -2300,6 +2312,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_MULTI_BSSID,
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
IEEE80211_HW_EXT_KEY_ID_NATIVE,
+ IEEE80211_HW_EXT_KEY_ID_COMPAT,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
@@ -2660,6 +2673,39 @@ 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 supports "Extended Key ID" from IEEE 802.11-2016, allowing to rekey
+ * the in-use unicast key with no impact for ongoing transmissions.
+ *
+ * There are two ways mac80211 drivers can support Extended Key ID:
+ * 1) Native
+ * When using "Native" Extended Key ID mode mac80211 can install two unicast
+ * keys per station to the driver, using the two key IDs "0" and "1".
+ * Compatible drivers/cards can simply set @IEEE80211_HW_EXT_KEY_ID_NATIVE,
+ * allowing mac80211 to install two unicast keys per station to the driver
+ * with %SET_KEY. Mac80211 uses the Native mode when the driver is either
+ * setting @IEEE80211_HW_EXT_KEY_ID_NATIVE or is not providing a callback
+ * for set_key().
+ *
+ * 2) Compatibility
+ * This mode is for drivers and cards which are not able to handle two
+ * unicast key for a station for Rx. For drivers setting
+ * @IEEE80211_HW_EXT_KEY_ID_COMPAT mac80211 will make sure that never more
+ * than one unicast key is active for Rx in the hardware, falling back to
+ * software decryption while installing a new unicast key. Divers using this
+ * mode must implement the additional key commands %ENABLE_KEY_RX and
+ * %DISABLE_KEY_RX to allow switching Rx crypto offload on and off without
+ * impact for Tx. Drivers also must not activate Rx crypto offload when
+ * %SET_KEY is called for a key with @IEEE80211_KEY_FLAG_NO_AUTO_TX set.
+ * Compatibility mode will only be really lossless when there is a clean cut
+ * over to the new key and MPDUs using both key IDs are not mixed. It can
+ * also cause CPU spikes when falling back to software encryption, depending
+ * on the amount of Rx packets at that time. Mac80211 uses the Compatibility
+ * mode when the driver is setting @IEEE80211_HW_EXT_KEY_ID_COMPAT.
+ */
+
/**
* DOC: Powersave support
*
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index aa6f23e1a457..9c4899aaf346 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -222,6 +222,7 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_MULTI_BSSID),
FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
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 20bf9db7a388..bd38167916ad 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -127,7 +127,9 @@ static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata,
static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
{
struct ieee80211_sub_if_data *sdata = key->sdata;
+ struct ieee80211_local *local = key->local;
struct sta_info *sta;
+ bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
int ret = -EOPNOTSUPP;
might_sleep();
@@ -150,10 +152,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
return -EINVAL;
}
- if (!key->local->ops->set_key)
+ if (!local->ops->set_key)
goto out_unsupported;
- assert_key_lock(key->local);
+ assert_key_lock(local);
sta = key->sta;
@@ -161,8 +163,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
* If this is a per-STA GTK, check if it
* is supported; if not, return.
*/
- if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
- !ieee80211_hw_check(&key->local->hw, SUPPORTS_PER_STA_GTK))
+ if (sta && !pairwise &&
+ !ieee80211_hw_check(&local->hw, SUPPORTS_PER_STA_GTK))
goto out_unsupported;
if (sta && !sta->uploaded)
@@ -173,13 +175,33 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
* The driver doesn't know anything about VLAN interfaces.
* Hence, don't send GTKs for VLAN interfaces to the driver.
*/
- if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+ if (!pairwise) {
ret = 1;
goto out_unsupported;
}
}
- ret = drv_set_key(key->local, SET_KEY, sdata,
+ if (key->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX) {
+ /* 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 && !local->wowlan &&
+ ieee80211_hw_check(&local->hw, EXT_KEY_ID_COMPAT) &&
+ 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, DISABLE_KEY_RX,
+ sdata, &sta->sta, &old->conf))
+ return -EINVAL;
+ }
+ }
+ }
+
+ ret = drv_set_key(local, SET_KEY, sdata,
sta ? &sta->sta : NULL, &key->conf);
if (!ret) {
@@ -221,7 +243,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
/* all of these we can do in software - if driver can */
if (ret == 1)
return 0;
- if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL))
+ if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL))
return -EINVAL;
return 0;
default:
@@ -276,6 +298,10 @@ int ieee80211_set_tx_key(struct ieee80211_key *key)
sta->ptk_idx = key->conf.keyidx;
ieee80211_check_fast_xmit(sta);
+ if (ieee80211_hw_check(&local->hw, EXT_KEY_ID_COMPAT) &&
+ key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
+ key->flags |= KEY_FLAG_DELAYED_RX_ACCEL;
+
return 0;
}
@@ -1063,6 +1089,31 @@ 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
+ * the remote sta has switched over to the new key.
+ */
+void delayed_rx_accel_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, delayed_rx_accel_wk);
+ local = sta->local;
+ sdata = sta->sdata;
+
+ mutex_lock(&local->key_mtx);
+ key = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
+ drv_set_key(local, ENABLE_KEY_RX, sdata, &sta->sta, &key->conf);
+
+ 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 f06fbd03d235..21e8618b1d55 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -31,11 +31,15 @@ struct sta_info;
* in the hardware for TX crypto hardware acceleration.
* @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_DELAYED_RX_ACCEL: This key has to use Rx SW decryption till we get
+ * at least one MPDU from the remote sta encrypted with the key. (Needed
+ * for COMPAT Extended ID support.)
*/
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_DELAYED_RX_ACCEL = BIT(3),
};
enum ieee80211_internal_tkip_state {
@@ -165,5 +169,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 delayed_rx_accel_work(struct work_struct *wk);
#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 2dea3fe3a35d..0563c7e84ea4 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1058,11 +1058,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
switch (ieee80211_extended_key_id) {
case 2:
- /* Force on */
- ieee80211_hw_set(&local->hw, EXT_KEY_ID_NATIVE);
+ /* Force on when driver is not supporting COMPAT mode */
+ if (!ieee80211_hw_check(&local->hw, EXT_KEY_ID_COMPAT))
+ ieee80211_hw_set(&local->hw, EXT_KEY_ID_NATIVE);
/* fall trough */
case 1:
if (!local->ops->set_key ||
+ 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 4a03c18b39a8..e3e4fb1073d6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2032,6 +2032,12 @@ 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_DELAYED_RX_ACCEL)) {
+ rx->key->flags &= ~KEY_FLAG_DELAYED_RX_ACCEL;
+ ieee80211_queue_work(&rx->local->hw,
+ &rx->sta->delayed_rx_accel_wk);
+ }
+
/* 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 7c61f6aee873..41ea1d05a946 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_work_sync(&sta->delayed_rx_accel_wk);
cancel_work_sync(&sta->drv_deliver_wk);
/*
@@ -326,6 +327,7 @@ 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_WORK(&sta->delayed_rx_accel_wk, delayed_rx_accel_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 71f7e4973329..45f7cbfe9698 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -450,6 +450,8 @@ struct ieee80211_sta_rx_stats {
* @sdata: virtual interface this station belongs to
* @ptk: peer keys negotiated with this station, if any
* @ptk_idx: last installed peer key index
+ * @delayed_rx_accel_wk: Used to activate Rx crypto offload only after
+ * we have seen one MPDU encrypted with the key.
* @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 +532,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 work_struct delayed_rx_accel_wk;
u8 ptk_idx;
struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv;
--
2.21.0
^ permalink raw reply related
* [PATCH v2 0/4] Extended Key ID support
From: Alexander Wetzel @ 2019-03-19 20:34 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Alexander Wetzel
This patch series adds support for IEEE 802.11-2016 Extended Key ID
support. Compared to the last RFC there are again quite some API
changes, but also some bug fixes. (The bug fixes I remember are outlined
in the different patches.)
The main differences are:
1) This series drops support to let the driver decide which key/keyid
shall be used to encrypt a MPDU. The drivers must now always encrypt
the MPDU with the key mac80211 has selected for it. This allows us to
use the "normal" key install API for drivers and gets rid of special
calls for Extended Key ID between mac80211 and the drivers.
2) It also drops the overly complex handling for tailroom needed and
just handles the Rx-only keys like Rx/Tx ones.
3) The "old" Rx-only key flag has been replaced by
IEEE80211_KEY_FLAG_NO_AUTO_TX. It's no longer cleared and primarily
intended to stop ieee80211_key_replace() to activating the key for
Tx, but also allows COMPAT driver to determine if Rx HW crypto can be
activated or not.
4) COMPAT Extended Key ID will enable Rx decryption offload only after
(at least) one MPDU has been decoded for the key with SW crypto.
5) COMPAT Extended Key ID support now has two dedicated key calls for
activating/deactivating Rx HW offload.
6) A-MPDU border signal is now generated unconditionally, so there will
always be one more packet with the old key, regardless of the time
passed since the new key has been activated.
I think the API here is much simpler to understand and use, but it's
also a reversal of the decision from the first RFC version to not use
key flags to distinguish between normal and Extended Key ID installs.
(Normally only COMPAT drivers should care about the flag.)
I've tested the patches, but mostly only the full series.
Changes compared to v1 of the patch:
- Native Extended Key ID is enabled automatically for drivers not
supporting hardware encryption and do not offer a set_key() callback.
Alexander Wetzel (4):
nl80211/cfg80211: Extended Key ID support
mac80211: IEEE 802.11 Extended Key ID support
mac80211: Compatibility Extended Key ID support
mac80211: Mark A-MPDU keyid borders for drivers
include/net/cfg80211.h | 2 +
include/net/mac80211.h | 58 +++++++++++++-
include/uapi/linux/nl80211.h | 28 +++++++
net/mac80211/cfg.c | 36 +++++++++
net/mac80211/debugfs.c | 2 +
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/key.c | 143 ++++++++++++++++++++++++++++++-----
net/mac80211/key.h | 7 ++
net/mac80211/main.c | 24 ++++++
net/mac80211/rx.c | 80 +++++++++++---------
net/mac80211/sta_info.c | 12 +++
net/mac80211/sta_info.h | 7 +-
net/mac80211/tx.c | 73 +++++++++++++-----
net/wireless/nl80211.c | 32 +++++++-
net/wireless/rdev-ops.h | 3 +-
net/wireless/trace.h | 31 ++++++--
net/wireless/util.c | 21 +++--
17 files changed, 468 insertions(+), 93 deletions(-)
--
2.21.0
^ permalink raw reply
* [PATCH] ath10k: Fix ASPM L1 state on QCA988X
From: Tomislav Požega @ 2019-03-19 19:59 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Sujith Manoharan
On some systems there are heavy crashes if the kernel config
option CONFIG_PCIEASPM_PERFORMANCE is not set. Patch provided by
Sujith for ath9k fixes this issue and the card operates without
crashes with kernel default CONFIG_PCIEASPM_DEFAULT option that uses
BIOS provided ASPM settings. Tested with QCA9862 mPCIe card.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
---
drivers/net/wireless/ath/ath10k/pci.c | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 271f92c..e24403c 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -2787,14 +2787,25 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar,
enum ath10k_firmware_mode fw_mode)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ struct pci_dev *pdev = ar_pci->pdev;
int ret;
+ u32 val;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n");
- pcie_capability_read_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+ if (ar->dev_id == QCA988X_2_0_DEVICE_ID) {
+ pci_read_config_dword(pdev, 0x70c, &val);
+ if ((val & 0xff000000) == 0x17000000) {
+ val &= 0x00ffffff;
+ val |= 0x27000000;
+ pci_write_config_dword(pdev, 0x570c, val);
+ }
+ } else {
+ pcie_capability_read_word(ar_pci->pdev, PCI_EXP_LNKCTL,
&ar_pci->link_ctl);
- pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+ pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL,
ar_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
+ }
/*
* Bring the target up cleanly.
--
1.7.0.4
^ permalink raw reply related
* Re: pull-request: wireless-drivers 2019-03-19
From: David Miller @ 2019-03-19 19:47 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <87pnqm4pmf.fsf@kamboji.qca.qualcomm.com>
From: Kalle Valo <kvalo@codeaurora.org>
Date: Tue, 19 Mar 2019 21:43:04 +0200
> here are some fixes to net tree for 5.1. Please let me know if there are
> any problems.
Pulled, thanks Kalle.
^ permalink raw reply
* pull-request: wireless-drivers 2019-03-19
From: Kalle Valo @ 2019-03-19 19:43 UTC (permalink / raw)
To: David Miller; +Cc: linux-wireless, netdev, linux-kernel
Hi Dave,
here are some fixes to net tree for 5.1. Please let me know if there are
any problems.
Kalle
The following changes since commit 4177c5d94264b57f426ef5c45a788808d1a1e536:
net/sched: act_tunnel_key: Fix double free dst_cache (2019-03-05 12:57:28 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git tags/wireless-drivers-for-davem-2019-03-19
for you to fetch changes up to 7dfc45e6282a7662279d168cc1219929456f8750:
mt76x02: do not enable RTS/CTS by default (2019-03-19 17:37:25 +0200)
----------------------------------------------------------------
wireless-drivers fixes for 5.1
First set of fixes for 5.1. Lots of fixes for mt76 this time.
iwlwifi
* fix warning with do_div()
mt7601u
* avoid using hardware which is supported by mt76
mt76
* more fixes for hweight8() usage
* fix hardware restart for mt76x2
* fix writing txwi on USB devices
* fix (and disable by default) ED/CCA support on 76x2
* fix powersave issues on 7603
* fix return value check for ioremap on 7603
* fix duplicate USB device IDs
----------------------------------------------------------------
Arnd Bergmann (1):
iwlwifi: fix 64-bit division
Felix Fietkau (16):
mt76: rewrite dma descriptor base and ring size on queue reset
mt76: mt76x02: when setting a key, use PN from mac80211
mt76: mt76x2: implement full device restart on watchdog reset
mt76: mt76x02: only update the base mac address if necessary
mt76: mt76x02: reduce false positives in ED/CCA tx blocking
mt76: mt7603: fix tx status HT rate validation
mt76: mt76x2: fix external LNA gain settings
mt76: mt76x2: fix 2.4 GHz channel gain settings
mt76: mt7603: clear ps filtering mode before releasing buffered frames
mt76: mt7603: fix up hardware queue index for PS filtered packets
mt76: mt7603: notify mac80211 about buffered frames in ps queue
mt76: mt7603: clear the service period on releasing PS filtered packets
mt76: when releasing PS frames, end the service period if no frame was found
mt76: mt76x02: disable ED/CCA by default
mt76: mt7603: set moredata flag when queueing ps-filtered packets
mt76: mt7603: use the correct hweight8() function
Kalle Valo (1):
Merge tag 'mt76-for-kvalo-2019-03-07' of https://github.com/nbd168/wireless
Lorenzo Bianconi (3):
mt76: introduce q->stopped parameter
mt76x2u: remove duplicated entry in mt76x2u_device_table
mt76: fix schedule while atomic in mt76x02_reset_state
Stanislaw Gruszka (4):
mt76x02: fix hdr pointer in write txwi for USB
mt7601u: check chip version on probe
mt76x02u: check chip version on probe
mt76x02: do not enable RTS/CTS by default
Wei Yongjun (1):
mt76: fix return value check in mt76_wmac_probe()
.../net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 4 +-
drivers/net/wireless/mediatek/mt76/dma.c | 7 +-
drivers/net/wireless/mediatek/mt76/mac80211.c | 18 +++--
drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++
drivers/net/wireless/mediatek/mt76/mt7603/beacon.c | 3 +-
drivers/net/wireless/mediatek/mt76/mt7603/dma.c | 17 ++++-
drivers/net/wireless/mediatek/mt76/mt7603/init.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7603/main.c | 16 +++++
drivers/net/wireless/mediatek/mt76/mt7603/mcu.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7603/soc.c | 4 +-
.../net/wireless/mediatek/mt76/mt76x0/initvals.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 10 ++-
drivers/net/wireless/mediatek/mt76/mt76x02.h | 11 +++
.../net/wireless/mediatek/mt76/mt76x02_debugfs.c | 27 +++++++
drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c | 3 +-
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 67 ++++++++++++++++--
drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 +
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 82 +++++++++++++++++++---
drivers/net/wireless/mediatek/mt76/mt76x02_phy.c | 2 +
.../net/wireless/mediatek/mt76/mt76x02_usb_core.c | 3 +-
drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 14 ++--
drivers/net/wireless/mediatek/mt76/mt76x2/init.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h | 1 +
.../net/wireless/mediatek/mt76/mt76x2/pci_init.c | 2 +-
.../net/wireless/mediatek/mt76/mt76x2/pci_mcu.c | 21 ++++++
drivers/net/wireless/mediatek/mt76/mt76x2/phy.c | 30 +++++---
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 7 +-
.../net/wireless/mediatek/mt76/mt76x2/usb_mac.c | 1 -
drivers/net/wireless/mediatek/mt76/tx.c | 11 ++-
drivers/net/wireless/mediatek/mt76/usb.c | 6 +-
drivers/net/wireless/mediatek/mt7601u/usb.c | 4 ++
32 files changed, 329 insertions(+), 58 deletions(-)
--
Kalle Valo
^ permalink raw reply
* [PATCH] net:mwl8k:move spin_lock_bh to spin_lock in tasklet
From: Jeff Xie @ 2019-03-19 16:24 UTC (permalink / raw)
To: buytenh, kvalo; +Cc: davem, chongguiguzi, linux-wireless, netdev, linux-kernel
It is unnecessary to call spin_lock_bh in a tasklet.
Signed-off-by: Jeff Xie <chongguiguzi@gmail.com>
---
drivers/net/wireless/marvell/mwl8k.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c
index 8e4e9b6..21a86cc 100644
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
@@ -4631,7 +4631,7 @@ static void mwl8k_tx_poll(unsigned long data)
limit = 32;
- spin_lock_bh(&priv->tx_lock);
+ spin_lock(&priv->tx_lock);
for (i = 0; i < mwl8k_tx_queues(priv); i++)
limit -= mwl8k_txq_reclaim(hw, i, limit, 0);
@@ -4641,7 +4641,7 @@ static void mwl8k_tx_poll(unsigned long data)
priv->tx_wait = NULL;
}
- spin_unlock_bh(&priv->tx_lock);
+ spin_unlock(&priv->tx_lock);
if (limit) {
writel(~MWL8K_A2H_INT_TX_DONE,
--
2.7.4
^ permalink raw reply related
* Re: [RFC] mt76: usb: reduce locking in mt76u_tx_tasklet
From: Lorenzo Bianconi @ 2019-03-19 16:23 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Lorenzo Bianconi, nbd, linux-wireless
In-Reply-To: <20190319160426.GA15616@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 2457 bytes --]
> On Tue, Mar 19, 2019 at 01:58:13PM +0100, Lorenzo Bianconi wrote:
> > > On Mon, Mar 18, 2019 at 12:09:32PM +0100, Lorenzo Bianconi wrote:
> > > > Similar to pci counterpart, reduce locking in mt76u_tx_tasklet since
> > > > q->head is managed just in mt76u_tx_tasklet and q->queued is updated
> > > > holding q->lock
> > > >
> > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > ---
> > > > drivers/net/wireless/mediatek/mt76/usb.c | 18 +++++++++++-------
> > > > 1 file changed, 11 insertions(+), 7 deletions(-)
> > > >
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> > > > index ac03acdae279..8cd70c32d77a 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/usb.c
> > > > +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> > > > @@ -634,29 +634,33 @@ static void mt76u_tx_tasklet(unsigned long data)
> > > > int i;
> > > >
> > > > for (i = 0; i < IEEE80211_NUM_ACS; i++) {
> > > > + u32 n_queued = 0, n_sw_queued = 0;
> > > > +
> > > > sq = &dev->q_tx[i];
> > > > q = sq->q;
> > > >
> > > > - spin_lock_bh(&q->lock);
> > > > - while (true) {
> > > > + while (q->queued > n_queued) {
> > > > buf = &q->entry[q->head].ubuf;
> > > > - if (!buf->done || !q->queued)
> > > > + if (!buf->done)
> > > > break;
> > >
> > > I'm still thinking if this is safe or not. Is somewhat tricky to
> > > read variable outside the lock because in such case there is no time
> > > guarantee when variable written on one CPU gets updated value on
> > > different CPU. And for USB is not only q->queued but also buf->done.
> >
> > Hi Stanislaw,
> >
> > I was wondering if this is safe as well, but q->queued is updated holding q->lock
> > and I guess it will ensure to not overlap tx and status code path.
>
> Overlap will not happen, at worst what can happen is q->queued will be
> smaller on tx_tasklet than on tx_queue_skb.
Yes, that is the point :)
>
> > Regarding buf->done, it is already updated without holding the lock in mt76u_complete_tx
>
> That's actually a bug, but it's not important, if tx_tasklet will not
> see updated buf->done <- true value by mt76u_complete_tx on different
> cpu, it will not complete skb. It will be done on next tx_tasklet iteration.
> Worse thing would be opposite situation.
Can this really occur? (since queued is update holding the lock)
>
> Stanislaw
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [RFC] mt76: usb: reduce locking in mt76u_tx_tasklet
From: Stanislaw Gruszka @ 2019-03-19 16:04 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: Lorenzo Bianconi, nbd, linux-wireless
In-Reply-To: <20190319125812.GA21821@localhost.localdomain>
On Tue, Mar 19, 2019 at 01:58:13PM +0100, Lorenzo Bianconi wrote:
> > On Mon, Mar 18, 2019 at 12:09:32PM +0100, Lorenzo Bianconi wrote:
> > > Similar to pci counterpart, reduce locking in mt76u_tx_tasklet since
> > > q->head is managed just in mt76u_tx_tasklet and q->queued is updated
> > > holding q->lock
> > >
> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > ---
> > > drivers/net/wireless/mediatek/mt76/usb.c | 18 +++++++++++-------
> > > 1 file changed, 11 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> > > index ac03acdae279..8cd70c32d77a 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/usb.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> > > @@ -634,29 +634,33 @@ static void mt76u_tx_tasklet(unsigned long data)
> > > int i;
> > >
> > > for (i = 0; i < IEEE80211_NUM_ACS; i++) {
> > > + u32 n_queued = 0, n_sw_queued = 0;
> > > +
> > > sq = &dev->q_tx[i];
> > > q = sq->q;
> > >
> > > - spin_lock_bh(&q->lock);
> > > - while (true) {
> > > + while (q->queued > n_queued) {
> > > buf = &q->entry[q->head].ubuf;
> > > - if (!buf->done || !q->queued)
> > > + if (!buf->done)
> > > break;
> >
> > I'm still thinking if this is safe or not. Is somewhat tricky to
> > read variable outside the lock because in such case there is no time
> > guarantee when variable written on one CPU gets updated value on
> > different CPU. And for USB is not only q->queued but also buf->done.
>
> Hi Stanislaw,
>
> I was wondering if this is safe as well, but q->queued is updated holding q->lock
> and I guess it will ensure to not overlap tx and status code path.
Overlap will not happen, at worst what can happen is q->queued will be
smaller on tx_tasklet than on tx_queue_skb.
> Regarding buf->done, it is already updated without holding the lock in mt76u_complete_tx
That's actually a bug, but it's not important, if tx_tasklet will not
see updated buf->done <- true value by mt76u_complete_tx on different
cpu, it will not complete skb. It will be done on next tx_tasklet iteration.
Worse thing would be opposite situation.
Stanislaw
^ permalink raw reply
* Re: [PATCH 5.1] mt76x02: do not enable RTS/CTS by default
From: Kalle Valo @ 2019-03-19 15:38 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: linux-wireless, Felix Fietkau, Lorenzo Bianconi,
Stanislaw Gruszka
In-Reply-To: <1552393927-26634-1-git-send-email-sgruszka@redhat.com>
Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> My commit 26a7b5473191 ("mt76x02: set protection according to ht
> operation element") enabled by default RTS/CTS protection for OFDM
> and CCK traffic, because MT_TX_RTS_CFG_THRESH is configured to non
> 0xffff by initvals and .set_rts_threshold callback is not called by
> mac80211 on initialization, only on user request or during
> ieee80211_reconfig() (suspend/resuem or restart_hw).
>
> Enabling RTS/CTS cause some problems when sending probe request
> frames by hcxdumptool penetration tool, but I expect it can cause
> other issues on different scenarios.
>
> Restore previous setting of RTS/CTS being disabled by default for
> OFDM/CCK by changing MT_TX_RTS_CFG_THRESH initvals to 0xffff.
>
> Fixes: 26a7b5473191 ("mt76x02: set protection according to ht operation element")
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Patch applied to wireless-drivers.git, thanks.
7dfc45e6282a mt76x02: do not enable RTS/CTS by default
--
https://patchwork.kernel.org/patch/10849179/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v2] mt76: fix schedule while atomic in mt76x02_reset_state
From: Kalle Valo @ 2019-03-19 15:37 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: nbd, linux-wireless
In-Reply-To: <f5d501960f82e62806e4a4566e0b50795b2103db.1552309862.git.lorenzo@kernel.org>
Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> Fix following schedule while atomic in mt76x02_reset_state
> since synchronize_rcu is run inside a RCU section
>
> [44036.944222] mt76x2e 0000:06:00.0: MCU message 31 (seq 3) timed out
> [44036.944281] BUG: sleeping function called from invalid context at kernel/rcu/tree_exp.h:818
> [44036.944284] in_atomic(): 1, irqs_disabled(): 0, pid: 28066, name: kworker/u4:1
> [44036.944287] INFO: lockdep is turned off.
> [44036.944292] CPU: 1 PID: 28066 Comm: kworker/u4:1 Tainted: G W 5.0.0-rc7-wdn-t1+ #7
> [44036.944294] Hardware name: Dell Inc. Studio XPS 1340/0K183D, BIOS A11 09/08/2009
> [44036.944305] Workqueue: phy1 mt76x02_wdt_work [mt76x02_lib]
> [44036.944308] Call Trace:
> [44036.944317] dump_stack+0x67/0x90
> [44036.944322] ___might_sleep.cold.88+0x9f/0xaf
> [44036.944327] rcu_blocking_is_gp+0x13/0x50
> [44036.944330] synchronize_rcu+0x17/0x80
> [44036.944337] mt76_sta_state+0x138/0x1d0 [mt76]
> [44036.944349] mt76x02_wdt_work+0x1c9/0x610 [mt76x02_lib]
> [44036.944355] process_one_work+0x2a5/0x620
> [44036.944361] worker_thread+0x35/0x3e0
> [44036.944368] kthread+0x11c/0x140
> [44036.944376] ret_from_fork+0x3a/0x50
> [44036.944384] BUG: scheduling while atomic: kworker/u4:1/28066/0x00000002
> [44036.944387] INFO: lockdep is turned off.
> [44036.944389] Modules linked in: cmac ctr ccm af_packet snd_hda_codec_hdmi
>
> Introduce __mt76_sta_remove in order to run sta_remove without holding dev->mutex.
> Move __mt76_sta_remove outside of RCU section in mt76x02_reset_state
>
> Fixes: e4ebb8b403d1 ("mt76: mt76x2: implement full device restart on watchdog reset")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Patch applied to wireless-drivers.git, thanks.
13f61dfc5235 mt76: fix schedule while atomic in mt76x02_reset_state
--
https://patchwork.kernel.org/patch/10847437/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH] mt76: mt7603: use the correct hweight8() function
From: Kalle Valo @ 2019-03-19 15:36 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless
In-Reply-To: <20190311130953.61869-1-nbd@nbd.name>
Felix Fietkau <nbd@nbd.name> wrote:
> __sw_hweight8() is only defined if CONFIG_GENERIC_HWEIGHT is enabled.
> The function that works on all architectures is hweight8().
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Patch applied to wireless-drivers.git, thanks.
f2a00a821aac mt76: mt7603: use the correct hweight8() function
--
https://patchwork.kernel.org/patch/10847433/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v2] mt76x02u: check chip version on probe
From: Kalle Valo @ 2019-03-19 15:35 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: linux-wireless, Felix Fietkau, Lorenzo Bianconi,
Xose Vazquez Perez, Stanislaw Gruszka
In-Reply-To: <1551961341-28975-1-git-send-email-sgruszka@redhat.com>
Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> Since some USB device IDs are duplicated between mt76x0u, mt7601u
> and mt76x2u device, check chip version on probe and return error if
> not match the driver.
>
> Don't think this is serious issue, probe most likely will fail at
> some other point for wrong device, but we do not have to configure
> it if we know is not our device.
>
> Reported-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Patch applied to wireless-drivers.git, thanks.
40b941611bd4 mt76x02u: check chip version on probe
--
https://patchwork.kernel.org/patch/10842759/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v2] mt7601u: check chip version on probe
From: Kalle Valo @ 2019-03-19 15:33 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: linux-wireless, Jakub Kicinski, Xose Vazquez Perez,
Stanislaw Gruszka
In-Reply-To: <1551961327-28912-1-git-send-email-sgruszka@redhat.com>
Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> Since some USB device IDs are duplicated between mt7601u and mt76x0u
> devices, check chip version on probe and return error if not match
> 0x7601.
>
> Don't think this is serious issue, probe most likely will fail at
> some other point for wrong device, but we do not have to configure
> it if we know is not mt7601u device.
>
> Reported-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> Acked-by: Jakub Kicinski <kubakici@wp.pl>
Patch applied to wireless-drivers.git, thanks.
c0316470683a mt7601u: check chip version on probe
--
https://patchwork.kernel.org/patch/10842757/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* [PATCH] rtl8723ae: Make rtl8723e_dm_refresh_rate_adaptive_mask static
From: Yue Haibing @ 2019-03-19 15:19 UTC (permalink / raw)
To: davem, pkshih, kvalo; +Cc: linux-kernel, netdev, linux-wireless, YueHaibing
From: YueHaibing <yuehaibing@huawei.com>
Fix sparse warning:
drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c:666:6:
warning: symbol 'rtl8723e_dm_refresh_rate_adaptive_mask' was not declared. Should it be static?
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
index 514891e..d8260c7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
@@ -663,7 +663,7 @@ void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
}
-void rtl8723e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
+static void rtl8723e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
--
2.7.4
^ permalink raw reply related
* Re: [PATCH RFC v2] mac80211: debugfs option to force TX status frames
From: Julius Niedworok @ 2019-03-19 15:07 UTC (permalink / raw)
To: Jeremy Sowden
Cc: Kalle Valo, ga58taw, linux-wireless, david, nc, Johannes Berg,
David S. Miller, netdev, linux-kernel
In-Reply-To: <20190311145240.akms2pz2hxsalmaz@azazel.net>
> On 11.03.2019 15:52, Jeremy Sowden wrote:
>
> It's the value that matters, not the type. It will only be too big for
> the buffer if the result of casting local->force_tx_status to int is
> less than -9 or greeater than 99.
>
> scnprintf(buf, size(buf), "%lld\n", (long long)local->force_tx_status)
>
> would also be fine if the value were in range. Note also that scnprintf
> will not overrun the buffer: it will truncate the string.
Thanks for the clarification :)
> As it happens, arguments to variadic functions are subject to the
> "default argument promotions," so if local->force_tx_status is in fact a
> bool (I can't find the definition), it would be promoted to int and the
> cast is superfluous.
Yes - the cast is superfluous. We still think it might be useful to keep it
there to make the point that the value will be casted. However, if you
prefer to omit the cast, we are happy to take it out.
Thank you,
Julius and Charlie
^ permalink raw reply
* [PATCH] net:rtlwifi:move spin_lock_bh to spin_lock in tasklet
From: Jeff Xie @ 2019-03-19 14:31 UTC (permalink / raw)
To: pkshih, kvalo; +Cc: davem, linux-wireless, netdev, linux-kernel, chongguiguzi
It is unnecessary to call spin_lock_bh in a tasklet.
Signed-off-by: Jeff Xie <chongguiguzi@gmail.com>
---
drivers/net/wireless/realtek/rtlwifi/pci.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 48ca521..4055e0a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -499,16 +499,16 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
- spin_lock_bh(&rtlpriv->locks.waitq_lock);
+ spin_lock(&rtlpriv->locks.waitq_lock);
if (!skb_queue_empty(&mac->skb_waitq[tid]) &&
(ring->entries - skb_queue_len(&ring->queue) >
rtlhal->max_earlymode_num)) {
skb = skb_dequeue(&mac->skb_waitq[tid]);
} else {
- spin_unlock_bh(&rtlpriv->locks.waitq_lock);
+ spin_unlock(&rtlpriv->locks.waitq_lock);
break;
}
- spin_unlock_bh(&rtlpriv->locks.waitq_lock);
+ spin_unlock(&rtlpriv->locks.waitq_lock);
/* Some macaddr can't do early mode. like
* multicast/broadcast/no_qos data
--
2.7.4
^ permalink raw reply related
* Re: [RFC] mt76: usb: reduce locking in mt76u_tx_tasklet
From: Lorenzo Bianconi @ 2019-03-19 12:58 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Lorenzo Bianconi, nbd, linux-wireless
In-Reply-To: <20190319110708.GA5360@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1748 bytes --]
> On Mon, Mar 18, 2019 at 12:09:32PM +0100, Lorenzo Bianconi wrote:
> > Similar to pci counterpart, reduce locking in mt76u_tx_tasklet since
> > q->head is managed just in mt76u_tx_tasklet and q->queued is updated
> > holding q->lock
> >
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > ---
> > drivers/net/wireless/mediatek/mt76/usb.c | 18 +++++++++++-------
> > 1 file changed, 11 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> > index ac03acdae279..8cd70c32d77a 100644
> > --- a/drivers/net/wireless/mediatek/mt76/usb.c
> > +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> > @@ -634,29 +634,33 @@ static void mt76u_tx_tasklet(unsigned long data)
> > int i;
> >
> > for (i = 0; i < IEEE80211_NUM_ACS; i++) {
> > + u32 n_queued = 0, n_sw_queued = 0;
> > +
> > sq = &dev->q_tx[i];
> > q = sq->q;
> >
> > - spin_lock_bh(&q->lock);
> > - while (true) {
> > + while (q->queued > n_queued) {
> > buf = &q->entry[q->head].ubuf;
> > - if (!buf->done || !q->queued)
> > + if (!buf->done)
> > break;
>
> I'm still thinking if this is safe or not. Is somewhat tricky to
> read variable outside the lock because in such case there is no time
> guarantee when variable written on one CPU gets updated value on
> different CPU. And for USB is not only q->queued but also buf->done.
Hi Stanislaw,
I was wondering if this is safe as well, but q->queued is updated holding q->lock
and I guess it will ensure to not overlap tx and status code path.
Regarding buf->done, it is already updated without holding the lock in mt76u_complete_tx
Regards,
Lorenzo
>
> Stanislaw
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [RFC] mt76: usb: reduce locking in mt76u_tx_tasklet
From: Stanislaw Gruszka @ 2019-03-19 11:07 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: nbd, linux-wireless, lorenzo.bianconi
In-Reply-To: <1ee5ce7818f9d45c9713ce99e810cb84f50dcf03.1552907276.git.lorenzo@kernel.org>
On Mon, Mar 18, 2019 at 12:09:32PM +0100, Lorenzo Bianconi wrote:
> Similar to pci counterpart, reduce locking in mt76u_tx_tasklet since
> q->head is managed just in mt76u_tx_tasklet and q->queued is updated
> holding q->lock
>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/usb.c | 18 +++++++++++-------
> 1 file changed, 11 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> index ac03acdae279..8cd70c32d77a 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -634,29 +634,33 @@ static void mt76u_tx_tasklet(unsigned long data)
> int i;
>
> for (i = 0; i < IEEE80211_NUM_ACS; i++) {
> + u32 n_queued = 0, n_sw_queued = 0;
> +
> sq = &dev->q_tx[i];
> q = sq->q;
>
> - spin_lock_bh(&q->lock);
> - while (true) {
> + while (q->queued > n_queued) {
> buf = &q->entry[q->head].ubuf;
> - if (!buf->done || !q->queued)
> + if (!buf->done)
> break;
I'm still thinking if this is safe or not. Is somewhat tricky to
read variable outside the lock because in such case there is no time
guarantee when variable written on one CPU gets updated value on
different CPU. And for USB is not only q->queued but also buf->done.
Stanislaw
^ permalink raw reply
* [PATCH v2] mac80211: un-schedule TXQs on powersave start
From: Felix Fietkau @ 2019-03-19 11:00 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, Toke Høiland-Jørgensen
Once a station enters powersave, its queues should not be returned by
ieee80211_next_txq() anymore. They will be re-scheduled again after the
station has woken up again
Fixes: 1866760096bf4 ("mac80211: Add TXQ scheduling API")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/rx.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 295535b75184..60aac91e35d0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1568,7 +1568,15 @@ static void sta_ps_start(struct sta_info *sta)
return;
for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
- if (txq_has_queue(sta->sta.txq[tid]))
+ struct ieee80211_txq *txq = sta->sta.txq[tid];
+ struct txq_info *txqi = to_txq_info(txq);
+
+ spin_lock(&local->active_txq_lock[txq->ac]);
+ if (!list_empty(&txqi->schedule_order))
+ list_del_init(&txqi->schedule_order);
+ spin_unlock(&local->active_txq_lock[txq->ac]);
+
+ if (txq_has_queue(txq))
set_bit(tid, &sta->txq_buffered_tids);
else
clear_bit(tid, &sta->txq_buffered_tids);
--
2.17.0
^ permalink raw reply related
* [PATCH] mac80211: un-schedule TXQs on powersave start
From: Felix Fietkau @ 2019-03-19 10:49 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, Toke Høiland-Jørgensen
Once a station enters powersave, its queues should not be returned by
ieee80211_next_txq() anymore. They will be re-scheduled again after the
station has woken up again
Fixes: 1866760096bf4 ("mac80211: Add TXQ scheduling API")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/rx.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 295535b75184..7a7738942034 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1568,7 +1568,15 @@ static void sta_ps_start(struct sta_info *sta)
return;
for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
- if (txq_has_queue(sta->sta.txq[tid]))
+ struct ieee80211_txq *txq = sta->sta.txq[tid];
+ struct txq_info *txqi = to_txq_info(txq);
+
+ spin_lock_bh(&local->active_txq_lock[txq->ac]);
+ if (!list_empty(&txqi->schedule_order))
+ list_del_init(&txqi->schedule_order);
+ spin_unlock_bh(&local->active_txq_lock[txq->ac]);
+
+ if (txq_has_queue(txq))
set_bit(tid, &sta->txq_buffered_tids);
else
clear_bit(tid, &sta->txq_buffered_tids);
--
2.17.0
^ permalink raw reply related
* [PATCH v2 12/12] mt76x02: enable AP mode for USB
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>
Enable AP mode. For now without multi-vif support, this will require
more testing and investigation.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index ed6463c9166e..284dae65cdf1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -142,6 +142,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
@@ -158,7 +159,6 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
wiphy->reg_notifier = mt76x02_regd_notifier;
wiphy->iface_combinations = mt76x02_if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb);
- wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
/* init led callbacks */
--
1.9.3
^ permalink raw reply related
* [PATCH v2 11/12] mt76: unify set_tim
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>
All mt76 drivers (now also USB drivers) require empty .set_tim
callback. Add it to common mt76 module and use on all drivers.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/mediatek/mt76/mac80211.c | 7 +++++++
drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++
drivers/net/wireless/mediatek/mt76/mt7603/main.c | 8 +-------
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 9 +--------
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 1 +
drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c | 8 +-------
drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 1 +
7 files changed, 14 insertions(+), 22 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 47eecb4d4d01..851caabbecda 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -785,3 +785,10 @@ void mt76_csa_check(struct mt76_dev *dev)
__mt76_csa_check, dev);
}
EXPORT_SYMBOL_GPL(mt76_csa_check);
+
+int
+mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt76_set_tim);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index edff44f32c8e..c163ba68647e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -732,6 +732,8 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void mt76_csa_check(struct mt76_dev *dev);
void mt76_csa_finish(struct mt76_dev *dev);
+int mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set);
+
/* internal */
void mt76_tx_free(struct mt76_dev *dev);
struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index 7849528db134..a03729824c4d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -664,12 +664,6 @@ static void mt7603_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *cont
mt76_tx(&dev->mt76, control->sta, wcid, skb);
}
-static int
-mt7603_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
-{
- return 0;
-}
-
const struct ieee80211_ops mt7603_ops = {
.tx = mt7603_tx,
.start = mt7603_start,
@@ -691,7 +685,7 @@ static void mt7603_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *cont
.sta_rate_tbl_update = mt7603_sta_rate_tbl_update,
.release_buffered_frames = mt7603_release_buffered_frames,
.set_coverage_class = mt7603_set_coverage_class,
- .set_tim = mt7603_set_tim,
+ .set_tim = mt76_set_tim,
.get_survey = mt76_get_survey,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index e35165416cf0..a7ff7e32b9b3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -74,13 +74,6 @@ static void mt76x0e_stop(struct ieee80211_hw *hw)
{
}
-static int
-mt76x0e_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- bool set)
-{
- return 0;
-}
-
static const struct ieee80211_ops mt76x0e_ops = {
.tx = mt76x02_tx,
.start = mt76x0e_start,
@@ -101,7 +94,7 @@ static void mt76x0e_stop(struct ieee80211_hw *hw)
.get_survey = mt76_get_survey,
.get_txpower = mt76_get_txpower,
.flush = mt76x0e_flush,
- .set_tim = mt76x0e_set_tim,
+ .set_tim = mt76_set_tim,
.release_buffered_frames = mt76_release_buffered_frames,
.set_coverage_class = mt76x02_set_coverage_class,
.set_rts_threshold = mt76x02_set_rts_threshold,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index b9b8a1dafbc9..cf97bbd89485 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -152,6 +152,7 @@ static void mt76x0u_stop(struct ieee80211_hw *hw)
.set_rts_threshold = mt76x02_set_rts_threshold,
.wake_tx_queue = mt76_wake_tx_queue,
.get_txpower = mt76_get_txpower,
+ .set_tim = mt76_set_tim,
.release_buffered_frames = mt76_release_buffered_frames,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
index 878ce92405ed..16dc8e2451b5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
@@ -135,12 +135,6 @@
{
}
-static int
-mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
-{
- return 0;
-}
-
static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
u32 rx_ant)
{
@@ -197,7 +191,7 @@ static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
.release_buffered_frames = mt76_release_buffered_frames,
.set_coverage_class = mt76x02_set_coverage_class,
.get_survey = mt76_get_survey,
- .set_tim = mt76x2_set_tim,
+ .set_tim = mt76_set_tim,
.set_antenna = mt76x2_set_antenna,
.get_antenna = mt76x2_get_antenna,
.set_rts_threshold = mt76x02_set_rts_threshold,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
index 46c6b3764f5a..eb414fb75fb1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
@@ -129,5 +129,6 @@ static void mt76x2u_stop(struct ieee80211_hw *hw)
.sw_scan_complete = mt76x02_sw_scan_complete,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.get_txpower = mt76_get_txpower,
+ .set_tim = mt76_set_tim,
.release_buffered_frames = mt76_release_buffered_frames,
};
--
1.9.3
^ permalink raw reply related
* [PATCH v2 10/12] mt76x02u: add mt76_release_buffered_frames
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>
Create software MT_TXQ_PSD queue for USB and map it to MT_TXQ_VO
since we do not have USB endpoint for PSD. This should make
mt76_release_buffered_frames() work by sending released frames
via MT_TXQ_VO.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 1 +
drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 1 +
drivers/net/wireless/mediatek/mt76/usb.c | 7 ++++++-
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 0348a1b38d2d..b9b8a1dafbc9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -152,6 +152,7 @@ static void mt76x0u_stop(struct ieee80211_hw *hw)
.set_rts_threshold = mt76x02_set_rts_threshold,
.wake_tx_queue = mt76_wake_tx_queue,
.get_txpower = mt76_get_txpower,
+ .release_buffered_frames = mt76_release_buffered_frames,
};
static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
index 1e6856856536..46c6b3764f5a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
@@ -129,4 +129,5 @@ static void mt76x2u_stop(struct ieee80211_hw *hw)
.sw_scan_complete = mt76x02_sw_scan_complete,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.get_txpower = mt76_get_txpower,
+ .release_buffered_frames = mt76_release_buffered_frames,
};
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 27896a435d6c..7b62bd63d395 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -792,9 +792,14 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
struct mt76_queue *q;
int i, j;
- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ for (i = 0; i <= MT_TXQ_PSD; i++) {
INIT_LIST_HEAD(&dev->q_tx[i].swq);
+ if (i >= IEEE80211_NUM_ACS) {
+ dev->q_tx[i].q = dev->q_tx[0].q;
+ continue;
+ }
+
q = devm_kzalloc(dev->dev, sizeof(*q), GFP_KERNEL);
if (!q)
return -ENOMEM;
--
1.9.3
^ permalink raw reply related
* [PATCH v2 09/12] mt76x02: make beacon slots bigger for USB
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>
Since we sent PS buffered frames via beacon memory we need to make
beacon slots bigger. That imply we will also need to decrease number
of slots as beacon SRAM memory is limited to 8kB.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/mediatek/mt76/mt76x02.h | 3 +-
.../net/wireless/mediatek/mt76/mt76x02_beacon.c | 34 ++++------------------
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 2 ++
.../net/wireless/mediatek/mt76/mt76x02_usb_core.c | 20 ++++++++-----
4 files changed, 22 insertions(+), 37 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 93f9436ab809..d665137d256c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -69,6 +69,8 @@ struct mt76x02_calibration {
};
struct mt76x02_beacon_ops {
+ unsigned int nslots;
+ unsigned int slot_size;
void (*pre_tbtt_enable) (struct mt76x02_dev *, bool);
void (*beacon_enable) (struct mt76x02_dev *, bool);
};
@@ -194,7 +196,6 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info, u32 changed);
-extern const u16 mt76x02_beacon_offsets[16];
struct beacon_bc_data {
struct mt76x02_dev *dev;
struct sk_buff_head q;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
index c0be90988f82..0c232d02f189 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -18,36 +18,14 @@
#include "mt76x02.h"
-const u16 mt76x02_beacon_offsets[16] = {
- /* 1024 byte per beacon */
- 0xc000,
- 0xc400,
- 0xc800,
- 0xcc00,
- 0xd000,
- 0xd400,
- 0xd800,
- 0xdc00,
- /* BSS idx 8-15 not used for beacons */
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
-};
-EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets);
-
static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
{
- u16 val, base = MT_BEACON_BASE;
u32 regs[4] = {};
+ u16 val;
int i;
- for (i = 0; i < 16; i++) {
- val = mt76x02_beacon_offsets[i] - base;
+ for (i = 0; i < dev->beacon_ops->nslots; i++) {
+ val = i * dev->beacon_ops->slot_size;
regs[i / 4] |= (val / 64) << (8 * (i % 4));
}
@@ -58,7 +36,7 @@ static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
static int
mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb)
{
- int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
+ int beacon_len = dev->beacon_ops->slot_size;
struct mt76x02_txwi txwi;
if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi)))
@@ -77,8 +55,8 @@ static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
__mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx,
struct sk_buff *skb)
{
- int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
- int beacon_addr = mt76x02_beacon_offsets[bcn_idx];
+ int beacon_len = dev->beacon_ops->slot_size;
+ int beacon_addr = MT_BEACON_BASE + (beacon_len * bcn_idx);
int ret = 0;
int i;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index eea8e4718600..79c1126f4ba4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -85,6 +85,8 @@ static void mt76x02e_beacon_enable(struct mt76x02_dev *dev, bool en)
void mt76x02e_init_beacon_config(struct mt76x02_dev *dev)
{
static const struct mt76x02_beacon_ops beacon_ops = {
+ .nslots = 8,
+ .slot_size = 1024,
.pre_tbtt_enable = mt76x02e_pre_tbtt_enable,
.beacon_enable = mt76x02e_beacon_enable,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 89249621bcec..c403218533da 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -107,6 +107,13 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
/* Trigger pre-TBTT event 8 ms before TBTT */
#define PRE_TBTT_USEC 8000
+
+/* Beacon SRAM memory is limited to 8kB. We need to send PS buffered frames
+ * (which can be 1500 bytes big) via beacon memory. That make limit of number
+ * of slots to 5. TODO: dynamically calculate offsets in beacon SRAM.
+ */
+#define N_BCN_SLOTS 5
+
static void mt76x02u_start_pre_tbtt_timer(struct mt76x02_dev *dev)
{
u64 time;
@@ -164,7 +171,6 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
{
struct mt76x02_dev *dev =
container_of(work, struct mt76x02_dev, pre_tbtt_work);
- int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
struct beacon_bc_data data = {};
struct sk_buff *skb;
int i, nbeacons;
@@ -179,14 +185,10 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
mt76x02_update_beacon_iter, dev);
nbeacons = hweight8(dev->beacon_mask);
- mt76x02_enqueue_buffered_bc(dev, &data, 8 - nbeacons);
+ mt76x02_enqueue_buffered_bc(dev, &data, N_BCN_SLOTS - nbeacons);
- for (i = nbeacons; i < 8; i++) {
+ for (i = nbeacons; i < N_BCN_SLOTS; i++) {
skb = __skb_dequeue(&data.q);
- if (skb && skb->len >= beacon_len) {
- dev_kfree_skb(skb);
- skb = NULL;
- }
mt76x02_mac_set_beacon(dev, i, skb);
}
@@ -224,7 +226,7 @@ static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en)
/* Timer is already stopped, only clean up
* PS buffered frames if any.
*/
- for (i = 0; i < 8; i++)
+ for (i = 0; i < N_BCN_SLOTS; i++)
mt76x02_mac_set_beacon(dev, i, NULL);
}
}
@@ -232,6 +234,8 @@ static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en)
void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
{
static const struct mt76x02_beacon_ops beacon_ops = {
+ .nslots = N_BCN_SLOTS,
+ .slot_size = (8192 / N_BCN_SLOTS) & ~63,
.pre_tbtt_enable = mt76x02u_pre_tbtt_enable,
.beacon_enable = mt76x02u_beacon_enable,
};
--
1.9.3
^ permalink raw reply related
* [PATCH v2 08/12] mt76x02u: implement pre TBTT work for USB
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>
Program beacons data and PS buffered frames on TBTT work for USB.
We do not have MT_TXQ_PSD queue available via USB endpoints. The way
we can send PS broadcast frames in timely manner before PS stations go
sleep again is program them in beacon data area. Hardware do not modify
those frames since TXWI is properly configured. mt76x02_mac_set_beacon()
already handle this and free no longer used frames.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
.../net/wireless/mediatek/mt76/mt76x02_beacon.c | 2 ++
.../net/wireless/mediatek/mt76/mt76x02_usb_core.c | 36 ++++++++++++++++++++--
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
index d77088b7659e..c0be90988f82 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -38,6 +38,7 @@
0xc000,
0xc000,
};
+EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets);
static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
{
@@ -134,6 +135,7 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
bcn_idx - 1);
return 0;
}
+EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon);
static void
__mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 82b78cc5b362..89249621bcec 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -164,9 +164,32 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
{
struct mt76x02_dev *dev =
container_of(work, struct mt76x02_dev, pre_tbtt_work);
+ int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
+ struct beacon_bc_data data = {};
+ struct sk_buff *skb;
+ int i, nbeacons;
if (!dev->beacon_mask)
return;
+
+ mt76x02_resync_beacon_timer(dev);
+
+ ieee80211_iterate_active_interfaces(mt76_hw(dev),
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt76x02_update_beacon_iter, dev);
+
+ nbeacons = hweight8(dev->beacon_mask);
+ mt76x02_enqueue_buffered_bc(dev, &data, 8 - nbeacons);
+
+ for (i = nbeacons; i < 8; i++) {
+ skb = __skb_dequeue(&data.q);
+ if (skb && skb->len >= beacon_len) {
+ dev_kfree_skb(skb);
+ skb = NULL;
+ }
+ mt76x02_mac_set_beacon(dev, i, skb);
+ }
+
mt76x02u_restart_pre_tbtt_timer(dev);
}
@@ -190,13 +213,20 @@ static void mt76x02u_pre_tbtt_enable(struct mt76x02_dev *dev, bool en)
static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en)
{
+ int i;
+
if (WARN_ON_ONCE(!dev->beacon_int))
return;
- if (en)
+ if (en) {
mt76x02u_start_pre_tbtt_timer(dev);
-
- /* Nothing to do on disable as timer is already stopped */
+ } else {
+ /* Timer is already stopped, only clean up
+ * PS buffered frames if any.
+ */
+ for (i = 0; i < 8; i++)
+ mt76x02_mac_set_beacon(dev, i, NULL);
+ }
}
void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
--
1.9.3
^ permalink raw reply related
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