linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO
@ 2025-03-12 11:13 Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 01/21] wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl to MLO Lorenzo Bianconi
                   ` (20 more replies)
  0 siblings, 21 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

This series is the second preliminary work needed to support MLO in
MT7996 driver.

---
Lorenzo Bianconi (9):
      wifi: mt76: mt7996: Add mt7996_sta_link to mt7996_mcu_add_bss_info signature
      wifi: mt76: mt7996: rework mt7996_sta_hw_queue_read to support MLO
      wifi: mt76: mt7996: rework mt7996_mac_sta_rc_work to support MLO
      wifi: mt76: mt7996: rework mt7996_mac_sta_poll to support MLO
      wifi: mt76: mt7996: rework mt7996_update_mu_group to support MLO
      wifi: mt76: mt7996: rework mt7996_net_fill_forward_path to support MLO
      wifi: mt76: mt7996: set vif default link_id adding/removing vif links
      wifi: mt76: mt7996: rework mt7996_ampdu_action to support MLO
      wifi: mt76: mt7996: Update mt7996_tx to MLO support

Shayne Chen (12):
      wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl to MLO
      wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()
      wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta rouine
      wifi: mt76: mt7996: rework mt7996_mac_write_txwi() for MLO support
      wifi: mt76: mt7996: Rely on wcid_to_sta in mt7996_mac_add_txs_skb()
      wifi: mt76: mt7996: rework mt7996_rx_get_wcid to support MLO
      wifi: mt76: mt7996: rework mt7996_sta_set_4addr and mt7996_sta_set_decap_offload to support MLO
      wifi: mt76: mt7996: rework mt7996_set_hw_key to support MLO
      wifi: mt76: mt7996: remove mt7996_mac_enable_rtscts()
      wifi: mt76: mt7996: rework mt7996_mcu_add_obss_spr to support MLO
      wifi: mt76: mt7996: rework mt7996_mcu_beacon_inband_discov to support MLO
      wifi: mt76: mt7996: rework set/get_tsf callabcks to support MLO

 .../net/wireless/mediatek/mt76/mt7996/debugfs.c    |  54 ++-
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    | 163 +++++--
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 493 ++++++++++++++-------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 321 +++++++++-----
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.h    |  32 ++
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  43 +-
 6 files changed, 754 insertions(+), 352 deletions(-)
---
base-commit: 61cf5540d86945a531dd939e90e72a4b134d7cb8
change-id: 20250312-b4-mt7996-mlo-p2-dd8efe4b6964

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


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

* [PATCH 01/21] wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl to MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 02/21] wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv() Lorenzo Bianconi
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

Update mt7996_mcu_add_rate_ctrl routine and all the called subroutines
to support MLO.
This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    |   9 +-
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |   4 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 144 +++++++++++----------
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  15 ++-
 4 files changed, 96 insertions(+), 76 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 7ddd4b0cadf5d1983379a93ba56da461748ca60e..48ba975f069c5062f450326a359ff3442ac96f30 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2294,10 +2294,15 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
 		if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
 			       IEEE80211_RC_NSS_CHANGED |
 			       IEEE80211_RC_BW_CHANGED))
-			mt7996_mcu_add_rate_ctrl(dev, vif, sta, true);
+			mt7996_mcu_add_rate_ctrl(dev, vif, &vif->bss_conf,
+						 &sta->deflink,
+						 &msta->vif->deflink,
+						 msta_link, true);
 
 		if (changed & IEEE80211_RC_SMPS_CHANGED)
-			mt7996_mcu_set_fixed_field(dev, vif, sta, NULL,
+			mt7996_mcu_set_fixed_field(dev, &sta->deflink,
+						   &msta->vif->deflink,
+						   msta_link, NULL,
 						   RATE_PARAM_MMPS_UPDATE);
 
 		spin_lock_bh(&dev->mt76.sta_poll_lock);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 11ad95e05b94857c95375cdf877518e7ee89f08e..25dbf086c8ef02307ef2510b21853b1eee28f922 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1046,7 +1046,9 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 			if (err)
 				return err;
 
-			err = mt7996_mcu_add_rate_ctrl(dev, vif, sta, false);
+			err = mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
+						       link_sta, link,
+						       msta_link, false);
 			if (err)
 				return err;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index e6ebb309a8257637c122702df2f2924649b7fabe..0cc822a8a6799a4552fa537cab2f13d6537bb1a8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -167,11 +167,11 @@ mt7996_mcu_set_sta_he_mcs(struct ieee80211_link_sta *link_sta,
 }
 
 static void
-mt7996_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
-			   const u16 *mask)
+mt7996_mcu_set_sta_vht_mcs(struct ieee80211_link_sta *link_sta,
+			   __le16 *vht_mcs, const u16 *mask)
 {
-	u16 mcs, mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
-	int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;
+	u16 mcs, mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map);
+	int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss;
 
 	for (nss = 0; nss < max_nss; nss++, mcs_map >>= 2) {
 		switch (mcs_map & 0x3) {
@@ -193,13 +193,13 @@ mt7996_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
 }
 
 static void
-mt7996_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,
-			  const u8 *mask)
+mt7996_mcu_set_sta_ht_mcs(struct ieee80211_link_sta *link_sta,
+			  u8 *ht_mcs, const u8 *mask)
 {
-	int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;
+	int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss;
 
 	for (nss = 0; nss < max_nss; nss++)
-		ht_mcs[nss] = sta->deflink.ht_cap.mcs.rx_mask[nss] & mask[nss];
+		ht_mcs[nss] = link_sta->ht_cap.mcs.rx_mask[nss] & mask[nss];
 }
 
 static int
@@ -1888,18 +1888,18 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
 				     MCU_WM_UNI_CMD(RA), true);
 }
 
-int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta, void *data, u32 field)
+int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
+			       struct ieee80211_link_sta *link_sta,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link,
+			       void *data, u32 field)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct sta_phy_uni *phy = data;
 	struct sta_rec_ra_fixed_uni *ra;
 	struct sk_buff *skb;
 	struct tlv *tlv;
 
-	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
 					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
@@ -1919,7 +1919,7 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif
 			ra->phy = *phy;
 		break;
 	case RATE_PARAM_MMPS_UPDATE:
-		ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode);
+		ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode);
 		break;
 	default:
 		break;
@@ -1931,12 +1931,13 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif
 }
 
 static int
-mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta)
+mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
+			       struct ieee80211_link_sta *link_sta,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct cfg80211_chan_def *chandef = &mvif->deflink.phy->mt76->chandef;
-	struct cfg80211_bitrate_mask *mask = &mvif->deflink.bitrate_mask;
+	struct cfg80211_chan_def *chandef = &link->phy->mt76->chandef;
+	struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
 	enum nl80211_band band = chandef->chan->band;
 	struct sta_phy_uni phy = {};
 	int ret, nrates = 0;
@@ -1957,11 +1958,11 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 		}								\
 	} while (0)
 
-	if (sta->deflink.he_cap.has_he) {
+	if (link_sta->he_cap.has_he) {
 		__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
-	} else if (sta->deflink.vht_cap.vht_supported) {
+	} else if (link_sta->vht_cap.vht_supported) {
 		__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
-	} else if (sta->deflink.ht_cap.ht_supported) {
+	} else if (link_sta->ht_cap.ht_supported) {
 		__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
 	} else {
 		nrates = hweight32(mask->control[band].legacy);
@@ -1978,7 +1979,8 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 
 	/* fixed single rate */
 	if (nrates == 1) {
-		ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+		ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
+						 msta_link, &phy,
 						 RATE_PARAM_FIXED_MCS);
 		if (ret)
 			return ret;
@@ -1987,7 +1989,6 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 	/* fixed GI */
 	if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
 	    mask->control[band].he_gi != GENMASK(7, 0)) {
-		struct mt7996_sta_link *msta_link = (void *)sta->drv_priv;
 		u32 addr;
 
 		/* firmware updates only TXCMD but doesn't take WTBL into
@@ -1995,12 +1996,13 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 		 * actual txrate hardware sends out.
 		 */
 		addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 7);
-		if (sta->deflink.he_cap.has_he)
+		if (link_sta->he_cap.has_he)
 			mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
 		else
 			mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
 
-		ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+		ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
+						 msta_link, &phy,
 						 RATE_PARAM_FIXED_GI);
 		if (ret)
 			return ret;
@@ -2008,7 +2010,8 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 
 	/* fixed HE_LTF */
 	if (mask->control[band].he_ltf != GENMASK(7, 0)) {
-		ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+		ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
+						 msta_link, &phy,
 						 RATE_PARAM_FIXED_HE_LTF);
 		if (ret)
 			return ret;
@@ -2019,30 +2022,32 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
 
 static void
 mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
-			     struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_bss_conf *link_conf,
+			     struct ieee80211_link_sta *link_sta,
+			     struct mt7996_vif_link *link)
 {
 #define INIT_RCPI 180
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt76_phy *mphy = mvif->deflink.phy->mt76;
+	struct mt76_phy *mphy = link->phy->mt76;
 	struct cfg80211_chan_def *chandef = &mphy->chandef;
-	struct cfg80211_bitrate_mask *mask = &mvif->deflink.bitrate_mask;
+	struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
+	u32 cap = link_sta->sta->wme ? STA_CAP_WMM : 0;
 	enum nl80211_band band = chandef->chan->band;
 	struct sta_rec_ra_uni *ra;
 	struct tlv *tlv;
-	u32 supp_rate = sta->deflink.supp_rates[band];
-	u32 cap = sta->wme ? STA_CAP_WMM : 0;
+	u32 supp_rate = link_sta->supp_rates[band];
 
 	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
 	ra = (struct sta_rec_ra_uni *)tlv;
 
 	ra->valid = true;
 	ra->auto_rate = true;
-	ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, &sta->deflink);
+	ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, link_sta);
 	ra->channel = chandef->chan->hw_value;
-	ra->bw = (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) ?
-		 CMD_CBW_320MHZ : sta->deflink.bandwidth;
+	ra->bw = (link_sta->bandwidth == IEEE80211_STA_RX_BW_320) ?
+		 CMD_CBW_320MHZ : link_sta->bandwidth;
 	ra->phy.bw = ra->bw;
-	ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode);
+	ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode);
 
 	if (supp_rate) {
 		supp_rate &= mask->control[band].legacy;
@@ -2062,60 +2067,60 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
 		}
 	}
 
-	if (sta->deflink.ht_cap.ht_supported) {
+	if (link_sta->ht_cap.ht_supported) {
 		ra->supp_mode |= MODE_HT;
-		ra->af = sta->deflink.ht_cap.ampdu_factor;
-		ra->ht_gf = !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
+		ra->af = link_sta->ht_cap.ampdu_factor;
+		ra->ht_gf = !!(link_sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
 
 		cap |= STA_CAP_HT;
-		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
+		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
 			cap |= STA_CAP_SGI_20;
-		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
+		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
 			cap |= STA_CAP_SGI_40;
-		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)
+		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)
 			cap |= STA_CAP_TX_STBC;
-		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
+		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
 			cap |= STA_CAP_RX_STBC;
-		if (vif->bss_conf.ht_ldpc &&
-		    (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
+		if (link_conf->ht_ldpc &&
+		    (link_sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
 			cap |= STA_CAP_LDPC;
 
-		mt7996_mcu_set_sta_ht_mcs(sta, ra->ht_mcs,
+		mt7996_mcu_set_sta_ht_mcs(link_sta, ra->ht_mcs,
 					  mask->control[band].ht_mcs);
 		ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
 	}
 
-	if (sta->deflink.vht_cap.vht_supported) {
+	if (link_sta->vht_cap.vht_supported) {
 		u8 af;
 
 		ra->supp_mode |= MODE_VHT;
 		af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
-			       sta->deflink.vht_cap.cap);
+			       link_sta->vht_cap.cap);
 		ra->af = max_t(u8, ra->af, af);
 
 		cap |= STA_CAP_VHT;
-		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)
+		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)
 			cap |= STA_CAP_VHT_SGI_80;
-		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160)
+		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160)
 			cap |= STA_CAP_VHT_SGI_160;
-		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
+		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
 			cap |= STA_CAP_VHT_TX_STBC;
-		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
+		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
 			cap |= STA_CAP_VHT_RX_STBC;
-		if ((vif->type != NL80211_IFTYPE_AP || vif->bss_conf.vht_ldpc) &&
-		    (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
+		if ((vif->type != NL80211_IFTYPE_AP || link_conf->vht_ldpc) &&
+		    (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
 			cap |= STA_CAP_VHT_LDPC;
 
-		mt7996_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs,
+		mt7996_mcu_set_sta_vht_mcs(link_sta, ra->supp_vht_mcs,
 					   mask->control[band].vht_mcs);
 	}
 
-	if (sta->deflink.he_cap.has_he) {
+	if (link_sta->he_cap.has_he) {
 		ra->supp_mode |= MODE_HE;
 		cap |= STA_CAP_HE;
 
-		if (sta->deflink.he_6ghz_capa.capa)
-			ra->af = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
+		if (link_sta->he_6ghz_capa.capa)
+			ra->af = le16_get_bits(link_sta->he_6ghz_capa.capa,
 					       IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
 	}
 	ra->sta_cap = cpu_to_le32(cap);
@@ -2123,16 +2128,17 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
 	memset(ra->rx_rcpi, INIT_RCPI, sizeof(ra->rx_rcpi));
 }
 
-int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			     struct ieee80211_sta *sta, bool changed)
+int mt7996_mcu_add_rate_ctrl(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 mt7996_sta_link *msta_link, bool changed)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
 	struct sk_buff *skb;
 	int ret;
 
-	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
 					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
@@ -2143,19 +2149,19 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	 * update sta_rec_he here.
 	 */
 	if (changed)
-		mt7996_mcu_sta_he_tlv(skb, &sta->deflink, &mvif->deflink);
+		mt7996_mcu_sta_he_tlv(skb, link_sta, link);
 
 	/* sta_rec_ra accommodates BW, NSS and only MCS range format
 	 * i.e 0-{7,8,9} for VHT.
 	 */
-	mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
+	mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, link_conf, link_sta, link);
 
 	ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
 				    MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
 	if (ret)
 		return ret;
 
-	return mt7996_mcu_add_rate_ctrl_fixed(dev, vif, sta);
+	return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link);
 }
 
 static int
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 84b9ff707d56501d212932a9fa6a3037259a1077..a91a50b72218c6a2d0dd32968681325ea7e6a042 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -593,16 +593,23 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
 				    struct ieee80211_vif *vif, u32 changed);
 int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct ieee80211_he_obss_pd *he_obss_pd);
-int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			     struct ieee80211_sta *sta, bool changed);
+int mt7996_mcu_add_rate_ctrl(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 mt7996_sta_link *msta_link, bool changed);
 int mt7996_set_channel(struct mt76_phy *mphy);
 int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
 int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		      struct ieee80211_bss_conf *link_conf);
 int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
 				   void *data, u16 version);
-int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta, void *data, u32 field);
+int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
+			       struct ieee80211_link_sta *link_sta,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link,
+			       void *data, u32 field);
 int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
 int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
 int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);

-- 
2.48.1


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

* [PATCH 02/21] wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 01/21] wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl to MLO Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-18  8:51   ` Shayne Chen (陳軒丞)
  2025-03-12 11:13 ` [PATCH 03/21] wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta rouine Lorenzo Bianconi
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

mt7996_mcu_sta_mld_setup_tlv is needed to push MLO configuration to the
MCU. This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 79 +++++++++++++++++++++++++
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 32 ++++++++++
 2 files changed, 111 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 0cc822a8a6799a4552fa537cab2f13d6537bb1a8..ac01eb880e2a6f6ef3a81591bcacd2b90c48986a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2197,6 +2197,80 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 				 sizeof(req), true);
 }
 
+static void
+mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+			     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);
+	struct mld_setup_link *mld_setup_link;
+	struct sta_rec_mld_setup *mld_setup;
+	struct mt7996_sta_link *msta_link;
+	struct ieee80211_vif *vif;
+	unsigned int link_id;
+	struct tlv *tlv;
+
+	msta_link = mt76_dereference(msta->link[msta->deflink_id], &dev->mt76);
+	if (!msta_link)
+		return;
+
+	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD,
+				      sizeof(struct sta_rec_mld_setup) +
+				      sizeof(struct mld_setup_link) * nlinks);
+
+	mld_setup = (struct sta_rec_mld_setup *)tlv;
+	memcpy(mld_setup->mld_addr, sta->addr, ETH_ALEN);
+	mld_setup->setup_wcid = cpu_to_le16(msta_link->wcid.idx);
+	mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx);
+
+	if (nlinks > 1) {
+		link_id = __ffs(links & ~BIT(msta->deflink_id));
+		msta_link = mt76_dereference(msta->link[msta->deflink_id],
+					     &dev->mt76);
+		if (!msta_link)
+			return;
+	}
+	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) {
+		struct mt7996_vif_link *link;
+
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
+
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		if (!msta_link)
+			continue;
+
+		mld_setup_link->wcid = cpu_to_le16(msta_link->wcid.idx);
+		mld_setup_link->bss_idx = link->mt76.idx;
+		mld_setup_link++;
+	}
+}
+
+static void
+mt7996_mcu_sta_eht_mld_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+			   struct ieee80211_sta *sta)
+{
+	struct sta_rec_eht_mld *eht_mld;
+	struct tlv *tlv;
+	int i;
+
+	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld));
+	eht_mld = (struct sta_rec_eht_mld *)tlv;
+
+	for (i = 0; i < ARRAY_SIZE(eht_mld->str_cap); i++)
+		eht_mld->str_cap[i] = 0x7;
+}
+
 int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		       struct ieee80211_bss_conf *link_conf,
 		       struct ieee80211_link_sta *link_sta,
@@ -2255,6 +2329,11 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		mt7996_mcu_sta_eht_tlv(skb, link_sta);
 		/* starec muru */
 		mt7996_mcu_sta_muru_tlv(dev, skb, link_conf, link_sta);
+
+		if (sta->mlo && conn_state != CONN_STATE_DISCONNECT) {
+			mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
+			mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
+		}
 	}
 
 	ret = mt7996_mcu_add_group(dev, link_conf->vif, sta);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
index 5fdc47dad28c66a46c12a1fcede9ef10c7e6d44e..2ab6a53bee869a69d2ee7c0f342e379450c3d6dc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
@@ -625,6 +625,35 @@ struct sta_rec_hdr_trans {
 	u8 mesh;
 } __packed;
 
+struct sta_rec_mld_setup {
+	__le16 tag;
+	__le16 len;
+	u8 mld_addr[ETH_ALEN];
+	__le16 primary_id;
+	__le16 seconed_id;
+	__le16 setup_wcid;
+	u8 link_num;
+	u8 info;
+	u8 __rsv[2];
+	u8 link_info[];
+} __packed;
+
+struct sta_rec_eht_mld {
+	__le16 tag;
+	__le16 len;
+	u8 nsep;
+	u8 __rsv1[2];
+	u8 str_cap[__MT_MAX_BAND];
+	__le16 eml_cap;
+	u8 __rsv2[4];
+} __packed;
+
+struct mld_setup_link {
+	__le16 wcid;
+	u8 bss_idx;
+	u8 __rsv;
+} __packed;
+
 struct hdr_trans_en {
 	__le16 tag;
 	__le16 len;
@@ -798,6 +827,9 @@ enum {
 					 sizeof(struct sta_rec_eht) +		\
 					 sizeof(struct sta_rec_hdrt) +		\
 					 sizeof(struct sta_rec_hdr_trans) +	\
+					 sizeof(struct sta_rec_mld_setup) +	\
+					 sizeof(struct mld_setup_link) * 3 +	\
+					 sizeof(struct sta_rec_eht_mld) +	\
 					 sizeof(struct tlv))
 
 #define MT7996_MAX_BEACON_SIZE		1338

-- 
2.48.1


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

* [PATCH 03/21] wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta rouine
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 01/21] wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl to MLO Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 02/21] wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv() Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 04/21] wifi: mt76: mt7996: rework mt7996_mac_write_txwi() for MLO support Lorenzo Bianconi
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

mt7996_mcu_teardown_mld_sta is used to remove MLO configuration from the
MCU. This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 12 +++++++++---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 18 ++++++++++++++++++
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 +++
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 25dbf086c8ef02307ef2510b21853b1eee28f922..642d633b5126ce81f3d32a9bd912603e2c328c8a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1017,6 +1017,7 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 		     struct ieee80211_sta *sta, enum mt76_sta_event ev)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+	unsigned long links = sta->valid_links;
 	struct ieee80211_link_sta *link_sta;
 	unsigned int link_id;
 
@@ -1067,11 +1068,16 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 				mt7996_mac_twt_teardown_flow(dev, link,
 							     msta_link, i);
 
-			mt7996_mcu_add_sta(dev, link_conf, link_sta, link,
-					   msta_link, CONN_STATE_DISCONNECT,
-					   false);
+			if (sta->mlo && links == BIT(link_id)) /* last link */
+				mt7996_mcu_teardown_mld_sta(dev, link,
+							    msta_link);
+			else
+				mt7996_mcu_add_sta(dev, link_conf, link_sta,
+						   link, msta_link,
+						   CONN_STATE_DISCONNECT, false);
 			msta_link->wcid.sta_disabled = 1;
 			msta_link->wcid.sta = 0;
+			links = links & ~BIT(link_id);
 			break;
 		}
 	}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index ac01eb880e2a6f6ef3a81591bcacd2b90c48986a..46c5e639b9630199ffa601e545fa76690f0101e3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2346,6 +2346,24 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
 }
 
+int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
+				struct mt7996_vif_link *link,
+				struct mt7996_sta_link *msta_link)
+{
+	struct sk_buff *skb;
+
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
+					      &msta_link->wcid,
+					      MT7996_STA_UPDATE_MAX_SIZE);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+	mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF, sizeof(struct tlv));
+
+	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+}
+
 static int
 mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
 		       struct sk_buff *skb,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index a91a50b72218c6a2d0dd32968681325ea7e6a042..c2a2916e0647cfdcbee9912e3915241465e32cac 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -578,6 +578,9 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		       struct mt7996_vif_link *link,
 		       struct mt7996_sta_link *msta_link,
 		       int conn_state, bool newly);
+int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
+				struct mt7996_vif_link *link,
+				struct mt7996_sta_link *msta_link);
 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
 			 bool add);

-- 
2.48.1


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

* [PATCH 04/21] wifi: mt76: mt7996: rework mt7996_mac_write_txwi() for MLO support
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (2 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 03/21] wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta rouine Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 05/21] wifi: mt76: mt7996: Rely on wcid_to_sta in mt7996_mac_add_txs_skb() Lorenzo Bianconi
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

Update mt7996_mac_write_txwi routine and all the called subroutines to
support MLO.
This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 55 ++++++++++++++++++-------
 1 file changed, 41 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 48ba975f069c5062f450326a359ff3442ac96f30..eed692cd64a6acedb2f6d9aaf6f459bf4a4f5b08 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -730,9 +730,8 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
 	u32 val;
 
 	if (wcid->sta) {
-		struct ieee80211_sta *sta;
+		struct ieee80211_sta *sta = wcid_to_sta(wcid);
 
-		sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
 		wmm = sta->wme;
 	}
 
@@ -759,7 +758,9 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
 
 static void
 mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
-			    struct sk_buff *skb, struct ieee80211_key_conf *key)
+			    struct sk_buff *skb,
+			    struct ieee80211_key_conf *key,
+			    struct mt76_wcid *wcid)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
@@ -767,6 +768,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
 	bool multicast = is_multicast_ether_addr(hdr->addr1);
 	u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
 	__le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
+	u16 seqno = le16_to_cpu(sc);
 	u8 fc_type, fc_stype;
 	u32 val;
 
@@ -816,9 +818,13 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
 		txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
 	}
 
-	if (info->flags & IEEE80211_TX_CTL_INJECTED) {
-		u16 seqno = le16_to_cpu(sc);
+	if (multicast && ieee80211_vif_is_mld(info->control.vif)) {
+		val = MT_TXD3_SN_VALID |
+		      FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
+		txwi[3] |= cpu_to_le32(val);
+	}
 
+	if (info->flags & IEEE80211_TX_CTL_INJECTED) {
 		if (ieee80211_is_back_req(hdr->frame_control)) {
 			struct ieee80211_bar *bar;
 
@@ -831,6 +837,19 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
 		txwi[3] |= cpu_to_le32(val);
 		txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
 	}
+
+	if (ieee80211_vif_is_mld(info->control.vif) &&
+	    (multicast || unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))))
+		txwi[5] |= cpu_to_le32(MT_TXD5_FL);
+
+	if (ieee80211_is_nullfunc(fc) && ieee80211_has_a4(fc) &&
+	    ieee80211_vif_is_mld(info->control.vif)) {
+		txwi[5] |= cpu_to_le32(MT_TXD5_FL);
+		txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
+	}
+
+	if (!wcid->sta && ieee80211_is_mgmt(fc))
+		txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
 }
 
 void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
@@ -846,6 +865,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
 	struct mt76_vif_link *mlink = NULL;
 	struct mt7996_vif *mvif;
+	unsigned int link_id;
 	u16 tx_count = 15;
 	u32 val;
 	bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
@@ -853,13 +873,15 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 	bool beacon = !!(changed & (BSS_CHANGED_BEACON |
 				    BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
 
-	if (vif) {
-		mvif = (struct mt7996_vif *)vif->drv_priv;
-		if (wcid->offchannel)
-			mlink = rcu_dereference(mvif->mt76.offchannel_link);
-		if (!mlink)
-			mlink = &mvif->deflink.mt76;
-	}
+	if (wcid != &dev->mt76.global_wcid)
+		link_id = wcid->link_id;
+	else
+		link_id = u32_get_bits(info->control.flags,
+				       IEEE80211_TX_CTRL_MLO_LINK);
+
+	mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
+	if (mvif)
+		mlink = rcu_dereference(mvif->mt76.link[link_id]);
 
 	if (mlink) {
 		omac_idx = mlink->omac_idx;
@@ -911,7 +933,10 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 		val |= MT_TXD5_TX_STATUS_HOST;
 	txwi[5] = cpu_to_le32(val);
 
-	val = MT_TXD6_DIS_MAT | MT_TXD6_DAS;
+	val = MT_TXD6_DAS;
+	if (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
+		val |= MT_TXD6_DIS_MAT;
+
 	if (is_mt7996(&dev->mt76))
 		val |= FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
 	else if (is_8023 || !ieee80211_is_mgmt(hdr->frame_control))
@@ -923,7 +948,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 	if (is_8023)
 		mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid);
 	else
-		mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
+		mt7996_mac_write_txwi_80211(dev, txwi, skb, key, wcid);
 
 	if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
 		bool mcast = ieee80211_is_data(hdr->frame_control) &&
@@ -940,6 +965,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 		}
 
 		val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW;
+		if (mcast)
+			val |= MT_TXD6_DIS_MAT;
 		txwi[6] |= cpu_to_le32(val);
 		txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
 	}

-- 
2.48.1


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

* [PATCH 05/21] wifi: mt76: mt7996: Rely on wcid_to_sta in mt7996_mac_add_txs_skb()
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (3 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 04/21] wifi: mt76: mt7996: rework mt7996_mac_write_txwi() for MLO support Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 06/21] wifi: mt76: mt7996: rework mt7996_rx_get_wcid to support MLO Lorenzo Bianconi
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-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 eed692cd64a6acedb2f6d9aaf6f459bf4a4f5b08..9f8436edc81377d852dd4e7221575c7e1255187c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1287,7 +1287,7 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
 		struct ieee80211_sta *sta;
 		u8 tid;
 
-		sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
+		sta = wcid_to_sta(wcid);
 		tid = FIELD_GET(MT_TXS0_TID, txs);
 		ieee80211_refresh_tx_agg_session_timer(sta, tid);
 	}

-- 
2.48.1


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

* [PATCH 06/21] wifi: mt76: mt7996: rework mt7996_rx_get_wcid to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (4 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 05/21] wifi: mt76: mt7996: Rely on wcid_to_sta in mt7996_mac_add_txs_skb() Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 07/21] wifi: mt76: mt7996: rework mt7996_sta_set_4addr and mt7996_sta_set_decap_offload " Lorenzo Bianconi
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

The wcid idx and band idx in the TXS are sometimes mismatched since the
FW will select a transmission link according to a private algorithm.
That is, the wcid idx in the TXS would be the one registered by the
driver rather than the actual wcid idx used during transmission.
However, the band idx in the TXS is the band select for transmission.
Therefore, we should get the driver-registered wcid in order
to notify the driver the packet has been acked; otherwise,
the driver will be unable to match the transmitted packet and its TXS.
This is a preliminary patch to enable MLO for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 33 +++++++++++++++++++------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 9f8436edc81377d852dd4e7221575c7e1255187c..b8d88fdee97a3567b57a20d0322859b7ae8ce88a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -53,29 +53,48 @@ static const struct mt7996_dfs_radar_spec jp_radar_specs = {
 };
 
 static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
-					    u16 idx, bool unicast)
+					    u16 idx, u8 band_idx)
 {
 	struct mt7996_sta_link *msta_link;
 	struct mt7996_sta *msta;
+	struct mt7996_vif *mvif;
 	struct mt76_wcid *wcid;
+	int i;
 
 	if (idx >= ARRAY_SIZE(dev->mt76.wcid))
 		return NULL;
 
 	wcid = rcu_dereference(dev->mt76.wcid[idx]);
-	if (unicast || !wcid)
-		return wcid;
+	if (!wcid)
+		return NULL;
 
-	if (!wcid->sta)
+	if (!mt7996_band_valid(dev, band_idx))
 		return NULL;
 
+	if (wcid->phy_idx == band_idx)
+		return wcid;
+
 	msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
 	msta = msta_link->sta;
-
 	if (!msta || !msta->vif)
 		return NULL;
 
-	return &msta->vif->deflink.msta_link.wcid;
+	mvif = msta->vif;
+	for (i = 0; i < ARRAY_SIZE(mvif->mt76.link); i++) {
+		struct mt76_vif_link *mlink;
+
+		mlink = rcu_dereference(mvif->mt76.link[i]);
+		if (!mlink)
+			continue;
+
+		if (mlink->band_idx != band_idx)
+			continue;
+
+		msta_link = rcu_dereference(msta->link[i]);
+		break;
+	}
+
+	return &msta_link->wcid;
 }
 
 bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
@@ -483,7 +502,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
 
 	unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
 	idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
-	status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
+	status->wcid = mt7996_rx_get_wcid(dev, idx, band_idx);
 
 	if (status->wcid) {
 		struct mt7996_sta_link *msta_link;

-- 
2.48.1


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

* [PATCH 07/21] wifi: mt76: mt7996: rework mt7996_sta_set_4addr and mt7996_sta_set_decap_offload to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (5 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 06/21] wifi: mt76: mt7996: rework mt7996_rx_get_wcid to support MLO Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 08/21] wifi: mt76: mt7996: Add mt7996_sta_link to mt7996_mcu_add_bss_info signature Lorenzo Bianconi
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

Rework mt7996_sta_set_4addr and mt7996_sta_set_decap_offload routines in
order to properly support multi-link. This is a preliminary patch to enable
MLO for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 74 ++++++++++++++++------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 11 +---
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 +-
 3 files changed, 61 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 642d633b5126ce81f3d32a9bd912603e2c328c8a..f7703e00712cd1a59484ceddfad5bd00b8814250 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1540,19 +1540,37 @@ static void mt7996_sta_set_4addr(struct ieee80211_hw *hw,
 				 struct ieee80211_sta *sta,
 				 bool enabled)
 {
-	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+	struct ieee80211_link_sta *link_sta;
+	unsigned int link_id;
 
-	if (enabled)
-		set_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
-	else
-		clear_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
+	mutex_lock(&dev->mt76.mutex);
 
-	if (!msta_link->wcid.sta)
-		return;
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
 
-	mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta);
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
+
+		if (enabled)
+			set_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
+		else
+			clear_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
+
+		if (!msta_link->wcid.sta)
+			continue;
+
+		mt7996_mcu_wtbl_update_hdr_trans(dev, vif, link, msta_link);
+	}
+
+	mutex_unlock(&dev->mt76.mutex);
 }
 
 static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
@@ -1560,19 +1578,39 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
 					 struct ieee80211_sta *sta,
 					 bool enabled)
 {
-	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+	struct ieee80211_link_sta *link_sta;
+	unsigned int link_id;
 
-	if (enabled)
-		set_bit(MT_WCID_FLAG_HDR_TRANS, &msta_link->wcid.flags);
-	else
-		clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta_link->wcid.flags);
+	mutex_lock(&dev->mt76.mutex);
 
-	if (!msta_link->wcid.sta)
-		return;
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
 
-	mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta);
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
+
+		if (enabled)
+			set_bit(MT_WCID_FLAG_HDR_TRANS,
+				&msta_link->wcid.flags);
+		else
+			clear_bit(MT_WCID_FLAG_HDR_TRANS,
+				  &msta_link->wcid.flags);
+
+		if (!msta_link->wcid.sta)
+			continue;
+
+		mt7996_mcu_wtbl_update_hdr_trans(dev, vif, link, msta_link);
+	}
+
+	mutex_unlock(&dev->mt76.mutex);
 }
 
 static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 46c5e639b9630199ffa601e545fa76690f0101e3..7c097aaead328bd234d87e535497c2f788ffa4c3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -4465,17 +4465,12 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
 
 int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
 				     struct ieee80211_vif *vif,
-				     struct ieee80211_sta *sta)
+				     struct mt7996_vif_link *link,
+				     struct mt7996_sta_link *msta_link)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link;
-	struct mt7996_sta *msta;
 	struct sk_buff *skb;
 
-	msta = sta ? (struct mt7996_sta *)sta->drv_priv : NULL;
-	msta_link = msta ? &msta->deflink : &mvif->deflink.msta_link;
-
-	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+	skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
 					      &msta_link->wcid,
 					      MT7996_STA_UPDATE_MAX_SIZE);
 	if (IS_ERR(skb))
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index c2a2916e0647cfdcbee9912e3915241465e32cac..f226090bcd02ea478113e4bccea0492cfa34477d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -749,7 +749,8 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif
 			       struct ieee80211_key_conf *key);
 int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
 				     struct ieee80211_vif *vif,
-				     struct ieee80211_sta *sta);
+				     struct mt7996_vif_link *link,
+				     struct mt7996_sta_link *msta_link);
 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,

-- 
2.48.1


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

* [PATCH 08/21] wifi: mt76: mt7996: Add mt7996_sta_link to mt7996_mcu_add_bss_info signature
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (6 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 07/21] wifi: mt76: mt7996: rework mt7996_sta_set_4addr and mt7996_sta_set_decap_offload " Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 09/21] wifi: mt76: mt7996: rework mt7996_set_hw_key to support MLO Lorenzo Bianconi
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

This is a preliminary patch to introduce MLO support for MT996 driver.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 13 ++++++++-----
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    |  5 +++--
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 ++-
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index f7703e00712cd1a59484ceddfad5bd00b8814250..4abbe761b732f1ea7791ba1f86c2c87db1eea91d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -195,7 +195,8 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
 	if (cmd == SET_KEY && !sta && !mlink->mt76.cipher) {
 		mlink->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);
-		mt7996_mcu_add_bss_info(phy, vif, &vif->bss_conf, &mlink->mt76, true);
+		mt7996_mcu_add_bss_info(phy, vif, &vif->bss_conf, &mlink->mt76,
+					&mlink->msta_link, true);
 	}
 
 	if (cmd == SET_KEY) {
@@ -288,7 +289,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	mt7996_init_bitrate_mask(vif, link);
 
-	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, true);
+	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, true);
 	/* defer the first STA_REC of BMC entry to BSS_CHANGED_BSSID for STA
 	 * interface, since firmware only records BSSID when the entry is new
 	 */
@@ -314,7 +315,7 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
 			   CONN_STATE_DISCONNECT, false);
-	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, false);
+	mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, false);
 
 	mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false);
 
@@ -704,7 +705,8 @@ mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 				continue;
 
 			mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
-						&link->mt76, true);
+						&link->mt76, &link->msta_link,
+						true);
 			mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
 					   CONN_STATE_PORT_SECURE,
 					   !!(changed & BSS_CHANGED_BSSID));
@@ -740,7 +742,8 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	 */
 	if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
 	    (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
-		mt7996_mcu_add_bss_info(phy, vif, info, &link->mt76, true);
+		mt7996_mcu_add_bss_info(phy, vif, info, &link->mt76,
+					&link->msta_link, true);
 		mt7996_mcu_add_sta(dev, info, NULL, link, NULL,
 				   CONN_STATE_PORT_SECURE,
 				   !!(changed & BSS_CHANGED_BSSID));
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 7c097aaead328bd234d87e535497c2f788ffa4c3..d1a0dd4698fbe5cf248796ed6f13b99f3c191af1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1064,7 +1064,8 @@ __mt7996_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, int
 
 int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct ieee80211_bss_conf *link_conf,
-			    struct mt76_vif_link *mlink, int enable)
+			    struct mt76_vif_link *mlink,
+			    struct mt7996_sta_link *msta_link, int enable)
 {
 	struct mt7996_dev *dev = phy->dev;
 	struct sk_buff *skb;
@@ -1081,7 +1082,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 
 	/* bss_basic must be first */
 	mt7996_mcu_bss_basic_tlv(skb, vif, link_conf, mlink, phy->mt76,
-				 mlink->wcid->idx, enable);
+				 msta_link->wcid.idx, enable);
 	mt7996_mcu_bss_sec_tlv(skb, mlink);
 
 	if (vif->type == NL80211_IFTYPE_MONITOR)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index f226090bcd02ea478113e4bccea0492cfa34477d..4d5ab3f4b78ee6fc584370372fe34b44292e4594 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -571,7 +571,8 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct mt76_vif_link *mlink, bool enable);
 int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 			    struct ieee80211_bss_conf *link_conf,
-			    struct mt76_vif_link *mlink, int enable);
+			    struct mt76_vif_link *mlink,
+			    struct mt7996_sta_link *msta_link, int enable);
 int mt7996_mcu_add_sta(struct mt7996_dev *dev,
 		       struct ieee80211_bss_conf *link_conf,
 		       struct ieee80211_link_sta *link_sta,

-- 
2.48.1


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

* [PATCH 09/21] wifi: mt76: mt7996: rework mt7996_set_hw_key to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (7 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 08/21] wifi: mt76: mt7996: Add mt7996_sta_link to mt7996_mcu_add_bss_info signature Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 10/21] wifi: mt76: mt7996: rework mt7996_sta_hw_queue_read " Lorenzo Bianconi
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

Modify mt7996_set_hw_key routine to work in a multi-link setup.
This is a preliminary patch to enable MLO for MT7996 driver

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 138 +++++++++++++--------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    |  18 +--
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |   4 +-
 3 files changed, 99 insertions(+), 61 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 4abbe761b732f1ea7791ba1f86c2c87db1eea91d..a845c3e758adcc4802f704a99ac39aa9ca670c88 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -158,62 +158,101 @@ mt7996_init_bitrate_mask(struct ieee80211_vif *vif, struct mt7996_vif_link *mlin
 static int
 mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-		  struct mt7996_vif_link *mlink, struct ieee80211_key_conf *key)
+		  struct ieee80211_key_conf *key)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt76_wcid *wcid = &mlink->msta_link.wcid;
-	struct mt7996_phy *phy;
 	int idx = key->keyidx;
-	u8 *wcid_keyidx;
+	unsigned int link_id;
+	unsigned long links;
+
+	if (key->link_id >= 0)
+		links = BIT(key->link_id);
+	else if (sta && sta->valid_links)
+		links = sta->valid_links;
+	else if (vif->valid_links)
+		links = vif->valid_links;
+	else
+		links = BIT(0);
 
-	phy = mt7996_vif_link_phy(mlink);
-	if (!phy)
-		return -EINVAL;
+	for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
+		u8 *wcid_keyidx;
+		int err;
 
-	if (sta) {
-		struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
 
-		wcid = &msta->deflink.wcid;
-		if (!wcid->sta)
-			return -EOPNOTSUPP;
-	}
-	wcid_keyidx = &wcid->hw_key_idx;
+		if (sta) {
+			struct mt7996_sta *msta;
 
-	switch (key->cipher) {
-	case WLAN_CIPHER_SUITE_AES_CMAC:
-	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
-	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-		if (key->keyidx == 6 || key->keyidx == 7) {
-			wcid_keyidx = &wcid->hw_key_idx2;
-			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
+			msta = (struct mt7996_sta *)sta->drv_priv;
+			msta_link = mt76_dereference(msta->link[link_id],
+						     &dev->mt76);
+			if (!msta_link)
+				continue;
+
+			if (!msta_link->wcid.sta)
+				return -EOPNOTSUPP;
+		} else {
+			msta_link = &link->msta_link;
+		}
+		wcid_keyidx = &msta_link->wcid.hw_key_idx;
+
+		switch (key->cipher) {
+		case WLAN_CIPHER_SUITE_AES_CMAC:
+		case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+		case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+		case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+			if (key->keyidx == 6 || key->keyidx == 7) {
+				wcid_keyidx = &msta_link->wcid.hw_key_idx2;
+				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
+			}
+			break;
+		default:
+			break;
 		}
-		break;
-	default:
-		break;
-	}
 
-	if (cmd == SET_KEY && !sta && !mlink->mt76.cipher) {
-		mlink->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);
-		mt7996_mcu_add_bss_info(phy, vif, &vif->bss_conf, &mlink->mt76,
-					&mlink->msta_link, true);
-	}
+		if (cmd == SET_KEY && !sta && !link->mt76.cipher) {
+			struct ieee80211_bss_conf *link_conf;
 
-	if (cmd == SET_KEY) {
-		*wcid_keyidx = idx;
-	} else {
-		if (idx == *wcid_keyidx)
-			*wcid_keyidx = -1;
-		return 0;
-	}
+			link_conf = link_conf_dereference_protected(vif,
+								    link_id);
+			if (!link_conf)
+				link_conf = &vif->bss_conf;
 
-	mt76_wcid_key_setup(&dev->mt76, wcid, key);
+			link->mt76.cipher =
+				mt76_connac_mcu_get_cipher(key->cipher);
+			mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
+						&link->mt76, msta_link, true);
+		}
 
-	if (key->keyidx == 6 || key->keyidx == 7)
-		return mt7996_mcu_bcn_prot_enable(dev, vif, key);
+		if (cmd == SET_KEY) {
+			*wcid_keyidx = idx;
+		} else {
+			if (idx == *wcid_keyidx)
+				*wcid_keyidx = -1;
+			continue;
+		}
 
-	return mt7996_mcu_add_key(&dev->mt76, vif, key,
-				  MCU_WMWA_UNI_CMD(STA_REC_UPDATE), wcid, cmd);
+		mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key);
+
+		if (key->keyidx == 6 || key->keyidx == 7) {
+			err = mt7996_mcu_bcn_prot_enable(dev, link,
+							 msta_link, key);
+			if (err)
+				return err;
+		}
+
+		err = mt7996_mcu_add_key(&dev->mt76, vif, key,
+					 MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
+					 &msta_link->wcid, cmd);
+		if (err)
+			return err;
+	}
+
+	return 0;
 }
 
 static void
@@ -221,12 +260,10 @@ mt7996_key_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		struct ieee80211_sta *sta, struct ieee80211_key_conf *key,
 		void *data)
 {
-	struct mt7996_vif_link *mlink = data;
-
 	if (sta)
 		return;
 
-	WARN_ON(mt7996_set_hw_key(hw, SET_KEY, vif, NULL, mlink, key));
+	WARN_ON(mt7996_set_hw_key(hw, SET_KEY, vif, NULL, key));
 }
 
 int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
@@ -298,7 +335,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 				   CONN_STATE_PORT_SECURE, true);
 	rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
 
-	ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, link);
+	ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, NULL);
 
 	return 0;
 }
@@ -486,7 +523,6 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_vif_link *mlink = &mvif->deflink;
 	int err;
 
 	/* The hardware does not support per-STA RX GTK, fallback
@@ -521,11 +557,11 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		return -EOPNOTSUPP;
 	}
 
-	if (!mt7996_vif_link_phy(mlink))
-	    return 0; /* defer until after link add */
+	if (!mt7996_vif_link_phy(&mvif->deflink))
+		return 0; /* defer until after link add */
 
 	mutex_lock(&dev->mt76.mutex);
-	err = mt7996_set_hw_key(hw, cmd, vif, sta, mlink, key);
+	err = mt7996_set_hw_key(hw, cmd, vif, sta, key);
 	mutex_unlock(&dev->mt76.mutex);
 
 	return err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index d1a0dd4698fbe5cf248796ed6f13b99f3c191af1..b9f689436bfd3859e01ff7025a1f77cec8348824 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2430,18 +2430,17 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
 	return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
 }
 
-static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
-			     u8 *pn)
+static int mt7996_mcu_get_pn(struct mt7996_dev *dev,
+			     struct mt7996_vif_link *link,
+			     struct mt7996_sta_link *msta_link, u8 *pn)
 {
 #define TSC_TYPE_BIGTK_PN 2
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link = &mvif->deflink.msta_link;
 	struct sta_rec_pn_info *pn_info;
 	struct sk_buff *skb, *rskb;
 	struct tlv *tlv;
 	int ret;
 
-	skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->deflink.mt76,
+	skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
 					    &msta_link->wcid);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
@@ -2466,10 +2465,11 @@ static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
 	return 0;
 }
 
-int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link,
 			       struct ieee80211_key_conf *key)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
 	struct sk_buff *skb;
 	struct tlv *tlv;
@@ -2478,7 +2478,7 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif
 		  sizeof(struct mt7996_mcu_bcn_prot_tlv);
 	int ret;
 
-	skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->deflink.mt76, len);
+	skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76, len);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
 
@@ -2486,7 +2486,7 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif
 
 	bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
 
-	ret = mt7996_mcu_get_pn(dev, vif, pn);
+	ret = mt7996_mcu_get_pn(dev, link, msta_link, pn);
 	if (ret) {
 		dev_kfree_skb(skb);
 		return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 4d5ab3f4b78ee6fc584370372fe34b44292e4594..1e79757b7a5197426438532a2f0c39e54d6ebae5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -746,7 +746,9 @@ 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,
 		       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, struct ieee80211_vif *vif,
+int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
+			       struct mt7996_vif_link *link,
+			       struct mt7996_sta_link *msta_link,
 			       struct ieee80211_key_conf *key);
 int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
 				     struct ieee80211_vif *vif,

-- 
2.48.1


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

* [PATCH 10/21] wifi: mt76: mt7996: rework mt7996_sta_hw_queue_read to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (8 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 09/21] wifi: mt76: mt7996: rework mt7996_set_hw_key to support MLO Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 11/21] wifi: mt76: mt7996: remove mt7996_mac_enable_rtscts() Lorenzo Bianconi
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Extend mt7996_sta_hw_queue_read to support multi-link setup.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7996/debugfs.c    | 54 +++++++++++++++-------
 1 file changed, 38 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index d453c2fc97e4fad10a29093b70e2ede8375ee0d8..4a28db17a2874078489e08ac8a038a51834b33a0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -616,29 +616,51 @@ static void
 mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
 {
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct mt7996_vif *mvif = msta->vif;
+	struct mt7996_dev *dev = mvif->deflink.phy->dev;
+	struct ieee80211_link_sta *link_sta;
 	struct seq_file *s = data;
-	u8 ac;
+	struct ieee80211_vif *vif;
+	unsigned int link_id;
 
-	for (ac = 0; ac < 4; ac++) {
-		u32 qlen, ctrl, val;
-		u32 idx = msta_link->wcid.idx >> 5;
-		u8 offs = msta_link->wcid.idx & GENMASK(4, 0);
+	vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
+
+	rcu_read_lock();
 
-		ctrl = BIT(31) | BIT(11) | (ac << 24);
-		val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt76_vif_link *mlink;
+		u8 ac;
 
-		if (val & BIT(offs))
+		mlink = rcu_dereference(mvif->mt76.link[link_id]);
+		if (!mlink)
 			continue;
 
-		mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta_link->wcid.idx);
-		qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
-				      GENMASK(11, 0));
-		seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
-			   sta->addr, msta_link->wcid.idx,
-			   msta->vif->deflink.mt76.wmm_idx, ac, qlen);
+		msta_link = rcu_dereference(msta->link[link_id]);
+		if (!msta_link)
+			continue;
+
+		for (ac = 0; ac < 4; ac++) {
+			u32 idx = msta_link->wcid.idx >> 5, qlen, ctrl, val;
+			u8 offs = msta_link->wcid.idx & GENMASK(4, 0);
+
+			ctrl = BIT(31) | BIT(11) | (ac << 24);
+			val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
+
+			if (val & BIT(offs))
+				continue;
+
+			mt76_wr(dev,
+				MT_FL_Q0_CTRL, ctrl | msta_link->wcid.idx);
+			qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
+					      GENMASK(11, 0));
+			seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
+				   sta->addr, msta_link->wcid.idx,
+				   mlink->wmm_idx, ac, qlen);
+		}
 	}
+
+	rcu_read_unlock();
 }
 
 static int

-- 
2.48.1


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

* [PATCH 11/21] wifi: mt76: mt7996: remove mt7996_mac_enable_rtscts()
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (9 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 10/21] wifi: mt76: mt7996: rework mt7996_sta_hw_queue_read " Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 12/21] wifi: mt76: mt7996: rework mt7996_mac_sta_rc_work to support MLO Lorenzo Bianconi
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek

From: Shayne Chen <shayne.chen@mediatek.com>

It is controlled by FW, also, driver should not directly write WTBL to
prevent WTBL overwritten issues.

Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    | 14 --------------
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |  3 ---
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  2 --
 3 files changed, 19 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index b8d88fdee97a3567b57a20d0322859b7ae8ce88a..c1c7638e29a1205629f4eb126e15163981109557 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -217,20 +217,6 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 	rcu_read_unlock();
 }
 
-void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
-			      struct ieee80211_vif *vif, bool enable)
-{
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_sta_link *msta_link = &mvif->deflink.msta_link;
-	u32 addr;
-
-	addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 5);
-	if (enable)
-		mt76_set(dev, addr, BIT(5));
-	else
-		mt76_clear(dev, addr, BIT(5));
-}
-
 /* The HW does not translate the mac header to 802.3 for mesh point */
 static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index a845c3e758adcc4802f704a99ac39aa9ca670c88..8d7ad2dc2d7bccf6c8f5fe4862828b61145a0c85 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -785,9 +785,6 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 				   !!(changed & BSS_CHANGED_BSSID));
 	}
 
-	if (changed & BSS_CHANGED_ERP_CTS_PROT)
-		mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot);
-
 	if (changed & BSS_CHANGED_ERP_SLOT) {
 		int slottime = info->use_short_slot ? 9 : 20;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 1e79757b7a5197426438532a2f0c39e54d6ebae5..8a347dd8e648a43250e7dd717cb65f77cb4a61dd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -707,8 +707,6 @@ bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
 void mt7996_mac_reset_counters(struct mt7996_phy *phy);
 void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
 void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
-void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
-			      struct ieee80211_vif *vif, bool enable);
 void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 			   struct sk_buff *skb, struct mt76_wcid *wcid,
 			   struct ieee80211_key_conf *key, int pid,

-- 
2.48.1


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

* [PATCH 12/21] wifi: mt76: mt7996: rework mt7996_mac_sta_rc_work to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (10 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 11/21] wifi: mt76: mt7996: remove mt7996_mac_enable_rtscts() Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 13/21] wifi: mt76: mt7996: rework mt7996_mac_sta_poll " Lorenzo Bianconi
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

Rework mt7996_mac_sta_rc_work routine in order to support multi-link
setup.

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Co-developed-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c  | 40 ++++++++++++++++++------
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 30 ++++++++++++------
 2 files changed, 52 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index c1c7638e29a1205629f4eb126e15163981109557..c56b1126abd59da5895d94fb368004adf6ffbbc8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2300,13 +2300,20 @@ void mt7996_mac_update_stats(struct mt7996_phy *phy)
 void mt7996_mac_sta_rc_work(struct work_struct *work)
 {
 	struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work);
+	struct ieee80211_bss_conf *link_conf;
+	struct ieee80211_link_sta *link_sta;
 	struct mt7996_sta_link *msta_link;
+	struct mt7996_vif_link *link;
+	struct mt76_vif_link *mlink;
 	struct ieee80211_sta *sta;
 	struct ieee80211_vif *vif;
 	struct mt7996_sta *msta;
-	u32 changed;
+	struct mt7996_vif *mvif;
 	LIST_HEAD(list);
+	u32 changed;
+	u8 link_id;
 
+	rcu_read_lock();
 	spin_lock_bh(&dev->mt76.sta_poll_lock);
 	list_splice_init(&dev->sta_rc_list, &list);
 
@@ -2319,21 +2326,35 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
 		msta_link->changed = 0;
 		spin_unlock_bh(&dev->mt76.sta_poll_lock);
 
+		sta = wcid_to_sta(&msta_link->wcid);
+		link_id = msta_link->wcid.link_id;
 		msta = msta_link->sta;
-		sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
-		vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
+		mvif = msta->vif;
+		vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
+
+		mlink = rcu_dereference(mvif->mt76.link[link_id]);
+		if (!mlink)
+			continue;
+
+		link_sta = rcu_dereference(sta->link[link_id]);
+		if (!link_sta)
+			continue;
+
+		link_conf = rcu_dereference(vif->link_conf[link_id]);
+		if (!link_conf)
+			continue;
+
+		link = (struct mt7996_vif_link *)mlink;
 
 		if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
 			       IEEE80211_RC_NSS_CHANGED |
 			       IEEE80211_RC_BW_CHANGED))
-			mt7996_mcu_add_rate_ctrl(dev, vif, &vif->bss_conf,
-						 &sta->deflink,
-						 &msta->vif->deflink,
-						 msta_link, true);
+			mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
+						 link_sta, link, msta_link,
+						 true);
 
 		if (changed & IEEE80211_RC_SMPS_CHANGED)
-			mt7996_mcu_set_fixed_field(dev, &sta->deflink,
-						   &msta->vif->deflink,
+			mt7996_mcu_set_fixed_field(dev, link_sta, link,
 						   msta_link, NULL,
 						   RATE_PARAM_MMPS_UPDATE);
 
@@ -2341,6 +2362,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
 	}
 
 	spin_unlock_bh(&dev->mt76.sta_poll_lock);
+	rcu_read_unlock();
 }
 
 void mt7996_mac_work(struct work_struct *work)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 8d7ad2dc2d7bccf6c8f5fe4862828b61145a0c85..4d3098e47dbbc25ced2a4b40c6b92423c451899e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -304,6 +304,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.tx_info |= MT_WCID_TX_INFO_SET;
 	mt76_wcid_init(&msta_link->wcid, band_idx);
 
@@ -1521,29 +1522,39 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
 	}
 }
 
-static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
+static void mt7996_link_rate_ctrl_update(void *data, struct ieee80211_sta *sta)
 {
 	struct mt7996_sta *msta = (struct mt7996_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;
 	u32 *changed = data;
 
+	rcu_read_lock();
+
+	msta_link = rcu_dereference(msta->link[msta->deflink_id]);
+	if (!msta_link)
+		goto out;
+
 	spin_lock_bh(&dev->mt76.sta_poll_lock);
+
 	msta_link->changed |= *changed;
 	if (list_empty(&msta_link->rc_list))
 		list_add_tail(&msta_link->rc_list, &dev->sta_rc_list);
+
 	spin_unlock_bh(&dev->mt76.sta_poll_lock);
+out:
+	rcu_read_unlock();
 }
 
-static void mt7996_sta_rc_update(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif,
-				 struct ieee80211_link_sta *link_sta,
-				 u32 changed)
+static void mt7996_link_sta_rc_update(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif,
+				      struct ieee80211_link_sta *link_sta,
+				      u32 changed)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct ieee80211_sta *sta = link_sta->sta;
 
-	mt7996_sta_rc_work(&changed, sta);
+	mt7996_link_rate_ctrl_update(&changed, sta);
 	ieee80211_queue_work(hw, &dev->rc_work);
 }
 
@@ -1565,7 +1576,8 @@ mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	 * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT
 	 * then multiple MCS setting (MCS 4,5,6) is not supported.
 	 */
-	ieee80211_iterate_stations_atomic(hw, mt7996_sta_rc_work, &changed);
+	ieee80211_iterate_stations_atomic(hw, mt7996_link_rate_ctrl_update,
+					  &changed);
 	ieee80211_queue_work(hw, &dev->rc_work);
 
 	return 0;
@@ -2023,7 +2035,7 @@ const struct ieee80211_ops mt7996_ops = {
 	.link_info_changed = mt7996_link_info_changed,
 	.sta_state = mt7996_sta_state,
 	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
-	.link_sta_rc_update = mt7996_sta_rc_update,
+	.link_sta_rc_update = mt7996_link_sta_rc_update,
 	.set_key = mt7996_set_key,
 	.ampdu_action = mt7996_ampdu_action,
 	.set_rts_threshold = mt7996_set_rts_threshold,

-- 
2.48.1


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

* [PATCH 13/21] wifi: mt76: mt7996: rework mt7996_mac_sta_poll to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (11 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 12/21] wifi: mt76: mt7996: rework mt7996_mac_sta_rc_work to support MLO Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 14/21] wifi: mt76: mt7996: rework mt7996_update_mu_group " Lorenzo Bianconi
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Rework mt7996_mac_sta_poll routine in order to support multi-link
setup.

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

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index c56b1126abd59da5895d94fb368004adf6ffbbc8..6870ee189dca61a989d4b7cfde741588c8f18482 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -123,10 +123,12 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 		[IEEE80211_AC_VO] = 6
 	};
 	struct mt7996_sta_link *msta_link;
+	struct mt76_vif_link *mlink;
 	struct ieee80211_sta *sta;
 	struct mt7996_sta *msta;
 	u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
 	LIST_HEAD(sta_poll_list);
+	struct mt76_wcid *wcid;
 	int i;
 
 	spin_lock_bh(&dev->mt76.sta_poll_lock);
@@ -150,10 +152,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 					     struct mt7996_sta_link,
 					     wcid.poll_list);
 		msta = msta_link->sta;
-		list_del_init(&msta_link->wcid.poll_list);
+		wcid = &msta_link->wcid;
+		list_del_init(&wcid->poll_list);
 		spin_unlock_bh(&dev->mt76.sta_poll_lock);
 
-		idx = msta_link->wcid.idx;
+		idx = wcid->idx;
 
 		/* refresh peer's airtime reporting */
 		addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
@@ -181,7 +184,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 			       sizeof(msta_link->airtime_ac));
 		}
 
-		if (!msta_link->wcid.sta)
+		if (!wcid->sta)
 			continue;
 
 		sta = container_of((void *)msta, struct ieee80211_sta,
@@ -207,8 +210,15 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
 		rssi[2] = to_rssi(GENMASK(23, 16), val);
 		rssi[3] = to_rssi(GENMASK(31, 14), val);
 
-		msta_link->ack_signal =
-			mt76_rx_signal(msta->vif->deflink.phy->mt76->antenna_mask, rssi);
+		mlink = rcu_dereference(msta->vif->mt76.link[wcid->link_id]);
+		if (mlink) {
+			struct mt76_phy *mphy = mt76_vif_link_phy(mlink);
+
+			if (mphy)
+				msta_link->ack_signal =
+					mt76_rx_signal(mphy->antenna_mask,
+						       rssi);
+		}
 
 		ewma_avg_signal_add(&msta_link->avg_ack_signal,
 				    -msta_link->ack_signal);

-- 
2.48.1


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

* [PATCH 14/21] wifi: mt76: mt7996: rework mt7996_update_mu_group to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (12 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 13/21] wifi: mt76: mt7996: rework mt7996_mac_sta_poll " Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:13 ` [PATCH 15/21] wifi: mt76: mt7996: rework mt7996_net_fill_forward_path " Lorenzo Bianconi
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Rework mt7996_update_mu_group routine in order to support multi-link
setup.

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

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 4d3098e47dbbc25ced2a4b40c6b92423c451899e..2bf6453975ae584b2ab7cc9a46cc80ad7d73d05d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -700,12 +700,11 @@ mt7996_get_rates_table(struct mt7996_phy *phy, struct ieee80211_bss_conf *conf,
 }
 
 static void
-mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+mt7996_update_mu_group(struct ieee80211_hw *hw, struct mt7996_vif_link *link,
 		       struct ieee80211_bss_conf *info)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	u8 band = mvif->deflink.mt76.band_idx;
+	u8 band = link->mt76.band_idx;
 	u32 *mu;
 
 	mu = (u32 *)info->mu_group.membership;
@@ -831,7 +830,7 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		mt7996_mcu_beacon_inband_discov(dev, vif, changed);
 
 	if (changed & BSS_CHANGED_MU_GROUPS)
-		mt7996_update_mu_group(hw, vif, info);
+		mt7996_update_mu_group(hw, link, info);
 
 	if (changed & BSS_CHANGED_TXPOWER &&
 	    info->txpower != phy->txpower) {

-- 
2.48.1


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

* [PATCH 15/21] wifi: mt76: mt7996: rework mt7996_net_fill_forward_path to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (13 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 14/21] wifi: mt76: mt7996: rework mt7996_update_mu_group " Lorenzo Bianconi
@ 2025-03-12 11:13 ` Lorenzo Bianconi
  2025-03-12 11:14 ` [PATCH 16/21] wifi: mt76: mt7996: rework mt7996_mcu_add_obss_spr " Lorenzo Bianconi
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:13 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Rework mt7996_net_fill_forward_path routine in order to support multi-link
setup.

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

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 2bf6453975ae584b2ab7cc9a46cc80ad7d73d05d..4a33979ee8535303fa3d09ec4500546d26f700eb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1973,13 +1973,26 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
-	struct mt7996_vif_link *mlink = &mvif->deflink;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+	struct mt7996_sta_link *msta_link;
+	struct mt7996_vif_link *link;
+	struct mt76_vif_link *mlink;
 	struct mt7996_phy *phy;
 
-	phy = mt7996_vif_link_phy(mlink);
+	mlink = rcu_dereference(mvif->mt76.link[msta->deflink_id]);
+	if (!mlink)
+		return -EIO;
+
+	msta_link = rcu_dereference(msta->link[msta->deflink_id]);
+	if (!msta_link)
+		return -EIO;
+
+	if (!msta_link->wcid.sta || msta_link->wcid.idx > MT7996_WTBL_STA)
+		return -EIO;
+
+	link = (struct mt7996_vif_link *)mlink;
+	phy = mt7996_vif_link_phy(link);
 	if (!phy)
 		return -ENODEV;
 
@@ -1989,13 +2002,10 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
 	if (!mtk_wed_device_active(wed))
 		return -ENODEV;
 
-	if (!msta_link->wcid.sta || msta_link->wcid.idx > MT7996_WTBL_STA)
-		return -EIO;
-
 	path->type = DEV_PATH_MTK_WDMA;
 	path->dev = ctx->dev;
 	path->mtk_wdma.wdma_idx = wed->wdma_idx;
-	path->mtk_wdma.bss = mvif->deflink.mt76.idx;
+	path->mtk_wdma.bss = mlink->idx;
 	path->mtk_wdma.queue = 0;
 	path->mtk_wdma.wcid = msta_link->wcid.idx;
 

-- 
2.48.1


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

* [PATCH 16/21] wifi: mt76: mt7996: rework mt7996_mcu_add_obss_spr to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (14 preceding siblings ...)
  2025-03-12 11:13 ` [PATCH 15/21] wifi: mt76: mt7996: rework mt7996_net_fill_forward_path " Lorenzo Bianconi
@ 2025-03-12 11:14 ` Lorenzo Bianconi
  2025-03-12 11:14 ` [PATCH 17/21] wifi: mt76: mt7996: rework mt7996_mcu_beacon_inband_discov " Lorenzo Bianconi
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:14 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

Rework mt7996_mcu_add_obss_spr routine in order to support multi-link
setup.

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |  3 ++-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 11 ++++++-----
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 ++-
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 4a33979ee8535303fa3d09ec4500546d26f700eb..eeb856984298c1e07396c0338e0858afbdb21501 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -807,7 +807,7 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		mt7996_mcu_set_tx(dev, vif, info);
 
 	if (changed & BSS_CHANGED_HE_OBSS_PD)
-		mt7996_mcu_add_obss_spr(phy, vif, &info->he_obss_pd);
+		mt7996_mcu_add_obss_spr(phy, link, &info->he_obss_pd);
 
 	if (changed & BSS_CHANGED_HE_BSS_COLOR) {
 		if ((vif->type == NL80211_IFTYPE_AP &&
@@ -1254,6 +1254,7 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	mtxq = (struct mt76_txq *)txq->drv_priv;
 
 	mutex_lock(&dev->mt76.mutex);
+
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid, ssn,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index b9f689436bfd3859e01ff7025a1f77cec8348824..318ab7c2baa22861637137edfb666e779e662557 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -4193,12 +4193,12 @@ mt7996_mcu_set_obss_spr_pd(struct mt7996_phy *phy,
 }
 
 static int
-mt7996_mcu_set_obss_spr_siga(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+mt7996_mcu_set_obss_spr_siga(struct mt7996_phy *phy,
+			     struct mt7996_vif_link *link,
 			     struct ieee80211_he_obss_pd *he_obss_pd)
 {
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_dev *dev = phy->dev;
-	u8 omac = mvif->deflink.mt76.omac_idx;
+	u8 omac = link->mt76.omac_idx;
 	struct {
 		u8 band_idx;
 		u8 __rsv[3];
@@ -4270,7 +4270,8 @@ mt7996_mcu_set_obss_spr_bitmap(struct mt7996_phy *phy,
 				 sizeof(req), true);
 }
 
-int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
+			    struct mt7996_vif_link *link,
 			    struct ieee80211_he_obss_pd *he_obss_pd)
 {
 	int ret;
@@ -4304,7 +4305,7 @@ int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
 		return ret;
 
 	/* Set SR prohibit */
-	ret = mt7996_mcu_set_obss_spr_siga(phy, vif, he_obss_pd);
+	ret = mt7996_mcu_set_obss_spr_siga(phy, link, he_obss_pd);
 	if (ret)
 		return ret;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 8a347dd8e648a43250e7dd717cb65f77cb4a61dd..45280f8f34fc4a56dddb3944232c17fdf4b61f69 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -595,7 +595,8 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct ieee80211_bss_conf *link_conf);
 int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
 				    struct ieee80211_vif *vif, u32 changed);
-int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
+			    struct mt7996_vif_link *link,
 			    struct ieee80211_he_obss_pd *he_obss_pd);
 int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
 			     struct ieee80211_vif *vif,

-- 
2.48.1


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

* [PATCH 17/21] wifi: mt76: mt7996: rework mt7996_mcu_beacon_inband_discov to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (15 preceding siblings ...)
  2025-03-12 11:14 ` [PATCH 16/21] wifi: mt76: mt7996: rework mt7996_mcu_add_obss_spr " Lorenzo Bianconi
@ 2025-03-12 11:14 ` Lorenzo Bianconi
  2025-03-12 11:14 ` [PATCH 18/21] wifi: mt76: mt7996: set vif default link_id adding/removing vif links Lorenzo Bianconi
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:14 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

Rework mt7996_mcu_beacon_inband_discov routine in order to support
multi-link setup.

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   |  2 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 19 ++++++++++---------
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  3 ++-
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index eeb856984298c1e07396c0338e0858afbdb21501..bcca1850d471bc43390c2f9e2ffecf6d9a05f377 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -827,7 +827,7 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 	if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
 		       BSS_CHANGED_FILS_DISCOVERY))
-		mt7996_mcu_beacon_inband_discov(dev, vif, changed);
+		mt7996_mcu_beacon_inband_discov(dev, info, link, changed);
 
 	if (changed & BSS_CHANGED_MU_GROUPS)
 		mt7996_update_mu_group(hw, link, info);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 318ab7c2baa22861637137edfb666e779e662557..85602a8594e0c9ab3a0055e04cf1ca836d62b6b9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2717,13 +2717,14 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 }
 
 int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
-				    struct ieee80211_vif *vif, u32 changed)
+				    struct ieee80211_bss_conf *link_conf,
+				    struct mt7996_vif_link *link, u32 changed)
 {
 #define OFFLOAD_TX_MODE_SU	BIT(0)
 #define OFFLOAD_TX_MODE_MU	BIT(1)
+	struct ieee80211_vif *vif = link_conf->vif;
 	struct ieee80211_hw *hw = mt76_hw(dev);
-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_phy *phy = link->phy;
 	struct mt76_wcid *wcid = &dev->mt76.global_wcid;
 	struct bss_inband_discovery_tlv *discov;
 	struct ieee80211_tx_info *info;
@@ -2740,21 +2741,21 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
 	chandef = &phy->mt76->chandef;
 	band = chandef->chan->band;
 
-	if (vif->bss_conf.nontransmitted)
+	if (link_conf->nontransmitted)
 		return 0;
 
-	rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->deflink.mt76,
+	rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76,
 					  MT7996_MAX_BSS_OFFLOAD_SIZE);
 	if (IS_ERR(rskb))
 		return PTR_ERR(rskb);
 
 	if (changed & BSS_CHANGED_FILS_DISCOVERY &&
-	    vif->bss_conf.fils_discovery.max_interval) {
-		interval = vif->bss_conf.fils_discovery.max_interval;
+	    link_conf->fils_discovery.max_interval) {
+		interval = link_conf->fils_discovery.max_interval;
 		skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
 	} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
-		   vif->bss_conf.unsol_bcast_probe_resp_interval) {
-		interval = vif->bss_conf.unsol_bcast_probe_resp_interval;
+		   link_conf->unsol_bcast_probe_resp_interval) {
+		interval = link_conf->unsol_bcast_probe_resp_interval;
 		skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
 	}
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 45280f8f34fc4a56dddb3944232c17fdf4b61f69..124a48e2706e412afc91af5e1c057fca40fe5e3c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -594,7 +594,8 @@ int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
 int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct ieee80211_bss_conf *link_conf);
 int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
-				    struct ieee80211_vif *vif, u32 changed);
+				    struct ieee80211_bss_conf *link_conf,
+				    struct mt7996_vif_link *link, u32 changed);
 int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
 			    struct mt7996_vif_link *link,
 			    struct ieee80211_he_obss_pd *he_obss_pd);

-- 
2.48.1


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

* [PATCH 18/21] wifi: mt76: mt7996: set vif default link_id adding/removing vif links
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (16 preceding siblings ...)
  2025-03-12 11:14 ` [PATCH 17/21] wifi: mt76: mt7996: rework mt7996_mcu_beacon_inband_discov " Lorenzo Bianconi
@ 2025-03-12 11:14 ` Lorenzo Bianconi
  2025-03-12 11:14 ` [PATCH 19/21] wifi: mt76: mt7996: rework set/get_tsf callabcks to support MLO Lorenzo Bianconi
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:14 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

This info will be consumed by subsequent patches (e.g. in set/get tsf
routines).

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

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index bcca1850d471bc43390c2f9e2ffecf6d9a05f377..40efba5bcaac364f8aa1ebf528e283494178616b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -271,6 +271,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 			struct mt76_vif_link *mlink)
 {
 	struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
+	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta_link *msta_link = &link->msta_link;
 	struct mt7996_phy *phy = mphy->priv;
 	struct mt7996_dev *dev = phy->dev;
@@ -338,6 +339,9 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, NULL);
 
+	if (mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED)
+		mvif->mt76.deflink_id = link_conf->link_id;
+
 	return 0;
 }
 
@@ -346,6 +350,7 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 			    struct mt76_vif_link *mlink)
 {
 	struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
+	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_sta_link *msta_link = &link->msta_link;
 	struct mt7996_phy *phy = mphy->priv;
 	struct mt7996_dev *dev = phy->dev;
@@ -359,6 +364,19 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 
 	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
 
+	if (mvif->mt76.deflink_id == link_conf->link_id) {
+		struct ieee80211_bss_conf *iter;
+		unsigned int link_id;
+
+		mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED;
+		for_each_vif_active_link(vif, iter, link_id) {
+			if (link_id != IEEE80211_LINK_UNSPECIFIED) {
+				mvif->mt76.deflink_id = link_id;
+				break;
+			}
+		}
+	}
+
 	dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);
 	phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
 
@@ -443,6 +461,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
 	mt76_vif_init(vif, &mvif->mt76);
 
 	vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
+	mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED;
 
 out:
 	mutex_unlock(&dev->mt76.mutex);

-- 
2.48.1


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

* [PATCH 19/21] wifi: mt76: mt7996: rework set/get_tsf callabcks to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (17 preceding siblings ...)
  2025-03-12 11:14 ` [PATCH 18/21] wifi: mt76: mt7996: set vif default link_id adding/removing vif links Lorenzo Bianconi
@ 2025-03-12 11:14 ` Lorenzo Bianconi
  2025-03-12 11:14 ` [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action " Lorenzo Bianconi
  2025-03-12 11:14 ` [PATCH 21/21] wifi: mt76: mt7996: Update mt7996_tx to MLO support Lorenzo Bianconi
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:14 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek, Bo Jiao,
	Peter Chiu, Lorenzo Bianconi

From: Shayne Chen <shayne.chen@mediatek.com>

This is a preliminary patch in order to enable MLO for MT7996 driver.

Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@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>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    |  2 +-
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 48 ++++++++++++++--------
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  2 +-
 3 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 6870ee189dca61a989d4b7cfde741588c8f18482..a52b4e71b267e9a72b69cb2ffbc95befb1cca655 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -2732,7 +2732,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
 
 		flow->sched = true;
 		flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow);
-		curr_tsf = __mt7996_get_tsf(hw, msta->vif);
+		curr_tsf = __mt7996_get_tsf(hw, &msta->vif->deflink);
 		div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem);
 		flow_tsf = curr_tsf + interval - rem;
 		twt_agrt->twt = cpu_to_le64(flow_tsf);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 40efba5bcaac364f8aa1ebf528e283494178616b..8bcb4b8e3ef58c23294c16c10d38384bfba87e30 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1336,10 +1336,10 @@ mt7996_get_stats(struct ieee80211_hw *hw,
 	return 0;
 }
 
-u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif)
+u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link)
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_phy *phy = link->phy;
 	union {
 		u64 t64;
 		u32 t32[2];
@@ -1351,8 +1351,8 @@ u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif)
 
 	lockdep_assert_held(&dev->mt76.mutex);
 
-	n = mvif->deflink.mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
-					       : mvif->deflink.mt76.omac_idx;
+	n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
+					       : link->mt76.omac_idx;
 	/* TSF software read */
 	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,
 		 MT_LPON_TCR_SW_READ);
@@ -1370,7 +1370,7 @@ mt7996_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	u64 ret;
 
 	mutex_lock(&dev->mt76.mutex);
-	ret = __mt7996_get_tsf(hw, mvif);
+	ret = __mt7996_get_tsf(hw, &mvif->deflink);
 	mutex_unlock(&dev->mt76.mutex);
 
 	return ret;
@@ -1382,26 +1382,33 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_vif_link *link;
+	struct mt7996_phy *phy;
 	union {
 		u64 t64;
 		u32 t32[2];
 	} tsf = { .t64 = timestamp, };
 	u16 n;
 
-	if (!phy)
-		return;
-
 	mutex_lock(&dev->mt76.mutex);
 
-	n = mvif->deflink.mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
-					       : mvif->deflink.mt76.omac_idx;
+	link = mt7996_vif_link(dev, vif, mvif->mt76.deflink_id);
+	if (!link)
+		goto unlock;
+
+	n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
+					       : link->mt76.omac_idx;
+	phy = link->phy;
+	if (!phy)
+		goto unlock;
+
 	mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]);
 	mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]);
 	/* TSF software overwrite */
 	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,
 		 MT_LPON_TCR_SW_WRITE);
 
+unlock:
 	mutex_unlock(&dev->mt76.mutex);
 }
 
@@ -1411,26 +1418,33 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
-	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_vif_link *link;
+	struct mt7996_phy *phy;
 	union {
 		u64 t64;
 		u32 t32[2];
 	} tsf = { .t64 = timestamp, };
 	u16 n;
 
-	if (!phy)
-		return;
-
 	mutex_lock(&dev->mt76.mutex);
 
-	n = mvif->deflink.mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
-					       : mvif->deflink.mt76.omac_idx;
+	link = mt7996_vif_link(dev, vif, mvif->mt76.deflink_id);
+	if (!link)
+		goto unlock;
+
+	phy = link->phy;
+	if (!phy)
+		goto unlock;
+
+	n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
+					       : link->mt76.omac_idx;
 	mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]);
 	mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]);
 	/* TSF software adjust*/
 	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,
 		 MT_LPON_TCR_SW_ADJUST);
 
+unlock:
 	mutex_unlock(&dev->mt76.mutex);
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 124a48e2706e412afc91af5e1c057fca40fe5e3c..815a3c68b8723469e32e74b85979eaf75c1b176a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -535,7 +535,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
 				     void __iomem *mem_base, u32 device_id);
 void mt7996_wfsys_reset(struct mt7996_dev *dev);
 irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
-u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
+u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link);
 int mt7996_register_device(struct mt7996_dev *dev);
 void mt7996_unregister_device(struct mt7996_dev *dev);
 int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,

-- 
2.48.1


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

* [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action to support MLO
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (18 preceding siblings ...)
  2025-03-12 11:14 ` [PATCH 19/21] wifi: mt76: mt7996: rework set/get_tsf callabcks to support MLO Lorenzo Bianconi
@ 2025-03-12 11:14 ` Lorenzo Bianconi
  2025-03-18  6:28   ` Shayne Chen
  2025-03-12 11:14 ` [PATCH 21/21] wifi: mt76: mt7996: Update mt7996_tx to MLO support Lorenzo Bianconi
  20 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:14 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Active/de-active TX/RX BA sessssion for each active links running
mt7996_ampdu_action routine.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 89 ++++++++++++++--------
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 16 ++--
 drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  5 +-
 3 files changed, 64 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 8bcb4b8e3ef58c23294c16c10d38384bfba87e30..adeb267b2801894590f90d02e902ebec602de98a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1259,12 +1259,13 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	enum ieee80211_ampdu_mlme_action action = params->action;
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct ieee80211_sta *sta = params->sta;
-	struct ieee80211_txq *txq = sta->txq[params->tid];
 	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
+	struct ieee80211_txq *txq = sta->txq[params->tid];
+	struct ieee80211_link_sta *link_sta;
 	u16 tid = params->tid;
 	u16 ssn = params->ssn;
 	struct mt76_txq *mtxq;
+	unsigned int link_id;
 	int ret = 0;
 
 	if (!txq)
@@ -1274,38 +1275,60 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 	mutex_lock(&dev->mt76.mutex);
 
-	switch (action) {
-	case IEEE80211_AMPDU_RX_START:
-		mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid, ssn,
-				   params->buf_size);
-		ret = mt7996_mcu_add_rx_ba(dev, params, true);
-		break;
-	case IEEE80211_AMPDU_RX_STOP:
-		mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid);
-		ret = mt7996_mcu_add_rx_ba(dev, params, false);
-		break;
-	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		mtxq->aggr = true;
-		mtxq->send_bar = false;
-		ret = mt7996_mcu_add_tx_ba(dev, params, true);
-		break;
-	case IEEE80211_AMPDU_TX_STOP_FLUSH:
-	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
-		mtxq->aggr = false;
-		clear_bit(tid, &msta_link->wcid.ampdu_state);
-		ret = mt7996_mcu_add_tx_ba(dev, params, false);
-		break;
-	case IEEE80211_AMPDU_TX_START:
-		set_bit(tid, &msta_link->wcid.ampdu_state);
-		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
-		break;
-	case IEEE80211_AMPDU_TX_STOP_CONT:
-		mtxq->aggr = false;
-		clear_bit(tid, &msta_link->wcid.ampdu_state);
-		ret = mt7996_mcu_add_tx_ba(dev, params, false);
-		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
+	for_each_sta_active_link(vif, sta, link_sta, link_id) {
+		struct mt7996_sta_link *msta_link;
+		struct mt7996_vif_link *link;
+
+		msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
+		if (!msta_link)
+			continue;
+
+		link = mt7996_vif_link(dev, vif, link_id);
+		if (!link)
+			continue;
+
+		switch (action) {
+		case IEEE80211_AMPDU_RX_START:
+			mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid,
+					   ssn, params->buf_size);
+			ret = mt7996_mcu_add_rx_ba(dev, params, link, true);
+			break;
+		case IEEE80211_AMPDU_RX_STOP:
+			mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid);
+			ret = mt7996_mcu_add_rx_ba(dev, params, link, false);
+			break;
+		case IEEE80211_AMPDU_TX_OPERATIONAL:
+			mtxq->aggr = true;
+			mtxq->send_bar = false;
+			ret = mt7996_mcu_add_tx_ba(dev, params, link,
+						   msta_link, true);
+			break;
+		case IEEE80211_AMPDU_TX_STOP_FLUSH:
+		case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+			mtxq->aggr = false;
+			clear_bit(tid, &msta_link->wcid.ampdu_state);
+			ret = mt7996_mcu_add_tx_ba(dev, params, link,
+						   msta_link, false);
+			break;
+		case IEEE80211_AMPDU_TX_START:
+			set_bit(tid, &msta_link->wcid.ampdu_state);
+			ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
+			break;
+		case IEEE80211_AMPDU_TX_STOP_CONT:
+			mtxq->aggr = false;
+			clear_bit(tid, &msta_link->wcid.ampdu_state);
+			ret = mt7996_mcu_add_tx_ba(dev, params, link,
+						   msta_link, false);
+			break;
+		}
+
+		if (ret)
+			break;
 	}
+
+	if (action == IEEE80211_AMPDU_TX_STOP_CONT)
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+
 	mutex_unlock(&dev->mt76.mutex);
 
 	return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 85602a8594e0c9ab3a0055e04cf1ca836d62b6b9..89e4f0e8858322b636650a27d9ab0872987b7011 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1160,26 +1160,20 @@ mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif_link *mvif,
 /** starec & wtbl **/
 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
-			 bool enable)
+			 struct mt7996_vif_link *link,
+			 struct mt7996_sta_link *msta_link, bool enable)
 {
-	struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;
-	struct mt7996_sta_link *msta_link = &msta->deflink;
-	struct mt7996_vif *mvif = msta->vif;
-
 	if (enable && !params->amsdu)
 		msta_link->wcid.amsdu = false;
 
-	return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params, enable, true);
+	return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable, true);
 }
 
 int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
-			 bool enable)
+			 struct mt7996_vif_link *link, bool enable)
 {
-	struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;
-	struct mt7996_vif *mvif = msta->vif;
-
-	return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params, enable, false);
+	return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable, false);
 }
 
 static void
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 815a3c68b8723469e32e74b85979eaf75c1b176a..43e646ed6094cb7fb78d201fc3ee8446ad2a16a1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -584,10 +584,11 @@ int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
 				struct mt7996_sta_link *msta_link);
 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
-			 bool add);
+			 struct mt7996_vif_link *link,
+			 struct mt7996_sta_link *msta_link, bool enable);
 int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
 			 struct ieee80211_ampdu_params *params,
-			 bool add);
+			 struct mt7996_vif_link *link, bool enable);
 int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
 				struct mt76_vif_link *mlink,
 				struct cfg80211_he_bss_color *he_bss_color);

-- 
2.48.1


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

* [PATCH 21/21] wifi: mt76: mt7996: Update mt7996_tx to MLO support
  2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
                   ` (19 preceding siblings ...)
  2025-03-12 11:14 ` [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action " Lorenzo Bianconi
@ 2025-03-12 11:14 ` Lorenzo Bianconi
  20 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-12 11:14 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
	Lorenzo Bianconi

Rework mt7996_tx routine in order to support multi-link
setup.

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

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index adeb267b2801894590f90d02e902ebec602de98a..91c64e3a0860ff0dc5405627b23f79f4ebd1dafd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1200,12 +1200,18 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_vif *vif = info->control.vif;
 	struct mt76_wcid *wcid = &dev->mt76.global_wcid;
+	u8 link_id = u32_get_bits(info->control.flags,
+				  IEEE80211_TX_CTRL_MLO_LINK);
+
+	rcu_read_lock();
 
 	if (vif) {
-		struct mt7996_vif *mvif;
+		struct mt7996_vif *mvif = (void *)vif->drv_priv;
+		struct mt76_vif_link *mlink;
 
-		mvif = (struct mt7996_vif *)vif->drv_priv;
-		wcid = &mvif->deflink.msta_link.wcid;
+		mlink = rcu_dereference(mvif->mt76.link[link_id]);
+		if (mlink && mlink->wcid)
+			wcid = mlink->wcid;
 
 		if (mvif->mt76.roc_phy &&
 		    (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) {
@@ -1217,19 +1223,22 @@ static void mt7996_tx(struct ieee80211_hw *hw,
 		}
 	}
 
-	if (control->sta) {
-		struct mt7996_sta_link *msta_link;
-
-		msta_link = (struct mt7996_sta_link *)control->sta->drv_priv;
-		wcid = &msta_link->wcid;
-	}
-
 	if (!mphy) {
 		ieee80211_free_txskb(hw, skb);
-		return;
+		goto unlock;
 	}
 
+	if (control->sta) {
+		struct mt7996_sta *msta = (void *)control->sta->drv_priv;
+		struct mt7996_sta_link *msta_link;
+
+		msta_link = rcu_dereference(msta->link[link_id]);
+		if (msta_link)
+			wcid = &msta_link->wcid;
+	}
 	mt76_tx(mphy, control->sta, wcid, skb);
+unlock:
+	rcu_read_unlock();
 }
 
 static int mt7996_set_rts_threshold(struct ieee80211_hw *hw, u32 val)

-- 
2.48.1


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

* Re: [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action to support MLO
  2025-03-12 11:14 ` [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action " Lorenzo Bianconi
@ 2025-03-18  6:28   ` Shayne Chen
  2025-03-18  8:30     ` Shayne Chen
  0 siblings, 1 reply; 27+ messages in thread
From: Shayne Chen @ 2025-03-18  6:28 UTC (permalink / raw)
  To: Lorenzo Bianconi, Felix Fietkau, Ryder Lee, Sean Wang,
	Johannes Berg, Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek

Hi Lorenzo,

On Wed, 2025-03-12 at 12:14 +0100, Lorenzo Bianconi wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Active/de-active TX/RX BA sessssion for each active links running
> mt7996_ampdu_action routine.
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
>  drivers/net/wireless/mediatek/mt76/mt7996/main.c   | 89
> ++++++++++++++--------
>  drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    | 16 ++--
>  drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h |  5 +-
>  3 files changed, 64 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index
> 8bcb4b8e3ef58c23294c16c10d38384bfba87e30..adeb267b2801894590f90d02e90
> 2ebec602de98a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -1259,12 +1259,13 @@ mt7996_ampdu_action(struct ieee80211_hw *hw,
> struct ieee80211_vif *vif,
>         enum ieee80211_ampdu_mlme_action action = params->action;
>         struct mt7996_dev *dev = mt7996_hw_dev(hw);
>         struct ieee80211_sta *sta = params->sta;
> -       struct ieee80211_txq *txq = sta->txq[params->tid];
>         struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
> -       struct mt7996_sta_link *msta_link = &msta->deflink;
> +       struct ieee80211_txq *txq = sta->txq[params->tid];
> +       struct ieee80211_link_sta *link_sta;
>         u16 tid = params->tid;
>         u16 ssn = params->ssn;
>         struct mt76_txq *mtxq;
> +       unsigned int link_id;
>         int ret = 0;
> 
>         if (!txq)
> @@ -1274,38 +1275,60 @@ mt7996_ampdu_action(struct ieee80211_hw *hw,
> struct ieee80211_vif *vif,
> 
>         mutex_lock(&dev->mt76.mutex);
> 
> -       switch (action) {
> -       case IEEE80211_AMPDU_RX_START:
> -               mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid,
> ssn,
> -                                  params->buf_size);
> -               ret = mt7996_mcu_add_rx_ba(dev, params, true);
> -               break;
> -       case IEEE80211_AMPDU_RX_STOP:
> -               mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid);
> -               ret = mt7996_mcu_add_rx_ba(dev, params, false);
> -               break;
> -       case IEEE80211_AMPDU_TX_OPERATIONAL:
> -               mtxq->aggr = true;
> -               mtxq->send_bar = false;
> -               ret = mt7996_mcu_add_tx_ba(dev, params, true);
> -               break;
> -       case IEEE80211_AMPDU_TX_STOP_FLUSH:
> -       case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
> -               mtxq->aggr = false;
> -               clear_bit(tid, &msta_link->wcid.ampdu_state);
> -               ret = mt7996_mcu_add_tx_ba(dev, params, false);
> -               break;
> -       case IEEE80211_AMPDU_TX_START:
> -               set_bit(tid, &msta_link->wcid.ampdu_state);
> -               ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
> -               break;
> -       case IEEE80211_AMPDU_TX_STOP_CONT:
> -               mtxq->aggr = false;
> -               clear_bit(tid, &msta_link->wcid.ampdu_state);
> -               ret = mt7996_mcu_add_tx_ba(dev, params, false);
> -               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
> -               break;
> +       for_each_sta_active_link(vif, sta, link_sta, link_id) {
> +               struct mt7996_sta_link *msta_link;
> +               struct mt7996_vif_link *link;
> +
> +               msta_link = mt76_dereference(msta->link[link_id],
> &dev->mt76);
> +               if (!msta_link)
> +                       continue;
> +
> +               link = mt7996_vif_link(dev, vif, link_id);
> +               if (!link)
> +                       continue;
> +
> +               switch (action) {
> +               case IEEE80211_AMPDU_RX_START:
> +                       mt76_rx_aggr_start(&dev->mt76, &msta_link-
> >wcid, tid,
> +                                          ssn, params->buf_size);
> +                       ret = mt7996_mcu_add_rx_ba(dev, params, link,
> true);
> +                       break;
> +               case IEEE80211_AMPDU_RX_STOP:
> +                       mt76_rx_aggr_stop(&dev->mt76, &msta_link-
> >wcid, tid);
> +                       ret = mt7996_mcu_add_rx_ba(dev, params, link,
> false);
> +                       break;
> +               case IEEE80211_AMPDU_TX_OPERATIONAL:
> +                       mtxq->aggr = true;
> +                       mtxq->send_bar = false;
> +                       ret = mt7996_mcu_add_tx_ba(dev, params, link,
> +                                                  msta_link, true);
> +                       break;
> +               case IEEE80211_AMPDU_TX_STOP_FLUSH:
> +               case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
> +                       mtxq->aggr = false;
> +                       clear_bit(tid, &msta_link->wcid.ampdu_state);
> +                       ret = mt7996_mcu_add_tx_ba(dev, params, link,
> +                                                  msta_link, false);
> +                       break;
> +               case IEEE80211_AMPDU_TX_START:
> +                       set_bit(tid, &msta_link->wcid.ampdu_state);
> +                       ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
> +                       break;
> +               case IEEE80211_AMPDU_TX_STOP_CONT:
> +                       mtxq->aggr = false;
> +                       clear_bit(tid, &msta_link->wcid.ampdu_state);
> +                       ret = mt7996_mcu_add_tx_ba(dev, params, link,
> +                                                  msta_link, false);
> +                       break;
> +               }
> +
> +               if (ret)
> +                       break;
>         }
> +
> +       if (action == IEEE80211_AMPDU_TX_STOP_CONT)
> +               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
> +
>         mutex_unlock(&dev->mt76.mutex);
> 
>         return ret;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index
> 85602a8594e0c9ab3a0055e04cf1ca836d62b6b9..89e4f0e8858322b636650a27d9a
> b0872987b7011 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> @@ -1160,26 +1160,20 @@ mt7996_mcu_sta_ba(struct mt7996_dev *dev,
> struct mt76_vif_link *mvif,
>  /** starec & wtbl **/
>  int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
>                          struct ieee80211_ampdu_params *params,
> -                        bool enable)
> +                        struct mt7996_vif_link *link,
> +                        struct mt7996_sta_link *msta_link, bool
> enable)
>  {
> -       struct mt7996_sta *msta = (struct mt7996_sta *)params->sta-
> >drv_priv;
> -       struct mt7996_sta_link *msta_link = &msta->deflink;
> -       struct mt7996_vif *mvif = msta->vif;
> -
>         if (enable && !params->amsdu)
>                 msta_link->wcid.amsdu = false;
> 
> -       return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params,
> enable, true);
> +       return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable,
> true);

Per-link-bss setting is now ready for mt7996_mcu_sta_ba(), while for
per-link-sta, the wcid is still retrieved from deflink through the
following line:

struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv

We may also need to pass msta_link->wcid to mt7996_mcu_sta_ba().
>  }
> 
>  int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
>                          struct ieee80211_ampdu_params *params,
> -                        bool enable)
> +                        struct mt7996_vif_link *link, bool enable)
>  {
> -       struct mt7996_sta *msta = (struct mt7996_sta *)params->sta-
> >drv_priv;
> -       struct mt7996_vif *mvif = msta->vif;
> -
> -       return mt7996_mcu_sta_ba(dev, &mvif->deflink.mt76, params,
> enable, false);
> +       return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable,
> false);

Same here.
>  }
> 
>  static void
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> index
> 815a3c68b8723469e32e74b85979eaf75c1b176a..43e646ed6094cb7fb78d201fc3e
> e8446ad2a16a1 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> @@ -584,10 +584,11 @@ int mt7996_mcu_teardown_mld_sta(struct
> mt7996_dev *dev,
>                                 struct mt7996_sta_link *msta_link);
>  int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
>                          struct ieee80211_ampdu_params *params,
> -                        bool add);
> +                        struct mt7996_vif_link *link,
> +                        struct mt7996_sta_link *msta_link, bool
> enable);
>  int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
>                          struct ieee80211_ampdu_params *params,
> -                        bool add);
> +                        struct mt7996_vif_link *link, bool enable);
>  int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
>                                 struct mt76_vif_link *mlink,
>                                 struct cfg80211_he_bss_color
> *he_bss_color);
> 
> --
> 2.48.1
> 

Regards,
Shayne

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

* Re: [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action to support MLO
  2025-03-18  6:28   ` Shayne Chen
@ 2025-03-18  8:30     ` Shayne Chen
  2025-03-18 13:53       ` Lorenzo Bianconi
  0 siblings, 1 reply; 27+ messages in thread
From: Shayne Chen @ 2025-03-18  8:30 UTC (permalink / raw)
  To: Lorenzo Bianconi, Felix Fietkau, Ryder Lee, Sean Wang,
	Johannes Berg, Matthias Brugger, AngeloGioacchino Del Regno
  Cc: linux-wireless, linux-arm-kernel, linux-mediatek

Hi Lorenzo,

Sorry, please ignore the previous mail.
I just aware that the deflink is now used as the primary/assoc link, so
it should work.

Regards,
Shayne

On Tue, 2025-03-18 at 14:28 +0800, Shayne Chen wrote:
> Hi Lorenzo,
> 
> On Wed, 2025-03-12 at 12:14 +0100, Lorenzo Bianconi wrote:
> > 
> 
> Regards,
> Shayne


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

* Re: [PATCH 02/21] wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()
  2025-03-12 11:13 ` [PATCH 02/21] wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv() Lorenzo Bianconi
@ 2025-03-18  8:51   ` Shayne Chen (陳軒丞)
  2025-03-18 13:53     ` lorenzo
  0 siblings, 1 reply; 27+ messages in thread
From: Shayne Chen (陳軒丞) @ 2025-03-18  8:51 UTC (permalink / raw)
  To: Sean Wang, nbd@nbd.name, lorenzo@kernel.org, Ryder Lee,
	johannes@sipsolutions.net, matthias.bgg@gmail.com,
	AngeloGioacchino Del Regno
  Cc: linux-wireless@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-mediatek@lists.infradead.org, Bo Jiao (焦波),
	Chui-hao Chiu (邱垂浩)

On Wed, 2025-03-12 at 12:13 +0100, Lorenzo Bianconi wrote:
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index
> 0cc822a8a6799a4552fa537cab2f13d6537bb1a8..ac01eb880e2a6f6ef3a81591bca
> cd2b90c48986a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> @@ -2197,6 +2197,80 @@ mt7996_mcu_add_group(struct mt7996_dev *dev,
> struct ieee80211_vif *vif,
>                                  sizeof(req), true);
>  }
> 
> +static void
> +mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff
> *skb,
> +                            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);
> +       struct mld_setup_link *mld_setup_link;
> +       struct sta_rec_mld_setup *mld_setup;
> +       struct mt7996_sta_link *msta_link;
> +       struct ieee80211_vif *vif;
> +       unsigned int link_id;
> +       struct tlv *tlv;
> +
> +       msta_link = mt76_dereference(msta->link[msta->deflink_id],
> &dev->mt76);
> +       if (!msta_link)
> +               return;
> +
> +       tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD,
> +                                     sizeof(struct
> sta_rec_mld_setup) +
> +                                     sizeof(struct mld_setup_link) *
> nlinks);
> +
> +       mld_setup = (struct sta_rec_mld_setup *)tlv;
> +       memcpy(mld_setup->mld_addr, sta->addr, ETH_ALEN);
> +       mld_setup->setup_wcid = cpu_to_le16(msta_link->wcid.idx);
> +       mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx);
> +
> +       if (nlinks > 1) {
> +               link_id = __ffs(links & ~BIT(msta->deflink_id));
> +               msta_link = mt76_dereference(msta->link[msta-
> >deflink_id],
> +                                            &dev->mt76);
> +               if (!msta_link)
> +                       return;
> +       }
> +       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) {
> +               struct mt7996_vif_link *link;
> +
> +               msta_link = mt76_dereference(msta->link[link_id],
> &dev->mt76);
> +               if (!msta_link)
> +                       continue;
> +
> +               link = mt7996_vif_link(dev, vif, link_id);
> +               if (!link)
> +                       continue;
> +
> +               if (!msta_link)
> +                       continue;
> +
> +               mld_setup_link->wcid = cpu_to_le16(msta_link-
> >wcid.idx);
> +               mld_setup_link->bss_idx = link->mt76.idx;
> +               mld_setup_link++;
> +       }
> +}
> +
> +static void
> +mt7996_mcu_sta_eht_mld_tlv(struct mt7996_dev *dev, struct sk_buff
> *skb,
> +                          struct ieee80211_sta *sta)
> +{
> +       struct sta_rec_eht_mld *eht_mld;
> +       struct tlv *tlv;
> +       int i;
> +
> +       tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD,
> sizeof(*eht_mld));
> +       eht_mld = (struct sta_rec_eht_mld *)tlv;
> +
> +       for (i = 0; i < ARRAY_SIZE(eht_mld->str_cap); i++)
> +               eht_mld->str_cap[i] = 0x7;
> +}
> +
>  int mt7996_mcu_add_sta(struct mt7996_dev *dev,
>                        struct ieee80211_bss_conf *link_conf,
>                        struct ieee80211_link_sta *link_sta,
> @@ -2255,6 +2329,11 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
>                 mt7996_mcu_sta_eht_tlv(skb, link_sta);
>                 /* starec muru */
>                 mt7996_mcu_sta_muru_tlv(dev, skb, link_conf,
> link_sta);
> +
> +               if (sta->mlo && conn_state != CONN_STATE_DISCONNECT)

The latter check seems already to be handled by:
if (conn_state == CONN_STATE_DISCONNECT)
    goto out;

> {
> +                       mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
> +                       mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
> +               }
>         }
> 
>         ret = mt7996_mcu_add_group(dev, link_conf->vif, sta);
> 


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

* Re: [PATCH 02/21] wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv()
  2025-03-18  8:51   ` Shayne Chen (陳軒丞)
@ 2025-03-18 13:53     ` lorenzo
  0 siblings, 0 replies; 27+ messages in thread
From: lorenzo @ 2025-03-18 13:53 UTC (permalink / raw)
  To: Shayne Chen (陳軒丞)
  Cc: Sean Wang, nbd@nbd.name, Ryder Lee, johannes@sipsolutions.net,
	matthias.bgg@gmail.com, AngeloGioacchino Del Regno,
	linux-wireless@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-mediatek@lists.infradead.org, Bo Jiao (焦波),
	Chui-hao Chiu (邱垂浩)

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

[...]
> > link_sta);
> > +
> > +               if (sta->mlo && conn_state != CONN_STATE_DISCONNECT)
> 
> The latter check seems already to be handled by:
> if (conn_state == CONN_STATE_DISCONNECT)
>     goto out;

ack, I will fix it.

Regards,
Lorenzo

> 
> > {
> > +                       mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
> > +                       mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
> > +               }
> >         }
> > 
> >         ret = mt7996_mcu_add_group(dev, link_conf->vif, sta);
> > 
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action to support MLO
  2025-03-18  8:30     ` Shayne Chen
@ 2025-03-18 13:53       ` Lorenzo Bianconi
  0 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2025-03-18 13:53 UTC (permalink / raw)
  To: Shayne Chen
  Cc: Felix Fietkau, Ryder Lee, Sean Wang, Johannes Berg,
	Matthias Brugger, AngeloGioacchino Del Regno, linux-wireless,
	linux-arm-kernel, linux-mediatek

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

> Hi Lorenzo,
> 
> Sorry, please ignore the previous mail.
> I just aware that the deflink is now used as the primary/assoc link, so
> it should work.
> 
> Regards,
> Shayne
> 
> On Tue, 2025-03-18 at 14:28 +0800, Shayne Chen wrote:
> > Hi Lorenzo,
> > 
> > On Wed, 2025-03-12 at 12:14 +0100, Lorenzo Bianconi wrote:
> > > 
> > 
> > Regards,
> > Shayne
> 

ack, no worries.

Regards,
Lorenzo

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

end of thread, other threads:[~2025-03-18 13:53 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-12 11:13 [PATCH 00/21] wifi: mt76: mt7996: second preliminary work to support MLO Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 01/21] wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl to MLO Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 02/21] wifi: mt76: mt7996: Add mt7996_mcu_sta_mld_setup_tlv() and mt7996_mcu_sta_eht_mld_tlv() Lorenzo Bianconi
2025-03-18  8:51   ` Shayne Chen (陳軒丞)
2025-03-18 13:53     ` lorenzo
2025-03-12 11:13 ` [PATCH 03/21] wifi: mt76: mt7996: Add mt7996_mcu_teardown_mld_sta rouine Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 04/21] wifi: mt76: mt7996: rework mt7996_mac_write_txwi() for MLO support Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 05/21] wifi: mt76: mt7996: Rely on wcid_to_sta in mt7996_mac_add_txs_skb() Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 06/21] wifi: mt76: mt7996: rework mt7996_rx_get_wcid to support MLO Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 07/21] wifi: mt76: mt7996: rework mt7996_sta_set_4addr and mt7996_sta_set_decap_offload " Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 08/21] wifi: mt76: mt7996: Add mt7996_sta_link to mt7996_mcu_add_bss_info signature Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 09/21] wifi: mt76: mt7996: rework mt7996_set_hw_key to support MLO Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 10/21] wifi: mt76: mt7996: rework mt7996_sta_hw_queue_read " Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 11/21] wifi: mt76: mt7996: remove mt7996_mac_enable_rtscts() Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 12/21] wifi: mt76: mt7996: rework mt7996_mac_sta_rc_work to support MLO Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 13/21] wifi: mt76: mt7996: rework mt7996_mac_sta_poll " Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 14/21] wifi: mt76: mt7996: rework mt7996_update_mu_group " Lorenzo Bianconi
2025-03-12 11:13 ` [PATCH 15/21] wifi: mt76: mt7996: rework mt7996_net_fill_forward_path " Lorenzo Bianconi
2025-03-12 11:14 ` [PATCH 16/21] wifi: mt76: mt7996: rework mt7996_mcu_add_obss_spr " Lorenzo Bianconi
2025-03-12 11:14 ` [PATCH 17/21] wifi: mt76: mt7996: rework mt7996_mcu_beacon_inband_discov " Lorenzo Bianconi
2025-03-12 11:14 ` [PATCH 18/21] wifi: mt76: mt7996: set vif default link_id adding/removing vif links Lorenzo Bianconi
2025-03-12 11:14 ` [PATCH 19/21] wifi: mt76: mt7996: rework set/get_tsf callabcks to support MLO Lorenzo Bianconi
2025-03-12 11:14 ` [PATCH 20/21] wifi: mt76: mt7996: rework mt7996_ampdu_action " Lorenzo Bianconi
2025-03-18  6:28   ` Shayne Chen
2025-03-18  8:30     ` Shayne Chen
2025-03-18 13:53       ` Lorenzo Bianconi
2025-03-12 11:14 ` [PATCH 21/21] wifi: mt76: mt7996: Update mt7996_tx to MLO support 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).