[PATCH wireless] wifi: mt76: mt7925: fix MT7927 receive loss after a channel switch

Devin Wittmayer lucid_duck at justthetip.ca
Mon Oct 12 19:38:10 PDT 2026


When the access point announces a channel switch, an MT7927 stays
connected but stops receiving until it reconnects.

To set the band, the driver deletes the MT7927's firmware interface and
adds it back whenever a single-link interface is put on a channel. A
channel switch does this mid-connection, and the connection is not
restored.

Skip it on a channel switch unless the band changes. Monitor mode still
needs it to retune.

Fixes: 05fd14885303 ("wifi: mt76: mt7925: sync MT7927 BSS band assignment")
Link: https://lore.kernel.org/linux-wireless/20260306-mt7927-wifi-support-v1-17-c77e7445511d@jetm.me/
Cc: stable at vger.kernel.org
Signed-off-by: Devin Wittmayer <lucid_duck at justthetip.ca>
---

Notes:
    Tested on a Framework 13 with its built-in MT7927 and an MT7925, both
    downloading while a WiFi 7 access point switched. Switches after which
    the MT7927 needed a reconnect:
    
                             7.2.10      + fix       7.3-rc7     + fix
      channel moved          10 of 10    0 of 10     10 of 10    0 of 10
      width changed          26 of 26    0 of 26     26 of 26    0 of 26
      puncturing removed     10 of 10    0 of 10     10 of 10    0 of 10
    
    With the fix both cards can pause for up to three seconds at a switch,
    as the MT7925 also does without it. Monitor mode, AP mode, joins and
    moves between 2.4 and 5 GHz work as before, and the card still recovers
    from a firmware reset and from suspend. Two other MediaTek cards on a
    second machine came through every switch, stock and patched.
    
    The series as first posted only resent the interface when the band
    changed:
    https://lore.kernel.org/linux-wireless/20260306-mt7927-wifi-support-v1-17-c77e7445511d@jetm.me/

 .../net/wireless/mediatek/mt76/mt7925/main.c  | 25 +++++++++++++------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index b46408f4aed2..bdd44b52f886 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -2401,10 +2401,11 @@ mt7927_reconfig_band(struct mt792x_dev *dev, struct ieee80211_vif *vif,
 					   true);
 }
 
-static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_bss_conf *link_conf,
-				     struct ieee80211_chanctx_conf *ctx)
+static int __mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_bss_conf *link_conf,
+				       struct ieee80211_chanctx_conf *ctx,
+				       bool switching)
 {
 	struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv;
 	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
@@ -2429,7 +2430,9 @@ static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
 		if (is_mt7927(&dev->mt76)) {
 			band_idx = mt7927_band_idx(ctx->def.chan->band);
 
-			mt7927_reconfig_band(dev, vif, link_conf, mconf, band_idx);
+			if (!switching || mconf->mt76.band_idx != band_idx)
+				mt7927_reconfig_band(dev, vif, link_conf, mconf,
+						     band_idx);
 		}
 	}
 
@@ -2441,6 +2444,14 @@ static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
 	return 0;
 }
 
+static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *link_conf,
+				     struct ieee80211_chanctx_conf *ctx)
+{
+	return __mt7925_assign_vif_chanctx(hw, vif, link_conf, ctx, false);
+}
+
 static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw,
 					struct ieee80211_vif *vif,
 					struct ieee80211_bss_conf *link_conf,
@@ -2491,8 +2502,8 @@ static int mt7925_switch_vif_chanctx(struct ieee80211_hw *hw,
 				     int n_vifs,
 				     enum ieee80211_chanctx_switch_mode mode)
 {
-	return mt7925_assign_vif_chanctx(hw, vifs->vif, vifs->link_conf,
-					 vifs->new_ctx);
+	return __mt7925_assign_vif_chanctx(hw, vifs->vif, vifs->link_conf,
+					   vifs->new_ctx, true);
 }
 
 void mt7925_csa_work(struct work_struct *work)
-- 
2.56.0




More information about the Linux-mediatek mailing list