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 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 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 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 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 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 * 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 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 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 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 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