File Index
Files and directories
Sign in
FILE

regd.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/realtek/rtw89/regd.c C
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/* Copyright(c) 2019-2020  Realtek Corporation
   3 */
   4
   5#include "acpi.h"
   6#include "debug.h"
   7#include "ps.h"
   8#include "util.h"
   9
  10static
  11void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request);
  12
  13#define COUNTRY_REGD(_alpha2, _rule_2ghz, _rule_5ghz, _rule_6ghz, _fmap) \
  14	{							\
  15		.alpha2 = _alpha2,				\
  16		.txpwr_regd[RTW89_BAND_2G] = _rule_2ghz,	\
  17		.txpwr_regd[RTW89_BAND_5G] = _rule_5ghz,	\
  18		.txpwr_regd[RTW89_BAND_6G] = _rule_6ghz,	\
  19		.func_bitmap = { _fmap, },	\
  20	}
  21
  22static_assert(BITS_PER_TYPE(unsigned long) >= NUM_OF_RTW89_REGD_FUNC);
  23
  24static const struct rtw89_regd rtw89_ww_regd =
  25	COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW, 0x0);
  26
  27static const struct rtw89_regd rtw89_regd_map[] = {
  28	COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC, 0x0),
  29	COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
  30	COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
  31	COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE, 0x0),
  32	COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
  33	COUNTRY_REGD("CR", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
  34	COUNTRY_REGD("EC", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
  35	COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
  36	COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
  37	COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
  38	COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC, 0x0),
  39	COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
  40	COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
  41	COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
  42	COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
  43	COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x1),
  44	COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
  45	COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
  46	COUNTRY_REGD("PR", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
  47	COUNTRY_REGD("DO", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
  48	COUNTRY_REGD("AT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  49	COUNTRY_REGD("BE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  50	COUNTRY_REGD("CY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  51	COUNTRY_REGD("CZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  52	COUNTRY_REGD("DK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  53	COUNTRY_REGD("EE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  54	COUNTRY_REGD("FI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  55	COUNTRY_REGD("FR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  56	COUNTRY_REGD("DE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  57	COUNTRY_REGD("GR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  58	COUNTRY_REGD("HU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  59	COUNTRY_REGD("IS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  60	COUNTRY_REGD("IE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  61	COUNTRY_REGD("IT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  62	COUNTRY_REGD("LV", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  63	COUNTRY_REGD("LI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  64	COUNTRY_REGD("LT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  65	COUNTRY_REGD("LU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  66	COUNTRY_REGD("MT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  67	COUNTRY_REGD("MC", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  68	COUNTRY_REGD("NL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  69	COUNTRY_REGD("NO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  70	COUNTRY_REGD("PL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  71	COUNTRY_REGD("PT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  72	COUNTRY_REGD("SK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  73	COUNTRY_REGD("SI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  74	COUNTRY_REGD("ES", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  75	COUNTRY_REGD("SE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  76	COUNTRY_REGD("CH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  77	COUNTRY_REGD("GB", RTW89_UK, RTW89_UK, RTW89_UK, 0x0),
  78	COUNTRY_REGD("AL", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
  79	COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  80	COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  81	COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
  82	COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  83	COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
  84	COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  85	COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  86	COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
  87	COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  88	COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  89	COUNTRY_REGD("KZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
  90	COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  91	COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  92	COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  93	COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  94	COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  95	COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
  96	COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  97	COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
  98	COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
  99	COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 100	COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 101	COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR, 0x0),
 102	COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x2),
 103	COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 104	COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 105	COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 106	COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 107	COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 108	COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 109	COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 110	COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE, 0x0),
 111	COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 112	COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 113	COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 114	COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 115	COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 116	COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN, 0x0),
 117	COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 118	COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 119	COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 120	COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC, 0x1),
 121	COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 122	COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 123	COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 124	COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 125	COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 126	COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI, 0x0),
 127	COUNTRY_REGD("TH", RTW89_THAILAND, RTW89_THAILAND, RTW89_THAILAND, 0x0),
 128	COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 129	COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA, 0x0),
 130	COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA, 0x0),
 131	COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 132	COUNTRY_REGD("CA", RTW89_IC, RTW89_IC, RTW89_IC, 0x1),
 133	COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_MKK, 0x0),
 134	COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 135	COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 136	COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 137	COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 138	COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 139	COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 140	COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 141	COUNTRY_REGD("AD", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 142	COUNTRY_REGD("AO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 143	COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 144	COUNTRY_REGD("AQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 145	COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 146	COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 147	COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 148	COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 149	COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 150	COUNTRY_REGD("BY", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 151	COUNTRY_REGD("BZ", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 152	COUNTRY_REGD("BJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 153	COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 154	COUNTRY_REGD("BT", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 155	COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 156	COUNTRY_REGD("BV", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 157	COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 158	COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 159	COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 160	COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 161	COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 162	COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 163	COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 164	COUNTRY_REGD("CV", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 165	COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 166	COUNTRY_REGD("CF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 167	COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 168	COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
 169	COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
 170	COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 171	COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 172	COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 173	COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 174	COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 175	COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 176	COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 177	COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 178	COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 179	COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 180	COUNTRY_REGD("FK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 181	COUNTRY_REGD("FO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 182	COUNTRY_REGD("FJ", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 183	COUNTRY_REGD("GF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 184	COUNTRY_REGD("PF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 185	COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 186	COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 187	COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 188	COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 189	COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 190	COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 191	COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 192	COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 193	COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 194	COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 195	COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 196	COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 197	COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 198	COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 199	COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
 200	COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 201	COUNTRY_REGD("IM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 202	COUNTRY_REGD("JE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 203	COUNTRY_REGD("KI", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 204	COUNTRY_REGD("XK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 205	COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 206	COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 207	COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 208	COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 209	COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 210	COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 211	COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 212	COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 213	COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 214	COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 215	COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 216	COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 217	COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 218	COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 219	COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 220	COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 221	COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 222	COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 223	COUNTRY_REGD("NP", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 224	COUNTRY_REGD("NC", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 225	COUNTRY_REGD("NE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 226	COUNTRY_REGD("NU", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
 227	COUNTRY_REGD("NF", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
 228	COUNTRY_REGD("MP", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 229	COUNTRY_REGD("PW", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 230	COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 231	COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 232	COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 233	COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 234	COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 235	COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 236	COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 237	COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 238	COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 239	COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 240	COUNTRY_REGD("SM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 241	COUNTRY_REGD("ST", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 242	COUNTRY_REGD("SC", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
 243	COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 244	COUNTRY_REGD("SB", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 245	COUNTRY_REGD("SO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 246	COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 247	COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 248	COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 249	COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 250	COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 251	COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 252	COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 253	COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA, 0x0),
 254	COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 255	COUNTRY_REGD("TM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 256	COUNTRY_REGD("TC", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 257	COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA, 0x0),
 258	COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 259	COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
 260	COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0),
 261	COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 262	COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 263	COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 264	COUNTRY_REGD("ZM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 265	COUNTRY_REGD("CU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 266	COUNTRY_REGD("IR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 267	COUNTRY_REGD("SY", RTW89_ETSI, RTW89_NA, RTW89_NA, 0x0),
 268	COUNTRY_REGD("SD", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 269	COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0),
 270};
 271
 272static const char rtw89_alpha2_list_eu[][3] = {
 273	"AT",
 274	"BE",
 275	"CY",
 276	"CZ",
 277	"DK",
 278	"EE",
 279	"FI",
 280	"FR",
 281	"DE",
 282	"GR",
 283	"HU",
 284	"IS",
 285	"IE",
 286	"IT",
 287	"LV",
 288	"LI",
 289	"LT",
 290	"LU",
 291	"MT",
 292	"MC",
 293	"NL",
 294	"NO",
 295	"PL",
 296	"PT",
 297	"SK",
 298	"SI",
 299	"ES",
 300	"SE",
 301	"CH",
 302	"BG",
 303	"HR",
 304	"RO",
 305};
 306
 307static const struct rtw89_regd *rtw89_regd_find_reg_by_name(struct rtw89_dev *rtwdev,
 308							    const char *alpha2)
 309{
 310	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 311	const struct rtw89_regd_ctrl *regd_ctrl = &regulatory->ctrl;
 312	u32 i;
 313
 314	for (i = 0; i < regd_ctrl->nr; i++) {
 315		if (!memcmp(regd_ctrl->map[i].alpha2, alpha2, 2))
 316			return &regd_ctrl->map[i];
 317	}
 318
 319	return &rtw89_ww_regd;
 320}
 321
 322static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
 323{
 324	return regd == &rtw89_ww_regd;
 325}
 326
 327static u8 rtw89_regd_get_index(struct rtw89_dev *rtwdev, const struct rtw89_regd *regd)
 328{
 329	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 330	const struct rtw89_regd_ctrl *regd_ctrl = &regulatory->ctrl;
 331
 332	BUILD_BUG_ON(ARRAY_SIZE(rtw89_regd_map) > RTW89_REGD_MAX_COUNTRY_NUM);
 333
 334	if (rtw89_regd_is_ww(regd))
 335		return RTW89_REGD_MAX_COUNTRY_NUM;
 336
 337	return regd - regd_ctrl->map;
 338}
 339
 340static u8 rtw89_regd_get_index_by_name(struct rtw89_dev *rtwdev, const char *alpha2)
 341{
 342	const struct rtw89_regd *regd;
 343
 344	regd = rtw89_regd_find_reg_by_name(rtwdev, alpha2);
 345	return rtw89_regd_get_index(rtwdev, regd);
 346}
 347
 348#define rtw89_debug_regd(_dev, _regd, _desc, _argv...) \
 349do { \
 350	typeof(_regd) __r = _regd; \
 351	rtw89_debug(_dev, RTW89_DBG_REGD, _desc \
 352		    ": %c%c: mapping txregd to {2g: %d, 5g: %d, 6g: %d}\n", \
 353		    ##_argv, __r->alpha2[0], __r->alpha2[1], \
 354		    __r->txpwr_regd[RTW89_BAND_2G], \
 355		    __r->txpwr_regd[RTW89_BAND_5G], \
 356		    __r->txpwr_regd[RTW89_BAND_6G]); \
 357} while (0)
 358
 359static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev,
 360				   struct wiphy *wiphy)
 361{
 362	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 363	const struct rtw89_chip_info *chip = rtwdev->chip;
 364	struct ieee80211_supported_band *sband;
 365	struct rtw89_acpi_dsm_result res = {};
 366	bool enable;
 367	u8 index;
 368	int ret;
 369	u8 val;
 370
 371	sband = wiphy->bands[NL80211_BAND_5GHZ];
 372	if (!sband)
 373		return;
 374
 375	if (!chip->support_unii4) {
 376		sband->n_channels -= RTW89_5GHZ_UNII4_CHANNEL_NUM;
 377		return;
 378	}
 379
 380	bitmap_fill(regulatory->block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
 381
 382	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_UNII4_SUP, &res);
 383	if (ret) {
 384		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 385			    "acpi: cannot eval unii 4: %d\n", ret);
 386		val = u8_encode_bits(1, RTW89_ACPI_CONF_UNII4_US);
 387		goto bottom;
 388	}
 389
 390	val = res.u.value;
 391
 392	rtw89_debug(rtwdev, RTW89_DBG_REGD,
 393		    "acpi: eval if allow unii-4: 0x%x\n", val);
 394
 395bottom:
 396	index = rtw89_regd_get_index_by_name(rtwdev, "US");
 397	enable = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_US);
 398	if (enable && index != RTW89_REGD_MAX_COUNTRY_NUM)
 399		clear_bit(index, regulatory->block_unii4);
 400
 401	index = rtw89_regd_get_index_by_name(rtwdev, "CA");
 402	enable = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_CA);
 403	if (enable && index != RTW89_REGD_MAX_COUNTRY_NUM)
 404		clear_bit(index, regulatory->block_unii4);
 405}
 406
 407static void __rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev, bool block,
 408					   const char *alpha2)
 409{
 410	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 411	u8 index;
 412
 413	index = rtw89_regd_get_index_by_name(rtwdev, alpha2);
 414	if (index == RTW89_REGD_MAX_COUNTRY_NUM) {
 415		rtw89_debug(rtwdev, RTW89_DBG_REGD, "%s: unknown alpha2 %c%c\n",
 416			    __func__, alpha2[0], alpha2[1]);
 417		return;
 418	}
 419
 420	if (block)
 421		set_bit(index, regulatory->block_6ghz);
 422	else
 423		clear_bit(index, regulatory->block_6ghz);
 424}
 425
 426static void rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev)
 427{
 428	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 429	const struct rtw89_acpi_country_code *country;
 430	const struct rtw89_acpi_policy_6ghz *ptr;
 431	struct rtw89_acpi_dsm_result res = {};
 432	bool to_block;
 433	int i, j;
 434	int ret;
 435
 436	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_BP, &res);
 437	if (ret) {
 438		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 439			    "acpi: cannot eval policy 6ghz: %d\n", ret);
 440		return;
 441	}
 442
 443	ptr = res.u.policy_6ghz;
 444
 445	switch (ptr->policy_mode) {
 446	case RTW89_ACPI_POLICY_BLOCK:
 447		to_block = true;
 448		break;
 449	case RTW89_ACPI_POLICY_ALLOW:
 450		to_block = false;
 451		/* only below list is allowed; block all first */
 452		bitmap_fill(regulatory->block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM);
 453		break;
 454	default:
 455		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 456			    "%s: unknown policy mode: %d\n", __func__,
 457			    ptr->policy_mode);
 458		goto out;
 459	}
 460
 461	for (i = 0; i < ptr->country_count; i++) {
 462		country = &ptr->country_list[i];
 463		if (memcmp("EU", country->alpha2, 2) != 0) {
 464			__rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
 465						       country->alpha2);
 466			continue;
 467		}
 468
 469		for (j = 0; j < ARRAY_SIZE(rtw89_alpha2_list_eu); j++)
 470			__rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
 471						       rtw89_alpha2_list_eu[j]);
 472	}
 473
 474out:
 475	kfree(ptr);
 476}
 477
 478static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev)
 479{
 480	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 481	const struct rtw89_acpi_policy_6ghz_sp *ptr;
 482	struct rtw89_acpi_dsm_result res = {};
 483	bool enable;
 484	u8 index;
 485	int ret;
 486
 487	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, &res);
 488	if (ret) {
 489		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 490			    "acpi: cannot eval policy 6ghz-sp: %d\n", ret);
 491		return;
 492	}
 493
 494	ptr = res.u.policy_6ghz_sp;
 495
 496	switch (ptr->override) {
 497	default:
 498		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 499			    "%s: unknown override case: %d\n", __func__,
 500			    ptr->override);
 501		fallthrough;
 502	case 0:
 503		goto out;
 504	case 1:
 505		break;
 506	}
 507
 508	bitmap_fill(regulatory->block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM);
 509
 510	index = rtw89_regd_get_index_by_name(rtwdev, "US");
 511	enable = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US);
 512	if (enable && index != RTW89_REGD_MAX_COUNTRY_NUM)
 513		clear_bit(index, regulatory->block_6ghz_sp);
 514
 515	index = rtw89_regd_get_index_by_name(rtwdev, "CA");
 516	enable = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_CA);
 517	if (enable && index != RTW89_REGD_MAX_COUNTRY_NUM)
 518		clear_bit(index, regulatory->block_6ghz_sp);
 519
 520out:
 521	kfree(ptr);
 522}
 523
 524static void rtw89_regd_setup_policy_6ghz_vlp(struct rtw89_dev *rtwdev)
 525{
 526	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 527	const struct rtw89_acpi_policy_6ghz_vlp *ptr = NULL;
 528	struct rtw89_acpi_dsm_result res = {};
 529	bool enable;
 530	u8 index;
 531	int ret;
 532	u8 val;
 533
 534	/* By default, allow 6 GHz VLP on all countries except US and CA. */
 535	val = ~(RTW89_ACPI_CONF_6GHZ_VLP_US | RTW89_ACPI_CONF_6GHZ_VLP_CA);
 536
 537	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_VLP_SUP, &res);
 538	if (ret) {
 539		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 540			    "acpi: cannot eval policy 6ghz-vlp: %d\n", ret);
 541		goto bottom;
 542	}
 543
 544	ptr = res.u.policy_6ghz_vlp;
 545
 546	switch (ptr->override) {
 547	default:
 548		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 549			    "%s: unknown override case: %d\n", __func__,
 550			    ptr->override);
 551		fallthrough;
 552	case 0:
 553		break;
 554	case 1:
 555		val = ptr->conf;
 556		break;
 557	}
 558
 559bottom:
 560	index = rtw89_regd_get_index_by_name(rtwdev, "US");
 561	enable = u8_get_bits(val, RTW89_ACPI_CONF_6GHZ_VLP_US);
 562	if (!enable && index != RTW89_REGD_MAX_COUNTRY_NUM)
 563		set_bit(index, regulatory->block_6ghz_vlp);
 564
 565	index = rtw89_regd_get_index_by_name(rtwdev, "CA");
 566	enable = u8_get_bits(val, RTW89_ACPI_CONF_6GHZ_VLP_CA);
 567	if (!enable && index != RTW89_REGD_MAX_COUNTRY_NUM)
 568		set_bit(index, regulatory->block_6ghz_vlp);
 569
 570	kfree(ptr);
 571}
 572
 573static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
 574{
 575	const struct rtw89_chip_info *chip = rtwdev->chip;
 576	bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ);
 577	bool regd_allow_6ghz = chip_support_6ghz;
 578	struct ieee80211_supported_band *sband;
 579	struct rtw89_acpi_dsm_result res = {};
 580	int ret;
 581	u8 val;
 582
 583	if (!chip_support_6ghz)
 584		goto bottom;
 585
 586	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &res);
 587	if (ret) {
 588		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 589			    "acpi: cannot eval 6ghz: %d\n", ret);
 590		goto bottom;
 591	}
 592
 593	val = res.u.value;
 594
 595	rtw89_debug(rtwdev, RTW89_DBG_REGD,
 596		    "acpi: eval if disallow 6ghz: %d\n", val);
 597
 598	switch (val) {
 599	case 0:
 600		regd_allow_6ghz = true;
 601		break;
 602	case 1:
 603		regd_allow_6ghz = false;
 604		break;
 605	default:
 606		break;
 607	}
 608
 609bottom:
 610	rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n",
 611		    regd_allow_6ghz);
 612
 613	if (regd_allow_6ghz) {
 614		rtw89_regd_setup_policy_6ghz(rtwdev);
 615		rtw89_regd_setup_policy_6ghz_sp(rtwdev);
 616		rtw89_regd_setup_policy_6ghz_vlp(rtwdev);
 617		return;
 618	}
 619
 620	sband = wiphy->bands[NL80211_BAND_6GHZ];
 621	if (!sband)
 622		return;
 623
 624	wiphy->bands[NL80211_BAND_6GHZ] = NULL;
 625	kfree((__force void *)sband->iftype_data);
 626	kfree(sband);
 627}
 628
 629#define RTW89_DEF_REGD_STR(regd) \
 630	[RTW89_ ## regd] = #regd
 631
 632static const char * const rtw89_regd_string[] = {
 633	RTW89_DEF_REGD_STR(WW),
 634	RTW89_DEF_REGD_STR(ETSI),
 635	RTW89_DEF_REGD_STR(FCC),
 636	RTW89_DEF_REGD_STR(MKK),
 637	RTW89_DEF_REGD_STR(NA),
 638	RTW89_DEF_REGD_STR(IC),
 639	RTW89_DEF_REGD_STR(KCC),
 640	RTW89_DEF_REGD_STR(ACMA),
 641	RTW89_DEF_REGD_STR(NCC),
 642	RTW89_DEF_REGD_STR(MEXICO),
 643	RTW89_DEF_REGD_STR(CHILE),
 644	RTW89_DEF_REGD_STR(UKRAINE),
 645	RTW89_DEF_REGD_STR(CN),
 646	RTW89_DEF_REGD_STR(QATAR),
 647	RTW89_DEF_REGD_STR(UK),
 648	RTW89_DEF_REGD_STR(THAILAND),
 649};
 650
 651static_assert(ARRAY_SIZE(rtw89_regd_string) == RTW89_REGD_NUM);
 652
 653const char *rtw89_regd_get_string(enum rtw89_regulation_type regd)
 654{
 655	if (regd < 0 || regd >= RTW89_REGD_NUM)
 656		return "(unknown)";
 657
 658	return rtw89_regd_string[regd];
 659}
 660
 661static void rtw89_regd_setup_reg_rules(struct rtw89_dev *rtwdev)
 662{
 663	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 664	const struct rtw89_acpi_policy_reg_rules *ptr;
 665	struct rtw89_acpi_dsm_result res = {};
 666	int ret;
 667
 668	regulatory->txpwr_uk_follow_etsi = true;
 669
 670	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_REG_RULES_EN, &res);
 671	if (ret) {
 672		rtw89_debug(rtwdev, RTW89_DBG_REGD,
 673			    "acpi: cannot eval policy reg-rules: %d\n", ret);
 674		return;
 675	}
 676
 677	ptr = res.u.policy_reg_rules;
 678
 679	regulatory->txpwr_uk_follow_etsi =
 680		!u8_get_bits(ptr->conf, RTW89_ACPI_CONF_REG_RULE_REGD_UK);
 681
 682	kfree(ptr);
 683}
 684
 685int rtw89_regd_setup(struct rtw89_dev *rtwdev)
 686{
 687	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 688	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
 689	const struct rtw89_regd_data *regd_data = elm_info->regd;
 690	struct wiphy *wiphy = rtwdev->hw->wiphy;
 691
 692	if (regd_data) {
 693		regulatory->ctrl.nr = regd_data->nr;
 694		regulatory->ctrl.map = regd_data->map;
 695	} else {
 696		regulatory->ctrl.nr = ARRAY_SIZE(rtw89_regd_map);
 697		regulatory->ctrl.map = rtw89_regd_map;
 698	}
 699
 700	regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
 701
 702	rtw89_regd_setup_reg_rules(rtwdev);
 703
 704	if (!wiphy)
 705		return -EINVAL;
 706
 707	rtw89_regd_setup_unii4(rtwdev, wiphy);
 708	rtw89_regd_setup_6ghz(rtwdev, wiphy);
 709
 710	wiphy->reg_notifier = rtw89_regd_notifier;
 711	return 0;
 712}
 713
 714int rtw89_regd_init_hint(struct rtw89_dev *rtwdev)
 715{
 716	const struct rtw89_regd *chip_regd;
 717	struct wiphy *wiphy = rtwdev->hw->wiphy;
 718	int ret;
 719
 720	if (!wiphy)
 721		return -EINVAL;
 722
 723	chip_regd = rtw89_regd_find_reg_by_name(rtwdev, rtwdev->efuse.country_code);
 724	if (!rtw89_regd_is_ww(chip_regd)) {
 725		rtwdev->regulatory.regd = chip_regd;
 726		rtwdev->regulatory.programmed = true;
 727
 728		/* Ignore country ie if there is a country domain programmed in chip */
 729		wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
 730		wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
 731
 732		ret = regulatory_hint(rtwdev->hw->wiphy,
 733				      rtwdev->regulatory.regd->alpha2);
 734		if (ret)
 735			rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret);
 736
 737		rtw89_debug_regd(rtwdev, chip_regd, "efuse country code");
 738		return 0;
 739	}
 740
 741	rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
 742			 "worldwide roaming chip, follow the setting of stack");
 743	return 0;
 744}
 745
 746static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
 747					  struct wiphy *wiphy)
 748{
 749	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 750	const struct rtw89_chip_info *chip = rtwdev->chip;
 751	const struct rtw89_regd *regd = regulatory->regd;
 752	struct ieee80211_supported_band *sband;
 753	u8 index;
 754	int i;
 755
 756	sband = wiphy->bands[NL80211_BAND_5GHZ];
 757	if (!sband)
 758		return;
 759
 760	if (!chip->support_unii4)
 761		return;
 762
 763	index = rtw89_regd_get_index(rtwdev, regd);
 764	if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
 765	    !test_bit(index, regulatory->block_unii4))
 766		return;
 767
 768	rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n",
 769		    regd->alpha2[0], regd->alpha2[1]);
 770
 771	for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++)
 772		sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
 773}
 774
 775static bool regd_is_6ghz_blocked(struct rtw89_dev *rtwdev)
 776{
 777	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 778	const struct rtw89_regd *regd = regulatory->regd;
 779	u8 index;
 780
 781	index = rtw89_regd_get_index(rtwdev, regd);
 782	if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
 783	    !test_bit(index, regulatory->block_6ghz))
 784		return false;
 785
 786	rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n",
 787		    regd->alpha2[0], regd->alpha2[1]);
 788	return true;
 789}
 790
 791static bool regd_is_6ghz_not_applicable(struct rtw89_dev *rtwdev)
 792{
 793	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 794	const struct rtw89_regd *regd = regulatory->regd;
 795
 796	if (regd->txpwr_regd[RTW89_BAND_6G] != RTW89_NA)
 797		return false;
 798
 799	rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is N/A in regd map\n",
 800		    regd->alpha2[0], regd->alpha2[1]);
 801	return true;
 802}
 803
 804static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
 805					 struct wiphy *wiphy)
 806{
 807	struct ieee80211_supported_band *sband;
 808	int i;
 809
 810	if (!regd_is_6ghz_blocked(rtwdev) &&
 811	    !regd_is_6ghz_not_applicable(rtwdev))
 812		return;
 813
 814	sband = wiphy->bands[NL80211_BAND_6GHZ];
 815	if (!sband)
 816		return;
 817
 818	for (i = 0; i < sband->n_channels; i++)
 819		sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
 820}
 821
 822static void rtw89_regd_apply_policy_tas(struct rtw89_dev *rtwdev)
 823{
 824	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 825	const struct rtw89_regd *regd = regulatory->regd;
 826	struct rtw89_tas_info *tas = &rtwdev->tas;
 827	u8 tas_country;
 828
 829	if (!tas->enable)
 830		return;
 831
 832	if (memcmp("US", regd->alpha2, 2) == 0)
 833		tas_country = RTW89_ACPI_CONF_TAS_US;
 834	else if (memcmp("CA", regd->alpha2, 2) == 0)
 835		tas_country = RTW89_ACPI_CONF_TAS_CA;
 836	else if (memcmp("KR", regd->alpha2, 2) == 0)
 837		tas_country = RTW89_ACPI_CONF_TAS_KR;
 838	else
 839		tas_country = RTW89_ACPI_CONF_TAS_OTHERS;
 840
 841	tas->block_regd = !(tas->enabled_countries & tas_country &&
 842			    test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap));
 843}
 844
 845static void rtw89_regd_apply_policy_ant_gain(struct rtw89_dev *rtwdev)
 846{
 847	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 848	struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
 849	const struct rtw89_chip_info *chip = rtwdev->chip;
 850	const struct rtw89_regd *regd = regulatory->regd;
 851
 852	if (!chip->support_ant_gain)
 853		return;
 854
 855	ant_gain->block_country = !test_bit(RTW89_REGD_FUNC_DAG, regd->func_bitmap);
 856}
 857
 858static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
 859				      struct wiphy *wiphy,
 860				      struct regulatory_request *request)
 861{
 862	rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(rtwdev, request->alpha2);
 863	/* This notification might be set from the system of distros,
 864	 * and it does not expect the regulatory will be modified by
 865	 * connecting to an AP (i.e. country ie).
 866	 */
 867	if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
 868	    !rtw89_regd_is_ww(rtwdev->regulatory.regd))
 869		wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
 870	else
 871		wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
 872}
 873
 874static
 875void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 876{
 877	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 878	struct rtw89_dev *rtwdev = hw->priv;
 879
 880	wiphy_lock(wiphy);
 881	rtw89_leave_ps_mode(rtwdev);
 882
 883	if (rtwdev->regulatory.programmed)
 884		goto policy;
 885
 886	rtw89_regd_notifier_apply(rtwdev, wiphy, request);
 887	rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
 888			 "get from initiator %d, alpha2",
 889			 request->initiator);
 890
 891policy:
 892	rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
 893	rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
 894	rtw89_regd_apply_policy_tas(rtwdev);
 895	rtw89_regd_apply_policy_ant_gain(rtwdev);
 896
 897	rtw89_core_set_chip_txpwr(rtwdev);
 898
 899	wiphy_unlock(wiphy);
 900}
 901
 902/* Maximum Transmit Power field (@raw) can be EIRP or PSD.
 903 * Both units are 0.5 dB-based. Return a constraint in dB.
 904 */
 905static s8 tpe_get_constraint(s8 raw)
 906{
 907	const u8 hw_deviation = 3; /* unit: 0.5 dB */
 908	const u8 antenna_gain = 10; /* unit: 0.5 dB */
 909	const u8 array_gain = 6; /* unit: 0.5 dB */
 910	const u8 offset = hw_deviation + antenna_gain + array_gain;
 911
 912	return (raw - offset) / 2;
 913}
 914
 915static void tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe *tpe, s8 cstr)
 916{
 917	if (tpe->valid) {
 918		tpe->constraint = min(tpe->constraint, cstr);
 919		return;
 920	}
 921
 922	tpe->constraint = cstr;
 923	tpe->valid = true;
 924}
 925
 926static void tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe *tpe,
 927			       const struct ieee80211_parsed_tpe_eirp *eirp)
 928{
 929	unsigned int i;
 930	s8 cstr;
 931
 932	if (!eirp->valid)
 933		return;
 934
 935	for (i = 0; i < eirp->count; i++) {
 936		cstr = tpe_get_constraint(eirp->power[i]);
 937		tpe_intersect_constraint(tpe, cstr);
 938	}
 939}
 940
 941static s8 tpe_convert_psd_to_eirp(s8 psd)
 942{
 943	static const unsigned int mlog20 = 1301;
 944
 945	return psd + 10 * mlog20 / 1000;
 946}
 947
 948static void tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe *tpe,
 949			      const struct ieee80211_parsed_tpe_psd *psd)
 950{
 951	unsigned int i;
 952	s8 cstr_psd;
 953	s8 cstr;
 954
 955	if (!psd->valid)
 956		return;
 957
 958	for (i = 0; i < psd->count; i++) {
 959		cstr_psd = tpe_get_constraint(psd->power[i]);
 960		cstr = tpe_convert_psd_to_eirp(cstr_psd);
 961		tpe_intersect_constraint(tpe, cstr);
 962	}
 963}
 964
 965static void rtw89_calculate_tpe(struct rtw89_dev *rtwdev,
 966				struct rtw89_reg_6ghz_tpe *result_tpe,
 967				const struct ieee80211_parsed_tpe *parsed_tpe)
 968{
 969	static const u8 category = IEEE80211_TPE_CAT_6GHZ_DEFAULT;
 970
 971	tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_local[category]);
 972	tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_reg_client[category]);
 973	tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_local[category]);
 974	tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_reg_client[category]);
 975}
 976
 977static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
 978{
 979	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 980	struct rtw89_reg_6ghz_tpe new = {};
 981	struct rtw89_vif_link *rtwvif_link;
 982	struct rtw89_vif *rtwvif;
 983	unsigned int link_id;
 984	bool changed = false;
 985
 986	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
 987		const struct rtw89_reg_6ghz_tpe *tmp;
 988		const struct rtw89_chan *chan;
 989
 990		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
 991			chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
 992			if (chan->band_type != RTW89_BAND_6G)
 993				continue;
 994
 995			tmp = &rtwvif_link->reg_6ghz_tpe;
 996			if (!tmp->valid)
 997				continue;
 998
 999			tpe_intersect_constraint(&new, tmp->constraint);
1000		}
1001	}
1002
1003	if (memcmp(&regulatory->reg_6ghz_tpe, &new,
1004		   sizeof(regulatory->reg_6ghz_tpe)) != 0)
1005		changed = true;
1006
1007	if (changed) {
1008		if (new.valid)
1009			rtw89_debug(rtwdev, RTW89_DBG_REGD,
1010				    "recalc 6 GHz reg TPE to %d dBm\n",
1011				    new.constraint);
1012		else
1013			rtw89_debug(rtwdev, RTW89_DBG_REGD,
1014				    "recalc 6 GHz reg TPE to none\n");
1015
1016		regulatory->reg_6ghz_tpe = new;
1017	}
1018
1019	return changed;
1020}
1021
1022static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev,
1023				     struct rtw89_vif_link *rtwvif_link, bool active,
1024				     unsigned int *changed)
1025{
1026	struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe;
1027	struct ieee80211_bss_conf *bss_conf;
1028
1029	memset(tpe, 0, sizeof(*tpe));
1030
1031	if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD)
1032		goto bottom;
1033
1034	rcu_read_lock();
1035
1036	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
1037	rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe);
1038
1039	rcu_read_unlock();
1040
1041	if (!tpe->valid)
1042		goto bottom;
1043
1044	if (tpe->constraint < RTW89_MIN_VALID_POWER_CONSTRAINT) {
1045		rtw89_err(rtwdev,
1046			  "%s: constraint %d dBm is less than min valid val\n",
1047			  __func__, tpe->constraint);
1048
1049		tpe->valid = false;
1050		return -EINVAL;
1051	}
1052
1053bottom:
1054	*changed += __rtw89_reg_6ghz_tpe_recalc(rtwdev);
1055	return 0;
1056}
1057
1058static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
1059{
1060	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
1061	const struct rtw89_regd *regd = regulatory->regd;
1062	enum rtw89_reg_6ghz_power sel;
1063	const struct rtw89_chan *chan;
1064	struct rtw89_vif_link *rtwvif_link;
1065	struct rtw89_vif *rtwvif;
1066	unsigned int link_id;
1067	int count = 0;
1068	u8 index;
1069
1070	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
1071		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
1072			chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
1073			if (chan->band_type != RTW89_BAND_6G)
1074				continue;
1075
1076			if (count != 0 && rtwvif_link->reg_6ghz_power == sel)
1077				continue;
1078
1079			sel = rtwvif_link->reg_6ghz_power;
1080			count++;
1081		}
1082	}
1083
1084	if (count != 1)
1085		sel = RTW89_REG_6GHZ_POWER_DFLT;
1086
1087	if (sel == RTW89_REG_6GHZ_POWER_STD) {
1088		index = rtw89_regd_get_index(rtwdev, regd);
1089		if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
1090		    test_bit(index, regulatory->block_6ghz_sp)) {
1091			rtw89_debug(rtwdev, RTW89_DBG_REGD,
1092				    "%c%c 6 GHz SP is blocked by policy\n",
1093				    regd->alpha2[0], regd->alpha2[1]);
1094			sel = RTW89_REG_6GHZ_POWER_DFLT;
1095		}
1096	}
1097
1098	if (regulatory->reg_6ghz_power == sel)
1099		return false;
1100
1101	rtw89_debug(rtwdev, RTW89_DBG_REGD,
1102		    "recalc 6 GHz reg power type to %d\n", sel);
1103
1104	regulatory->reg_6ghz_power = sel;
1105	return true;
1106}
1107
1108static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
1109				       struct rtw89_vif_link *rtwvif_link, bool active,
1110				       unsigned int *changed)
1111{
1112	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
1113	const struct rtw89_regd *regd = regulatory->regd;
1114	bool blocked[NUM_OF_RTW89_REG_6GHZ_POWER] = {};
1115	u8 index = rtw89_regd_get_index(rtwdev, regd);
1116	struct ieee80211_bss_conf *bss_conf;
1117	bool dflt = false;
1118
1119	if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
1120	    test_bit(index, regulatory->block_6ghz_vlp))
1121		blocked[RTW89_REG_6GHZ_POWER_VLP] = true;
1122
1123	rcu_read_lock();
1124
1125	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
1126
1127	if (active) {
1128		switch (bss_conf->power_type) {
1129		case IEEE80211_REG_VLP_AP:
1130			rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
1131			break;
1132		case IEEE80211_REG_LPI_AP:
1133			rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
1134			break;
1135		case IEEE80211_REG_SP_AP:
1136			rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
1137			break;
1138		default:
1139			rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
1140			dflt = true;
1141			break;
1142		}
1143	} else {
1144		rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
1145		dflt = true;
1146	}
1147
1148	rcu_read_unlock();
1149
1150	if (!dflt && blocked[rtwvif_link->reg_6ghz_power]) {
1151		rtw89_debug(rtwdev, RTW89_DBG_REGD,
1152			    "%c%c 6 GHz power type-%u is blocked by policy\n",
1153			    regd->alpha2[0], regd->alpha2[1],
1154			    rtwvif_link->reg_6ghz_power);
1155		return -EINVAL;
1156	}
1157
1158	*changed += __rtw89_reg_6ghz_power_recalc(rtwdev);
1159	return 0;
1160}
1161
1162int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
1163			  bool active)
1164{
1165	unsigned int changed = 0;
1166	int ret;
1167
1168	lockdep_assert_wiphy(rtwdev->hw->wiphy);
1169
1170	/* The result of reg_6ghz_tpe may depend on reg_6ghz_power type,
1171	 * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc().
1172	 */
1173
1174	ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed);
1175	if (ret)
1176		return ret;
1177
1178	ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed);
1179	if (ret)
1180		return ret;
1181
1182	if (changed)
1183		rtw89_core_set_chip_txpwr(rtwdev);
1184
1185	return 0;
1186}
~/ Read-only file preview.