0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/export.h>
0013 #include <linux/bitfield.h>
0014 #include <net/cfg80211.h>
0015 #include "core.h"
0016 #include "rdev-ops.h"
0017
0018 static bool cfg80211_valid_60g_freq(u32 freq)
0019 {
0020 return freq >= 58320 && freq <= 70200;
0021 }
0022
0023 void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
0024 struct ieee80211_channel *chan,
0025 enum nl80211_channel_type chan_type)
0026 {
0027 if (WARN_ON(!chan))
0028 return;
0029
0030 chandef->chan = chan;
0031 chandef->freq1_offset = chan->freq_offset;
0032 chandef->center_freq2 = 0;
0033 chandef->edmg.bw_config = 0;
0034 chandef->edmg.channels = 0;
0035
0036 switch (chan_type) {
0037 case NL80211_CHAN_NO_HT:
0038 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
0039 chandef->center_freq1 = chan->center_freq;
0040 break;
0041 case NL80211_CHAN_HT20:
0042 chandef->width = NL80211_CHAN_WIDTH_20;
0043 chandef->center_freq1 = chan->center_freq;
0044 break;
0045 case NL80211_CHAN_HT40PLUS:
0046 chandef->width = NL80211_CHAN_WIDTH_40;
0047 chandef->center_freq1 = chan->center_freq + 10;
0048 break;
0049 case NL80211_CHAN_HT40MINUS:
0050 chandef->width = NL80211_CHAN_WIDTH_40;
0051 chandef->center_freq1 = chan->center_freq - 10;
0052 break;
0053 default:
0054 WARN_ON(1);
0055 }
0056 }
0057 EXPORT_SYMBOL(cfg80211_chandef_create);
0058
0059 static bool cfg80211_edmg_chandef_valid(const struct cfg80211_chan_def *chandef)
0060 {
0061 int max_contiguous = 0;
0062 int num_of_enabled = 0;
0063 int contiguous = 0;
0064 int i;
0065
0066 if (!chandef->edmg.channels || !chandef->edmg.bw_config)
0067 return false;
0068
0069 if (!cfg80211_valid_60g_freq(chandef->chan->center_freq))
0070 return false;
0071
0072 for (i = 0; i < 6; i++) {
0073 if (chandef->edmg.channels & BIT(i)) {
0074 contiguous++;
0075 num_of_enabled++;
0076 } else {
0077 contiguous = 0;
0078 }
0079
0080 max_contiguous = max(contiguous, max_contiguous);
0081 }
0082
0083
0084
0085
0086 switch (chandef->edmg.bw_config) {
0087 case IEEE80211_EDMG_BW_CONFIG_4:
0088 case IEEE80211_EDMG_BW_CONFIG_8:
0089 case IEEE80211_EDMG_BW_CONFIG_12:
0090 if (max_contiguous < 1)
0091 return false;
0092 break;
0093 case IEEE80211_EDMG_BW_CONFIG_5:
0094 case IEEE80211_EDMG_BW_CONFIG_9:
0095 case IEEE80211_EDMG_BW_CONFIG_13:
0096 if (max_contiguous < 2)
0097 return false;
0098 break;
0099 case IEEE80211_EDMG_BW_CONFIG_6:
0100 case IEEE80211_EDMG_BW_CONFIG_10:
0101 case IEEE80211_EDMG_BW_CONFIG_14:
0102 if (max_contiguous < 3)
0103 return false;
0104 break;
0105 case IEEE80211_EDMG_BW_CONFIG_7:
0106 case IEEE80211_EDMG_BW_CONFIG_11:
0107 case IEEE80211_EDMG_BW_CONFIG_15:
0108 if (max_contiguous < 4)
0109 return false;
0110 break;
0111
0112 default:
0113 return false;
0114 }
0115
0116
0117 switch (chandef->edmg.bw_config) {
0118 case IEEE80211_EDMG_BW_CONFIG_4:
0119 case IEEE80211_EDMG_BW_CONFIG_5:
0120 case IEEE80211_EDMG_BW_CONFIG_6:
0121 case IEEE80211_EDMG_BW_CONFIG_7:
0122 break;
0123 case IEEE80211_EDMG_BW_CONFIG_8:
0124 case IEEE80211_EDMG_BW_CONFIG_9:
0125 case IEEE80211_EDMG_BW_CONFIG_10:
0126 case IEEE80211_EDMG_BW_CONFIG_11:
0127 if (num_of_enabled < 2)
0128 return false;
0129 break;
0130 case IEEE80211_EDMG_BW_CONFIG_12:
0131 case IEEE80211_EDMG_BW_CONFIG_13:
0132 case IEEE80211_EDMG_BW_CONFIG_14:
0133 case IEEE80211_EDMG_BW_CONFIG_15:
0134 if (num_of_enabled < 4 || max_contiguous < 2)
0135 return false;
0136 break;
0137 default:
0138 return false;
0139 }
0140
0141 return true;
0142 }
0143
0144 static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
0145 {
0146 int mhz;
0147
0148 switch (chan_width) {
0149 case NL80211_CHAN_WIDTH_1:
0150 mhz = 1;
0151 break;
0152 case NL80211_CHAN_WIDTH_2:
0153 mhz = 2;
0154 break;
0155 case NL80211_CHAN_WIDTH_4:
0156 mhz = 4;
0157 break;
0158 case NL80211_CHAN_WIDTH_8:
0159 mhz = 8;
0160 break;
0161 case NL80211_CHAN_WIDTH_16:
0162 mhz = 16;
0163 break;
0164 case NL80211_CHAN_WIDTH_5:
0165 mhz = 5;
0166 break;
0167 case NL80211_CHAN_WIDTH_10:
0168 mhz = 10;
0169 break;
0170 case NL80211_CHAN_WIDTH_20:
0171 case NL80211_CHAN_WIDTH_20_NOHT:
0172 mhz = 20;
0173 break;
0174 case NL80211_CHAN_WIDTH_40:
0175 mhz = 40;
0176 break;
0177 case NL80211_CHAN_WIDTH_80P80:
0178 case NL80211_CHAN_WIDTH_80:
0179 mhz = 80;
0180 break;
0181 case NL80211_CHAN_WIDTH_160:
0182 mhz = 160;
0183 break;
0184 case NL80211_CHAN_WIDTH_320:
0185 mhz = 320;
0186 break;
0187 default:
0188 WARN_ON_ONCE(1);
0189 return -1;
0190 }
0191 return mhz;
0192 }
0193
0194 static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
0195 {
0196 return nl80211_chan_width_to_mhz(c->width);
0197 }
0198
0199 bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
0200 {
0201 u32 control_freq, oper_freq;
0202 int oper_width, control_width;
0203
0204 if (!chandef->chan)
0205 return false;
0206
0207 if (chandef->freq1_offset >= 1000)
0208 return false;
0209
0210 control_freq = chandef->chan->center_freq;
0211
0212 switch (chandef->width) {
0213 case NL80211_CHAN_WIDTH_5:
0214 case NL80211_CHAN_WIDTH_10:
0215 case NL80211_CHAN_WIDTH_20:
0216 case NL80211_CHAN_WIDTH_20_NOHT:
0217 if (ieee80211_chandef_to_khz(chandef) !=
0218 ieee80211_channel_to_khz(chandef->chan))
0219 return false;
0220 if (chandef->center_freq2)
0221 return false;
0222 break;
0223 case NL80211_CHAN_WIDTH_1:
0224 case NL80211_CHAN_WIDTH_2:
0225 case NL80211_CHAN_WIDTH_4:
0226 case NL80211_CHAN_WIDTH_8:
0227 case NL80211_CHAN_WIDTH_16:
0228 if (chandef->chan->band != NL80211_BAND_S1GHZ)
0229 return false;
0230
0231 control_freq = ieee80211_channel_to_khz(chandef->chan);
0232 oper_freq = ieee80211_chandef_to_khz(chandef);
0233 control_width = nl80211_chan_width_to_mhz(
0234 ieee80211_s1g_channel_width(
0235 chandef->chan));
0236 oper_width = cfg80211_chandef_get_width(chandef);
0237
0238 if (oper_width < 0 || control_width < 0)
0239 return false;
0240 if (chandef->center_freq2)
0241 return false;
0242
0243 if (control_freq + MHZ_TO_KHZ(control_width) / 2 >
0244 oper_freq + MHZ_TO_KHZ(oper_width) / 2)
0245 return false;
0246
0247 if (control_freq - MHZ_TO_KHZ(control_width) / 2 <
0248 oper_freq - MHZ_TO_KHZ(oper_width) / 2)
0249 return false;
0250 break;
0251 case NL80211_CHAN_WIDTH_80P80:
0252 if (!chandef->center_freq2)
0253 return false;
0254
0255 if (chandef->center_freq1 - chandef->center_freq2 == 80 ||
0256 chandef->center_freq2 - chandef->center_freq1 == 80)
0257 return false;
0258 break;
0259 default:
0260 if (chandef->center_freq2)
0261 return false;
0262 break;
0263 }
0264
0265 switch (chandef->width) {
0266 case NL80211_CHAN_WIDTH_5:
0267 case NL80211_CHAN_WIDTH_10:
0268 case NL80211_CHAN_WIDTH_20:
0269 case NL80211_CHAN_WIDTH_20_NOHT:
0270 case NL80211_CHAN_WIDTH_1:
0271 case NL80211_CHAN_WIDTH_2:
0272 case NL80211_CHAN_WIDTH_4:
0273 case NL80211_CHAN_WIDTH_8:
0274 case NL80211_CHAN_WIDTH_16:
0275
0276 break;
0277 case NL80211_CHAN_WIDTH_320:
0278 if (chandef->center_freq1 == control_freq + 150 ||
0279 chandef->center_freq1 == control_freq + 130 ||
0280 chandef->center_freq1 == control_freq + 110 ||
0281 chandef->center_freq1 == control_freq + 90 ||
0282 chandef->center_freq1 == control_freq - 90 ||
0283 chandef->center_freq1 == control_freq - 110 ||
0284 chandef->center_freq1 == control_freq - 130 ||
0285 chandef->center_freq1 == control_freq - 150)
0286 break;
0287 fallthrough;
0288 case NL80211_CHAN_WIDTH_160:
0289 if (chandef->center_freq1 == control_freq + 70 ||
0290 chandef->center_freq1 == control_freq + 50 ||
0291 chandef->center_freq1 == control_freq - 50 ||
0292 chandef->center_freq1 == control_freq - 70)
0293 break;
0294 fallthrough;
0295 case NL80211_CHAN_WIDTH_80P80:
0296 case NL80211_CHAN_WIDTH_80:
0297 if (chandef->center_freq1 == control_freq + 30 ||
0298 chandef->center_freq1 == control_freq - 30)
0299 break;
0300 fallthrough;
0301 case NL80211_CHAN_WIDTH_40:
0302 if (chandef->center_freq1 == control_freq + 10 ||
0303 chandef->center_freq1 == control_freq - 10)
0304 break;
0305 fallthrough;
0306 default:
0307 return false;
0308 }
0309
0310
0311 if (chandef->center_freq1 == 2484 &&
0312 chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
0313 return false;
0314
0315 if (cfg80211_chandef_is_edmg(chandef) &&
0316 !cfg80211_edmg_chandef_valid(chandef))
0317 return false;
0318
0319 return true;
0320 }
0321 EXPORT_SYMBOL(cfg80211_chandef_valid);
0322
0323 static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
0324 u32 *pri40, u32 *pri80, u32 *pri160)
0325 {
0326 int tmp;
0327
0328 switch (c->width) {
0329 case NL80211_CHAN_WIDTH_40:
0330 *pri40 = c->center_freq1;
0331 *pri80 = 0;
0332 *pri160 = 0;
0333 break;
0334 case NL80211_CHAN_WIDTH_80:
0335 case NL80211_CHAN_WIDTH_80P80:
0336 *pri160 = 0;
0337 *pri80 = c->center_freq1;
0338
0339 tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
0340
0341 tmp /= 2;
0342
0343 *pri40 = c->center_freq1 - 20 + 40 * tmp;
0344 break;
0345 case NL80211_CHAN_WIDTH_160:
0346 *pri160 = c->center_freq1;
0347
0348 tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
0349
0350 tmp /= 2;
0351
0352 *pri40 = c->center_freq1 - 60 + 40 * tmp;
0353
0354 tmp /= 2;
0355 *pri80 = c->center_freq1 - 40 + 80 * tmp;
0356 break;
0357 case NL80211_CHAN_WIDTH_320:
0358
0359 tmp = (150 + c->chan->center_freq - c->center_freq1) / 20;
0360
0361 tmp /= 2;
0362
0363 *pri40 = c->center_freq1 - 140 + 40 * tmp;
0364
0365 tmp /= 2;
0366 *pri80 = c->center_freq1 - 120 + 80 * tmp;
0367
0368 tmp /= 2;
0369 *pri160 = c->center_freq1 - 80 + 160 * tmp;
0370 break;
0371 default:
0372 WARN_ON_ONCE(1);
0373 }
0374 }
0375
0376 const struct cfg80211_chan_def *
0377 cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
0378 const struct cfg80211_chan_def *c2)
0379 {
0380 u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80, c1_pri160, c2_pri160;
0381
0382
0383 if (cfg80211_chandef_identical(c1, c2))
0384 return c1;
0385
0386
0387 if (c1->chan != c2->chan)
0388 return NULL;
0389
0390
0391
0392
0393
0394 if (c1->width == c2->width)
0395 return NULL;
0396
0397
0398
0399
0400
0401 if (c1->width == NL80211_CHAN_WIDTH_5 ||
0402 c1->width == NL80211_CHAN_WIDTH_10 ||
0403 c2->width == NL80211_CHAN_WIDTH_5 ||
0404 c2->width == NL80211_CHAN_WIDTH_10)
0405 return NULL;
0406
0407 if (c1->width == NL80211_CHAN_WIDTH_20_NOHT ||
0408 c1->width == NL80211_CHAN_WIDTH_20)
0409 return c2;
0410
0411 if (c2->width == NL80211_CHAN_WIDTH_20_NOHT ||
0412 c2->width == NL80211_CHAN_WIDTH_20)
0413 return c1;
0414
0415 chandef_primary_freqs(c1, &c1_pri40, &c1_pri80, &c1_pri160);
0416 chandef_primary_freqs(c2, &c2_pri40, &c2_pri80, &c2_pri160);
0417
0418 if (c1_pri40 != c2_pri40)
0419 return NULL;
0420
0421 if (c1->width == NL80211_CHAN_WIDTH_40)
0422 return c2;
0423
0424 if (c2->width == NL80211_CHAN_WIDTH_40)
0425 return c1;
0426
0427 if (c1_pri80 != c2_pri80)
0428 return NULL;
0429
0430 if (c1->width == NL80211_CHAN_WIDTH_80 &&
0431 c2->width > NL80211_CHAN_WIDTH_80)
0432 return c2;
0433
0434 if (c2->width == NL80211_CHAN_WIDTH_80 &&
0435 c1->width > NL80211_CHAN_WIDTH_80)
0436 return c1;
0437
0438 WARN_ON(!c1_pri160 && !c2_pri160);
0439 if (c1_pri160 && c2_pri160 && c1_pri160 != c2_pri160)
0440 return NULL;
0441
0442 if (c1->width > c2->width)
0443 return c1;
0444 return c2;
0445 }
0446 EXPORT_SYMBOL(cfg80211_chandef_compatible);
0447
0448 static void cfg80211_set_chans_dfs_state(struct wiphy *wiphy, u32 center_freq,
0449 u32 bandwidth,
0450 enum nl80211_dfs_state dfs_state)
0451 {
0452 struct ieee80211_channel *c;
0453 u32 freq;
0454
0455 for (freq = center_freq - bandwidth/2 + 10;
0456 freq <= center_freq + bandwidth/2 - 10;
0457 freq += 20) {
0458 c = ieee80211_get_channel(wiphy, freq);
0459 if (!c || !(c->flags & IEEE80211_CHAN_RADAR))
0460 continue;
0461
0462 c->dfs_state = dfs_state;
0463 c->dfs_state_entered = jiffies;
0464 }
0465 }
0466
0467 void cfg80211_set_dfs_state(struct wiphy *wiphy,
0468 const struct cfg80211_chan_def *chandef,
0469 enum nl80211_dfs_state dfs_state)
0470 {
0471 int width;
0472
0473 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
0474 return;
0475
0476 width = cfg80211_chandef_get_width(chandef);
0477 if (width < 0)
0478 return;
0479
0480 cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq1,
0481 width, dfs_state);
0482
0483 if (!chandef->center_freq2)
0484 return;
0485 cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq2,
0486 width, dfs_state);
0487 }
0488
0489 static u32 cfg80211_get_start_freq(u32 center_freq,
0490 u32 bandwidth)
0491 {
0492 u32 start_freq;
0493
0494 bandwidth = MHZ_TO_KHZ(bandwidth);
0495 if (bandwidth <= MHZ_TO_KHZ(20))
0496 start_freq = center_freq;
0497 else
0498 start_freq = center_freq - bandwidth / 2 + MHZ_TO_KHZ(10);
0499
0500 return start_freq;
0501 }
0502
0503 static u32 cfg80211_get_end_freq(u32 center_freq,
0504 u32 bandwidth)
0505 {
0506 u32 end_freq;
0507
0508 bandwidth = MHZ_TO_KHZ(bandwidth);
0509 if (bandwidth <= MHZ_TO_KHZ(20))
0510 end_freq = center_freq;
0511 else
0512 end_freq = center_freq + bandwidth / 2 - MHZ_TO_KHZ(10);
0513
0514 return end_freq;
0515 }
0516
0517 static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
0518 u32 center_freq,
0519 u32 bandwidth)
0520 {
0521 struct ieee80211_channel *c;
0522 u32 freq, start_freq, end_freq;
0523
0524 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
0525 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
0526
0527 for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
0528 c = ieee80211_get_channel_khz(wiphy, freq);
0529 if (!c)
0530 return -EINVAL;
0531
0532 if (c->flags & IEEE80211_CHAN_RADAR)
0533 return 1;
0534 }
0535 return 0;
0536 }
0537
0538
0539 int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
0540 const struct cfg80211_chan_def *chandef,
0541 enum nl80211_iftype iftype)
0542 {
0543 int width;
0544 int ret;
0545
0546 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
0547 return -EINVAL;
0548
0549 switch (iftype) {
0550 case NL80211_IFTYPE_ADHOC:
0551 case NL80211_IFTYPE_AP:
0552 case NL80211_IFTYPE_P2P_GO:
0553 case NL80211_IFTYPE_MESH_POINT:
0554 width = cfg80211_chandef_get_width(chandef);
0555 if (width < 0)
0556 return -EINVAL;
0557
0558 ret = cfg80211_get_chans_dfs_required(wiphy,
0559 ieee80211_chandef_to_khz(chandef),
0560 width);
0561 if (ret < 0)
0562 return ret;
0563 else if (ret > 0)
0564 return BIT(chandef->width);
0565
0566 if (!chandef->center_freq2)
0567 return 0;
0568
0569 ret = cfg80211_get_chans_dfs_required(wiphy,
0570 MHZ_TO_KHZ(chandef->center_freq2),
0571 width);
0572 if (ret < 0)
0573 return ret;
0574 else if (ret > 0)
0575 return BIT(chandef->width);
0576
0577 break;
0578 case NL80211_IFTYPE_STATION:
0579 case NL80211_IFTYPE_OCB:
0580 case NL80211_IFTYPE_P2P_CLIENT:
0581 case NL80211_IFTYPE_MONITOR:
0582 case NL80211_IFTYPE_AP_VLAN:
0583 case NL80211_IFTYPE_P2P_DEVICE:
0584 case NL80211_IFTYPE_NAN:
0585 break;
0586 case NL80211_IFTYPE_WDS:
0587 case NL80211_IFTYPE_UNSPECIFIED:
0588 case NUM_NL80211_IFTYPES:
0589 WARN_ON(1);
0590 }
0591
0592 return 0;
0593 }
0594 EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
0595
0596 static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy,
0597 u32 center_freq,
0598 u32 bandwidth)
0599 {
0600 struct ieee80211_channel *c;
0601 u32 freq, start_freq, end_freq;
0602 int count = 0;
0603
0604 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
0605 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
0606
0607
0608
0609
0610
0611
0612
0613 for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
0614 c = ieee80211_get_channel_khz(wiphy, freq);
0615 if (!c)
0616 return -EINVAL;
0617
0618 if (c->flags & IEEE80211_CHAN_DISABLED)
0619 return -EINVAL;
0620
0621 if (c->flags & IEEE80211_CHAN_RADAR) {
0622 if (c->dfs_state == NL80211_DFS_UNAVAILABLE)
0623 return -EINVAL;
0624
0625 if (c->dfs_state == NL80211_DFS_USABLE)
0626 count++;
0627 }
0628 }
0629
0630 return count;
0631 }
0632
0633 bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
0634 const struct cfg80211_chan_def *chandef)
0635 {
0636 int width;
0637 int r1, r2 = 0;
0638
0639 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
0640 return false;
0641
0642 width = cfg80211_chandef_get_width(chandef);
0643 if (width < 0)
0644 return false;
0645
0646 r1 = cfg80211_get_chans_dfs_usable(wiphy,
0647 MHZ_TO_KHZ(chandef->center_freq1),
0648 width);
0649
0650 if (r1 < 0)
0651 return false;
0652
0653 switch (chandef->width) {
0654 case NL80211_CHAN_WIDTH_80P80:
0655 WARN_ON(!chandef->center_freq2);
0656 r2 = cfg80211_get_chans_dfs_usable(wiphy,
0657 MHZ_TO_KHZ(chandef->center_freq2),
0658 width);
0659 if (r2 < 0)
0660 return false;
0661 break;
0662 default:
0663 WARN_ON(chandef->center_freq2);
0664 break;
0665 }
0666
0667 return (r1 + r2 > 0);
0668 }
0669
0670
0671
0672
0673
0674 bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef,
0675 struct ieee80211_channel *chan,
0676 bool primary_only)
0677 {
0678 int width;
0679 u32 freq;
0680
0681 if (!chandef->chan)
0682 return false;
0683
0684 if (chandef->chan->center_freq == chan->center_freq)
0685 return true;
0686
0687 if (primary_only)
0688 return false;
0689
0690 width = cfg80211_chandef_get_width(chandef);
0691 if (width <= 20)
0692 return false;
0693
0694 for (freq = chandef->center_freq1 - width / 2 + 10;
0695 freq <= chandef->center_freq1 + width / 2 - 10; freq += 20) {
0696 if (chan->center_freq == freq)
0697 return true;
0698 }
0699
0700 if (!chandef->center_freq2)
0701 return false;
0702
0703 for (freq = chandef->center_freq2 - width / 2 + 10;
0704 freq <= chandef->center_freq2 + width / 2 - 10; freq += 20) {
0705 if (chan->center_freq == freq)
0706 return true;
0707 }
0708
0709 return false;
0710 }
0711
0712 bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
0713 {
0714 unsigned int link;
0715
0716 ASSERT_WDEV_LOCK(wdev);
0717
0718 switch (wdev->iftype) {
0719 case NL80211_IFTYPE_AP:
0720 case NL80211_IFTYPE_P2P_GO:
0721 for_each_valid_link(wdev, link) {
0722 if (wdev->links[link].ap.beacon_interval)
0723 return true;
0724 }
0725 break;
0726 case NL80211_IFTYPE_ADHOC:
0727 if (wdev->u.ibss.ssid_len)
0728 return true;
0729 break;
0730 case NL80211_IFTYPE_MESH_POINT:
0731 if (wdev->u.mesh.id_len)
0732 return true;
0733 break;
0734 case NL80211_IFTYPE_STATION:
0735 case NL80211_IFTYPE_OCB:
0736 case NL80211_IFTYPE_P2P_CLIENT:
0737 case NL80211_IFTYPE_MONITOR:
0738 case NL80211_IFTYPE_AP_VLAN:
0739 case NL80211_IFTYPE_P2P_DEVICE:
0740
0741 case NL80211_IFTYPE_NAN:
0742 break;
0743 case NL80211_IFTYPE_UNSPECIFIED:
0744 case NL80211_IFTYPE_WDS:
0745 case NUM_NL80211_IFTYPES:
0746 WARN_ON(1);
0747 }
0748
0749 return false;
0750 }
0751
0752 bool cfg80211_wdev_on_sub_chan(struct wireless_dev *wdev,
0753 struct ieee80211_channel *chan,
0754 bool primary_only)
0755 {
0756 unsigned int link;
0757
0758 switch (wdev->iftype) {
0759 case NL80211_IFTYPE_AP:
0760 case NL80211_IFTYPE_P2P_GO:
0761 for_each_valid_link(wdev, link) {
0762 if (cfg80211_is_sub_chan(&wdev->links[link].ap.chandef,
0763 chan, primary_only))
0764 return true;
0765 }
0766 break;
0767 case NL80211_IFTYPE_ADHOC:
0768 return cfg80211_is_sub_chan(&wdev->u.ibss.chandef, chan,
0769 primary_only);
0770 case NL80211_IFTYPE_MESH_POINT:
0771 return cfg80211_is_sub_chan(&wdev->u.mesh.chandef, chan,
0772 primary_only);
0773 default:
0774 break;
0775 }
0776
0777 return false;
0778 }
0779
0780 static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy,
0781 struct ieee80211_channel *chan)
0782 {
0783 struct wireless_dev *wdev;
0784
0785 list_for_each_entry(wdev, &wiphy->wdev_list, list) {
0786 wdev_lock(wdev);
0787 if (!cfg80211_beaconing_iface_active(wdev)) {
0788 wdev_unlock(wdev);
0789 continue;
0790 }
0791
0792 if (cfg80211_wdev_on_sub_chan(wdev, chan, false)) {
0793 wdev_unlock(wdev);
0794 return true;
0795 }
0796 wdev_unlock(wdev);
0797 }
0798
0799 return false;
0800 }
0801
0802 static bool
0803 cfg80211_offchan_chain_is_active(struct cfg80211_registered_device *rdev,
0804 struct ieee80211_channel *channel)
0805 {
0806 if (!rdev->background_radar_wdev)
0807 return false;
0808
0809 if (!cfg80211_chandef_valid(&rdev->background_radar_chandef))
0810 return false;
0811
0812 return cfg80211_is_sub_chan(&rdev->background_radar_chandef, channel,
0813 false);
0814 }
0815
0816 bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
0817 struct ieee80211_channel *chan)
0818 {
0819 struct cfg80211_registered_device *rdev;
0820
0821 ASSERT_RTNL();
0822
0823 if (!(chan->flags & IEEE80211_CHAN_RADAR))
0824 return false;
0825
0826 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
0827 if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
0828 continue;
0829
0830 if (cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan))
0831 return true;
0832
0833 if (cfg80211_offchan_chain_is_active(rdev, chan))
0834 return true;
0835 }
0836
0837 return false;
0838 }
0839
0840 static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
0841 u32 center_freq,
0842 u32 bandwidth)
0843 {
0844 struct ieee80211_channel *c;
0845 u32 freq, start_freq, end_freq;
0846 bool dfs_offload;
0847
0848 dfs_offload = wiphy_ext_feature_isset(wiphy,
0849 NL80211_EXT_FEATURE_DFS_OFFLOAD);
0850
0851 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
0852 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
0853
0854
0855
0856
0857
0858
0859 for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
0860 c = ieee80211_get_channel_khz(wiphy, freq);
0861 if (!c)
0862 return false;
0863
0864 if (c->flags & IEEE80211_CHAN_DISABLED)
0865 return false;
0866
0867 if ((c->flags & IEEE80211_CHAN_RADAR) &&
0868 (c->dfs_state != NL80211_DFS_AVAILABLE) &&
0869 !(c->dfs_state == NL80211_DFS_USABLE && dfs_offload))
0870 return false;
0871 }
0872
0873 return true;
0874 }
0875
0876 static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
0877 const struct cfg80211_chan_def *chandef)
0878 {
0879 int width;
0880 int r;
0881
0882 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
0883 return false;
0884
0885 width = cfg80211_chandef_get_width(chandef);
0886 if (width < 0)
0887 return false;
0888
0889 r = cfg80211_get_chans_dfs_available(wiphy,
0890 MHZ_TO_KHZ(chandef->center_freq1),
0891 width);
0892
0893
0894 if (!r)
0895 return r;
0896
0897 switch (chandef->width) {
0898 case NL80211_CHAN_WIDTH_80P80:
0899 WARN_ON(!chandef->center_freq2);
0900 r = cfg80211_get_chans_dfs_available(wiphy,
0901 MHZ_TO_KHZ(chandef->center_freq2),
0902 width);
0903 break;
0904 default:
0905 WARN_ON(chandef->center_freq2);
0906 break;
0907 }
0908
0909 return r;
0910 }
0911
0912 static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
0913 u32 center_freq,
0914 u32 bandwidth)
0915 {
0916 struct ieee80211_channel *c;
0917 u32 start_freq, end_freq, freq;
0918 unsigned int dfs_cac_ms = 0;
0919
0920 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
0921 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
0922
0923 for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
0924 c = ieee80211_get_channel_khz(wiphy, freq);
0925 if (!c)
0926 return 0;
0927
0928 if (c->flags & IEEE80211_CHAN_DISABLED)
0929 return 0;
0930
0931 if (!(c->flags & IEEE80211_CHAN_RADAR))
0932 continue;
0933
0934 if (c->dfs_cac_ms > dfs_cac_ms)
0935 dfs_cac_ms = c->dfs_cac_ms;
0936 }
0937
0938 return dfs_cac_ms;
0939 }
0940
0941 unsigned int
0942 cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
0943 const struct cfg80211_chan_def *chandef)
0944 {
0945 int width;
0946 unsigned int t1 = 0, t2 = 0;
0947
0948 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
0949 return 0;
0950
0951 width = cfg80211_chandef_get_width(chandef);
0952 if (width < 0)
0953 return 0;
0954
0955 t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
0956 MHZ_TO_KHZ(chandef->center_freq1),
0957 width);
0958
0959 if (!chandef->center_freq2)
0960 return t1;
0961
0962 t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
0963 MHZ_TO_KHZ(chandef->center_freq2),
0964 width);
0965
0966 return max(t1, t2);
0967 }
0968
0969 static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
0970 u32 center_freq, u32 bandwidth,
0971 u32 prohibited_flags)
0972 {
0973 struct ieee80211_channel *c;
0974 u32 freq, start_freq, end_freq;
0975
0976 start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
0977 end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
0978
0979 for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
0980 c = ieee80211_get_channel_khz(wiphy, freq);
0981 if (!c || c->flags & prohibited_flags)
0982 return false;
0983 }
0984
0985 return true;
0986 }
0987
0988
0989 static bool cfg80211_edmg_usable(struct wiphy *wiphy, u8 edmg_channels,
0990 enum ieee80211_edmg_bw_config edmg_bw_config,
0991 int primary_channel,
0992 struct ieee80211_edmg *edmg_cap)
0993 {
0994 struct ieee80211_channel *chan;
0995 int i, freq;
0996 int channels_counter = 0;
0997
0998 if (!edmg_channels && !edmg_bw_config)
0999 return true;
1000
1001 if ((!edmg_channels && edmg_bw_config) ||
1002 (edmg_channels && !edmg_bw_config))
1003 return false;
1004
1005 if (!(edmg_channels & BIT(primary_channel - 1)))
1006 return false;
1007
1008
1009 for (i = 0; i < 6; i++) {
1010 if (!(edmg_channels & BIT(i)))
1011 continue;
1012
1013 if (!(edmg_cap->channels & BIT(i)))
1014 return false;
1015
1016 channels_counter++;
1017
1018 freq = ieee80211_channel_to_frequency(i + 1,
1019 NL80211_BAND_60GHZ);
1020 chan = ieee80211_get_channel(wiphy, freq);
1021 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
1022 return false;
1023 }
1024
1025
1026 if (channels_counter > 4)
1027 return false;
1028
1029
1030
1031
1032 if ((edmg_bw_config % 4) > (edmg_cap->bw_config % 4))
1033 return false;
1034
1035 if (edmg_bw_config > edmg_cap->bw_config)
1036 return false;
1037
1038 return true;
1039 }
1040
1041 bool cfg80211_chandef_usable(struct wiphy *wiphy,
1042 const struct cfg80211_chan_def *chandef,
1043 u32 prohibited_flags)
1044 {
1045 struct ieee80211_sta_ht_cap *ht_cap;
1046 struct ieee80211_sta_vht_cap *vht_cap;
1047 struct ieee80211_edmg *edmg_cap;
1048 u32 width, control_freq, cap;
1049 bool ext_nss_cap, support_80_80 = false, support_320 = false;
1050 const struct ieee80211_sband_iftype_data *iftd;
1051 struct ieee80211_supported_band *sband;
1052 int i;
1053
1054 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
1055 return false;
1056
1057 ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
1058 vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
1059 edmg_cap = &wiphy->bands[chandef->chan->band]->edmg_cap;
1060 ext_nss_cap = __le16_to_cpu(vht_cap->vht_mcs.tx_highest) &
1061 IEEE80211_VHT_EXT_NSS_BW_CAPABLE;
1062
1063 if (edmg_cap->channels &&
1064 !cfg80211_edmg_usable(wiphy,
1065 chandef->edmg.channels,
1066 chandef->edmg.bw_config,
1067 chandef->chan->hw_value,
1068 edmg_cap))
1069 return false;
1070
1071 control_freq = chandef->chan->center_freq;
1072
1073 switch (chandef->width) {
1074 case NL80211_CHAN_WIDTH_1:
1075 width = 1;
1076 break;
1077 case NL80211_CHAN_WIDTH_2:
1078 width = 2;
1079 break;
1080 case NL80211_CHAN_WIDTH_4:
1081 width = 4;
1082 break;
1083 case NL80211_CHAN_WIDTH_8:
1084 width = 8;
1085 break;
1086 case NL80211_CHAN_WIDTH_16:
1087 width = 16;
1088 break;
1089 case NL80211_CHAN_WIDTH_5:
1090 width = 5;
1091 break;
1092 case NL80211_CHAN_WIDTH_10:
1093 prohibited_flags |= IEEE80211_CHAN_NO_10MHZ;
1094 width = 10;
1095 break;
1096 case NL80211_CHAN_WIDTH_20:
1097 if (!ht_cap->ht_supported &&
1098 chandef->chan->band != NL80211_BAND_6GHZ)
1099 return false;
1100 fallthrough;
1101 case NL80211_CHAN_WIDTH_20_NOHT:
1102 prohibited_flags |= IEEE80211_CHAN_NO_20MHZ;
1103 width = 20;
1104 break;
1105 case NL80211_CHAN_WIDTH_40:
1106 width = 40;
1107 if (chandef->chan->band == NL80211_BAND_6GHZ)
1108 break;
1109 if (!ht_cap->ht_supported)
1110 return false;
1111 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
1112 ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
1113 return false;
1114 if (chandef->center_freq1 < control_freq &&
1115 chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
1116 return false;
1117 if (chandef->center_freq1 > control_freq &&
1118 chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
1119 return false;
1120 break;
1121 case NL80211_CHAN_WIDTH_80P80:
1122 cap = vht_cap->cap;
1123 support_80_80 =
1124 (cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) ||
1125 (cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
1126 cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) ||
1127 (ext_nss_cap &&
1128 u32_get_bits(cap, IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) > 1);
1129 if (chandef->chan->band != NL80211_BAND_6GHZ && !support_80_80)
1130 return false;
1131 fallthrough;
1132 case NL80211_CHAN_WIDTH_80:
1133 prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
1134 width = 80;
1135 if (chandef->chan->band == NL80211_BAND_6GHZ)
1136 break;
1137 if (!vht_cap->vht_supported)
1138 return false;
1139 break;
1140 case NL80211_CHAN_WIDTH_160:
1141 prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
1142 width = 160;
1143 if (chandef->chan->band == NL80211_BAND_6GHZ)
1144 break;
1145 if (!vht_cap->vht_supported)
1146 return false;
1147 cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
1148 if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
1149 cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ &&
1150 !(ext_nss_cap &&
1151 (vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)))
1152 return false;
1153 break;
1154 case NL80211_CHAN_WIDTH_320:
1155 prohibited_flags |= IEEE80211_CHAN_NO_320MHZ;
1156 width = 320;
1157
1158 if (chandef->chan->band != NL80211_BAND_6GHZ)
1159 return false;
1160
1161 sband = wiphy->bands[NL80211_BAND_6GHZ];
1162 if (!sband)
1163 return false;
1164
1165 for (i = 0; i < sband->n_iftype_data; i++) {
1166 iftd = &sband->iftype_data[i];
1167 if (!iftd->eht_cap.has_eht)
1168 continue;
1169
1170 if (iftd->eht_cap.eht_cap_elem.phy_cap_info[0] &
1171 IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) {
1172 support_320 = true;
1173 break;
1174 }
1175 }
1176
1177 if (!support_320)
1178 return false;
1179 break;
1180 default:
1181 WARN_ON_ONCE(1);
1182 return false;
1183 }
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196 if (width > 20)
1197 prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
1198
1199
1200 if (width < 20)
1201 prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
1202
1203
1204 if (!cfg80211_secondary_chans_ok(wiphy,
1205 ieee80211_chandef_to_khz(chandef),
1206 width, prohibited_flags))
1207 return false;
1208
1209 if (!chandef->center_freq2)
1210 return true;
1211 return cfg80211_secondary_chans_ok(wiphy,
1212 MHZ_TO_KHZ(chandef->center_freq2),
1213 width, prohibited_flags);
1214 }
1215 EXPORT_SYMBOL(cfg80211_chandef_usable);
1216
1217 static bool cfg80211_ir_permissive_check_wdev(enum nl80211_iftype iftype,
1218 struct wireless_dev *wdev,
1219 struct ieee80211_channel *chan)
1220 {
1221 struct ieee80211_channel *other_chan = NULL;
1222 unsigned int link_id;
1223 int r1, r2;
1224
1225 for_each_valid_link(wdev, link_id) {
1226 if (wdev->iftype == NL80211_IFTYPE_STATION &&
1227 wdev->links[link_id].client.current_bss)
1228 other_chan = wdev->links[link_id].client.current_bss->pub.channel;
1229
1230
1231
1232
1233
1234
1235
1236
1237 if (iftype == NL80211_IFTYPE_P2P_GO &&
1238 wdev->iftype == NL80211_IFTYPE_P2P_GO &&
1239 wdev->links[link_id].ap.beacon_interval &&
1240 !(chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
1241 other_chan = wdev->links[link_id].ap.chandef.chan;
1242
1243 if (!other_chan)
1244 continue;
1245
1246 if (chan == other_chan)
1247 return true;
1248
1249 if (chan->band != NL80211_BAND_5GHZ &&
1250 chan->band != NL80211_BAND_6GHZ)
1251 continue;
1252
1253 r1 = cfg80211_get_unii(chan->center_freq);
1254 r2 = cfg80211_get_unii(other_chan->center_freq);
1255
1256 if (r1 != -EINVAL && r1 == r2) {
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269 if (chan->center_freq == 5825 &&
1270 other_chan->center_freq != 5825)
1271 continue;
1272 return true;
1273 }
1274 }
1275
1276 return false;
1277 }
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288 static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy,
1289 enum nl80211_iftype iftype,
1290 struct ieee80211_channel *chan)
1291 {
1292 struct wireless_dev *wdev;
1293 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1294
1295 lockdep_assert_held(&rdev->wiphy.mtx);
1296
1297 if (!IS_ENABLED(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
1298 !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR))
1299 return false;
1300
1301
1302 if (iftype != NL80211_IFTYPE_P2P_GO &&
1303 iftype != NL80211_IFTYPE_STATION &&
1304 iftype != NL80211_IFTYPE_P2P_CLIENT)
1305 return false;
1306
1307 if (regulatory_indoor_allowed() &&
1308 (chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
1309 return true;
1310
1311 if (!(chan->flags & IEEE80211_CHAN_IR_CONCURRENT))
1312 return false;
1313
1314
1315
1316
1317
1318
1319
1320
1321 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
1322 bool ret;
1323
1324 wdev_lock(wdev);
1325 ret = cfg80211_ir_permissive_check_wdev(iftype, wdev, chan);
1326 wdev_unlock(wdev);
1327
1328 if (ret)
1329 return ret;
1330 }
1331
1332 return false;
1333 }
1334
1335 static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy,
1336 struct cfg80211_chan_def *chandef,
1337 enum nl80211_iftype iftype,
1338 bool check_no_ir)
1339 {
1340 bool res;
1341 u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
1342 IEEE80211_CHAN_RADAR;
1343
1344 trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
1345
1346 if (check_no_ir)
1347 prohibited_flags |= IEEE80211_CHAN_NO_IR;
1348
1349 if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
1350 cfg80211_chandef_dfs_available(wiphy, chandef)) {
1351
1352 prohibited_flags = IEEE80211_CHAN_DISABLED;
1353 }
1354
1355 res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags);
1356
1357 trace_cfg80211_return_bool(res);
1358 return res;
1359 }
1360
1361 bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
1362 struct cfg80211_chan_def *chandef,
1363 enum nl80211_iftype iftype)
1364 {
1365 return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, true);
1366 }
1367 EXPORT_SYMBOL(cfg80211_reg_can_beacon);
1368
1369 bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
1370 struct cfg80211_chan_def *chandef,
1371 enum nl80211_iftype iftype)
1372 {
1373 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1374 bool check_no_ir;
1375
1376 lockdep_assert_held(&rdev->wiphy.mtx);
1377
1378
1379
1380
1381
1382
1383
1384 check_no_ir = !cfg80211_ir_permissive_chan(wiphy, iftype,
1385 chandef->chan);
1386
1387 return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
1388 }
1389 EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax);
1390
1391 int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
1392 struct cfg80211_chan_def *chandef)
1393 {
1394 if (!rdev->ops->set_monitor_channel)
1395 return -EOPNOTSUPP;
1396 if (!cfg80211_has_monitors_only(rdev))
1397 return -EBUSY;
1398
1399 return rdev_set_monitor_channel(rdev, chandef);
1400 }
1401
1402 bool cfg80211_any_usable_channels(struct wiphy *wiphy,
1403 unsigned long sband_mask,
1404 u32 prohibited_flags)
1405 {
1406 int idx;
1407
1408 prohibited_flags |= IEEE80211_CHAN_DISABLED;
1409
1410 for_each_set_bit(idx, &sband_mask, NUM_NL80211_BANDS) {
1411 struct ieee80211_supported_band *sband = wiphy->bands[idx];
1412 int chanidx;
1413
1414 if (!sband)
1415 continue;
1416
1417 for (chanidx = 0; chanidx < sband->n_channels; chanidx++) {
1418 struct ieee80211_channel *chan;
1419
1420 chan = &sband->channels[chanidx];
1421
1422 if (chan->flags & prohibited_flags)
1423 continue;
1424
1425 return true;
1426 }
1427 }
1428
1429 return false;
1430 }
1431 EXPORT_SYMBOL(cfg80211_any_usable_channels);
1432
1433 struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
1434 unsigned int link_id)
1435 {
1436
1437
1438
1439
1440
1441
1442
1443 if (link_id || wdev->valid_links & BIT(0)) {
1444 ASSERT_WDEV_LOCK(wdev);
1445 WARN_ON(!(wdev->valid_links & BIT(link_id)));
1446 }
1447
1448 switch (wdev->iftype) {
1449 case NL80211_IFTYPE_MESH_POINT:
1450 return &wdev->u.mesh.chandef;
1451 case NL80211_IFTYPE_ADHOC:
1452 return &wdev->u.ibss.chandef;
1453 case NL80211_IFTYPE_OCB:
1454 return &wdev->u.ocb.chandef;
1455 case NL80211_IFTYPE_AP:
1456 case NL80211_IFTYPE_P2P_GO:
1457 return &wdev->links[link_id].ap.chandef;
1458 default:
1459 return NULL;
1460 }
1461 }
1462 EXPORT_SYMBOL(wdev_chandef);