diff mbox series

[v4,03/11] wifi: ath12k: WMI support to process EHT capabilities

Message ID 20230602235820.23912-4-quic_alokad@quicinc.com (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show
Series wifi: ath12k: (v4) EHT support | expand

Commit Message

Aloka Dixit June 2, 2023, 11:58 p.m. UTC
Add WMI support to process the EHT capabilities passed by
the firmware. Add required EHT specific definitions in
structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse.

For single_pdev chip such as WCN7850, only one pdev is created
and only one hardware is registered to mac80211. This one pdev
manages both 2.4 GHz radio and 5 GHz/6 GHz radio.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
Co-developed-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Co-developed-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
---
v4: Add support for WCN7850.
v3: No change from v2.
v2: Changed 'target' to 'firmware' in the description.

 drivers/net/wireless/ath/ath12k/core.h |  16 +++
 drivers/net/wireless/ath/ath12k/wmi.c  | 147 +++++++++++++++++++++++++
 drivers/net/wireless/ath/ath12k/wmi.h  |  38 +++++++
 3 files changed, 201 insertions(+)

Comments

Kalle Valo June 15, 2023, 11:49 a.m. UTC | #1
Aloka Dixit <quic_alokad@quicinc.com> writes:

> Add WMI support to process the EHT capabilities passed by
> the firmware. Add required EHT specific definitions in
> structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse.
>
> For single_pdev chip such as WCN7850, only one pdev is created
> and only one hardware is registered to mac80211. This one pdev
> manages both 2.4 GHz radio and 5 GHz/6 GHz radio.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
> Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
> Co-developed-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
> Co-developed-by: Wen Gong <quic_wgong@quicinc.com>
> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>

[...]

> +struct ath12k_fw_pdev {
> +	u32 pdev_id;
> +	u32 phy_id;
> +	u32 supported_bands;
> +};

So we have now two very similar structures, ath12k_pdev and
ath12k_fw_pdev. It would be good to document above the structs their
purpose. Any ideas what I could add?
Wen Gong June 16, 2023, 10:50 a.m. UTC | #2
On 6/15/2023 7:49 PM, Kalle Valo wrote:
> Aloka Dixit <quic_alokad@quicinc.com> writes:
>
>> Add WMI support to process the EHT capabilities passed by
>> the firmware. Add required EHT specific definitions in
>> structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse.
>>
>> For single_pdev chip such as WCN7850, only one pdev is created
>> and only one hardware is registered to mac80211. This one pdev
>> manages both 2.4 GHz radio and 5 GHz/6 GHz radio.
>>
>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
>> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
>> Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
>> Co-developed-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
>> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
>> Co-developed-by: Wen Gong <quic_wgong@quicinc.com>
>> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
> [...]
>
>> +struct ath12k_fw_pdev {
>> +	u32 pdev_id;
>> +	u32 phy_id;
>> +	u32 supported_bands;
>> +};
> So we have now two very similar structures, ath12k_pdev and
> ath12k_fw_pdev. It would be good to document above the structs their
> purpose. Any ideas what I could add?

For single_pdev, the ath12k_pdev is always one pdev.

and ath12k_fw_pdev is more than one for single_pdev.

>
Aloka Dixit July 24, 2023, 5:42 p.m. UTC | #3
On 6/16/2023 3:50 AM, Wen Gong wrote:
> On 6/15/2023 7:49 PM, Kalle Valo wrote:
>> Aloka Dixit <quic_alokad@quicinc.com> writes:
>>
>>> Add WMI support to process the EHT capabilities passed by
>>> the firmware. Add required EHT specific definitions in
>>> structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse.
>>>
>>> For single_pdev chip such as WCN7850, only one pdev is created
>>> and only one hardware is registered to mac80211. This one pdev
>>> manages both 2.4 GHz radio and 5 GHz/6 GHz radio.
>>>
>>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
>>> Tested-on: WCN7850 hw2.0 PCI 
>>> WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
>>> Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
>>> Co-developed-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
>>> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
>>> Co-developed-by: Wen Gong <quic_wgong@quicinc.com>
>>> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
>> [...]
>>
>>> +struct ath12k_fw_pdev {
>>> +    u32 pdev_id;
>>> +    u32 phy_id;
>>> +    u32 supported_bands;
>>> +};
>> So we have now two very similar structures, ath12k_pdev and
>> ath12k_fw_pdev. It would be good to document above the structs their
>> purpose. Any ideas what I could add?
> 
> For single_pdev, the ath12k_pdev is always one pdev.
> 
> and ath12k_fw_pdev is more than one for single_pdev.
> 
>>

Okay will add a comment in the next version.
Wen Gong July 25, 2023, 10:51 a.m. UTC | #4
On 6/15/2023 7:49 PM, Kalle Valo wrote:
> Aloka Dixit <quic_alokad@quicinc.com> writes:
>
[...]
> [...]
>
>> +struct ath12k_fw_pdev {
>> +	u32 pdev_id;
>> +	u32 phy_id;
>> +	u32 supported_bands;
>> +};
> So we have now two very similar structures, ath12k_pdev and
> ath12k_fw_pdev. It would be good to document above the structs their
> purpose. Any ideas what I could add?
Currently ath12k has single_pdev parameter, it impact the interface 
number of wifi.

For single_pdev=ture, ab->num_radios is set to 1 and all capbility of 
2.4 GHz/
5 GHz/6 GHz is saved into ab->pdevs[0] in 
ath12k_wmi_ext_soc_hal_reg_caps_parse().
ath12k_mac_register() will call only one time into 
__ath12k_mac_register(), and
ieee80211_register_hw() is called only one time, and only one wifi 
interface in
the result of "iw dev/ifconfig", the interface support 2.4 GHz/5 GHz/6 
GHz. Actually
there hare more than one PHY in firmware, firmware maintain the all PHY 
data and
provide a single pdev/soc interface to ath12k, then ath12k do not need 
to consider
the PHY info such as channel/BAND<->PHY mapping relationship, it is 
convenient for
ath12k to support 2.4 GHz/5 GHz/6 GHz.

For single_pdev=false, ab->num_radios is more than 1, ab->pdevs[] has 
muti valid
element, each element only support one BAND. Firmware do not provide a 
single
pdev/soc interface, so ath12k need to maintain the PHY data such as 
channel/BAND<->
PHY mapping relationship, and ath12k_mac_register() will call muti-time 
into
__ath12k_mac_register(), and ieee80211_register_hw() is called 
muti-time, and muti
wifi interface in the result of "iw dev/ifconfig", and each interface 
only support
one BAND, for example, wlan0 only support 2.4 GHz, wlan1 only support 5 
GHz, and
wlan2 only support 6 GHz.

For single_pdev=ture, ath12k also need to know some info about the PHYs 
sush as
pdev_id/phy_id/supported_bands in this patch, so ab->fw_pdev is used to 
store the
PHY data.
Aloka Dixit July 25, 2023, 7:44 p.m. UTC | #5
On 7/25/2023 3:51 AM, Wen Gong wrote:
> On 6/15/2023 7:49 PM, Kalle Valo wrote:
>> Aloka Dixit <quic_alokad@quicinc.com> writes:
>>
> [...]
>> [...]
>>
>>> +struct ath12k_fw_pdev {
>>> +    u32 pdev_id;
>>> +    u32 phy_id;
>>> +    u32 supported_bands;
>>> +};
>> So we have now two very similar structures, ath12k_pdev and
>> ath12k_fw_pdev. It would be good to document above the structs their
>> purpose. Any ideas what I could add?
> Currently ath12k has single_pdev parameter, it impact the interface 
> number of wifi.
> 
> For single_pdev=ture, ab->num_radios is set to 1 and all capbility of 
> 2.4 GHz/
> 5 GHz/6 GHz is saved into ab->pdevs[0] in 
> ath12k_wmi_ext_soc_hal_reg_caps_parse().
> ath12k_mac_register() will call only one time into 
> __ath12k_mac_register(), and
> ieee80211_register_hw() is called only one time, and only one wifi 
> interface in
> the result of "iw dev/ifconfig", the interface support 2.4 GHz/5 GHz/6 
> GHz. Actually
> there hare more than one PHY in firmware, firmware maintain the all PHY 
> data and
> provide a single pdev/soc interface to ath12k, then ath12k do not need 
> to consider
> the PHY info such as channel/BAND<->PHY mapping relationship, it is 
> convenient for
> ath12k to support 2.4 GHz/5 GHz/6 GHz.
> 
> For single_pdev=false, ab->num_radios is more than 1, ab->pdevs[] has 
> muti valid
> element, each element only support one BAND. Firmware do not provide a 
> single
> pdev/soc interface, so ath12k need to maintain the PHY data such as 
> channel/BAND<->
> PHY mapping relationship, and ath12k_mac_register() will call muti-time 
> into
> __ath12k_mac_register(), and ieee80211_register_hw() is called 
> muti-time, and muti
> wifi interface in the result of "iw dev/ifconfig", and each interface 
> only support
> one BAND, for example, wlan0 only support 2.4 GHz, wlan1 only support 5 
> GHz, and
> wlan2 only support 6 GHz.
> 
> For single_pdev=ture, ath12k also need to know some info about the PHYs 
> sush as
> pdev_id/phy_id/supported_bands in this patch, so ab->fw_pdev is used to 
> store the
> PHY data.


The new struct ath12k_fw_pdev is anyway going to have as many elements 
as the num_radio, right? Then there must be a way to reuse the common 
struct ath12k_pdev instead as it done for QCN devices. I understand this 
it will need changes to all the existing code for the single-pdev where 
it might have hard-coded pdev[0] for the original structure. Something 
to think about in a separate patch-set.

For now I will send new version with comments (as far as I understood 
it) because without this patch WCN devices show a crash during boot-up.

Thanks.
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 2f93296db792..df762cabacc2 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -580,6 +580,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 {
@@ -638,6 +646,12 @@  struct ath12k_soc_dp_stats {
 	struct ath12k_soc_dp_tx_err_stats tx_err;
 };
 
+struct ath12k_fw_pdev {
+	u32 pdev_id;
+	u32 phy_id;
+	u32 supported_bands;
+};
+
 /* Master structure to hold the hw data which may be used in core module */
 struct ath12k_base {
 	enum ath12k_hw_rev hw_rev;
@@ -670,6 +684,8 @@  struct ath12k_base {
 	/* Protects data like peers */
 	spinlock_t base_lock;
 	struct ath12k_pdev pdevs[MAX_RADIOS];
+	struct ath12k_fw_pdev fw_pdev[MAX_RADIOS];
+	u8 fw_pdev_count;
 	struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS];
 	struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS];
 	unsigned long long free_vdev_map;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 6512267ae4ca..7b82e7240594 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.
@@ -3811,6 +3821,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,
@@ -4038,6 +4049,126 @@  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)
+{
+	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)
+{
+	struct ath12k_wmi_mac_phy_caps_ext_params *caps =
+			(struct ath12k_wmi_mac_phy_caps_ext_params *)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 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)
@@ -4054,6 +4185,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 d89c12bfb009..b722eab281c3 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2581,6 +2581,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];