wifi: mt76: mt7921: add support to update fw capability with MTFG table
authorQuan Zhou <quan.zhou@mediatek.com>
Wed, 7 Dec 2022 05:03:41 +0000 (13:03 +0800)
committerFelix Fietkau <nbd@nbd.name>
Fri, 9 Dec 2022 15:45:39 +0000 (16:45 +0100)
In ACPI enabled devices, mt7921 should read MTFG table from platform
hardware. Apply necessary settings for firmware capabilities through CLC
command.

Co-developed-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Quan Zhou <quan.zhou@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c
drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h

index 47e034a9b0037a35641fb1b4d2a20c400c873a88..a98d0fb42d0ac1fe1039ab737f617258543d5be6 100644 (file)
@@ -135,6 +135,22 @@ mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version)
        return ret;
 }
 
+/* MTFG : Flag Table */
+static int
+mt7921_asar_acpi_read_mtfg(struct mt7921_dev *dev, u8 **table)
+{
+       int len, ret;
+
+       ret = mt7921_acpi_read(dev, MT7921_ACPI_MTFG, table, &len);
+       if (ret)
+               return ret;
+
+       if (len < MT7921_ASAR_MIN_FG)
+               ret = -EINVAL;
+
+       return ret;
+}
+
 int mt7921_init_acpi_sar(struct mt7921_dev *dev)
 {
        struct mt7921_acpi_sar *asar;
@@ -162,6 +178,12 @@ int mt7921_init_acpi_sar(struct mt7921_dev *dev)
                asar->geo = NULL;
        }
 
+       /* MTFG is optional */
+       ret = mt7921_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg);
+       if (ret) {
+               devm_kfree(dev->mt76.dev, asar->fg);
+               asar->fg = NULL;
+       }
        dev->phy.acpisar = asar;
 
        return 0;
@@ -280,3 +302,36 @@ int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
 
        return 0;
 }
+
+u8 mt7921_acpi_get_flags(struct mt7921_phy *phy)
+{
+       struct mt7921_asar_fg *fg;
+       struct {
+               u8 acpi_idx;
+               u8 chip_idx;
+       } map[] = {
+               {1, 1},
+               {4, 2},
+       };
+       u8 flags = BIT(0);
+       int i, j;
+
+       if (!phy->acpisar)
+               return 0;
+
+       fg = phy->acpisar->fg;
+       if (!fg)
+               return flags;
+
+       /* pickup necessary settings per device and
+        * translate the index of bitmap for chip command.
+        */
+       for (i = 0; i < fg->nr_flag; i++)
+               for (j = 0; j < ARRAY_SIZE(map); j++)
+                       if (fg->flag[i] == map[j].acpi_idx) {
+                               flags |= BIT(map[j].chip_idx);
+                               break;
+                       }
+
+       return flags;
+}
index 23f86bfae0c057beaf35542d6109068dafb089c0..35268b0890ad7d743df7fd9cf0bf45531eefec78 100644 (file)
@@ -8,10 +8,12 @@
 #define MT7921_ASAR_MAX_DYN            8
 #define MT7921_ASAR_MIN_GEO            3
 #define MT7921_ASAR_MAX_GEO            8
+#define MT7921_ASAR_MIN_FG             8
 
 #define MT7921_ACPI_MTCL               "MTCL"
 #define MT7921_ACPI_MTDS               "MTDS"
 #define MT7921_ACPI_MTGS               "MTGS"
+#define MT7921_ACPI_MTFG               "MTFG"
 
 struct mt7921_asar_dyn_limit {
        u8 idx;
@@ -77,6 +79,15 @@ struct mt7921_asar_cl {
        u8 cl6g[6];
 } __packed;
 
+struct mt7921_asar_fg {
+       u8 names[4];
+       u8 version;
+       u8 rsvd;
+       u8 nr_flag;
+       u8 rsvd1;
+       u8 flag[0];
+} __packed;
+
 struct mt7921_acpi_sar {
        u8 ver;
        union {
@@ -88,6 +99,7 @@ struct mt7921_acpi_sar {
                struct mt7921_asar_geo_v2 *geo_v2;
        };
        struct mt7921_asar_cl *countrylist;
+       struct mt7921_asar_fg *fg;
 };
 
 #endif
index fb9c0f66cb27c33882b78a2f1f28d1620b8ab84a..8930b5a4467c4dc0fe26835af492221a3a3fa627 100644 (file)
@@ -1184,13 +1184,15 @@ int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
                __le16 len;
                u8 idx;
                u8 env;
-               u8 pad1[2];
+               u8 acpi_conf;
+               u8 pad1;
                u8 alpha2[2];
                u8 type[2];
                u8 rsvd[64];
        } __packed req = {
                .idx = idx,
                .env = env_cap,
+               .acpi_conf = mt7921_acpi_get_flags(&dev->phy),
        };
        int ret, valid_cnt = 0;
        u8 i, *pos;
index 15d6b7fe1c6c8986c1810cca18290b5bb68dfe28..efff4d43d79636be5f69e0b1c019081ffa4e89f4 100644 (file)
@@ -554,6 +554,7 @@ int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
 #ifdef CONFIG_ACPI
 int mt7921_init_acpi_sar(struct mt7921_dev *dev);
 int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default);
+u8 mt7921_acpi_get_flags(struct mt7921_phy *phy);
 #else
 static inline int
 mt7921_init_acpi_sar(struct mt7921_dev *dev)
@@ -566,6 +567,12 @@ mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
 {
        return 0;
 }
+
+static inline u8
+mt7921_acpi_get_flags(struct mt7921_phy *phy)
+{
+       return 0;
+}
 #endif
 int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
                          const struct cfg80211_sar_specs *sar);