wifi: mt76: mt7925: add EHT control support based on the CLC data
authorMing Yen Hsieh <mingyen.hsieh@mediatek.com>
Tue, 4 Mar 2025 11:36:45 +0000 (19:36 +0800)
committerFelix Fietkau <nbd@nbd.name>
Wed, 19 Mar 2025 13:47:03 +0000 (14:47 +0100)
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>
drivers/net/wireless/mediatek/mt76/mt7925/init.c
drivers/net/wireless/mediatek/mt76/mt7925/main.c
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
drivers/net/wireless/mediatek/mt76/mt792x.h

index a2bb36dab2310ed6afb0fcaa55a4bc879bc357d1..46b12a2e81ee2b3667945a861fce4818373ed21d 100644 (file)
@@ -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;
index 0b390b2691e3f210d4518687bed7380f10151a0e..e79364ac129ee171b91eeae340bf525f18acc0c9 100644 (file)
@@ -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;
 
index 0f58a5afb77a56e1925756ffe094ff6fbf282aaa..575b51931d7d4f06b8fd3a54239e352336273ee7 100644 (file)
@@ -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);
 
index 073e433069e0e5832ea9cbe72921121ea998ecc6..5cd3073dfc50405f12bb693882811bcff9e922ea 100644 (file)
@@ -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,
index 048f9ab161263339d32a8228f4835401542b51fb..97e9de88a63d86d54841952eee8b979e8c9a0f41 100644 (file)
@@ -71,6 +71,7 @@ struct mt792x_fw_features {
 enum {
        MT792x_CLC_POWER,
        MT792x_CLC_POWER_EXT,
+       MT792x_CLC_BE_CTRL,
        MT792x_CLC_MAX_NUM,
 };