* [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning
@ 2025-11-18 10:27 Felix Fietkau
2025-11-18 10:27 ` [PATCH 2/2] wifi: mt76: support upgrading passive scans to active Felix Fietkau
2025-11-18 13:46 ` [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning Ben Greear
0 siblings, 2 replies; 4+ messages in thread
From: Felix Fietkau @ 2025-11-18 10:27 UTC (permalink / raw)
To: linux-wireless; +Cc: Chad Monroe
From: Chad Monroe <chad@monroe.io>
avoid unnecessary channel switch when performing an on-channel scan
using a multi-radio device.
Fixes: c56d6edebc1f ("wifi: mt76: mt7996: use emulated hardware scan support")
Signed-off-by: Chad Monroe <chad@monroe.io>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/wireless/mediatek/mt76/scan.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c
index ff9176cdee3d..0b1922f7792e 100644
--- a/drivers/net/wireless/mediatek/mt76/scan.c
+++ b/drivers/net/wireless/mediatek/mt76/scan.c
@@ -16,7 +16,7 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)
clear_bit(MT76_SCANNING, &phy->state);
- if (dev->scan.chan && phy->main_chandef.chan &&
+ if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel &&
!test_bit(MT76_MCU_RESET, &dev->phy.state))
mt76_set_channel(phy, &phy->main_chandef, false);
mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);
@@ -94,7 +94,7 @@ void mt76_scan_work(struct work_struct *work)
return;
}
- if (dev->scan.chan && phy->num_sta) {
+ if (dev->scan.chan && phy->num_sta && phy->offchannel) {
dev->scan.chan = NULL;
mt76_set_channel(phy, &phy->main_chandef, false);
goto out;
@@ -102,20 +102,22 @@ void mt76_scan_work(struct work_struct *work)
dev->scan.chan = req->channels[dev->scan.chan_idx++];
cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20);
- mt76_set_channel(phy, &chandef, true);
+ if (dev->scan.chan != phy->main_chandef.chan)
+ mt76_set_channel(phy, &chandef, true);
if (!req->n_ssids ||
chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
goto out;
- duration = HZ / 16; /* ~60 ms */
+ if (phy->offchannel)
+ duration = HZ / 16; /* ~60 ms */
local_bh_disable();
for (i = 0; i < req->n_ssids; i++)
mt76_scan_send_probe(dev, &req->ssids[i]);
local_bh_enable();
out:
- if (dev->scan.chan)
+ if (dev->scan.chan && phy->offchannel)
duration = max_t(int, duration,
msecs_to_jiffies(req->duration +
(req->duration >> 5)));
--
2.51.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] wifi: mt76: support upgrading passive scans to active
2025-11-18 10:27 [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning Felix Fietkau
@ 2025-11-18 10:27 ` Felix Fietkau
2025-11-18 13:46 ` [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning Ben Greear
1 sibling, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2025-11-18 10:27 UTC (permalink / raw)
To: linux-wireless; +Cc: Chad Monroe, Piotr Kubik
From: Chad Monroe <chad@monroe.io>
On channels with NO_IR or RADAR flags, wait for beacon before sending
probe requests. Allows active scanning and WPS on restricted channels
if another AP is already present.
Fixes: c56d6edebc1f ("wifi: mt76: mt7996: use emulated hardware scan support")
Tested-by: Piotr Kubik <piotr.kubik@adtran.com>
Signed-off-by: Chad Monroe <chad@monroe.io>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++
.../net/wireless/mediatek/mt76/mt7996/mac.c | 3 ++
drivers/net/wireless/mediatek/mt76/scan.c | 34 +++++++++++++++++--
3 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 0c067b14a900..8125d9fd11fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1012,6 +1012,8 @@ struct mt76_dev {
struct mt76_vif_link *mlink;
struct mt76_phy *phy;
int chan_idx;
+ bool beacon_wait;
+ bool beacon_received;
} scan;
#ifdef CONFIG_NL80211_TESTMODE
@@ -1599,6 +1601,7 @@ int mt76_get_rate(struct mt76_dev *dev,
int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req);
void mt76_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void mt76_scan_rx_beacon(struct mt76_dev *dev, struct ieee80211_channel *chan);
void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const u8 *mac);
void mt76_sw_scan_complete(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 2560e2f46e89..11cbcf82460e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -554,6 +554,9 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
qos_ctl = FIELD_GET(MT_RXD10_QOS_CTL, v2);
seq_ctrl = FIELD_GET(MT_RXD10_SEQ_CTRL, v2);
+ if (ieee80211_is_beacon(fc))
+ mt76_scan_rx_beacon(&dev->mt76, mphy->chandef.chan);
+
rxd += 4;
if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL;
diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c
index 0b1922f7792e..5746aeb3e608 100644
--- a/drivers/net/wireless/mediatek/mt76/scan.c
+++ b/drivers/net/wireless/mediatek/mt76/scan.c
@@ -79,6 +79,23 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
rcu_read_unlock();
}
+void mt76_scan_rx_beacon(struct mt76_dev *dev, struct ieee80211_channel *chan)
+{
+ struct mt76_phy *phy;
+
+ if (!dev->scan.beacon_wait || dev->scan.beacon_received ||
+ dev->scan.chan != chan)
+ return;
+
+ phy = dev->scan.phy;
+ if (!phy)
+ return;
+
+ dev->scan.beacon_received = true;
+ ieee80211_queue_delayed_work(phy->hw, &dev->scan_work, 0);
+}
+EXPORT_SYMBOL_GPL(mt76_scan_rx_beacon);
+
void mt76_scan_work(struct work_struct *work)
{
struct mt76_dev *dev = container_of(work, struct mt76_dev,
@@ -87,8 +104,15 @@ void mt76_scan_work(struct work_struct *work)
struct cfg80211_chan_def chandef = {};
struct mt76_phy *phy = dev->scan.phy;
int duration = HZ / 9; /* ~110 ms */
+ bool beacon_rx;
int i;
+ beacon_rx = dev->scan.beacon_wait && dev->scan.beacon_received;
+ dev->scan.beacon_wait = false;
+
+ if (beacon_rx)
+ goto probe;
+
if (dev->scan.chan_idx >= req->n_channels) {
mt76_scan_complete(dev, false);
return;
@@ -105,10 +129,16 @@ void mt76_scan_work(struct work_struct *work)
if (dev->scan.chan != phy->main_chandef.chan)
mt76_set_channel(phy, &chandef, true);
- if (!req->n_ssids ||
- chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
+ if (!req->n_ssids)
goto out;
+ if (chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) {
+ dev->scan.beacon_received = false;
+ dev->scan.beacon_wait = true;
+ goto out;
+ }
+
+probe:
if (phy->offchannel)
duration = HZ / 16; /* ~60 ms */
local_bh_disable();
--
2.51.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning
2025-11-18 10:27 [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning Felix Fietkau
2025-11-18 10:27 ` [PATCH 2/2] wifi: mt76: support upgrading passive scans to active Felix Fietkau
@ 2025-11-18 13:46 ` Ben Greear
2025-11-18 16:47 ` Ben Greear
1 sibling, 1 reply; 4+ messages in thread
From: Ben Greear @ 2025-11-18 13:46 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless; +Cc: Chad Monroe
On 11/18/25 2:27 AM, Felix Fietkau wrote:
> From: Chad Monroe <chad@monroe.io>
>
> avoid unnecessary channel switch when performing an on-channel scan
> using a multi-radio device.
>
> Fixes: c56d6edebc1f ("wifi: mt76: mt7996: use emulated hardware scan support")
> Signed-off-by: Chad Monroe <chad@monroe.io>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---
> drivers/net/wireless/mediatek/mt76/scan.c | 12 +++++++-----
> 1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c
> index ff9176cdee3d..0b1922f7792e 100644
> --- a/drivers/net/wireless/mediatek/mt76/scan.c
> +++ b/drivers/net/wireless/mediatek/mt76/scan.c
> @@ -16,7 +16,7 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)
>
> clear_bit(MT76_SCANNING, &phy->state);
>
> - if (dev->scan.chan && phy->main_chandef.chan &&
> + if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel &&
> !test_bit(MT76_MCU_RESET, &dev->phy.state))
> mt76_set_channel(phy, &phy->main_chandef, false);
> mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);
> @@ -94,7 +94,7 @@ void mt76_scan_work(struct work_struct *work)
> return;
> }
>
> - if (dev->scan.chan && phy->num_sta) {
> + if (dev->scan.chan && phy->num_sta && phy->offchannel) {
> dev->scan.chan = NULL;
> mt76_set_channel(phy, &phy->main_chandef, false);
> goto out;
> @@ -102,20 +102,22 @@ void mt76_scan_work(struct work_struct *work)
>
> dev->scan.chan = req->channels[dev->scan.chan_idx++];
> cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20);
> - mt76_set_channel(phy, &chandef, true);
> + if (dev->scan.chan != phy->main_chandef.chan)
> + mt76_set_channel(phy, &chandef, true);
Do you still need to call the cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20);
method above if scan.chan == main_chandef.chan?
Thanks,
Ben
>
> if (!req->n_ssids ||
> chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
> goto out;
>
> - duration = HZ / 16; /* ~60 ms */
> + if (phy->offchannel)
> + duration = HZ / 16; /* ~60 ms */
> local_bh_disable();
> for (i = 0; i < req->n_ssids; i++)
> mt76_scan_send_probe(dev, &req->ssids[i]);
> local_bh_enable();
>
> out:
> - if (dev->scan.chan)
> + if (dev->scan.chan && phy->offchannel)
> duration = max_t(int, duration,
> msecs_to_jiffies(req->duration +
> (req->duration >> 5)));
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning
2025-11-18 13:46 ` [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning Ben Greear
@ 2025-11-18 16:47 ` Ben Greear
0 siblings, 0 replies; 4+ messages in thread
From: Ben Greear @ 2025-11-18 16:47 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless; +Cc: Chad Monroe
On 11/18/25 5:46 AM, Ben Greear wrote:
> On 11/18/25 2:27 AM, Felix Fietkau wrote:
>> From: Chad Monroe <chad@monroe.io>
>>
>> avoid unnecessary channel switch when performing an on-channel scan
>> using a multi-radio device.
>>
>> Fixes: c56d6edebc1f ("wifi: mt76: mt7996: use emulated hardware scan support")
>> Signed-off-by: Chad Monroe <chad@monroe.io>
>> Signed-off-by: Felix Fietkau <nbd@nbd.name>
>> ---
>> drivers/net/wireless/mediatek/mt76/scan.c | 12 +++++++-----
>> 1 file changed, 7 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c
>> index ff9176cdee3d..0b1922f7792e 100644
>> --- a/drivers/net/wireless/mediatek/mt76/scan.c
>> +++ b/drivers/net/wireless/mediatek/mt76/scan.c
>> @@ -16,7 +16,7 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)
>> clear_bit(MT76_SCANNING, &phy->state);
>> - if (dev->scan.chan && phy->main_chandef.chan &&
>> + if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel &&
>> !test_bit(MT76_MCU_RESET, &dev->phy.state))
>> mt76_set_channel(phy, &phy->main_chandef, false);
>> mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);
>> @@ -94,7 +94,7 @@ void mt76_scan_work(struct work_struct *work)
>> return;
>> }
>> - if (dev->scan.chan && phy->num_sta) {
>> + if (dev->scan.chan && phy->num_sta && phy->offchannel) {
>> dev->scan.chan = NULL;
>> mt76_set_channel(phy, &phy->main_chandef, false);
>> goto out;
>> @@ -102,20 +102,22 @@ void mt76_scan_work(struct work_struct *work)
>> dev->scan.chan = req->channels[dev->scan.chan_idx++];
>> cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20);
>> - mt76_set_channel(phy, &chandef, true);
>> + if (dev->scan.chan != phy->main_chandef.chan)
>> + mt76_set_channel(phy, &chandef, true);
>
> Do you still need to call the cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20);
> method above if scan.chan == main_chandef.chan?
>
> Thanks,
> Ben
Nevermind, I see why you need it.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-11-18 16:47 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-18 10:27 [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning Felix Fietkau
2025-11-18 10:27 ` [PATCH 2/2] wifi: mt76: support upgrading passive scans to active Felix Fietkau
2025-11-18 13:46 ` [PATCH 1/2] wifi: mt76: fix multi-radio on-channel scanning Ben Greear
2025-11-18 16:47 ` Ben Greear
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox