From: Johannes Berg Add a cfg80211_chandef_add_npca() helper function that takes an existing chandef without NPCA and sets the NPCA information from the format used in UHR operation and UHR Parameters Update. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 13 ++++++++++++ net/wireless/chan.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9e66490dab4f..2546567792e2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1150,6 +1150,19 @@ int cfg80211_chandef_primary(const struct cfg80211_chan_def *chandef, enum nl80211_chan_width primary_chan_width, u16 *punctured); +/** + * cfg80211_chandef_add_npca - parse and add NPCA information to chandef + * @wiphy: the wiphy this will be used for, for channel pointer lookup + * @chandef: the chandef to modify, must be a valid chandef without NPCA + * @npca: the NPCA information, can be %NULL + * + * Returns: 0 if the NPCA information was added and the resulting + * chandef is valid, a negative error code on errors + */ +int cfg80211_chandef_add_npca(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef, + const struct ieee80211_uhr_npca_info *npca); + /** * nl80211_send_chandef - sends the channel definition. * @msg: the msg to send channel definition diff --git a/net/wireless/chan.c b/net/wireless/chan.c index fae71f2d13ed..70fec444955e 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -556,6 +556,52 @@ int cfg80211_chandef_primary(const struct cfg80211_chan_def *c, } EXPORT_SYMBOL(cfg80211_chandef_primary); +int cfg80211_chandef_add_npca(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef, + const struct ieee80211_uhr_npca_info *npca) +{ + struct cfg80211_chan_def new_chandef = *chandef; + u32 width, npca_freq; + u8 offs; + + if (chandef->npca_chan || chandef->npca_punctured) + return -EINVAL; + + if (WARN_ON(!cfg80211_chandef_valid(chandef))) + return -EINVAL; + + if (!npca) + return 0; + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_80: + case NL80211_CHAN_WIDTH_160: + case NL80211_CHAN_WIDTH_320: + break; + default: + return -EINVAL; + } + + offs = le32_get_bits(npca->params, + IEEE80211_UHR_NPCA_PARAMS_PRIMARY_CHAN_OFFS); + + width = cfg80211_chandef_get_width(chandef); + npca_freq = chandef->center_freq1 - width / 2 + 10 + 20 * offs; + new_chandef.npca_chan = ieee80211_get_channel(wiphy, npca_freq); + if (!new_chandef.npca_chan) + return -EINVAL; + + if (npca->params & cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES)) + new_chandef.npca_punctured = le16_to_cpu(npca->dis_subch_bmap[0]); + + if (!cfg80211_chandef_valid(&new_chandef)) + return -EINVAL; + + *chandef = new_chandef; + return 0; +} +EXPORT_SYMBOL(cfg80211_chandef_add_npca); + static const struct cfg80211_chan_def * check_chandef_primary_compat(const struct cfg80211_chan_def *c1, const struct cfg80211_chan_def *c2, -- 2.53.0