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 (!rtw89_regd_is_ww(chip_regd)) {
725 rtwdev->regulatory.regd = chip_regd;
726 /* Ignore country ie if there is a country domain programmed in chip */
727 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
728 wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
729
730 ret = regulatory_hint(rtwdev->hw->wiphy,
731 rtwdev->regulatory.regd->alpha2);
732 if (ret)
733 rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret);
734
735 rtw89_debug_regd(rtwdev, chip_regd, "efuse country code");
736 return 0;
737 }
738
739 rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
740 "worldwide roaming chip, follow the setting of stack");
741 return 0;
742 }
743
rtw89_regd_apply_policy_unii4(struct rtw89_dev * rtwdev,struct wiphy * wiphy)744 static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
745 struct wiphy *wiphy)
746 {
747 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
748 const struct rtw89_chip_info *chip = rtwdev->chip;
749 const struct rtw89_regd *regd = regulatory->regd;
750 struct ieee80211_supported_band *sband;
751 u8 index;
752 int i;
753
754 sband = wiphy->bands[NL80211_BAND_5GHZ];
755 if (!sband)
756 return;
757
758 if (!chip->support_unii4)
759 return;
760
761 index = rtw89_regd_get_index(rtwdev, regd);
762 if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
763 !test_bit(index, regulatory->block_unii4))
764 return;
765
766 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n",
767 regd->alpha2[0], regd->alpha2[1]);
768
769 for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++)
770 sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
771 }
772
regd_is_6ghz_blocked(struct rtw89_dev * rtwdev)773 static bool regd_is_6ghz_blocked(struct rtw89_dev *rtwdev)
774 {
775 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
776 const struct rtw89_regd *regd = regulatory->regd;
777 u8 index;
778
779 index = rtw89_regd_get_index(rtwdev, regd);
780 if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
781 !test_bit(index, regulatory->block_6ghz))
782 return false;
783
784 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n",
785 regd->alpha2[0], regd->alpha2[1]);
786 return true;
787 }
788
regd_is_6ghz_not_applicable(struct rtw89_dev * rtwdev)789 static bool regd_is_6ghz_not_applicable(struct rtw89_dev *rtwdev)
790 {
791 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
792 const struct rtw89_regd *regd = regulatory->regd;
793
794 if (regd->txpwr_regd[RTW89_BAND_6G] != RTW89_NA)
795 return false;
796
797 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is N/A in regd map\n",
798 regd->alpha2[0], regd->alpha2[1]);
799 return true;
800 }
801
rtw89_regd_apply_policy_6ghz(struct rtw89_dev * rtwdev,struct wiphy * wiphy)802 static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
803 struct wiphy *wiphy)
804 {
805 struct ieee80211_supported_band *sband;
806 int i;
807
808 if (!regd_is_6ghz_blocked(rtwdev) &&
809 !regd_is_6ghz_not_applicable(rtwdev))
810 return;
811
812 sband = wiphy->bands[NL80211_BAND_6GHZ];
813 if (!sband)
814 return;
815
816 for (i = 0; i < sband->n_channels; i++)
817 sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
818 }
819
rtw89_regd_apply_policy_tas(struct rtw89_dev * rtwdev)820 static void rtw89_regd_apply_policy_tas(struct rtw89_dev *rtwdev)
821 {
822 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
823 const struct rtw89_regd *regd = regulatory->regd;
824 struct rtw89_tas_info *tas = &rtwdev->tas;
825 u8 tas_country;
826
827 if (!tas->enable)
828 return;
829
830 if (memcmp("US", regd->alpha2, 2) == 0)
831 tas_country = RTW89_ACPI_CONF_TAS_US;
832 else if (memcmp("CA", regd->alpha2, 2) == 0)
833 tas_country = RTW89_ACPI_CONF_TAS_CA;
834 else if (memcmp("KR", regd->alpha2, 2) == 0)
835 tas_country = RTW89_ACPI_CONF_TAS_KR;
836 else
837 tas_country = RTW89_ACPI_CONF_TAS_OTHERS;
838
839 tas->block_regd = !(tas->enabled_countries & tas_country &&
840 test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap));
841 }
842
rtw89_regd_apply_policy_ant_gain(struct rtw89_dev * rtwdev)843 static void rtw89_regd_apply_policy_ant_gain(struct rtw89_dev *rtwdev)
844 {
845 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
846 struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
847 const struct rtw89_chip_info *chip = rtwdev->chip;
848 const struct rtw89_regd *regd = regulatory->regd;
849
850 if (!chip->support_ant_gain)
851 return;
852
853 ant_gain->block_country = !test_bit(RTW89_REGD_FUNC_DAG, regd->func_bitmap);
854 }
855
rtw89_regd_notifier_apply(struct rtw89_dev * rtwdev,struct wiphy * wiphy,struct regulatory_request * request)856 static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
857 struct wiphy *wiphy,
858 struct regulatory_request *request)
859 {
860 rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(rtwdev, request->alpha2);
861 /* This notification might be set from the system of distros,
862 * and it does not expect the regulatory will be modified by
863 * connecting to an AP (i.e. country ie).
864 */
865 if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
866 !rtw89_regd_is_ww(rtwdev->regulatory.regd))
867 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
868 else
869 wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
870
871 rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
872 rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
873 rtw89_regd_apply_policy_tas(rtwdev);
874 rtw89_regd_apply_policy_ant_gain(rtwdev);
875 }
876
877 static
rtw89_regd_notifier(struct wiphy * wiphy,struct regulatory_request * request)878 void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
879 {
880 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
881 struct rtw89_dev *rtwdev = hw->priv;
882
883 wiphy_lock(wiphy);
884 rtw89_leave_ps_mode(rtwdev);
885
886 if (wiphy->regd) {
887 rtw89_debug(rtwdev, RTW89_DBG_REGD,
888 "There is a country domain programmed in chip, ignore notifications\n");
889 goto exit;
890 }
891 rtw89_regd_notifier_apply(rtwdev, wiphy, request);
892 rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
893 "get from initiator %d, alpha2",
894 request->initiator);
895
896 rtw89_core_set_chip_txpwr(rtwdev);
897
898 exit:
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 */
tpe_get_constraint(s8 raw)905 static 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
tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe * tpe,s8 cstr)915 static 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
tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe * tpe,const struct ieee80211_parsed_tpe_eirp * eirp)926 static 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
tpe_convert_psd_to_eirp(s8 psd)941 static 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
tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe * tpe,const struct ieee80211_parsed_tpe_psd * psd)948 static 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
rtw89_calculate_tpe(struct rtw89_dev * rtwdev,struct rtw89_reg_6ghz_tpe * result_tpe,const struct ieee80211_parsed_tpe * parsed_tpe)965 static 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
__rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev * rtwdev)977 static 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(®ulatory->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
rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active,unsigned int * changed)1022 static 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
1053 bottom:
1054 *changed += __rtw89_reg_6ghz_tpe_recalc(rtwdev);
1055 return 0;
1056 }
1057
__rtw89_reg_6ghz_power_recalc(struct rtw89_dev * rtwdev)1058 static 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
rtw89_reg_6ghz_power_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active,unsigned int * changed)1108 static 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 }
1146
1147 rcu_read_unlock();
1148
1149 if (!dflt && blocked[rtwvif_link->reg_6ghz_power]) {
1150 rtw89_debug(rtwdev, RTW89_DBG_REGD,
1151 "%c%c 6 GHz power type-%u is blocked by policy\n",
1152 regd->alpha2[0], regd->alpha2[1],
1153 rtwvif_link->reg_6ghz_power);
1154 return -EINVAL;
1155 }
1156
1157 *changed += __rtw89_reg_6ghz_power_recalc(rtwdev);
1158 return 0;
1159 }
1160
rtw89_reg_6ghz_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active)1161 int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
1162 bool active)
1163 {
1164 unsigned int changed = 0;
1165 int ret;
1166
1167 lockdep_assert_wiphy(rtwdev->hw->wiphy);
1168
1169 /* The result of reg_6ghz_tpe may depend on reg_6ghz_power type,
1170 * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc().
1171 */
1172
1173 ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed);
1174 if (ret)
1175 return ret;
1176
1177 ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed);
1178 if (ret)
1179 return ret;
1180
1181 if (changed)
1182 rtw89_core_set_chip_txpwr(rtwdev);
1183
1184 return 0;
1185 }
1186