[PATCH wireless v2] wifi: mt76: move the channel survey when the channel changes

Chris hoopyfrood42 at gmail.com
Wed Sep 30 18:25:41 PDT 2026


On Wed, Sep 30, 2026 at 8:35 PM Devin Wittmayer
<lucid_duck at justthetip.ca> wrote:
>
> mt7921 and mt7925 report every survey counter against one channel and
> never mark the one in use. Both use channel contexts, so the code that
> moves the survey never runs.
>
> Move it when a context is assigned or changed, after booking the time
> spent on the old channel.
>
> Tested on MT7922 over PCIe, MT7921AU and MT7925 over USB.
>
> Fixes: 41ac53c899bd ("wifi: mt76: mt7921: introduce chanctx support")
> Cc: stable at vger.kernel.org
> Reported-by: Chris <hoopyfrood42 at gmail.com>
> Closes: https://lore.kernel.org/linux-wireless/CAHaeJsT8O8Nhq351hFp3NAL8e0iU85N-LBdYZ9nYHFHVy7t_hQ@mail.gmail.com/
>
> Signed-off-by: Devin Wittmayer <lucid_duck at justthetip.ca>
> ---
> v2: aim it at the wireless tree and tag it for stable. No code change.
>
>  drivers/net/wireless/mediatek/mt76/mac80211.c   | 17 +++++++++++++++++
>  drivers/net/wireless/mediatek/mt76/mt76.h       |  2 ++
>  .../net/wireless/mediatek/mt76/mt7921/main.c    |  1 +
>  .../net/wireless/mediatek/mt76/mt7925/main.c    |  2 ++
>  .../net/wireless/mediatek/mt76/mt792x_core.c    |  1 +
>  5 files changed, 23 insertions(+)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
> index abbe65cbcd89..fdfdb324ab98 100644
> --- a/drivers/net/wireless/mediatek/mt76/mac80211.c
> +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
> @@ -1045,6 +1045,23 @@ void mt76_update_survey(struct mt76_phy *phy)
>  }
>  EXPORT_SYMBOL_GPL(mt76_update_survey);
>
> +/* For drivers that retune without __mt76_set_channel(): book the time spent
> + * on the old channel before moving the survey to the new one.
> + */
> +void mt76_set_survey_channel(struct mt76_phy *phy,
> +                            struct cfg80211_chan_def *chandef)
> +{
> +       if (!chandef->chan)
> +               return;
> +
> +       mt76_update_survey(phy);
> +
> +       phy->chandef = *chandef;
> +       phy->main_chandef = *chandef;
> +       phy->chan_state = mt76_channel_state(phy, chandef->chan);
> +}
> +EXPORT_SYMBOL_GPL(mt76_set_survey_channel);
> +
>  int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
>                        bool offchannel)
>  {
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 62b41c8bb7c0..2cbe9884ab46 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -1548,6 +1548,8 @@ void mt76_sta_ps_transition(struct mt76_dev *dev, struct mt76_wcid *wcid,
>  bool mt76_has_tx_pending(struct mt76_phy *phy);
>  int mt76_update_channel(struct mt76_phy *phy);
>  void mt76_update_survey(struct mt76_phy *phy);
> +void mt76_set_survey_channel(struct mt76_phy *phy,
> +                            struct cfg80211_chan_def *chandef);
>  void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time);
>  int mt76_get_survey(struct ieee80211_hw *hw, int idx,
>                     struct survey_info *survey);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> index 68a059504e83..915d6789c668 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> @@ -1423,6 +1423,7 @@ mt7921_change_chanctx(struct ieee80211_hw *hw,
>         } else {
>                 mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->bss_conf.mt76, ctx);
>         }
> +       mt76_set_survey_channel(mvif->phy->mt76, &ctx->def);
>         mt792x_mutex_release(phy->dev);
>  }
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> index 5993b31e1aae..e21bd79dcc56 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> @@ -2063,6 +2063,7 @@ mt7925_change_chanctx(struct ieee80211_hw *hw,
>                                                       link_conf, ctx);
>                 }
>         }
> +       mt76_set_survey_channel(mvif->phy->mt76, &ctx->def);
>
>         mt792x_mutex_release(phy->dev);
>  }
> @@ -2399,6 +2400,7 @@ static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,
>
>         mconf->mt76.ctx = ctx;
>         mctx->bss_conf = mconf;
> +       mt76_set_survey_channel(mvif->phy->mt76, &ctx->def);
>         mutex_unlock(&dev->mt76.mutex);
>
>         return 0;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> index 0ad33f74c228..6a0d5b2c2d59 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> @@ -472,6 +472,7 @@ int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw,
>         mutex_lock(&dev->mt76.mutex);
>         mvif->bss_conf.mt76.ctx = ctx;
>         mctx->bss_conf = &mvif->bss_conf;
> +       mt76_set_survey_channel(&dev->mphy, &ctx->def);
>         mutex_unlock(&dev->mt76.mutex);
>
>         return 0;
> --
> 2.55.0
>

Tested on a Netgear A9000 (MT7925, USB 0846:9072) in monitor mode,
Ubuntu 7.0.0-34 with the patch backported (the mt7921 hunk needed
rebasing for the older brace-less if/else). Before: tuned to 2437 and
then 5180 MHz, every counter stayed on 5955 MHz and no channel was
marked in use. After: each of 2412/2437/2462/5180/5745/5955/6115 MHz
is "[in use]" while tuned, gets its own active time (~4.2 s per 4 s
dwell), keeps it when left and resumes on return.

The busy half of the report is unchanged: busy still grows by 0xADBEEF
µs (11,386.6 ms) per update, now on the right channel. So the MIB busy
register read is still returning 0xDEADBEEF on this chip.

Tested-by: Chris hoopyfrood42 at gmail.com



More information about the Linux-mediatek mailing list