diff mbox series

[v4,06/11] wifi: ath12k: prepare EHT peer assoc parameters

Message ID 20230602235820.23912-7-quic_alokad@quicinc.com
State Superseded
Headers show
Series wifi: ath12k: (v4) EHT support | expand

Commit Message

Aloka Dixit June 2, 2023, 11:58 p.m. UTC
Add new parameters and prepare the association data for an EHT peer.
MCS data uses the format described in IEEE P802.11be/D2.0, May 2022,
9.4.2.313.4, convert it into the format expected by the firmware.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
---
v4: No change from v3.
v3: Incremented peer_eht_mcs_count for IEEE80211_STA_RX_BW_160 in
ath12k_peer_assoc_h_eht().
v2: No change from v1.

 drivers/net/wireless/ath/ath12k/mac.c | 145 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath12k/wmi.h |  17 +++
 2 files changed, 162 insertions(+)

Comments

Wen Gong July 24, 2023, 10:16 a.m. UTC | #1
On 6/3/2023 7:58 AM, Aloka Dixit wrote:
> ...
> +	default:
> +		if (arg->peer_phymode == MODE_11BE_EHT20) {
> +			const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20 =
> +					&eht_cap->eht_mcs_nss_supp.only_20mhz;

When ath12k used as station mode, it entered here as well as AP mode.

But remote is AP device for station mode, then remote AP device do not 
have the only_20mhz data(EHT-MCS Map (20 MHz-Only Non-AP STA)).

Also 20 MHz should be same for 5 GHz/6 GHz(MODE_11BE_EHT20) and 2.4 
GHz(MODE_11BE_EHT20_2G), right?

> +
> +			ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss,
> +					       bw_20->rx_tx_mcs9_max_nss,
> +					       bw_20->rx_tx_mcs11_max_nss,
> +					       bw_20->rx_tx_mcs13_max_nss,
> +					       &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
> +					       &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
> +		} else {
> +			bw = &eht_cap->eht_mcs_nss_supp.bw._80;
> +			ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
> +					       bw->rx_tx_mcs9_max_nss,
> +					       bw->rx_tx_mcs11_max_nss,
> +					       bw->rx_tx_mcs13_max_nss,
> +					       &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
> +					       &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
> +		}
> +
> +		arg->peer_eht_mcs_count++;
> +		break;
> +	}
> +}
> +

...
Aloka Dixit July 24, 2023, 6:24 p.m. UTC | #2
On 7/24/2023 3:16 AM, Wen Gong wrote:
> On 6/3/2023 7:58 AM, Aloka Dixit wrote:
>> ...
>> +    default:
>> +        if (arg->peer_phymode == MODE_11BE_EHT20) {
>> +            const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20 =
>> +                    &eht_cap->eht_mcs_nss_supp.only_20mhz;
> 
> When ath12k used as station mode, it entered here as well as AP mode.
> 
> But remote is AP device for station mode, then remote AP device do not 
> have the only_20mhz data(EHT-MCS Map (20 MHz-Only Non-AP STA)).
> 

What issue are you seeing? Please elaborate.

The default case will be entered for both AP and non-AP STA modes for 
all bandwidths.

If the device is a 20-MHz-only device, it will skip 320, 160 and 
directly enter the default case where 'if' condition will be true.

If the device is not a 20-MHZ-only device then it will enter the 'else' 
condition after processing 320 and 160 as applicable.

> Also 20 MHz should be same for 5 GHz/6 GHz(MODE_11BE_EHT20) and 2.4 
> GHz(MODE_11BE_EHT20_2G), right?
> 

Good point, I will add a check for MODE_11BE_EHT20_2G as well here.

>> +
>> +            ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss,
>> +                           bw_20->rx_tx_mcs9_max_nss,
>> +                           bw_20->rx_tx_mcs11_max_nss,
>> +                           bw_20->rx_tx_mcs13_max_nss,
>> +                           &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
>> +                           &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
>> +        } else {
>> +            bw = &eht_cap->eht_mcs_nss_supp.bw._80;
>> +            ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
>> +                           bw->rx_tx_mcs9_max_nss,
>> +                           bw->rx_tx_mcs11_max_nss,
>> +                           bw->rx_tx_mcs13_max_nss,
>> +                           &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
>> +                           &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
>> +        }
>> +
>> +        arg->peer_eht_mcs_count++;
>> +        break;
>> +    }
>> +}
>> +
> 
> ...
Wen Gong July 25, 2023, 10:07 a.m. UTC | #3
On 7/25/2023 2:24 AM, Aloka Dixit wrote:
> On 7/24/2023 3:16 AM, Wen Gong wrote:
>> On 6/3/2023 7:58 AM, Aloka Dixit wrote:
>>> ...
>>> +    default:
>>> +        if (arg->peer_phymode == MODE_11BE_EHT20) {
>>> +            const struct ieee80211_eht_mcs_nss_supp_20mhz_only 
>>> *bw_20 =
>>> + &eht_cap->eht_mcs_nss_supp.only_20mhz;
>>
>> When ath12k used as station mode, it entered here as well as AP mode.
>>
>> But remote is AP device for station mode, then remote AP device do 
>> not have the only_20mhz data(EHT-MCS Map (20 MHz-Only Non-AP STA)).
>>
>
> What issue are you seeing? Please elaborate.
>
> The default case will be entered for both AP and non-AP STA modes for 
> all bandwidths.
>
> If the device is a 20-MHz-only device, it will skip 320, 160 and 
> directly enter the default case where 'if' condition will be true.
>
> If the device is not a 20-MHZ-only device then it will enter the 
> 'else' condition after processing 320 and 160 as applicable.
When I configured AP with 11BE-EHT mode for 20 MHz bandwidth on 5 GHz/6 
GHz band,
and then connect to the AP with ath12k for station mode. Then the 
peer_phymode
is MODE_11BE_EHT20, and then ath12k entered the default in function
ath12k_peer_assoc_h_eht() and use the bw_20 which is assigned with
eht_cap->eht_mcs_nss_supp.only_20mhz.

For station mode of ath12k, the eht_cap->eht_mcs_nss_supp is from the IE 
"Supported
EHT-MCS and NSS Set" in assoc resp of AP in function 
ieee80211_eht_cap_ie_to_sta_eht_cap().
Now it is "EHT-MCS Map (BW <= 80MHz): 0x222222" for the AP(11BE-EHT mode 
for 20 MHz
bandwidth on 6 GHz band) in my test as below IEs.

The field only_20mhz and field _80 are union in struct 
ieee80211_eht_mcs_nss_supp, the
value of field _80 is 0x222222 for this AP, then the value of field 
only_20mhz is like this:
rx_tx_mcs7_max_nss=0x22,
rx_tx_mcs9_max_nss=0x22,
rx_tx_mcs11_max_nss=0x22,
rx_tx_mcs13_max_nss=0.

Then ath12k_mac_set_eht_mcs() will get value 0 fro mcs13 because it used 
the field only_20mhz
passed by ath12k_peer_assoc_h_eht().

ieee80211_eht_cap_ie_to_sta_eht_cap()
{
...
     /* Copy MCS/NSS which depends on the peer capabilities */
     memset(&eht_cap->eht_mcs_nss_supp, 0,
            sizeof(eht_cap->eht_mcs_nss_supp));
     memcpy(&eht_cap->eht_mcs_nss_supp, pos, mcs_nss_size);
...
}

struct ieee80211_eht_mcs_nss_supp {
     union {
         struct ieee80211_eht_mcs_nss_supp_20mhz_only only_20mhz;
         struct {
             struct ieee80211_eht_mcs_nss_supp_bw _80;
             struct ieee80211_eht_mcs_nss_supp_bw _160;
             struct ieee80211_eht_mcs_nss_supp_bw _320;
         } __packed bw;
     } __packed;
} __packed;

struct ieee80211_eht_mcs_nss_supp_20mhz_only {
     u8 rx_tx_mcs7_max_nss;
     u8 rx_tx_mcs9_max_nss;
     u8 rx_tx_mcs11_max_nss;
     u8 rx_tx_mcs13_max_nss;
};

struct ieee80211_eht_mcs_nss_supp_bw {
     u8 rx_tx_mcs9_max_nss;
     u8 rx_tx_mcs11_max_nss;
     u8 rx_tx_mcs13_max_nss;
};


IEs of the AP:
Ext Tag: HE Capabilities (IEEE Std 802.11ax/D3.0)
     Tag Number: Element ID Extension (255)
     Ext Tag length: 29
     Ext Tag Number: HE Capabilities (IEEE Std 802.11ax/D3.0) (35)
     HE MAC Capabilities Information: 0x10401a08010d
     HE Phy Capabilities Information
         .... ...0 = Reserved: 0x0
         0000 000. = Channel Width Set: 0x00
             .... ..0. = 40MHz in 2.4GHz band: Not supported
             .... .0.. = 40 & 80MHz in the 5GHz or 6GHz band: Not 
supported //20 MHz
             .... 0... = 160MHz in the 5GHz or 6GHz band: Not supported
             ...0 .... = 160/80+80MHz in the 5GHz or 6GHz band: Not 
supported
             ..0. .... = 242 tone RUs in the 2.4GHz band: Not supported
             .0.. .... = 242 tone RUs in the 5GHz or 6GHz band: Not 
supported
             0... .... = Reserved: 0x0
         Bits 8 to 23: 0x4063
         Bits 24 to 39: 0x1f88
         Bits 40 to 55: 0x8141
         Bits 56 to 71: 0x111c
         Bits 72 to 87: 0x0008
     Supported HE-MCS and NSS Set
     PPE Thresholds
Ext Tag: HE Operation (IEEE Std 802.11ax/D3.0)
     Tag Number: Element ID Extension (255)
     Ext Tag length: 12
     Ext Tag Number: HE Operation (IEEE Std 802.11ax/D3.0) (36)
     HE Operation Parameters: 0x023ff4
     BSS Color Information: 0x0c
     Basic HE-MCS and NSS Set: 0xfffc
     6GHz Operation Information
         Primary Channel: 37
         6GHz Operation Information Control Field
             .... ..00 = Channel Width: 20 MHz (0) //20 MHz
             .... .0.. = Duplicate Beacon: False
             0000 0... = Reserved: 0x00
         Channel Center Frequency Segment0: 37
         Channel Center Frequency Segment1: 0
         Minimum rate: 1
Ext Tag: EHT Capabilities (IEEE Std 802.11be/D2.0)
     Tag Number: Element ID Extension (255)
     Ext Tag length: 15
     Ext Tag Number: EHT Capabilities (IEEE Std 802.11be/D2.0) (108)
     EHT MAC Capabilities Information: 0x0000
     EHT PHY Capabilities Information
     Supported EHT-MCS and NSS Set
         EHT-MCS Map (BW <= 80MHz): 0x222222
             .... .... .... .... .... 0010 = Rx Max Nss That Supports 
EHT-MCS 0-9: 2
             .... .... .... .... 0010 .... = Tx Max Nss That Supports 
EHT-MCS 0-9: 2
             .... .... .... 0010 .... .... = Rx Max Nss That Supports 
EHT-MCS 10-11: 2
             .... .... 0010 .... .... .... = Tx Max Nss That Supports 
EHT-MCS 10-11: 2
             .... 0010 .... .... .... .... = Rx Max Nss That Supports 
EHT-MCS 12-13: 2
             0010 .... .... .... .... .... = Tx Max Nss That Supports 
EHT-MCS 12-13: 2
     EHT PPE Thresholds: <MISSING>


call stack of ieee80211_eht_cap_ie_to_sta_eht_cap():
RIP: 0010:ieee80211_eht_cap_ie_to_sta_eht_cap+0x5a/0x110 [mac80211]
[86593.088253] RSP: 0018:ffffb5fcc1f8f990 EFLAGS: 00010206
[86593.088254] RAX: 0000000000000000 RBX: ffff8c45c2fd6b70 RCX: 
0000000000000000
[86593.088256] RDX: ffff8c45c2fd710e RSI: ffff8c44cba0a408 RDI: 
ffff8c45c2fd6c30
[86593.088257] RBP: ffffb5fcc1f8f9c8 R08: ffff8c45c2fd7147 R09: 
000000000000000e
[86593.088258] R10: ffff8c44cba0a408 R11: ffff8c45c2fd6bd8 R12: 
ffff8c45cd0989c0
[86593.088259] R13: 0000000000000000 R14: ffff8c45c2fd7147 R15: 
ffff8c45c8198000
[86593.088261] FS:  0000000000000000(0000) GS:ffff8c46d6200000(0000) 
knlGS:0000000000000000
[86593.088262] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[86593.088264] CR2: 0000032d89c60000 CR3: 000000000800a006 CR4: 
00000000001706f0
[86593.088265] Call Trace:
[86593.088267]  <TASK>
[86593.088270]  ieee80211_rx_mgmt_assoc_resp.cold+0xed8/0x1b9b [mac80211]
[86593.088336]  ieee80211_sta_rx_queued_mgmt+0x351/0xdd0 [mac80211]
[86593.088394]  ? newidle_balance+0x252/0x410
[86593.088399]  ? dequeue_entity+0x125/0x400
[86593.088402]  ? preempt_count_add+0x7c/0xc0
[86593.088406]  ? _raw_spin_lock_irqsave+0x28/0x60
[86593.088410]  ieee80211_iface_work+0x30a/0x410 [mac80211]
[86593.088459]  ? __schedule+0x319/0x9b0
[86593.088461]  process_one_work+0x227/0x440
[86593.088465]  worker_thread+0x31/0x3e0
[86593.088467]  ? process_one_work+0x440/0x440
[86593.088469]  kthread+0xfe/0x130
[86593.088471]  ? kthread_complete_and_exit+0x20/0x20
[86593.088473]  ret_from_fork+0x22/0x30
[86593.088479]  </TASK>

>
>> Also 20 MHz should be same for 5 GHz/6 GHz(MODE_11BE_EHT20) and 2.4 
>> GHz(MODE_11BE_EHT20_2G), right?
>>
>
> Good point, I will add a check for MODE_11BE_EHT20_2G as well here.
>
>>> +
>>> + ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss,
>>> +                           bw_20->rx_tx_mcs9_max_nss,
>>> +                           bw_20->rx_tx_mcs11_max_nss,
>>> +                           bw_20->rx_tx_mcs13_max_nss,
>>> + &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
>>> + &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
>>> +        } else {
>>> +            bw = &eht_cap->eht_mcs_nss_supp.bw._80;
>>> +            ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
>>> +                           bw->rx_tx_mcs9_max_nss,
>>> +                           bw->rx_tx_mcs11_max_nss,
>>> +                           bw->rx_tx_mcs13_max_nss,
>>> + &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
>>> + &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
>>> +        }
>>> +
>>> +        arg->peer_eht_mcs_count++;
>>> +        break;
>>> +    }
>>> +}
>>> +
>>
>> ...
>
Aloka Dixit July 25, 2023, 10:44 p.m. UTC | #4
On 7/25/2023 3:07 AM, Wen Gong wrote:
> 
> For station mode of ath12k, the eht_cap->eht_mcs_nss_supp is from the IE 
> "Supported
> EHT-MCS and NSS Set" in assoc resp of AP in function 
> ieee80211_eht_cap_ie_to_sta_eht_cap().
> Now it is "EHT-MCS Map (BW <= 80MHz): 0x222222" for the AP(11BE-EHT mode 
> for 20 MHz
> bandwidth on 6 GHz band) in my test as below IEs.
> 
> The field only_20mhz and field _80 are union in struct 
> ieee80211_eht_mcs_nss_supp, the
> value of field _80 is 0x222222 for this AP, then the value of field 
> only_20mhz is like this:
> rx_tx_mcs7_max_nss=0x22,
> rx_tx_mcs9_max_nss=0x22,
> rx_tx_mcs11_max_nss=0x22,
> rx_tx_mcs13_max_nss=0.
> 
> Then ath12k_mac_set_eht_mcs() will get value 0 fro mcs13 because it used 
> the field only_20mhz
> passed by ath12k_peer_assoc_h_eht().
> 

Understood, I fixed the default case to check for the he_cap field for 
the bandwidth support instead of peer_phymode in v5.
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 4f61c8993c87..446a0db67516 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -2064,6 +2064,150 @@  static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
 	WARN_ON(phymode == MODE_UNKNOWN);
 }
 
+static void ath12k_mac_set_eht_mcs(u8 rx_tx_mcs7, u8 rx_tx_mcs9,
+				   u8 rx_tx_mcs11, u8 rx_tx_mcs13,
+				   u32 *rx_mcs, u32 *tx_mcs)
+{
+	*rx_mcs = 0;
+	u32p_replace_bits(rx_mcs,
+			  u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_RX),
+			  WMI_EHT_MCS_NSS_0_7);
+	u32p_replace_bits(rx_mcs,
+			  u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_RX),
+			  WMI_EHT_MCS_NSS_8_9);
+	u32p_replace_bits(rx_mcs,
+			  u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_RX),
+			  WMI_EHT_MCS_NSS_10_11);
+	u32p_replace_bits(rx_mcs,
+			  u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_RX),
+			  WMI_EHT_MCS_NSS_12_13);
+
+	*tx_mcs = 0;
+	u32p_replace_bits(tx_mcs,
+			  u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_TX),
+			  WMI_EHT_MCS_NSS_0_7);
+	u32p_replace_bits(tx_mcs,
+			  u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_TX),
+			  WMI_EHT_MCS_NSS_8_9);
+	u32p_replace_bits(tx_mcs,
+			  u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_TX),
+			  WMI_EHT_MCS_NSS_10_11);
+	u32p_replace_bits(tx_mcs,
+			  u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_TX),
+			  WMI_EHT_MCS_NSS_12_13);
+}
+
+static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres,
+					     struct ath12k_wmi_ppe_threshold_arg *ppet)
+{
+	u32 bit_pos = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE;
+	u8 nss;
+
+	ppet->numss_m1 = u8_get_bits(ppe_thres[0], IEEE80211_EHT_PPE_THRES_NSS_MASK);
+	ppet->ru_bit_mask = u16_get_bits(get_unaligned_le16(ppe_thres),
+					 IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
+
+	for (nss = 0; nss <= ppet->numss_m1; nss++) {
+		u8 ru;
+
+		for (ru = 0;
+		     ru < hweight8(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
+		     ru++) {
+			u32 val = 0;
+			u8 i;
+
+			if ((ppet->ru_bit_mask & BIT(ru)) == 0)
+				continue;
+
+			for (i = 0;
+			     i < IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE;
+			     i++) {
+				val >>= 1;
+				val |= ((ppe_thres[bit_pos / 8] >>
+					 (bit_pos % 8)) & 0x1) << 5;
+				bit_pos++;
+			}
+			ppet->ppet16_ppet8_ru3_ru0[nss] |=
+				(val <<
+				 (ru * IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE));
+		}
+	}
+}
+
+static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_sta *sta,
+				    struct ath12k_wmi_peer_assoc_arg *arg)
+{
+	const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
+	const struct ieee80211_eht_mcs_nss_supp_bw *bw;
+	u32 *rx_mcs, *tx_mcs;
+
+	if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
+		return;
+
+	arg->eht_flag = true;
+	if ((eht_cap->eht_cap_elem.phy_cap_info[5] &
+	     IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) &&
+	    eht_cap->eht_ppe_thres[0] != 0)
+		ath12k_mac_set_eht_ppe_threshold(eht_cap->eht_ppe_thres,
+						 &arg->peer_eht_ppet);
+	memcpy(arg->peer_eht_cap_mac, eht_cap->eht_cap_elem.mac_cap_info,
+	       sizeof(eht_cap->eht_cap_elem.mac_cap_info));
+	memcpy(arg->peer_eht_cap_phy, eht_cap->eht_cap_elem.phy_cap_info,
+	       sizeof(eht_cap->eht_cap_elem.phy_cap_info));
+
+	rx_mcs = arg->peer_eht_rx_mcs_set;
+	tx_mcs = arg->peer_eht_tx_mcs_set;
+	switch (sta->deflink.bandwidth) {
+	case IEEE80211_STA_RX_BW_320:
+		bw = &eht_cap->eht_mcs_nss_supp.bw._320;
+		ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
+				       bw->rx_tx_mcs9_max_nss,
+				       bw->rx_tx_mcs11_max_nss,
+				       bw->rx_tx_mcs13_max_nss,
+				       &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320],
+				       &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320]);
+		arg->peer_eht_mcs_count++;
+		fallthrough;
+
+	case IEEE80211_STA_RX_BW_160:
+		bw = &eht_cap->eht_mcs_nss_supp.bw._160;
+		ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
+				       bw->rx_tx_mcs9_max_nss,
+				       bw->rx_tx_mcs11_max_nss,
+				       bw->rx_tx_mcs13_max_nss,
+				       &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160],
+				       &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160]);
+		arg->peer_eht_mcs_count++;
+		fallthrough;
+
+	default:
+		if (arg->peer_phymode == MODE_11BE_EHT20) {
+			const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20 =
+					&eht_cap->eht_mcs_nss_supp.only_20mhz;
+
+			ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss,
+					       bw_20->rx_tx_mcs9_max_nss,
+					       bw_20->rx_tx_mcs11_max_nss,
+					       bw_20->rx_tx_mcs13_max_nss,
+					       &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
+					       &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
+		} else {
+			bw = &eht_cap->eht_mcs_nss_supp.bw._80;
+			ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
+					       bw->rx_tx_mcs9_max_nss,
+					       bw->rx_tx_mcs11_max_nss,
+					       bw->rx_tx_mcs13_max_nss,
+					       &rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
+					       &tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
+		}
+
+		arg->peer_eht_mcs_count++;
+		break;
+	}
+}
+
 static void ath12k_peer_assoc_prepare(struct ath12k *ar,
 				      struct ieee80211_vif *vif,
 				      struct ieee80211_sta *sta,
@@ -2083,6 +2227,7 @@  static void ath12k_peer_assoc_prepare(struct ath12k *ar,
 	ath12k_peer_assoc_h_ht(ar, vif, sta, arg);
 	ath12k_peer_assoc_h_vht(ar, vif, sta, arg);
 	ath12k_peer_assoc_h_he(ar, vif, sta, arg);
+	ath12k_peer_assoc_h_eht(ar, vif, sta, arg);
 	ath12k_peer_assoc_h_qos(ar, vif, sta, arg);
 	ath12k_peer_assoc_h_phymode(ar, vif, sta, arg);
 	ath12k_peer_assoc_h_smps(sta, arg);
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index aecc739164ae..d88d1575443d 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2583,6 +2583,7 @@  struct ath12k_wmi_soc_hal_reg_caps_params {
 
 #define WMI_MAX_EHTCAP_MAC_SIZE  2
 #define WMI_MAX_EHTCAP_PHY_SIZE  3
+#define WMI_MAX_EHTCAP_RATE_SET  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.
@@ -2596,6 +2597,15 @@  struct ath12k_wmi_soc_hal_reg_caps_params {
 #define WMI_MAX_EHT_SUPP_MCS_2G_SIZE  2
 #define WMI_MAX_EHT_SUPP_MCS_5G_SIZE  4
 
+#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_80    0
+#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_160   1
+#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_320   2
+
+#define WMI_EHT_MCS_NSS_0_7    GENMASK(3, 0)
+#define WMI_EHT_MCS_NSS_8_9    GENMASK(7, 4)
+#define WMI_EHT_MCS_NSS_10_11  GENMASK(11, 8)
+#define WMI_EHT_MCS_NSS_12_13  GENMASK(15, 12)
+
 struct ath12k_wmi_mac_phy_caps_ext_params {
 	__le32 hw_mode_id;
 	union {
@@ -3565,6 +3575,13 @@  struct ath12k_wmi_peer_assoc_arg {
 	bool twt_responder;
 	bool twt_requester;
 	struct ath12k_wmi_ppe_threshold_arg peer_ppet;
+	bool eht_flag;
+	u32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE];
+	u32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE];
+	u32 peer_eht_mcs_count;
+	u32 peer_eht_rx_mcs_set[WMI_MAX_EHTCAP_RATE_SET];
+	u32 peer_eht_tx_mcs_set[WMI_MAX_EHTCAP_RATE_SET];
+	struct ath12k_wmi_ppe_threshold_arg peer_eht_ppet;
 };
 
 struct wmi_peer_assoc_complete_cmd {