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> --- net/wireless/nl80211.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 70ca74a75f22..395794dba0a7 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); @@ -9765,10 +9766,16 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, return false; if (!cfg80211_beaconing_iface_active(wdev)) - return true; + return all_ok; + + if (wdev->valid_links) { + radio_idx = cfg80211_get_radio_idx_by_chan(wdev->wiphy, chan); + if (radio_idx < 0) + return !all_ok; + } /* - * 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 +9784,33 @@ 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) + if (wdev->valid_links) { + link_radio_idx = cfg80211_get_radio_idx_by_chan(wdev->wiphy, + chandef->chan); + if (link_radio_idx < 0 || + link_radio_idx == radio_idx) { + all_ok = false; + break; + } + } else { all_ok = false; + } } if (all_ok) base-commit: 28aa52b6189f1cc409f96910c63fa1b99370b99e -- 2.34.1