31bc86197eac6c54eb510d73201971a66a6f1632
[librecmc/librecmc.git] /
1 From b25413fed3d43e1ed3340df4d928971bb8639f66 Mon Sep 17 00:00:00 2001
2 From: Aloka Dixit <quic_alokad@quicinc.com>
3 Date: Mon, 30 Jan 2023 16:12:24 -0800
4 Subject: [PATCH] wifi: cfg80211: move puncturing bitmap validation from
5  mac80211
6
7 - Move ieee80211_valid_disable_subchannel_bitmap() from mlme.c to
8   chan.c, rename it as cfg80211_valid_disable_subchannel_bitmap()
9   and export it.
10 - Modify the prototype to include struct cfg80211_chan_def instead
11   of only bandwidth to support a check which returns false if the
12   primary channel is punctured.
13
14 Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
15 Link: https://lore.kernel.org/r/20230131001227.25014-2-quic_alokad@quicinc.com
16 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
17 ---
18  include/net/cfg80211.h | 12 +++++++
19  net/mac80211/mlme.c    | 73 ++++--------------------------------------
20  net/wireless/chan.c    | 69 +++++++++++++++++++++++++++++++++++++++
21  3 files changed, 87 insertions(+), 67 deletions(-)
22
23 --- a/include/net/cfg80211.h
24 +++ b/include/net/cfg80211.h
25 @@ -8951,4 +8951,16 @@ static inline int cfg80211_color_change_
26                                          0, 0);
27  }
28  
29 +/**
30 + * cfg80211_valid_disable_subchannel_bitmap - validate puncturing bitmap
31 + * @bitmap: bitmap to be validated
32 + * @chandef: channel definition
33 + *
34 + * Validate the puncturing bitmap.
35 + *
36 + * Return: %true if the bitmap is valid. %false otherwise.
37 + */
38 +bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap,
39 +                                             const struct cfg80211_chan_def *chandef);
40 +
41  #endif /* __NET_CFG80211_H */
42 --- a/net/mac80211/mlme.c
43 +++ b/net/mac80211/mlme.c
44 @@ -88,67 +88,6 @@ MODULE_PARM_DESC(probe_wait_ms,
45   */
46  #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
47  
48 -struct ieee80211_per_bw_puncturing_values {
49 -       u8 len;
50 -       const u16 *valid_values;
51 -};
52 -
53 -static const u16 puncturing_values_80mhz[] = {
54 -       0x8, 0x4, 0x2, 0x1
55 -};
56 -
57 -static const u16 puncturing_values_160mhz[] = {
58 -        0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1, 0xc0, 0x30, 0xc, 0x3
59 -};
60 -
61 -static const u16 puncturing_values_320mhz[] = {
62 -       0xc000, 0x3000, 0xc00, 0x300, 0xc0, 0x30, 0xc, 0x3, 0xf000, 0xf00,
63 -       0xf0, 0xf, 0xfc00, 0xf300, 0xf0c0, 0xf030, 0xf00c, 0xf003, 0xc00f,
64 -       0x300f, 0xc0f, 0x30f, 0xcf, 0x3f
65 -};
66 -
67 -#define IEEE80211_PER_BW_VALID_PUNCTURING_VALUES(_bw) \
68 -       { \
69 -               .len = ARRAY_SIZE(puncturing_values_ ## _bw ## mhz), \
70 -               .valid_values = puncturing_values_ ## _bw ## mhz \
71 -       }
72 -
73 -static const struct ieee80211_per_bw_puncturing_values per_bw_puncturing[] = {
74 -       IEEE80211_PER_BW_VALID_PUNCTURING_VALUES(80),
75 -       IEEE80211_PER_BW_VALID_PUNCTURING_VALUES(160),
76 -       IEEE80211_PER_BW_VALID_PUNCTURING_VALUES(320)
77 -};
78 -
79 -static bool ieee80211_valid_disable_subchannel_bitmap(u16 *bitmap,
80 -                                                     enum nl80211_chan_width bw)
81 -{
82 -       u32 idx, i;
83 -
84 -       switch (bw) {
85 -       case NL80211_CHAN_WIDTH_80:
86 -               idx = 0;
87 -               break;
88 -       case NL80211_CHAN_WIDTH_160:
89 -               idx = 1;
90 -               break;
91 -       case NL80211_CHAN_WIDTH_320:
92 -               idx = 2;
93 -               break;
94 -       default:
95 -               *bitmap = 0;
96 -               break;
97 -       }
98 -
99 -       if (!*bitmap)
100 -               return true;
101 -
102 -       for (i = 0; i < per_bw_puncturing[idx].len; i++)
103 -               if (per_bw_puncturing[idx].valid_values[i] == *bitmap)
104 -                       return true;
105 -
106 -       return false;
107 -}
108 -
109  /*
110   * Extract from the given disabled subchannel bitmap (raw format
111   * from the EHT Operation Element) the bits for the subchannel
112 @@ -206,8 +145,8 @@ ieee80211_handle_puncturing_bitmap(struc
113                         ieee80211_extract_dis_subch_bmap(eht_oper, chandef,
114                                                          bitmap);
115  
116 -               if (ieee80211_valid_disable_subchannel_bitmap(&bitmap,
117 -                                                             chandef->width))
118 +               if (cfg80211_valid_disable_subchannel_bitmap(&bitmap,
119 +                                                            chandef))
120                         break;
121                 link->u.mgd.conn_flags |=
122                         ieee80211_chandef_downgrade(chandef);
123 @@ -5584,8 +5523,8 @@ static bool ieee80211_config_puncturing(
124             extracted == link->conf->eht_puncturing)
125                 return true;
126  
127 -       if (!ieee80211_valid_disable_subchannel_bitmap(&bitmap,
128 -                                                      link->conf->chandef.width)) {
129 +       if (!cfg80211_valid_disable_subchannel_bitmap(&bitmap,
130 +                                                     &link->conf->chandef)) {
131                 link_info(link,
132                           "Got an invalid disable subchannel bitmap from AP %pM: bitmap = 0x%x, bw = 0x%x. disconnect\n",
133                           link->u.mgd.bssid,
134 @@ -7072,8 +7011,8 @@ ieee80211_setup_assoc_link(struct ieee80
135                         u16 bitmap;
136  
137                         bitmap = get_unaligned_le16(disable_subchannel_bitmap);
138 -                       if (ieee80211_valid_disable_subchannel_bitmap(&bitmap,
139 -                                                                     link->conf->chandef.width))
140 +                       if (cfg80211_valid_disable_subchannel_bitmap(&bitmap,
141 +                                                                    &link->conf->chandef))
142                                 ieee80211_handle_puncturing_bitmap(link,
143                                                                    eht_oper,
144                                                                    bitmap,
145 --- a/net/wireless/chan.c
146 +++ b/net/wireless/chan.c
147 @@ -1505,3 +1505,72 @@ struct cfg80211_chan_def *wdev_chandef(s
148         }
149  }
150  EXPORT_SYMBOL(wdev_chandef);
151 +
152 +struct cfg80211_per_bw_puncturing_values {
153 +       u8 len;
154 +       const u16 *valid_values;
155 +};
156 +
157 +static const u16 puncturing_values_80mhz[] = {
158 +       0x8, 0x4, 0x2, 0x1
159 +};
160 +
161 +static const u16 puncturing_values_160mhz[] = {
162 +        0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1, 0xc0, 0x30, 0xc, 0x3
163 +};
164 +
165 +static const u16 puncturing_values_320mhz[] = {
166 +       0xc000, 0x3000, 0xc00, 0x300, 0xc0, 0x30, 0xc, 0x3, 0xf000, 0xf00,
167 +       0xf0, 0xf, 0xfc00, 0xf300, 0xf0c0, 0xf030, 0xf00c, 0xf003, 0xc00f,
168 +       0x300f, 0xc0f, 0x30f, 0xcf, 0x3f
169 +};
170 +
171 +#define CFG80211_PER_BW_VALID_PUNCTURING_VALUES(_bw) \
172 +       { \
173 +               .len = ARRAY_SIZE(puncturing_values_ ## _bw ## mhz), \
174 +               .valid_values = puncturing_values_ ## _bw ## mhz \
175 +       }
176 +
177 +static const struct cfg80211_per_bw_puncturing_values per_bw_puncturing[] = {
178 +       CFG80211_PER_BW_VALID_PUNCTURING_VALUES(80),
179 +       CFG80211_PER_BW_VALID_PUNCTURING_VALUES(160),
180 +       CFG80211_PER_BW_VALID_PUNCTURING_VALUES(320)
181 +};
182 +
183 +bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap,
184 +                                             const struct cfg80211_chan_def *chandef)
185 +{
186 +       u32 idx, i, start_freq;
187 +
188 +       switch (chandef->width) {
189 +       case NL80211_CHAN_WIDTH_80:
190 +               idx = 0;
191 +               start_freq = chandef->center_freq1 - 40;
192 +               break;
193 +       case NL80211_CHAN_WIDTH_160:
194 +               idx = 1;
195 +               start_freq = chandef->center_freq1 - 80;
196 +               break;
197 +       case NL80211_CHAN_WIDTH_320:
198 +               idx = 2;
199 +               start_freq = chandef->center_freq1 - 160;
200 +               break;
201 +       default:
202 +               *bitmap = 0;
203 +               break;
204 +       }
205 +
206 +       if (!*bitmap)
207 +               return true;
208 +
209 +       /* check if primary channel is punctured */
210 +       if (*bitmap & (u16)BIT((chandef->chan->center_freq - start_freq) / 20))
211 +               return false;
212 +
213 +       for (i = 0; i < per_bw_puncturing[idx].len; i++)
214 +               if (per_bw_puncturing[idx].valid_values[i] == *bitmap)
215 +                       return true;
216 +
217 +       return false;
218 +}
219 +EXPORT_SYMBOL(cfg80211_valid_disable_subchannel_bitmap);