summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek
diff options
context:
space:
mode:
authorMing Yen Hsieh <mingyen.hsieh@mediatek.com>2025-03-04 19:36:45 +0800
committerFelix Fietkau <nbd@nbd.name>2025-03-19 14:47:03 +0100
commitf0317215b367e22e1cde5dcdb4c0687f0a85b913 (patch)
treea9b87d0ad1c509f77ff862b91fced8bea20a2420 /drivers/net/wireless/mediatek
parentf2027ef3f733d3f0bb7f27fa3343784058f946ab (diff)
wifi: mt76: mt7925: add EHT control support based on the CLC data
Some countries do not support EHT modulation for now. To prevent violating regulations, the MT7925 chipset should control the EHT capabilities. Therefore, when a regulatory domain change is detected during scanning, the `mt7925_regd_be_ctrl` will process the CLC data to update the EHT capabilities. Signed-off-by: Ming Yen Hsieh <mingyen.hsieh@mediatek.com> Link: https://patch.msgid.link/20250304113649.867387-2-mingyen.hsieh@mediatek.com Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/init.c38
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/main.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mcu.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h27
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt792x.h1
5 files changed, 71 insertions, 7 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net/wireless/mediatek/mt76/mt7925/init.c
index a2bb36dab231..46b12a2e81ee 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/init.c
@@ -58,6 +58,44 @@ static int mt7925_thermal_init(struct mt792x_phy *phy)
return PTR_ERR_OR_ZERO(hwmon);
}
+void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2)
+{
+ struct mt792x_phy *phy = &dev->phy;
+ struct mt7925_clc_rule_v2 *rule;
+ struct mt7925_clc *clc;
+ bool old = dev->has_eht, new = true;
+ u8 *pos;
+
+ if (!phy->clc[MT792x_CLC_BE_CTRL])
+ goto out;
+
+ clc = (struct mt7925_clc *)phy->clc[MT792x_CLC_BE_CTRL];
+ pos = clc->data;
+
+ while (1) {
+ rule = (struct mt7925_clc_rule_v2 *)pos;
+
+ if (rule->alpha2[0] == alpha2[0] &&
+ rule->alpha2[1] == alpha2[1]) {
+ new = false;
+ break;
+ }
+
+ /* Check the last one */
+ if (rule->flag && BIT(0))
+ break;
+
+ pos += sizeof(*rule);
+ }
+
+out:
+ if (old == new)
+ return;
+
+ dev->has_eht = new;
+ mt7925_set_stream_he_eht_caps(phy);
+}
+
void mt7925_regd_update(struct mt792x_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 0b390b2691e3..e79364ac129e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -1418,6 +1418,8 @@ void mt7925_scan_work(struct work_struct *work)
if (!is_valid_alpha2(evt->alpha2))
break;
+ mt7925_regd_be_ctrl(phy->dev, evt->alpha2);
+
if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')
break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 0f58a5afb77a..575b51931d7d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -742,7 +742,9 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
continue;
/* header content sanity */
- if (u8_get_bits(clc->type, MT_EE_HW_TYPE_ENCAP) != hw_encap)
+ if ((clc->idx == MT792x_CLC_BE_CTRL &&
+ u8_get_bits(clc->t2.type, MT_EE_HW_TYPE_ENCAP) != hw_encap) ||
+ u8_get_bits(clc->t0.type, MT_EE_HW_TYPE_ENCAP) != hw_encap)
continue;
phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc,
@@ -851,7 +853,6 @@ mt7925_mcu_parse_phy_cap(struct mt792x_dev *dev, char *data)
mdev->phy.chainmask = mdev->phy.antenna_mask;
mdev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);
mdev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);
- dev->has_eht = cap->eht;
}
static void
@@ -3193,7 +3194,7 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
if (!clc)
return 0;
- pos = clc->data + sizeof(*seg) * clc->nr_seg;
+ pos = clc->data + sizeof(*seg) * clc->t0.nr_seg;
last_pos = clc->data + le32_to_cpu(*(__le32 *)(clc->data + 4));
while (pos < last_pos) {
struct mt7925_clc_rule *rule = (struct mt7925_clc_rule *)pos;
@@ -3239,6 +3240,9 @@ int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
/* submit all clc config */
for (i = 0; i < ARRAY_SIZE(phy->clc); i++) {
+ if (i == MT792x_CLC_BE_CTRL)
+ continue;
+
ret = __mt7925_mcu_set_clc(dev, alpha2, env_cap,
phy->clc[i], i);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
index 073e433069e0..5cd3073dfc50 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
@@ -137,6 +137,12 @@ enum {
MT7925_CLC_MAX_NUM,
};
+struct mt7925_clc_rule_v2 {
+ u32 flag;
+ u8 alpha2[2];
+ u8 rsv[10];
+} __packed;
+
struct mt7925_clc_rule {
u8 alpha2[2];
u8 type[2];
@@ -152,14 +158,26 @@ struct mt7925_clc_segment {
u8 rsv2[4];
} __packed;
-struct mt7925_clc {
- __le32 len;
- u8 idx;
- u8 ver;
+struct mt7925_clc_type0 {
u8 nr_country;
u8 type;
u8 nr_seg;
u8 rsv[7];
+} __packed;
+
+struct mt7925_clc_type2 {
+ u8 type;
+ u8 rsv[9];
+} __packed;
+
+struct mt7925_clc {
+ __le32 len;
+ u8 idx;
+ u8 ver;
+ union {
+ struct mt7925_clc_type0 t0;
+ struct mt7925_clc_type2 t2;
+ };
u8 data[];
} __packed;
@@ -238,6 +256,7 @@ int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd);
int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
u8 bit_op, u32 bit_map);
+void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2);
void mt7925_regd_update(struct mt792x_dev *dev);
int mt7925_mac_init(struct mt792x_dev *dev);
int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 048f9ab16126..97e9de88a63d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -71,6 +71,7 @@ struct mt792x_fw_features {
enum {
MT792x_CLC_POWER,
MT792x_CLC_POWER_EXT,
+ MT792x_CLC_BE_CTRL,
MT792x_CLC_MAX_NUM,
};