From: Ming Yen Hsieh Date: Tue, 4 Mar 2025 11:36:45 +0000 (+0800) Subject: wifi: mt76: mt7925: add EHT control support based on the CLC data X-Git-Tag: v6.15-rc1~160^2~20^2~1^2~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0317215b367e22e1cde5dcdb4c0687f0a85b913;p=thirdparty%2Flinux.git 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 Link: https://patch.msgid.link/20250304113649.867387-2-mingyen.hsieh@mediatek.com Signed-off-by: Felix Fietkau --- diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net/wireless/mediatek/mt76/mt7925/init.c index a2bb36dab2310..46b12a2e81ee2 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 0b390b2691e3f..e79364ac129ee 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 0f58a5afb77a5..575b51931d7d4 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 073e433069e0e..5cd3073dfc504 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 048f9ab161263..97e9de88a63d8 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, };