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
10 static
11 void 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
22 static_assert(BITS_PER_TYPE(unsigned long) >= NUM_OF_RTW89_REGD_FUNC);
23
24 static const struct rtw89_regd rtw89_ww_regd =
25 COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW, 0x0);
26
27 static 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
272 static 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
rtw89_regd_find_reg_by_name(struct rtw89_dev * rtwdev,const char * alpha2)307 static 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 = ®ulatory->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 ®d_ctrl->map[i];
317 }
318
319 return &rtw89_ww_regd;
320 }
321
rtw89_regd_is_ww(const struct rtw89_regd * regd)322 static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
323 {
324 return regd == &rtw89_ww_regd;
325 }
326
rtw89_regd_get_index(struct rtw89_dev * rtwdev,const struct rtw89_regd * regd)327 static 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 = ®ulatory->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
rtw89_regd_get_index_by_name(struct rtw89_dev * rtwdev,const char * alpha2)340 static 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...) \
349 do { \
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
rtw89_regd_setup_unii4(struct rtw89_dev * rtwdev,struct wiphy * wiphy)359 static 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
395 bottom:
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
__rtw89_regd_setup_policy_6ghz(struct rtw89_dev * rtwdev,bool block,const char * alpha2)407 static 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
rtw89_regd_setup_policy_6ghz(struct rtw89_dev * rtwdev)426 static 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
474 out:
475 kfree(ptr);
476 }
477
rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev * rtwdev)478 static 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
520 out:
521 kfree(ptr);
522 }
523
rtw89_regd_setup_policy_6ghz_vlp(struct rtw89_dev * rtwdev)524 static 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
559 bottom:
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
rtw89_regd_setup_6ghz(struct rtw89_dev * rtwdev,struct wiphy * wiphy)573 static 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
609 bottom:
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
632 static 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
651 static_assert(ARRAY_SIZE(rtw89_regd_string) == RTW89_REGD_NUM);
652
rtw89_regd_get_string(enum rtw89_regulation_type regd)653 const 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
rtw89_regd_setup_reg_rules(struct rtw89_dev * rtwdev)661 static 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
rtw89_regd_setup(struct rtw89_dev * rtwdev)685 int 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
rtw89_regd_init_hint(struct rtw89_dev * rtwdev)714 int 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 defined(__FreeBSD__)
725 rtwdev->regulatory.regd = chip_regd;
726 #endif
727 if (!rtw89_regd_is_ww(chip_regd)) {
728 #if defined(__linux__)
729 rtwdev->regulatory.regd = chip_regd;
730 #endif
731 /* Ignore country ie if there is a country domain programmed in chip */
732 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
733 wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
734
735 ret = regulatory_hint(rtwdev->hw->wiphy,
736 rtwdev->regulatory.regd->alpha2);
737 if (ret)
738 rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret);
739
740 rtw89_debug_regd(rtwdev, chip_regd, "efuse country code");
741 return 0;
742 }
743
744 rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
745 "worldwide roaming chip, follow the setting of stack");
746 return 0;
747 }
748
rtw89_regd_apply_policy_unii4(struct rtw89_dev * rtwdev,struct wiphy * wiphy)749 static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
750 struct wiphy *wiphy)
751 {
752 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
753 const struct rtw89_chip_info *chip = rtwdev->chip;
754 const struct rtw89_regd *regd = regulatory->regd;
755 struct ieee80211_supported_band *sband;
756 u8 index;
757 int i;
758
759 sband = wiphy->bands[NL80211_BAND_5GHZ];
760 if (!sband)
761 return;
762
763 if (!chip->support_unii4)
764 return;
765
766 index = rtw89_regd_get_index(rtwdev, regd);
767 if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
768 !test_bit(index, regulatory->block_unii4))
769 return;
770
771 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n",
772 regd->alpha2[0], regd->alpha2[1]);
773
774 for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++)
775 sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
776 }
777
regd_is_6ghz_blocked(struct rtw89_dev * rtwdev)778 static bool regd_is_6ghz_blocked(struct rtw89_dev *rtwdev)
779 {
780 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
781 const struct rtw89_regd *regd = regulatory->regd;
782 u8 index;
783
784 index = rtw89_regd_get_index(rtwdev, regd);
785 if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
786 !test_bit(index, regulatory->block_6ghz))
787 return false;
788
789 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n",
790 regd->alpha2[0], regd->alpha2[1]);
791 return true;
792 }
793
regd_is_6ghz_not_applicable(struct rtw89_dev * rtwdev)794 static bool regd_is_6ghz_not_applicable(struct rtw89_dev *rtwdev)
795 {
796 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
797 const struct rtw89_regd *regd = regulatory->regd;
798
799 if (regd->txpwr_regd[RTW89_BAND_6G] != RTW89_NA)
800 return false;
801
802 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is N/A in regd map\n",
803 regd->alpha2[0], regd->alpha2[1]);
804 return true;
805 }
806
rtw89_regd_apply_policy_6ghz(struct rtw89_dev * rtwdev,struct wiphy * wiphy)807 static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
808 struct wiphy *wiphy)
809 {
810 struct ieee80211_supported_band *sband;
811 int i;
812
813 if (!regd_is_6ghz_blocked(rtwdev) &&
814 !regd_is_6ghz_not_applicable(rtwdev))
815 return;
816
817 sband = wiphy->bands[NL80211_BAND_6GHZ];
818 if (!sband)
819 return;
820
821 for (i = 0; i < sband->n_channels; i++)
822 sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
823 }
824
rtw89_regd_apply_policy_tas(struct rtw89_dev * rtwdev)825 static void rtw89_regd_apply_policy_tas(struct rtw89_dev *rtwdev)
826 {
827 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
828 const struct rtw89_regd *regd = regulatory->regd;
829 struct rtw89_tas_info *tas = &rtwdev->tas;
830 u8 tas_country;
831
832 if (!tas->enable)
833 return;
834
835 if (memcmp("US", regd->alpha2, 2) == 0)
836 tas_country = RTW89_ACPI_CONF_TAS_US;
837 else if (memcmp("CA", regd->alpha2, 2) == 0)
838 tas_country = RTW89_ACPI_CONF_TAS_CA;
839 else if (memcmp("KR", regd->alpha2, 2) == 0)
840 tas_country = RTW89_ACPI_CONF_TAS_KR;
841 else
842 tas_country = RTW89_ACPI_CONF_TAS_OTHERS;
843
844 tas->block_regd = !(tas->enabled_countries & tas_country &&
845 test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap));
846 }
847
rtw89_regd_apply_policy_ant_gain(struct rtw89_dev * rtwdev)848 static void rtw89_regd_apply_policy_ant_gain(struct rtw89_dev *rtwdev)
849 {
850 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
851 struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
852 const struct rtw89_chip_info *chip = rtwdev->chip;
853 const struct rtw89_regd *regd = regulatory->regd;
854
855 if (!chip->support_ant_gain)
856 return;
857
858 ant_gain->block_country = !test_bit(RTW89_REGD_FUNC_DAG, regd->func_bitmap);
859 }
860
rtw89_regd_notifier_apply(struct rtw89_dev * rtwdev,struct wiphy * wiphy,struct regulatory_request * request)861 static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
862 struct wiphy *wiphy,
863 struct regulatory_request *request)
864 {
865 rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(rtwdev, request->alpha2);
866 /* This notification might be set from the system of distros,
867 * and it does not expect the regulatory will be modified by
868 * connecting to an AP (i.e. country ie).
869 */
870 if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
871 !rtw89_regd_is_ww(rtwdev->regulatory.regd))
872 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
873 else
874 wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
875
876 rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
877 rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
878 rtw89_regd_apply_policy_tas(rtwdev);
879 rtw89_regd_apply_policy_ant_gain(rtwdev);
880 }
881
882 static
rtw89_regd_notifier(struct wiphy * wiphy,struct regulatory_request * request)883 void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
884 {
885 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
886 struct rtw89_dev *rtwdev = hw->priv;
887
888 wiphy_lock(wiphy);
889 rtw89_leave_ps_mode(rtwdev);
890
891 if (wiphy->regd) {
892 rtw89_debug(rtwdev, RTW89_DBG_REGD,
893 "There is a country domain programmed in chip, ignore notifications\n");
894 goto exit;
895 }
896 rtw89_regd_notifier_apply(rtwdev, wiphy, request);
897 rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
898 "get from initiator %d, alpha2",
899 request->initiator);
900
901 rtw89_core_set_chip_txpwr(rtwdev);
902
903 exit:
904 wiphy_unlock(wiphy);
905 }
906
907 /* Maximum Transmit Power field (@raw) can be EIRP or PSD.
908 * Both units are 0.5 dB-based. Return a constraint in dB.
909 */
tpe_get_constraint(s8 raw)910 static s8 tpe_get_constraint(s8 raw)
911 {
912 const u8 hw_deviation = 3; /* unit: 0.5 dB */
913 const u8 antenna_gain = 10; /* unit: 0.5 dB */
914 const u8 array_gain = 6; /* unit: 0.5 dB */
915 const u8 offset = hw_deviation + antenna_gain + array_gain;
916
917 return (raw - offset) / 2;
918 }
919
tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe * tpe,s8 cstr)920 static void tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe *tpe, s8 cstr)
921 {
922 if (tpe->valid) {
923 tpe->constraint = min(tpe->constraint, cstr);
924 return;
925 }
926
927 tpe->constraint = cstr;
928 tpe->valid = true;
929 }
930
tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe * tpe,const struct ieee80211_parsed_tpe_eirp * eirp)931 static void tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe *tpe,
932 const struct ieee80211_parsed_tpe_eirp *eirp)
933 {
934 unsigned int i;
935 s8 cstr;
936
937 if (!eirp->valid)
938 return;
939
940 for (i = 0; i < eirp->count; i++) {
941 cstr = tpe_get_constraint(eirp->power[i]);
942 tpe_intersect_constraint(tpe, cstr);
943 }
944 }
945
tpe_convert_psd_to_eirp(s8 psd)946 static s8 tpe_convert_psd_to_eirp(s8 psd)
947 {
948 static const unsigned int mlog20 = 1301;
949
950 return psd + 10 * mlog20 / 1000;
951 }
952
tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe * tpe,const struct ieee80211_parsed_tpe_psd * psd)953 static void tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe *tpe,
954 const struct ieee80211_parsed_tpe_psd *psd)
955 {
956 unsigned int i;
957 s8 cstr_psd;
958 s8 cstr;
959
960 if (!psd->valid)
961 return;
962
963 for (i = 0; i < psd->count; i++) {
964 cstr_psd = tpe_get_constraint(psd->power[i]);
965 cstr = tpe_convert_psd_to_eirp(cstr_psd);
966 tpe_intersect_constraint(tpe, cstr);
967 }
968 }
969
rtw89_calculate_tpe(struct rtw89_dev * rtwdev,struct rtw89_reg_6ghz_tpe * result_tpe,const struct ieee80211_parsed_tpe * parsed_tpe)970 static void rtw89_calculate_tpe(struct rtw89_dev *rtwdev,
971 struct rtw89_reg_6ghz_tpe *result_tpe,
972 const struct ieee80211_parsed_tpe *parsed_tpe)
973 {
974 static const u8 category = IEEE80211_TPE_CAT_6GHZ_DEFAULT;
975
976 tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_local[category]);
977 tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_reg_client[category]);
978 tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_local[category]);
979 tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_reg_client[category]);
980 }
981
__rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev * rtwdev)982 static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
983 {
984 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
985 struct rtw89_reg_6ghz_tpe new = {};
986 struct rtw89_vif_link *rtwvif_link;
987 struct rtw89_vif *rtwvif;
988 unsigned int link_id;
989 bool changed = false;
990
991 rtw89_for_each_rtwvif(rtwdev, rtwvif) {
992 const struct rtw89_reg_6ghz_tpe *tmp;
993 const struct rtw89_chan *chan;
994
995 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
996 chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
997 if (chan->band_type != RTW89_BAND_6G)
998 continue;
999
1000 tmp = &rtwvif_link->reg_6ghz_tpe;
1001 if (!tmp->valid)
1002 continue;
1003
1004 tpe_intersect_constraint(&new, tmp->constraint);
1005 }
1006 }
1007
1008 if (memcmp(®ulatory->reg_6ghz_tpe, &new,
1009 sizeof(regulatory->reg_6ghz_tpe)) != 0)
1010 changed = true;
1011
1012 if (changed) {
1013 if (new.valid)
1014 rtw89_debug(rtwdev, RTW89_DBG_REGD,
1015 "recalc 6 GHz reg TPE to %d dBm\n",
1016 new.constraint);
1017 else
1018 rtw89_debug(rtwdev, RTW89_DBG_REGD,
1019 "recalc 6 GHz reg TPE to none\n");
1020
1021 regulatory->reg_6ghz_tpe = new;
1022 }
1023
1024 return changed;
1025 }
1026
rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active,unsigned int * changed)1027 static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev,
1028 struct rtw89_vif_link *rtwvif_link, bool active,
1029 unsigned int *changed)
1030 {
1031 struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe;
1032 struct ieee80211_bss_conf *bss_conf;
1033
1034 memset(tpe, 0, sizeof(*tpe));
1035
1036 if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD)
1037 goto bottom;
1038
1039 rcu_read_lock();
1040
1041 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
1042 rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe);
1043
1044 rcu_read_unlock();
1045
1046 if (!tpe->valid)
1047 goto bottom;
1048
1049 if (tpe->constraint < RTW89_MIN_VALID_POWER_CONSTRAINT) {
1050 rtw89_err(rtwdev,
1051 "%s: constraint %d dBm is less than min valid val\n",
1052 __func__, tpe->constraint);
1053
1054 tpe->valid = false;
1055 return -EINVAL;
1056 }
1057
1058 bottom:
1059 *changed += __rtw89_reg_6ghz_tpe_recalc(rtwdev);
1060 return 0;
1061 }
1062
__rtw89_reg_6ghz_power_recalc(struct rtw89_dev * rtwdev)1063 static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
1064 {
1065 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
1066 const struct rtw89_regd *regd = regulatory->regd;
1067 enum rtw89_reg_6ghz_power sel;
1068 const struct rtw89_chan *chan;
1069 struct rtw89_vif_link *rtwvif_link;
1070 struct rtw89_vif *rtwvif;
1071 unsigned int link_id;
1072 int count = 0;
1073 u8 index;
1074
1075 rtw89_for_each_rtwvif(rtwdev, rtwvif) {
1076 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
1077 chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
1078 if (chan->band_type != RTW89_BAND_6G)
1079 continue;
1080
1081 if (count != 0 && rtwvif_link->reg_6ghz_power == sel)
1082 continue;
1083
1084 sel = rtwvif_link->reg_6ghz_power;
1085 count++;
1086 }
1087 }
1088
1089 if (count != 1)
1090 sel = RTW89_REG_6GHZ_POWER_DFLT;
1091
1092 if (sel == RTW89_REG_6GHZ_POWER_STD) {
1093 index = rtw89_regd_get_index(rtwdev, regd);
1094 if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
1095 test_bit(index, regulatory->block_6ghz_sp)) {
1096 rtw89_debug(rtwdev, RTW89_DBG_REGD,
1097 "%c%c 6 GHz SP is blocked by policy\n",
1098 regd->alpha2[0], regd->alpha2[1]);
1099 sel = RTW89_REG_6GHZ_POWER_DFLT;
1100 }
1101 }
1102
1103 if (regulatory->reg_6ghz_power == sel)
1104 return false;
1105
1106 rtw89_debug(rtwdev, RTW89_DBG_REGD,
1107 "recalc 6 GHz reg power type to %d\n", sel);
1108
1109 regulatory->reg_6ghz_power = sel;
1110 return true;
1111 }
1112
rtw89_reg_6ghz_power_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active,unsigned int * changed)1113 static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
1114 struct rtw89_vif_link *rtwvif_link, bool active,
1115 unsigned int *changed)
1116 {
1117 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
1118 const struct rtw89_regd *regd = regulatory->regd;
1119 bool blocked[NUM_OF_RTW89_REG_6GHZ_POWER] = {};
1120 u8 index = rtw89_regd_get_index(rtwdev, regd);
1121 struct ieee80211_bss_conf *bss_conf;
1122 bool dflt = false;
1123
1124 if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
1125 test_bit(index, regulatory->block_6ghz_vlp))
1126 blocked[RTW89_REG_6GHZ_POWER_VLP] = true;
1127
1128 rcu_read_lock();
1129
1130 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
1131
1132 if (active) {
1133 switch (bss_conf->power_type) {
1134 case IEEE80211_REG_VLP_AP:
1135 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
1136 break;
1137 case IEEE80211_REG_LPI_AP:
1138 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
1139 break;
1140 case IEEE80211_REG_SP_AP:
1141 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
1142 break;
1143 default:
1144 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
1145 dflt = true;
1146 break;
1147 }
1148 } else {
1149 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
1150 }
1151
1152 rcu_read_unlock();
1153
1154 if (!dflt && blocked[rtwvif_link->reg_6ghz_power]) {
1155 rtw89_debug(rtwdev, RTW89_DBG_REGD,
1156 "%c%c 6 GHz power type-%u is blocked by policy\n",
1157 regd->alpha2[0], regd->alpha2[1],
1158 rtwvif_link->reg_6ghz_power);
1159 return -EINVAL;
1160 }
1161
1162 *changed += __rtw89_reg_6ghz_power_recalc(rtwdev);
1163 return 0;
1164 }
1165
rtw89_reg_6ghz_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active)1166 int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
1167 bool active)
1168 {
1169 unsigned int changed = 0;
1170 int ret;
1171
1172 lockdep_assert_wiphy(rtwdev->hw->wiphy);
1173
1174 /* The result of reg_6ghz_tpe may depend on reg_6ghz_power type,
1175 * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc().
1176 */
1177
1178 ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed);
1179 if (ret)
1180 return ret;
1181
1182 ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed);
1183 if (ret)
1184 return ret;
1185
1186 if (changed)
1187 rtw89_core_set_chip_txpwr(rtwdev);
1188
1189 return 0;
1190 }
1191