Add new attributes NL80211_ATTR_RU_PUNCT_BITMAP and NL80211_ATTR_RU_PUNCT_SUPP_HE to receive RU puncturing information from the userspace. - Bitmap consists of 16 bits, each bit corresponding to a 20 MHz channel in the operating bandwidth. Lowest bit corresponds to the lowest frequency. Validate the bitmap against the minimum bandwidth support advertised by the driver. - HE support flag indicates whether OFDMA puncturing patterns should be considered during validation. Signed-off-by: Aloka Dixit <quic_alokad@xxxxxxxxxxx> --- include/uapi/linux/nl80211.h | 10 ++++++++ net/wireless/nl80211.c | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b4849afede98..1cccc1e8dc29 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2667,6 +2667,14 @@ enum nl80211_commands { * the driver supports preamble puncturing, value should be of type * &enum nl80211_ru_punct_supp_bw * + * @NL80211_ATTR_RU_PUNCT_SUPP_HE: flag attribute, used to indicate that RU + * puncturing bitmap validation should include OFDMA bitmaps. + * + * @NL80211_ATTR_RU_PUNCT_BITMAP: (u16) RU puncturing bitmap where the lowest + * bit corresponds to the lowest 20 MHz channel. Each bit set to 1 + * indicates that the sub-channel is punctured, set 0 indicates that the + * channel is active. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3180,6 +3188,8 @@ enum nl80211_attrs { NL80211_ATTR_EHT_CAPABILITY, NL80211_ATTR_RU_PUNCT_SUPP_BW, + NL80211_ATTR_RU_PUNCT_SUPP_HE, + NL80211_ATTR_RU_PUNCT_BITMAP, /* add attributes here, update the policy in nl80211.c */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 3b244b96d15f..720e53917013 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -784,6 +784,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { NL80211_EHT_MAX_CAPABILITY_LEN), [NL80211_ATTR_RU_PUNCT_SUPP_BW] = NLA_POLICY_MAX(NLA_U8, NL80211_RU_PUNCT_SUPP_BW_320), + [NL80211_ATTR_RU_PUNCT_SUPP_HE] = { .type = NLA_FLAG }, + [NL80211_ATTR_RU_PUNCT_BITMAP] = { .type = NLA_U16 }, }; /* policy for the key attributes */ @@ -3117,6 +3119,46 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) wdev->iftype == NL80211_IFTYPE_P2P_GO; } +static int nl80211_parse_ru_punct_bitmap(struct cfg80211_registered_device *rdev, + struct genl_info *info, + struct cfg80211_chan_def *chandef) +{ + chandef->ru_punct_bitmap_supp_he = + nla_get_flag(info->attrs[NL80211_ATTR_RU_PUNCT_SUPP_HE]); + + chandef->ru_punct_bitmap = + nla_get_u16(info->attrs[NL80211_ATTR_RU_PUNCT_BITMAP]); + + if (!chandef->ru_punct_bitmap) + return 0; + + if (!rdev->wiphy.ru_punct_supp_bw && + (chandef->ru_punct_bitmap || chandef->ru_punct_bitmap_supp_he)) + return -EOPNOTSUPP; + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_80: + if (rdev->wiphy.ru_punct_supp_bw >= + NL80211_RU_PUNCT_SUPP_BW_160) + return -EOPNOTSUPP; + break; + + case NL80211_CHAN_WIDTH_160: + if (rdev->wiphy.ru_punct_supp_bw >= + NL80211_RU_PUNCT_SUPP_BW_320) + return -EOPNOTSUPP; + break; + + case NL80211_CHAN_WIDTH_320: + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, struct genl_info *info, struct cfg80211_chan_def *chandef) @@ -3124,6 +3166,7 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, struct netlink_ext_ack *extack = info->extack; struct nlattr **attrs = info->attrs; u32 control_freq; + int err; if (!attrs[NL80211_ATTR_WIPHY_FREQ]) return -EINVAL; @@ -3230,6 +3273,12 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, return -EINVAL; } + if (info->attrs[NL80211_ATTR_RU_PUNCT_BITMAP]) { + err = nl80211_parse_ru_punct_bitmap(rdev, info, chandef); + if (err) + return err; + } + return 0; } -- 2.31.1