1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /* Copyright (C) 2025 MediaTek Inc. */
3
4 #include <linux/of.h>
5 #include "mt7921.h"
6 #include "regd.h"
7 #include "mcu.h"
8
9 static bool mt7921_disable_clc;
10 module_param_named(disable_clc, mt7921_disable_clc, bool, 0644);
11 MODULE_PARM_DESC(disable_clc, "disable CLC support");
12
13 static struct ieee80211_regdomain mt7921_regd_ww = {
14 .n_reg_rules = 1,
15 .alpha2 = "00",
16 .reg_rules = {
17 /* IEEE 802.11b/g, channels 1..11 */
18 REG_RULE(2412 - 10, 2462 + 10, 40, 6, 20, 0),
19 }
20 };
21
mt7921_regd_clc_supported(struct mt792x_dev * dev)22 bool mt7921_regd_clc_supported(struct mt792x_dev *dev)
23 {
24 if (mt7921_disable_clc ||
25 mt76_is_usb(&dev->mt76))
26 return false;
27
28 return true;
29 }
30
31 static void
mt7921_regd_channel_update(struct wiphy * wiphy,struct mt792x_dev * dev)32 mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
33 {
34 #define IS_UNII_INVALID(idx, sfreq, efreq) \
35 (!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq))
36 struct ieee80211_supported_band *sband;
37 struct mt76_dev *mdev = &dev->mt76;
38 struct device_node *np, *band_np;
39 struct ieee80211_channel *ch;
40 int i, cfreq;
41
42 np = mt76_find_power_limits_node(mdev);
43
44 sband = wiphy->bands[NL80211_BAND_5GHZ];
45 if (!sband)
46 return;
47
48 band_np = np ? of_get_child_by_name(np, "txpower-5g") : NULL;
49 for (i = 0; i < sband->n_channels; i++) {
50 ch = &sband->channels[i];
51 cfreq = ch->center_freq;
52
53 if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
54 ch->flags |= IEEE80211_CHAN_DISABLED;
55 continue;
56 }
57
58 /* UNII-4 */
59 if (IS_UNII_INVALID(0, 5845, 5925))
60 ch->flags |= IEEE80211_CHAN_DISABLED;
61 }
62
63 sband = wiphy->bands[NL80211_BAND_6GHZ];
64 if (!sband)
65 return;
66
67 band_np = np ? of_get_child_by_name(np, "txpower-6g") : NULL;
68 for (i = 0; i < sband->n_channels; i++) {
69 ch = &sband->channels[i];
70 cfreq = ch->center_freq;
71
72 if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
73 ch->flags |= IEEE80211_CHAN_DISABLED;
74 continue;
75 }
76
77 /* UNII-5/6/7/8 */
78 if (IS_UNII_INVALID(1, 5925, 6425) ||
79 IS_UNII_INVALID(2, 6425, 6525) ||
80 IS_UNII_INVALID(3, 6525, 6875) ||
81 IS_UNII_INVALID(4, 6875, 7125))
82 ch->flags |= IEEE80211_CHAN_DISABLED;
83 }
84 }
85
__mt7921_mcu_regd_update(struct mt792x_dev * dev,u8 * alpha2,enum environment_cap country_ie_env)86 int __mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
87 enum environment_cap country_ie_env)
88 {
89 struct mt76_dev *mdev = &dev->mt76;
90 struct ieee80211_hw *hw = mdev->hw;
91 struct wiphy *wiphy = hw->wiphy;
92 int ret;
93
94 lockdep_assert_held(&dev->mt76.mutex);
95
96 if (!dev->regd_change)
97 return 0;
98
99 ret = mt7921_mcu_set_clc(dev, alpha2, country_ie_env);
100 if (ret < 0)
101 return ret;
102
103 mt7921_regd_channel_update(wiphy, dev);
104
105 ret = mt76_connac_mcu_set_channel_domain(hw->priv);
106 if (ret < 0)
107 return ret;
108
109 ret = mt7921_set_tx_sar_pwr(hw, NULL);
110
111 return ret;
112 }
113
mt7921_mcu_regd_update(struct mt792x_dev * dev,u8 * alpha2,enum environment_cap country_ie_env)114 int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
115 enum environment_cap country_ie_env)
116 {
117 int ret;
118
119 dev->regd_in_progress = true;
120
121 mt792x_mutex_acquire(dev);
122 ret = __mt7921_mcu_regd_update(dev, alpha2, country_ie_env);
123 mt792x_mutex_release(dev);
124
125 dev->regd_change = false;
126 dev->regd_in_progress = false;
127 wake_up(&dev->wait);
128
129 return ret;
130 }
131 EXPORT_SYMBOL_GPL(mt7921_mcu_regd_update);
132
mt7921_regd_notifier(struct wiphy * wiphy,struct regulatory_request * req)133 void mt7921_regd_notifier(struct wiphy *wiphy,
134 struct regulatory_request *req)
135 {
136 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
137 struct mt792x_dev *dev = mt792x_hw_dev(hw);
138 struct mt76_connac_pm *pm = &dev->pm;
139 struct mt76_dev *mdev = &dev->mt76;
140
141 if (req->initiator == NL80211_REGDOM_SET_BY_USER &&
142 !dev->regd_user)
143 dev->regd_user = true;
144
145 /* do not need to update the same country twice */
146 if (!memcmp(req->alpha2, mdev->alpha2, 2) &&
147 dev->country_ie_env == req->country_ie_env)
148 return;
149
150 memcpy(mdev->alpha2, req->alpha2, 2);
151 mdev->region = req->dfs_region;
152 dev->country_ie_env = req->country_ie_env;
153
154 if (req->initiator == NL80211_REGDOM_SET_BY_USER) {
155 if (dev->mt76.alpha2[0] == '0' && dev->mt76.alpha2[1] == '0')
156 wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
157 else
158 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
159 }
160
161 dev->regd_change = true;
162
163 if (pm->suspended)
164 return;
165
166 if (MT7921_REGD_SUPPORTED(&dev->phy)) {
167 mt7921_regd_update(&dev->phy, req->alpha2);
168
169 return;
170 }
171
172 mt7921_mcu_regd_update(dev, req->alpha2,
173 req->country_ie_env);
174 }
175
176 static struct sk_buff *
mt7921_regd_query_regdb(struct mt792x_phy * phy,char * alpha2)177 mt7921_regd_query_regdb(struct mt792x_phy *phy, char *alpha2)
178 {
179 struct wiphy *wiphy = phy->mt76->hw->wiphy;
180 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
181 struct mt792x_dev *dev = mt792x_hw_dev(hw);
182 struct mt7921_clc *clc = phy->clc[MT792x_CLC_REGD];
183 struct mt7921_regd_query_req *req;
184 struct mt7921_regd_cc *regd_cc;
185 struct sk_buff *ret_skb = NULL;
186 u8 *pos, *last_pos;
187 int ret = 0;
188
189 if (!clc)
190 return NULL;
191
192 pos = clc->data;
193 last_pos = pos + le32_to_cpu(clc->len) - sizeof(struct mt7921_clc);
194 while (pos < last_pos) {
195 u32 req_len = 0;
196 u32 rules_len = 0;
197 u32 sign_len = 4;
198 u32 n_reg_rules;
199
200 if (pos + sizeof(*regd_cc) > last_pos)
201 break;
202
203 regd_cc = (struct mt7921_regd_cc *)pos;
204 n_reg_rules = le32_to_cpu(regd_cc->n_reg_rules);
205 if (n_reg_rules > NL80211_MAX_SUPP_REG_RULES)
206 break;
207
208 rules_len = sizeof(struct mt7921_regd_rule_header) +
209 sizeof(struct mt7921_regd_rule) * n_reg_rules;
210
211 if (pos + sizeof(*regd_cc) + rules_len + sign_len > last_pos)
212 break;
213
214 pos += sizeof(*regd_cc) + rules_len + sign_len;
215 if (memcmp(regd_cc->alpha2, alpha2, 2))
216 continue;
217
218 req_len = sizeof(*req) + rules_len + sign_len;
219 req = kzalloc(req_len, GFP_KERNEL);
220
221 if (!req)
222 return NULL;
223
224 req->ver = regd_cc->ver;
225 req->sign_type = regd_cc->sign_type;
226 req->size = cpu_to_le32(rules_len + sign_len);
227 req->n_reg_rules = regd_cc->n_reg_rules;
228
229 memcpy(req->alpha2, regd_cc->alpha2, 2);
230 memcpy(req->data, regd_cc->data, rules_len + sign_len);
231
232 ret = mt76_mcu_send_and_get_msg(&dev->mt76,
233 MCU_CE_CMD(SET_REGD_CH),
234 req, req_len, true, &ret_skb);
235
236 kfree(req);
237
238 return ret < 0 ? NULL : ret_skb;
239 }
240
241 return NULL;
242 }
243
mt7921_regd_update(struct mt792x_phy * phy,char * alpha2)244 int mt7921_regd_update(struct mt792x_phy *phy, char *alpha2)
245 {
246 struct wiphy *wiphy = phy->mt76->hw->wiphy;
247 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
248 struct mt792x_dev *dev = mt792x_hw_dev(hw);
249 struct mt7921_regd_rule *mt7921_rule;
250 struct mt76_dev *mdev = &dev->mt76;
251 struct ieee80211_regdomain *regd;
252 struct ieee80211_reg_rule *rule;
253 struct mt7921_regd_rule_ev *ev;
254 int i, num_of_rules = 0;
255 struct sk_buff *skb;
256 int ret = 0;
257
258 if (dev->hw_full_reset)
259 return 0;
260
261 if (!MT7921_REGD_SUPPORTED(phy))
262 return -EOPNOTSUPP;
263
264 mt792x_mutex_acquire(dev);
265 skb = mt7921_regd_query_regdb(phy, alpha2);
266 mt792x_mutex_release(dev);
267
268 if (!skb) {
269 ret = -EINVAL;
270 goto err;
271 }
272
273 if (skb->len < sizeof(*ev) + 4) {
274 ret = -EINVAL;
275 goto err;
276 }
277
278 ev = (struct mt7921_regd_rule_ev *)(skb->data + 4);
279 num_of_rules = le32_to_cpu(ev->n_reg_rules);
280
281 if (!num_of_rules ||
282 WARN_ON_ONCE(num_of_rules > NL80211_MAX_SUPP_REG_RULES)) {
283 ret = -EINVAL;
284 goto err;
285 }
286
287 if (skb->len < struct_size(ev, reg_rule, num_of_rules) + 4) {
288 ret = -EINVAL;
289 goto err;
290 }
291
292 regd = kzalloc(struct_size(regd, reg_rules, num_of_rules), GFP_KERNEL);
293 if (!regd) {
294 ret = -ENOMEM;
295 goto err;
296 }
297
298 for (i = 0; i < num_of_rules; i++) {
299 mt7921_rule = &ev->reg_rule[i];
300 rule = ®d->reg_rules[i];
301
302 rule->freq_range.start_freq_khz =
303 MHZ_TO_KHZ(le32_to_cpu(mt7921_rule->start_freq));
304 rule->freq_range.end_freq_khz =
305 MHZ_TO_KHZ(le32_to_cpu(mt7921_rule->end_freq));
306 rule->freq_range.max_bandwidth_khz =
307 MHZ_TO_KHZ(le32_to_cpu(mt7921_rule->max_bw));
308 /* not used by fw */
309 rule->power_rule.max_antenna_gain = DBI_TO_MBI(6);
310 rule->power_rule.max_eirp = DBM_TO_MBM(22);
311 rule->flags = le32_to_cpu(mt7921_rule->flags);
312 }
313
314 regd->n_reg_rules = num_of_rules;
315 regd->dfs_region = ev->dfs_region;
316
317 memcpy(regd->alpha2, alpha2, 2);
318 memcpy(mdev->alpha2, alpha2, 2);
319
320 dev->regd_change = true;
321 mt7921_mcu_regd_update(dev, alpha2, ENVIRON_ANY);
322
323 ret = regulatory_set_wiphy_regd(wiphy, regd);
324
325 kfree(regd);
326 err:
327 dev_kfree_skb(skb);
328
329 if (ret < 0)
330 return regulatory_set_wiphy_regd(wiphy, &mt7921_regd_ww);
331
332 return ret;
333 }
334 EXPORT_SYMBOL_GPL(mt7921_regd_update);
335
336 static bool
mt7921_regd_is_valid_alpha2(const char * alpha2)337 mt7921_regd_is_valid_alpha2(const char *alpha2)
338 {
339 if (!alpha2)
340 return false;
341
342 if (alpha2[0] == '0' && alpha2[1] == '0')
343 return true;
344
345 if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
346 return true;
347
348 return false;
349 }
350
mt7921_regd_change(struct mt792x_phy * phy,char * alpha2)351 int mt7921_regd_change(struct mt792x_phy *phy, char *alpha2)
352 {
353 struct wiphy *wiphy = phy->mt76->hw->wiphy;
354 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
355 struct mt792x_dev *dev = mt792x_hw_dev(hw);
356 struct mt76_dev *mdev = &dev->mt76;
357
358 if (dev->hw_full_reset)
359 return 0;
360
361 if (!mt7921_regd_is_valid_alpha2(alpha2) ||
362 !mt7921_regd_clc_supported(dev) ||
363 dev->regd_user)
364 return -EINVAL;
365
366 if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')
367 return 0;
368
369 /* do not need to update the same country twice */
370 if (!memcmp(alpha2, mdev->alpha2, 2))
371 return 0;
372
373 if (MT7921_REGD_SUPPORTED(phy))
374 return mt7921_regd_update(phy, alpha2);
375 else if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN)
376 return regulatory_hint(wiphy, alpha2);
377 else
378 return mt7921_mcu_set_clc(dev, alpha2, ENVIRON_INDOOR);
379 }
380
mt7921_regd_init(struct mt792x_phy * phy)381 int mt7921_regd_init(struct mt792x_phy *phy)
382 {
383 struct wiphy *wiphy = phy->mt76->hw->wiphy;
384 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
385 struct mt792x_dev *dev = mt792x_hw_dev(hw);
386 struct mt76_dev *mdev = &dev->mt76;
387
388 if (MT7921_REGD_SUPPORTED(phy)) {
389 wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED |
390 REGULATORY_DISABLE_BEACON_HINTS;
391 return mt7921_regd_update(phy, "00");
392 } else if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN)
393 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE |
394 REGULATORY_DISABLE_BEACON_HINTS;
395 else
396 memzero_explicit(&mdev->alpha2, sizeof(mdev->alpha2));
397
398 return 0;
399 }
400