6a84feeeba28a5f39ed0a879b0df6768f9725435
[librecmc/librecmc.git] /
1 From d7c1a9a0ed180d8884798ce97afe7283622a484f Mon Sep 17 00:00:00 2001
2 From: Aloka Dixit <quic_alokad@quicinc.com>
3 Date: Mon, 30 Jan 2023 16:12:25 -0800
4 Subject: [PATCH] wifi: nl80211: validate and configure puncturing bitmap
5
6 - New feature flag, NL80211_EXT_FEATURE_PUNCT, to advertise
7   driver support for preamble puncturing in AP mode.
8 - New attribute, NL80211_ATTR_PUNCT_BITMAP, to receive a puncturing
9   bitmap from the userspace during AP bring up (NL80211_CMD_START_AP)
10   and channel switch (NL80211_CMD_CHANNEL_SWITCH) operations. Each bit
11   corresponds to a 20 MHz channel in the operating bandwidth, lowest
12   bit for the lowest channel. Bit set to 1 indicates that the channel
13   is punctured. Higher 16 bits are reserved.
14 - New members added to structures cfg80211_ap_settings and
15   cfg80211_csa_settings to propagate the bitmap to the driver after
16   validation.
17
18 Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
19 Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
20 Link: https://lore.kernel.org/r/20230131001227.25014-3-quic_alokad@quicinc.com
21 [move validation against 0xffff into policy]
22 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
23 ---
24  include/net/cfg80211.h       |  8 ++++++++
25  include/uapi/linux/nl80211.h | 11 +++++++++++
26  net/wireless/nl80211.c       | 32 ++++++++++++++++++++++++++++++++
27  3 files changed, 51 insertions(+)
28
29 --- a/include/net/cfg80211.h
30 +++ b/include/net/cfg80211.h
31 @@ -1330,6 +1330,9 @@ struct cfg80211_unsol_bcast_probe_resp {
32   * @fils_discovery: FILS discovery transmission parameters
33   * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
34   * @mbssid_config: AP settings for multiple bssid
35 + * @punct_bitmap: Preamble puncturing bitmap. Each bit represents
36 + *     a 20 MHz channel, lowest bit corresponding to the lowest channel.
37 + *     Bit set to 1 indicates that the channel is punctured.
38   */
39  struct cfg80211_ap_settings {
40         struct cfg80211_chan_def chandef;
41 @@ -1364,6 +1367,7 @@ struct cfg80211_ap_settings {
42         struct cfg80211_fils_discovery fils_discovery;
43         struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
44         struct cfg80211_mbssid_config mbssid_config;
45 +       u16 punct_bitmap;
46  };
47  
48  /**
49 @@ -1381,6 +1385,9 @@ struct cfg80211_ap_settings {
50   * @radar_required: whether radar detection is required on the new channel
51   * @block_tx: whether transmissions should be blocked while changing
52   * @count: number of beacons until switch
53 + * @punct_bitmap: Preamble puncturing bitmap. Each bit represents
54 + *     a 20 MHz channel, lowest bit corresponding to the lowest channel.
55 + *     Bit set to 1 indicates that the channel is punctured.
56   */
57  struct cfg80211_csa_settings {
58         struct cfg80211_chan_def chandef;
59 @@ -1393,6 +1400,7 @@ struct cfg80211_csa_settings {
60         bool radar_required;
61         bool block_tx;
62         u8 count;
63 +       u16 punct_bitmap;
64  };
65  
66  /**
67 --- a/include/uapi/linux/nl80211.h
68 +++ b/include/uapi/linux/nl80211.h
69 @@ -2751,6 +2751,12 @@ enum nl80211_commands {
70   *     the incoming frame RX timestamp.
71   * @NL80211_ATTR_TD_BITMAP: Transition Disable bitmap, for subsequent
72   *     (re)associations.
73 + *
74 + * @NL80211_ATTR_PUNCT_BITMAP: (u32) Preamble puncturing bitmap, lowest
75 + *     bit corresponds to the lowest 20 MHz channel. Each bit set to 1
76 + *     indicates that the sub-channel is punctured. Higher 16 bits are
77 + *     reserved.
78 + *
79   * @NUM_NL80211_ATTR: total number of nl80211_attrs available
80   * @NL80211_ATTR_MAX: highest attribute number currently defined
81   * @__NL80211_ATTR_AFTER_LAST: internal use
82 @@ -3280,6 +3286,8 @@ enum nl80211_attrs {
83         NL80211_ATTR_RX_HW_TIMESTAMP,
84         NL80211_ATTR_TD_BITMAP,
85  
86 +       NL80211_ATTR_PUNCT_BITMAP,
87 +
88         /* add attributes here, update the policy in nl80211.c */
89  
90         __NL80211_ATTR_AFTER_LAST,
91 @@ -6294,6 +6302,8 @@ enum nl80211_feature_flags {
92   *     might apply, e.g. no scans in progress, no offchannel operations
93   *     in progress, and no active connections.
94   *
95 + * @NL80211_EXT_FEATURE_PUNCT: Driver supports preamble puncturing in AP mode.
96 + *
97   * @NUM_NL80211_EXT_FEATURES: number of extended features.
98   * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
99   */
100 @@ -6362,6 +6372,7 @@ enum nl80211_ext_feature_index {
101         NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD,
102         NL80211_EXT_FEATURE_RADAR_BACKGROUND,
103         NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE,
104 +       NL80211_EXT_FEATURE_PUNCT,
105  
106         /* add new features before the definition below */
107         NUM_NL80211_EXT_FEATURES,
108 --- a/net/wireless/nl80211.c
109 +++ b/net/wireless/nl80211.c
110 @@ -799,6 +799,7 @@ static const struct nla_policy nl80211_p
111         [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
112         [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
113         [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
114 +       [NL80211_ATTR_PUNCT_BITMAP] = NLA_POLICY_RANGE(NLA_U8, 0, 0xffff),
115  };
116  
117  /* policy for the key attributes */
118 @@ -3167,6 +3168,21 @@ static bool nl80211_can_set_dev_channel(
119                 wdev->iftype == NL80211_IFTYPE_P2P_GO;
120  }
121  
122 +static int nl80211_parse_punct_bitmap(struct cfg80211_registered_device *rdev,
123 +                                     struct genl_info *info,
124 +                                     const struct cfg80211_chan_def *chandef,
125 +                                     u16 *punct_bitmap)
126 +{
127 +       if (!wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_PUNCT))
128 +               return -EINVAL;
129 +
130 +       *punct_bitmap = nla_get_u32(info->attrs[NL80211_ATTR_PUNCT_BITMAP]);
131 +       if (!cfg80211_valid_disable_subchannel_bitmap(punct_bitmap, chandef))
132 +               return -EINVAL;
133 +
134 +       return 0;
135 +}
136 +
137  int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
138                           struct genl_info *info,
139                           struct cfg80211_chan_def *chandef)
140 @@ -5912,6 +5928,14 @@ static int nl80211_start_ap(struct sk_bu
141                 goto out;
142         }
143  
144 +       if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
145 +               err = nl80211_parse_punct_bitmap(rdev, info,
146 +                                                &params->chandef,
147 +                                                &params->punct_bitmap);
148 +               if (err)
149 +                       goto out;
150 +       }
151 +
152         if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
153                                            wdev->iftype)) {
154                 err = -EINVAL;
155 @@ -10050,6 +10074,14 @@ skip_beacons:
156         if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
157                 params.block_tx = true;
158  
159 +       if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
160 +               err = nl80211_parse_punct_bitmap(rdev, info,
161 +                                                &params.chandef,
162 +                                                &params.punct_bitmap);
163 +               if (err)
164 +                       goto free;
165 +       }
166 +
167         wdev_lock(wdev);
168         err = rdev_channel_switch(rdev, dev, &params);
169         wdev_unlock(wdev);