diff options
| author | Ming Yen Hsieh <mingyen.hsieh@mediatek.com> | 2025-10-31 17:03:51 +0800 |
|---|---|---|
| committer | Felix Fietkau <nbd@nbd.name> | 2025-11-24 14:37:55 +0100 |
| commit | 3bc62aa4484dcb9529fea70e756743769b1145e6 (patch) | |
| tree | f44877c46bb1358a7e95ca39244cb46e63381b22 | |
| parent | 6338709a4f8636911b4eacfdd75cc12e28702285 (diff) | |
wifi: mt76: mt7925: add auto regdomain switch support
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>
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/init.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/main.c | 23 | ||||
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/regd.c | 61 | ||||
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/regd.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt792x.h | 1 |
7 files changed, 68 insertions, 27 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net/wireless/mediatek/mt76/mt7925/init.c index 741e38b29b77..36f7e98f256c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/init.c @@ -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); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c index 19c9bec7c7e6..871b67101976 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c @@ -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) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index 641be23011b1..cb913dfedcda 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -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: diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c index 983766faa972..54c4ab2f322c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -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); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regd.c b/drivers/net/wireless/mediatek/mt76/mt7925/regd.c index 12d8aac16e34..4565e1132b36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/regd.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/regd.c @@ -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; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regd.h b/drivers/net/wireless/mediatek/mt76/mt7925/regd.h index edcda72b12b0..0767f078862e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/regd.h +++ b/drivers/net/wireless/mediatek/mt76/mt7925/regd.h @@ -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 diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index da7831f9efec..ed2606e9251a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -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) |