The MT7927 (Filogic 380) firmware requires explicit band_idx assignment (0 for 2.4GHz, 1 for 5GHz/6GHz) instead of 0xff (auto-select) used by MT7925. Without this, the firmware selects the wrong radio for 5GHz and 6GHz connections, causing WPA 4-way handshake timeout and data plane failures on those bands. Add mt7925_mt7927_hw_band_from_nl() helper to map nl80211_band to hardware band index, and use it throughout the driver: - mac_link_bss_add: set band_idx from link channel at BSS creation - assign_vif_chanctx: update band_idx when channel context changes, resend DEV_INFO to firmware if band changed - bss_basic_tlv: set band_idx in BSS info sent to firmware - set_roc / set_mlo_roc / abort_roc: send concrete dbdcband instead of 0xff auto-select - roc_iter / roc_handle_grant: clamp invalid grant band_idx values using rfband as fallback, process grants for all MT7927 request types (not just JOIN) All changes guarded by is_mt7927() - no impact on MT7925 behavior. Originally discovered and fixed by marcin-fm; Loong0x00 contributed additional improvements based on marcin-fm's patch. Co-developed-by: Marcin FM Signed-off-by: Marcin FM Co-developed-by: 张旭涵 Signed-off-by: 张旭涵 Assisted-by: Claude Code (claude-opus-4-6) Tested-by: Marcin FM Tested-by: Cristian-Florin Radoi Tested-by: George Salukvadze Tested-by: Evgeny Kapusta <3193631@gmail.com> Tested-by: Samu Toljamo Tested-by: Ariel Rosenfeld Tested-by: Chapuis Dario Tested-by: Thibaut François Tested-by: 张旭涵 Signed-off-by: Javier Tia --- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 40 +++++++++++++++- drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 54 ++++++++++++++++++---- drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h | 5 ++ 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index f82c56c46324..fcb9f26c8b87 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -400,7 +400,24 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev, mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ? 0 : mconf->mt76.idx; - mconf->mt76.band_idx = 0xff; + + if (is_mt7927(&dev->mt76)) { + struct ieee80211_channel *chan = NULL; + + if (link_conf->chanreq.oper.chan) + chan = link_conf->chanreq.oper.chan; + else if (mvif->phy->mt76->chandef.chan) + chan = mvif->phy->mt76->chandef.chan; + + if (chan) + mconf->mt76.band_idx = + mt7925_mt7927_hw_band_from_nl(chan->band); + else + mconf->mt76.band_idx = 0xff; + } else { + mconf->mt76.band_idx = 0xff; + } + mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ? 0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; mconf->mt76.link_idx = hweight16(mvif->valid_links); @@ -417,7 +434,8 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev, mlink->wcid.idx = idx; mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET; - mt76_wcid_init(&mlink->wcid, 0); + mt76_wcid_init(&mlink->wcid, + mconf->mt76.band_idx == 0xff ? 0 : mconf->mt76.band_idx); mt7925_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -2119,9 +2137,12 @@ static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw, { struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_link_sta *mlink; struct mt792x_dev *dev = mt792x_hw_dev(hw); struct ieee80211_bss_conf *pri_link_conf; struct mt792x_bss_conf *mconf; + u8 band_idx; + u8 old_band; mutex_lock(&dev->mt76.mutex); @@ -2137,6 +2158,21 @@ static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw, mconf = &mvif->bss_conf; } + old_band = mconf->mt76.band_idx; + if (is_mt7927(&dev->mt76) && ctx->def.chan) { + band_idx = mt7925_mt7927_hw_band_from_nl(ctx->def.chan->band); + mconf->mt76.band_idx = band_idx; + mlink = mt792x_sta_to_link(&mvif->sta, mconf->link_id); + if (mlink) + mlink->wcid.phy_idx = band_idx; + + if (old_band != band_idx && vif->type == NL80211_IFTYPE_STATION && + mlink) + mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf, + &mconf->mt76, &mlink->wcid, + true); + } + mconf->mt76.ctx = ctx; mctx->bss_conf = mconf; mutex_unlock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c index 8b5ffb240d52..3458aa8c79cb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -301,16 +301,36 @@ mt7925_mcu_connection_loss_event(struct mt792x_dev *dev, struct sk_buff *skb) static void mt7925_mcu_roc_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt7925_roc_grant_tlv *grant = priv; + u8 band_idx = grant->dbdcband; if (ieee80211_vif_is_mld(vif) && vif->type == NL80211_IFTYPE_STATION) return; - if (mvif->idx != grant->bss_idx) + if (mvif->bss_conf.mt76.idx != grant->bss_idx) return; - mvif->band_idx = grant->dbdcband; + /* MT7927 firmware requires band_idx 0 (2.4G) or 1 (5/6G). + * Clamp invalid grant values using rfband as fallback. + */ + if (is_mt7927(&mvif->phy->dev->mt76) && band_idx > 1) { + switch (grant->rfband) { + case 1: /* 2.4 GHz */ + band_idx = 0; + break; + case 2: /* 5 GHz */ + case 3: /* 6 GHz */ + band_idx = 1; + break; + default: + band_idx = mvif->bss_conf.mt76.band_idx <= 1 ? + mvif->bss_conf.mt76.band_idx : 0; + break; + } + } + + mvif->bss_conf.mt76.band_idx = band_idx; } static void mt7925_mcu_roc_handle_grant(struct mt792x_dev *dev, @@ -327,10 +347,11 @@ static void mt7925_mcu_roc_handle_grant(struct mt792x_dev *dev, if (grant->reqtype == MT7925_ROC_REQ_ROC) ieee80211_ready_on_channel(hw); - else if (grant->reqtype == MT7925_ROC_REQ_JOIN) + else if (is_mt7927(&dev->mt76) || grant->reqtype == MT7925_ROC_REQ_JOIN) ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7925_mcu_roc_iter, grant); + dev->phy.roc_grant = true; wake_up(&dev->phy.roc_wait); duration = le32_to_cpu(grant->max_interval); @@ -1378,10 +1399,15 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, req.roc[i].center_chan2 = 0; req.roc[i].center_chan2_from_ap = 0; - /* STR : 0xfe indicates BAND_ALL with enabling DBDC - * EMLSR : 0xff indicates (BAND_AUTO) without DBDC - */ - req.roc[i].dbdcband = type == MT7925_ROC_REQ_JOIN ? 0xfe : 0xff; + if (is_mt7927(&mvif->phy->dev->mt76)) + req.roc[i].dbdcband = + mt7925_mt7927_hw_band_from_nl(chan->band); + else + /* STR : 0xfe indicates BAND_ALL with enabling DBDC + * EMLSR : 0xff indicates (BAND_AUTO) without DBDC + */ + req.roc[i].dbdcband = type == MT7925_ROC_REQ_JOIN ? + 0xfe : 0xff; if (chan->hw_value < center_ch) req.roc[i].sco = 1; /* SCA */ @@ -1419,7 +1445,9 @@ int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf, .bw_from_ap = CMD_CBW_20MHZ, .center_chan = center_ch, .center_chan_from_ap = center_ch, - .dbdcband = 0xff, /* auto */ + .dbdcband = is_mt7927(&dev->mt76) ? + mt7925_mt7927_hw_band_from_nl(chan->band) : + 0xff, /* auto */ }, }; @@ -1466,7 +1494,10 @@ int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf, .len = cpu_to_le16(sizeof(struct roc_abort_tlv)), .tokenid = token_id, .bss_idx = mconf->mt76.idx, - .dbdcband = 0xff, /* auto*/ + .dbdcband = is_mt7927(&dev->mt76) && + mconf->mt76.band_idx <= 1 ? + mconf->mt76.band_idx : + 0xff, /* auto */ }, }; @@ -2495,6 +2526,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, basic_req->phymode_ext = mt7925_get_phy_mode_ext(phy, vif, band, link_sta); + if (is_mt7927(phy->dev)) + mconf->mt76.band_idx = mt7925_mt7927_hw_band_from_nl(band); + if (band == NL80211_BAND_2GHZ) basic_req->nonht_basic_phy = cpu_to_le16(PHY_TYPE_ERP_INDEX); else diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h index ba3d2c4de4ce..d3c89ea0afab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h @@ -63,6 +63,11 @@ enum mt7925_roc_req { MT7925_ROC_REQ_NUM }; +static inline u8 mt7925_mt7927_hw_band_from_nl(enum nl80211_band band) +{ + return band == NL80211_BAND_2GHZ ? 0 : 1; +} + enum { UNI_EVENT_ROC_GRANT = 0, UNI_EVENT_ROC_GRANT_SUB_LINK = 4, -- 2.53.0