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_regd_ctrl *regd_ctrl = ®ulatory->ctrl;
364 const struct rtw89_chip_info *chip = rtwdev->chip;
365 struct ieee80211_supported_band *sband;
366 struct rtw89_acpi_dsm_result res = {};
367 bool enable_by_fcc;
368 bool enable_by_ic;
369 int ret;
370 u8 val;
371 int i;
372
373 sband = wiphy->bands[NL80211_BAND_5GHZ];
374 if (!sband)
375 return;
376
377 if (!chip->support_unii4) {
378 sband->n_channels -= RTW89_5GHZ_UNII4_CHANNEL_NUM;
379 return;
380 }
381
382 bitmap_fill(regulatory->block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
383
384 ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_UNII4_SUP, &res);
385 if (ret) {
386 rtw89_debug(rtwdev, RTW89_DBG_REGD,
387 "acpi: cannot eval unii 4: %d\n", ret);
388 enable_by_fcc = true;
389 enable_by_ic = false;
390 goto bottom;
391 }
392
393 val = res.u.value;
394 enable_by_fcc = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_FCC);
395 enable_by_ic = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_IC);
396
397 rtw89_debug(rtwdev, RTW89_DBG_REGD,
398 "acpi: eval if allow unii-4: 0x%x\n", val);
399
400 bottom:
401 for (i = 0; i < regd_ctrl->nr; i++) {
402 const struct rtw89_regd *regd = ®d_ctrl->map[i];
403
404 switch (regd->txpwr_regd[RTW89_BAND_5G]) {
405 case RTW89_FCC:
406 if (enable_by_fcc)
407 clear_bit(i, regulatory->block_unii4);
408 break;
409 case RTW89_IC:
410 if (enable_by_ic)
411 clear_bit(i, regulatory->block_unii4);
412 break;
413 default:
414 break;
415 }
416 }
417 }
418
__rtw89_regd_setup_policy_6ghz(struct rtw89_dev * rtwdev,bool block,const char * alpha2)419 static void __rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev, bool block,
420 const char *alpha2)
421 {
422 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
423 u8 index;
424
425 index = rtw89_regd_get_index_by_name(rtwdev, alpha2);
426 if (index == RTW89_REGD_MAX_COUNTRY_NUM) {
427 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%s: unknown alpha2 %c%c\n",
428 __func__, alpha2[0], alpha2[1]);
429 return;
430 }
431
432 if (block)
433 set_bit(index, regulatory->block_6ghz);
434 else
435 clear_bit(index, regulatory->block_6ghz);
436 }
437
rtw89_regd_setup_policy_6ghz(struct rtw89_dev * rtwdev)438 static void rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev)
439 {
440 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
441 const struct rtw89_acpi_country_code *country;
442 const struct rtw89_acpi_policy_6ghz *ptr;
443 struct rtw89_acpi_dsm_result res = {};
444 bool to_block;
445 int i, j;
446 int ret;
447
448 ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_BP, &res);
449 if (ret) {
450 rtw89_debug(rtwdev, RTW89_DBG_REGD,
451 "acpi: cannot eval policy 6ghz: %d\n", ret);
452 return;
453 }
454
455 ptr = res.u.policy_6ghz;
456
457 switch (ptr->policy_mode) {
458 case RTW89_ACPI_POLICY_BLOCK:
459 to_block = true;
460 break;
461 case RTW89_ACPI_POLICY_ALLOW:
462 to_block = false;
463 /* only below list is allowed; block all first */
464 bitmap_fill(regulatory->block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM);
465 break;
466 default:
467 rtw89_debug(rtwdev, RTW89_DBG_REGD,
468 "%s: unknown policy mode: %d\n", __func__,
469 ptr->policy_mode);
470 goto out;
471 }
472
473 for (i = 0; i < ptr->country_count; i++) {
474 country = &ptr->country_list[i];
475 if (memcmp("EU", country->alpha2, 2) != 0) {
476 __rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
477 country->alpha2);
478 continue;
479 }
480
481 for (j = 0; j < ARRAY_SIZE(rtw89_alpha2_list_eu); j++)
482 __rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
483 rtw89_alpha2_list_eu[j]);
484 }
485
486 out:
487 kfree(ptr);
488 }
489
rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev * rtwdev)490 static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev)
491 {
492 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
493 const struct rtw89_regd_ctrl *regd_ctrl = ®ulatory->ctrl;
494 const struct rtw89_acpi_policy_6ghz_sp *ptr;
495 struct rtw89_acpi_dsm_result res = {};
496 bool enable_by_us;
497 int ret;
498 int i;
499
500 ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, &res);
501 if (ret) {
502 rtw89_debug(rtwdev, RTW89_DBG_REGD,
503 "acpi: cannot eval policy 6ghz-sp: %d\n", ret);
504 return;
505 }
506
507 ptr = res.u.policy_6ghz_sp;
508
509 switch (ptr->override) {
510 default:
511 rtw89_debug(rtwdev, RTW89_DBG_REGD,
512 "%s: unknown override case: %d\n", __func__,
513 ptr->override);
514 fallthrough;
515 case 0:
516 goto out;
517 case 1:
518 break;
519 }
520
521 bitmap_fill(regulatory->block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM);
522
523 enable_by_us = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US);
524
525 for (i = 0; i < regd_ctrl->nr; i++) {
526 const struct rtw89_regd *tmp = ®d_ctrl->map[i];
527
528 if (enable_by_us && memcmp(tmp->alpha2, "US", 2) == 0)
529 clear_bit(i, regulatory->block_6ghz_sp);
530 }
531
532 out:
533 kfree(ptr);
534 }
535
rtw89_regd_setup_6ghz(struct rtw89_dev * rtwdev,struct wiphy * wiphy)536 static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
537 {
538 const struct rtw89_chip_info *chip = rtwdev->chip;
539 bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ);
540 bool regd_allow_6ghz = chip_support_6ghz;
541 struct ieee80211_supported_band *sband;
542 struct rtw89_acpi_dsm_result res = {};
543 int ret;
544 u8 val;
545
546 if (!chip_support_6ghz)
547 goto bottom;
548
549 ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &res);
550 if (ret) {
551 rtw89_debug(rtwdev, RTW89_DBG_REGD,
552 "acpi: cannot eval 6ghz: %d\n", ret);
553 goto bottom;
554 }
555
556 val = res.u.value;
557
558 rtw89_debug(rtwdev, RTW89_DBG_REGD,
559 "acpi: eval if disallow 6ghz: %d\n", val);
560
561 switch (val) {
562 case 0:
563 regd_allow_6ghz = true;
564 break;
565 case 1:
566 regd_allow_6ghz = false;
567 break;
568 default:
569 break;
570 }
571
572 bottom:
573 rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n",
574 regd_allow_6ghz);
575
576 if (regd_allow_6ghz) {
577 rtw89_regd_setup_policy_6ghz(rtwdev);
578 rtw89_regd_setup_policy_6ghz_sp(rtwdev);
579 return;
580 }
581
582 sband = wiphy->bands[NL80211_BAND_6GHZ];
583 if (!sband)
584 return;
585
586 wiphy->bands[NL80211_BAND_6GHZ] = NULL;
587 kfree((__force void *)sband->iftype_data);
588 kfree(sband);
589 }
590
rtw89_regd_setup(struct rtw89_dev * rtwdev)591 int rtw89_regd_setup(struct rtw89_dev *rtwdev)
592 {
593 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
594 struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
595 const struct rtw89_regd_data *regd_data = elm_info->regd;
596 struct wiphy *wiphy = rtwdev->hw->wiphy;
597
598 if (regd_data) {
599 regulatory->ctrl.nr = regd_data->nr;
600 regulatory->ctrl.map = regd_data->map;
601 } else {
602 regulatory->ctrl.nr = ARRAY_SIZE(rtw89_regd_map);
603 regulatory->ctrl.map = rtw89_regd_map;
604 }
605
606 regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
607
608 if (!wiphy)
609 return -EINVAL;
610
611 rtw89_regd_setup_unii4(rtwdev, wiphy);
612 rtw89_regd_setup_6ghz(rtwdev, wiphy);
613
614 wiphy->reg_notifier = rtw89_regd_notifier;
615 return 0;
616 }
617
rtw89_regd_init_hint(struct rtw89_dev * rtwdev)618 int rtw89_regd_init_hint(struct rtw89_dev *rtwdev)
619 {
620 const struct rtw89_regd *chip_regd;
621 struct wiphy *wiphy = rtwdev->hw->wiphy;
622 int ret;
623
624 if (!wiphy)
625 return -EINVAL;
626
627 chip_regd = rtw89_regd_find_reg_by_name(rtwdev, rtwdev->efuse.country_code);
628 if (!rtw89_regd_is_ww(chip_regd)) {
629 rtwdev->regulatory.regd = chip_regd;
630 /* Ignore country ie if there is a country domain programmed in chip */
631 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
632 wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
633
634 ret = regulatory_hint(rtwdev->hw->wiphy,
635 rtwdev->regulatory.regd->alpha2);
636 if (ret)
637 rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret);
638
639 rtw89_debug_regd(rtwdev, chip_regd, "efuse country code");
640 return 0;
641 }
642
643 rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
644 "worldwide roaming chip, follow the setting of stack");
645 return 0;
646 }
647
rtw89_regd_apply_policy_unii4(struct rtw89_dev * rtwdev,struct wiphy * wiphy)648 static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
649 struct wiphy *wiphy)
650 {
651 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
652 const struct rtw89_chip_info *chip = rtwdev->chip;
653 const struct rtw89_regd *regd = regulatory->regd;
654 struct ieee80211_supported_band *sband;
655 u8 index;
656 int i;
657
658 sband = wiphy->bands[NL80211_BAND_5GHZ];
659 if (!sband)
660 return;
661
662 if (!chip->support_unii4)
663 return;
664
665 index = rtw89_regd_get_index(rtwdev, regd);
666 if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
667 !test_bit(index, regulatory->block_unii4))
668 return;
669
670 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n",
671 regd->alpha2[0], regd->alpha2[1]);
672
673 for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++)
674 sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
675 }
676
regd_is_6ghz_blocked(struct rtw89_dev * rtwdev)677 static bool regd_is_6ghz_blocked(struct rtw89_dev *rtwdev)
678 {
679 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
680 const struct rtw89_regd *regd = regulatory->regd;
681 u8 index;
682
683 index = rtw89_regd_get_index(rtwdev, regd);
684 if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
685 !test_bit(index, regulatory->block_6ghz))
686 return false;
687
688 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n",
689 regd->alpha2[0], regd->alpha2[1]);
690 return true;
691 }
692
regd_is_6ghz_not_applicable(struct rtw89_dev * rtwdev)693 static bool regd_is_6ghz_not_applicable(struct rtw89_dev *rtwdev)
694 {
695 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
696 const struct rtw89_regd *regd = regulatory->regd;
697
698 if (regd->txpwr_regd[RTW89_BAND_6G] != RTW89_NA)
699 return false;
700
701 rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is N/A in regd map\n",
702 regd->alpha2[0], regd->alpha2[1]);
703 return true;
704 }
705
rtw89_regd_apply_policy_6ghz(struct rtw89_dev * rtwdev,struct wiphy * wiphy)706 static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
707 struct wiphy *wiphy)
708 {
709 struct ieee80211_supported_band *sband;
710 int i;
711
712 if (!regd_is_6ghz_blocked(rtwdev) &&
713 !regd_is_6ghz_not_applicable(rtwdev))
714 return;
715
716 sband = wiphy->bands[NL80211_BAND_6GHZ];
717 if (!sband)
718 return;
719
720 for (i = 0; i < sband->n_channels; i++)
721 sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
722 }
723
rtw89_regd_apply_policy_tas(struct rtw89_dev * rtwdev)724 static void rtw89_regd_apply_policy_tas(struct rtw89_dev *rtwdev)
725 {
726 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
727 const struct rtw89_regd *regd = regulatory->regd;
728 struct rtw89_tas_info *tas = &rtwdev->tas;
729
730 if (!tas->enable)
731 return;
732
733 tas->block_regd = !test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap);
734 }
735
rtw89_regd_apply_policy_ant_gain(struct rtw89_dev * rtwdev)736 static void rtw89_regd_apply_policy_ant_gain(struct rtw89_dev *rtwdev)
737 {
738 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
739 struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
740 const struct rtw89_chip_info *chip = rtwdev->chip;
741 const struct rtw89_regd *regd = regulatory->regd;
742
743 if (!chip->support_ant_gain)
744 return;
745
746 ant_gain->block_country = !test_bit(RTW89_REGD_FUNC_DAG, regd->func_bitmap);
747 }
748
rtw89_regd_notifier_apply(struct rtw89_dev * rtwdev,struct wiphy * wiphy,struct regulatory_request * request)749 static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
750 struct wiphy *wiphy,
751 struct regulatory_request *request)
752 {
753 rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(rtwdev, request->alpha2);
754 /* This notification might be set from the system of distros,
755 * and it does not expect the regulatory will be modified by
756 * connecting to an AP (i.e. country ie).
757 */
758 if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
759 !rtw89_regd_is_ww(rtwdev->regulatory.regd))
760 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
761 else
762 wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
763
764 rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
765 rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
766 rtw89_regd_apply_policy_tas(rtwdev);
767 rtw89_regd_apply_policy_ant_gain(rtwdev);
768 }
769
770 static
rtw89_regd_notifier(struct wiphy * wiphy,struct regulatory_request * request)771 void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
772 {
773 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
774 struct rtw89_dev *rtwdev = hw->priv;
775
776 wiphy_lock(wiphy);
777 rtw89_leave_ps_mode(rtwdev);
778
779 if (wiphy->regd) {
780 rtw89_debug(rtwdev, RTW89_DBG_REGD,
781 "There is a country domain programmed in chip, ignore notifications\n");
782 goto exit;
783 }
784 rtw89_regd_notifier_apply(rtwdev, wiphy, request);
785 rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
786 "get from initiator %d, alpha2",
787 request->initiator);
788
789 rtw89_core_set_chip_txpwr(rtwdev);
790
791 exit:
792 wiphy_unlock(wiphy);
793 }
794
795 /* Maximum Transmit Power field (@raw) can be EIRP or PSD.
796 * Both units are 0.5 dB-based. Return a constraint in dB.
797 */
tpe_get_constraint(s8 raw)798 static s8 tpe_get_constraint(s8 raw)
799 {
800 const u8 hw_deviation = 3; /* unit: 0.5 dB */
801 const u8 antenna_gain = 10; /* unit: 0.5 dB */
802 const u8 array_gain = 6; /* unit: 0.5 dB */
803 const u8 offset = hw_deviation + antenna_gain + array_gain;
804
805 return (raw - offset) / 2;
806 }
807
tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe * tpe,s8 cstr)808 static void tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe *tpe, s8 cstr)
809 {
810 if (tpe->valid) {
811 tpe->constraint = min(tpe->constraint, cstr);
812 return;
813 }
814
815 tpe->constraint = cstr;
816 tpe->valid = true;
817 }
818
tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe * tpe,const struct ieee80211_parsed_tpe_eirp * eirp)819 static void tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe *tpe,
820 const struct ieee80211_parsed_tpe_eirp *eirp)
821 {
822 unsigned int i;
823 s8 cstr;
824
825 if (!eirp->valid)
826 return;
827
828 for (i = 0; i < eirp->count; i++) {
829 cstr = tpe_get_constraint(eirp->power[i]);
830 tpe_intersect_constraint(tpe, cstr);
831 }
832 }
833
tpe_convert_psd_to_eirp(s8 psd)834 static s8 tpe_convert_psd_to_eirp(s8 psd)
835 {
836 static const unsigned int mlog20 = 1301;
837
838 return psd + 10 * mlog20 / 1000;
839 }
840
tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe * tpe,const struct ieee80211_parsed_tpe_psd * psd)841 static void tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe *tpe,
842 const struct ieee80211_parsed_tpe_psd *psd)
843 {
844 unsigned int i;
845 s8 cstr_psd;
846 s8 cstr;
847
848 if (!psd->valid)
849 return;
850
851 for (i = 0; i < psd->count; i++) {
852 cstr_psd = tpe_get_constraint(psd->power[i]);
853 cstr = tpe_convert_psd_to_eirp(cstr_psd);
854 tpe_intersect_constraint(tpe, cstr);
855 }
856 }
857
rtw89_calculate_tpe(struct rtw89_dev * rtwdev,struct rtw89_reg_6ghz_tpe * result_tpe,const struct ieee80211_parsed_tpe * parsed_tpe)858 static void rtw89_calculate_tpe(struct rtw89_dev *rtwdev,
859 struct rtw89_reg_6ghz_tpe *result_tpe,
860 const struct ieee80211_parsed_tpe *parsed_tpe)
861 {
862 static const u8 category = IEEE80211_TPE_CAT_6GHZ_DEFAULT;
863
864 tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_local[category]);
865 tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_reg_client[category]);
866 tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_local[category]);
867 tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_reg_client[category]);
868 }
869
__rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev * rtwdev)870 static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
871 {
872 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
873 struct rtw89_reg_6ghz_tpe new = {};
874 struct rtw89_vif_link *rtwvif_link;
875 struct rtw89_vif *rtwvif;
876 unsigned int link_id;
877 bool changed = false;
878
879 rtw89_for_each_rtwvif(rtwdev, rtwvif) {
880 const struct rtw89_reg_6ghz_tpe *tmp;
881 const struct rtw89_chan *chan;
882
883 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
884 chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
885 if (chan->band_type != RTW89_BAND_6G)
886 continue;
887
888 tmp = &rtwvif_link->reg_6ghz_tpe;
889 if (!tmp->valid)
890 continue;
891
892 tpe_intersect_constraint(&new, tmp->constraint);
893 }
894 }
895
896 if (memcmp(®ulatory->reg_6ghz_tpe, &new,
897 sizeof(regulatory->reg_6ghz_tpe)) != 0)
898 changed = true;
899
900 if (changed) {
901 if (new.valid)
902 rtw89_debug(rtwdev, RTW89_DBG_REGD,
903 "recalc 6 GHz reg TPE to %d dBm\n",
904 new.constraint);
905 else
906 rtw89_debug(rtwdev, RTW89_DBG_REGD,
907 "recalc 6 GHz reg TPE to none\n");
908
909 regulatory->reg_6ghz_tpe = new;
910 }
911
912 return changed;
913 }
914
rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active,unsigned int * changed)915 static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev,
916 struct rtw89_vif_link *rtwvif_link, bool active,
917 unsigned int *changed)
918 {
919 struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe;
920 struct ieee80211_bss_conf *bss_conf;
921
922 memset(tpe, 0, sizeof(*tpe));
923
924 if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD)
925 goto bottom;
926
927 rcu_read_lock();
928
929 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
930 rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe);
931
932 rcu_read_unlock();
933
934 if (!tpe->valid)
935 goto bottom;
936
937 if (tpe->constraint < RTW89_MIN_VALID_POWER_CONSTRAINT) {
938 rtw89_err(rtwdev,
939 "%s: constraint %d dBm is less than min valid val\n",
940 __func__, tpe->constraint);
941
942 tpe->valid = false;
943 return -EINVAL;
944 }
945
946 bottom:
947 *changed += __rtw89_reg_6ghz_tpe_recalc(rtwdev);
948 return 0;
949 }
950
__rtw89_reg_6ghz_power_recalc(struct rtw89_dev * rtwdev)951 static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
952 {
953 struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
954 const struct rtw89_regd *regd = regulatory->regd;
955 enum rtw89_reg_6ghz_power sel;
956 const struct rtw89_chan *chan;
957 struct rtw89_vif_link *rtwvif_link;
958 struct rtw89_vif *rtwvif;
959 unsigned int link_id;
960 int count = 0;
961 u8 index;
962
963 rtw89_for_each_rtwvif(rtwdev, rtwvif) {
964 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
965 chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
966 if (chan->band_type != RTW89_BAND_6G)
967 continue;
968
969 if (count != 0 && rtwvif_link->reg_6ghz_power == sel)
970 continue;
971
972 sel = rtwvif_link->reg_6ghz_power;
973 count++;
974 }
975 }
976
977 if (count != 1)
978 sel = RTW89_REG_6GHZ_POWER_DFLT;
979
980 if (sel == RTW89_REG_6GHZ_POWER_STD) {
981 index = rtw89_regd_get_index(rtwdev, regd);
982 if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
983 test_bit(index, regulatory->block_6ghz_sp)) {
984 rtw89_debug(rtwdev, RTW89_DBG_REGD,
985 "%c%c 6 GHz SP is blocked by policy\n",
986 regd->alpha2[0], regd->alpha2[1]);
987 sel = RTW89_REG_6GHZ_POWER_DFLT;
988 }
989 }
990
991 if (regulatory->reg_6ghz_power == sel)
992 return false;
993
994 rtw89_debug(rtwdev, RTW89_DBG_REGD,
995 "recalc 6 GHz reg power type to %d\n", sel);
996
997 regulatory->reg_6ghz_power = sel;
998 return true;
999 }
1000
rtw89_reg_6ghz_power_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active,unsigned int * changed)1001 static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
1002 struct rtw89_vif_link *rtwvif_link, bool active,
1003 unsigned int *changed)
1004 {
1005 struct ieee80211_bss_conf *bss_conf;
1006
1007 rcu_read_lock();
1008
1009 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
1010
1011 if (active) {
1012 switch (bss_conf->power_type) {
1013 case IEEE80211_REG_VLP_AP:
1014 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
1015 break;
1016 case IEEE80211_REG_LPI_AP:
1017 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
1018 break;
1019 case IEEE80211_REG_SP_AP:
1020 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
1021 break;
1022 default:
1023 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
1024 break;
1025 }
1026 } else {
1027 rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
1028 }
1029
1030 rcu_read_unlock();
1031
1032 *changed += __rtw89_reg_6ghz_power_recalc(rtwdev);
1033 return 0;
1034 }
1035
rtw89_reg_6ghz_recalc(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,bool active)1036 int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
1037 bool active)
1038 {
1039 unsigned int changed = 0;
1040 int ret;
1041
1042 lockdep_assert_wiphy(rtwdev->hw->wiphy);
1043
1044 /* The result of reg_6ghz_tpe may depend on reg_6ghz_power type,
1045 * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc().
1046 */
1047
1048 ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed);
1049 if (ret)
1050 return ret;
1051
1052 ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed);
1053 if (ret)
1054 return ret;
1055
1056 if (changed)
1057 rtw89_core_set_chip_txpwr(rtwdev);
1058
1059 return 0;
1060 }
1061