]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mt76: mt7925: add auto regdomain switch support
authorMing Yen Hsieh <mingyen.hsieh@mediatek.com>
Fri, 31 Oct 2025 09:03:51 +0000 (17:03 +0800)
committerFelix Fietkau <nbd@nbd.name>
Mon, 24 Nov 2025 13:37:55 +0000 (14:37 +0100)
Implement 802.11d-based automatic regulatory domain switching to
dynamically determine the regulatory domain at runtime.

Signed-off-by: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
Link: https://patch.msgid.link/20251031090352.1400079-6-mingyen.hsieh@mediatek.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7925/init.c
drivers/net/wireless/mediatek/mt76/mt7925/mac.c
drivers/net/wireless/mediatek/mt76/mt7925/main.c
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
drivers/net/wireless/mediatek/mt76/mt7925/regd.c
drivers/net/wireless/mediatek/mt76/mt7925/regd.h
drivers/net/wireless/mediatek/mt76/mt792x.h

index 741e38b29b77b64715eec587a6b2f0eb8681078a..36f7e98f256cd8ad9524ec713998d51dfd8aec07 100644 (file)
@@ -91,8 +91,6 @@ int mt7925_mac_init(struct mt792x_dev *dev)
 
        mt7925_mac_init_basic_rates(dev);
 
-       memzero_explicit(&dev->mt76.alpha2, sizeof(dev->mt76.alpha2));
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(mt7925_mac_init);
index 19c9bec7c7e673552456c51c01ff00279e4ac051..871b67101976a7d72ca10c9736ccfa59b0f21122 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/timekeeping.h>
 #include "mt7925.h"
 #include "../dma.h"
+#include "regd.h"
 #include "mac.h"
 #include "mcu.h"
 
@@ -1329,9 +1330,7 @@ void mt7925_mac_reset_work(struct work_struct *work)
                                            mt7925_vif_connect_iter, NULL);
        mt76_connac_power_save_sched(&dev->mt76.phy, pm);
 
-       mt792x_mutex_acquire(dev);
-       mt7925_mcu_set_clc(dev, "00", ENVIRON_INDOOR);
-       mt792x_mutex_release(dev);
+       mt7925_regd_change(&dev->phy, "00");
 }
 
 void mt7925_coredump_work(struct work_struct *work)
index 641be23011b1c90866e5d1c7509fb55ec97c2156..cb913dfedcdab18b0c2a2587534ed8acb5122832 100644 (file)
@@ -1313,20 +1313,6 @@ void mt7925_mlo_pm_work(struct work_struct *work)
                                            mt7925_mlo_pm_iter, dev);
 }
 
-static bool is_valid_alpha2(const char *alpha2)
-{
-       if (!alpha2)
-               return false;
-
-       if (alpha2[0] == '0' && alpha2[1] == '0')
-               return true;
-
-       if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
-               return true;
-
-       return false;
-}
-
 void mt7925_scan_work(struct work_struct *work)
 {
        struct mt792x_phy *phy;
@@ -1335,7 +1321,6 @@ void mt7925_scan_work(struct work_struct *work)
                                                scan_work.work);
 
        while (true) {
-               struct mt76_dev *mdev = &phy->dev->mt76;
                struct sk_buff *skb;
                struct tlv *tlv;
                int tlv_len;
@@ -1366,13 +1351,7 @@ void mt7925_scan_work(struct work_struct *work)
                        case UNI_EVENT_SCAN_DONE_CHNLINFO:
                                evt = (struct mt7925_mcu_scan_chinfo_event *)tlv->data;
 
-                               if (!is_valid_alpha2(evt->alpha2))
-                                       break;
-
-                               if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')
-                                       break;
-
-                               mt7925_mcu_set_clc(phy->dev, evt->alpha2, ENVIRON_INDOOR);
+                               mt7925_regd_change(phy, evt->alpha2);
 
                                break;
                        case UNI_EVENT_SCAN_DONE_NLO:
index 983766faa9725024f43d70e60f018027aa4f76e1..54c4ab2f322cda519a093482ef6eedfd2ad9b28d 100644 (file)
@@ -755,6 +755,7 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
                }
        }
 
+       ret = mt7925_regd_init(phy);
 out:
        release_firmware(fw);
 
index 12d8aac16e34ab58f6e44ed4d9e3f80c4edb1efa..4565e1132b3616f92edab0e747549a4a8c3a0108 100644 (file)
@@ -197,3 +197,64 @@ void mt7925_regd_notifier(struct wiphy *wiphy, struct regulatory_request *req)
                               req->country_ie_env);
        return;
 }
+
+static bool
+mt7925_regd_is_valid_alpha2(const char *alpha2)
+{
+       if (!alpha2)
+               return false;
+
+       if (alpha2[0] == '0' && alpha2[1] == '0')
+               return true;
+
+       if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
+               return true;
+
+       return false;
+}
+
+int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2)
+{
+       struct wiphy *wiphy = phy->mt76->hw->wiphy;
+       struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+       struct mt792x_dev *dev = mt792x_hw_dev(hw);
+       struct mt76_dev *mdev = &dev->mt76;
+
+       if (dev->hw_full_reset)
+               return 0;
+
+       if (!mt7925_regd_is_valid_alpha2(alpha2) ||
+           !mt7925_regd_clc_supported(dev))
+               return -EINVAL;
+
+       if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')
+               return 0;
+
+       /* do not need to update the same country twice */
+       if (!memcmp(alpha2, mdev->alpha2, 2))
+               return 0;
+
+       if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN) {
+               return regulatory_hint(wiphy, alpha2);
+       } else {
+               return mt7925_mcu_set_clc(dev, alpha2, ENVIRON_INDOOR);
+       }
+}
+EXPORT_SYMBOL_GPL(mt7925_regd_change);
+
+int mt7925_regd_init(struct mt792x_phy *phy)
+{
+       struct wiphy *wiphy = phy->mt76->hw->wiphy;
+       struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+       struct mt792x_dev *dev = mt792x_hw_dev(hw);
+       struct mt76_dev *mdev = &dev->mt76;
+
+       if (phy->chip_cap & MT792x_CHIP_CAP_11D_EN) {
+               wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE |
+                                          REGULATORY_DISABLE_BEACON_HINTS;
+       } else {
+               memzero_explicit(&mdev->alpha2, sizeof(mdev->alpha2));
+       }
+
+       return 0;
+}
index edcda72b12b0b0bc59f673acaec6051ee66a9b91..0767f078862e7083bfe14522996ab5ba7aa8b963 100644 (file)
@@ -12,6 +12,8 @@ int mt7925_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
 void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2);
 void mt7925_regd_notifier(struct wiphy *wiphy, struct regulatory_request *req);
 bool mt7925_regd_clc_supported(struct mt792x_dev *dev);
+int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2);
+int mt7925_regd_init(struct mt792x_phy *phy);
 
 #endif
 
index da7831f9efec3760e2f294b18867319f287716b5..ed2606e9251ab107b488b7ed8be8003147cd9de8 100644 (file)
@@ -28,6 +28,7 @@
 #define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
 #define MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN BIT(1)
 #define MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN BIT(3)
+#define MT792x_CHIP_CAP_11D_EN BIT(4)
 #define MT792x_CHIP_CAP_MLO_EN BIT(8)
 #define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)