wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/566-ath12k-propagation-of-EHT-capabilities-from-firmware.patch
John Crispin 144c5d00f4 ipq95xx/mac80211: update to ATH12.3-CS
Signed-off-by: John Crispin <john@phrozen.org>
2024-02-28 18:56:21 +01:00

687 lines
23 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 813d79336da8367f94049bd22929d1f1001a39d2 Mon Sep 17 00:00:00 2001
From: Aloka Dixit <quic_alokad@quicinc.com>
Date: Thu, 10 Feb 2022 17:09:20 -0800
Subject: [PATCH 04/27] ath12k: propagation of EHT capabilities from firmware
to kernel
This commit adds new WMI definitions and functions required to parse
the EHT capabilities advertised by the firmware and propagate those
to the kernel.
Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
---
drivers/net/wireless/ath/ath11k/wmi.h | 1 -
drivers/net/wireless/ath/ath12k/core.h | 8 +
drivers/net/wireless/ath/ath12k/mac.c | 283 ++++++++++++++++++-------
drivers/net/wireless/ath/ath12k/wmi.c | 132 +++++++++++-
drivers/net/wireless/ath/ath12k/wmi.h | 88 +++++++-
5 files changed, 433 insertions(+), 79 deletions(-)
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -659,6 +659,14 @@ struct ath12k_band_cap {
u32 he_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE];
struct ath12k_ppe_threshold he_ppet;
u16 he_6ghz_capa;
+ u32 eht_cap_mac_info[PSOC_HOST_MAX_MAC_SIZE];
+ u32 eht_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE];
+ u32 eht_mcs_20_only;
+ u32 eht_mcs_80;
+ u32 eht_mcs_160;
+ u32 eht_mcs_320;
+ struct ath12k_ppe_threshold eht_ppet;
+ u32 eht_cap_info_internal;
};
struct ath12k_pdev_cap {
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -4560,6 +4560,48 @@ static void ath12k_gen_ppe_thresh(struct
}
}
+static void ath12k_gen_eht_ppe_thresh(struct ath12k_ppe_threshold *fw_ppet,
+ struct ieee80211_sta_eht_cap *cap)
+{
+ int nss, ru;
+ u8 len = 0, bit = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE;
+
+ len = hweight8(fw_ppet->ru_bit_mask);
+ len *= (1 + fw_ppet->numss_m1);
+
+ len = (len * IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE) +
+ IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE;
+ len = DIV_ROUND_UP(len, 8);
+
+ cap->eht_ppe_thres[0] = FIELD_PREP(IEEE80211_EHT_PPE_THRES_NSS_MASK,
+ fw_ppet->numss_m1);
+ cap->eht_ppe_thres[0] |= FIELD_PREP((u8)IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK,
+ fw_ppet->ru_bit_mask);
+ cap->eht_ppe_thres[1] |= (fw_ppet->ru_bit_mask >>
+ (8 - IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_POS));
+
+ for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
+ for (ru = 0;
+ ru < hweight8(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
+ ru++) {
+ u8 val;
+ int i;
+
+ if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
+ continue;
+ val = (fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
+ 0x3f;
+ val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
+ for (i = (2 * IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE) - 1;
+ i >= 0; i--) {
+ cap->eht_ppe_thres[bit / 8] |=
+ ((val >> i) & 0x1) << ((bit % 8));
+ bit++;
+ }
+ }
+ }
+}
+
static void
ath12k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem)
{
@@ -4711,18 +4753,156 @@ static void ath12k_mac_set_hemcsmap(stru
cpu_to_le16(txmcs_map_160 & 0xffff);
}
-static int ath12k_mac_copy_he_cap(struct ath12k *ar,
- struct ath12k_pdev_cap *cap,
- struct ieee80211_sband_iftype_data *data,
- int band)
-{
+static void ath12k_mac_copy_he_cap(struct ath12k *ar,
+ struct ath12k_band_cap *band_cap,
+ struct ieee80211_sta_he_cap *he_cap,
+ struct ieee80211_he_cap_elem *he_cap_elem,
+ int iftype)
+{
+ he_cap->has_he = true;
+ memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
+ sizeof(he_cap_elem->mac_cap_info));
+ memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
+ sizeof(he_cap_elem->phy_cap_info));
+
+ he_cap_elem->mac_cap_info[1] &=
+ IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
+
+ he_cap_elem->phy_cap_info[5] &=
+ ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
+ he_cap_elem->phy_cap_info[5] &=
+ ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
+ he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
+
+ switch (iftype) {
+ case NL80211_IFTYPE_AP:
+ he_cap_elem->phy_cap_info[3] &=
+ ~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
+ he_cap_elem->phy_cap_info[9] |=
+ IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
+ break;
+ case NL80211_IFTYPE_STATION:
+ he_cap_elem->mac_cap_info[0] &= ~IEEE80211_HE_MAC_CAP0_TWT_RES;
+ he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;
+ he_cap_elem->phy_cap_info[9] |=
+ IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ ath12k_mac_filter_he_cap_mesh(he_cap_elem);
+ break;
+ }
+
+ he_cap->he_mcs_nss_supp.rx_mcs_80 =
+ cpu_to_le16(band_cap->he_mcs & 0xffff);
+ he_cap->he_mcs_nss_supp.tx_mcs_80 =
+ cpu_to_le16(band_cap->he_mcs & 0xffff);
+ he_cap->he_mcs_nss_supp.rx_mcs_160 =
+ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+ he_cap->he_mcs_nss_supp.tx_mcs_160 =
+ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+ he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
+ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+ he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
+ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+
+ ath12k_mac_set_hemcsmap(ar, &ar->pdev->cap, he_cap);
+ memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
+ if (he_cap_elem->phy_cap_info[6] &
+ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
+ ath12k_gen_ppe_thresh(&band_cap->he_ppet,
+ he_cap->ppe_thres);
+}
+
+static void ath12k_gen_eht_mcs_nss(struct ath12k_band_cap *band_cap,
+ struct ieee80211_eht_mcs_nss_supp *mcs_nss,
+ const struct ieee80211_he_cap_elem *he_cap,
+ const struct ieee80211_eht_cap_elem_fixed *eht_cap)
+{
+ if ((he_cap->phy_cap_info[0] &
+ (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0)
+ memcpy(&mcs_nss->only_20mhz, &band_cap->eht_mcs_20_only,
+ sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only));
+
+ if (he_cap->phy_cap_info[0] &
+ (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
+ memcpy(&mcs_nss->bw._80, &band_cap->eht_mcs_80,
+ sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
+
+ if (he_cap->phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
+ memcpy(&mcs_nss->bw._160, &band_cap->eht_mcs_160,
+ sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
+
+ if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
+ memcpy(&mcs_nss->bw._320, &band_cap->eht_mcs_320,
+ sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
+}
+
+static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
+ struct ath12k_band_cap *band_cap,
+ struct ieee80211_he_cap_elem *he_cap_elem,
+ struct ieee80211_sta_eht_cap *eht_cap,
+ struct ieee80211_eht_cap_elem_fixed *eht_cap_elem,
+ int iftype)
+{
+ memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));
+
+ eht_cap->has_eht = true;
+ memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,
+ sizeof(eht_cap_elem->mac_cap_info));
+ memcpy(eht_cap_elem->phy_cap_info, band_cap->eht_cap_phy_info,
+ sizeof(eht_cap_elem->phy_cap_info));
+
+ switch (iftype) {
+ case NL80211_IFTYPE_AP:
+ eht_cap_elem->phy_cap_info[0] &=
+ ~IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ;
+ eht_cap_elem->phy_cap_info[4] &=
+ ~IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO;
+ break;
+ case NL80211_IFTYPE_STATION:
+ eht_cap_elem->phy_cap_info[7] &=
+ ~(IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
+ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
+ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ);
+ eht_cap_elem->phy_cap_info[7] &=
+ ~(IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
+ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
+ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ);
+ break;
+ default:
+ break;
+ }
+
+ ath12k_gen_eht_mcs_nss(band_cap, &eht_cap->eht_mcs_nss_supp,
+ he_cap_elem, eht_cap_elem);
+
+ if (eht_cap_elem->phy_cap_info[5] &
+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT)
+ ath12k_gen_eht_ppe_thresh(&band_cap->eht_ppet, eht_cap);
+}
+
+static int ath12k_mac_copy_he_eht_cap(struct ath12k *ar,
+ struct ath12k_pdev_cap *cap,
+ struct ieee80211_sband_iftype_data *data,
+ int band)
+{
+ struct ath12k_band_cap *band_cap = &cap->band[band];
+ struct ieee80211_sta_he_cap *he_cap;
+ struct ieee80211_he_cap_elem *he_cap_elem;
+ struct ieee80211_sta_eht_cap *eht_cap;
+ struct ieee80211_eht_cap_elem_fixed *eht_cap_elem;
int i, idx = 0;
for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
- struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
- struct ath12k_band_cap *band_cap = &cap->band[band];
- struct ieee80211_he_cap_elem *he_cap_elem =
- &he_cap->he_cap_elem;
+ he_cap = &data[idx].he_cap;
+ he_cap_elem = &he_cap->he_cap_elem;
+ eht_cap = &data[idx].eht_cap;
+ eht_cap_elem = &eht_cap->eht_cap_elem;
switch (i) {
case NL80211_IFTYPE_STATION:
@@ -4735,91 +4915,40 @@ static int ath12k_mac_copy_he_cap(struct
}
data[idx].types_mask = BIT(i);
- he_cap->has_he = true;
- memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
- sizeof(he_cap_elem->mac_cap_info));
- memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
- sizeof(he_cap_elem->phy_cap_info));
-
- he_cap_elem->mac_cap_info[1] &=
- IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
- he_cap_elem->phy_cap_info[0] &=
- ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
- he_cap_elem->phy_cap_info[0] &=
- ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
- he_cap_elem->phy_cap_info[5] &=
- ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
- he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
-
- switch (i) {
- case NL80211_IFTYPE_AP:
- he_cap_elem->phy_cap_info[3] &=
- ~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
- he_cap_elem->phy_cap_info[9] |=
- IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
- break;
- case NL80211_IFTYPE_STATION:
- he_cap_elem->mac_cap_info[0] &=
- ~IEEE80211_HE_MAC_CAP0_TWT_RES;
- he_cap_elem->mac_cap_info[0] |=
- IEEE80211_HE_MAC_CAP0_TWT_REQ;
- he_cap_elem->phy_cap_info[9] |=
- IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
- break;
- case NL80211_IFTYPE_MESH_POINT:
- ath12k_mac_filter_he_cap_mesh(he_cap_elem);
- break;
- }
-
- he_cap->he_mcs_nss_supp.rx_mcs_80 =
- cpu_to_le16(band_cap->he_mcs & 0xffff);
- he_cap->he_mcs_nss_supp.tx_mcs_80 =
- cpu_to_le16(band_cap->he_mcs & 0xffff);
- he_cap->he_mcs_nss_supp.rx_mcs_160 =
- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- he_cap->he_mcs_nss_supp.tx_mcs_160 =
- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-
- ath12k_mac_set_hemcsmap(ar, &ar->pdev->cap, he_cap);
- memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
- if (he_cap_elem->phy_cap_info[6] &
- IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
- ath12k_gen_ppe_thresh(&band_cap->he_ppet,
- he_cap->ppe_thres);
+ ath12k_mac_copy_he_cap(ar, band_cap, he_cap, he_cap_elem, i);
if (band == NL80211_BAND_6GHZ) {
data[idx].he_6ghz_capa.capa =
ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
}
+ ath12k_mac_copy_eht_cap(ar, band_cap, he_cap_elem, eht_cap,
+ eht_cap_elem, i);
+
idx++;
}
return idx;
}
-static void ath12k_mac_setup_he_cap(struct ath12k *ar,
- struct ath12k_pdev_cap *cap)
+static void ath12k_mac_setup_he_eht_cap(struct ath12k *ar,
+ struct ath12k_pdev_cap *cap)
{
struct ieee80211_supported_band *band;
int count;
if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
- count = ath12k_mac_copy_he_cap(ar, cap,
- ar->mac.iftype[NL80211_BAND_2GHZ],
- NL80211_BAND_2GHZ);
+ count = ath12k_mac_copy_he_eht_cap(ar, cap,
+ ar->mac.iftype[NL80211_BAND_2GHZ],
+ NL80211_BAND_2GHZ);
band = &ar->mac.sbands[NL80211_BAND_2GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
band->n_iftype_data = count;
}
if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
- count = ath12k_mac_copy_he_cap(ar, cap,
- ar->mac.iftype[NL80211_BAND_5GHZ],
- NL80211_BAND_5GHZ);
+ count = ath12k_mac_copy_he_eht_cap(ar, cap,
+ ar->mac.iftype[NL80211_BAND_5GHZ],
+ NL80211_BAND_5GHZ);
band = &ar->mac.sbands[NL80211_BAND_5GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
band->n_iftype_data = count;
@@ -4827,9 +4956,9 @@ static void ath12k_mac_setup_he_cap(stru
if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
ar->supports_6ghz) {
- count = ath12k_mac_copy_he_cap(ar, cap,
- ar->mac.iftype[NL80211_BAND_6GHZ],
- NL80211_BAND_6GHZ);
+ count = ath12k_mac_copy_he_eht_cap(ar, cap,
+ ar->mac.iftype[NL80211_BAND_6GHZ],
+ NL80211_BAND_6GHZ);
band = &ar->mac.sbands[NL80211_BAND_6GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
band->n_iftype_data = count;
@@ -4877,7 +5006,7 @@ static int __ath12k_set_antenna(struct a
/* Reload HT/VHT/HE capability */
ath12k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
- ath12k_mac_setup_he_cap(ar, &ar->pdev->cap);
+ ath12k_mac_setup_he_eht_cap(ar, &ar->pdev->cap);
return 0;
}
@@ -7532,7 +7661,7 @@ static int __ath12k_mac_register(struct
goto err;
ath12k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
- ath12k_mac_setup_he_cap(ar, cap);
+ ath12k_mac_setup_he_eht_cap(ar, cap);
ret = ath12k_mac_setup_iface_combinations(ar);
if (ret) {
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -56,8 +56,11 @@ struct wmi_tlv_svc_rdy_ext_parse {
};
struct wmi_tlv_svc_rdy_ext2_parse {
+ struct ath12k_service_ext2_param param;
struct wmi_tlv_dma_ring_caps_parse dma_caps_parse;
bool dma_ring_cap_done;
+ bool spectral_bin_scaling_done;
+ bool mac_phy_caps_ext_done;
};
struct wmi_tlv_rdy_parse {
@@ -4202,14 +4205,125 @@ err:
return ret;
}
+static int ath12k_pull_svc_ready_ext2(struct ath12k_pdev_wmi *wmi_handle,
+ const void *ptr,
+ struct ath12k_service_ext2_param *param)
+{
+ const struct wmi_service_ready_ext2_event *ev = ptr;
+
+ if (!ev)
+ return -EINVAL;
+
+ param->reg_db_version = ev->reg_db_version;
+ param->hw_min_max_tx_power_2g = ev->hw_min_max_tx_power_2g;
+ param->hw_min_max_tx_power_5g = ev->hw_min_max_tx_power_5g;
+ param->chwidth_num_peer_caps = ev->chwidth_num_peer_caps;
+ param->preamble_puncture_bw = ev->preamble_puncture_bw;
+ param->max_user_per_ppdu_ofdma = ev->max_user_per_ppdu_ofdma;
+ param->max_user_per_ppdu_mumimo = ev->max_user_per_ppdu_mumimo;
+ param->target_cap_flags = ev->target_cap_flags;
+ return 0;
+}
+
+static int ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,
+ struct wmi_mac_phy_caps_ext *caps,
+ struct ath12k_pdev *pdev)
+{
+ struct ath12k_band_cap *cap_band;
+ struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
+
+ if (pdev_cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
+ cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
+ memcpy(cap_band->eht_cap_mac_info, &caps->eht_cap_mac_info_2G,
+ sizeof(u32) * PSOC_HOST_MAX_MAC_SIZE);
+ memcpy(cap_band->eht_cap_phy_info, &caps->eht_cap_phy_info_2G,
+ sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
+ cap_band->eht_mcs_20_only = caps->eht_supp_mcs_ext_2G[0];
+ cap_band->eht_mcs_80 = caps->eht_supp_mcs_ext_2G[1];
+ cap_band->eht_mcs_160 = 0xFFFFFFFF;
+ cap_band->eht_mcs_320 = 0xFFFFFFFF;
+ memcpy(&cap_band->eht_ppet, &caps->eht_ppet2G,
+ sizeof(struct ath12k_ppe_threshold));
+ cap_band->eht_cap_info_internal = caps->eht_cap_info_internal;
+ }
+
+ if (pdev_cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
+ cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
+ memcpy(cap_band->eht_cap_mac_info, &caps->eht_cap_mac_info_5G,
+ sizeof(u32) * PSOC_HOST_MAX_MAC_SIZE);
+ memcpy(cap_band->eht_cap_phy_info, &caps->eht_cap_phy_info_5G,
+ sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
+ cap_band->eht_mcs_20_only = caps->eht_supp_mcs_ext_5G[0];
+ cap_band->eht_mcs_80 = caps->eht_supp_mcs_ext_5G[1];
+ cap_band->eht_mcs_160 = caps->eht_supp_mcs_ext_5G[2];
+ cap_band->eht_mcs_320 = caps->eht_supp_mcs_ext_5G[3];
+ memcpy(&cap_band->eht_ppet, &caps->eht_ppet5G,
+ sizeof(struct ath12k_ppe_threshold));
+ cap_band->eht_cap_info_internal = caps->eht_cap_info_internal;
+
+ cap_band = &pdev_cap->band[NL80211_BAND_6GHZ];
+ memcpy(cap_band->eht_cap_mac_info, &caps->eht_cap_mac_info_5G,
+ sizeof(u32) * PSOC_HOST_MAX_MAC_SIZE);
+ memcpy(cap_band->eht_cap_phy_info, &caps->eht_cap_phy_info_5G,
+ sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
+ cap_band->eht_mcs_20_only = caps->eht_supp_mcs_ext_5G[0];
+ cap_band->eht_mcs_80 = caps->eht_supp_mcs_ext_5G[1];
+ cap_band->eht_mcs_160 = caps->eht_supp_mcs_ext_5G[2];
+ cap_band->eht_mcs_320 = caps->eht_supp_mcs_ext_5G[3];
+ memcpy(&cap_band->eht_ppet, &caps->eht_ppet5G,
+ sizeof(struct ath12k_ppe_threshold));
+ cap_band->eht_cap_info_internal = 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 wmi_mac_phy_caps_ext *caps = (struct wmi_mac_phy_caps_ext *)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 == caps->u.wmi_pdev_to_link_map.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_tlv_svc_rdy_ext2_parse(struct ath12k_base *ab,
u16 tag, u16 len,
const void *ptr, void *data)
{
+ struct ath12k_pdev_wmi *wmi_handle = &ab->wmi_ab.wmi[0];
struct wmi_tlv_svc_rdy_ext2_parse *parse = data;
int ret;
switch (tag) {
+ case WMI_TAG_SERVICE_READY_EXT2_EVENT:
+ ret = ath12k_pull_svc_ready_ext2(wmi_handle, ptr,
+ &parse->param);
+ if (ret) {
+ ath12k_warn(ab, "unable to extract ext params\n");
+ return ret;
+ }
+ break;
+
case WMI_TAG_ARRAY_STRUCT:
if (!parse->dma_ring_cap_done) {
ret = ath12k_wmi_tlv_dma_ring_caps(ab, len, ptr,
@@ -4218,6 +4332,22 @@ static int ath12k_wmi_tlv_svc_rdy_ext2_p
return ret;
parse->dma_ring_cap_done = true;
+ } else if (!parse->spectral_bin_scaling_done) {
+ /* To-Do: 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:
@@ -4230,7 +4360,7 @@ static int ath12k_wmi_tlv_svc_rdy_ext2_p
static int ath12k_service_ready_ext2_event(struct ath12k_base *ab,
struct sk_buff *skb)
{
- struct wmi_tlv_svc_rdy_ext2_parse svc_rdy_ext2 = { };
+ struct wmi_tlv_svc_rdy_ext2_parse svc_rdy_ext2 = { 0 };
int ret;
ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -1831,6 +1831,7 @@ enum wmi_tlv_tag {
/* TODO add all the missing cmds */
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301,
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO,
+ WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334,
WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F,
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
@@ -2160,7 +2161,6 @@ struct ath12k_ppe_threshold {
u32 ru_bit_mask;
u32 ppet16_ppet8_ru3_ru0[PSOC_HOST_MAX_NUM_SS];
};
-
struct ath12k_service_ext_param {
u32 default_conc_scan_config_bits;
u32 default_fw_config_bits;
@@ -2178,6 +2178,7 @@ struct ath12k_hw_mode_caps {
u32 hw_mode_config_type;
};
+#define PSOC_HOST_MAX_MAC_SIZE (2)
#define PSOC_HOST_MAX_PHY_SIZE (3)
#define ATH12K_11B_SUPPORT BIT(0)
#define ATH12K_11G_SUPPORT BIT(1)
@@ -2199,6 +2200,32 @@ struct ath12k_hal_reg_capabilities_ext {
u32 high_5ghz_chan;
};
+#define WMI_MAX_EHTCAP_MAC_SIZE 2
+#define WMI_MAX_EHTCAP_PHY_SIZE 3
+
+/*
+ * 0 index indicated EHT-MCS map for 20Mhz only sta (4 bytes valid)
+ * 1 index for <= 80MHz bw (only 3 bytes are valid and other is reserved)
+ * 2 index for == 160Mhz bw (only 3 bytes are valid and other is reserved)
+ * 3 index for == 320Mhz bw (only 3 bytes are valid and other is reserved)
+ */
+#define WMI_MAX_EHT_SUPP_MCS_2G_SIZE 2
+#define WMI_MAX_EHT_SUPP_MCS_5G_SIZE 4
+
+struct ath12k_service_ext2_param {
+ u32 reg_db_version;
+ u32 hw_min_max_tx_power_2g;
+ u32 hw_min_max_tx_power_5g;
+ u32 chwidth_num_peer_caps;
+ u32 preamble_puncture_bw;
+ u32 max_user_per_ppdu_ofdma;
+ u32 max_user_per_ppdu_mumimo;
+ u32 target_cap_flags;
+ u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];
+ u32 max_num_linkview_peers;
+ u32 max_num_msduq_supported_per_tid;
+};
+
#define WMI_HOST_MAX_PDEV 3
struct wlan_host_mem_chunk {
@@ -2469,6 +2496,65 @@ struct wmi_soc_hal_reg_capabilities {
u32 num_phy;
} __packed;
+struct wmi_service_ready_ext2_event {
+ u32 reg_db_version;
+ u32 hw_min_max_tx_power_2g;
+ u32 hw_min_max_tx_power_5g;
+ u32 chwidth_num_peer_caps;
+ u32 preamble_puncture_bw;
+ u32 max_user_per_ppdu_ofdma;
+ u32 max_user_per_ppdu_mumimo;
+ u32 target_cap_flags;
+ u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];
+ u32 max_num_linkview_peers;
+ u32 max_num_msduq_supported_per_tid;
+ u32 default_num_msduq_supported_per_tid;
+} __packed;
+
+enum wmi_spectral_scaling_formula_id {
+ NO_SCALING = 0,
+ AGC_GAIN_RSSI_CORR_BASED = 1,
+};
+
+struct wmi_spectral_bin_scaling {
+ u32 pdev_id;
+ enum wmi_spectral_scaling_formula_id formula_id;
+ u32 low_level_offset;
+ u32 high_level_offset;
+ u32 rssi_thr;
+ u32 default_agc_max_gain;
+} __packed;
+
+enum wmi_eht_mcs_support {
+ WMI_EHT_MCS_SUPPORT_0_9 = 0,
+ WMI_EHT_MCS_SUPPORT_0_11 = 1,
+ WMI_EHT_MCS_SUPPORT_0_13 = 2,
+ WMI_EHT_MCS_NOT_SUPPORTED = 3,
+};
+
+struct wmi_mac_phy_caps_ext {
+ u32 hw_mode_id;
+ union {
+ struct {
+ u32 pdev_id:16,
+ hw_link_id:16;
+ } wmi_pdev_to_link_map;
+ u32 pdev_id;
+ } u;
+ u32 phy_id;
+ u32 wireless_modes_ext;
+ u32 eht_cap_mac_info_2G[WMI_MAX_EHTCAP_MAC_SIZE];
+ u32 eht_cap_mac_info_5G[WMI_MAX_EHTCAP_MAC_SIZE];
+ u32 rsvd0[2];
+ u32 eht_cap_phy_info_2G[WMI_MAX_EHTCAP_PHY_SIZE];
+ u32 eht_cap_phy_info_5G[WMI_MAX_EHTCAP_PHY_SIZE];
+ struct wmi_ppe_threshold eht_ppet2G;
+ struct wmi_ppe_threshold eht_ppet5G;
+ u32 eht_cap_info_internal;
+ u32 eht_supp_mcs_ext_2G[WMI_MAX_EHT_SUPP_MCS_2G_SIZE];
+ u32 eht_supp_mcs_ext_5G[WMI_MAX_EHT_SUPP_MCS_5G_SIZE];
+} __packed;
+
/* 2 word representation of MAC addr */
struct wmi_mac_addr {
union {