wifi: mt76: mt7996: add support for variants with auxiliary RX path
authorShayne Chen <shayne.chen@mediatek.com>
Mon, 23 Oct 2023 15:38:44 +0000 (23:38 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 7 Dec 2023 17:50:20 +0000 (18:50 +0100)
Add support to correctly configure the rx chainmask of variants that
have additional auxiliary RX path. e.g., 4T5R.
The auxiliary RX path is transparent to driver, but driver needs to
correctly configure it in the set channel fw command.

Co-developed-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c
drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h

index 544b6c6f1ea329fbe18e9ab3702967c1ae9a4389..9db7e531076d152f76ec26af8126b10c4a685577 100644 (file)
@@ -148,36 +148,49 @@ static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
 
 int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
 {
-       u8 path, nss, band_idx = phy->mt76->band_idx;
+       u8 path, rx_path, nss, band_idx = phy->mt76->band_idx;
        u8 *eeprom = dev->mt76.eeprom.data;
        struct mt76_phy *mphy = phy->mt76;
+       int max_path = 5, max_nss = 4;
        int ret;
 
        switch (band_idx) {
        case MT_BAND1:
                path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND1,
                                 eeprom[MT_EE_WIFI_CONF + 2]);
+               rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND1,
+                                   eeprom[MT_EE_WIFI_CONF + 3]);
                nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND1,
                                eeprom[MT_EE_WIFI_CONF + 5]);
                break;
        case MT_BAND2:
                path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND2,
                                 eeprom[MT_EE_WIFI_CONF + 2]);
+               rx_path = FIELD_GET(MT_EE_WIFI_CONF4_RX_PATH_BAND2,
+                                   eeprom[MT_EE_WIFI_CONF + 4]);
                nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND2,
                                eeprom[MT_EE_WIFI_CONF + 5]);
                break;
        default:
                path = FIELD_GET(MT_EE_WIFI_CONF1_TX_PATH_BAND0,
                                 eeprom[MT_EE_WIFI_CONF + 1]);
+               rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND0,
+                                   eeprom[MT_EE_WIFI_CONF + 3]);
                nss = FIELD_GET(MT_EE_WIFI_CONF4_STREAM_NUM_BAND0,
                                eeprom[MT_EE_WIFI_CONF + 4]);
                break;
        }
 
-       if (!path || path > 4)
-               path = 4;
+       if (!path || path > max_path)
+               path = max_path;
 
-       nss = min_t(u8, min_t(u8, 4, nss), path);
+       if (!nss || nss > max_nss)
+               nss = max_nss;
+
+       nss = min_t(u8, nss, path);
+
+       if (path != rx_path)
+               phy->has_aux_rx = true;
 
        mphy->antenna_mask = BIT(nss) - 1;
        mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];
index 0c749774f6b10fdcb8caabc8d706e0b98b552500..412d6e2f8014c1e655c5691f091edf144b360f2d 100644 (file)
@@ -33,6 +33,9 @@ enum mt7996_eeprom_field {
 #define MT_EE_WIFI_CONF1_TX_PATH_BAND0         GENMASK(5, 3)
 #define MT_EE_WIFI_CONF2_TX_PATH_BAND1         GENMASK(2, 0)
 #define MT_EE_WIFI_CONF2_TX_PATH_BAND2         GENMASK(5, 3)
+#define MT_EE_WIFI_CONF3_RX_PATH_BAND0         GENMASK(2, 0)
+#define MT_EE_WIFI_CONF3_RX_PATH_BAND1         GENMASK(5, 3)
+#define MT_EE_WIFI_CONF4_RX_PATH_BAND2         GENMASK(2, 0)
 #define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0      GENMASK(5, 3)
 #define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1      GENMASK(2, 0)
 #define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2      GENMASK(5, 3)
index 03a9474120b71bd97d0ebe72a2eacebfeae2f7ab..55e97a857963474bbc9583a3cd2451b54707c3f4 100644 (file)
@@ -3299,7 +3299,7 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
                .center_ch = ieee80211_frequency_to_channel(freq1),
                .bw = mt76_connac_chan_bw(chandef),
                .tx_path_num = hweight16(phy->mt76->chainmask),
-               .rx_path = phy->mt76->chainmask >> dev->chainshift[band_idx],
+               .rx_path = mt7996_rx_chainmask(phy) >> dev->chainshift[band_idx],
                .band_idx = band_idx,
                .channel_band = ch_band[chandef->chan->band],
        };
index e7818b2b253f9fe14ec3773eda2c772e6cc4bfcd..6acc0ae286fa4ca7ef03c86736d694c03c4320ba 100644 (file)
@@ -210,6 +210,8 @@ struct mt7996_phy {
 
        struct mt76_mib_stats mib;
        struct mt76_channel_state state_ts;
+
+       bool has_aux_rx;
 };
 
 struct mt7996_dev {
@@ -501,6 +503,18 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
 void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
                          size_t len);
 
+static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
+{
+       int max_nss = hweight8(phy->mt76->hw->wiphy->available_antennas_tx);
+       int cur_nss = hweight8(phy->mt76->antenna_mask);
+       u16 tx_chainmask = phy->mt76->chainmask;
+
+       if (cur_nss != max_nss)
+               return tx_chainmask;
+
+       return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
+}
+
 void mt7996_mac_init(struct mt7996_dev *dev);
 u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
 bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);