~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/wireless/chan.c

Version: ~ [ linux-5.4-rc3 ] ~ [ linux-5.3.6 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.79 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.149 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.196 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.196 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.75 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * This file contains helper code to handle channel
  4  * settings and keeping track of what is possible at
  5  * any point in time.
  6  *
  7  * Copyright 2009       Johannes Berg <johannes@sipsolutions.net>
  8  * Copyright 2013-2014  Intel Mobile Communications GmbH
  9  */
 10 
 11 #include <linux/export.h>
 12 #include <net/cfg80211.h>
 13 #include "core.h"
 14 #include "rdev-ops.h"
 15 
 16 void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
 17                              struct ieee80211_channel *chan,
 18                              enum nl80211_channel_type chan_type)
 19 {
 20         if (WARN_ON(!chan))
 21                 return;
 22 
 23         chandef->chan = chan;
 24         chandef->center_freq2 = 0;
 25 
 26         switch (chan_type) {
 27         case NL80211_CHAN_NO_HT:
 28                 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
 29                 chandef->center_freq1 = chan->center_freq;
 30                 break;
 31         case NL80211_CHAN_HT20:
 32                 chandef->width = NL80211_CHAN_WIDTH_20;
 33                 chandef->center_freq1 = chan->center_freq;
 34                 break;
 35         case NL80211_CHAN_HT40PLUS:
 36                 chandef->width = NL80211_CHAN_WIDTH_40;
 37                 chandef->center_freq1 = chan->center_freq + 10;
 38                 break;
 39         case NL80211_CHAN_HT40MINUS:
 40                 chandef->width = NL80211_CHAN_WIDTH_40;
 41                 chandef->center_freq1 = chan->center_freq - 10;
 42                 break;
 43         default:
 44                 WARN_ON(1);
 45         }
 46 }
 47 EXPORT_SYMBOL(cfg80211_chandef_create);
 48 
 49 bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
 50 {
 51         u32 control_freq;
 52 
 53         if (!chandef->chan)
 54                 return false;
 55 
 56         control_freq = chandef->chan->center_freq;
 57 
 58         switch (chandef->width) {
 59         case NL80211_CHAN_WIDTH_5:
 60         case NL80211_CHAN_WIDTH_10:
 61         case NL80211_CHAN_WIDTH_20:
 62         case NL80211_CHAN_WIDTH_20_NOHT:
 63                 if (chandef->center_freq1 != control_freq)
 64                         return false;
 65                 if (chandef->center_freq2)
 66                         return false;
 67                 break;
 68         case NL80211_CHAN_WIDTH_40:
 69                 if (chandef->center_freq1 != control_freq + 10 &&
 70                     chandef->center_freq1 != control_freq - 10)
 71                         return false;
 72                 if (chandef->center_freq2)
 73                         return false;
 74                 break;
 75         case NL80211_CHAN_WIDTH_80P80:
 76                 if (chandef->center_freq1 != control_freq + 30 &&
 77                     chandef->center_freq1 != control_freq + 10 &&
 78                     chandef->center_freq1 != control_freq - 10 &&
 79                     chandef->center_freq1 != control_freq - 30)
 80                         return false;
 81                 if (!chandef->center_freq2)
 82                         return false;
 83                 /* adjacent is not allowed -- that's a 160 MHz channel */
 84                 if (chandef->center_freq1 - chandef->center_freq2 == 80 ||
 85                     chandef->center_freq2 - chandef->center_freq1 == 80)
 86                         return false;
 87                 break;
 88         case NL80211_CHAN_WIDTH_80:
 89                 if (chandef->center_freq1 != control_freq + 30 &&
 90                     chandef->center_freq1 != control_freq + 10 &&
 91                     chandef->center_freq1 != control_freq - 10 &&
 92                     chandef->center_freq1 != control_freq - 30)
 93                         return false;
 94                 if (chandef->center_freq2)
 95                         return false;
 96                 break;
 97         case NL80211_CHAN_WIDTH_160:
 98                 if (chandef->center_freq1 != control_freq + 70 &&
 99                     chandef->center_freq1 != control_freq + 50 &&
100                     chandef->center_freq1 != control_freq + 30 &&
101                     chandef->center_freq1 != control_freq + 10 &&
102                     chandef->center_freq1 != control_freq - 10 &&
103                     chandef->center_freq1 != control_freq - 30 &&
104                     chandef->center_freq1 != control_freq - 50 &&
105                     chandef->center_freq1 != control_freq - 70)
106                         return false;
107                 if (chandef->center_freq2)
108                         return false;
109                 break;
110         default:
111                 return false;
112         }
113 
114         return true;
115 }
116 EXPORT_SYMBOL(cfg80211_chandef_valid);
117 
118 static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
119                                   u32 *pri40, u32 *pri80)
120 {
121         int tmp;
122 
123         switch (c->width) {
124         case NL80211_CHAN_WIDTH_40:
125                 *pri40 = c->center_freq1;
126                 *pri80 = 0;
127                 break;
128         case NL80211_CHAN_WIDTH_80:
129         case NL80211_CHAN_WIDTH_80P80:
130                 *pri80 = c->center_freq1;
131                 /* n_P20 */
132                 tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
133                 /* n_P40 */
134                 tmp /= 2;
135                 /* freq_P40 */
136                 *pri40 = c->center_freq1 - 20 + 40 * tmp;
137                 break;
138         case NL80211_CHAN_WIDTH_160:
139                 /* n_P20 */
140                 tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
141                 /* n_P40 */
142                 tmp /= 2;
143                 /* freq_P40 */
144                 *pri40 = c->center_freq1 - 60 + 40 * tmp;
145                 /* n_P80 */
146                 tmp /= 2;
147                 *pri80 = c->center_freq1 - 40 + 80 * tmp;
148                 break;
149         default:
150                 WARN_ON_ONCE(1);
151         }
152 }
153 
154 static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
155 {
156         int width;
157 
158         switch (c->width) {
159         case NL80211_CHAN_WIDTH_5:
160                 width = 5;
161                 break;
162         case NL80211_CHAN_WIDTH_10:
163                 width = 10;
164                 break;
165         case NL80211_CHAN_WIDTH_20:
166         case NL80211_CHAN_WIDTH_20_NOHT:
167                 width = 20;
168                 break;
169         case NL80211_CHAN_WIDTH_40:
170                 width = 40;
171                 break;
172         case NL80211_CHAN_WIDTH_80P80:
173         case NL80211_CHAN_WIDTH_80:
174                 width = 80;
175                 break;
176         case NL80211_CHAN_WIDTH_160:
177                 width = 160;
178                 break;
179         default:
180                 WARN_ON_ONCE(1);
181                 return -1;
182         }
183         return width;
184 }
185 
186 const struct cfg80211_chan_def *
187 cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
188                             const struct cfg80211_chan_def *c2)
189 {
190         u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80;
191 
192         /* If they are identical, return */
193         if (cfg80211_chandef_identical(c1, c2))
194                 return c1;
195 
196         /* otherwise, must have same control channel */
197         if (c1->chan != c2->chan)
198                 return NULL;
199 
200         /*
201          * If they have the same width, but aren't identical,
202          * then they can't be compatible.
203          */
204         if (c1->width == c2->width)
205                 return NULL;
206 
207         /*
208          * can't be compatible if one of them is 5 or 10 MHz,
209          * but they don't have the same width.
210          */
211         if (c1->width == NL80211_CHAN_WIDTH_5 ||
212             c1->width == NL80211_CHAN_WIDTH_10 ||
213             c2->width == NL80211_CHAN_WIDTH_5 ||
214             c2->width == NL80211_CHAN_WIDTH_10)
215                 return NULL;
216 
217         if (c1->width == NL80211_CHAN_WIDTH_20_NOHT ||
218             c1->width == NL80211_CHAN_WIDTH_20)
219                 return c2;
220 
221         if (c2->width == NL80211_CHAN_WIDTH_20_NOHT ||
222             c2->width == NL80211_CHAN_WIDTH_20)
223                 return c1;
224 
225         chandef_primary_freqs(c1, &c1_pri40, &c1_pri80);
226         chandef_primary_freqs(c2, &c2_pri40, &c2_pri80);
227 
228         if (c1_pri40 != c2_pri40)
229                 return NULL;
230 
231         WARN_ON(!c1_pri80 && !c2_pri80);
232         if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80)
233                 return NULL;
234 
235         if (c1->width > c2->width)
236                 return c1;
237         return c2;
238 }
239 EXPORT_SYMBOL(cfg80211_chandef_compatible);
240 
241 static void cfg80211_set_chans_dfs_state(struct wiphy *wiphy, u32 center_freq,
242                                          u32 bandwidth,
243                                          enum nl80211_dfs_state dfs_state)
244 {
245         struct ieee80211_channel *c;
246         u32 freq;
247 
248         for (freq = center_freq - bandwidth/2 + 10;
249              freq <= center_freq + bandwidth/2 - 10;
250              freq += 20) {
251                 c = ieee80211_get_channel(wiphy, freq);
252                 if (!c || !(c->flags & IEEE80211_CHAN_RADAR))
253                         continue;
254 
255                 c->dfs_state = dfs_state;
256                 c->dfs_state_entered = jiffies;
257         }
258 }
259 
260 void cfg80211_set_dfs_state(struct wiphy *wiphy,
261                             const struct cfg80211_chan_def *chandef,
262                             enum nl80211_dfs_state dfs_state)
263 {
264         int width;
265 
266         if (WARN_ON(!cfg80211_chandef_valid(chandef)))
267                 return;
268 
269         width = cfg80211_chandef_get_width(chandef);
270         if (width < 0)
271                 return;
272 
273         cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq1,
274                                      width, dfs_state);
275 
276         if (!chandef->center_freq2)
277                 return;
278         cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq2,
279                                      width, dfs_state);
280 }
281 
282 static u32 cfg80211_get_start_freq(u32 center_freq,
283                                    u32 bandwidth)
284 {
285         u32 start_freq;
286 
287         if (bandwidth <= 20)
288                 start_freq = center_freq;
289         else
290                 start_freq = center_freq - bandwidth/2 + 10;
291 
292         return start_freq;
293 }
294 
295 static u32 cfg80211_get_end_freq(u32 center_freq,
296                                  u32 bandwidth)
297 {
298         u32 end_freq;
299 
300         if (bandwidth <= 20)
301                 end_freq = center_freq;
302         else
303                 end_freq = center_freq + bandwidth/2 - 10;
304 
305         return end_freq;
306 }
307 
308 static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
309                                             u32 center_freq,
310                                             u32 bandwidth)
311 {
312         struct ieee80211_channel *c;
313         u32 freq, start_freq, end_freq;
314 
315         start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
316         end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
317 
318         for (freq = start_freq; freq <= end_freq; freq += 20) {
319                 c = ieee80211_get_channel(wiphy, freq);
320                 if (!c)
321                         return -EINVAL;
322 
323                 if (c->flags & IEEE80211_CHAN_RADAR)
324                         return 1;
325         }
326         return 0;
327 }
328 
329 
330 int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
331                                   const struct cfg80211_chan_def *chandef,
332                                   enum nl80211_iftype iftype)
333 {
334         int width;
335         int ret;
336 
337         if (WARN_ON(!cfg80211_chandef_valid(chandef)))
338                 return -EINVAL;
339 
340         switch (iftype) {
341         case NL80211_IFTYPE_ADHOC:
342         case NL80211_IFTYPE_AP:
343         case NL80211_IFTYPE_P2P_GO:
344         case NL80211_IFTYPE_MESH_POINT:
345                 width = cfg80211_chandef_get_width(chandef);
346                 if (width < 0)
347                         return -EINVAL;
348 
349                 ret = cfg80211_get_chans_dfs_required(wiphy,
350                                                       chandef->center_freq1,
351                                                       width);
352                 if (ret < 0)
353                         return ret;
354                 else if (ret > 0)
355                         return BIT(chandef->width);
356 
357                 if (!chandef->center_freq2)
358                         return 0;
359 
360                 ret = cfg80211_get_chans_dfs_required(wiphy,
361                                                       chandef->center_freq2,
362                                                       width);
363                 if (ret < 0)
364                         return ret;
365                 else if (ret > 0)
366                         return BIT(chandef->width);
367 
368                 break;
369         case NL80211_IFTYPE_STATION:
370         case NL80211_IFTYPE_OCB:
371         case NL80211_IFTYPE_P2P_CLIENT:
372         case NL80211_IFTYPE_MONITOR:
373         case NL80211_IFTYPE_AP_VLAN:
374         case NL80211_IFTYPE_WDS:
375         case NL80211_IFTYPE_P2P_DEVICE:
376         case NL80211_IFTYPE_NAN:
377                 break;
378         case NL80211_IFTYPE_UNSPECIFIED:
379         case NUM_NL80211_IFTYPES:
380                 WARN_ON(1);
381         }
382 
383         return 0;
384 }
385 EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
386 
387 static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy,
388                                          u32 center_freq,
389                                          u32 bandwidth)
390 {
391         struct ieee80211_channel *c;
392         u32 freq, start_freq, end_freq;
393         int count = 0;
394 
395         start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
396         end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
397 
398         /*
399          * Check entire range of channels for the bandwidth.
400          * Check all channels are DFS channels (DFS_USABLE or
401          * DFS_AVAILABLE). Return number of usable channels
402          * (require CAC). Allow DFS and non-DFS channel mix.
403          */
404         for (freq = start_freq; freq <= end_freq; freq += 20) {
405                 c = ieee80211_get_channel(wiphy, freq);
406                 if (!c)
407                         return -EINVAL;
408 
409                 if (c->flags & IEEE80211_CHAN_DISABLED)
410                         return -EINVAL;
411 
412                 if (c->flags & IEEE80211_CHAN_RADAR) {
413                         if (c->dfs_state == NL80211_DFS_UNAVAILABLE)
414                                 return -EINVAL;
415 
416                         if (c->dfs_state == NL80211_DFS_USABLE)
417                                 count++;
418                 }
419         }
420 
421         return count;
422 }
423 
424 bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
425                                  const struct cfg80211_chan_def *chandef)
426 {
427         int width;
428         int r1, r2 = 0;
429 
430         if (WARN_ON(!cfg80211_chandef_valid(chandef)))
431                 return false;
432 
433         width = cfg80211_chandef_get_width(chandef);
434         if (width < 0)
435                 return false;
436 
437         r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1,
438                                           width);
439 
440         if (r1 < 0)
441                 return false;
442 
443         switch (chandef->width) {
444         case NL80211_CHAN_WIDTH_80P80:
445                 WARN_ON(!chandef->center_freq2);
446                 r2 = cfg80211_get_chans_dfs_usable(wiphy,
447                                                    chandef->center_freq2,
448                                                    width);
449                 if (r2 < 0)
450                         return false;
451                 break;
452         default:
453                 WARN_ON(chandef->center_freq2);
454                 break;
455         }
456 
457         return (r1 + r2 > 0);
458 }
459 
460 /*
461  * Checks if center frequency of chan falls with in the bandwidth
462  * range of chandef.
463  */
464 bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef,
465                           struct ieee80211_channel *chan)
466 {
467         int width;
468         u32 freq;
469 
470         if (chandef->chan->center_freq == chan->center_freq)
471                 return true;
472 
473         width = cfg80211_chandef_get_width(chandef);
474         if (width <= 20)
475                 return false;
476 
477         for (freq = chandef->center_freq1 - width / 2 + 10;
478              freq <= chandef->center_freq1 + width / 2 - 10; freq += 20) {
479                 if (chan->center_freq == freq)
480                         return true;
481         }
482 
483         if (!chandef->center_freq2)
484                 return false;
485 
486         for (freq = chandef->center_freq2 - width / 2 + 10;
487              freq <= chandef->center_freq2 + width / 2 - 10; freq += 20) {
488                 if (chan->center_freq == freq)
489                         return true;
490         }
491 
492         return false;
493 }
494 
495 bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
496 {
497         bool active = false;
498 
499         ASSERT_WDEV_LOCK(wdev);
500 
501         if (!wdev->chandef.chan)
502                 return false;
503 
504         switch (wdev->iftype) {
505         case NL80211_IFTYPE_AP:
506         case NL80211_IFTYPE_P2P_GO:
507                 active = wdev->beacon_interval != 0;
508                 break;
509         case NL80211_IFTYPE_ADHOC:
510                 active = wdev->ssid_len != 0;
511                 break;
512         case NL80211_IFTYPE_MESH_POINT:
513                 active = wdev->mesh_id_len != 0;
514                 break;
515         case NL80211_IFTYPE_STATION:
516         case NL80211_IFTYPE_OCB:
517         case NL80211_IFTYPE_P2P_CLIENT:
518         case NL80211_IFTYPE_MONITOR:
519         case NL80211_IFTYPE_AP_VLAN:
520         case NL80211_IFTYPE_WDS:
521         case NL80211_IFTYPE_P2P_DEVICE:
522         /* Can NAN type be considered as beaconing interface? */
523         case NL80211_IFTYPE_NAN:
524                 break;
525         case NL80211_IFTYPE_UNSPECIFIED:
526         case NUM_NL80211_IFTYPES:
527                 WARN_ON(1);
528         }
529 
530         return active;
531 }
532 
533 static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy,
534                                         struct ieee80211_channel *chan)
535 {
536         struct wireless_dev *wdev;
537 
538         list_for_each_entry(wdev, &wiphy->wdev_list, list) {
539                 wdev_lock(wdev);
540                 if (!cfg80211_beaconing_iface_active(wdev)) {
541                         wdev_unlock(wdev);
542                         continue;
543                 }
544 
545                 if (cfg80211_is_sub_chan(&wdev->chandef, chan)) {
546                         wdev_unlock(wdev);
547                         return true;
548                 }
549                 wdev_unlock(wdev);
550         }
551 
552         return false;
553 }
554 
555 bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
556                                   struct ieee80211_channel *chan)
557 {
558         struct cfg80211_registered_device *rdev;
559 
560         ASSERT_RTNL();
561 
562         if (!(chan->flags & IEEE80211_CHAN_RADAR))
563                 return false;
564 
565         list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
566                 if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
567                         continue;
568 
569                 if (cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan))
570                         return true;
571         }
572 
573         return false;
574 }
575 
576 static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
577                                              u32 center_freq,
578                                              u32 bandwidth)
579 {
580         struct ieee80211_channel *c;
581         u32 freq, start_freq, end_freq;
582 
583         start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
584         end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
585 
586         /*
587          * Check entire range of channels for the bandwidth.
588          * If any channel in between is disabled or has not
589          * had gone through CAC return false
590          */
591         for (freq = start_freq; freq <= end_freq; freq += 20) {
592                 c = ieee80211_get_channel(wiphy, freq);
593                 if (!c)
594                         return false;
595 
596                 if (c->flags & IEEE80211_CHAN_DISABLED)
597                         return false;
598 
599                 if ((c->flags & IEEE80211_CHAN_RADAR)  &&
600                     (c->dfs_state != NL80211_DFS_AVAILABLE))
601                         return false;
602         }
603 
604         return true;
605 }
606 
607 static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
608                                 const struct cfg80211_chan_def *chandef)
609 {
610         int width;
611         int r;
612 
613         if (WARN_ON(!cfg80211_chandef_valid(chandef)))
614                 return false;
615 
616         width = cfg80211_chandef_get_width(chandef);
617         if (width < 0)
618                 return false;
619 
620         r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1,
621                                              width);
622 
623         /* If any of channels unavailable for cf1 just return */
624         if (!r)
625                 return r;
626 
627         switch (chandef->width) {
628         case NL80211_CHAN_WIDTH_80P80:
629                 WARN_ON(!chandef->center_freq2);
630                 r = cfg80211_get_chans_dfs_available(wiphy,
631                                                      chandef->center_freq2,
632                                                      width);
633                 break;
634         default:
635                 WARN_ON(chandef->center_freq2);
636                 break;
637         }
638 
639         return r;
640 }
641 
642 static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
643                                                     u32 center_freq,
644                                                     u32 bandwidth)
645 {
646         struct ieee80211_channel *c;
647         u32 start_freq, end_freq, freq;
648         unsigned int dfs_cac_ms = 0;
649 
650         start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
651         end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
652 
653         for (freq = start_freq; freq <= end_freq; freq += 20) {
654                 c = ieee80211_get_channel(wiphy, freq);
655                 if (!c)
656                         return 0;
657 
658                 if (c->flags & IEEE80211_CHAN_DISABLED)
659                         return 0;
660 
661                 if (!(c->flags & IEEE80211_CHAN_RADAR))
662                         continue;
663 
664                 if (c->dfs_cac_ms > dfs_cac_ms)
665                         dfs_cac_ms = c->dfs_cac_ms;
666         }
667 
668         return dfs_cac_ms;
669 }
670 
671 unsigned int
672 cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
673                               const struct cfg80211_chan_def *chandef)
674 {
675         int width;
676         unsigned int t1 = 0, t2 = 0;
677 
678         if (WARN_ON(!cfg80211_chandef_valid(chandef)))
679                 return 0;
680 
681         width = cfg80211_chandef_get_width(chandef);
682         if (width < 0)
683                 return 0;
684 
685         t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
686                                              chandef->center_freq1,
687                                              width);
688 
689         if (!chandef->center_freq2)
690                 return t1;
691 
692         t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
693                                              chandef->center_freq2,
694                                              width);
695 
696         return max(t1, t2);
697 }
698 
699 static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
700                                         u32 center_freq, u32 bandwidth,
701                                         u32 prohibited_flags)
702 {
703         struct ieee80211_channel *c;
704         u32 freq, start_freq, end_freq;
705 
706         start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
707         end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
708 
709         for (freq = start_freq; freq <= end_freq; freq += 20) {
710                 c = ieee80211_get_channel(wiphy, freq);
711                 if (!c || c->flags & prohibited_flags)
712                         return false;
713         }
714 
715         return true;
716 }
717 
718 bool cfg80211_chandef_usable(struct wiphy *wiphy,
719                              const struct cfg80211_chan_def *chandef,
720                              u32 prohibited_flags)
721 {
722         struct ieee80211_sta_ht_cap *ht_cap;
723         struct ieee80211_sta_vht_cap *vht_cap;
724         u32 width, control_freq, cap;
725 
726         if (WARN_ON(!cfg80211_chandef_valid(chandef)))
727                 return false;
728 
729         ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
730         vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
731 
732         control_freq = chandef->chan->center_freq;
733 
734         switch (chandef->width) {
735         case NL80211_CHAN_WIDTH_5:
736                 width = 5;
737                 break;
738         case NL80211_CHAN_WIDTH_10:
739                 prohibited_flags |= IEEE80211_CHAN_NO_10MHZ;
740                 width = 10;
741                 break;
742         case NL80211_CHAN_WIDTH_20:
743                 if (!ht_cap->ht_supported)
744                         return false;
745         case NL80211_CHAN_WIDTH_20_NOHT:
746                 prohibited_flags |= IEEE80211_CHAN_NO_20MHZ;
747                 width = 20;
748                 break;
749         case NL80211_CHAN_WIDTH_40:
750                 width = 40;
751                 if (!ht_cap->ht_supported)
752                         return false;
753                 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
754                     ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
755                         return false;
756                 if (chandef->center_freq1 < control_freq &&
757                     chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
758                         return false;
759                 if (chandef->center_freq1 > control_freq &&
760                     chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
761                         return false;
762                 break;
763         case NL80211_CHAN_WIDTH_80P80:
764                 cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
765                 if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
766                         return false;
767         case NL80211_CHAN_WIDTH_80:
768                 if (!vht_cap->vht_supported)
769                         return false;
770                 prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
771                 width = 80;
772                 break;
773         case NL80211_CHAN_WIDTH_160:
774                 if (!vht_cap->vht_supported)
775                         return false;
776                 cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
777                 if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
778                     cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
779                         return false;
780                 prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
781                 width = 160;
782                 break;
783         default:
784                 WARN_ON_ONCE(1);
785                 return false;
786         }
787 
788         /*
789          * TODO: What if there are only certain 80/160/80+80 MHz channels
790          *       allowed by the driver, or only certain combinations?
791          *       For 40 MHz the driver can set the NO_HT40 flags, but for
792          *       80/160 MHz and in particular 80+80 MHz this isn't really
793          *       feasible and we only have NO_80MHZ/NO_160MHZ so far but
794          *       no way to cover 80+80 MHz or more complex restrictions.
795          *       Note that such restrictions also need to be advertised to
796          *       userspace, for example for P2P channel selection.
797          */
798 
799         if (width > 20)
800                 prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
801 
802         /* 5 and 10 MHz are only defined for the OFDM PHY */
803         if (width < 20)
804                 prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
805 
806 
807         if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
808                                          width, prohibited_flags))
809                 return false;
810 
811         if (!chandef->center_freq2)
812                 return true;
813         return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2,
814                                            width, prohibited_flags);
815 }
816 EXPORT_SYMBOL(cfg80211_chandef_usable);
817 
818 /*
819  * Check if the channel can be used under permissive conditions mandated by
820  * some regulatory bodies, i.e., the channel is marked with
821  * IEEE80211_CHAN_IR_CONCURRENT and there is an additional station interface
822  * associated to an AP on the same channel or on the same UNII band
823  * (assuming that the AP is an authorized master).
824  * In addition allow operation on a channel on which indoor operation is
825  * allowed, iff we are currently operating in an indoor environment.
826  */
827 static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy,
828                                         enum nl80211_iftype iftype,
829                                         struct ieee80211_channel *chan)
830 {
831         struct wireless_dev *wdev;
832         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
833 
834         ASSERT_RTNL();
835 
836         if (!IS_ENABLED(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
837             !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR))
838                 return false;
839 
840         /* only valid for GO and TDLS off-channel (station/p2p-CL) */
841         if (iftype != NL80211_IFTYPE_P2P_GO &&
842             iftype != NL80211_IFTYPE_STATION &&
843             iftype != NL80211_IFTYPE_P2P_CLIENT)
844                 return false;
845 
846         if (regulatory_indoor_allowed() &&
847             (chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
848                 return true;
849 
850         if (!(chan->flags & IEEE80211_CHAN_IR_CONCURRENT))
851                 return false;
852 
853         /*
854          * Generally, it is possible to rely on another device/driver to allow
855          * the IR concurrent relaxation, however, since the device can further
856          * enforce the relaxation (by doing a similar verifications as this),
857          * and thus fail the GO instantiation, consider only the interfaces of
858          * the current registered device.
859          */
860         list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
861                 struct ieee80211_channel *other_chan = NULL;
862                 int r1, r2;
863 
864                 wdev_lock(wdev);
865                 if (wdev->iftype == NL80211_IFTYPE_STATION &&
866                     wdev->current_bss)
867                         other_chan = wdev->current_bss->pub.channel;
868 
869                 /*
870                  * If a GO already operates on the same GO_CONCURRENT channel,
871                  * this one (maybe the same one) can beacon as well. We allow
872                  * the operation even if the station we relied on with
873                  * GO_CONCURRENT is disconnected now. But then we must make sure
874                  * we're not outdoor on an indoor-only channel.
875                  */
876                 if (iftype == NL80211_IFTYPE_P2P_GO &&
877                     wdev->iftype == NL80211_IFTYPE_P2P_GO &&
878                     wdev->beacon_interval &&
879                     !(chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
880                         other_chan = wdev->chandef.chan;
881                 wdev_unlock(wdev);
882 
883                 if (!other_chan)
884                         continue;
885 
886                 if (chan == other_chan)
887                         return true;
888 
889                 if (chan->band != NL80211_BAND_5GHZ)
890                         continue;
891 
892                 r1 = cfg80211_get_unii(chan->center_freq);
893                 r2 = cfg80211_get_unii(other_chan->center_freq);
894 
895                 if (r1 != -EINVAL && r1 == r2) {
896                         /*
897                          * At some locations channels 149-165 are considered a
898                          * bundle, but at other locations, e.g., Indonesia,
899                          * channels 149-161 are considered a bundle while
900                          * channel 165 is left out and considered to be in a
901                          * different bundle. Thus, in case that there is a
902                          * station interface connected to an AP on channel 165,
903                          * it is assumed that channels 149-161 are allowed for
904                          * GO operations. However, having a station interface
905                          * connected to an AP on channels 149-161, does not
906                          * allow GO operation on channel 165.
907                          */
908                         if (chan->center_freq == 5825 &&
909                             other_chan->center_freq != 5825)
910                                 continue;
911                         return true;
912                 }
913         }
914 
915         return false;
916 }
917 
918 static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy,
919                                      struct cfg80211_chan_def *chandef,
920                                      enum nl80211_iftype iftype,
921                                      bool check_no_ir)
922 {
923         bool res;
924         u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
925                                IEEE80211_CHAN_RADAR;
926 
927         trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
928 
929         if (check_no_ir)
930                 prohibited_flags |= IEEE80211_CHAN_NO_IR;
931 
932         if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
933             cfg80211_chandef_dfs_available(wiphy, chandef)) {
934                 /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
935                 prohibited_flags = IEEE80211_CHAN_DISABLED;
936         }
937 
938         res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags);
939 
940         trace_cfg80211_return_bool(res);
941         return res;
942 }
943 
944 bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
945                              struct cfg80211_chan_def *chandef,
946                              enum nl80211_iftype iftype)
947 {
948         return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, true);
949 }
950 EXPORT_SYMBOL(cfg80211_reg_can_beacon);
951 
952 bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
953                                    struct cfg80211_chan_def *chandef,
954                                    enum nl80211_iftype iftype)
955 {
956         bool check_no_ir;
957 
958         ASSERT_RTNL();
959 
960         /*
961          * Under certain conditions suggested by some regulatory bodies a
962          * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
963          * only if such relaxations are not enabled and the conditions are not
964          * met.
965          */
966         check_no_ir = !cfg80211_ir_permissive_chan(wiphy, iftype,
967                                                    chandef->chan);
968 
969         return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
970 }
971 EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax);
972 
973 int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
974                                  struct cfg80211_chan_def *chandef)
975 {
976         if (!rdev->ops->set_monitor_channel)
977                 return -EOPNOTSUPP;
978         if (!cfg80211_has_monitors_only(rdev))
979                 return -EBUSY;
980 
981         return rdev_set_monitor_channel(rdev, chandef);
982 }
983 
984 void
985 cfg80211_get_chan_state(struct wireless_dev *wdev,
986                         struct ieee80211_channel **chan,
987                         enum cfg80211_chan_mode *chanmode,
988                         u8 *radar_detect)
989 {
990         int ret;
991 
992         *chan = NULL;
993         *chanmode = CHAN_MODE_UNDEFINED;
994 
995         ASSERT_WDEV_LOCK(wdev);
996 
997         if (wdev->netdev && !netif_running(wdev->netdev))
998                 return;
999 
1000         switch (wdev->iftype) {
1001         case NL80211_IFTYPE_ADHOC:
1002                 if (wdev->current_bss) {
1003                         *chan = wdev->current_bss->pub.channel;
1004                         *chanmode = (wdev->ibss_fixed &&
1005                                      !wdev->ibss_dfs_possible)
1006                                   ? CHAN_MODE_SHARED
1007                                   : CHAN_MODE_EXCLUSIVE;
1008 
1009                         /* consider worst-case - IBSS can try to return to the
1010                          * original user-specified channel as creator */
1011                         if (wdev->ibss_dfs_possible)
1012                                 *radar_detect |= BIT(wdev->chandef.width);
1013                         return;
1014                 }
1015                 break;
1016         case NL80211_IFTYPE_STATION:
1017         case NL80211_IFTYPE_P2P_CLIENT:
1018                 if (wdev->current_bss) {
1019                         *chan = wdev->current_bss->pub.channel;
1020                         *chanmode = CHAN_MODE_SHARED;
1021                         return;
1022                 }
1023                 break;
1024         case NL80211_IFTYPE_AP:
1025         case NL80211_IFTYPE_P2P_GO:
1026                 if (wdev->cac_started) {
1027                         *chan = wdev->chandef.chan;
1028                         *chanmode = CHAN_MODE_SHARED;
1029                         *radar_detect |= BIT(wdev->chandef.width);
1030                 } else if (wdev->beacon_interval) {
1031                         *chan = wdev->chandef.chan;
1032                         *chanmode = CHAN_MODE_SHARED;
1033 
1034                         ret = cfg80211_chandef_dfs_required(wdev->wiphy,
1035                                                             &wdev->chandef,
1036                                                             wdev->iftype);
1037                         WARN_ON(ret < 0);
1038                         if (ret > 0)
1039                                 *radar_detect |= BIT(wdev->chandef.width);
1040                 }
1041                 return;
1042         case NL80211_IFTYPE_MESH_POINT:
1043                 if (wdev->mesh_id_len) {
1044                         *chan = wdev->chandef.chan;
1045                         *chanmode = CHAN_MODE_SHARED;
1046 
1047                         ret = cfg80211_chandef_dfs_required(wdev->wiphy,
1048                                                             &wdev->chandef,
1049                                                             wdev->iftype);
1050                         WARN_ON(ret < 0);
1051                         if (ret > 0)
1052                                 *radar_detect |= BIT(wdev->chandef.width);
1053                 }
1054                 return;
1055         case NL80211_IFTYPE_OCB:
1056                 if (wdev->chandef.chan) {
1057                         *chan = wdev->chandef.chan;
1058                         *chanmode = CHAN_MODE_SHARED;
1059                         return;
1060                 }
1061                 break;
1062         case NL80211_IFTYPE_MONITOR:
1063         case NL80211_IFTYPE_AP_VLAN:
1064         case NL80211_IFTYPE_WDS:
1065         case NL80211_IFTYPE_P2P_DEVICE:
1066         case NL80211_IFTYPE_NAN:
1067                 /* these interface types don't really have a channel */
1068                 return;
1069         case NL80211_IFTYPE_UNSPECIFIED:
1070         case NUM_NL80211_IFTYPES:
1071                 WARN_ON(1);
1072         }
1073 }
1074 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp