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