linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes
@ 2025-07-04 13:08 Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 1/9] wifi: mt76: fix vif link allocation Lorenzo Bianconi
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Multiple MLO fixes for MT7996 driver in the mixed MLO/non-MLO scenario.

---
Felix Fietkau (1):
      wifi: mt76: fix vif link allocation

Lorenzo Bianconi (8):
      wifi: mt76: mt7996: Fix secondary link lookup in mt7996_mcu_sta_mld_setup_tlv()
      wifi: mt76: mt7996: Rely on for_each_sta_active_link() in mt7996_mcu_sta_mld_setup_tlv()
      wifi: mt76: mt7996: Do not set wcid.sta to 1 in mt7996_mac_sta_event()
      wifi: mt76: mt7996: Fix mlink lookup in mt7996_tx_prepare_skb
      wifi: mt76: mt7996: Fix possible OOB access in mt7996_tx()
      wifi: mt76: mt7996: Fix valid_links bitmask in mt7996_mac_sta_{add,remove}
      wifi: mt76: mt7996: Add MLO support to mt7996_tx_check_aggr()
      wifi: mt76: mt7996: Move num_sta accounting in mt7996_mac_sta_{add,remove}_links

 drivers/net/wireless/mediatek/mt76/channel.c     |  4 +-
 drivers/net/wireless/mediatek/mt76/mt76.h        |  5 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c  | 48 +++++++-------
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 80 ++++++++++++++----------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c  | 17 +++--
 5 files changed, 83 insertions(+), 71 deletions(-)
---
base-commit: b3a431fe2e399b2e0cc5f43f7e9d63d63d3710ee
change-id: 20250704-mt7996-mlo-fixes-ec842bcc890b

Best regards,
-- 
Lorenzo Bianconi <lorenzo@kernel.org>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH mt76 1/9] wifi: mt76: fix vif link allocation
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 2/9] wifi: mt76: mt7996: Fix secondary link lookup in mt7996_mcu_sta_mld_setup_tlv() Lorenzo Bianconi
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek

From: Felix Fietkau <nbd@nbd.name>

Reuse the vif deflink for link_id = 0 in order to avoid confusion with
vif->bss_conf, which also gets a link id of 0.

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

diff --git a/drivers/net/wireless/mediatek/mt76/channel.c b/drivers/net/wireless/mediatek/mt76/channel.c
index cc2d888e3f17a58512e6282686b446109ec7ab3c..77b75792eb488e9c5da9ca8026c04157182c13a4 100644
--- a/drivers/net/wireless/mediatek/mt76/channel.c
+++ b/drivers/net/wireless/mediatek/mt76/channel.c
@@ -173,13 +173,13 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw,
 	if (!mlink)
 		goto out;
 
-	if (link_conf != &vif->bss_conf)
+	if (mlink != (struct mt76_vif_link *)vif->drv_priv)
 		rcu_assign_pointer(mvif->link[link_id], NULL);
 
 	dev->drv->vif_link_remove(phy, vif, link_conf, mlink);
 	mlink->ctx = NULL;
 
-	if (link_conf != &vif->bss_conf)
+	if (mlink != (struct mt76_vif_link *)vif->drv_priv)
 		kfree_rcu(mlink, rcu_head);
 
 out:
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 14927a92f9d1b313253158c0e53dce8fab9fba18..022d83bb03da1803440c942c9343b709d76aecd4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1865,6 +1865,9 @@ mt76_vif_link(struct mt76_dev *dev, struct ieee80211_vif *vif, int link_id)
 	struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
 	struct mt76_vif_data *mvif = mlink->mvif;
 
+	if (!link_id)
+		return mlink;
+
 	return mt76_dereference(mvif->link[link_id], dev);
 }
 
@@ -1875,7 +1878,7 @@ mt76_vif_conf_link(struct mt76_dev *dev, struct ieee80211_vif *vif,
 	struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
 	struct mt76_vif_data *mvif = mlink->mvif;
 
-	if (link_conf == &vif->bss_conf)
+	if (link_conf == &vif->bss_conf || !link_conf->link_id)
 		return mlink;
 
 	return mt76_dereference(mvif->link[link_conf->link_id], dev);

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH mt76 2/9] wifi: mt76: mt7996: Fix secondary link lookup in mt7996_mcu_sta_mld_setup_tlv()
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 1/9] wifi: mt76: fix vif link allocation Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 3/9] wifi: mt76: mt7996: Rely on for_each_sta_active_link() " Lorenzo Bianconi
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Use proper link_id value for secondary link lookup in
mt7996_mcu_sta_mld_setup_tlv routine.

Fixes: 00cef41d9d8f5 ("wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index f0adc0b4b8b6ccdc6ce11991a4d99b89500fe7a9..1bf5632cb0f754d49ec6201254d35652d23c0a8c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2243,8 +2243,7 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 
 	if (nlinks > 1) {
 		link_id = __ffs(links & ~BIT(msta->deflink_id));
-		msta_link = mt76_dereference(msta->link[msta->deflink_id],
-					     &dev->mt76);
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
 		if (!msta_link)
 			return;
 	}

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH mt76 3/9] wifi: mt76: mt7996: Rely on for_each_sta_active_link() in mt7996_mcu_sta_mld_setup_tlv()
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 1/9] wifi: mt76: fix vif link allocation Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 2/9] wifi: mt76: mt7996: Fix secondary link lookup in mt7996_mcu_sta_mld_setup_tlv() Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 4/9] wifi: mt76: mt7996: Do not set wcid.sta to 1 in mt7996_mac_sta_event() Lorenzo Bianconi
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Reuse for_each_sta_active_link utility macro in
mt7996_mcu_sta_mld_setup_tlv routine.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 1bf5632cb0f754d49ec6201254d35652d23c0a8c..0374872db4777cc85eed594f7d977dd822927b6d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2216,15 +2216,15 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 
 static void
 mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+			     struct ieee80211_vif *vif,
 			     struct ieee80211_sta *sta)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	unsigned long links = sta->valid_links;
-	unsigned int nlinks = hweight16(links);
+	unsigned int nlinks = hweight16(sta->valid_links);
 	struct mld_setup_link *mld_setup_link;
+	struct ieee80211_link_sta *link_sta;
 	struct sta_rec_mld_setup *mld_setup;
 	struct mt7996_sta_link *msta_link;
-	struct ieee80211_vif *vif;
 	unsigned int link_id;
 	struct tlv *tlv;
 
@@ -2242,7 +2242,7 @@ 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(links & ~BIT(msta->deflink_id));
+		link_id = __ffs(sta->valid_links & ~BIT(msta->deflink_id));
 		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
 		if (!msta_link)
 			return;
@@ -2250,9 +2250,8 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 	mld_setup->seconed_id = cpu_to_le16(msta_link->wcid.idx);
 	mld_setup->link_num = nlinks;
 
-	vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
 	mld_setup_link = (struct mld_setup_link *)mld_setup->link_info;
-	for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
 		struct mt7996_vif_link *link;
 
 		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
@@ -2344,7 +2343,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		mt7996_mcu_sta_muru_tlv(dev, skb, link_conf, link_sta);
 
 		if (sta->mlo) {
-			mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
+			mt7996_mcu_sta_mld_setup_tlv(dev, skb, link_conf->vif,
+						     sta);
 			mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
 		}
 	}

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH mt76 4/9] wifi: mt76: mt7996: Do not set wcid.sta to 1 in mt7996_mac_sta_event()
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
                   ` (2 preceding siblings ...)
  2025-07-04 13:08 ` [PATCH mt76 3/9] wifi: mt76: mt7996: Rely on for_each_sta_active_link() " Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 5/9] wifi: mt76: mt7996: Fix mlink lookup in mt7996_tx_prepare_skb Lorenzo Bianconi
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

msta_link->wcid.sta is already set to 1 in mt7996_mac_sta_init_link
routine.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 5283aee619a9811f2e75fa4434ceced9185991f0..d1f90dea512bade652743611b7d062863a63ccfe 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1119,7 +1119,6 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 				return err;
 
 			msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET;
-			msta_link->wcid.sta = 1;
 			break;
 		case MT76_STA_EVENT_AUTHORIZE:
 			err = mt7996_mcu_add_sta(dev, link_conf, link_sta,

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH mt76 5/9] wifi: mt76: mt7996: Fix mlink lookup in mt7996_tx_prepare_skb
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
                   ` (3 preceding siblings ...)
  2025-07-04 13:08 ` [PATCH mt76 4/9] wifi: mt76: mt7996: Do not set wcid.sta to 1 in mt7996_mac_sta_event() Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 6/9] wifi: mt76: mt7996: Fix possible OOB access in mt7996_tx() Lorenzo Bianconi
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Use proper link_id in mt7996_tx_prepare_skb routine for mlink lookup.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 0dbd4662bc842947abf09f9ae3aa4a1d4b86cba8..0844f27b8458fe53c0765ece70fe91acdfc6510a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1087,9 +1087,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
 		if (wcid->offchannel)
 			mlink = rcu_dereference(mvif->mt76.offchannel_link);
 		if (!mlink)
-			mlink = &mvif->deflink.mt76;
+			mlink = rcu_dereference(mvif->mt76.link[wcid->link_id]);
 
-		txp->fw.bss_idx = mlink->idx;
+		txp->fw.bss_idx = mlink ? mlink->idx : mvif->deflink.mt76.idx;
 	}
 
 	txp->fw.token = cpu_to_le16(id);

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH mt76 6/9] wifi: mt76: mt7996: Fix possible OOB access in mt7996_tx()
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
                   ` (4 preceding siblings ...)
  2025-07-04 13:08 ` [PATCH mt76 5/9] wifi: mt76: mt7996: Fix mlink lookup in mt7996_tx_prepare_skb Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 7/9] wifi: mt76: mt7996: Fix valid_links bitmask in mt7996_mac_sta_{add,remove} Lorenzo Bianconi
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Fis possible Out-Of-Boundary access in mt7996_tx routine if link_id is
set to IEEE80211_LINK_UNSPECIFIED

Fixes: 3ce8acb86b661 ("wifi: mt76: mt7996: Update mt7996_tx to MLO support")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index d1f90dea512bade652743611b7d062863a63ccfe..6404514556419f75b69a783d96b0920157263e04 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1216,10 +1216,17 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 
 	if (vif) {
 		struct mt7996_vif *mvif = (void *)vif->drv_priv;
-		struct mt76_vif_link *mlink;
+		struct mt76_vif_link *mlink = &mvif->deflink.mt76;
 
-		mlink = rcu_dereference(mvif->mt76.link[link_id]);
-		if (mlink && mlink->wcid)
+		if (link_id < IEEE80211_LINK_UNSPECIFIED)
+			mlink = rcu_dereference(mvif->mt76.link[link_id]);
+
+		if (!mlink) {
+			ieee80211_free_txskb(hw, skb);
+			goto unlock;
+		}
+
+		if (mlink->wcid)
 			wcid = mlink->wcid;
 
 		if (mvif->mt76.roc_phy &&
@@ -1228,7 +1235,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 			if (mphy->roc_link)
 				wcid = mphy->roc_link->wcid;
 		} else {
-			mphy = mt76_vif_link_phy(&mvif->deflink.mt76);
+			mphy = mt76_vif_link_phy(mlink);
 		}
 	}
 
@@ -1237,7 +1244,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 		goto unlock;
 	}
 
-	if (control->sta) {
+	if (control->sta && link_id < IEEE80211_LINK_UNSPECIFIED) {
 		struct mt7996_sta *msta = (void *)control->sta->drv_priv;
 		struct mt7996_sta_link *msta_link;
 

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH mt76 7/9] wifi: mt76: mt7996: Fix valid_links bitmask in mt7996_mac_sta_{add,remove}
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
                   ` (5 preceding siblings ...)
  2025-07-04 13:08 ` [PATCH mt76 6/9] wifi: mt76: mt7996: Fix possible OOB access in mt7996_tx() Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 8/9] wifi: mt76: mt7996: Add MLO support to mt7996_tx_check_aggr() Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 9/9] wifi: mt76: mt7996: Move num_sta accounting in mt7996_mac_sta_{add,remove}_links Lorenzo Bianconi
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

sta->valid_links bitmask can be set even for non-MLO client.

Fixes: dd82a9e02c054 ("wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 6404514556419f75b69a783d96b0920157263e04..ea0cdd092a3f396c2a8cb655ff941b833fb9983e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1061,7 +1061,7 @@ mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	unsigned long links = sta->mlo ? sta->valid_links : BIT(0);
+	unsigned long links = sta->valid_links ? sta->valid_links : BIT(0);
 	int err;
 
 	mutex_lock(&mdev->mutex);
@@ -1155,7 +1155,7 @@ mt7996_mac_sta_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 {
 	struct mt76_dev *mdev = mphy->dev;
 	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
-	unsigned long links = sta->mlo ? sta->valid_links : BIT(0);
+	unsigned long links = sta->valid_links ? sta->valid_links : BIT(0);
 
 	mutex_lock(&mdev->mutex);
 

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH mt76 8/9] wifi: mt76: mt7996: Add MLO support to mt7996_tx_check_aggr()
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
                   ` (6 preceding siblings ...)
  2025-07-04 13:08 ` [PATCH mt76 7/9] wifi: mt76: mt7996: Fix valid_links bitmask in mt7996_mac_sta_{add,remove} Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  2025-07-04 13:08 ` [PATCH mt76 9/9] wifi: mt76: mt7996: Move num_sta accounting in mt7996_mac_sta_{add,remove}_links Lorenzo Bianconi
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Generalize mt7996_tx_check_aggr() and mt7996_txwi_free() routines to
introduce MLO support for MT7996 driver.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 44 ++++++++++++-------------
 1 file changed, 21 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 0844f27b8458fe53c0765ece70fe91acdfc6510a..02e10d744feb45048401ef15e74c3e03b53b5e08 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1129,15 +1129,14 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
 }
 
 static void
-mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
+mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta,
+		     struct mt76_wcid *wcid, struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
-	struct mt7996_sta_link *msta_link;
-	struct mt7996_sta *msta;
 	u16 fc, tid;
 
-	if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
+	if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
 		return;
 
 	tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
@@ -1146,7 +1145,8 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
 
 	if (is_8023) {
 		fc = IEEE80211_FTYPE_DATA |
-		     (sta->wme ? IEEE80211_STYPE_QOS_DATA : IEEE80211_STYPE_DATA);
+		     (link_sta->sta->wme ? IEEE80211_STYPE_QOS_DATA
+					 : IEEE80211_STYPE_DATA);
 	} else {
 		/* No need to get precise TID for Action/Management Frame,
 		 * since it will not meet the following Frame Control
@@ -1162,19 +1162,16 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
 	if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
 		return;
 
-	msta = (struct mt7996_sta *)sta->drv_priv;
-	msta_link = &msta->deflink;
-
-	if (!test_and_set_bit(tid, &msta_link->wcid.ampdu_state))
-		ieee80211_start_tx_ba_session(sta, tid, 0);
+	if (!test_and_set_bit(tid, &wcid->ampdu_state))
+		ieee80211_start_tx_ba_session(link_sta->sta, tid, 0);
 }
 
 static void
 mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
-		 struct ieee80211_sta *sta, struct list_head *free_list)
+		 struct ieee80211_link_sta *link_sta,
+		 struct mt76_wcid *wcid, struct list_head *free_list)
 {
 	struct mt76_dev *mdev = &dev->mt76;
-	struct mt76_wcid *wcid;
 	__le32 *txwi;
 	u16 wcid_idx;
 
@@ -1183,12 +1180,10 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
 		goto out;
 
 	txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
-	if (sta) {
-		wcid = (struct mt76_wcid *)sta->drv_priv;
+	if (link_sta) {
 		wcid_idx = wcid->idx;
-
 		if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
-			mt7996_tx_check_aggr(sta, t->skb);
+			mt7996_tx_check_aggr(link_sta, wcid, t->skb);
 	} else {
 		wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX);
 	}
@@ -1207,8 +1202,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
 	struct mt76_dev *mdev = &dev->mt76;
 	struct mt76_phy *phy2 = mdev->phys[MT_BAND1];
 	struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
+	struct ieee80211_link_sta *link_sta = NULL;
 	struct mt76_txwi_cache *txwi;
-	struct ieee80211_sta *sta = NULL;
 	struct mt76_wcid *wcid = NULL;
 	LIST_HEAD(free_list);
 	struct sk_buff *skb, *tmp;
@@ -1245,7 +1240,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
 		 */
 		info = le32_to_cpu(*cur_info);
 		if (info & MT_TXFREE_INFO_PAIR) {
-			struct mt7996_sta_link *msta_link;
+			struct ieee80211_sta *sta;
 			u16 idx;
 
 			idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
@@ -1254,9 +1249,11 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
 			if (!sta)
 				goto next;
 
-			msta_link = container_of(wcid, struct mt7996_sta_link,
-						 wcid);
-			mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
+			link_sta = rcu_dereference(sta->link[wcid->link_id]);
+			if (!link_sta)
+				goto next;
+
+			mt76_wcid_add_poll(&dev->mt76, wcid);
 next:
 			/* ver 7 has a new DW with pair = 1, skip it */
 			if (ver == 7 && ((void *)(cur_info + 1) < end) &&
@@ -1289,7 +1286,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
 			if (!txwi)
 				continue;
 
-			mt7996_txwi_free(dev, txwi, sta, &free_list);
+			mt7996_txwi_free(dev, txwi, link_sta, wcid,
+					 &free_list);
 		}
 	}
 
@@ -1748,7 +1746,7 @@ void mt7996_tx_token_put(struct mt7996_dev *dev)
 
 	spin_lock_bh(&dev->mt76.token_lock);
 	idr_for_each_entry(&dev->mt76.token, txwi, id) {
-		mt7996_txwi_free(dev, txwi, NULL, NULL);
+		mt7996_txwi_free(dev, txwi, NULL, NULL, NULL);
 		dev->mt76.token_count--;
 	}
 	spin_unlock_bh(&dev->mt76.token_lock);

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH mt76 9/9] wifi: mt76: mt7996: Move num_sta accounting in mt7996_mac_sta_{add,remove}_links
  2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
                   ` (7 preceding siblings ...)
  2025-07-04 13:08 ` [PATCH mt76 8/9] wifi: mt76: mt7996: Add MLO support to mt7996_tx_check_aggr() Lorenzo Bianconi
@ 2025-07-04 13:08 ` Lorenzo Bianconi
  8 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2025-07-04 13:08 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
	Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Move phy num_sta accounting in mt7996_mac_sta_add() and
mt7996_mac_sta_remove() routines in order to take into account all
possibles MLO links.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 58 +++++++++++++-----------
 1 file changed, 32 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index ea0cdd092a3f396c2a8cb655ff941b833fb9983e..f846b8309ae2e9c39f9d5f2a21ca1edd89dcdf0c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -960,8 +960,8 @@ mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
 }
 
 static void
-mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta,
-			    unsigned long links)
+mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+			    struct ieee80211_sta *sta, unsigned long links)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt76_dev *mdev = &dev->mt76;
@@ -969,6 +969,8 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta,
 
 	for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
 		struct mt7996_sta_link *msta_link = NULL;
+		struct mt7996_vif_link *link;
+		struct mt76_phy *mphy;
 
 		msta_link = rcu_replace_pointer(msta->link[link_id], msta_link,
 						lockdep_is_held(&mdev->mutex));
@@ -976,6 +978,15 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta,
 			continue;
 
 		mt7996_mac_sta_deinit_link(dev, msta_link);
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		mphy = mt76_vif_link_phy(&link->mt76);
+		if (!mphy)
+			continue;
+
+		mphy->num_sta--;
 		if (msta->deflink_id == link_id) {
 			msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
 			continue;
@@ -997,6 +1008,7 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		struct ieee80211_bss_conf *link_conf;
 		struct ieee80211_link_sta *link_sta;
 		struct mt7996_vif_link *link;
+		struct mt76_phy *mphy;
 
 		if (rcu_access_pointer(msta->link[link_id]))
 			continue;
@@ -1023,12 +1035,19 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 					       link_id);
 		if (err)
 			goto error_unlink;
+
+		mphy = mt76_vif_link_phy(&link->mt76);
+		if (!mphy) {
+			err = -EINVAL;
+			goto error_unlink;
+		}
+		mphy->num_sta++;
 	}
 
 	return 0;
 
 error_unlink:
-	mt7996_mac_sta_remove_links(dev, sta, new_links);
+	mt7996_mac_sta_remove_links(dev, vif, sta, new_links);
 
 	return err;
 }
@@ -1045,7 +1064,7 @@ mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 	mutex_lock(&dev->mt76.mutex);
 
-	mt7996_mac_sta_remove_links(dev, sta, rem);
+	mt7996_mac_sta_remove_links(dev, vif, sta, rem);
 	ret = mt7996_mac_sta_add_links(dev, vif, sta, add);
 
 	mutex_unlock(&dev->mt76.mutex);
@@ -1054,25 +1073,21 @@ mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 }
 
 static int
-mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
+mt7996_mac_sta_add(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		   struct ieee80211_sta *sta)
 {
-	struct mt76_dev *mdev = mphy->dev;
-	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	unsigned long links = sta->valid_links ? sta->valid_links : BIT(0);
 	int err;
 
-	mutex_lock(&mdev->mutex);
+	mutex_lock(&dev->mt76.mutex);
 
 	msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
 	msta->vif = mvif;
 	err = mt7996_mac_sta_add_links(dev, vif, sta, links);
-	if (!err)
-		mphy->num_sta++;
 
-	mutex_unlock(&mdev->mutex);
+	mutex_unlock(&dev->mt76.mutex);
 
 	return err;
 }
@@ -1150,19 +1165,14 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 }
 
 static void
-mt7996_mac_sta_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
+mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		      struct ieee80211_sta *sta)
 {
-	struct mt76_dev *mdev = mphy->dev;
-	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
 	unsigned long links = sta->valid_links ? sta->valid_links : BIT(0);
 
-	mutex_lock(&mdev->mutex);
-
-	mt7996_mac_sta_remove_links(dev, sta, links);
-	mphy->num_sta--;
-
-	mutex_unlock(&mdev->mutex);
+	mutex_lock(&dev->mt76.mutex);
+	mt7996_mac_sta_remove_links(dev, vif, sta, links);
+	mutex_unlock(&dev->mt76.mutex);
 }
 
 static int
@@ -1170,20 +1180,16 @@ mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		 struct ieee80211_sta *sta, enum ieee80211_sta_state old_state,
 		 enum ieee80211_sta_state new_state)
 {
-	struct mt76_phy *mphy = mt76_vif_phy(hw, vif);
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	enum mt76_sta_event ev;
 
-	if (!mphy)
-		return -EINVAL;
-
 	if (old_state == IEEE80211_STA_NOTEXIST &&
 	    new_state == IEEE80211_STA_NONE)
-		return mt7996_mac_sta_add(mphy, vif, sta);
+		return mt7996_mac_sta_add(dev, vif, sta);
 
 	if (old_state == IEEE80211_STA_NONE &&
 	    new_state == IEEE80211_STA_NOTEXIST)
-		mt7996_mac_sta_remove(mphy, vif, sta);
+		mt7996_mac_sta_remove(dev, vif, sta);
 
 	if (old_state == IEEE80211_STA_AUTH &&
 	    new_state == IEEE80211_STA_ASSOC)

-- 
2.50.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2025-07-04 14:36 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-04 13:08 [PATCH mt76 0/9] wifi: mt76: mt7996: Various MLO fixes Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 1/9] wifi: mt76: fix vif link allocation Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 2/9] wifi: mt76: mt7996: Fix secondary link lookup in mt7996_mcu_sta_mld_setup_tlv() Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 3/9] wifi: mt76: mt7996: Rely on for_each_sta_active_link() " Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 4/9] wifi: mt76: mt7996: Do not set wcid.sta to 1 in mt7996_mac_sta_event() Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 5/9] wifi: mt76: mt7996: Fix mlink lookup in mt7996_tx_prepare_skb Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 6/9] wifi: mt76: mt7996: Fix possible OOB access in mt7996_tx() Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 7/9] wifi: mt76: mt7996: Fix valid_links bitmask in mt7996_mac_sta_{add,remove} Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 8/9] wifi: mt76: mt7996: Add MLO support to mt7996_tx_check_aggr() Lorenzo Bianconi
2025-07-04 13:08 ` [PATCH mt76 9/9] wifi: mt76: mt7996: Move num_sta accounting in mt7996_mac_sta_{add,remove}_links 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).