There are variants of mt7996 which are different from eht supported and wtbl size limit. Get the hw caps with CHIP_CONFIG command. Signed-off-by: Shayne Chen <shayne.chen@xxxxxxxxxxxx> --- .../wireless/mediatek/mt76/mt7996/eeprom.c | 27 +++++++++++ .../net/wireless/mediatek/mt76/mt7996/mcu.c | 46 +++++++++++++++++++ .../wireless/mediatek/mt76/mt7996/mt7996.h | 4 ++ 3 files changed, 77 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c index 5d8e0353627e..2e48c5a40f81 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c @@ -87,6 +87,28 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev) return mt7996_check_eeprom(dev); } +static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev) +{ +#define MODE_HE_ONLY BIT(0) +#define WTBL_SIZE_GROUP GENMASK(31, 28) + u32 cap = 0; + int ret; + + ret = mt7996_mcu_get_chip_config(dev, &cap); + if (ret) + return ret; + + if (cap) { + dev->has_eht = !(cap & MODE_HE_ONLY); + dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP); + } + + if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4) + dev->wtbl_size_group = 2; /* set default */ + + return 0; +} + static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy) { u8 *eeprom = phy->dev->mt76.eeprom.data; @@ -133,6 +155,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy) u8 path, nss, band_idx = phy->mt76->band_idx; u8 *eeprom = dev->mt76.eeprom.data; struct mt76_phy *mphy = phy->mt76; + int ret; switch (band_idx) { case MT_BAND1: @@ -167,6 +190,10 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy) dev->chainshift[band_idx + 1] = dev->chainshift[band_idx] + hweight16(mphy->chainmask); + ret = mt7996_eeprom_parse_efuse_hw_cap(dev); + if (ret) + return ret; + return mt7996_eeprom_parse_band_config(phy); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index d593ed9e3f73..f42f18f00a26 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -2978,6 +2978,52 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num) return 0; } +int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap) +{ +#define NIC_CAP 3 +#define UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION 0x21 + struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; + } __packed req = { + .tag = cpu_to_le16(NIC_CAP), + .len = cpu_to_le16(sizeof(req) - 4), + }; + struct sk_buff *skb; + u8 *buf; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_WM_UNI_CMD_QUERY(CHIP_CONFIG), &req, + sizeof(req), true, &skb); + if (ret) + return ret; + + /* fixed field */ + skb_pull(skb, 4); + + buf = skb->data; + while (buf - skb->data < skb->len) { + struct tlv *tlv = (struct tlv *)buf; + + switch (le16_to_cpu(tlv->tag)) { + case UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION: + *cap = le32_to_cpu(*(__le32 *)(buf + sizeof(*tlv))); + break; + default: + break; + }; + + buf += le16_to_cpu(tlv->len); + } + + dev_kfree_skb(skb); + + return 0; +} + int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 725344791b4c..00f3beda74cc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -264,6 +264,7 @@ struct mt7996_dev { bool dbdc_support:1; bool tbtc_support:1; bool flash_mode:1; + bool has_eht:1; bool ibf; u8 fw_debug_wm; @@ -281,6 +282,8 @@ struct mt7996_dev { u32 reg_l1_backup; u32 reg_l2_backup; + + u8 wtbl_size_group; }; enum { @@ -419,6 +422,7 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, int mt7996_mcu_set_eeprom(struct mt7996_dev *dev); int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset); int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num); +int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap); int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band); int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action); int mt7996_mcu_set_fcc5_lpn(struct mt7996_dev *dev, int val); -- 2.25.1