* [PATCH mt76 v2] wifi: mt76: fix handling channel context with different bands in mt76_switch_vif_chanctx()
@ 2026-07-20 9:01 Shayne Chen
0 siblings, 0 replies; only message in thread
From: Shayne Chen @ 2026-07-20 9:01 UTC (permalink / raw)
To: Felix Fietkau
Cc: linux-wireless, Lorenzo Bianconi, Ryder Lee, Evelyn Tsai,
Money Wang, linux-mediatek, Shayne Chen, Rex Lu
When performing channel switches on different radios within a short
timeframe, channel contexts with different bands can be carried for
each struct ieee80211_vif_chanctx_switch.
Rework mt76_switch_vif_chanctx() to properly handle this scenario.
Fixes: 82334623af0c ("wifi: mt76: add chanctx functions for multi-channel phy support")
Co-developed-by: Rex Lu <rex.lu@mediatek.com>
Signed-off-by: Rex Lu <rex.lu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
v2:
- prevent from doing duplicated works if need_update[band] is marked
---
drivers/net/wireless/mediatek/mt76/channel.c | 92 +++++++++++---------
1 file changed, 49 insertions(+), 43 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/channel.c b/drivers/net/wireless/mediatek/mt76/channel.c
index 6edcb3b8f279..28ad7bcaffd4 100644
--- a/drivers/net/wireless/mediatek/mt76/channel.c
+++ b/drivers/net/wireless/mediatek/mt76/channel.c
@@ -186,68 +186,74 @@ int mt76_switch_vif_chanctx(struct ieee80211_hw *hw,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode)
{
- struct mt76_chanctx *old_ctx = (struct mt76_chanctx *)vifs->old_ctx->drv_priv;
- struct mt76_chanctx *new_ctx = (struct mt76_chanctx *)vifs->new_ctx->drv_priv;
- struct ieee80211_chanctx_conf *conf = vifs->new_ctx;
- struct mt76_phy *old_phy = old_ctx->phy;
- struct mt76_phy *phy = hw->priv;
+ struct ieee80211_vif_chanctx_switch *v;
+ struct mt76_chanctx *old_ctx, *new_ctx;
+ struct mt76_phy *old_phy, *phy = hw->priv;
struct mt76_dev *dev = phy->dev;
struct mt76_vif_link *mlink;
- bool update_chan;
+ bool need_update[__MT_MAX_BAND] = {};
int i, ret = 0;
- if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS)
- phy = new_ctx->phy = dev->band_phys[conf->def.chan->band];
- else
- phy = new_ctx->phy;
- if (!phy)
- return -EINVAL;
+ for (i = 0; i < n_vifs; i++) {
+ v = &vifs[i];
+ new_ctx = (struct mt76_chanctx *)v->new_ctx->drv_priv;
+ if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS)
+ phy = new_ctx->phy = dev->band_phys[v->new_ctx->def.chan->band];
+ else
+ phy = new_ctx->phy;
- update_chan = phy->chanctx != new_ctx;
- if (update_chan) {
- if (dev->scan.phy == phy)
- mt76_abort_scan(dev);
+ if (!phy)
+ return -EINVAL;
- cancel_delayed_work_sync(&phy->mac_work);
+ if (need_update[phy->band_idx])
+ continue;
+
+ if (phy->chanctx != new_ctx) {
+ if (dev->scan.phy == phy)
+ mt76_abort_scan(dev);
+
+ cancel_delayed_work_sync(&phy->mac_work);
+ need_update[phy->band_idx] = true;
+ }
}
mutex_lock(&dev->mutex);
- if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS &&
- phy != old_phy && old_phy->chanctx == old_ctx)
- old_phy->chanctx = NULL;
+ for (i = 0; i < n_vifs; i++) {
+ v = &vifs[i];
+ old_ctx = (struct mt76_chanctx *)v->old_ctx->drv_priv;
+ old_phy = old_ctx->phy;
+
+ new_ctx = (struct mt76_chanctx *)v->new_ctx->drv_priv;
+ phy = new_ctx->phy;
- if (update_chan)
- ret = mt76_phy_update_channel(phy, vifs->new_ctx);
+ if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS && old_phy->chanctx &&
+ old_phy->chanctx == old_ctx && phy != old_phy)
+ old_phy->chanctx = NULL;
- if (ret)
- goto out;
+ if (need_update[phy->band_idx]) {
+ ret = mt76_phy_update_channel(phy, v->new_ctx);
+ if (ret)
+ goto out;
- if (old_phy == phy)
- goto skip_link_replace;
+ need_update[phy->band_idx] = false;
+ }
- for (i = 0; i < n_vifs; i++) {
- mlink = mt76_vif_conf_link(dev, vifs[i].vif, vifs[i].link_conf);
+ mlink = mt76_vif_conf_link(dev, v->vif, v->link_conf);
if (!mlink)
continue;
- dev->drv->vif_link_remove(old_phy, vifs[i].vif,
- vifs[i].link_conf, mlink);
-
- ret = dev->drv->vif_link_add(phy, vifs[i].vif,
- vifs[i].link_conf, mlink);
- if (ret)
- goto out;
-
- }
+ if (old_phy != phy) {
+ dev->drv->vif_link_remove(old_phy, v->vif, v->link_conf,
+ mlink);
-skip_link_replace:
- for (i = 0; i < n_vifs; i++) {
- mlink = mt76_vif_conf_link(dev, vifs[i].vif, vifs[i].link_conf);
- if (!mlink)
- continue;
+ ret = dev->drv->vif_link_add(phy, v->vif, v->link_conf,
+ mlink);
+ if (ret)
+ goto out;
+ }
- mlink->ctx = vifs->new_ctx;
+ mlink->ctx = v->new_ctx;
if (mlink->beacon_mon_interval)
WRITE_ONCE(mlink->beacon_mon_last, jiffies);
}
--
2.51.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-20 9:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 9:01 [PATCH mt76 v2] wifi: mt76: fix handling channel context with different bands in mt76_switch_vif_chanctx() Shayne Chen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox