Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/rtw89/regd.c
48253 views
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
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 = &regulatory->ctrl;
312
u32 i;
313
314
for (i = 0; i < regd_ctrl->nr; i++) {
315
if (!memcmp(regd_ctrl->map[i].alpha2, alpha2, 2))
316
return &regd_ctrl->map[i];
317
}
318
319
return &rtw89_ww_regd;
320
}
321
322
static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
323
{
324
return regd == &rtw89_ww_regd;
325
}
326
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 = &regulatory->ctrl;
331
332
BUILD_BUG_ON(ARRAY_SIZE(rtw89_regd_map) > RTW89_REGD_MAX_COUNTRY_NUM);
333
334
if (rtw89_regd_is_ww(regd))
335
return RTW89_REGD_MAX_COUNTRY_NUM;
336
337
return regd - regd_ctrl->map;
338
}
339
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
*/
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
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
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
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
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
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
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(&regulatory->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
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
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
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
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
1192