mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
wifi: mt76: mt7921: add auto regdomain switch support
Implement 802.11d-based automatic regulatory domain switching to dynamically determine the regulatory domain at runtime. The scan-done event structure by reusing reserved padding and appending new fields; the layout and values remains backward-compatible with existing users. Co-developed-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: JB Tsai <jb.tsai@mediatek.com> Link: https://patch.msgid.link/20260303053637.465465-4-jb.tsai@mediatek.com Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
e88098133e
commit
ae05055d30
|
|
@ -1599,7 +1599,7 @@ struct mt76_connac_hw_scan_done {
|
|||
u8 pno_enabled;
|
||||
u8 pad2[3];
|
||||
u8 sparse_channel_valid_num;
|
||||
u8 pad3[3];
|
||||
u8 alpha2[3];
|
||||
u8 channel_num[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
|
||||
/* idle format for channel_idle_time
|
||||
* 0: first bytes: idle time(ms) 2nd byte: dwell time(ms)
|
||||
|
|
@ -1612,6 +1612,7 @@ struct mt76_connac_hw_scan_done {
|
|||
u8 mdrdy_count[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
|
||||
__le32 beacon_2g_num;
|
||||
__le32 beacon_5g_num;
|
||||
__le16 channel_scan_time[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac_sched_scan_req {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "mt7921.h"
|
||||
#include "../dma.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "regd.h"
|
||||
#include "mcu.h"
|
||||
|
||||
#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
|
||||
|
|
@ -699,6 +700,8 @@ void mt7921_mac_reset_work(struct work_struct *work)
|
|||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_vif_connect_iter, NULL);
|
||||
mt76_connac_power_save_sched(&dev->mt76.phy, pm);
|
||||
|
||||
mt7921_regd_change(&dev->phy, "00");
|
||||
}
|
||||
|
||||
void mt7921_coredump_work(struct work_struct *work)
|
||||
|
|
|
|||
|
|
@ -1031,8 +1031,16 @@ void mt7921_scan_work(struct work_struct *work)
|
|||
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
|
||||
if (rxd->eid == MCU_EVENT_SCHED_SCAN_DONE) {
|
||||
ieee80211_sched_scan_results(phy->mt76->hw);
|
||||
} else if (test_and_clear_bit(MT76_HW_SCANNING,
|
||||
&phy->mt76->state)) {
|
||||
} else if (rxd->eid == MCU_EVENT_SCAN_DONE) {
|
||||
struct mt76_connac_hw_scan_done *event = NULL;
|
||||
|
||||
skb_pull(skb, sizeof(*rxd));
|
||||
event = (struct mt76_connac_hw_scan_done *)skb->data;
|
||||
mt7921_regd_change(phy, event->alpha2);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(MT76_HW_SCANNING,
|
||||
&phy->mt76->state)) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -484,7 +484,8 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
|
|||
goto out;
|
||||
}
|
||||
}
|
||||
ret = mt7921_mcu_set_clc(dev, "00", ENVIRON_INDOOR);
|
||||
|
||||
ret = mt7921_regd_init(phy);
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
|
|
|
|||
|
|
@ -110,26 +110,92 @@ int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
|
|||
EXPORT_SYMBOL_GPL(mt7921_mcu_regd_update);
|
||||
|
||||
void mt7921_regd_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
struct regulatory_request *req)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
|
||||
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
|
||||
dev->mt76.region = request->dfs_region;
|
||||
dev->country_ie_env = request->country_ie_env;
|
||||
/* do not need to update the same country twice */
|
||||
if (!memcmp(req->alpha2, mdev->alpha2, 2) &&
|
||||
dev->country_ie_env == req->country_ie_env)
|
||||
return;
|
||||
|
||||
if (request->initiator == NL80211_REGDOM_SET_BY_USER) {
|
||||
memcpy(mdev->alpha2, req->alpha2, 2);
|
||||
mdev->region = req->dfs_region;
|
||||
dev->country_ie_env = req->country_ie_env;
|
||||
|
||||
if (req->initiator == NL80211_REGDOM_SET_BY_USER) {
|
||||
if (dev->mt76.alpha2[0] == '0' && dev->mt76.alpha2[1] == '0')
|
||||
wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
|
||||
else
|
||||
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
|
||||
}
|
||||
|
||||
dev->regd_change = true;
|
||||
|
||||
if (pm->suspended)
|
||||
return;
|
||||
|
||||
mt7921_mcu_regd_update(dev, request->alpha2,
|
||||
request->country_ie_env);
|
||||
mt7921_mcu_regd_update(dev, req->alpha2,
|
||||
req->country_ie_env);
|
||||
}
|
||||
|
||||
static bool
|
||||
mt7921_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 mt7921_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 (!mt7921_regd_is_valid_alpha2(alpha2) ||
|
||||
!mt7921_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 mt7921_mcu_set_clc(dev, alpha2, ENVIRON_INDOOR);
|
||||
}
|
||||
|
||||
int mt7921_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,5 +13,7 @@ int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
|
|||
void mt7921_regd_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request);
|
||||
bool mt7921_regd_clc_supported(struct mt792x_dev *dev);
|
||||
int mt7921_regd_change(struct mt792x_phy *phy, char *alpha2);
|
||||
int mt7921_regd_init(struct mt792x_phy *phy);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user