hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/wireless/chan.c
....@@ -6,9 +6,11 @@
66 *
77 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
88 * Copyright 2013-2014 Intel Mobile Communications GmbH
9
+ * Copyright 2018-2020 Intel Corporation
910 */
1011
1112 #include <linux/export.h>
13
+#include <linux/bitfield.h>
1214 #include <net/cfg80211.h>
1315 #include "core.h"
1416 #include "rdev-ops.h"
....@@ -26,6 +28,7 @@
2628 return;
2729
2830 chandef->chan = chan;
31
+ chandef->freq1_offset = chan->freq_offset;
2932 chandef->center_freq2 = 0;
3033 chandef->edmg.bw_config = 0;
3134 chandef->edmg.channels = 0;
....@@ -138,11 +141,67 @@
138141 return true;
139142 }
140143
144
+static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
145
+{
146
+ int mhz;
147
+
148
+ switch (chan_width) {
149
+ case NL80211_CHAN_WIDTH_1:
150
+ mhz = 1;
151
+ break;
152
+ case NL80211_CHAN_WIDTH_2:
153
+ mhz = 2;
154
+ break;
155
+ case NL80211_CHAN_WIDTH_4:
156
+ mhz = 4;
157
+ break;
158
+ case NL80211_CHAN_WIDTH_8:
159
+ mhz = 8;
160
+ break;
161
+ case NL80211_CHAN_WIDTH_16:
162
+ mhz = 16;
163
+ break;
164
+ case NL80211_CHAN_WIDTH_5:
165
+ mhz = 5;
166
+ break;
167
+ case NL80211_CHAN_WIDTH_10:
168
+ mhz = 10;
169
+ break;
170
+ case NL80211_CHAN_WIDTH_20:
171
+ case NL80211_CHAN_WIDTH_20_NOHT:
172
+ mhz = 20;
173
+ break;
174
+ case NL80211_CHAN_WIDTH_40:
175
+ mhz = 40;
176
+ break;
177
+ case NL80211_CHAN_WIDTH_80P80:
178
+ case NL80211_CHAN_WIDTH_80:
179
+ mhz = 80;
180
+ break;
181
+ case NL80211_CHAN_WIDTH_160:
182
+ mhz = 160;
183
+ break;
184
+ default:
185
+ WARN_ON_ONCE(1);
186
+ return -1;
187
+ }
188
+ return mhz;
189
+}
190
+
191
+static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
192
+{
193
+ return nl80211_chan_width_to_mhz(c->width);
194
+}
195
+
141196 bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
142197 {
143
- u32 control_freq;
198
+ u32 control_freq, oper_freq;
199
+ int oper_width, control_width;
144200
145201 if (!chandef->chan)
202
+ return false;
203
+
204
+ if (chandef->freq1_offset >= 1000)
146205 return false;
147206
148207 control_freq = chandef->chan->center_freq;
....@@ -152,9 +211,38 @@
152211 case NL80211_CHAN_WIDTH_10:
153212 case NL80211_CHAN_WIDTH_20:
154213 case NL80211_CHAN_WIDTH_20_NOHT:
155
- if (chandef->center_freq1 != control_freq)
214
+ if (ieee80211_chandef_to_khz(chandef) !=
215
+ ieee80211_channel_to_khz(chandef->chan))
156216 return false;
157217 if (chandef->center_freq2)
218
+ return false;
219
+ break;
220
+ case NL80211_CHAN_WIDTH_1:
221
+ case NL80211_CHAN_WIDTH_2:
222
+ case NL80211_CHAN_WIDTH_4:
223
+ case NL80211_CHAN_WIDTH_8:
224
+ case NL80211_CHAN_WIDTH_16:
225
+ if (chandef->chan->band != NL80211_BAND_S1GHZ)
226
+ return false;
227
+
228
+ control_freq = ieee80211_channel_to_khz(chandef->chan);
229
+ oper_freq = ieee80211_chandef_to_khz(chandef);
230
+ control_width = nl80211_chan_width_to_mhz(
231
+ ieee80211_s1g_channel_width(
232
+ chandef->chan));
233
+ oper_width = cfg80211_chandef_get_width(chandef);
234
+
235
+ if (oper_width < 0 || control_width < 0)
236
+ return false;
237
+ if (chandef->center_freq2)
238
+ return false;
239
+
240
+ if (control_freq + MHZ_TO_KHZ(control_width) / 2 >
241
+ oper_freq + MHZ_TO_KHZ(oper_width) / 2)
242
+ return false;
243
+
244
+ if (control_freq - MHZ_TO_KHZ(control_width) / 2 <
245
+ oper_freq - MHZ_TO_KHZ(oper_width) / 2)
158246 return false;
159247 break;
160248 case NL80211_CHAN_WIDTH_40:
....@@ -203,6 +291,11 @@
203291 return false;
204292 }
205293
294
+ /* channel 14 is only for IEEE 802.11b */
295
+ if (chandef->center_freq1 == 2484 &&
296
+ chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
297
+ return false;
298
+
206299 if (cfg80211_chandef_is_edmg(chandef) &&
207300 !cfg80211_edmg_chandef_valid(chandef))
208301 return false;
....@@ -245,38 +338,6 @@
245338 default:
246339 WARN_ON_ONCE(1);
247340 }
248
-}
249
-
250
-static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
251
-{
252
- int width;
253
-
254
- switch (c->width) {
255
- case NL80211_CHAN_WIDTH_5:
256
- width = 5;
257
- break;
258
- case NL80211_CHAN_WIDTH_10:
259
- width = 10;
260
- break;
261
- case NL80211_CHAN_WIDTH_20:
262
- case NL80211_CHAN_WIDTH_20_NOHT:
263
- width = 20;
264
- break;
265
- case NL80211_CHAN_WIDTH_40:
266
- width = 40;
267
- break;
268
- case NL80211_CHAN_WIDTH_80P80:
269
- case NL80211_CHAN_WIDTH_80:
270
- width = 80;
271
- break;
272
- case NL80211_CHAN_WIDTH_160:
273
- width = 160;
274
- break;
275
- default:
276
- WARN_ON_ONCE(1);
277
- return -1;
278
- }
279
- return width;
280341 }
281342
282343 const struct cfg80211_chan_def *
....@@ -380,10 +441,11 @@
380441 {
381442 u32 start_freq;
382443
383
- if (bandwidth <= 20)
444
+ bandwidth = MHZ_TO_KHZ(bandwidth);
445
+ if (bandwidth <= MHZ_TO_KHZ(20))
384446 start_freq = center_freq;
385447 else
386
- start_freq = center_freq - bandwidth/2 + 10;
448
+ start_freq = center_freq - bandwidth / 2 + MHZ_TO_KHZ(10);
387449
388450 return start_freq;
389451 }
....@@ -393,10 +455,11 @@
393455 {
394456 u32 end_freq;
395457
396
- if (bandwidth <= 20)
458
+ bandwidth = MHZ_TO_KHZ(bandwidth);
459
+ if (bandwidth <= MHZ_TO_KHZ(20))
397460 end_freq = center_freq;
398461 else
399
- end_freq = center_freq + bandwidth/2 - 10;
462
+ end_freq = center_freq + bandwidth / 2 - MHZ_TO_KHZ(10);
400463
401464 return end_freq;
402465 }
....@@ -411,8 +474,8 @@
411474 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
412475 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
413476
414
- for (freq = start_freq; freq <= end_freq; freq += 20) {
415
- c = ieee80211_get_channel(wiphy, freq);
477
+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
478
+ c = ieee80211_get_channel_khz(wiphy, freq);
416479 if (!c)
417480 return -EINVAL;
418481
....@@ -443,8 +506,8 @@
443506 return -EINVAL;
444507
445508 ret = cfg80211_get_chans_dfs_required(wiphy,
446
- chandef->center_freq1,
447
- width);
509
+ ieee80211_chandef_to_khz(chandef),
510
+ width);
448511 if (ret < 0)
449512 return ret;
450513 else if (ret > 0)
....@@ -454,8 +517,8 @@
454517 return 0;
455518
456519 ret = cfg80211_get_chans_dfs_required(wiphy,
457
- chandef->center_freq2,
458
- width);
520
+ MHZ_TO_KHZ(chandef->center_freq2),
521
+ width);
459522 if (ret < 0)
460523 return ret;
461524 else if (ret > 0)
....@@ -497,8 +560,8 @@
497560 * DFS_AVAILABLE). Return number of usable channels
498561 * (require CAC). Allow DFS and non-DFS channel mix.
499562 */
500
- for (freq = start_freq; freq <= end_freq; freq += 20) {
501
- c = ieee80211_get_channel(wiphy, freq);
563
+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
564
+ c = ieee80211_get_channel_khz(wiphy, freq);
502565 if (!c)
503566 return -EINVAL;
504567
....@@ -530,8 +593,9 @@
530593 if (width < 0)
531594 return false;
532595
533
- r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1,
534
- width);
596
+ r1 = cfg80211_get_chans_dfs_usable(wiphy,
597
+ MHZ_TO_KHZ(chandef->center_freq1),
598
+ width);
535599
536600 if (r1 < 0)
537601 return false;
....@@ -540,8 +604,8 @@
540604 case NL80211_CHAN_WIDTH_80P80:
541605 WARN_ON(!chandef->center_freq2);
542606 r2 = cfg80211_get_chans_dfs_usable(wiphy,
543
- chandef->center_freq2,
544
- width);
607
+ MHZ_TO_KHZ(chandef->center_freq2),
608
+ width);
545609 if (r2 < 0)
546610 return false;
547611 break;
....@@ -688,8 +752,8 @@
688752 * If any channel in between is disabled or has not
689753 * had gone through CAC return false
690754 */
691
- for (freq = start_freq; freq <= end_freq; freq += 20) {
692
- c = ieee80211_get_channel(wiphy, freq);
755
+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
756
+ c = ieee80211_get_channel_khz(wiphy, freq);
693757 if (!c)
694758 return false;
695759
....@@ -718,7 +782,8 @@
718782 if (width < 0)
719783 return false;
720784
721
- r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1,
785
+ r = cfg80211_get_chans_dfs_available(wiphy,
786
+ MHZ_TO_KHZ(chandef->center_freq1),
722787 width);
723788
724789 /* If any of channels unavailable for cf1 just return */
....@@ -729,8 +794,8 @@
729794 case NL80211_CHAN_WIDTH_80P80:
730795 WARN_ON(!chandef->center_freq2);
731796 r = cfg80211_get_chans_dfs_available(wiphy,
732
- chandef->center_freq2,
733
- width);
797
+ MHZ_TO_KHZ(chandef->center_freq2),
798
+ width);
734799 break;
735800 default:
736801 WARN_ON(chandef->center_freq2);
....@@ -751,8 +816,8 @@
751816 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
752817 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
753818
754
- for (freq = start_freq; freq <= end_freq; freq += 20) {
755
- c = ieee80211_get_channel(wiphy, freq);
819
+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
820
+ c = ieee80211_get_channel_khz(wiphy, freq);
756821 if (!c)
757822 return 0;
758823
....@@ -784,14 +849,14 @@
784849 return 0;
785850
786851 t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
787
- chandef->center_freq1,
852
+ MHZ_TO_KHZ(chandef->center_freq1),
788853 width);
789854
790855 if (!chandef->center_freq2)
791856 return t1;
792857
793858 t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
794
- chandef->center_freq2,
859
+ MHZ_TO_KHZ(chandef->center_freq2),
795860 width);
796861
797862 return max(t1, t2);
....@@ -807,8 +872,8 @@
807872 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
808873 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
809874
810
- for (freq = start_freq; freq <= end_freq; freq += 20) {
811
- c = ieee80211_get_channel(wiphy, freq);
875
+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
876
+ c = ieee80211_get_channel_khz(wiphy, freq);
812877 if (!c || c->flags & prohibited_flags)
813878 return false;
814879 }
....@@ -877,6 +942,7 @@
877942 struct ieee80211_sta_vht_cap *vht_cap;
878943 struct ieee80211_edmg *edmg_cap;
879944 u32 width, control_freq, cap;
945
+ bool support_80_80 = false;
880946
881947 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
882948 return false;
....@@ -896,6 +962,21 @@
896962 control_freq = chandef->chan->center_freq;
897963
898964 switch (chandef->width) {
965
+ case NL80211_CHAN_WIDTH_1:
966
+ width = 1;
967
+ break;
968
+ case NL80211_CHAN_WIDTH_2:
969
+ width = 2;
970
+ break;
971
+ case NL80211_CHAN_WIDTH_4:
972
+ width = 4;
973
+ break;
974
+ case NL80211_CHAN_WIDTH_8:
975
+ width = 8;
976
+ break;
977
+ case NL80211_CHAN_WIDTH_16:
978
+ width = 16;
979
+ break;
899980 case NL80211_CHAN_WIDTH_5:
900981 width = 5;
901982 break;
....@@ -904,14 +985,18 @@
904985 width = 10;
905986 break;
906987 case NL80211_CHAN_WIDTH_20:
907
- if (!ht_cap->ht_supported)
988
+ if (!ht_cap->ht_supported &&
989
+ chandef->chan->band != NL80211_BAND_6GHZ)
908990 return false;
991
+ fallthrough;
909992 case NL80211_CHAN_WIDTH_20_NOHT:
910993 prohibited_flags |= IEEE80211_CHAN_NO_20MHZ;
911994 width = 20;
912995 break;
913996 case NL80211_CHAN_WIDTH_40:
914997 width = 40;
998
+ if (chandef->chan->band == NL80211_BAND_6GHZ)
999
+ break;
9151000 if (!ht_cap->ht_supported)
9161001 return false;
9171002 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
....@@ -925,24 +1010,35 @@
9251010 return false;
9261011 break;
9271012 case NL80211_CHAN_WIDTH_80P80:
928
- cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
929
- if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
1013
+ cap = vht_cap->cap;
1014
+ support_80_80 =
1015
+ (cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) ||
1016
+ (cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
1017
+ cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) ||
1018
+ u32_get_bits(cap, IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) > 1;
1019
+ if (chandef->chan->band != NL80211_BAND_6GHZ && !support_80_80)
9301020 return false;
1021
+ fallthrough;
9311022 case NL80211_CHAN_WIDTH_80:
932
- if (!vht_cap->vht_supported)
933
- return false;
9341023 prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
9351024 width = 80;
1025
+ if (chandef->chan->band == NL80211_BAND_6GHZ)
1026
+ break;
1027
+ if (!vht_cap->vht_supported)
1028
+ return false;
9361029 break;
9371030 case NL80211_CHAN_WIDTH_160:
1031
+ prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
1032
+ width = 160;
1033
+ if (chandef->chan->band == NL80211_BAND_6GHZ)
1034
+ break;
9381035 if (!vht_cap->vht_supported)
9391036 return false;
9401037 cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
9411038 if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
942
- cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
1039
+ cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ &&
1040
+ !(vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
9431041 return false;
944
- prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
945
- width = 160;
9461042 break;
9471043 default:
9481044 WARN_ON_ONCE(1);
....@@ -968,13 +1064,15 @@
9681064 prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
9691065
9701066
971
- if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
1067
+ if (!cfg80211_secondary_chans_ok(wiphy,
1068
+ ieee80211_chandef_to_khz(chandef),
9721069 width, prohibited_flags))
9731070 return false;
9741071
9751072 if (!chandef->center_freq2)
9761073 return true;
977
- return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2,
1074
+ return cfg80211_secondary_chans_ok(wiphy,
1075
+ MHZ_TO_KHZ(chandef->center_freq2),
9781076 width, prohibited_flags);
9791077 }
9801078 EXPORT_SYMBOL(cfg80211_chandef_usable);
....@@ -1050,7 +1148,8 @@
10501148 if (chan == other_chan)
10511149 return true;
10521150
1053
- if (chan->band != NL80211_BAND_5GHZ)
1151
+ if (chan->band != NL80211_BAND_5GHZ &&
1152
+ chan->band != NL80211_BAND_6GHZ)
10541153 continue;
10551154
10561155 r1 = cfg80211_get_unii(chan->center_freq);