diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e807999fc8e8..ddcf559430dd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -849,6 +849,10 @@ struct key_params { * struct cfg80211_chan_def - channel definition * @chan: the (control) channel * @npca_chan: the NPCA primary channel + * Note that if DBE is in use, this channel may appear to be + * inside the primary half of the chandef. Implementations + * can use the position of this channel to understand how + * NPCA is used. * @width: channel width * @center_freq1: center frequency of first segment * @center_freq2: center frequency of second segment @@ -864,6 +868,8 @@ struct key_params { * @npca_punctured: NPCA puncturing bitmap, like @punctured but for * NPCA transmissions. If NPCA is used (@npca_chan is not %NULL) * this will be a superset of the @punctured bimap. + * Note that if DBE is used, this bitmap is also shifted to be in + * accordance with the overall chandef bandwidth. * @s1g_primary_2mhz: Indicates if the control channel pointed to * by 'chan' exists as a 1MHz primary subchannel within an * S1G 2MHz primary channel. @@ -1154,6 +1160,23 @@ int cfg80211_chandef_primary(const struct cfg80211_chan_def *chandef, enum nl80211_chan_width primary_chan_width, u16 *punctured); +/** + * cfg80211_chandef_npca_valid - check that NPCA information is valid + * @wiphy: the wiphy to check for, for channel pointer lookup + * @chandef: the BSS channel chandef to check against + * @npca: NPCA information, can be %NULL in which case this + * always returns %true + * + * Note that DBE must not have been configured into the chandef yet + * before checking NPCA, i.e. @chandef must represent the BSS channel. + * + * Returns: %true if the NPCA channel and puncturing bitmap are valid + * according to the chandef, %false otherwise + */ +bool cfg80211_chandef_npca_valid(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, + const struct ieee80211_uhr_npca_info *npca); + /** * cfg80211_chandef_add_npca - parse and add NPCA information to chandef * @wiphy: the wiphy this will be used for, for channel pointer lookup diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3db8a499a1c8..a818568d34b9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -406,7 +406,10 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata, npca = ieee80211_uhr_npca_info(uhr_oper); - if (cfg80211_chandef_add_npca(sdata->local->hw.wiphy, + /* DBE is not considered yet, so this works */ + if (!cfg80211_chandef_npca_valid(sdata->local->hw.wiphy, + &npca_chandef, npca) || + cfg80211_chandef_add_npca(sdata->local->hw.wiphy, &npca_chandef, npca)) { sdata_info(sdata, "AP UHR NPCA settings invalid, disabling UHR\n"); diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 5289a4ddacd6..ed35b55b1b67 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -460,9 +460,6 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) return false; if (chandef->npca_chan) { - bool pri_upper, npca_upper; - u32 cf1; - switch (chandef->width) { case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_160: @@ -471,24 +468,6 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) default: return false; } - - if (!cfg80211_chandef_valid_control_freq(chandef, - chandef->npca_chan->center_freq)) - return false; - - cf1 = chandef->center_freq1; - pri_upper = chandef->chan->center_freq > cf1; - npca_upper = chandef->npca_chan->center_freq > cf1; - - if (pri_upper == npca_upper) - return false; - - if (!valid_puncturing_bitmap(chandef, - chandef->npca_chan->center_freq, - chandef->npca_punctured) || - (chandef->punctured & chandef->npca_punctured) != - chandef->punctured) - return false; } else if (chandef->npca_punctured) { return false; } @@ -556,6 +535,44 @@ int cfg80211_chandef_primary(const struct cfg80211_chan_def *c, } EXPORT_SYMBOL(cfg80211_chandef_primary); +bool cfg80211_chandef_npca_valid(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, + const struct ieee80211_uhr_npca_info *npca) +{ + struct cfg80211_chan_def tmp = *chandef; + bool pri_upper, npca_upper; + u32 cf1; + + if (chandef->npca_chan || chandef->npca_punctured) + return false; + + if (!npca) + return true; + + if (cfg80211_chandef_add_npca(wiphy, &tmp, npca)) + return false; + + if (!cfg80211_chandef_valid_control_freq(&tmp, + tmp.npca_chan->center_freq)) + return false; + + cf1 = tmp.center_freq1; + pri_upper = tmp.chan->center_freq > cf1; + npca_upper = tmp.npca_chan->center_freq > cf1; + + if (pri_upper == npca_upper) + return false; + + if (!valid_puncturing_bitmap(&tmp, + tmp.npca_chan->center_freq, + tmp.npca_punctured) || + (tmp.punctured & tmp.npca_punctured) != tmp.punctured) + return false; + + return true; +} +EXPORT_SYMBOL(cfg80211_chandef_npca_valid); + int cfg80211_chandef_add_npca(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, const struct ieee80211_uhr_npca_info *npca)