From: Aditya Kumar Singh <aditya.kumar.singh@xxxxxxxxxxxxxxxx> In cfg80211_off_channel_oper_allowed(), the current logic disallows off-channel operations if any link operates on a radar channel, assuming such channels cannot be vacated. This assumption holds for non-MLO interfaces but not for MLO. With MLO and multi-radio devices, different links may operate on separate radios. This allows one link to scan off-channel while another remains on a radar channel. For example, in a 5 GHz split-phy setup, the lower band can scan while the upper band stays on a radar channel. Off-channel operations can be allowed if the radio/link onto which the input channel falls is different from the radio/link which has an active radar channel. Therefore, fix cfg80211_off_channel_oper_allowed() by returning false only if the requested channel maps to the same radio as an active radar channel. Allow off-channel operations when the requested channel is on a different radio, as in MLO with multi-radio setups. Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@xxxxxxxxxxxxxxxx> Signed-off-by: Amith A <quic_amitajit@xxxxxxxxxxx> --- Chnages in v2: - Fixed Johannes's comment to return constants where possible instead of variables and also simplified the logic of matching the radio of the input channel and the radio of the radar channel net/wireless/nl80211.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 70ca74a75f22..9286a7195d53 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9758,6 +9758,7 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, { unsigned int link_id; bool all_ok = true; + int radio_idx; lockdep_assert_wiphy(wdev->wiphy); @@ -9767,8 +9768,10 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, if (!cfg80211_beaconing_iface_active(wdev)) return true; + radio_idx = cfg80211_get_radio_idx_by_chan(wdev->wiphy, chan); + /* - * FIXME: check if we have a free HW resource/link for chan + * FIXME: check if we have a free radio/link for chan * * This, as well as the FIXME below, requires knowing the link * capabilities of the hardware. @@ -9777,20 +9780,28 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, /* we cannot leave radar channels */ for_each_valid_link(wdev, link_id) { struct cfg80211_chan_def *chandef; + int link_radio_idx; chandef = wdev_chandef(wdev, link_id); if (!chandef || !chandef->chan) continue; + if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) + continue; + /* - * FIXME: don't require all_ok, but rather check only the - * correct HW resource/link onto which 'chan' falls, - * as only that link leaves the channel for doing - * the off-channel operation. + * chandef->chan is a radar channel. If the radio/link onto + * which this radar channel falls is the same radio/link onto + * which the input 'chan' falls, off-channel operation should + * not be allowed. Hence, set 'all_ok' to false. */ - if (chandef->chan->flags & IEEE80211_CHAN_RADAR) + link_radio_idx = cfg80211_get_radio_idx_by_chan(wdev->wiphy, + chandef->chan); + if (link_radio_idx == radio_idx) { all_ok = false; + break; + } } if (all_ok) base-commit: 28aa52b6189f1cc409f96910c63fa1b99370b99e -- 2.34.1