^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright 2002-2005, Instant802 Networks, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2005-2006, Devicescape Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2013-2014 Intel Mobile Communications GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2017 Intel Deutschland GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2018 - 2019 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Permission to use, copy, modify, and/or distribute this software for any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * purpose with or without fee is hereby granted, provided that the above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * copyright notice and this permission notice appear in all copies.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * DOC: Wireless regulatory infrastructure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * The usual implementation is for a driver to read a device EEPROM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * determine which regulatory domain it should be operating under, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * looking up the allowable channels in a driver-local table and finally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * registering those channels in the wiphy structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Another set of compliance enforcement is for drivers to use their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * own compliance limits which can be stored on the EEPROM. The host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * driver or firmware may ensure these are used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * In addition to all this we provide an extra layer of regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * conformance. For drivers which do not have any regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * information CRDA provides the complete regulatory solution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * For others it provides a community effort on further restrictions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * to enhance compliance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Note: When number of rules --> infinity we will not be able to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * index on alpha2 any more, instead we'll probably have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * rely on some SHA1 checksum of the regdomain for example.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/nl80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/verification.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <net/cfg80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #include "reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include "rdev-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include "nl80211.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Grace period we give before making sure all current interfaces reside on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * channels allowed by the current regulatory domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define REG_ENFORCE_GRACE_MS 60000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * enum reg_request_treatment - regulatory request treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * @REG_REQ_OK: continue processing the regulatory request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * @REG_REQ_IGNORE: ignore the regulatory request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * @REG_REQ_INTERSECT: the regulatory domain resulting from this request should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * be intersected with the current one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * @REG_REQ_ALREADY_SET: the regulatory request will not change the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * regulatory settings, and no further processing is required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) enum reg_request_treatment {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) REG_REQ_OK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) REG_REQ_IGNORE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) REG_REQ_INTERSECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) REG_REQ_ALREADY_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static struct regulatory_request core_request_world = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .initiator = NL80211_REGDOM_SET_BY_CORE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .alpha2[0] = '0',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .alpha2[1] = '0',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .intersect = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .processed = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .country_ie_env = ENVIRON_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Receipt of information from last regulatory request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * protected by RTNL (and can be accessed with RCU protection)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static struct regulatory_request __rcu *last_request =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) (void __force __rcu *)&core_request_world;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* To trigger userspace events and load firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static struct platform_device *reg_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Central wireless core regulatory domains, we only need two,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * the current one and a world regulatory domain in case we have no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * information to give us an alpha2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * (protected by RTNL, can be read under RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * Number of devices that registered to the core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * that support cellular base station regulatory hints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * (protected by RTNL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int reg_num_devs_support_basehint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * State variable indicating if the platform on which the devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * are attached is operating in an indoor environment. The state variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * is relevant for all registered devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static bool reg_is_indoor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static spinlock_t reg_indoor_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Used to track the userspace process controlling the indoor setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static u32 reg_is_indoor_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void restore_regulatory_settings(bool reset_user, bool cached);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static void print_regdomain(const struct ieee80211_regdomain *rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return rcu_dereference_rtnl(cfg80211_regdomain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return rcu_dereference_rtnl(wiphy->regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) switch (dfs_region) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) case NL80211_DFS_UNSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return "unset";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case NL80211_DFS_FCC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return "FCC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) case NL80211_DFS_ETSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return "ETSI";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case NL80211_DFS_JP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return "JP";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return "Unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) const struct ieee80211_regdomain *regd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) const struct ieee80211_regdomain *wiphy_regd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) regd = get_cfg80211_regdom();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (!wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) wiphy_regd = get_wiphy_regdom(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!wiphy_regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (wiphy_regd->dfs_region == regd->dfs_region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) pr_debug("%s: device specific dfs_region (%s) disagrees with cfg80211's central dfs_region (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) dev_name(&wiphy->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) reg_dfs_region_str(wiphy_regd->dfs_region),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) reg_dfs_region_str(regd->dfs_region));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return regd->dfs_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static void rcu_free_regdom(const struct ieee80211_regdomain *r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) kfree_rcu((struct ieee80211_regdomain *)r, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static struct regulatory_request *get_last_request(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return rcu_dereference_rtnl(last_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* Used to queue up regulatory hints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static LIST_HEAD(reg_requests_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static spinlock_t reg_requests_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* Used to queue up beacon hints for review */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static LIST_HEAD(reg_pending_beacons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static spinlock_t reg_pending_beacons_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* Used to keep track of processed beacon hints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static LIST_HEAD(reg_beacon_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct reg_beacon {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct ieee80211_channel chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static void reg_check_chans_work(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static DECLARE_DELAYED_WORK(reg_check_chans, reg_check_chans_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void reg_todo(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static DECLARE_WORK(reg_work, reg_todo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* We keep a static world regulatory domain in case of the absence of CRDA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static const struct ieee80211_regdomain world_regdom = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .n_reg_rules = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .alpha2 = "00",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .reg_rules = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* IEEE 802.11b/g, channels 1..11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* IEEE 802.11b/g, channels 12..13. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) REG_RULE(2467-10, 2472+10, 20, 6, 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) NL80211_RRF_NO_IR | NL80211_RRF_AUTO_BW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* IEEE 802.11 channel 14 - Only JP enables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * this and for 802.11b only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) REG_RULE(2484-10, 2484+10, 20, 6, 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) NL80211_RRF_NO_IR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) NL80211_RRF_NO_OFDM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* IEEE 802.11a, channel 36..48 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) REG_RULE(5180-10, 5240+10, 80, 6, 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) NL80211_RRF_NO_IR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) NL80211_RRF_AUTO_BW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* IEEE 802.11a, channel 52..64 - DFS required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) REG_RULE(5260-10, 5320+10, 80, 6, 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) NL80211_RRF_NO_IR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) NL80211_RRF_AUTO_BW |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) NL80211_RRF_DFS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* IEEE 802.11a, channel 100..144 - DFS required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) REG_RULE(5500-10, 5720+10, 160, 6, 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) NL80211_RRF_NO_IR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) NL80211_RRF_DFS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* IEEE 802.11a, channel 149..165 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) REG_RULE(5745-10, 5825+10, 80, 6, 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) NL80211_RRF_NO_IR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* IEEE 802.11ad (60GHz), channels 1..3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* protected by RTNL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static const struct ieee80211_regdomain *cfg80211_world_regdom =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) &world_regdom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static char *ieee80211_regdom = "00";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static char user_alpha2[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static const struct ieee80211_regdomain *cfg80211_user_regdom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) module_param(ieee80211_regdom, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static void reg_free_request(struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (request == &core_request_world)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (request != get_last_request())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) kfree(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static void reg_free_last_request(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (lr != &core_request_world && lr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) kfree_rcu(lr, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static void reg_update_last_request(struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct regulatory_request *lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (lr == request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) reg_free_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) rcu_assign_pointer(last_request, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static void reset_regdomains(bool full_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) const struct ieee80211_regdomain *new_regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) const struct ieee80211_regdomain *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) r = get_cfg80211_regdom();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* avoid freeing static information or freeing something twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (r == cfg80211_world_regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) r = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (cfg80211_world_regdom == &world_regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) cfg80211_world_regdom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (r == &world_regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) r = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) rcu_free_regdom(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) rcu_free_regdom(cfg80211_world_regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) cfg80211_world_regdom = &world_regdom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) rcu_assign_pointer(cfg80211_regdomain, new_regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (!full_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) reg_update_last_request(&core_request_world);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * Dynamic world regulatory domain requested by the wireless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * core upon initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static void update_world_regdomain(const struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct regulatory_request *lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) WARN_ON(!lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) reset_regdomains(false, rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) cfg80211_world_regdom = rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) bool is_world_regdom(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (!alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return alpha2[0] == '0' && alpha2[1] == '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static bool is_alpha2_set(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (!alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return alpha2[0] && alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static bool is_unknown_alpha2(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (!alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * Special case where regulatory domain was built by driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * but a specific alpha2 cannot be determined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return alpha2[0] == '9' && alpha2[1] == '9';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static bool is_intersected_alpha2(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * Special case where regulatory domain is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * result of an intersection between two regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return alpha2[0] == '9' && alpha2[1] == '8';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static bool is_an_alpha2(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return isalpha(alpha2[0]) && isalpha(alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!alpha2_x || !alpha2_y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return alpha2_x[0] == alpha2_y[0] && alpha2_x[1] == alpha2_y[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static bool regdom_changes(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) const struct ieee80211_regdomain *r = get_cfg80211_regdom();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return !alpha2_equal(r->alpha2, alpha2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * The NL80211_REGDOM_SET_BY_USER regdom alpha2 is cached, this lets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * you know if a valid regulatory hint with NL80211_REGDOM_SET_BY_USER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * has ever been issued.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static bool is_user_regdom_saved(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (user_alpha2[0] == '9' && user_alpha2[1] == '7')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* This would indicate a mistake on the design */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (WARN(!is_world_regdom(user_alpha2) && !is_an_alpha2(user_alpha2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) "Unexpected user alpha2: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) user_alpha2[0], user_alpha2[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static const struct ieee80211_regdomain *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) reg_copy_regd(const struct ieee80211_regdomain *src_regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct ieee80211_regdomain *regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) regd = kzalloc(struct_size(regd, reg_rules, src_regd->n_reg_rules),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (!regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) for (i = 0; i < src_regd->n_reg_rules; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) memcpy(®d->reg_rules[i], &src_regd->reg_rules[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) sizeof(struct ieee80211_reg_rule));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static void cfg80211_save_user_regdom(const struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (!IS_ERR(cfg80211_user_regdom))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) kfree(cfg80211_user_regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) cfg80211_user_regdom = reg_copy_regd(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct reg_regdb_apply_request {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) const struct ieee80211_regdomain *regdom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static LIST_HEAD(reg_regdb_apply_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static DEFINE_MUTEX(reg_regdb_apply_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static void reg_regdb_apply(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct reg_regdb_apply_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) mutex_lock(®_regdb_apply_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) while (!list_empty(®_regdb_apply_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) request = list_first_entry(®_regdb_apply_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct reg_regdb_apply_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) list_del(&request->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) set_regdom(request->regdom, REGD_SOURCE_INTERNAL_DB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) kfree(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) mutex_unlock(®_regdb_apply_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static DECLARE_WORK(reg_regdb_work, reg_regdb_apply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int reg_schedule_apply(const struct ieee80211_regdomain *regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct reg_regdb_apply_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (!request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) kfree(regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) request->regdom = regdom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) mutex_lock(®_regdb_apply_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) list_add_tail(&request->list, ®_regdb_apply_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) mutex_unlock(®_regdb_apply_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) schedule_work(®_regdb_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) #ifdef CONFIG_CFG80211_CRDA_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /* Max number of consecutive attempts to communicate with CRDA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) #define REG_MAX_CRDA_TIMEOUTS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static u32 reg_crda_timeouts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static void crda_timeout_work(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static DECLARE_DELAYED_WORK(crda_timeout, crda_timeout_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static void crda_timeout_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) pr_debug("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) reg_crda_timeouts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) restore_regulatory_settings(true, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static void cancel_crda_timeout(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) cancel_delayed_work(&crda_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static void cancel_crda_timeout_sync(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) cancel_delayed_work_sync(&crda_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static void reset_crda_timeouts(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) reg_crda_timeouts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * This lets us keep regulatory code which is updated on a regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * basis in userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static int call_crda(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) char country[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) char *env[] = { country, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) snprintf(country, sizeof(country), "COUNTRY=%c%c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) alpha2[0], alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (!is_world_regdom((char *) alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) pr_debug("Calling CRDA for country: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) alpha2[0], alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) pr_debug("Calling CRDA to update world regulatory domain\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) ret = kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) queue_delayed_work(system_power_efficient_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) &crda_timeout, msecs_to_jiffies(3142));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static inline void cancel_crda_timeout(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static inline void cancel_crda_timeout_sync(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static inline void reset_crda_timeouts(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static inline int call_crda(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) #endif /* CONFIG_CFG80211_CRDA_SUPPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* code to directly load a firmware database through request_firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static const struct fwdb_header *regdb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct fwdb_country {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) u8 alpha2[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) __be16 coll_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* this struct cannot be extended */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) } __packed __aligned(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct fwdb_collection {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) u8 n_rules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) u8 dfs_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* no optional data yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* aligned to 2, then followed by __be16 array of rule pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) } __packed __aligned(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) enum fwdb_flags {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) FWDB_FLAG_NO_OFDM = BIT(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) FWDB_FLAG_NO_OUTDOOR = BIT(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) FWDB_FLAG_DFS = BIT(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) FWDB_FLAG_NO_IR = BIT(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) FWDB_FLAG_AUTO_BW = BIT(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct fwdb_wmm_ac {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) u8 ecw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) u8 aifsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) __be16 cot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct fwdb_wmm_rule {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) struct fwdb_wmm_ac client[IEEE80211_NUM_ACS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) struct fwdb_wmm_ac ap[IEEE80211_NUM_ACS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct fwdb_rule {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) u8 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) __be16 max_eirp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) __be32 start, end, max_bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* start of optional data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) __be16 cac_timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) __be16 wmm_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) } __packed __aligned(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) #define FWDB_MAGIC 0x52474442
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) #define FWDB_VERSION 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct fwdb_header {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) __be32 magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) __be32 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct fwdb_country country[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) } __packed __aligned(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int ecw2cw(int ecw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return (1 << ecw) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static bool valid_wmm(struct fwdb_wmm_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct fwdb_wmm_ac *ac = (struct fwdb_wmm_ac *)rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) for (i = 0; i < IEEE80211_NUM_ACS * 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) u16 cw_min = ecw2cw((ac[i].ecw & 0xf0) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) u16 cw_max = ecw2cw(ac[i].ecw & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) u8 aifsn = ac[i].aifsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (cw_min >= cw_max)
^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) if (aifsn < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct fwdb_rule *rule = (void *)(data + (rule_ptr << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if ((u8 *)rule + sizeof(rule->len) > data + size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* mandatory fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (rule->len < offsetofend(struct fwdb_rule, max_bw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct fwdb_wmm_rule *wmm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (wmm_ptr + sizeof(struct fwdb_wmm_rule) > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) wmm = (void *)(data + wmm_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (!valid_wmm(wmm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static bool valid_country(const u8 *data, unsigned int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) const struct fwdb_country *country)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct fwdb_collection *coll = (void *)(data + ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) __be16 *rules_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /* make sure we can read len/n_rules */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if ((u8 *)coll + offsetofend(typeof(*coll), n_rules) > data + size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /* make sure base struct and all rules fit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if ((u8 *)coll + ALIGN(coll->len, 2) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) (coll->n_rules * 2) > data + size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /* mandatory fields must exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (coll->len < offsetofend(struct fwdb_collection, dfs_region))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) for (i = 0; i < coll->n_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) u16 rule_ptr = be16_to_cpu(rules_ptr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (!valid_rule(data, size, rule_ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) #ifdef CONFIG_CFG80211_REQUIRE_SIGNED_REGDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static struct key *builtin_regdb_keys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static void __init load_keys_from_buffer(const u8 *p, unsigned int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) const u8 *end = p + buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) size_t plen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) key_ref_t key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) while (p < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * than 256 bytes in size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (end - p < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) goto dodgy_cert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (p[0] != 0x30 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) p[1] != 0x82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) goto dodgy_cert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) plen = (p[2] << 8) | p[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) plen += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (plen > end - p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto dodgy_cert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) key = key_create_or_update(make_key_ref(builtin_regdb_keys, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) "asymmetric", NULL, p, plen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) KEY_USR_VIEW | KEY_USR_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) KEY_ALLOC_NOT_IN_QUOTA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) KEY_ALLOC_BUILT_IN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) KEY_ALLOC_BYPASS_RESTRICTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (IS_ERR(key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) PTR_ERR(key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) pr_notice("Loaded X.509 cert '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) key_ref_to_ptr(key)->description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) key_ref_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) p += plen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) dodgy_cert:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) pr_err("Problem parsing in-kernel X.509 certificate list\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static int __init load_builtin_regdb_keys(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) builtin_regdb_keys =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) keyring_alloc(".builtin_regdb_keys",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (IS_ERR(builtin_regdb_keys))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return PTR_ERR(builtin_regdb_keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pr_notice("Loading compiled-in X.509 certificates for regulatory database\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) #ifdef CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) load_keys_from_buffer(shipped_regdb_certs, shipped_regdb_certs_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) #ifdef CONFIG_CFG80211_EXTRA_REGDB_KEYDIR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (CONFIG_CFG80211_EXTRA_REGDB_KEYDIR[0] != '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) load_keys_from_buffer(extra_regdb_certs, extra_regdb_certs_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) const struct firmware *sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) bool result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (request_firmware(&sig, "regulatory.db.p7s", ®_pdev->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) result = verify_pkcs7_signature(data, size, sig->data, sig->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) builtin_regdb_keys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) VERIFYING_UNSPECIFIED_SIGNATURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) NULL, NULL) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) release_firmware(sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return result;
^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 void free_regdb_keyring(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) key_put(builtin_regdb_keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static int load_builtin_regdb_keys(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static void free_regdb_keyring(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) #endif /* CONFIG_CFG80211_REQUIRE_SIGNED_REGDB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static bool valid_regdb(const u8 *data, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) const struct fwdb_header *hdr = (void *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) const struct fwdb_country *country;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (size < sizeof(*hdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (hdr->magic != cpu_to_be32(FWDB_MAGIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (hdr->version != cpu_to_be32(FWDB_VERSION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (!regdb_has_valid_signature(data, size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) country = &hdr->country[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) while ((u8 *)(country + 1) <= data + size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (!country->coll_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (!valid_country(data, size, country))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) country++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) static void set_wmm_rule(const struct fwdb_header *db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) const struct fwdb_country *country,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) const struct fwdb_rule *rule,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) struct ieee80211_reg_rule *rrule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) struct ieee80211_wmm_rule *wmm_rule = &rrule->wmm_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) struct fwdb_wmm_rule *wmm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) unsigned int i, wmm_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) wmm = (void *)((u8 *)db + wmm_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (!valid_wmm(wmm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) pr_err("Invalid regulatory WMM rule %u-%u in domain %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) be32_to_cpu(rule->start), be32_to_cpu(rule->end),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) country->alpha2[0], country->alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) for (i = 0; i < IEEE80211_NUM_ACS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) wmm_rule->client[i].cw_min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) ecw2cw((wmm->client[i].ecw & 0xf0) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) wmm_rule->client[i].cw_max = ecw2cw(wmm->client[i].ecw & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) wmm_rule->client[i].aifsn = wmm->client[i].aifsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) wmm_rule->client[i].cot =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 1000 * be16_to_cpu(wmm->client[i].cot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) wmm_rule->ap[i].cw_min = ecw2cw((wmm->ap[i].ecw & 0xf0) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) wmm_rule->ap[i].cw_max = ecw2cw(wmm->ap[i].ecw & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) wmm_rule->ap[i].aifsn = wmm->ap[i].aifsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) wmm_rule->ap[i].cot = 1000 * be16_to_cpu(wmm->ap[i].cot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) rrule->has_wmm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static int __regdb_query_wmm(const struct fwdb_header *db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) const struct fwdb_country *country, int freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct ieee80211_reg_rule *rrule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) for (i = 0; i < coll->n_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) __be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct fwdb_rule *rule = (void *)((u8 *)db + rule_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (rule->len < offsetofend(struct fwdb_rule, wmm_ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (freq >= KHZ_TO_MHZ(be32_to_cpu(rule->start)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) freq <= KHZ_TO_MHZ(be32_to_cpu(rule->end))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) set_wmm_rule(db, country, rule, rrule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) int reg_query_regdb_wmm(char *alpha2, int freq, struct ieee80211_reg_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) const struct fwdb_header *hdr = regdb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) const struct fwdb_country *country;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (!regdb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (IS_ERR(regdb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return PTR_ERR(regdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) country = &hdr->country[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) while (country->coll_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (alpha2_equal(alpha2, country->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return __regdb_query_wmm(regdb, country, freq, rule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) country++;
^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) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) EXPORT_SYMBOL(reg_query_regdb_wmm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int regdb_query_country(const struct fwdb_header *db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) const struct fwdb_country *country)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) struct ieee80211_regdomain *regdom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) regdom = kzalloc(struct_size(regdom, reg_rules, coll->n_rules),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (!regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) regdom->n_reg_rules = coll->n_rules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) regdom->alpha2[0] = country->alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) regdom->alpha2[1] = country->alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) regdom->dfs_region = coll->dfs_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) for (i = 0; i < regdom->n_reg_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) __be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) struct fwdb_rule *rule = (void *)((u8 *)db + rule_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct ieee80211_reg_rule *rrule = ®dom->reg_rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) rrule->freq_range.start_freq_khz = be32_to_cpu(rule->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) rrule->freq_range.end_freq_khz = be32_to_cpu(rule->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) rrule->freq_range.max_bandwidth_khz = be32_to_cpu(rule->max_bw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) rrule->power_rule.max_antenna_gain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) rrule->power_rule.max_eirp = be16_to_cpu(rule->max_eirp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) rrule->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (rule->flags & FWDB_FLAG_NO_OFDM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) rrule->flags |= NL80211_RRF_NO_OFDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (rule->flags & FWDB_FLAG_NO_OUTDOOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) rrule->flags |= NL80211_RRF_NO_OUTDOOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (rule->flags & FWDB_FLAG_DFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) rrule->flags |= NL80211_RRF_DFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (rule->flags & FWDB_FLAG_NO_IR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) rrule->flags |= NL80211_RRF_NO_IR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (rule->flags & FWDB_FLAG_AUTO_BW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) rrule->flags |= NL80211_RRF_AUTO_BW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) rrule->dfs_cac_ms = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* handle optional data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) rrule->dfs_cac_ms =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) 1000 * be16_to_cpu(rule->cac_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) set_wmm_rule(db, country, rule, rrule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return reg_schedule_apply(regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) static int query_regdb(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) const struct fwdb_header *hdr = regdb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) const struct fwdb_country *country;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (IS_ERR(regdb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return PTR_ERR(regdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) country = &hdr->country[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) while (country->coll_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (alpha2_equal(alpha2, country->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return regdb_query_country(regdb, country);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) country++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) static void regdb_fw_cb(const struct firmware *fw, void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) int set_error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) bool restore = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) void *db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (!fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) pr_info("failed to load regulatory.db\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) set_error = -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) } else if (!valid_regdb(fw->data, fw->size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) pr_info("loaded regulatory.db is malformed or signature is missing/invalid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) set_error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (regdb && !IS_ERR(regdb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) /* negative case - a bug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) * positive case - can happen due to race in case of multiple cb's in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) * queue, due to usage of asynchronous callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * Either case, just restore and free new db.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) } else if (set_error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) regdb = ERR_PTR(set_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) } else if (fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) db = kmemdup(fw->data, fw->size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (db) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) regdb = db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) restore = context && query_regdb(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) restore = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (restore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) restore_regulatory_settings(true, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) kfree(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static int query_regdb_file(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (regdb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) return query_regdb(alpha2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) alpha2 = kmemdup(alpha2, 2, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (!alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return request_firmware_nowait(THIS_MODULE, true, "regulatory.db",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) ®_pdev->dev, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) (void *)alpha2, regdb_fw_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) int reg_reload_regdb(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) void *db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) err = request_firmware(&fw, "regulatory.db", ®_pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (!valid_regdb(fw->data, fw->size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) err = -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) db = kmemdup(fw->data, fw->size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (!db) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (!IS_ERR_OR_NULL(regdb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) kfree(regdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) regdb = db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static bool reg_query_database(struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (query_regdb_file(request->alpha2) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (call_crda(request->alpha2) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) bool reg_is_valid_request(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!lr || lr->processed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return alpha2_equal(lr->alpha2, alpha2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) * Follow the driver's regulatory domain, if present, unless a country
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) * IE has been processed or a user wants to help complaince further
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) lr->initiator != NL80211_REGDOM_SET_BY_USER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) wiphy->regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return get_wiphy_regdom(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return get_cfg80211_regdom();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) reg_get_max_bandwidth_from_range(const struct ieee80211_regdomain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) const struct ieee80211_reg_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) const struct ieee80211_freq_range *freq_range = &rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) const struct ieee80211_freq_range *freq_range_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) const struct ieee80211_reg_rule *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) u32 start_freq, end_freq, idx, no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) for (idx = 0; idx < rd->n_reg_rules; idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (rule == &rd->reg_rules[idx])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (idx == rd->n_reg_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) /* get start_freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) no = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) while (no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) tmp = &rd->reg_rules[--no];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) freq_range_tmp = &tmp->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) freq_range = freq_range_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) start_freq = freq_range->start_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* get end_freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) freq_range = &rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) no = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) while (no < rd->n_reg_rules - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) tmp = &rd->reg_rules[++no];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) freq_range_tmp = &tmp->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) freq_range = freq_range_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) end_freq = freq_range->end_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return end_freq - start_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) const struct ieee80211_reg_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) unsigned int bw = reg_get_max_bandwidth_from_range(rd, rule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (rule->flags & NL80211_RRF_NO_160MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) bw = min_t(unsigned int, bw, MHZ_TO_KHZ(80));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (rule->flags & NL80211_RRF_NO_80MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) bw = min_t(unsigned int, bw, MHZ_TO_KHZ(40));
^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) * HT40+/HT40- limits are handled per-channel. Only limit BW if both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) * are not allowed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (rule->flags & NL80211_RRF_NO_HT40MINUS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) rule->flags & NL80211_RRF_NO_HT40PLUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) bw = min_t(unsigned int, bw, MHZ_TO_KHZ(20));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) return bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) /* Sanity check on a regulatory rule */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) const struct ieee80211_freq_range *freq_range = &rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) u32 freq_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (freq_range->start_freq_khz <= 0 || freq_range->end_freq_khz <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (freq_range->start_freq_khz > freq_range->end_freq_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (freq_range->end_freq_khz <= freq_range->start_freq_khz ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) freq_range->max_bandwidth_khz > freq_diff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) static bool is_valid_rd(const struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) const struct ieee80211_reg_rule *reg_rule = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (!rd->n_reg_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (WARN_ON(rd->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) for (i = 0; i < rd->n_reg_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) reg_rule = &rd->reg_rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (!is_valid_reg_rule(reg_rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) * freq_in_rule_band - tells us if a frequency is in a frequency band
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * @freq_range: frequency rule we want to query
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * @freq_khz: frequency we are inquiring about
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) * This lets us know if a specific frequency rule is or is not relevant to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * a specific frequency's band. Bands are device specific and artificial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * definitions (the "2.4 GHz band", the "5 GHz band" and the "60GHz band"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * however it is safe for now to assume that a frequency rule should not be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) * part of a frequency's band if the start freq or end freq are off by more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 20 GHz for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) * 60 GHz band.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) * This resolution can be lowered and should be considered as we add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) * regulatory rule support for other "bands".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) **/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) u32 freq_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) #define ONE_GHZ_IN_KHZ 1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) * From 802.11ad: directional multi-gigabit (DMG):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) * Pertaining to operation in a frequency band containing a channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) * with the Channel starting frequency above 45 GHz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) u32 limit = freq_khz > 45 * ONE_GHZ_IN_KHZ ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 20 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (abs(freq_khz - freq_range->start_freq_khz) <= limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (abs(freq_khz - freq_range->end_freq_khz) <= limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) #undef ONE_GHZ_IN_KHZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) * Later on we can perhaps use the more restrictive DFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) * region but we don't have information for that yet so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) * for now simply disallow conflicts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) static enum nl80211_dfs_regions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) const enum nl80211_dfs_regions dfs_region2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (dfs_region1 != dfs_region2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) return NL80211_DFS_UNSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return dfs_region1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) static void reg_wmm_rules_intersect(const struct ieee80211_wmm_ac *wmm_ac1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) const struct ieee80211_wmm_ac *wmm_ac2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) struct ieee80211_wmm_ac *intersect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) intersect->cw_min = max_t(u16, wmm_ac1->cw_min, wmm_ac2->cw_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) intersect->cw_max = max_t(u16, wmm_ac1->cw_max, wmm_ac2->cw_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) intersect->cot = min_t(u16, wmm_ac1->cot, wmm_ac2->cot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) intersect->aifsn = max_t(u8, wmm_ac1->aifsn, wmm_ac2->aifsn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * Helper for regdom_intersect(), this does the real
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) * mathematical intersection fun
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) const struct ieee80211_regdomain *rd2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) const struct ieee80211_reg_rule *rule1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) const struct ieee80211_reg_rule *rule2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) struct ieee80211_reg_rule *intersected_rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) const struct ieee80211_freq_range *freq_range1, *freq_range2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) struct ieee80211_freq_range *freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) const struct ieee80211_power_rule *power_rule1, *power_rule2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) struct ieee80211_power_rule *power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) const struct ieee80211_wmm_rule *wmm_rule1, *wmm_rule2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) struct ieee80211_wmm_rule *wmm_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) u32 freq_diff, max_bandwidth1, max_bandwidth2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) freq_range1 = &rule1->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) freq_range2 = &rule2->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) freq_range = &intersected_rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) power_rule1 = &rule1->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) power_rule2 = &rule2->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) power_rule = &intersected_rule->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) wmm_rule1 = &rule1->wmm_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) wmm_rule2 = &rule2->wmm_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) wmm_rule = &intersected_rule->wmm_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) freq_range->start_freq_khz = max(freq_range1->start_freq_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) freq_range2->start_freq_khz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) freq_range2->end_freq_khz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) max_bandwidth1 = freq_range1->max_bandwidth_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) max_bandwidth2 = freq_range2->max_bandwidth_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (rule1->flags & NL80211_RRF_AUTO_BW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (rule2->flags & NL80211_RRF_AUTO_BW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) max_bandwidth2 = reg_get_max_bandwidth(rd2, rule2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) freq_range->max_bandwidth_khz = min(max_bandwidth1, max_bandwidth2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) intersected_rule->flags = rule1->flags | rule2->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) * In case NL80211_RRF_AUTO_BW requested for both rules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) * set AUTO_BW in intersected rule also. Next we will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) * calculate BW correctly in handle_channel function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) * In other case remove AUTO_BW flag while we calculate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) * maximum bandwidth correctly and auto calculation is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) * not required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if ((rule1->flags & NL80211_RRF_AUTO_BW) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) (rule2->flags & NL80211_RRF_AUTO_BW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) intersected_rule->flags |= NL80211_RRF_AUTO_BW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) intersected_rule->flags &= ~NL80211_RRF_AUTO_BW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (freq_range->max_bandwidth_khz > freq_diff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) freq_range->max_bandwidth_khz = freq_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) power_rule->max_eirp = min(power_rule1->max_eirp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) power_rule2->max_eirp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) power_rule2->max_antenna_gain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) rule2->dfs_cac_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) if (rule1->has_wmm && rule2->has_wmm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) u8 ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) reg_wmm_rules_intersect(&wmm_rule1->client[ac],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) &wmm_rule2->client[ac],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) &wmm_rule->client[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) reg_wmm_rules_intersect(&wmm_rule1->ap[ac],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) &wmm_rule2->ap[ac],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) &wmm_rule->ap[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) intersected_rule->has_wmm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) } else if (rule1->has_wmm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) *wmm_rule = *wmm_rule1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) intersected_rule->has_wmm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) } else if (rule2->has_wmm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) *wmm_rule = *wmm_rule2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) intersected_rule->has_wmm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) intersected_rule->has_wmm = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (!is_valid_reg_rule(intersected_rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) /* check whether old rule contains new rule */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) static bool rule_contains(struct ieee80211_reg_rule *r1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) struct ieee80211_reg_rule *r2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) /* for simplicity, currently consider only same flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) if (r1->flags != r2->flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) /* verify r1 is more restrictive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if ((r1->power_rule.max_antenna_gain >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) r2->power_rule.max_antenna_gain) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) r1->power_rule.max_eirp > r2->power_rule.max_eirp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) /* make sure r2's range is contained within r1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (r1->freq_range.start_freq_khz > r2->freq_range.start_freq_khz ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) r1->freq_range.end_freq_khz < r2->freq_range.end_freq_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) /* and finally verify that r1.max_bw >= r2.max_bw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (r1->freq_range.max_bandwidth_khz <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) r2->freq_range.max_bandwidth_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) /* add or extend current rules. do nothing if rule is already contained */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) static void add_rule(struct ieee80211_reg_rule *rule,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) struct ieee80211_reg_rule *reg_rules, u32 *n_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) struct ieee80211_reg_rule *tmp_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) for (i = 0; i < *n_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) tmp_rule = ®_rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) /* rule is already contained - do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (rule_contains(tmp_rule, rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) /* extend rule if possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if (rule_contains(rule, tmp_rule)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) memcpy(tmp_rule, rule, sizeof(*rule));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) memcpy(®_rules[*n_rules], rule, sizeof(*rule));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) (*n_rules)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) * regdom_intersect - do the intersection between two regulatory domains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) * @rd1: first regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) * @rd2: second regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) * Use this function to get the intersection between two regulatory domains.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) * Once completed we will mark the alpha2 for the rd as intersected, "98",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) * as no one single alpha2 can represent this regulatory domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) * Returns a pointer to the regulatory domain structure which will hold the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) * resulting intersection of rules between rd1 and rd2. We will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) * kzalloc() this structure for you.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) static struct ieee80211_regdomain *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) regdom_intersect(const struct ieee80211_regdomain *rd1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) const struct ieee80211_regdomain *rd2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) unsigned int x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) unsigned int num_rules = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) const struct ieee80211_reg_rule *rule1, *rule2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) struct ieee80211_reg_rule intersected_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) struct ieee80211_regdomain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (!rd1 || !rd2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) * First we get a count of the rules we'll need, then we actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) * build them. This is to so we can malloc() and free() a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) * regdomain once. The reason we use reg_rules_intersect() here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) * is it will return -EINVAL if the rule computed makes no sense.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) * All rules that do check out OK are valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) for (x = 0; x < rd1->n_reg_rules; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) rule1 = &rd1->reg_rules[x];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) for (y = 0; y < rd2->n_reg_rules; y++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) rule2 = &rd2->reg_rules[y];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (!reg_rules_intersect(rd1, rd2, rule1, rule2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) &intersected_rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) num_rules++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) if (!num_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (!rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) for (x = 0; x < rd1->n_reg_rules; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) rule1 = &rd1->reg_rules[x];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) for (y = 0; y < rd2->n_reg_rules; y++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) rule2 = &rd2->reg_rules[y];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) r = reg_rules_intersect(rd1, rd2, rule1, rule2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) &intersected_rule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) * No need to memset here the intersected rule here as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) * we're not using the stack anymore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) add_rule(&intersected_rule, rd->reg_rules,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) &rd->n_reg_rules);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) rd->alpha2[0] = '9';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) rd->alpha2[1] = '8';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) rd2->dfs_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) * XXX: add support for the rest of enum nl80211_reg_rule_flags, we may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) * want to just have the channel structure use these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) static u32 map_regdom_flags(u32 rd_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) u32 channel_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (rd_flags & NL80211_RRF_NO_IR_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) channel_flags |= IEEE80211_CHAN_NO_IR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) if (rd_flags & NL80211_RRF_DFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) channel_flags |= IEEE80211_CHAN_RADAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) if (rd_flags & NL80211_RRF_NO_OFDM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) channel_flags |= IEEE80211_CHAN_NO_OFDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) if (rd_flags & NL80211_RRF_NO_OUTDOOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) channel_flags |= IEEE80211_CHAN_INDOOR_ONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (rd_flags & NL80211_RRF_IR_CONCURRENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) channel_flags |= IEEE80211_CHAN_IR_CONCURRENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (rd_flags & NL80211_RRF_NO_HT40MINUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) channel_flags |= IEEE80211_CHAN_NO_HT40MINUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (rd_flags & NL80211_RRF_NO_HT40PLUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) channel_flags |= IEEE80211_CHAN_NO_HT40PLUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) if (rd_flags & NL80211_RRF_NO_80MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) channel_flags |= IEEE80211_CHAN_NO_80MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) if (rd_flags & NL80211_RRF_NO_160MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) channel_flags |= IEEE80211_CHAN_NO_160MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (rd_flags & NL80211_RRF_NO_HE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) channel_flags |= IEEE80211_CHAN_NO_HE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return channel_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) static const struct ieee80211_reg_rule *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) freq_reg_info_regd(u32 center_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) const struct ieee80211_regdomain *regd, u32 bw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) bool band_rule_found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) bool bw_fits = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) if (!regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) for (i = 0; i < regd->n_reg_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) const struct ieee80211_reg_rule *rr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) const struct ieee80211_freq_range *fr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) rr = ®d->reg_rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) fr = &rr->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) * We only need to know if one frequency rule was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * in center_freq's band, that's enough, so let's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * not overwrite it once found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) if (!band_rule_found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) band_rule_found = freq_in_rule_band(fr, center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) bw_fits = cfg80211_does_bw_fit_range(fr, center_freq, bw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (band_rule_found && bw_fits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) return rr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (!band_rule_found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) return ERR_PTR(-ERANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) static const struct ieee80211_reg_rule *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) const struct ieee80211_regdomain *regd = reg_get_regdomain(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) const u32 bws[] = {0, 1, 2, 4, 5, 8, 10, 16, 20};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) const struct ieee80211_reg_rule *reg_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) int i = ARRAY_SIZE(bws) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) u32 bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) for (bw = MHZ_TO_KHZ(bws[i]); bw >= min_bw; bw = MHZ_TO_KHZ(bws[i--])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) reg_rule = freq_reg_info_regd(center_freq, regd, bw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (!IS_ERR(reg_rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) return reg_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) return reg_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) u32 center_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) u32 min_bw = center_freq < MHZ_TO_KHZ(1000) ? 1 : 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) return __freq_reg_info(wiphy, center_freq, MHZ_TO_KHZ(min_bw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) EXPORT_SYMBOL(freq_reg_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) switch (initiator) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) case NL80211_REGDOM_SET_BY_CORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) return "core";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) case NL80211_REGDOM_SET_BY_USER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) return "user";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) case NL80211_REGDOM_SET_BY_DRIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return "driver";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) case NL80211_REGDOM_SET_BY_COUNTRY_IE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) return "country element";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return "bug";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) EXPORT_SYMBOL(reg_initiator_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) const struct ieee80211_reg_rule *reg_rule,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) const struct ieee80211_channel *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) const struct ieee80211_freq_range *freq_range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) u32 max_bandwidth_khz, center_freq_khz, bw_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) bool is_s1g = chan->band == NL80211_BAND_S1GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) freq_range = ®_rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) max_bandwidth_khz = freq_range->max_bandwidth_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) center_freq_khz = ieee80211_channel_to_khz(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) /* Check if auto calculation requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) if (reg_rule->flags & NL80211_RRF_AUTO_BW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) /* If we get a reg_rule we can assume that at least 5Mhz fit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) if (!cfg80211_does_bw_fit_range(freq_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) center_freq_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) MHZ_TO_KHZ(10)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) bw_flags |= IEEE80211_CHAN_NO_10MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) if (!cfg80211_does_bw_fit_range(freq_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) center_freq_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) MHZ_TO_KHZ(20)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) bw_flags |= IEEE80211_CHAN_NO_20MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) if (is_s1g) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) /* S1G is strict about non overlapping channels. We can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) * calculate which bandwidth is allowed per channel by finding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) * the largest bandwidth which cleanly divides the freq_range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) int edge_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) int ch_bw = max_bandwidth_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) while (ch_bw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) edge_offset = (center_freq_khz - ch_bw / 2) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) freq_range->start_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) if (edge_offset % ch_bw == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) switch (KHZ_TO_MHZ(ch_bw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) bw_flags |= IEEE80211_CHAN_1MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) bw_flags |= IEEE80211_CHAN_2MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) bw_flags |= IEEE80211_CHAN_4MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) bw_flags |= IEEE80211_CHAN_8MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) bw_flags |= IEEE80211_CHAN_16MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) /* If we got here, no bandwidths fit on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) * this frequency, ie. band edge.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) bw_flags |= IEEE80211_CHAN_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) ch_bw /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) if (max_bandwidth_khz < MHZ_TO_KHZ(10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) bw_flags |= IEEE80211_CHAN_NO_10MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) if (max_bandwidth_khz < MHZ_TO_KHZ(20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) bw_flags |= IEEE80211_CHAN_NO_20MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (max_bandwidth_khz < MHZ_TO_KHZ(40))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) bw_flags |= IEEE80211_CHAN_NO_HT40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) if (max_bandwidth_khz < MHZ_TO_KHZ(80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) bw_flags |= IEEE80211_CHAN_NO_80MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) if (max_bandwidth_khz < MHZ_TO_KHZ(160))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) bw_flags |= IEEE80211_CHAN_NO_160MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return bw_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) static void handle_channel_single_rule(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) enum nl80211_reg_initiator initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) u32 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) struct regulatory_request *lr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) struct wiphy *request_wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) const struct ieee80211_reg_rule *reg_rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) u32 bw_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) const struct ieee80211_power_rule *power_rule = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) const struct ieee80211_regdomain *regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) regd = reg_get_regdomain(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) power_rule = ®_rule->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) request_wiphy && request_wiphy == wiphy &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) * This guarantees the driver's requested regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) * will always be used as a base for further regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) * settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) chan->flags = chan->orig_flags =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) map_regdom_flags(reg_rule->flags) | bw_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) chan->max_antenna_gain = chan->orig_mag =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) (int) MBI_TO_DBI(power_rule->max_antenna_gain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) chan->max_reg_power = chan->max_power = chan->orig_mpwr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) (int) MBM_TO_DBM(power_rule->max_eirp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) if (chan->flags & IEEE80211_CHAN_RADAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (reg_rule->dfs_cac_ms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) chan->dfs_state = NL80211_DFS_USABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) chan->dfs_state_entered = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) chan->beacon_found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) chan->max_antenna_gain =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) min_t(int, chan->orig_mag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) MBI_TO_DBI(power_rule->max_antenna_gain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) if (chan->flags & IEEE80211_CHAN_RADAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (reg_rule->dfs_cac_ms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (chan->orig_mpwr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) * will always follow the passed country IE power settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_FOLLOW_POWER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) chan->max_power = chan->max_reg_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) chan->max_power = min(chan->orig_mpwr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) chan->max_reg_power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) chan->max_power = chan->max_reg_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) static void handle_channel_adjacent_rules(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) enum nl80211_reg_initiator initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) u32 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) struct regulatory_request *lr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) struct wiphy *request_wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) const struct ieee80211_reg_rule *rrule1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) const struct ieee80211_reg_rule *rrule2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) struct ieee80211_freq_range *comb_range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) u32 bw_flags1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) u32 bw_flags2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) const struct ieee80211_power_rule *power_rule1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) const struct ieee80211_power_rule *power_rule2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) const struct ieee80211_regdomain *regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) regd = reg_get_regdomain(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) power_rule1 = &rrule1->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) power_rule2 = &rrule2->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) bw_flags1 = reg_rule_to_chan_bw_flags(regd, rrule1, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) bw_flags2 = reg_rule_to_chan_bw_flags(regd, rrule2, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) request_wiphy && request_wiphy == wiphy &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) /* This guarantees the driver's requested regulatory domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) * will always be used as a base for further regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) * settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) chan->flags =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) map_regdom_flags(rrule1->flags) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) map_regdom_flags(rrule2->flags) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) bw_flags1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) bw_flags2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) chan->orig_flags = chan->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) chan->max_antenna_gain =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) min_t(int, MBI_TO_DBI(power_rule1->max_antenna_gain),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) MBI_TO_DBI(power_rule2->max_antenna_gain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) chan->orig_mag = chan->max_antenna_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) chan->max_reg_power =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) min_t(int, MBM_TO_DBM(power_rule1->max_eirp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) MBM_TO_DBM(power_rule2->max_eirp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) chan->max_power = chan->max_reg_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) chan->orig_mpwr = chan->max_reg_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) if (chan->flags & IEEE80211_CHAN_RADAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) if (rrule1->dfs_cac_ms || rrule2->dfs_cac_ms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) chan->dfs_cac_ms = max_t(unsigned int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) rrule1->dfs_cac_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) rrule2->dfs_cac_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) chan->dfs_state = NL80211_DFS_USABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) chan->dfs_state_entered = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) chan->beacon_found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) chan->flags = flags | bw_flags1 | bw_flags2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) map_regdom_flags(rrule1->flags) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) map_regdom_flags(rrule2->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) /* reg_rule_to_chan_bw_flags may forbids 10 and forbids 20 MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) * (otherwise no adj. rule case), recheck therefore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) if (cfg80211_does_bw_fit_range(comb_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) ieee80211_channel_to_khz(chan),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) MHZ_TO_KHZ(10)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) chan->flags &= ~IEEE80211_CHAN_NO_10MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) if (cfg80211_does_bw_fit_range(comb_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) ieee80211_channel_to_khz(chan),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) MHZ_TO_KHZ(20)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) chan->flags &= ~IEEE80211_CHAN_NO_20MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) chan->max_antenna_gain =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) min_t(int, chan->orig_mag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) min_t(int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) MBI_TO_DBI(power_rule1->max_antenna_gain),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) MBI_TO_DBI(power_rule2->max_antenna_gain)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) chan->max_reg_power = min_t(int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) MBM_TO_DBM(power_rule1->max_eirp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) MBM_TO_DBM(power_rule2->max_eirp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) if (chan->flags & IEEE80211_CHAN_RADAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) if (rrule1->dfs_cac_ms || rrule2->dfs_cac_ms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) chan->dfs_cac_ms = max_t(unsigned int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) rrule1->dfs_cac_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) rrule2->dfs_cac_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) if (chan->orig_mpwr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) /* Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) * will always follow the passed country IE power settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_FOLLOW_POWER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) chan->max_power = chan->max_reg_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) chan->max_power = min(chan->orig_mpwr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) chan->max_reg_power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) chan->max_power = chan->max_reg_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) /* Note that right now we assume the desired channel bandwidth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) * is always 20 MHz for each individual channel (HT40 uses 20 MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) * per channel, the primary and the extension channel).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) static void handle_channel(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) enum nl80211_reg_initiator initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) struct ieee80211_channel *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) const u32 orig_chan_freq = ieee80211_channel_to_khz(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) struct wiphy *request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) const struct ieee80211_reg_rule *rrule = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) const struct ieee80211_reg_rule *rrule1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) const struct ieee80211_reg_rule *rrule2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) u32 flags = chan->orig_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) rrule = freq_reg_info(wiphy, orig_chan_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) if (IS_ERR(rrule)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) /* check for adjacent match, therefore get rules for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) * chan - 20 MHz and chan + 20 MHz and test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) * if reg rules are adjacent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) rrule1 = freq_reg_info(wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) orig_chan_freq - MHZ_TO_KHZ(20));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) rrule2 = freq_reg_info(wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) orig_chan_freq + MHZ_TO_KHZ(20));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) if (!IS_ERR(rrule1) && !IS_ERR(rrule2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) struct ieee80211_freq_range comb_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) if (rrule1->freq_range.end_freq_khz !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) rrule2->freq_range.start_freq_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) goto disable_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) comb_range.start_freq_khz =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) rrule1->freq_range.start_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) comb_range.end_freq_khz =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) rrule2->freq_range.end_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) comb_range.max_bandwidth_khz =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) min_t(u32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) rrule1->freq_range.max_bandwidth_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) rrule2->freq_range.max_bandwidth_khz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) if (!cfg80211_does_bw_fit_range(&comb_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) orig_chan_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) MHZ_TO_KHZ(20)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) goto disable_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) handle_channel_adjacent_rules(wiphy, initiator, chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) flags, lr, request_wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) rrule1, rrule2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) &comb_range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) disable_chan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) /* We will disable all channels that do not match our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) * received regulatory rule unless the hint is coming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) * from a Country IE and the Country IE had no information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) * about a band. The IEEE 802.11 spec allows for an AP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) * to send only a subset of the regulatory rules allowed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) * so an AP in the US that only supports 2.4 GHz may only send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) * a country IE with information for the 2.4 GHz band
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) * while 5 GHz is still supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) PTR_ERR(rrule) == -ERANGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) request_wiphy && request_wiphy == wiphy &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) pr_debug("Disabling freq %d.%03d MHz for good\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) chan->center_freq, chan->freq_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) chan->orig_flags |= IEEE80211_CHAN_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) chan->flags = chan->orig_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) pr_debug("Disabling freq %d.%03d MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) chan->center_freq, chan->freq_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) chan->flags |= IEEE80211_CHAN_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) handle_channel_single_rule(wiphy, initiator, chan, flags, lr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) request_wiphy, rrule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) static void handle_band(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) enum nl80211_reg_initiator initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) struct ieee80211_supported_band *sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) for (i = 0; i < sband->n_channels; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) handle_channel(wiphy, initiator, &sband->channels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) static bool reg_request_cell_base(struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) if (request->initiator != NL80211_REGDOM_SET_BY_USER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) bool reg_last_request_cell_base(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) return reg_request_cell_base(get_last_request());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) #ifdef CONFIG_CFG80211_REG_CELLULAR_HINTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) /* Core specific check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) reg_ignore_cell_hint(struct regulatory_request *pending_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) if (!reg_num_devs_support_basehint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) if (reg_request_cell_base(lr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) !regdom_changes(pending_request->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) /* Device specific check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) return !(wiphy->features & NL80211_FEATURE_CELL_BASE_REG_HINTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) reg_ignore_cell_hint(struct regulatory_request *pending_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) if (wiphy->regulatory_flags & REGULATORY_STRICT_REG &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) !(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) static bool ignore_reg_update(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) enum nl80211_reg_initiator initiator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) if (!lr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) pr_debug("Ignoring regulatory request set by %s since last_request is not set\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) reg_initiator_name(initiator));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) if (initiator == NL80211_REGDOM_SET_BY_CORE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) pr_debug("Ignoring regulatory request set by %s since the driver uses its own custom regulatory domain\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) reg_initiator_name(initiator));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) * wiphy->regd will be set once the device has its own
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) * desired regulatory domain set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) if (wiphy_strict_alpha2_regd(wiphy) && !wiphy->regd &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) !is_world_regdom(lr->alpha2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) pr_debug("Ignoring regulatory request set by %s since the driver requires its own regulatory domain to be set first\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) reg_initiator_name(initiator));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) if (reg_request_cell_base(lr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) return reg_dev_ignore_cell_hint(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) static bool reg_is_world_roaming(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) const struct ieee80211_regdomain *cr = get_cfg80211_regdom();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) const struct ieee80211_regdomain *wr = get_wiphy_regdom(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) if (is_world_regdom(cr->alpha2) || (wr && is_world_regdom(wr->alpha2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) struct reg_beacon *reg_beacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) bool channel_changed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) struct ieee80211_channel chan_before;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) sband = wiphy->bands[reg_beacon->chan.band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) chan = &sband->channels[chan_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) if (likely(!ieee80211_channel_equal(chan, ®_beacon->chan)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) if (chan->beacon_found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) chan->beacon_found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) if (!reg_is_world_roaming(wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) chan_before = *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) if (chan->flags & IEEE80211_CHAN_NO_IR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) chan->flags &= ~IEEE80211_CHAN_NO_IR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) channel_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) if (channel_changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) nl80211_send_beacon_hint_event(wiphy, &chan_before, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) * Called when a scan on a wiphy finds a beacon on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) * new channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) static void wiphy_update_new_beacon(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) struct reg_beacon *reg_beacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) if (!wiphy->bands[reg_beacon->chan.band])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) sband = wiphy->bands[reg_beacon->chan.band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) for (i = 0; i < sband->n_channels; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) handle_reg_beacon(wiphy, i, reg_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) * Called upon reg changes or a new wiphy is added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) static void wiphy_update_beacon_reg(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) struct reg_beacon *reg_beacon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) list_for_each_entry(reg_beacon, ®_beacon_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if (!wiphy->bands[reg_beacon->chan.band])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) sband = wiphy->bands[reg_beacon->chan.band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) for (i = 0; i < sband->n_channels; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) handle_reg_beacon(wiphy, i, reg_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) /* Reap the advantages of previously found beacons */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) static void reg_process_beacons(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) * Means we are just firing up cfg80211, so no beacons would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) * have been processed yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) if (!last_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) wiphy_update_beacon_reg(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) static bool is_ht40_allowed(struct ieee80211_channel *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) if (!chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) if (chan->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) /* This would happen when regulatory rules disallow HT40 completely */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) if ((chan->flags & IEEE80211_CHAN_NO_HT40) == IEEE80211_CHAN_NO_HT40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) static void reg_process_ht_flags_channel(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) struct ieee80211_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) struct ieee80211_supported_band *sband = wiphy->bands[channel->band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) struct ieee80211_channel *channel_before = NULL, *channel_after = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) const struct ieee80211_regdomain *regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) u32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) if (!is_ht40_allowed(channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) channel->flags |= IEEE80211_CHAN_NO_HT40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) * We need to ensure the extension channels exist to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) * be able to use HT40- or HT40+, this finds them (or not)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) for (i = 0; i < sband->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) struct ieee80211_channel *c = &sband->channels[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) if (c->center_freq == (channel->center_freq - 20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) channel_before = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) if (c->center_freq == (channel->center_freq + 20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) channel_after = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) regd = get_wiphy_regdom(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) if (regd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) const struct ieee80211_reg_rule *reg_rule =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) freq_reg_info_regd(MHZ_TO_KHZ(channel->center_freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) regd, MHZ_TO_KHZ(20));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) if (!IS_ERR(reg_rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) flags = reg_rule->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) * Please note that this assumes target bandwidth is 20 MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) * if that ever changes we also need to change the below logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) * to include that as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) if (!is_ht40_allowed(channel_before) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) flags & NL80211_RRF_NO_HT40MINUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) if (!is_ht40_allowed(channel_after) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) flags & NL80211_RRF_NO_HT40PLUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) static void reg_process_ht_flags_band(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) struct ieee80211_supported_band *sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) for (i = 0; i < sband->n_channels; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) reg_process_ht_flags_channel(wiphy, &sband->channels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) static void reg_process_ht_flags(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) if (!wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) for (band = 0; band < NUM_NL80211_BANDS; band++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) reg_process_ht_flags_band(wiphy, wiphy->bands[band]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) static void reg_call_notifier(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) if (wiphy->reg_notifier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) wiphy->reg_notifier(wiphy, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) struct cfg80211_chan_def chandef = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) enum nl80211_iftype iftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) iftype = wdev->iftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) /* make sure the interface is active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) if (!wdev->netdev || !netif_running(wdev->netdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) goto wdev_inactive_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) switch (iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) if (!wdev->beacon_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) goto wdev_inactive_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) chandef = wdev->chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) if (!wdev->ssid_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) goto wdev_inactive_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) chandef = wdev->chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) if (!wdev->current_bss ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) !wdev->current_bss->pub.channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) goto wdev_inactive_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) if (!rdev->ops->get_channel ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) rdev_get_channel(rdev, wdev, &chandef))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) cfg80211_chandef_create(&chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) wdev->current_bss->pub.channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) NL80211_CHAN_NO_HT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) case NL80211_IFTYPE_MONITOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) case NL80211_IFTYPE_P2P_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) /* no enforcement required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) /* others not implemented for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) switch (iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) return cfg80211_chandef_usable(wiphy, &chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) IEEE80211_CHAN_DISABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) wdev_inactive_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) static void reg_leave_invalid_chans(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) if (!reg_wdev_chan_valid(wiphy, wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) cfg80211_leave(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) static void reg_check_chans_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) pr_debug("Verifying active interfaces after reg change\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) list_for_each_entry(rdev, &cfg80211_rdev_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) if (!(rdev->wiphy.regulatory_flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) REGULATORY_IGNORE_STALE_KICKOFF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) reg_leave_invalid_chans(&rdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) static void reg_check_channels(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) * Give usermode a chance to do something nicer (move to another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) * channel, orderly disconnection), before forcing a disconnection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) mod_delayed_work(system_power_efficient_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) ®_check_chans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) msecs_to_jiffies(REG_ENFORCE_GRACE_MS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) static void wiphy_update_regulatory(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) enum nl80211_reg_initiator initiator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) if (ignore_reg_update(wiphy, initiator)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) * Regulatory updates set by CORE are ignored for custom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) * regulatory cards. Let us notify the changes to the driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) * as some drivers used this to restore its orig_* reg domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) if (initiator == NL80211_REGDOM_SET_BY_CORE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) wiphy->regulatory_flags & REGULATORY_CUSTOM_REG &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) !(wiphy->regulatory_flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) REGULATORY_WIPHY_SELF_MANAGED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) reg_call_notifier(wiphy, lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) lr->dfs_region = get_cfg80211_regdom()->dfs_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) for (band = 0; band < NUM_NL80211_BANDS; band++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) handle_band(wiphy, initiator, wiphy->bands[band]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) reg_process_beacons(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) reg_process_ht_flags(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) reg_call_notifier(wiphy, lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) struct wiphy *wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) wiphy_update_regulatory(wiphy, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) reg_check_channels();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) static void handle_channel_custom(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) const struct ieee80211_regdomain *regd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) u32 min_bw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) u32 bw_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) const struct ieee80211_reg_rule *reg_rule = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) const struct ieee80211_power_rule *power_rule = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) u32 bw, center_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) center_freq_khz = ieee80211_channel_to_khz(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) reg_rule = freq_reg_info_regd(center_freq_khz, regd, bw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) if (!IS_ERR(reg_rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) if (IS_ERR_OR_NULL(reg_rule)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) pr_debug("Disabling freq %d.%03d MHz as custom regd has no rule that fits it\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) chan->center_freq, chan->freq_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) chan->flags |= IEEE80211_CHAN_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) chan->orig_flags |= IEEE80211_CHAN_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) chan->flags = chan->orig_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) power_rule = ®_rule->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) chan->dfs_state_entered = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) chan->dfs_state = NL80211_DFS_USABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) chan->beacon_found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) chan->flags = chan->orig_flags | bw_flags |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) map_regdom_flags(reg_rule->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) chan->max_reg_power = chan->max_power =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) (int) MBM_TO_DBM(power_rule->max_eirp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) if (chan->flags & IEEE80211_CHAN_RADAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) if (reg_rule->dfs_cac_ms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) chan->max_power = chan->max_reg_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) static void handle_band_custom(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) struct ieee80211_supported_band *sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) const struct ieee80211_regdomain *regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) * We currently assume that you always want at least 20 MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) * otherwise channel 12 might get enabled if this rule is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) * compatible to US, which permits 2402 - 2472 MHz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) for (i = 0; i < sband->n_channels; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) handle_channel_custom(wiphy, &sband->channels[i], regd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) MHZ_TO_KHZ(20));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) /* Used by drivers prior to wiphy registration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) const struct ieee80211_regdomain *regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) unsigned int bands_set = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) WARN(!(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) "wiphy should have REGULATORY_CUSTOM_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) for (band = 0; band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) if (!wiphy->bands[band])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) handle_band_custom(wiphy, wiphy->bands[band], regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) bands_set++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) * no point in calling this if it won't have any effect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) * on your device's supported bands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) WARN_ON(!bands_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) static void reg_set_request_processed(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) bool need_more_processing = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) lr->processed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) if (!list_empty(®_requests_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) need_more_processing = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) cancel_crda_timeout();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) if (need_more_processing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) schedule_work(®_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) * reg_process_hint_core - process core regulatory requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) * @core_request: a pending core regulatory request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) * The wireless subsystem can use this function to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) * a regulatory request issued by the regulatory core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) reg_process_hint_core(struct regulatory_request *core_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) if (reg_query_database(core_request)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) core_request->intersect = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) core_request->processed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) reg_update_last_request(core_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) __reg_process_hint_user(struct regulatory_request *user_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) if (reg_request_cell_base(user_request))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) return reg_ignore_cell_hint(user_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) if (reg_request_cell_base(lr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) return REG_REQ_INTERSECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) * If the user knows better the user should set the regdom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) * to their country before the IE is picked up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) if (lr->initiator == NL80211_REGDOM_SET_BY_USER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) lr->intersect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) * Process user requests only after previous user/driver/core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) * requests have been processed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) lr->initiator == NL80211_REGDOM_SET_BY_USER) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) regdom_changes(lr->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) if (!regdom_changes(user_request->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) * reg_process_hint_user - process user regulatory requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) * @user_request: a pending user regulatory request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) * The wireless subsystem can use this function to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) * a regulatory request initiated by userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) reg_process_hint_user(struct regulatory_request *user_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) enum reg_request_treatment treatment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) treatment = __reg_process_hint_user(user_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) if (treatment == REG_REQ_IGNORE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) treatment == REG_REQ_ALREADY_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) user_request->intersect = treatment == REG_REQ_INTERSECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) user_request->processed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) if (reg_query_database(user_request)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) reg_update_last_request(user_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) user_alpha2[0] = user_request->alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) user_alpha2[1] = user_request->alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) __reg_process_hint_driver(struct regulatory_request *driver_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) if (regdom_changes(driver_request->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) * This would happen if you unplug and plug your card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) * back in or if you add a new device for which the previously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) * loaded card also agrees on the regulatory domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) !regdom_changes(driver_request->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) return REG_REQ_INTERSECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) * reg_process_hint_driver - process driver regulatory requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) * @wiphy: the wireless device for the regulatory request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) * @driver_request: a pending driver regulatory request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) * The wireless subsystem can use this function to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) * a regulatory request issued by an 802.11 driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) * Returns one of the different reg request treatment values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) reg_process_hint_driver(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) struct regulatory_request *driver_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) const struct ieee80211_regdomain *regd, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) enum reg_request_treatment treatment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) treatment = __reg_process_hint_driver(driver_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) switch (treatment) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) case REG_REQ_OK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) case REG_REQ_IGNORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) case REG_REQ_INTERSECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) case REG_REQ_ALREADY_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) regd = reg_copy_regd(get_cfg80211_regdom());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) if (IS_ERR(regd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) tmp = get_wiphy_regdom(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) rcu_assign_pointer(wiphy->regd, regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) rcu_free_regdom(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) driver_request->intersect = treatment == REG_REQ_INTERSECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) driver_request->processed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) * Since CRDA will not be called in this case as we already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) * have applied the requested regulatory domain before we just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) * inform userspace we have processed the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) if (treatment == REG_REQ_ALREADY_SET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) nl80211_send_reg_change_event(driver_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) reg_update_last_request(driver_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) reg_set_request_processed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) if (reg_query_database(driver_request)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) reg_update_last_request(driver_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) __reg_process_hint_country_ie(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) struct regulatory_request *country_ie_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) struct wiphy *last_wiphy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) if (reg_request_cell_base(lr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) /* Trust a Cell base station over the AP's country IE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) if (regdom_changes(country_ie_request->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) if (wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_IGNORE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) if (unlikely(!is_an_alpha2(country_ie_request->alpha2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) last_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) if (last_wiphy != wiphy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) * Two cards with two APs claiming different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) * Country IE alpha2s. We could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) * intersect them, but that seems unlikely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) * to be correct. Reject second one for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) if (regdom_changes(country_ie_request->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) if (regdom_changes(country_ie_request->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) * reg_process_hint_country_ie - process regulatory requests from country IEs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) * @wiphy: the wireless device for the regulatory request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) * @country_ie_request: a regulatory request from a country IE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) * The wireless subsystem can use this function to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) * a regulatory request issued by a country Information Element.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) * Returns one of the different reg request treatment values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) static enum reg_request_treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) reg_process_hint_country_ie(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) struct regulatory_request *country_ie_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) enum reg_request_treatment treatment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) treatment = __reg_process_hint_country_ie(wiphy, country_ie_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) switch (treatment) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) case REG_REQ_OK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) case REG_REQ_IGNORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) case REG_REQ_ALREADY_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) reg_free_request(country_ie_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) return REG_REQ_ALREADY_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) case REG_REQ_INTERSECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) * This doesn't happen yet, not sure we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) * ever want to support it for this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) WARN_ONCE(1, "Unexpected intersection for country elements");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) country_ie_request->intersect = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) country_ie_request->processed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) if (reg_query_database(country_ie_request)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) reg_update_last_request(country_ie_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) return REG_REQ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) return REG_REQ_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) const struct ieee80211_regdomain *wiphy1_regd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) const struct ieee80211_regdomain *wiphy2_regd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) const struct ieee80211_regdomain *cfg80211_regd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) bool dfs_domain_same;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) cfg80211_regd = rcu_dereference(cfg80211_regdomain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) wiphy1_regd = rcu_dereference(wiphy1->regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) if (!wiphy1_regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) wiphy1_regd = cfg80211_regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) wiphy2_regd = rcu_dereference(wiphy2->regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) if (!wiphy2_regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) wiphy2_regd = cfg80211_regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) dfs_domain_same = wiphy1_regd->dfs_region == wiphy2_regd->dfs_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) return dfs_domain_same;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) static void reg_copy_dfs_chan_state(struct ieee80211_channel *dst_chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) struct ieee80211_channel *src_chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) if (!(dst_chan->flags & IEEE80211_CHAN_RADAR) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) !(src_chan->flags & IEEE80211_CHAN_RADAR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) if (dst_chan->flags & IEEE80211_CHAN_DISABLED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) src_chan->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) if (src_chan->center_freq == dst_chan->center_freq &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) dst_chan->dfs_state == NL80211_DFS_USABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) dst_chan->dfs_state = src_chan->dfs_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) dst_chan->dfs_state_entered = src_chan->dfs_state_entered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) static void wiphy_share_dfs_chan_state(struct wiphy *dst_wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) struct wiphy *src_wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) struct ieee80211_supported_band *src_sband, *dst_sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) struct ieee80211_channel *src_chan, *dst_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) int i, j, band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) if (!reg_dfs_domain_same(dst_wiphy, src_wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) for (band = 0; band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) dst_sband = dst_wiphy->bands[band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) src_sband = src_wiphy->bands[band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) if (!dst_sband || !src_sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) for (i = 0; i < dst_sband->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) dst_chan = &dst_sband->channels[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) for (j = 0; j < src_sband->n_channels; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) src_chan = &src_sband->channels[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) reg_copy_dfs_chan_state(dst_chan, src_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) static void wiphy_all_share_dfs_chan_state(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) if (wiphy == &rdev->wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) wiphy_share_dfs_chan_state(wiphy, &rdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) /* This processes *all* regulatory hints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) static void reg_process_hint(struct regulatory_request *reg_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) struct wiphy *wiphy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) enum reg_request_treatment treatment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) enum nl80211_reg_initiator initiator = reg_request->initiator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) if (reg_request->wiphy_idx != WIPHY_IDX_INVALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) switch (initiator) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) case NL80211_REGDOM_SET_BY_CORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) treatment = reg_process_hint_core(reg_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) case NL80211_REGDOM_SET_BY_USER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) treatment = reg_process_hint_user(reg_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) case NL80211_REGDOM_SET_BY_DRIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) if (!wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) treatment = reg_process_hint_driver(wiphy, reg_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) case NL80211_REGDOM_SET_BY_COUNTRY_IE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) if (!wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) treatment = reg_process_hint_country_ie(wiphy, reg_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) WARN(1, "invalid initiator %d\n", initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) if (treatment == REG_REQ_IGNORE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) WARN(treatment != REG_REQ_OK && treatment != REG_REQ_ALREADY_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) "unexpected treatment value %d\n", treatment);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) /* This is required so that the orig_* parameters are saved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) * NOTE: treatment must be set for any case that reaches here!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) if (treatment == REG_REQ_ALREADY_SET && wiphy &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) wiphy_update_regulatory(wiphy, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) wiphy_all_share_dfs_chan_state(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) reg_check_channels();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) reg_free_request(reg_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) static void notify_self_managed_wiphys(struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) struct wiphy *wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) request->initiator == NL80211_REGDOM_SET_BY_USER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) reg_call_notifier(wiphy, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) * Regulatory hints come on a first come first serve basis and we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) * must process each one atomically.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) static void reg_process_pending_hints(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) struct regulatory_request *reg_request, *lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) /* When last_request->processed becomes true this will be rescheduled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) if (lr && !lr->processed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) pr_debug("Pending regulatory request, waiting for it to be processed...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) if (list_empty(®_requests_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) reg_request = list_first_entry(®_requests_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) struct regulatory_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) list_del_init(®_request->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) notify_self_managed_wiphys(reg_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) reg_process_hint(reg_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) if (!list_empty(®_requests_list) && lr && lr->processed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) schedule_work(®_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) /* Processes beacon hints -- this has nothing to do with country IEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) static void reg_process_pending_beacon_hints(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) struct reg_beacon *pending_beacon, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) /* This goes through the _pending_ beacon list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) spin_lock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) list_for_each_entry_safe(pending_beacon, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) ®_pending_beacons, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) list_del_init(&pending_beacon->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) /* Applies the beacon hint to current wiphys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) list_for_each_entry(rdev, &cfg80211_rdev_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) wiphy_update_new_beacon(&rdev->wiphy, pending_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) /* Remembers the beacon hint for new wiphys or reg changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) list_add_tail(&pending_beacon->list, ®_beacon_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) spin_unlock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) static void reg_process_self_managed_hints(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) struct wiphy *wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) const struct ieee80211_regdomain *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) const struct ieee80211_regdomain *regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) struct regulatory_request request = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) regd = rdev->requested_regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) rdev->requested_regd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) if (regd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) tmp = get_wiphy_regdom(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) rcu_assign_pointer(wiphy->regd, regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) rcu_free_regdom(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) for (band = 0; band < NUM_NL80211_BANDS; band++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) handle_band_custom(wiphy, wiphy->bands[band], regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) reg_process_ht_flags(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) request.wiphy_idx = get_wiphy_idx(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) request.alpha2[0] = regd->alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) request.alpha2[1] = regd->alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) nl80211_send_wiphy_reg_change_event(&request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) reg_check_channels();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) static void reg_todo(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) reg_process_pending_hints();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) reg_process_pending_beacon_hints();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) reg_process_self_managed_hints();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) static void queue_regulatory_request(struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) request->alpha2[0] = toupper(request->alpha2[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) request->alpha2[1] = toupper(request->alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) list_add_tail(&request->list, ®_requests_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) schedule_work(®_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) * Core regulatory hint -- happens during cfg80211_init()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) * and when we restore regulatory settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) static int regulatory_hint_core(const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) struct regulatory_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) if (!request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) request->alpha2[0] = alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) request->alpha2[1] = alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) request->initiator = NL80211_REGDOM_SET_BY_CORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) request->wiphy_idx = WIPHY_IDX_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) queue_regulatory_request(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) /* User hints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) int regulatory_hint_user(const char *alpha2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) enum nl80211_user_reg_hint_type user_reg_hint_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) struct regulatory_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) if (WARN_ON(!alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) if (!is_world_regdom(alpha2) && !is_an_alpha2(alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) if (!request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) request->wiphy_idx = WIPHY_IDX_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) request->alpha2[0] = alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) request->alpha2[1] = alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) request->initiator = NL80211_REGDOM_SET_BY_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) request->user_reg_hint_type = user_reg_hint_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) /* Allow calling CRDA again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) reset_crda_timeouts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) queue_regulatory_request(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) int regulatory_hint_indoor(bool is_indoor, u32 portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) spin_lock(®_indoor_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) /* It is possible that more than one user space process is trying to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) * configure the indoor setting. To handle such cases, clear the indoor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) * setting in case that some process does not think that the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) * is operating in an indoor environment. In addition, if a user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) * process indicates that it is controlling the indoor setting, save its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) * portid, i.e., make it the owner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) reg_is_indoor = is_indoor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) if (reg_is_indoor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) if (!reg_is_indoor_portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) reg_is_indoor_portid = portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) reg_is_indoor_portid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) spin_unlock(®_indoor_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) if (!is_indoor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) reg_check_channels();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) void regulatory_netlink_notify(u32 portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) spin_lock(®_indoor_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) if (reg_is_indoor_portid != portid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) spin_unlock(®_indoor_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) reg_is_indoor = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) reg_is_indoor_portid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) spin_unlock(®_indoor_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) reg_check_channels();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) /* Driver hints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) struct regulatory_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) if (WARN_ON(!alpha2 || !wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) wiphy->regulatory_flags &= ~REGULATORY_CUSTOM_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) if (!request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) request->wiphy_idx = get_wiphy_idx(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) request->alpha2[0] = alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) request->alpha2[1] = alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) request->initiator = NL80211_REGDOM_SET_BY_DRIVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) /* Allow calling CRDA again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) reset_crda_timeouts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) queue_regulatory_request(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) EXPORT_SYMBOL(regulatory_hint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) void regulatory_hint_country_ie(struct wiphy *wiphy, enum nl80211_band band,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) const u8 *country_ie, u8 country_ie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) char alpha2[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) enum environment_cap env = ENVIRON_ANY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) struct regulatory_request *request = NULL, *lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) /* IE len must be evenly divisible by 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) if (country_ie_len & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) request = kzalloc(sizeof(*request), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) if (!request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) alpha2[0] = country_ie[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) alpha2[1] = country_ie[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) if (country_ie[2] == 'I')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) env = ENVIRON_INDOOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) else if (country_ie[2] == 'O')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) env = ENVIRON_OUTDOOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) if (unlikely(!lr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) * We will run this only upon a successful connection on cfg80211.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) * We leave conflict resolution to the workqueue, where can hold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) * the RTNL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) lr->wiphy_idx != WIPHY_IDX_INVALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) request->wiphy_idx = get_wiphy_idx(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) request->alpha2[0] = alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) request->alpha2[1] = alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) request->country_ie_env = env;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) /* Allow calling CRDA again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) reset_crda_timeouts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) queue_regulatory_request(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) request = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) kfree(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) static void restore_alpha2(char *alpha2, bool reset_user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) /* indicates there is no alpha2 to consider for restoration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) alpha2[0] = '9';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) alpha2[1] = '7';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) /* The user setting has precedence over the module parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) if (is_user_regdom_saved()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) /* Unless we're asked to ignore it and reset it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) if (reset_user) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) pr_debug("Restoring regulatory settings including user preference\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) user_alpha2[0] = '9';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) user_alpha2[1] = '7';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) * If we're ignoring user settings, we still need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) * check the module parameter to ensure we put things
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) * back as they were for a full restore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) if (!is_world_regdom(ieee80211_regdom)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) pr_debug("Keeping preference on module parameter ieee80211_regdom: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) ieee80211_regdom[0], ieee80211_regdom[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) alpha2[0] = ieee80211_regdom[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) alpha2[1] = ieee80211_regdom[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) pr_debug("Restoring regulatory settings while preserving user preference for: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) user_alpha2[0], user_alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) alpha2[0] = user_alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) alpha2[1] = user_alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) } else if (!is_world_regdom(ieee80211_regdom)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) pr_debug("Keeping preference on module parameter ieee80211_regdom: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) ieee80211_regdom[0], ieee80211_regdom[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) alpha2[0] = ieee80211_regdom[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) alpha2[1] = ieee80211_regdom[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) pr_debug("Restoring regulatory settings\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) static void restore_custom_reg_settings(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) for (band = 0; band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) sband = wiphy->bands[band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) for (i = 0; i < sband->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) chan = &sband->channels[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) chan->flags = chan->orig_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) chan->max_antenna_gain = chan->orig_mag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) chan->max_power = chan->orig_mpwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) chan->beacon_found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) * Restoring regulatory settings involves ingoring any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) * possibly stale country IE information and user regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) * settings if so desired, this includes any beacon hints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) * learned as we could have traveled outside to another country
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) * after disconnection. To restore regulatory settings we do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) * exactly what we did at bootup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) * - send a core regulatory hint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) * - send a user regulatory hint if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) * Device drivers that send a regulatory hint for a specific country
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) * keep their own regulatory domain on wiphy->regd so that does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) * not need to be remembered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) static void restore_regulatory_settings(bool reset_user, bool cached)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) char alpha2[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) char world_alpha2[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) struct reg_beacon *reg_beacon, *btmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) LIST_HEAD(tmp_reg_req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) * Clear the indoor setting in case that it is not controlled by user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) * space, as otherwise there is no guarantee that the device is still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) * operating in an indoor environment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) spin_lock(®_indoor_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) if (reg_is_indoor && !reg_is_indoor_portid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) reg_is_indoor = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) reg_check_channels();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) spin_unlock(®_indoor_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) reset_regdomains(true, &world_regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) restore_alpha2(alpha2, reset_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) * If there's any pending requests we simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) * stash them to a temporary pending queue and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) * add then after we've restored regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) * settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) list_splice_tail_init(®_requests_list, &tmp_reg_req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) /* Clear beacon hints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) spin_lock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) list_for_each_entry_safe(reg_beacon, btmp, ®_pending_beacons, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) list_del(®_beacon->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) kfree(reg_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) spin_unlock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) list_for_each_entry_safe(reg_beacon, btmp, ®_beacon_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) list_del(®_beacon->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) kfree(reg_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) /* First restore to the basic regulatory settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) world_alpha2[0] = cfg80211_world_regdom->alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) restore_custom_reg_settings(&rdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) if (cached && (!is_an_alpha2(alpha2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) !IS_ERR_OR_NULL(cfg80211_user_regdom))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) reset_regdomains(false, cfg80211_world_regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) update_all_wiphy_regulatory(NL80211_REGDOM_SET_BY_CORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) print_regdomain(get_cfg80211_regdom());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) nl80211_send_reg_change_event(&core_request_world);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) reg_set_request_processed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) if (is_an_alpha2(alpha2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) !regulatory_hint_user(alpha2, NL80211_USER_REG_HINT_USER)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) struct regulatory_request *ureq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) ureq = list_last_entry(®_requests_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) struct regulatory_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) list_del(&ureq->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) notify_self_managed_wiphys(ureq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) reg_update_last_request(ureq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) set_regdom(reg_copy_regd(cfg80211_user_regdom),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) REGD_SOURCE_CACHED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) regulatory_hint_core(world_alpha2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) * This restores the ieee80211_regdom module parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) * preference or the last user requested regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) * settings, user regulatory settings takes precedence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) if (is_an_alpha2(alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) regulatory_hint_user(alpha2, NL80211_USER_REG_HINT_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) list_splice_tail_init(&tmp_reg_req_list, ®_requests_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) pr_debug("Kicking the queue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) schedule_work(®_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) static bool is_wiphy_all_set_reg_flag(enum ieee80211_regulatory_flags flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) if (!(wdev->wiphy->regulatory_flags & flag)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) void regulatory_hint_disconnect(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) /* Restore of regulatory settings is not required when wiphy(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) * ignore IE from connected access point but clearance of beacon hints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) * is required when wiphy(s) supports beacon hints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) if (is_wiphy_all_set_reg_flag(REGULATORY_COUNTRY_IE_IGNORE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) struct reg_beacon *reg_beacon, *btmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) if (is_wiphy_all_set_reg_flag(REGULATORY_DISABLE_BEACON_HINTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) spin_lock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) list_for_each_entry_safe(reg_beacon, btmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) ®_pending_beacons, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) list_del(®_beacon->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) kfree(reg_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) spin_unlock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) list_for_each_entry_safe(reg_beacon, btmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) ®_beacon_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) list_del(®_beacon->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) kfree(reg_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) pr_debug("All devices are disconnected, going to restore regulatory settings\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) restore_regulatory_settings(false, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) static bool freq_is_chan_12_13_14(u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) if (freq == ieee80211_channel_to_frequency(12, NL80211_BAND_2GHZ) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) freq == ieee80211_channel_to_frequency(13, NL80211_BAND_2GHZ) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) freq == ieee80211_channel_to_frequency(14, NL80211_BAND_2GHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) static bool pending_reg_beacon(struct ieee80211_channel *beacon_chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) struct reg_beacon *pending_beacon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) list_for_each_entry(pending_beacon, ®_pending_beacons, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) if (ieee80211_channel_equal(beacon_chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) &pending_beacon->chan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) int regulatory_hint_found_beacon(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) struct ieee80211_channel *beacon_chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) struct reg_beacon *reg_beacon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) bool processing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) if (beacon_chan->beacon_found ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) beacon_chan->flags & IEEE80211_CHAN_RADAR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) (beacon_chan->band == NL80211_BAND_2GHZ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) !freq_is_chan_12_13_14(beacon_chan->center_freq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) spin_lock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) processing = pending_reg_beacon(beacon_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) spin_unlock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) if (processing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) reg_beacon = kzalloc(sizeof(struct reg_beacon), gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) if (!reg_beacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) pr_debug("Found new beacon on frequency: %d.%03d MHz (Ch %d) on %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) beacon_chan->center_freq, beacon_chan->freq_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) ieee80211_freq_khz_to_channel(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) ieee80211_channel_to_khz(beacon_chan)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) wiphy_name(wiphy));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) memcpy(®_beacon->chan, beacon_chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) sizeof(struct ieee80211_channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) * Since we can be called from BH or and non-BH context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) * we must use spin_lock_bh()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) spin_lock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) list_add_tail(®_beacon->list, ®_pending_beacons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) spin_unlock_bh(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) schedule_work(®_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) static void print_rd_rules(const struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) const struct ieee80211_reg_rule *reg_rule = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) const struct ieee80211_freq_range *freq_range = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) const struct ieee80211_power_rule *power_rule = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) char bw[32], cac_time[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) pr_debug(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) for (i = 0; i < rd->n_reg_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) reg_rule = &rd->reg_rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) freq_range = ®_rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) power_rule = ®_rule->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) if (reg_rule->flags & NL80211_RRF_AUTO_BW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) snprintf(bw, sizeof(bw), "%d KHz, %u KHz AUTO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) freq_range->max_bandwidth_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) reg_get_max_bandwidth(rd, reg_rule));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) snprintf(bw, sizeof(bw), "%d KHz",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) freq_range->max_bandwidth_khz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) if (reg_rule->flags & NL80211_RRF_DFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) scnprintf(cac_time, sizeof(cac_time), "%u s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) reg_rule->dfs_cac_ms/1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) scnprintf(cac_time, sizeof(cac_time), "N/A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) * There may not be documentation for max antenna gain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) * in certain regions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) if (power_rule->max_antenna_gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) pr_debug(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) freq_range->start_freq_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) freq_range->end_freq_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) bw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) power_rule->max_antenna_gain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) power_rule->max_eirp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) cac_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) pr_debug(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) freq_range->start_freq_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) freq_range->end_freq_khz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) bw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) power_rule->max_eirp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) cac_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) switch (dfs_region) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) case NL80211_DFS_UNSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) case NL80211_DFS_FCC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) case NL80211_DFS_ETSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) case NL80211_DFS_JP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) pr_debug("Ignoring unknown DFS master region: %d\n", dfs_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) static void print_regdomain(const struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) if (is_intersected_alpha2(rd->alpha2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) rdev = cfg80211_rdev_by_wiphy_idx(lr->wiphy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) if (rdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) pr_debug("Current regulatory domain updated by AP to: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) rdev->country_ie_alpha2[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) rdev->country_ie_alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) pr_debug("Current regulatory domain intersected:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) pr_debug("Current regulatory domain intersected:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) } else if (is_world_regdom(rd->alpha2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) pr_debug("World regulatory domain updated:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) if (is_unknown_alpha2(rd->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) pr_debug("Regulatory domain changed to driver built-in settings (unknown country)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) if (reg_request_cell_base(lr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) pr_debug("Regulatory domain changed to country: %c%c by Cell Station\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) rd->alpha2[0], rd->alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) pr_debug("Regulatory domain changed to country: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) rd->alpha2[0], rd->alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) pr_debug(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) print_rd_rules(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) static void print_regdomain_info(const struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) pr_debug("Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) print_rd_rules(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) static int reg_set_rd_core(const struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) if (!is_world_regdom(rd->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) update_world_regdomain(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) struct regulatory_request *user_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) const struct ieee80211_regdomain *intersected_rd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) if (!regdom_changes(rd->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) if (!is_valid_rd(rd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) pr_err("Invalid regulatory domain detected: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) rd->alpha2[0], rd->alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) print_regdomain_info(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) if (!user_request->intersect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) reset_regdomains(false, rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) if (!intersected_rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) kfree(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) rd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) reset_regdomains(false, intersected_rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) struct regulatory_request *driver_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) const struct ieee80211_regdomain *regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) const struct ieee80211_regdomain *intersected_rd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) const struct ieee80211_regdomain *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) struct wiphy *request_wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) if (is_world_regdom(rd->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) if (!regdom_changes(rd->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) if (!is_valid_rd(rd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) pr_err("Invalid regulatory domain detected: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) rd->alpha2[0], rd->alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) print_regdomain_info(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) if (!request_wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) if (!driver_request->intersect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) if (request_wiphy->regd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) regd = reg_copy_regd(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) if (IS_ERR(regd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) return PTR_ERR(regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) rcu_assign_pointer(request_wiphy->regd, regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) reset_regdomains(false, rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) if (!intersected_rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) * We can trash what CRDA provided now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) * However if a driver requested this specific regulatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) * domain we keep it for its private use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) tmp = get_wiphy_regdom(request_wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) rcu_assign_pointer(request_wiphy->regd, rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) rcu_free_regdom(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) rd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) reset_regdomains(false, intersected_rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) struct regulatory_request *country_ie_request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) struct wiphy *request_wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) !is_unknown_alpha2(rd->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) * Lets only bother proceeding on the same alpha2 if the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) * rd is non static (it means CRDA was present and was used last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) * and the pending request came in from a country IE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) if (!is_valid_rd(rd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) pr_err("Invalid regulatory domain detected: %c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) rd->alpha2[0], rd->alpha2[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) print_regdomain_info(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) if (!request_wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) if (country_ie_request->intersect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) reset_regdomains(false, rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) * Use this call to set the current regulatory domain. Conflicts with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) * multiple drivers can be ironed out later. Caller must've already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) * kmalloc'd the rd structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) int set_regdom(const struct ieee80211_regdomain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) enum ieee80211_regd_source regd_src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) struct regulatory_request *lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) bool user_reset = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) if (IS_ERR_OR_NULL(rd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) if (!reg_is_valid_request(rd->alpha2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) kfree(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) if (regd_src == REGD_SOURCE_CRDA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) reset_crda_timeouts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) /* Note that this doesn't update the wiphys, this is done below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) switch (lr->initiator) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) case NL80211_REGDOM_SET_BY_CORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) r = reg_set_rd_core(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) case NL80211_REGDOM_SET_BY_USER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) cfg80211_save_user_regdom(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) r = reg_set_rd_user(rd, lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) user_reset = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) case NL80211_REGDOM_SET_BY_DRIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) r = reg_set_rd_driver(rd, lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) case NL80211_REGDOM_SET_BY_COUNTRY_IE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) r = reg_set_rd_country_ie(rd, lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) WARN(1, "invalid initiator %d\n", lr->initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) kfree(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) switch (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) case -EALREADY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) reg_set_request_processed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) /* Back to world regulatory in case of errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) restore_regulatory_settings(user_reset, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) kfree(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) /* This would make this whole thing pointless */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom()))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) /* update all wiphys now with the new established regulatory domain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) update_all_wiphy_regulatory(lr->initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) print_regdomain(get_cfg80211_regdom());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) nl80211_send_reg_change_event(lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) reg_set_request_processed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) static int __regulatory_set_wiphy_regd(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) const struct ieee80211_regdomain *regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) const struct ieee80211_regdomain *prev_regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) if (WARN_ON(!wiphy || !rd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) if (WARN(!(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) "wiphy should have REGULATORY_WIPHY_SELF_MANAGED\n"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) if (WARN(!is_valid_rd(rd), "Invalid regulatory domain detected\n")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) print_regdomain_info(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) regd = reg_copy_regd(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) if (IS_ERR(regd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) return PTR_ERR(regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) spin_lock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) prev_regd = rdev->requested_regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) rdev->requested_regd = regd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) spin_unlock(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) kfree(prev_regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) int regulatory_set_wiphy_regd(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) int ret = __regulatory_set_wiphy_regd(wiphy, rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) schedule_work(®_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) EXPORT_SYMBOL(regulatory_set_wiphy_regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) struct ieee80211_regdomain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) ret = __regulatory_set_wiphy_regd(wiphy, rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) /* process the request immediately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) reg_process_self_managed_hints();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) EXPORT_SYMBOL(regulatory_set_wiphy_regd_sync_rtnl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) void wiphy_regulatory_register(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) struct regulatory_request *lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) /* self-managed devices ignore beacon hints and country IE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) REGULATORY_COUNTRY_IE_IGNORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) * The last request may have been received before this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) * registration call. Call the driver notifier if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) * initiator is USER.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) if (lr->initiator == NL80211_REGDOM_SET_BY_USER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) reg_call_notifier(wiphy, lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) if (!reg_dev_ignore_cell_hint(wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) reg_num_devs_support_basehint++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) wiphy_update_regulatory(wiphy, lr->initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) wiphy_all_share_dfs_chan_state(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) void wiphy_regulatory_deregister(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) struct wiphy *request_wiphy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) struct regulatory_request *lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) lr = get_last_request();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) if (!reg_dev_ignore_cell_hint(wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) reg_num_devs_support_basehint--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) rcu_free_regdom(get_wiphy_regdom(wiphy));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) RCU_INIT_POINTER(wiphy->regd, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) if (lr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) if (!request_wiphy || request_wiphy != wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) lr->wiphy_idx = WIPHY_IDX_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) lr->country_ie_env = ENVIRON_ANY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) * See FCC notices for UNII band definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) * 5GHz: https://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) * 6GHz: https://www.fcc.gov/document/fcc-proposes-more-spectrum-unlicensed-use-0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) int cfg80211_get_unii(int freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) /* UNII-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) if (freq >= 5150 && freq <= 5250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) /* UNII-2A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) if (freq > 5250 && freq <= 5350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) /* UNII-2B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) if (freq > 5350 && freq <= 5470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) /* UNII-2C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) if (freq > 5470 && freq <= 5725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) /* UNII-3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) if (freq > 5725 && freq <= 5825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) /* UNII-5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) if (freq > 5925 && freq <= 6425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) return 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) /* UNII-6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) if (freq > 6425 && freq <= 6525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) return 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) /* UNII-7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) if (freq > 6525 && freq <= 6875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) return 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) /* UNII-8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) if (freq > 6875 && freq <= 7125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) return 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) bool regulatory_indoor_allowed(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077) return reg_is_indoor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) bool regulatory_pre_cac_allowed(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) const struct ieee80211_regdomain *regd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) const struct ieee80211_regdomain *wiphy_regd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) bool pre_cac_allowed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) regd = rcu_dereference(cfg80211_regdomain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) wiphy_regd = rcu_dereference(wiphy->regd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) if (!wiphy_regd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) if (regd->dfs_region == NL80211_DFS_ETSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) pre_cac_allowed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) return pre_cac_allowed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) if (regd->dfs_region == wiphy_regd->dfs_region &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) wiphy_regd->dfs_region == NL80211_DFS_ETSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) pre_cac_allowed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) return pre_cac_allowed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) EXPORT_SYMBOL(regulatory_pre_cac_allowed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) /* If we finished CAC or received radar, we should end any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) * CAC running on the same channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) * the check !cfg80211_chandef_dfs_usable contain 2 options:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) * either all channels are available - those the CAC_FINISHED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) * event has effected another wdev state, or there is a channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) * in unavailable state in wdev chandef - those the RADAR_DETECTED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) * event has effected another wdev state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) * In both cases we should end the CAC on the wdev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) if (wdev->cac_started &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) !cfg80211_chandef_dfs_usable(&rdev->wiphy, &wdev->chandef))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) rdev_end_cac(rdev, wdev->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) void regulatory_propagate_dfs_state(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) struct cfg80211_chan_def *chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) enum nl80211_dfs_state dfs_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) enum nl80211_radar_event event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) if (WARN_ON(!cfg80211_chandef_valid(chandef)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) if (wiphy == &rdev->wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) if (!ieee80211_get_channel(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) chandef->chan->center_freq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) if (event == NL80211_RADAR_DETECTED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) event == NL80211_RADAR_CAC_FINISHED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) cfg80211_sched_dfs_chan_update(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) cfg80211_check_and_end_cac(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) static int __init regulatory_init_db(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) * It's possible that - due to other bugs/issues - cfg80211
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) * never called regulatory_init() below, or that it failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) * in that case, don't try to do any further work here as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) * it's doomed to lead to crashes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) if (IS_ERR_OR_NULL(reg_pdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) err = load_builtin_regdb_keys();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) /* We always try to get an update for the static regdomain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) err = regulatory_hint_core(cfg80211_world_regdom->alpha2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) if (err == -ENOMEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) platform_device_unregister(reg_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) * N.B. kobject_uevent_env() can fail mainly for when we're out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) * memory which is handled and propagated appropriately above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) * but it can also fail during a netlink_broadcast() or during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) * early boot for call_usermodehelper(). For now treat these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) * errors as non-fatal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) pr_err("kobject_uevent_env() was unable to call CRDA during init\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) * Finally, if the user set the module parameter treat it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) * as a user hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) if (!is_world_regdom(ieee80211_regdom))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) regulatory_hint_user(ieee80211_regdom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) NL80211_USER_REG_HINT_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) late_initcall(regulatory_init_db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) int __init regulatory_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) if (IS_ERR(reg_pdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) return PTR_ERR(reg_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) spin_lock_init(®_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) spin_lock_init(®_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) spin_lock_init(®_indoor_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) rcu_assign_pointer(cfg80211_regdomain, cfg80211_world_regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) user_alpha2[0] = '9';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) user_alpha2[1] = '7';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) return regulatory_init_db();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) void regulatory_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) struct regulatory_request *reg_request, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236) struct reg_beacon *reg_beacon, *btmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) cancel_work_sync(®_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) cancel_crda_timeout_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240) cancel_delayed_work_sync(®_check_chans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) /* Lock to suppress warnings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) reset_regdomains(true, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) dev_set_uevent_suppress(®_pdev->dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) platform_device_unregister(reg_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) list_for_each_entry_safe(reg_beacon, btmp, ®_pending_beacons, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) list_del(®_beacon->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) kfree(reg_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) list_for_each_entry_safe(reg_beacon, btmp, ®_beacon_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) list_del(®_beacon->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) kfree(reg_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) list_for_each_entry_safe(reg_request, tmp, ®_requests_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) list_del(®_request->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) kfree(reg_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266) if (!IS_ERR_OR_NULL(regdb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) kfree(regdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) if (!IS_ERR_OR_NULL(cfg80211_user_regdom))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) kfree(cfg80211_user_regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) free_regdb_keyring();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) }