* [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask
@ 2025-11-05 9:30 Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 02/12] wifi: mt76: mt7996: no need to wait ACK event for SDO command Shayne Chen
` (10 more replies)
0 siblings, 11 replies; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, StanleyYP Wang, Shayne Chen
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Since wiphy->available_antennas_tx now accumulates the chainmask of all
the radios of a wiphy, use phy->orig_antenna_mask to get the original
max nss for comparison.
Fixes: 69d54ce7491d ("wifi: mt76: mt7996: switch to single multi-radio wiphy")
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 87730d26669d..891b187566b3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -786,7 +786,7 @@ void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
{
- int max_nss = hweight8(phy->mt76->hw->wiphy->available_antennas_tx);
+ int max_nss = hweight16(phy->orig_antenna_mask);
int cur_nss = hweight8(phy->mt76->antenna_mask);
u16 tx_chainmask = phy->mt76->chainmask;
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 02/12] wifi: mt76: mt7996: no need to wait ACK event for SDO command
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 03/12] wifi: mt76: mt7996: fix implicit beamforming support for mt7992 Shayne Chen
` (9 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Peter Chiu, Shayne Chen
From: Peter Chiu <chui-hao.chiu@mediatek.com>
For the SDO unified command, driver does not need to wait for ACK event so
do not mark MCU_CMD_ACK in command header.
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index dda01fa6d7bb..e97984693290 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -318,6 +318,9 @@ mt7996_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
else
uni_txd->option = MCU_CMD_UNI_EXT_ACK;
+ if (mcu_cmd == MCU_UNI_CMD_SDO)
+ uni_txd->option &= ~MCU_CMD_ACK;
+
if ((cmd & __MCU_CMD_FIELD_WA) && (cmd & __MCU_CMD_FIELD_WM))
uni_txd->s2d_index = MCU_S2D_H2CN;
else if (cmd & __MCU_CMD_FIELD_WA)
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 03/12] wifi: mt76: mt7996: fix implicit beamforming support for mt7992
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 02/12] wifi: mt76: mt7996: no need to wait ACK event for SDO command Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 04/12] wifi: mt76: mt7996: support fixed rate for link station Shayne Chen
` (8 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Howard Hsu, Shayne Chen
From: Howard Hsu <howard-yh.hsu@mediatek.com>
Fix the ibf_timeout field for mt7996, mt7992 and mt7990 chipsets. For
the mt7992, this value shall be set as 0xff, while the others shall be
set as 0x18.
Fixes: ad4c9a8a9803 ("wifi: mt76: mt7996: add implicit beamforming support for mt7992")
Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index e97984693290..82dd34a8780f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1825,8 +1825,8 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
bf->ibf_nrow = tx_ant;
if (link_sta->eht_cap.has_eht || link_sta->he_cap.has_he)
- bf->ibf_timeout = is_mt7996(&dev->mt76) ? MT7996_IBF_TIMEOUT :
- MT7992_IBF_TIMEOUT;
+ bf->ibf_timeout = is_mt7992(&dev->mt76) ? MT7992_IBF_TIMEOUT :
+ MT7996_IBF_TIMEOUT;
else if (!ebf && link_sta->bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol)
bf->ibf_timeout = MT7996_IBF_TIMEOUT_LEGACY;
else
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 04/12] wifi: mt76: mt7996: support fixed rate for link station
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 02/12] wifi: mt76: mt7996: no need to wait ACK event for SDO command Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 03/12] wifi: mt76: mt7996: fix implicit beamforming support for mt7992 Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 05/12] wifi: mt76: mt7996: fix several fields in mt7996_mcu_bss_basic_tlv() Shayne Chen
` (7 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen, Howard Hsu
Introduce mt7996_link_sta_add_debugfs() to extend fixed rate support for
MLO link station.
Co-developed-by: Howard Hsu <howard-yh.hsu@mediatek.com>
Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
.../wireless/mediatek/mt76/mt7996/debugfs.c | 72 +++++++++++--------
.../net/wireless/mediatek/mt76/mt7996/main.c | 1 +
.../wireless/mediatek/mt76/mt7996/mt7996.h | 3 +
3 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index a000275b369b..76d623b2cafb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -953,16 +953,34 @@ bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len)
#ifdef CONFIG_MAC80211_DEBUGFS
/** per-station debugfs **/
-static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
+static int
+mt7996_queues_show(struct seq_file *s, void *data)
+{
+ struct ieee80211_sta *sta = s->private;
+
+ mt7996_sta_hw_queue_read(s, sta);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(mt7996_queues);
+
+void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, struct dentry *dir)
+{
+ debugfs_create_file("hw-queues", 0400, dir, sta, &mt7996_queues_fops);
+}
+
+static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
{
#define SHORT_PREAMBLE 0
#define LONG_PREAMBLE 1
- struct ieee80211_sta *sta = file->private_data;
- struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+ struct ieee80211_link_sta *link_sta = file->private_data;
+ struct mt7996_sta *msta = (struct mt7996_sta *)link_sta->sta->drv_priv;
struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
- struct mt7996_sta_link *msta_link = &msta->deflink;
+ struct mt7996_sta_link *msta_link;
struct ra_rate phy = {};
char buf[100];
int ret;
@@ -981,12 +999,13 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
/* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9 EHT: 15
* bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3, BW320: 4
- * nss - vht: 1~4, he: 1~4, eht: 1~4, others: ignore
* mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2, eht: 0~13
+ * nss - vht: 1~4, he: 1~4, eht: 1~4, others: ignore
* gi - (ht/vht) lgi: 0, sgi: 1; (he) 0.8us: 0, 1.6us: 1, 3.2us: 2
* preamble - short: 1, long: 0
- * ldpc - off: 0, on: 1
* stbc - off: 0, on: 1
+ * ldpc - off: 0, on: 1
+ * spe - off: 0, on: 1
* ltf - 1xltf: 0, 2xltf: 1, 4xltf: 2
*/
if (sscanf(buf, "%hhu %hhu %hhu %hhu %hu %hhu %hhu %hhu %hhu %hu",
@@ -994,9 +1013,16 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
&phy.preamble, &phy.stbc, &phy.ldpc, &phy.spe, <f) != 10) {
dev_warn(dev->mt76.dev,
"format: Mode BW MCS NSS GI Preamble STBC LDPC SPE ltf\n");
- goto out;
+ return -EINVAL;
}
+ mutex_lock(&dev->mt76.mutex);
+
+ msta_link = mt76_dereference(msta->link[link_sta->link_id], &dev->mt76);
+ if (!msta_link) {
+ ret = -EINVAL;
+ goto out;
+ }
phy.wlan_idx = cpu_to_le16(msta_link->wcid.idx);
phy.gi = cpu_to_le16(gi);
phy.ltf = cpu_to_le16(ltf);
@@ -1005,36 +1031,26 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
ret = mt7996_mcu_set_fixed_rate_ctrl(dev, &phy, 0);
if (ret)
- return -EFAULT;
+ goto out;
+ ret = count;
out:
- return count;
+ mutex_unlock(&dev->mt76.mutex);
+ return ret;
}
static const struct file_operations fops_fixed_rate = {
- .write = mt7996_sta_fixed_rate_set,
+ .write = mt7996_link_sta_fixed_rate_set,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
-static int
-mt7996_queues_show(struct seq_file *s, void *data)
-{
- struct ieee80211_sta *sta = s->private;
-
- mt7996_sta_hw_queue_read(s, sta);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(mt7996_queues);
-
-void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, struct dentry *dir)
+void mt7996_link_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct dentry *dir)
{
- debugfs_create_file("fixed_rate", 0600, dir, sta, &fops_fixed_rate);
- debugfs_create_file("hw-queues", 0400, dir, sta, &mt7996_queues_fops);
+ debugfs_create_file("fixed_rate", 0600, dir, link_sta, &fops_fixed_rate);
}
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 08c4d9c8791b..5e0b57657e7e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -2283,6 +2283,7 @@ const struct ieee80211_ops mt7996_ops = {
.twt_teardown_request = mt7996_twt_teardown_request,
#ifdef CONFIG_MAC80211_DEBUGFS
.sta_add_debugfs = mt7996_sta_add_debugfs,
+ .link_sta_add_debugfs = mt7996_link_sta_add_debugfs,
#endif
.set_radar_background = mt7996_set_radar_background,
.net_fill_forward_path = mt7996_net_fill_forward_path,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 891b187566b3..65eeb37ab8c7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -863,6 +863,9 @@ int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
#ifdef CONFIG_MAC80211_DEBUGFS
void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir);
+void mt7996_link_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct dentry *dir);
#endif
int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
bool hif2, int *irq);
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 05/12] wifi: mt76: mt7996: fix several fields in mt7996_mcu_bss_basic_tlv()
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
` (2 preceding siblings ...)
2025-11-05 9:30 ` [PATCH mt76 04/12] wifi: mt76: mt7996: support fixed rate for link station Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 10:04 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 06/12] wifi: mt76: mt7996: fix teardown command for an MLD peer Shayne Chen
` (6 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen
Fix several fields in mt7996_mcu_bss_basic_tlv() that were not obtained
from the correct link. Without this patch, the MLD station interface
does not function properly.
Fixes: 34a41bfbcb71 ("wifi: mt76: mt7996: prepare mt7996_mcu_add_dev/bss_info for MLO support")
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7996/mcu.c | 21 ++++++++++---------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 82dd34a8780f..f1892aaf6a91 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1037,7 +1037,6 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
struct mt76_connac_bss_basic_tlv *bss;
u32 type = CONNECTION_INFRA_AP;
u16 sta_wlan_idx = wlan_idx;
- struct ieee80211_sta *sta;
struct tlv *tlv;
int idx;
@@ -1048,14 +1047,18 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
break;
case NL80211_IFTYPE_STATION:
if (enable) {
+ struct ieee80211_sta *sta;
+
rcu_read_lock();
- sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
- /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */
+ sta = ieee80211_find_sta(vif, link_conf->bssid);
if (sta) {
- struct mt76_wcid *wcid;
+ struct mt7996_sta *msta = (void *)sta->drv_priv;
+ struct mt7996_sta_link *msta_link;
+ int link_id = link_conf->link_id;
- wcid = (struct mt76_wcid *)sta->drv_priv;
- sta_wlan_idx = wcid->idx;
+ msta_link = rcu_dereference(msta->link[link_id]);
+ if (msta_link)
+ sta_wlan_idx = msta_link->wcid.idx;
}
rcu_read_unlock();
}
@@ -1072,8 +1075,6 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_BASIC, sizeof(*bss));
bss = (struct mt76_connac_bss_basic_tlv *)tlv;
- bss->bcn_interval = cpu_to_le16(link_conf->beacon_int);
- bss->dtim_period = link_conf->dtim_period;
bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
bss->sta_idx = cpu_to_le16(sta_wlan_idx);
bss->conn_type = cpu_to_le32(type);
@@ -1093,10 +1094,10 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
memcpy(bss->bssid, link_conf->bssid, ETH_ALEN);
bss->bcn_interval = cpu_to_le16(link_conf->beacon_int);
- bss->dtim_period = vif->bss_conf.dtim_period;
+ bss->dtim_period = link_conf->dtim_period;
bss->phymode = mt76_connac_get_phy_mode(phy, vif,
chandef->chan->band, NULL);
- bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, &vif->bss_conf,
+ bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, link_conf,
chandef->chan->band);
return 0;
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 06/12] wifi: mt76: mt7996: fix teardown command for an MLD peer
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
` (3 preceding siblings ...)
2025-11-05 9:30 ` [PATCH mt76 05/12] wifi: mt76: mt7996: fix several fields in mt7996_mcu_bss_basic_tlv() Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 10:09 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 07/12] wifi: mt76: mt7996: set link_valid field when initializing wcid Shayne Chen
` (5 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen
For an MLD peer, we only need to call the teardown command when removing
the last link, and there's no need to call mt7996_mcu_add_sta() for the
earlier links.
Fixes: c1d6dd5d03eb ("wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta rouine")
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7996/main.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 5e0b57657e7e..685be98b9f27 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1206,13 +1206,13 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
mt7996_mac_twt_teardown_flow(dev, link,
msta_link, i);
- if (sta->mlo && links == BIT(link_id)) /* last link */
- mt7996_mcu_teardown_mld_sta(dev, link,
- msta_link);
- else
+ if (!sta->mlo)
mt7996_mcu_add_sta(dev, link_conf, link_sta,
link, msta_link,
CONN_STATE_DISCONNECT, false);
+ else if (sta->mlo && links == BIT(link_id)) /* last link */
+ mt7996_mcu_teardown_mld_sta(dev, link,
+ msta_link);
msta_link->wcid.sta_disabled = 1;
msta_link->wcid.sta = 0;
links = links & ~BIT(link_id);
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 07/12] wifi: mt76: mt7996: set link_valid field when initializing wcid
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
` (4 preceding siblings ...)
2025-11-05 9:30 ` [PATCH mt76 06/12] wifi: mt76: mt7996: fix teardown command for an MLD peer Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 10:15 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 08/12] wifi: mt76: mt7996: use correct link_id when filling TXD and TXP Shayne Chen
` (4 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen
This ensures the upper layer uses the correct link ID during packet
processing.
Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7996/main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 685be98b9f27..c26f8f49ce44 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -343,6 +343,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
INIT_LIST_HEAD(&msta_link->rc_list);
msta_link->wcid.idx = idx;
msta_link->wcid.link_id = link_conf->link_id;
+ msta_link->wcid.link_valid = ieee80211_vif_is_mld(vif);
msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
mt76_wcid_init(&msta_link->wcid, band_idx);
@@ -984,6 +985,7 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
msta_link->wcid.sta = 1;
msta_link->wcid.idx = idx;
msta_link->wcid.link_id = link_id;
+ msta_link->wcid.link_valid = !!sta->valid_links;
msta_link->wcid.def_wcid = &msta->deflink.wcid;
ewma_avg_signal_init(&msta_link->avg_ack_signal);
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 08/12] wifi: mt76: mt7996: use correct link_id when filling TXD and TXP
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
` (5 preceding siblings ...)
2025-11-05 9:30 ` [PATCH mt76 07/12] wifi: mt76: mt7996: set link_valid field when initializing wcid Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 10:34 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 09/12] wifi: mt76: mt7996: fix MLD group index assignment Shayne Chen
` (3 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen
Obtain the correct link ID and, if needed, switch to the corresponding
wcid before populating the TX descriptor and TX payload.
Rules for link id:
- For QoS data from MLD peers (excluding EAPOL), select the primary or
secondary wcid based on whether the TID is odd or even to meet FW/HW
requirements
- For other packets, use IEEE80211_TX_CTRL_MLO_LINK if specified
(such as multicast and broadcast packets)
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7996/mac.c | 34 ++++++++++++++++---
.../net/wireless/mediatek/mt76/mt7996/main.c | 6 ++++
.../net/wireless/mediatek/mt76/mt7996/mcu.c | 4 +--
.../wireless/mediatek/mt76/mt7996/mt7996.h | 1 +
4 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 7d5f9d9b3b62..579084cbb30f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1035,15 +1035,20 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info)
{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct ieee80211_vif *vif = info->control.vif;
+ struct mt7996_vif *mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
+ struct mt7996_sta *msta = sta ? (struct mt7996_sta *)sta->drv_priv : NULL;
+ struct mt76_vif_link *mlink = NULL;
struct mt76_txwi_cache *t;
int id, i, pid, nbuf = tx_info->nbuf - 1;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
__le32 *ptr = (__le32 *)txwi_ptr;
u8 *txwi = (u8 *)txwi_ptr;
+ u8 link_id;
if (unlikely(tx_info->skb->len <= ETH_HLEN))
return -EINVAL;
@@ -1051,6 +1056,30 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (!wcid)
wcid = &dev->mt76.global_wcid;
+ if ((is_8023 || ieee80211_is_data_qos(hdr->frame_control)) && sta->mlo &&
+ likely(tx_info->skb->protocol != cpu_to_be16(ETH_P_PAE))) {
+ u8 tid = tx_info->skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+
+ link_id = (tid % 2) ? msta->seclink_id : msta->deflink_id;
+ } else {
+ link_id = u32_get_bits(info->control.flags,
+ IEEE80211_TX_CTRL_MLO_LINK);
+ }
+
+ if (link_id != wcid->link_id && link_id != IEEE80211_LINK_UNSPECIFIED) {
+ if (msta) {
+ struct mt7996_sta_link *msta_link =
+ rcu_dereference(msta->link[link_id]);
+
+ if (msta_link)
+ wcid = &msta_link->wcid;
+ } else if (mvif) {
+ mlink = rcu_dereference(mvif->mt76.link[link_id]);
+ if (mlink && mlink->wcid)
+ wcid = mlink->wcid;
+ }
+ }
+
t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
t->skb = tx_info->skb;
@@ -1155,10 +1184,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (!is_8023 && mt7996_tx_use_mgmt(dev, tx_info->skb))
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
- if (vif) {
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
- struct mt76_vif_link *mlink = NULL;
-
+ if (mvif) {
if (wcid->offchannel)
mlink = rcu_dereference(mvif->mt76.offchannel_link);
if (!mlink)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index c26f8f49ce44..3958688d622b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -963,6 +963,7 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
msta_link = &msta->deflink;
msta->deflink_id = link_id;
+ msta->seclink_id = msta->deflink_id;
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
struct mt76_txq *mtxq;
@@ -977,6 +978,11 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
msta_link = kzalloc(sizeof(*msta_link), GFP_KERNEL);
if (!msta_link)
return -ENOMEM;
+
+ if (msta->seclink_id == msta->deflink_id &&
+ (sta->valid_links & ~(BIT(msta->deflink_id))))
+ msta->seclink_id = __ffs(sta->valid_links &
+ ~(BIT(msta->deflink_id)));
}
INIT_LIST_HEAD(&msta_link->rc_list);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index f1892aaf6a91..2bb98df317a6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2394,8 +2394,8 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx);
if (nlinks > 1) {
- link_id = __ffs(sta->valid_links & ~BIT(msta->deflink_id));
- msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+ msta_link = mt76_dereference(msta->link[msta->seclink_id],
+ &dev->mt76);
if (!msta_link)
return;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 65eeb37ab8c7..c47820699ec8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -243,6 +243,7 @@ struct mt7996_sta {
struct mt7996_sta_link deflink; /* must be first */
struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
u8 deflink_id;
+ u8 seclink_id;
struct mt7996_vif *vif;
};
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 09/12] wifi: mt76: mt7996: fix MLD group index assignment
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
` (6 preceding siblings ...)
2025-11-05 9:30 ` [PATCH mt76 08/12] wifi: mt76: mt7996: use correct link_id when filling TXD and TXP Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 10:42 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 10/12] wifi: mt76: mt7996: fix MLO set key and group key issues Shayne Chen
` (2 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen
Fix extender mode and MBSS issues caused by incorrect assignment of the
MLD group and remap indices.
Fixes: ed01c310eca9 ("wifi: mt76: mt7996: Fix mt7996_mcu_bss_mld_tlv routine")
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7996/main.c | 58 +++++++++++++------
1 file changed, 40 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 3958688d622b..346d650107d4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -90,9 +90,11 @@ static void mt7996_stop(struct ieee80211_hw *hw, bool suspend)
{
}
-static inline int get_free_idx(u32 mask, u8 start, u8 end)
+static inline int get_free_idx(u64 mask, u8 start, u8 end)
{
- return ffs(~mask & GENMASK(end, start));
+ if (~mask & GENMASK_ULL(end, start))
+ return __ffs64(~mask & GENMASK_ULL(end, start)) + 1;
+ return 0;
}
static int get_omac_idx(enum nl80211_iftype type, u64 mask)
@@ -308,12 +310,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
if (idx < 0)
return -ENOSPC;
- if (!dev->mld_idx_mask) { /* first link in the group */
- mvif->mld_group_idx = get_own_mld_idx(dev->mld_idx_mask, true);
- mvif->mld_remap_idx = get_free_idx(dev->mld_remap_idx_mask,
- 0, 15);
- }
-
mld_idx = get_own_mld_idx(dev->mld_idx_mask, false);
if (mld_idx < 0)
return -ENOSPC;
@@ -331,10 +327,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
return ret;
dev->mt76.vif_mask |= BIT_ULL(mlink->idx);
- if (!dev->mld_idx_mask) {
- dev->mld_idx_mask |= BIT_ULL(mvif->mld_group_idx);
- dev->mld_remap_idx_mask |= BIT_ULL(mvif->mld_remap_idx);
- }
dev->mld_idx_mask |= BIT_ULL(link->mld_idx);
phy->omac_mask |= BIT_ULL(mlink->omac_idx);
@@ -424,11 +416,6 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);
dev->mld_idx_mask &= ~BIT_ULL(link->mld_idx);
phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
- if (!(dev->mld_idx_mask & ~BIT_ULL(mvif->mld_group_idx))) {
- /* last link */
- dev->mld_idx_mask &= ~BIT_ULL(mvif->mld_group_idx);
- dev->mld_remap_idx_mask &= ~BIT_ULL(mvif->mld_remap_idx);
- }
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta_link->wcid.poll_list))
@@ -2225,7 +2212,42 @@ mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u16 old_links, u16 new_links,
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
{
- return 0;
+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ int ret = 0;
+
+ mutex_lock(&dev->mt76.mutex);
+
+ if (!old_links) {
+ int idx;
+
+ idx = get_own_mld_idx(dev->mld_idx_mask, true);
+ if (idx < 0) {
+ ret = -ENOSPC;
+ goto out;
+ }
+ mvif->mld_group_idx = idx;
+ dev->mld_idx_mask |= BIT_ULL(mvif->mld_group_idx);
+
+ idx = get_free_idx(dev->mld_remap_idx_mask, 0, 15) - 1;
+ if (idx < 0) {
+ ret = -ENOSPC;
+ goto out;
+ }
+ mvif->mld_remap_idx = idx;
+ dev->mld_remap_idx_mask |= BIT_ULL(mvif->mld_remap_idx);
+ }
+
+ if (new_links)
+ goto out;
+
+ dev->mld_idx_mask &= ~BIT_ULL(mvif->mld_group_idx);
+ dev->mld_remap_idx_mask &= ~BIT_ULL(mvif->mld_remap_idx);
+
+out:
+ mutex_unlock(&dev->mt76.mutex);
+
+ return ret;
}
static void
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 10/12] wifi: mt76: mt7996: fix MLO set key and group key issues
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
` (7 preceding siblings ...)
2025-11-05 9:30 ` [PATCH mt76 09/12] wifi: mt76: mt7996: fix MLD group index assignment Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 11/12] wifi: mt76: mt7996: fix using wrong phy to start in mt7996_mac_restart() Shayne Chen
2025-11-05 9:31 ` [PATCH mt76 12/12] wifi: mt76: mt7996: fix EMI rings for RRO Shayne Chen
10 siblings, 0 replies; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen, Allen Ye, Peter Chiu
This patch fixes the following key issues:
- Pass correct link BSS to mt7996_mcu_add_key(), and use HW beacon
protection mode for mt7990 chipset
- Do not do group key deletion for GTK and IGTK due to FW design, the
delete key command will delete all group keys of a link BSS
- For deleting BIGTK, FW adds a new flow, but the "sec->add" field
should be filled with "SET_KEY". Note that if BIGTK is not deleted, it
will cause beacon decryption issue when switching from an AP interface
to a station interface
Fixes: 0c45d52276fd ("wifi: mt76: mt7996: fix setting beacon protection keys")
Co-developed-by: Allen Ye <allen.ye@mediatek.com>
Signed-off-by: Allen Ye <allen.ye@mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7996/mac.c | 7 +++-
.../net/wireless/mediatek/mt76/mt7996/main.c | 5 +--
.../net/wireless/mediatek/mt76/mt7996/mcu.c | 35 +++++++++++++------
.../wireless/mediatek/mt76/mt7996/mt7996.h | 2 +-
4 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 579084cbb30f..c1f2938d1f21 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -795,6 +795,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
__le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
u16 seqno = le16_to_cpu(sc);
+ bool hw_bigtk = false;
u8 fc_type, fc_stype;
u32 val;
@@ -820,7 +821,11 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
val |= MT_TXD1_FIXED_RATE;
- if (key && multicast && ieee80211_is_robust_mgmt_frame(skb)) {
+ if (is_mt7990(&dev->mt76) && ieee80211_is_beacon(fc) &&
+ (wcid->hw_key_idx2 == 6 || wcid->hw_key_idx2 == 7))
+ hw_bigtk = true;
+
+ if ((key && multicast && ieee80211_is_robust_mgmt_frame(skb)) || hw_bigtk) {
val |= MT_TXD1_BIP;
txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 346d650107d4..e3e0bd46b709 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -249,12 +249,13 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
else if (idx == *wcid_keyidx)
*wcid_keyidx = -1;
- if (cmd != SET_KEY && sta)
+ /* only do remove key for BIGTK */
+ if (cmd != SET_KEY && !is_bigtk)
return 0;
mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key);
- err = mt7996_mcu_add_key(&dev->mt76, vif, key,
+ err = mt7996_mcu_add_key(&dev->mt76, link, key,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
&msta_link->wcid, cmd);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 2bb98df317a6..14a88ef79b6c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2530,7 +2530,7 @@ int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
}
static int
-mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
+mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid,
struct sk_buff *skb,
struct ieee80211_key_conf *key,
enum set_key_cmd cmd)
@@ -2542,7 +2542,10 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec));
sec = (struct sta_rec_sec_uni *)tlv;
- sec->add = 0;
+ /* due to connac3 FW design, we only do remove key for BIGTK; even for
+ * removal, the field should be filled with SET_KEY
+ */
+ sec->add = SET_KEY;
sec->n_cipher = 1;
sec_key = &sec->key[0];
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
@@ -2582,29 +2585,33 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
break;
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ if (!is_mt7990(dev))
+ return -EOPNOTSUPP;
+ sec_key->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_256;
+ break;
default:
return -EOPNOTSUPP;
}
- sec_key->bcn_mode = BP_SW_MODE;
+ sec_key->bcn_mode = is_mt7990(dev) ? BP_HW_MODE : BP_SW_MODE;
return 0;
}
-int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd)
{
- struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
struct sk_buff *skb;
int ret;
- skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid,
- MT7996_STA_UPDATE_MAX_SIZE);
+ skb = __mt76_connac_mcu_alloc_sta_req(dev, (struct mt76_vif_link *)link,
+ wcid, MT7996_STA_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
return PTR_ERR(skb);
- ret = mt7996_mcu_sta_key_tlv(wcid, skb, key, cmd);
+ ret = mt7996_mcu_sta_key_tlv(dev, wcid, skb, key, cmd);
if (ret) {
dev_kfree_skb(skb);
return ret;
@@ -2724,12 +2731,18 @@ mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
static void
mt7996_mcu_beacon_cont(struct mt7996_dev *dev,
struct ieee80211_bss_conf *link_conf,
+ struct mt7996_vif_link *link,
struct sk_buff *rskb, struct sk_buff *skb,
struct bss_bcn_content_tlv *bcn,
struct ieee80211_mutable_offsets *offs)
{
- struct mt76_wcid *wcid = &dev->mt76.global_wcid;
- u8 *buf;
+ u8 *buf, keyidx = link->msta_link.wcid.hw_key_idx2;
+ struct mt76_wcid *wcid;
+
+ if (is_mt7990(&dev->mt76) && (keyidx == 6 || keyidx == 7))
+ wcid = &link->msta_link.wcid;
+ else
+ wcid = &dev->mt76.global_wcid;
bcn->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
bcn->tim_ie_pos = cpu_to_le16(offs->tim_offset);
@@ -2804,7 +2817,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
info = IEEE80211_SKB_CB(skb);
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mlink->band_idx);
- mt7996_mcu_beacon_cont(dev, link_conf, rskb, skb, bcn, &offs);
+ mt7996_mcu_beacon_cont(dev, link_conf, link, rskb, skb, bcn, &offs);
if (link_conf->bssid_indicator)
mt7996_mcu_beacon_mbss(rskb, skb, bcn, &offs);
mt7996_mcu_beacon_cntdwn(rskb, skb, &offs, link_conf->csa_active);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index c47820699ec8..7a884311800e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -849,7 +849,7 @@ void mt7996_update_channel(struct mt76_phy *mphy);
int mt7996_init_debugfs(struct mt7996_dev *dev);
void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len);
bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len);
-int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
+int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd);
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 11/12] wifi: mt76: mt7996: fix using wrong phy to start in mt7996_mac_restart()
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
` (8 preceding siblings ...)
2025-11-05 9:30 ` [PATCH mt76 10/12] wifi: mt76: mt7996: fix MLO set key and group key issues Shayne Chen
@ 2025-11-05 9:30 ` Shayne Chen
2025-11-05 10:45 ` Lorenzo Bianconi
2025-11-05 9:31 ` [PATCH mt76 12/12] wifi: mt76: mt7996: fix EMI rings for RRO Shayne Chen
10 siblings, 1 reply; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:30 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen
Pass the correct mt7996_phy to mt7996_run().
Fixes: 0a5df0ec47f7 ("wifi: mt76: mt7996: remove redundant per-phy mac80211 calls during restart")
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index c1f2938d1f21..2c869f710193 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2368,7 +2368,7 @@ mt7996_mac_restart(struct mt7996_dev *dev)
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
continue;
- ret = mt7996_run(&dev->phy);
+ ret = mt7996_run(phy);
if (ret)
goto out;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH mt76 12/12] wifi: mt76: mt7996: fix EMI rings for RRO
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
` (9 preceding siblings ...)
2025-11-05 9:30 ` [PATCH mt76 11/12] wifi: mt76: mt7996: fix using wrong phy to start in mt7996_mac_restart() Shayne Chen
@ 2025-11-05 9:31 ` Shayne Chen
2025-11-05 10:57 ` Lorenzo Bianconi
10 siblings, 1 reply; 19+ messages in thread
From: Shayne Chen @ 2025-11-05 9:31 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
linux-mediatek, Shayne Chen, Rex Lu
The RRO EMI rings only need to be allocated when WED is not active.
This patch fixes command timeout issue for the setting of WED off and
RRO on.
Fixes: 3a29164425e9 ("wifi: mt76: mt7996: Add SW path for HW-RRO v3.1")
Co-developed-by: Rex Lu <rex.lu@mediatek.com>
Signed-off-by: Rex Lu <rex.lu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7996/dma.c | 15 +++++++++------
.../net/wireless/mediatek/mt76/mt7996/init.c | 19 ++++++++++++++++---
2 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
index 7ac4defca29d..274b273df1ee 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
@@ -515,12 +515,15 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
if (ret)
return ret;
- /* We need to set cpu idx pointer before resetting the EMI
- * queues.
- */
- mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].emi_cpu_idx =
- &dev->wed_rro.emi_rings_cpu.ptr->ring[0].idx;
- mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C], true);
+ if (!mtk_wed_device_active(&mdev->mmio.wed)) {
+ /* We need to set cpu idx pointer before resetting the
+ * EMI queues.
+ */
+ mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].emi_cpu_idx =
+ &dev->wed_rro.emi_rings_cpu.ptr->ring[0].idx;
+ mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C],
+ true);
+ }
goto start_hw_rro;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
index bd7b720c64c5..00a8286bd136 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
@@ -960,9 +960,10 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
MT7996_RRO_MSDU_PG_SIZE_PER_CR);
}
- if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
+ if (!mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+ dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
- sizeof(dev->wed_rro.emi_rings_cpu.ptr),
+ sizeof(*dev->wed_rro.emi_rings_cpu.ptr),
&dev->wed_rro.emi_rings_cpu.phy_addr,
GFP_KERNEL);
if (!ptr)
@@ -971,7 +972,7 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
dev->wed_rro.emi_rings_cpu.ptr = ptr;
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
- sizeof(dev->wed_rro.emi_rings_dma.ptr),
+ sizeof(*dev->wed_rro.emi_rings_dma.ptr),
&dev->wed_rro.emi_rings_dma.phy_addr,
GFP_KERNEL);
if (!ptr)
@@ -1037,6 +1038,18 @@ static void mt7996_wed_rro_free(struct mt7996_dev *dev)
dev->wed_rro.msdu_pg[i].phy_addr);
}
+ if (dev->wed_rro.emi_rings_cpu.ptr)
+ dmam_free_coherent(dev->mt76.dma_dev,
+ sizeof(*dev->wed_rro.emi_rings_cpu.ptr),
+ dev->wed_rro.emi_rings_cpu.ptr,
+ dev->wed_rro.emi_rings_cpu.phy_addr);
+
+ if (dev->wed_rro.emi_rings_dma.ptr)
+ dmam_free_coherent(dev->mt76.dma_dev,
+ sizeof(*dev->wed_rro.emi_rings_dma.ptr),
+ dev->wed_rro.emi_rings_dma.ptr,
+ dev->wed_rro.emi_rings_dma.phy_addr);
+
if (!dev->wed_rro.session.ptr)
return;
--
2.51.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH mt76 05/12] wifi: mt76: mt7996: fix several fields in mt7996_mcu_bss_basic_tlv()
2025-11-05 9:30 ` [PATCH mt76 05/12] wifi: mt76: mt7996: fix several fields in mt7996_mcu_bss_basic_tlv() Shayne Chen
@ 2025-11-05 10:04 ` Lorenzo Bianconi
0 siblings, 0 replies; 19+ messages in thread
From: Lorenzo Bianconi @ 2025-11-05 10:04 UTC (permalink / raw)
To: Shayne Chen
Cc: Felix Fietkau, linux-wireless, Ryder Lee, Evelyn Tsai,
linux-mediatek
[-- Attachment #1: Type: text/plain, Size: 2935 bytes --]
> Fix several fields in mt7996_mcu_bss_basic_tlv() that were not obtained
> from the correct link. Without this patch, the MLD station interface
> does not function properly.
>
> Fixes: 34a41bfbcb71 ("wifi: mt76: mt7996: prepare mt7996_mcu_add_dev/bss_info for MLO support")
> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> .../net/wireless/mediatek/mt76/mt7996/mcu.c | 21 ++++++++++---------
> 1 file changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index 82dd34a8780f..f1892aaf6a91 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> @@ -1037,7 +1037,6 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
> struct mt76_connac_bss_basic_tlv *bss;
> u32 type = CONNECTION_INFRA_AP;
> u16 sta_wlan_idx = wlan_idx;
> - struct ieee80211_sta *sta;
> struct tlv *tlv;
> int idx;
>
> @@ -1048,14 +1047,18 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
> break;
> case NL80211_IFTYPE_STATION:
> if (enable) {
> + struct ieee80211_sta *sta;
> +
> rcu_read_lock();
> - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
> - /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */
> + sta = ieee80211_find_sta(vif, link_conf->bssid);
> if (sta) {
> - struct mt76_wcid *wcid;
> + struct mt7996_sta *msta = (void *)sta->drv_priv;
> + struct mt7996_sta_link *msta_link;
> + int link_id = link_conf->link_id;
>
> - wcid = (struct mt76_wcid *)sta->drv_priv;
> - sta_wlan_idx = wcid->idx;
> + msta_link = rcu_dereference(msta->link[link_id]);
> + if (msta_link)
> + sta_wlan_idx = msta_link->wcid.idx;
> }
> rcu_read_unlock();
> }
> @@ -1072,8 +1075,6 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
> tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_BASIC, sizeof(*bss));
>
> bss = (struct mt76_connac_bss_basic_tlv *)tlv;
> - bss->bcn_interval = cpu_to_le16(link_conf->beacon_int);
> - bss->dtim_period = link_conf->dtim_period;
> bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
> bss->sta_idx = cpu_to_le16(sta_wlan_idx);
> bss->conn_type = cpu_to_le32(type);
> @@ -1093,10 +1094,10 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
>
> memcpy(bss->bssid, link_conf->bssid, ETH_ALEN);
> bss->bcn_interval = cpu_to_le16(link_conf->beacon_int);
> - bss->dtim_period = vif->bss_conf.dtim_period;
> + bss->dtim_period = link_conf->dtim_period;
> bss->phymode = mt76_connac_get_phy_mode(phy, vif,
> chandef->chan->band, NULL);
> - bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, &vif->bss_conf,
> + bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, link_conf,
> chandef->chan->band);
>
> return 0;
> --
> 2.51.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH mt76 06/12] wifi: mt76: mt7996: fix teardown command for an MLD peer
2025-11-05 9:30 ` [PATCH mt76 06/12] wifi: mt76: mt7996: fix teardown command for an MLD peer Shayne Chen
@ 2025-11-05 10:09 ` Lorenzo Bianconi
0 siblings, 0 replies; 19+ messages in thread
From: Lorenzo Bianconi @ 2025-11-05 10:09 UTC (permalink / raw)
To: Shayne Chen
Cc: Felix Fietkau, linux-wireless, Ryder Lee, Evelyn Tsai,
linux-mediatek
[-- Attachment #1: Type: text/plain, Size: 1526 bytes --]
> For an MLD peer, we only need to call the teardown command when removing
> the last link, and there's no need to call mt7996_mcu_add_sta() for the
> earlier links.
>
> Fixes: c1d6dd5d03eb ("wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta rouine")
> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/mt7996/main.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index 5e0b57657e7e..685be98b9f27 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -1206,13 +1206,13 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
> mt7996_mac_twt_teardown_flow(dev, link,
> msta_link, i);
>
> - if (sta->mlo && links == BIT(link_id)) /* last link */
> - mt7996_mcu_teardown_mld_sta(dev, link,
> - msta_link);
> - else
> + if (!sta->mlo)
> mt7996_mcu_add_sta(dev, link_conf, link_sta,
> link, msta_link,
> CONN_STATE_DISCONNECT, false);
> + else if (sta->mlo && links == BIT(link_id)) /* last link */
> + mt7996_mcu_teardown_mld_sta(dev, link,
> + msta_link);
> msta_link->wcid.sta_disabled = 1;
> msta_link->wcid.sta = 0;
> links = links & ~BIT(link_id);
> --
> 2.51.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH mt76 07/12] wifi: mt76: mt7996: set link_valid field when initializing wcid
2025-11-05 9:30 ` [PATCH mt76 07/12] wifi: mt76: mt7996: set link_valid field when initializing wcid Shayne Chen
@ 2025-11-05 10:15 ` Lorenzo Bianconi
0 siblings, 0 replies; 19+ messages in thread
From: Lorenzo Bianconi @ 2025-11-05 10:15 UTC (permalink / raw)
To: Shayne Chen
Cc: Felix Fietkau, linux-wireless, Ryder Lee, Evelyn Tsai,
linux-mediatek
[-- Attachment #1: Type: text/plain, Size: 1437 bytes --]
> This ensures the upper layer uses the correct link ID during packet
> processing.
>
> Fixes: dd82a9e02c05 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/mt7996/main.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index 685be98b9f27..c26f8f49ce44 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -343,6 +343,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
> INIT_LIST_HEAD(&msta_link->rc_list);
> msta_link->wcid.idx = idx;
> msta_link->wcid.link_id = link_conf->link_id;
> + msta_link->wcid.link_valid = ieee80211_vif_is_mld(vif);
> msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
> mt76_wcid_init(&msta_link->wcid, band_idx);
>
> @@ -984,6 +985,7 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
> msta_link->wcid.sta = 1;
> msta_link->wcid.idx = idx;
> msta_link->wcid.link_id = link_id;
> + msta_link->wcid.link_valid = !!sta->valid_links;
> msta_link->wcid.def_wcid = &msta->deflink.wcid;
>
> ewma_avg_signal_init(&msta_link->avg_ack_signal);
> --
> 2.51.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH mt76 08/12] wifi: mt76: mt7996: use correct link_id when filling TXD and TXP
2025-11-05 9:30 ` [PATCH mt76 08/12] wifi: mt76: mt7996: use correct link_id when filling TXD and TXP Shayne Chen
@ 2025-11-05 10:34 ` Lorenzo Bianconi
0 siblings, 0 replies; 19+ messages in thread
From: Lorenzo Bianconi @ 2025-11-05 10:34 UTC (permalink / raw)
To: Shayne Chen
Cc: Felix Fietkau, linux-wireless, Ryder Lee, Evelyn Tsai,
linux-mediatek
[-- Attachment #1: Type: text/plain, Size: 3855 bytes --]
> Obtain the correct link ID and, if needed, switch to the corresponding
> wcid before populating the TX descriptor and TX payload.
>
> Rules for link id:
> - For QoS data from MLD peers (excluding EAPOL), select the primary or
> secondary wcid based on whether the TID is odd or even to meet FW/HW
> requirements
> - For other packets, use IEEE80211_TX_CTRL_MLO_LINK if specified
> (such as multicast and broadcast packets)
Hi Shayne,
thx for the fix. I guess it is mostly fine, just few comments inline. Fixing
them:
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Regards,
Lorenzo
>
> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
> ---
> .../net/wireless/mediatek/mt76/mt7996/mac.c | 34 ++++++++++++++++---
> .../net/wireless/mediatek/mt76/mt7996/main.c | 6 ++++
> .../net/wireless/mediatek/mt76/mt7996/mcu.c | 4 +--
> .../wireless/mediatek/mt76/mt7996/mt7996.h | 1 +
> 4 files changed, 39 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> index 7d5f9d9b3b62..579084cbb30f 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> @@ -1035,15 +1035,20 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
> struct ieee80211_sta *sta,
> struct mt76_tx_info *tx_info)
> {
[...]
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index c26f8f49ce44..3958688d622b 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -963,6 +963,7 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
>
> msta_link = &msta->deflink;
> msta->deflink_id = link_id;
> + msta->seclink_id = msta->deflink_id;
>
> for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
> struct mt76_txq *mtxq;
> @@ -977,6 +978,11 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
> msta_link = kzalloc(sizeof(*msta_link), GFP_KERNEL);
> if (!msta_link)
> return -ENOMEM;
> +
> + if (msta->seclink_id == msta->deflink_id &&
> + (sta->valid_links & ~(BIT(msta->deflink_id))))
> + msta->seclink_id = __ffs(sta->valid_links &
> + ~(BIT(msta->deflink_id)));
nit: you do need brackets around BIT().
I think we are missing seclink_id management when the corresponding link is
removed, right?
> }
>
> INIT_LIST_HEAD(&msta_link->rc_list);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index f1892aaf6a91..2bb98df317a6 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> @@ -2394,8 +2394,8 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
> mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx);
>
> if (nlinks > 1) {
> - link_id = __ffs(sta->valid_links & ~BIT(msta->deflink_id));
> - msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
> + msta_link = mt76_dereference(msta->link[msta->seclink_id],
> + &dev->mt76);
> if (!msta_link)
> return;
> }
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> index 65eeb37ab8c7..c47820699ec8 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> @@ -243,6 +243,7 @@ struct mt7996_sta {
> struct mt7996_sta_link deflink; /* must be first */
> struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
> u8 deflink_id;
> + u8 seclink_id;
>
> struct mt7996_vif *vif;
> };
> --
> 2.51.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH mt76 09/12] wifi: mt76: mt7996: fix MLD group index assignment
2025-11-05 9:30 ` [PATCH mt76 09/12] wifi: mt76: mt7996: fix MLD group index assignment Shayne Chen
@ 2025-11-05 10:42 ` Lorenzo Bianconi
0 siblings, 0 replies; 19+ messages in thread
From: Lorenzo Bianconi @ 2025-11-05 10:42 UTC (permalink / raw)
To: Shayne Chen
Cc: Felix Fietkau, linux-wireless, Ryder Lee, Evelyn Tsai,
linux-mediatek
[-- Attachment #1: Type: text/plain, Size: 3850 bytes --]
> Fix extender mode and MBSS issues caused by incorrect assignment of the
> MLD group and remap indices.
>
> Fixes: ed01c310eca9 ("wifi: mt76: mt7996: Fix mt7996_mcu_bss_mld_tlv routine")
> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> .../net/wireless/mediatek/mt76/mt7996/main.c | 58 +++++++++++++------
> 1 file changed, 40 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index 3958688d622b..346d650107d4 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -90,9 +90,11 @@ static void mt7996_stop(struct ieee80211_hw *hw, bool suspend)
> {
> }
>
> -static inline int get_free_idx(u32 mask, u8 start, u8 end)
> +static inline int get_free_idx(u64 mask, u8 start, u8 end)
> {
> - return ffs(~mask & GENMASK(end, start));
> + if (~mask & GENMASK_ULL(end, start))
> + return __ffs64(~mask & GENMASK_ULL(end, start)) + 1;
> + return 0;
> }
>
> static int get_omac_idx(enum nl80211_iftype type, u64 mask)
> @@ -308,12 +310,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
> if (idx < 0)
> return -ENOSPC;
>
> - if (!dev->mld_idx_mask) { /* first link in the group */
> - mvif->mld_group_idx = get_own_mld_idx(dev->mld_idx_mask, true);
> - mvif->mld_remap_idx = get_free_idx(dev->mld_remap_idx_mask,
> - 0, 15);
> - }
> -
> mld_idx = get_own_mld_idx(dev->mld_idx_mask, false);
> if (mld_idx < 0)
> return -ENOSPC;
> @@ -331,10 +327,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
> return ret;
>
> dev->mt76.vif_mask |= BIT_ULL(mlink->idx);
> - if (!dev->mld_idx_mask) {
> - dev->mld_idx_mask |= BIT_ULL(mvif->mld_group_idx);
> - dev->mld_remap_idx_mask |= BIT_ULL(mvif->mld_remap_idx);
> - }
> dev->mld_idx_mask |= BIT_ULL(link->mld_idx);
> phy->omac_mask |= BIT_ULL(mlink->omac_idx);
>
> @@ -424,11 +416,6 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
> dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);
> dev->mld_idx_mask &= ~BIT_ULL(link->mld_idx);
> phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
> - if (!(dev->mld_idx_mask & ~BIT_ULL(mvif->mld_group_idx))) {
> - /* last link */
> - dev->mld_idx_mask &= ~BIT_ULL(mvif->mld_group_idx);
> - dev->mld_remap_idx_mask &= ~BIT_ULL(mvif->mld_remap_idx);
> - }
>
> spin_lock_bh(&dev->mt76.sta_poll_lock);
> if (!list_empty(&msta_link->wcid.poll_list))
> @@ -2225,7 +2212,42 @@ mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> u16 old_links, u16 new_links,
> struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
> {
> - return 0;
> + struct mt7996_dev *dev = mt7996_hw_dev(hw);
> + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
> + int ret = 0;
> +
> + mutex_lock(&dev->mt76.mutex);
> +
> + if (!old_links) {
> + int idx;
> +
> + idx = get_own_mld_idx(dev->mld_idx_mask, true);
> + if (idx < 0) {
> + ret = -ENOSPC;
> + goto out;
> + }
> + mvif->mld_group_idx = idx;
> + dev->mld_idx_mask |= BIT_ULL(mvif->mld_group_idx);
> +
> + idx = get_free_idx(dev->mld_remap_idx_mask, 0, 15) - 1;
> + if (idx < 0) {
> + ret = -ENOSPC;
> + goto out;
> + }
> + mvif->mld_remap_idx = idx;
> + dev->mld_remap_idx_mask |= BIT_ULL(mvif->mld_remap_idx);
> + }
> +
> + if (new_links)
> + goto out;
> +
> + dev->mld_idx_mask &= ~BIT_ULL(mvif->mld_group_idx);
> + dev->mld_remap_idx_mask &= ~BIT_ULL(mvif->mld_remap_idx);
> +
> +out:
> + mutex_unlock(&dev->mt76.mutex);
> +
> + return ret;
> }
>
> static void
> --
> 2.51.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH mt76 11/12] wifi: mt76: mt7996: fix using wrong phy to start in mt7996_mac_restart()
2025-11-05 9:30 ` [PATCH mt76 11/12] wifi: mt76: mt7996: fix using wrong phy to start in mt7996_mac_restart() Shayne Chen
@ 2025-11-05 10:45 ` Lorenzo Bianconi
0 siblings, 0 replies; 19+ messages in thread
From: Lorenzo Bianconi @ 2025-11-05 10:45 UTC (permalink / raw)
To: Shayne Chen
Cc: Felix Fietkau, linux-wireless, Ryder Lee, Evelyn Tsai,
linux-mediatek
[-- Attachment #1: Type: text/plain, Size: 929 bytes --]
> Pass the correct mt7996_phy to mt7996_run().
>
> Fixes: 0a5df0ec47f7 ("wifi: mt76: mt7996: remove redundant per-phy mac80211 calls during restart")
> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> index c1f2938d1f21..2c869f710193 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> @@ -2368,7 +2368,7 @@ mt7996_mac_restart(struct mt7996_dev *dev)
> if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
> continue;
>
> - ret = mt7996_run(&dev->phy);
> + ret = mt7996_run(phy);
> if (ret)
> goto out;
> }
> --
> 2.51.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH mt76 12/12] wifi: mt76: mt7996: fix EMI rings for RRO
2025-11-05 9:31 ` [PATCH mt76 12/12] wifi: mt76: mt7996: fix EMI rings for RRO Shayne Chen
@ 2025-11-05 10:57 ` Lorenzo Bianconi
0 siblings, 0 replies; 19+ messages in thread
From: Lorenzo Bianconi @ 2025-11-05 10:57 UTC (permalink / raw)
To: Shayne Chen
Cc: Felix Fietkau, linux-wireless, Ryder Lee, Evelyn Tsai,
linux-mediatek, Rex Lu
[-- Attachment #1: Type: text/plain, Size: 3580 bytes --]
On Nov 05, Shayne Chen wrote:
> The RRO EMI rings only need to be allocated when WED is not active.
> This patch fixes command timeout issue for the setting of WED off and
> RRO on.
>
> Fixes: 3a29164425e9 ("wifi: mt76: mt7996: Add SW path for HW-RRO v3.1")
> Co-developed-by: Rex Lu <rex.lu@mediatek.com>
> Signed-off-by: Rex Lu <rex.lu@mediatek.com>
> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> .../net/wireless/mediatek/mt76/mt7996/dma.c | 15 +++++++++------
> .../net/wireless/mediatek/mt76/mt7996/init.c | 19 ++++++++++++++++---
> 2 files changed, 25 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
> index 7ac4defca29d..274b273df1ee 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
> @@ -515,12 +515,15 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
> if (ret)
> return ret;
>
> - /* We need to set cpu idx pointer before resetting the EMI
> - * queues.
> - */
> - mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].emi_cpu_idx =
> - &dev->wed_rro.emi_rings_cpu.ptr->ring[0].idx;
> - mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C], true);
> + if (!mtk_wed_device_active(&mdev->mmio.wed)) {
> + /* We need to set cpu idx pointer before resetting the
> + * EMI queues.
> + */
> + mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].emi_cpu_idx =
> + &dev->wed_rro.emi_rings_cpu.ptr->ring[0].idx;
> + mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C],
> + true);
> + }
> goto start_hw_rro;
> }
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
> index bd7b720c64c5..00a8286bd136 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
> @@ -960,9 +960,10 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
> MT7996_RRO_MSDU_PG_SIZE_PER_CR);
> }
>
> - if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
> + if (!mtk_wed_device_active(&dev->mt76.mmio.wed) &&
> + dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
> ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
> - sizeof(dev->wed_rro.emi_rings_cpu.ptr),
> + sizeof(*dev->wed_rro.emi_rings_cpu.ptr),
> &dev->wed_rro.emi_rings_cpu.phy_addr,
> GFP_KERNEL);
> if (!ptr)
> @@ -971,7 +972,7 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
> dev->wed_rro.emi_rings_cpu.ptr = ptr;
>
> ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
> - sizeof(dev->wed_rro.emi_rings_dma.ptr),
> + sizeof(*dev->wed_rro.emi_rings_dma.ptr),
> &dev->wed_rro.emi_rings_dma.phy_addr,
> GFP_KERNEL);
> if (!ptr)
> @@ -1037,6 +1038,18 @@ static void mt7996_wed_rro_free(struct mt7996_dev *dev)
> dev->wed_rro.msdu_pg[i].phy_addr);
> }
>
> + if (dev->wed_rro.emi_rings_cpu.ptr)
> + dmam_free_coherent(dev->mt76.dma_dev,
> + sizeof(*dev->wed_rro.emi_rings_cpu.ptr),
> + dev->wed_rro.emi_rings_cpu.ptr,
> + dev->wed_rro.emi_rings_cpu.phy_addr);
> +
> + if (dev->wed_rro.emi_rings_dma.ptr)
> + dmam_free_coherent(dev->mt76.dma_dev,
> + sizeof(*dev->wed_rro.emi_rings_dma.ptr),
> + dev->wed_rro.emi_rings_dma.ptr,
> + dev->wed_rro.emi_rings_dma.phy_addr);
> +
> if (!dev->wed_rro.session.ptr)
> return;
>
> --
> 2.51.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2025-11-05 10:57 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-05 9:30 [PATCH mt76 01/12] wifi: mt76: mt7996: fix max nss value when getting rx chainmask Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 02/12] wifi: mt76: mt7996: no need to wait ACK event for SDO command Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 03/12] wifi: mt76: mt7996: fix implicit beamforming support for mt7992 Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 04/12] wifi: mt76: mt7996: support fixed rate for link station Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 05/12] wifi: mt76: mt7996: fix several fields in mt7996_mcu_bss_basic_tlv() Shayne Chen
2025-11-05 10:04 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 06/12] wifi: mt76: mt7996: fix teardown command for an MLD peer Shayne Chen
2025-11-05 10:09 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 07/12] wifi: mt76: mt7996: set link_valid field when initializing wcid Shayne Chen
2025-11-05 10:15 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 08/12] wifi: mt76: mt7996: use correct link_id when filling TXD and TXP Shayne Chen
2025-11-05 10:34 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 09/12] wifi: mt76: mt7996: fix MLD group index assignment Shayne Chen
2025-11-05 10:42 ` Lorenzo Bianconi
2025-11-05 9:30 ` [PATCH mt76 10/12] wifi: mt76: mt7996: fix MLO set key and group key issues Shayne Chen
2025-11-05 9:30 ` [PATCH mt76 11/12] wifi: mt76: mt7996: fix using wrong phy to start in mt7996_mac_restart() Shayne Chen
2025-11-05 10:45 ` Lorenzo Bianconi
2025-11-05 9:31 ` [PATCH mt76 12/12] wifi: mt76: mt7996: fix EMI rings for RRO Shayne Chen
2025-11-05 10:57 ` Lorenzo Bianconi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).