Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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(&regd->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(&reg_regdb_apply_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	while (!list_empty(&reg_regdb_apply_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		request = list_first_entry(&reg_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(&reg_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(&reg_regdb_apply_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	list_add_tail(&request->list, &reg_regdb_apply_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	mutex_unlock(&reg_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(&reg_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(&reg_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", &reg_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 = &regdom->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) 				       &reg_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", &reg_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 = &reg_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(&reg_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 = &regd->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 = &reg_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 = &reg_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, &reg_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, &reg_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) 			 &reg_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 = &reg_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(&reg_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) 	if (!list_empty(&reg_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(&reg_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(&reg_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(&reg_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(&reg_requests_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) 		spin_unlock(&reg_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(&reg_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(&reg_request->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) 	spin_unlock(&reg_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(&reg_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) 	if (!list_empty(&reg_requests_list) && lr && lr->processed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) 		schedule_work(&reg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) 	spin_unlock(&reg_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(&reg_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) 				 &reg_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, &reg_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(&reg_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(&reg_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(&reg_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(&reg_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) 	list_add_tail(&request->list, &reg_requests_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) 	spin_unlock(&reg_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) 	schedule_work(&reg_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(&reg_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(&reg_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(&reg_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(&reg_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(&reg_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(&reg_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(&reg_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(&reg_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) 	list_splice_tail_init(&reg_requests_list, &tmp_reg_req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) 	spin_unlock(&reg_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(&reg_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) 	list_for_each_entry_safe(reg_beacon, btmp, &reg_pending_beacons, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) 		list_del(&reg_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(&reg_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, &reg_beacon_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) 		list_del(&reg_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(&reg_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) 			ureq = list_last_entry(&reg_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(&reg_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(&reg_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) 	list_splice_tail_init(&tmp_reg_req_list, &reg_requests_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) 	spin_unlock(&reg_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(&reg_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(&reg_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) 					 &reg_pending_beacons, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) 			list_del(&reg_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(&reg_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) 					 &reg_beacon_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) 			list_del(&reg_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, &reg_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(&reg_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(&reg_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(&reg_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(&reg_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) 	list_add_tail(&reg_beacon->list, &reg_pending_beacons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) 	spin_unlock_bh(&reg_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(&reg_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 = &reg_rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) 		power_rule = &reg_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(&reg_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(&reg_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(&reg_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(&reg_requests_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) 	spin_lock_init(&reg_pending_beacons_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) 	spin_lock_init(&reg_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(&reg_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(&reg_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(&reg_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, &reg_pending_beacons, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) 		list_del(&reg_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, &reg_beacon_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) 		list_del(&reg_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, &reg_requests_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) 		list_del(&reg_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) }