mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
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>
This commit is contained in:
committed by
Felix Fietkau
parent
6338709a4f
commit
3bc62aa448
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user