Add WMI support to process the EHT capabilities passed by the hardware. Add required EHT specific definitions in structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aloka Dixit <quic_alokad@xxxxxxxxxxx> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@xxxxxxxxxxx> --- drivers/net/wireless/ath/ath12k/core.h | 8 ++ drivers/net/wireless/ath/ath12k/wmi.c | 112 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 38 +++++++++ 3 files changed, 158 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 9439052a652e..ed21dd78a2b9 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -579,6 +579,14 @@ struct ath12k_band_cap { u32 he_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE]; struct ath12k_wmi_ppe_threshold_arg he_ppet; u16 he_6ghz_capa; + u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE]; + u32 eht_cap_phy_info[WMI_MAX_EHTCAP_PHY_SIZE]; + u32 eht_mcs_20_only; + u32 eht_mcs_80; + u32 eht_mcs_160; + u32 eht_mcs_320; + struct ath12k_wmi_ppe_threshold_arg eht_ppet; + u32 eht_cap_info_internal; }; struct ath12k_pdev_cap { diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 7ae0bb78b2b5..89c3bf759bd4 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -65,6 +65,8 @@ struct ath12k_wmi_svc_rdy_ext_parse { struct ath12k_wmi_svc_rdy_ext2_parse { struct ath12k_wmi_dma_ring_caps_parse dma_caps_parse; bool dma_ring_cap_done; + bool spectral_bin_scaling_done; + bool mac_phy_caps_ext_done; }; struct ath12k_wmi_rdy_parse { @@ -4034,6 +4036,100 @@ static int ath12k_service_ready_ext_event(struct ath12k_base *ab, return ret; } +static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band, + __le32 cap_mac_info[], + __le32 cap_phy_info[], + __le32 supp_mcs[], + struct ath12k_wmi_ppe_threshold_params *ppet, + __le32 cap_info_internal) +{ + struct ath12k_band_cap *cap_band = &pdev->cap.band[band]; + u8 i; + + for (i = 0; i < WMI_MAX_EHTCAP_MAC_SIZE; i++) + cap_band->eht_cap_mac_info[i] = le32_to_cpu(cap_mac_info[i]); + + for (i = 0; i < WMI_MAX_EHTCAP_PHY_SIZE; i++) + cap_band->eht_cap_phy_info[i] = le32_to_cpu(cap_phy_info[i]); + + cap_band->eht_mcs_20_only = le32_to_cpu(supp_mcs[0]); + cap_band->eht_mcs_80 = le32_to_cpu(supp_mcs[1]); + if (band != NL80211_BAND_2GHZ) { + cap_band->eht_mcs_160 = le32_to_cpu(supp_mcs[2]); + cap_band->eht_mcs_320 = le32_to_cpu(supp_mcs[3]); + } + + cap_band->eht_ppet.numss_m1 = le32_to_cpu(ppet->numss_m1); + cap_band->eht_ppet.ru_bit_mask = le32_to_cpu(ppet->ru_info); + for (i = 0; i < WMI_MAX_NUM_SS; i++) + cap_band->eht_ppet.ppet16_ppet8_ru3_ru0[i] = + le32_to_cpu(ppet->ppet16_ppet8_ru3_ru0[i]); + + cap_band->eht_cap_info_internal = le32_to_cpu(cap_info_internal); +} + +static int ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab, + struct ath12k_wmi_mac_phy_caps_ext_params *caps, + struct ath12k_pdev *pdev) +{ + if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) { + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_2GHZ, + caps->eht_cap_mac_info_2ghz, + caps->eht_cap_phy_info_2ghz, + caps->eht_supp_mcs_ext_2ghz, + &caps->eht_ppet_2ghz, + caps->eht_cap_info_internal); + } + + if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) { + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_5GHZ, + caps->eht_cap_mac_info_5ghz, + caps->eht_cap_phy_info_5ghz, + caps->eht_supp_mcs_ext_5ghz, + &caps->eht_ppet_5ghz, + caps->eht_cap_info_internal); + + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_6GHZ, + caps->eht_cap_mac_info_5ghz, + caps->eht_cap_phy_info_5ghz, + caps->eht_supp_mcs_ext_5ghz, + &caps->eht_ppet_5ghz, + caps->eht_cap_info_internal); + } + + return 0; +} + +static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag, + u16 len, const void *ptr, + void *data) +{ + struct ath12k_wmi_mac_phy_caps_ext_params *caps = + (struct ath12k_wmi_mac_phy_caps_ext_params *)ptr; + int i, ret; + + if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT) + return -EPROTO; + + for (i = 0; i < ab->num_radios; i++) { + if (ab->pdevs[i].pdev_id == le32_to_cpu(caps->pdev_id)) + break; + } + + if (i == ab->num_radios) + return -EINVAL; + + ret = ath12k_wmi_tlv_mac_phy_caps_ext_parse(ab, caps, &ab->pdevs[i]); + if (ret) { + ath12k_warn(ab, + "failed to extract mac phy caps ext, pdev_id:%d\n", + ab->pdevs[i].pdev_id); + return ret; + } + + return 0; +} + static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *ptr, void *data) @@ -4050,6 +4146,22 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, return ret; parse->dma_ring_cap_done = true; + } else if (!parse->spectral_bin_scaling_done) { + /* TODO: This is a place-holder as WMI tag for + * spectral scaling is before + * WMI_TAG_MAC_PHY_CAPABILITIES_EXT + */ + parse->spectral_bin_scaling_done = true; + } else if (!parse->mac_phy_caps_ext_done) { + ret = ath12k_wmi_tlv_iter(ab, ptr, len, + ath12k_wmi_tlv_mac_phy_caps_ext, + parse); + if (ret) { + ath12k_warn(ab, "failed to parse tlv %d\n", ret); + return ret; + } + + parse->mac_phy_caps_ext_done = true; } break; default: diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 08a8c9e0f59f..fa513a24bca4 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2577,6 +2577,44 @@ struct ath12k_wmi_soc_hal_reg_caps_params { __le32 num_phy; } __packed; +#define WMI_MAX_EHTCAP_MAC_SIZE 2 +#define WMI_MAX_EHTCAP_PHY_SIZE 3 + +/* Used for EHT MCS-NSS array. Data at each array index follows the format given + * in IEEE P802.11be/D2.0, May 20229.4.2.313.4. + * + * Index interpretation: + * 0 - 20 MHz only sta, all 4 bytes valid + * 1 - index for bandwidths <= 80 MHz except 20 MHz-only, first 3 bytes valid + * 2 - index for 160 MHz, first 3 bytes valid + * 3 - index for 320 MHz, first 3 bytes valid + */ +#define WMI_MAX_EHT_SUPP_MCS_2G_SIZE 2 +#define WMI_MAX_EHT_SUPP_MCS_5G_SIZE 4 + +struct ath12k_wmi_mac_phy_caps_ext_params { + __le32 hw_mode_id; + union { + struct { + __le16 pdev_id; + __le16 hw_link_id; + } __packed ath12k_wmi_pdev_to_link_map; + __le32 pdev_id; + }; + __le32 phy_id; + __le32 wireless_modes_ext; + __le32 eht_cap_mac_info_2ghz[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 eht_cap_mac_info_5ghz[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 rsvd0[2]; + __le32 eht_cap_phy_info_2ghz[WMI_MAX_EHTCAP_PHY_SIZE]; + __le32 eht_cap_phy_info_5ghz[WMI_MAX_EHTCAP_PHY_SIZE]; + struct ath12k_wmi_ppe_threshold_params eht_ppet_2ghz; + struct ath12k_wmi_ppe_threshold_params eht_ppet_5ghz; + __le32 eht_cap_info_internal; + __le32 eht_supp_mcs_ext_2ghz[WMI_MAX_EHT_SUPP_MCS_2G_SIZE]; + __le32 eht_supp_mcs_ext_5ghz[WMI_MAX_EHT_SUPP_MCS_5G_SIZE]; +} __packed; + /* 2 word representation of MAC addr */ struct ath12k_wmi_mac_addr_params { u8 addr[ETH_ALEN]; -- 2.39.0