diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath12k/wmi.c')
-rw-r--r-- | drivers/net/wireless/ath/ath12k/wmi.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index e6033ab15825..63e6c08c767c 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 { @@ -445,8 +447,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle, const struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params *hw_caps = svc->hw_caps; const struct ath12k_wmi_hw_mode_cap_params *wmi_hw_mode_caps = svc->hw_mode_caps; const struct ath12k_wmi_mac_phy_caps_params *wmi_mac_phy_caps = svc->mac_phy_caps; + struct ath12k_base *ab = wmi_handle->wmi_ab->ab; struct ath12k_band_cap *cap_band; struct ath12k_pdev_cap *pdev_cap = &pdev->cap; + struct ath12k_fw_pdev *fw_pdev; u32 phy_map; u32 hw_idx, phy_idx = 0; int i; @@ -475,6 +479,12 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle, pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands); pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density); + fw_pdev = &ab->fw_pdev[ab->fw_pdev_count]; + fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands); + fw_pdev->pdev_id = le32_to_cpu(mac_caps->pdev_id); + fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id); + ab->fw_pdev_count++; + /* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from * band to band for a single radio, need to see how this should be * handled. @@ -3815,6 +3825,7 @@ static int ath12k_wmi_ext_soc_hal_reg_caps_parse(struct ath12k_base *soc, soc->num_radios = 0; phy_id_map = le32_to_cpu(svc_rdy_ext->pref_hw_mode_caps.phy_id_map); + soc->fw_pdev_count = 0; while (phy_id_map && soc->num_radios < MAX_RADIOS) { ret = ath12k_pull_mac_phy_cap_svc_ready_ext(wmi_handle, @@ -4042,6 +4053,125 @@ err: return ret; } +static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band, + const __le32 cap_mac_info[], + const __le32 cap_phy_info[], + const __le32 supp_mcs[], + const 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, + const struct ath12k_wmi_caps_ext_params *caps, + struct ath12k_pdev *pdev) +{ + u32 bands; + int i; + + if (ab->hw_params->single_pdev_only) { + for (i = 0; i < ab->fw_pdev_count; i++) { + struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i]; + + if (fw_pdev->pdev_id == le32_to_cpu(caps->pdev_id) && + fw_pdev->phy_id == le32_to_cpu(caps->phy_id)) { + bands = fw_pdev->supported_bands; + break; + } + } + + if (i == ab->fw_pdev_count) + return -EINVAL; + } else { + bands = pdev->cap.supported_bands; + } + + if (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 (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) +{ + const struct ath12k_wmi_caps_ext_params *caps = ptr; + int i = 0, ret; + + if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT) + return -EPROTO; + + if (ab->hw_params->single_pdev_only) { + if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id)) + return 0; + } else { + 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 parse extended MAC PHY capabilities for pdev %d: %d\n", + ret, 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) @@ -4058,6 +4188,23 @@ 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 extended MAC PHY capabilities WMI TLV: %d\n", + ret); + return ret; + } + + parse->mac_phy_caps_ext_done = true; } break; default: |