Browse Source

qcacld-3.0: Implement beamforming configuration for EHT

Intersecting EHT beamforming configuration from ini and FW
indication, then save it to eht caps of mlme.
For sta, update mlme EHT beamforming configuration to FW
through WMI_VDEV_PARAM_SET_EHT_MU_MODE directly.
For ap, intersecting mlme EHT beamforming configuration and user
configuration, then send result to FW.

Change-Id: I3d6185896af9fc58eb1fb6db913d4a425f72c696
CRs-Fixed: 3113235
Bing Sun 3 years ago
parent
commit
3e6513e3b8

+ 24 - 0
components/mlme/core/src/wlan_mlme_main.c

@@ -1269,6 +1269,30 @@ static void mlme_init_twt_cfg(struct wlan_objmgr_psoc *psoc,
 static void mlme_init_eht_cap_in_cfg(struct wlan_objmgr_psoc *psoc,
 				     struct wlan_mlme_cfg *mlme_cfg)
 {
+	struct wlan_mlme_eht_caps *eht_caps = &mlme_cfg->eht_caps;
+
+	eht_caps->dot11_eht_cap.su_beamformer =
+			cfg_default(CFG_EHT_SU_BEAMFORMER);
+	eht_caps->dot11_eht_cap.su_beamformee =
+			cfg_default(CFG_EHT_SU_BEAMFORMEE);
+	eht_caps->dot11_eht_cap.mu_bformer_le_80mhz =
+			cfg_default(CFG_EHT_MU_BFORMER_LE_80MHZ);
+	eht_caps->dot11_eht_cap.mu_bformer_160mhz =
+			cfg_default(CFG_EHT_MU_BFORMER_160MHZ);
+	eht_caps->dot11_eht_cap.mu_bformer_320mhz =
+			cfg_default(CFG_EHT_MU_BFORMER_320MHZ);
+	eht_caps->dot11_eht_cap.bfee_ss_le_80mhz =
+			cfg_default(CFG_EHT_BFEE_SS_LE_80MHZ);
+	eht_caps->dot11_eht_cap.bfee_ss_160mhz =
+			cfg_default(CFG_EHT_BFEE_SS_160MHZ);
+	eht_caps->dot11_eht_cap.bfee_ss_320mhz =
+			cfg_default(CFG_EHT_BFEE_SS_320MHZ);
+	eht_caps->dot11_eht_cap.num_sounding_dim_le_80mhz =
+			cfg_default(CFG_EHT_NUM_SOUNDING_DIM_LE_80MHZ);
+	eht_caps->dot11_eht_cap.num_sounding_dim_160mhz =
+			cfg_default(CFG_EHT_NUM_SOUNDING_DIM_160MHZ);
+	eht_caps->dot11_eht_cap.num_sounding_dim_320mhz =
+			cfg_default(CFG_EHT_NUM_SOUNDING_DIM_320MHZ);
 }
 #else
 static void mlme_init_eht_cap_in_cfg(struct wlan_objmgr_psoc *psoc,

+ 4 - 1
components/mlme/dispatcher/inc/cfg_mlme.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -59,6 +60,7 @@
 #include "cfg_mlme_fe_rrm.h"
 #include "cfg_mlme_mwc.h"
 #include "cfg_mlme_reg.h"
+#include "cfg_mlme_eht_caps.h"
 
 /* Please Maintain Alphabetic Order here */
 #define CFG_MLME_ALL \
@@ -98,6 +100,7 @@
 	CFG_WEP_PARAMS_ALL \
 	CFG_WIFI_POS_ALL \
 	CFG_WMM_PARAMS_ALL\
-	CFG_WPS_ALL
+	CFG_WPS_ALL \
+	CFG_EHT_CAPS_ALL
 
 #endif /* __CFG_MLME_H */

+ 332 - 0
components/mlme/dispatcher/inc/cfg_mlme_eht_caps.h

@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: This file contains centralized definitions of converged configuration.
+ */
+
+#ifndef __CFG_MLME_EHT_CAPS_H
+#define __CFG_MLME_EHT_CAPS_H
+
+/*
+ * <ini>
+ * eht_su_beamformer - Enable SU beamformer
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable or disable SU beamformer
+ *
+ * Related: None
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_SU_BEAMFORMER CFG_BOOL( \
+				"eht_su_beamformer", \
+				0, \
+				"EHT Su Beamformer")
+
+/*
+ * <ini>
+ * eht_su_beamformee - Enable SU beamformee
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable or disable SU beamformee
+ *
+ * Related: None
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_SU_BEAMFORMEE CFG_BOOL( \
+				"eht_su_beamformee", \
+				0, \
+				"EHT Su Beamformee")
+
+/*
+ * <ini>
+ * mu_bformer_le_80mhz - Enable MU beamformer for BW <= 80
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable or disable MU beamformer for BW <= 80
+ *
+ * Related: None
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_MU_BFORMER_LE_80MHZ CFG_BOOL( \
+				"mu_bformer_le_80mhz", \
+				0, \
+				"EHT MU Beamformer BW <= 80 MHz")
+
+/*
+ * <ini>
+ * mu_bformer_160mhz - Enable MU beamformer for BW == 160
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable or disable MU beamformer for BW == 160
+ *
+ * Related: None
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_MU_BFORMER_160MHZ CFG_BOOL( \
+				"mu_bformer_160mhz", \
+				0, \
+				"EHT MU Beamformer BW = 160 MHz")
+
+/*
+ * <ini>
+ * mu_bformer_320mhz - Enable MU beamformer for BW == 320
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable or disable MU beamformer for BW == 320
+ *
+ * Related: None
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_MU_BFORMER_320MHZ CFG_BOOL( \
+				"mu_bformer_320mhz", \
+				0, \
+				"EHT MU Beamformer BW = 320 MHz")
+
+/*
+ * <ini>
+ * eht_bfee_ss_le_80mhz - For a PPDU bandwidth less than or equal to 80 MHz,
+ *                        indicates the maximum number of spatial streams that
+ *                        the STA can receive in an EHT sounding NDP.
+ * @Min: 0
+ * @Max: 7
+ * @Default: 0
+ *
+ * If the SU Beamformee subfield is 1, set to the maximum number of spatial
+ * streams that the STA is capable of receiving in an EHT sounding NDP minus 1.
+ * The minimum value of this field is 3.
+ * Reserved if the SU Beamformee field is 0.
+ *
+ * Related: NA
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_BFEE_SS_LE_80MHZ CFG_UINT( \
+				"eht_bfee_ss_le_80mhz", \
+				3, \
+				7, \
+				3, \
+				CFG_VALUE_OR_DEFAULT, \
+				"EHT Beamformee SS <= 80 MHz")
+
+/*
+ * <ini>
+ * eht_bfee_ss_160mhz - For a PPDU bandwidth of 160 MHz, indicates the
+ *                      maximum number of spatial streams that the STA
+ *                      can receive in an EHT sounding NDP.
+ * @Min: 0
+ * @Max: 7
+ * @Default: 0
+ *
+ * If the SU Beamformee subfield is 1, set to the maximum number of spatial
+ * streams that the STA is capable of receiving in an EHT sounding NDP minus 1.
+ * The minimum value of this field is 3.
+ * Reserved if the SU Beamformee field is 0.
+ *
+ * Related: NA
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_BFEE_SS_160MHZ CFG_UINT( \
+				"eht_bfee_ss_160mhz", \
+				3, \
+				7, \
+				3, \
+				CFG_VALUE_OR_DEFAULT, \
+				"EHT Beamformee SS = 160 MHz")
+
+/*
+ * <ini>
+ * eht_bfee_ss_320mhz - For a PPDU bandwidth of 320 MHz, indicates the
+ *                      maximum number of spatial streams that the STA
+ *                      can receive in an EHT sounding NDP.
+ * @Min: 0
+ * @Max: 7
+ * @Default: 0
+ *
+ * If the SU Beamformee subfield is 1, set to the maximum number of spatial
+ * streams that the STA is capable of receiving in an EHT sounding NDP minus 1.
+ * The minimum value of this field is 3.
+ * Reserved if the SU Beamformee field is 0.
+ *
+ * Related: NA
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_BFEE_SS_320MHZ CFG_UINT( \
+				"eht_bfee_ss_320mhz", \
+				3, \
+				7, \
+				3, \
+				CFG_VALUE_OR_DEFAULT, \
+				"EHT Beamformee SS = 320 MHz")
+
+/*
+ * <ini>
+ * eht_num_sounding_dim_le_80mhz - For bandwidth less than or equal to 80 MHz,
+ *                                 indicates the beamformer's capability
+ *                                 indicating the maximum value of the TXVECTOR
+ *                                 parameter NUM_STS for an EHT sounding NDP
+ * @Min: 0
+ * @Max: 7
+ * @Default: 0
+ *
+ * If the SU Beamformer subfield is 1, set to the supported maximum
+ * TXVECTOR parameter NUM_STS value minus 1.
+ * Reserved if the SU Beamformer subfield is 0.
+ *
+ * Related: NA
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_NUM_SOUNDING_DIM_LE_80MHZ CFG_UINT( \
+				"eht_num_sounding_dim_le_80mhz", \
+				0, \
+				7, \
+				0, \
+				CFG_VALUE_OR_DEFAULT, \
+				"EHT Number Of Sounding Dimensions <= 80 MHz")
+
+/*
+ * <ini>
+ * eht_num_sounding_dim_160mhz - For bandwidth of 160 MHz, indicates the
+ *                               beamformer's capability indicating the
+ *                               maximum value of the TXVECTOR parameter
+ *                               NUM_STS for an EHT sounding NDP
+ * @Min: 0
+ * @Max: 7
+ * @Default: 0
+ *
+ * If the SU Beamformer subfield is 1, set to the supported maximum
+ * TXVECTOR parameter NUM_STS value minus 1.
+ * Reserved if the SU Beamformer subfield is 0 or the Supported Channel
+ * Width Set field does not indicate support for bandwidth of 160 MHz.
+ *
+ * Related: NA
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_NUM_SOUNDING_DIM_160MHZ CFG_UINT( \
+				"eht_num_sounding_dim_160mhz", \
+				0, \
+				7, \
+				0, \
+				CFG_VALUE_OR_DEFAULT, \
+				"EHT Number Of Sounding Dimensions = 160 MHz")
+
+/*
+ * <ini>
+ * eht_num_sounding_dim_320mhz - For bandwidth of 320 MHz, indicates the
+ *                               beamformer's capability indicating the
+ *                               maximum value of the TXVECTOR parameter
+ *                               NUM_STS for an EHT sounding NDP
+ * @Min: 0
+ * @Max: 7
+ * @Default: 0
+ *
+ * If the SU Beamformer subfield is 1, set to the supported maximum
+ * TXVECTOR parameter NUM_STS value minus 1.
+ * Reserved if the SU Beamformer subfield is 0 or the Supported Channel
+ * Width Set field does not indicate support for bandwidth of 320 MHz.
+ *
+ * Related: NA
+ *
+ * Supported Feature: 11be
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_EHT_NUM_SOUNDING_DIM_320MHZ CFG_UINT( \
+				"eht_num_sounding_dim_320mhz", \
+				0, \
+				7, \
+				0, \
+				CFG_VALUE_OR_DEFAULT, \
+				"EHT Number Of Sounding Dimensions = 320 MHz")
+
+#define CFG_EHT_CAPS_ALL \
+	CFG(CFG_EHT_SU_BEAMFORMER) \
+	CFG(CFG_EHT_SU_BEAMFORMEE) \
+	CFG(CFG_EHT_MU_BFORMER_LE_80MHZ) \
+	CFG(CFG_EHT_MU_BFORMER_160MHZ) \
+	CFG(CFG_EHT_MU_BFORMER_320MHZ) \
+	CFG(CFG_EHT_BFEE_SS_LE_80MHZ) \
+	CFG(CFG_EHT_BFEE_SS_160MHZ) \
+	CFG(CFG_EHT_BFEE_SS_320MHZ) \
+	CFG(CFG_EHT_NUM_SOUNDING_DIM_LE_80MHZ) \
+	CFG(CFG_EHT_NUM_SOUNDING_DIM_160MHZ) \
+	CFG(CFG_EHT_NUM_SOUNDING_DIM_320MHZ)
+
+#endif /* __CFG_MLME_EHT_CAPS_H */
+

+ 51 - 1
components/mlme/dispatcher/src/wlan_mlme_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -974,6 +974,7 @@ QDF_STATUS mlme_update_tgt_eht_caps_in_cfg(struct wlan_objmgr_psoc *psoc,
 {
 	struct wlan_mlme_psoc_ext_obj *mlme_obj = mlme_get_psoc_ext_obj(psoc);
 	tDot11fIEeht_cap *eht_cap = &wma_cfg->eht_cap;
+	tDot11fIEeht_cap *mlme_eht_cap;
 
 	if (!mlme_obj)
 		return QDF_STATUS_E_FAILURE;
@@ -981,6 +982,55 @@ QDF_STATUS mlme_update_tgt_eht_caps_in_cfg(struct wlan_objmgr_psoc *psoc,
 	mlme_obj->cfg.eht_caps.dot11_eht_cap.present = 1;
 	qdf_mem_copy(&mlme_obj->cfg.eht_caps.dot11_eht_cap, eht_cap,
 		     sizeof(tDot11fIEeht_cap));
+	mlme_eht_cap = &mlme_obj->cfg.eht_caps.dot11_eht_cap;
+	if (mlme_obj->cfg.vht_caps.vht_cap_info.su_bformer) {
+		mlme_eht_cap->su_beamformer = eht_cap->su_beamformer;
+		if (cfg_in_range(CFG_EHT_NUM_SOUNDING_DIM_LE_80MHZ,
+				 eht_cap->num_sounding_dim_le_80mhz))
+			mlme_eht_cap->num_sounding_dim_le_80mhz =
+				eht_cap->num_sounding_dim_le_80mhz;
+		if (cfg_in_range(CFG_EHT_NUM_SOUNDING_DIM_160MHZ,
+				 eht_cap->num_sounding_dim_160mhz))
+			mlme_eht_cap->num_sounding_dim_160mhz =
+				eht_cap->num_sounding_dim_160mhz;
+		if (cfg_in_range(CFG_EHT_NUM_SOUNDING_DIM_320MHZ,
+				 eht_cap->num_sounding_dim_320mhz))
+			mlme_eht_cap->num_sounding_dim_320mhz =
+				eht_cap->num_sounding_dim_320mhz;
+		mlme_eht_cap->mu_bformer_le_80mhz =
+			eht_cap->mu_bformer_le_80mhz;
+		mlme_eht_cap->mu_bformer_160mhz = eht_cap->mu_bformer_160mhz;
+		mlme_eht_cap->mu_bformer_320mhz = eht_cap->mu_bformer_320mhz;
+
+	} else {
+		mlme_eht_cap->su_beamformer = 0;
+		mlme_eht_cap->num_sounding_dim_le_80mhz = 0;
+		mlme_eht_cap->num_sounding_dim_160mhz = 0;
+		mlme_eht_cap->num_sounding_dim_320mhz = 0;
+		mlme_eht_cap->mu_bformer_le_80mhz = 0;
+		mlme_eht_cap->mu_bformer_160mhz = 0;
+		mlme_eht_cap->mu_bformer_320mhz = 0;
+	}
+
+	if (mlme_obj->cfg.vht_caps.vht_cap_info.su_bformee) {
+		mlme_eht_cap->su_beamformee = eht_cap->su_beamformee;
+		if (cfg_in_range(CFG_EHT_BFEE_SS_LE_80MHZ,
+				 eht_cap->bfee_ss_le_80mhz))
+			mlme_eht_cap->bfee_ss_le_80mhz =
+						eht_cap->bfee_ss_le_80mhz;
+		if (cfg_in_range(CFG_EHT_BFEE_SS_160MHZ,
+				 eht_cap->bfee_ss_160mhz))
+			mlme_eht_cap->bfee_ss_160mhz = eht_cap->bfee_ss_160mhz;
+		if (cfg_in_range(CFG_EHT_BFEE_SS_320MHZ,
+				 eht_cap->bfee_ss_320mhz))
+			mlme_eht_cap->bfee_ss_320mhz = eht_cap->bfee_ss_320mhz;
+
+	} else {
+		mlme_eht_cap->su_beamformee = 0;
+		mlme_eht_cap->bfee_ss_le_80mhz = 0;
+		mlme_eht_cap->bfee_ss_160mhz = 0;
+		mlme_eht_cap->bfee_ss_320mhz = 0;
+	}
 	return QDF_STATUS_SUCCESS;
 }
 #endif

+ 119 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -8200,11 +8200,125 @@ static void lim_intersect_eht_caps(tDot11fIEeht_cap *rcvd_eht,
 				   tDot11fIEeht_cap *peer_eht,
 				   struct pe_session *session)
 {
+	tDot11fIEeht_cap *session_eht = &session->eht_config;
+
+	qdf_mem_copy(peer_eht, rcvd_eht, sizeof(*peer_eht));
+
+	peer_eht->su_beamformer = session_eht->su_beamformee ?
+					peer_eht->su_beamformer : 0;
+	peer_eht->su_beamformee = (session_eht->su_beamformer ||
+				   session_eht->mu_bformer_le_80mhz ||
+				   session_eht->mu_bformer_160mhz ||
+				   session_eht->mu_bformer_320mhz) ?
+					peer_eht->su_beamformee : 0;
+	peer_eht->mu_bformer_le_80mhz = session_eht->su_beamformee ?
+					peer_eht->mu_bformer_le_80mhz : 0;
+	peer_eht->mu_bformer_160mhz = session_eht->su_beamformee ?
+					peer_eht->mu_bformer_160mhz : 0;
+	peer_eht->mu_bformer_320mhz = session_eht->su_beamformee ?
+					peer_eht->mu_bformer_320mhz : 0;
 }
 
 void lim_update_usr_eht_cap(struct mac_context *mac_ctx,
 			    struct pe_session *session)
 {
+	struct add_ie_params *add_ie = &session->add_ie_params;
+	tDot11fIEeht_cap *eht_cap = &session->eht_config;
+	struct wlan_eht_cap_info_network_endian *eht_cap_from_ie;
+	uint8_t extracted_buff[DOT11F_IE_EHT_CAP_MAX_LEN + 2];
+	QDF_STATUS status;
+	struct wlan_vht_config *vht_cfg = &session->vht_config;
+	tDot11fIEhe_cap *he_cap = &session->he_config;
+	struct mlme_legacy_priv *mlme_priv;
+
+	qdf_mem_zero(extracted_buff, sizeof(extracted_buff));
+	status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff,
+			      &add_ie->probeRespBCNDataLen,
+			      DOT11F_EID_EHT_CAP, ONE_BYTE,
+			      EHT_CAP_OUI_TYPE, (uint8_t)EHT_CAP_OUI_SIZE,
+			      extracted_buff, DOT11F_IE_EHT_CAP_MAX_LEN);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		pe_debug("Failed to strip EHT cap IE status: %d", status);
+		return;
+	}
+
+	pe_debug("Before update: su_bformer: %d, su_bformee: %d, mu_bformer <= 80MHZ: %d 160MHZ: %d 320MHZ: %d",
+		 eht_cap->su_beamformer, eht_cap->su_beamformee,
+		 eht_cap->mu_bformer_le_80mhz, eht_cap->mu_bformer_160mhz,
+		 eht_cap->mu_bformer_320mhz);
+
+	eht_cap_from_ie = (struct wlan_eht_cap_info_network_endian *)
+					&extracted_buff[EHT_CAP_OUI_SIZE + 2];
+
+	eht_cap->su_beamformer =
+		eht_cap->su_beamformer & eht_cap_from_ie->su_beamformer;
+	eht_cap->su_beamformee =
+		eht_cap->su_beamformee & eht_cap_from_ie->su_beamformee;
+	eht_cap->mu_bformer_le_80mhz =
+		eht_cap->mu_bformer_le_80mhz &
+		eht_cap_from_ie->mu_bformer_le_80mhz;
+	eht_cap->mu_bformer_160mhz =
+		eht_cap->mu_bformer_160mhz &
+		eht_cap_from_ie->mu_bformer_160mhz;
+	eht_cap->mu_bformer_320mhz =
+		eht_cap->mu_bformer_320mhz &
+		eht_cap_from_ie->mu_bformer_320mhz;
+
+	pe_debug("After update: su_bformer: %d, su_bformee: %d, mu_bformer <= 80MHZ: %d 160MHZ: %d 320MHZ: %d",
+		 eht_cap->su_beamformer, eht_cap->su_beamformee,
+		 eht_cap->mu_bformer_le_80mhz, eht_cap->mu_bformer_160mhz,
+		 eht_cap->mu_bformer_320mhz);
+	if (!eht_cap->su_beamformer) {
+		eht_cap->mu_bformer_le_80mhz = 0;
+		eht_cap->mu_bformer_160mhz = 0;
+		eht_cap->mu_bformer_320mhz = 0;
+		eht_cap->num_sounding_dim_le_80mhz = 0;
+		eht_cap->num_sounding_dim_160mhz = 0;
+		eht_cap->num_sounding_dim_320mhz = 0;
+		he_cap->mu_beamformer = 0;
+		he_cap->num_sounding_lt_80 = 0;
+		he_cap->num_sounding_gt_80 = 0;
+		vht_cfg->su_beam_former = 0;
+		vht_cfg->mu_beam_former = 0;
+		vht_cfg->num_soundingdim = 0;
+	}
+	if (!eht_cap->su_beamformee) {
+		eht_cap->bfee_ss_le_80mhz = 0;
+		eht_cap->bfee_ss_160mhz = 0;
+		eht_cap->bfee_ss_320mhz = 0;
+		he_cap->bfee_sts_lt_80 = 0;
+		he_cap->bfee_sts_gt_80 = 0;
+		vht_cfg->su_beam_formee = 0;
+		vht_cfg->mu_beam_formee = 0;
+		vht_cfg->csnof_beamformer_antSup = 0;
+	}
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev);
+	if (mlme_priv) {
+		mlme_priv->eht_config.mu_bformer_le_80mhz =
+			eht_cap->mu_bformer_le_80mhz;
+		mlme_priv->eht_config.mu_bformer_160mhz =
+			eht_cap->mu_bformer_160mhz;
+		mlme_priv->eht_config.mu_bformer_320mhz =
+			eht_cap->mu_bformer_320mhz;
+		mlme_priv->eht_config.su_beamformer = eht_cap->su_beamformer;
+		mlme_priv->eht_config.su_beamformee = eht_cap->su_beamformee;
+		mlme_priv->eht_config.bfee_ss_le_80mhz =
+			eht_cap->bfee_ss_le_80mhz;
+		mlme_priv->eht_config.bfee_ss_160mhz = eht_cap->bfee_ss_160mhz;
+		mlme_priv->eht_config.bfee_ss_320mhz = eht_cap->bfee_ss_320mhz;
+		mlme_priv->eht_config.num_sounding_dim_le_80mhz =
+			eht_cap->num_sounding_dim_le_80mhz;
+		mlme_priv->eht_config.num_sounding_dim_160mhz =
+			eht_cap->num_sounding_dim_160mhz;
+		mlme_priv->eht_config.num_sounding_dim_320mhz =
+			eht_cap->num_sounding_dim_320mhz;
+	}
+	wma_set_eht_txbf_params(session->vdev_id, eht_cap->su_beamformer,
+				eht_cap->su_beamformee,
+				eht_cap->mu_bformer_le_80mhz ||
+				eht_cap->mu_bformer_160mhz ||
+				eht_cap->mu_bformer_320mhz);
 }
 
 static void
@@ -8239,6 +8353,11 @@ void lim_copy_join_req_eht_cap(struct pe_session *session)
 void lim_add_eht_cap(struct mac_context *mac_ctx, struct pe_session *pe_session,
 		     tpAddStaParams add_sta_params, tpSirAssocReq assoc_req)
 {
+	if (!add_sta_params->eht_capable || !assoc_req)
+		return;
+
+	qdf_mem_copy(&add_sta_params->eht_config, &assoc_req->eht_cap,
+		     sizeof(add_sta_params->eht_config));
 }
 
 void lim_intersect_ap_eht_caps(struct pe_session *session,

+ 1 - 3
core/sme/src/common/sme_api.c

@@ -15137,10 +15137,8 @@ void sme_update_score_config(mac_handle_t mac_handle, eCsrPhyMode phy_mode,
 	    phy_mode == eCSR_DOT11_MODE_11n_ONLY)
 		config.ht_cap = 1;
 
-#ifdef WLAN_FEATURE_11BE
-	if (!IS_FEATURE_SUPPORTED_BY_FW(DOT11BE))
+	if (!IS_FEATURE_11BE_SUPPORTED_BY_FW)
 		config.eht_cap = 0;
-#endif
 
 	if (!IS_FEATURE_SUPPORTED_BY_FW(DOT11AX))
 		config.he_cap = 0;

+ 3 - 3
core/sme/src/csr/csr_api_roam.c

@@ -5221,7 +5221,7 @@ csr_compute_mode_and_band(struct mac_context *mac_ctx,
 #ifdef WLAN_FEATURE_11BE
 	case eCSR_CFG_DOT11_MODE_11BE:
 	case eCSR_CFG_DOT11_MODE_11BE_ONLY:
-		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11BE)) {
+		if (IS_FEATURE_11BE_SUPPORTED_BY_FW) {
 			*dot11_mode = mac_ctx->roam.configParam.uCfgDot11Mode;
 		} else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX)) {
 			*dot11_mode = eCSR_CFG_DOT11_MODE_11AX;
@@ -5244,7 +5244,7 @@ csr_compute_mode_and_band(struct mac_context *mac_ctx,
 #endif
 	case eCSR_CFG_DOT11_MODE_AUTO:
 #ifdef WLAN_FEATURE_11BE
-		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11BE)) {
+		if (IS_FEATURE_11BE_SUPPORTED_BY_FW) {
 			*dot11_mode = eCSR_CFG_DOT11_MODE_11BE;
 		} else
 #endif
@@ -5393,7 +5393,7 @@ csr_roam_get_phy_mode_band_for_bss(struct mac_context *mac_ctx,
 		  profile->privacy, bss_op_ch_freq,
 		  IS_FEATURE_SUPPORTED_BY_FW(DOT11AX));
 #ifdef WLAN_FEATURE_11BE
-	sme_debug("BE :%d", IS_FEATURE_SUPPORTED_BY_FW(DOT11BE));
+	sme_debug("BE :%d", IS_FEATURE_11BE_SUPPORTED_BY_FW);
 #endif
 	return cfg_dot11_mode;
 }

+ 5 - 5
core/sme/src/csr/csr_util.c

@@ -828,7 +828,7 @@ uint32_t csr_translate_to_wni_cfg_dot11_mode(struct mac_context *mac,
 	switch (csrDot11Mode) {
 	case eCSR_CFG_DOT11_MODE_AUTO:
 #ifdef WLAN_FEATURE_11BE
-		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11BE))
+		if (IS_FEATURE_11BE_SUPPORTED_BY_FW)
 			ret = MLME_DOT11_MODE_11BE;
 		else
 #endif
@@ -887,7 +887,7 @@ uint32_t csr_translate_to_wni_cfg_dot11_mode(struct mac_context *mac,
 		break;
 #ifdef WLAN_FEATURE_11BE
 	case eCSR_CFG_DOT11_MODE_11BE_ONLY:
-		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11BE))
+		if (IS_FEATURE_11BE_SUPPORTED_BY_FW)
 			ret = MLME_DOT11_MODE_11BE_ONLY;
 		else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX))
 			ret = MLME_DOT11_MODE_11AX_ONLY;
@@ -897,7 +897,7 @@ uint32_t csr_translate_to_wni_cfg_dot11_mode(struct mac_context *mac,
 			ret = MLME_DOT11_MODE_11N;
 		break;
 	case eCSR_CFG_DOT11_MODE_11BE:
-		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11BE))
+		if (IS_FEATURE_11BE_SUPPORTED_BY_FW)
 			ret = MLME_DOT11_MODE_11BE;
 		else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX))
 			ret = MLME_DOT11_MODE_11AX;
@@ -1160,7 +1160,7 @@ csr_get_cfg_dot11_mode_from_csr_phy_mode(bool is_ap, eCsrPhyMode phyMode)
 		break;
 #ifdef WLAN_FEATURE_11BE
 	case eCSR_DOT11_MODE_11be:
-		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11BE))
+		if (IS_FEATURE_11BE_SUPPORTED_BY_FW)
 			cfgDot11Mode = eCSR_CFG_DOT11_MODE_11BE;
 		else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX))
 			cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AX;
@@ -1170,7 +1170,7 @@ csr_get_cfg_dot11_mode_from_csr_phy_mode(bool is_ap, eCsrPhyMode phyMode)
 			cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
 		break;
 	case eCSR_DOT11_MODE_11be_ONLY:
-		if (IS_FEATURE_SUPPORTED_BY_FW(DOT11BE))
+		if (IS_FEATURE_11BE_SUPPORTED_BY_FW)
 			cfgDot11Mode = eCSR_CFG_DOT11_MODE_11BE_ONLY;
 		else if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX))
 			cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AX_ONLY;

+ 6 - 1
core/wma/inc/wma_types.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -28,6 +28,11 @@
 
 #define IS_FEATURE_SUPPORTED_BY_FW(feat_enum_value) \
 				wma_get_fw_wlan_feat_caps(feat_enum_value)
+#ifdef WLAN_FEATURE_11BE
+#define IS_FEATURE_11BE_SUPPORTED_BY_FW IS_FEATURE_SUPPORTED_BY_FW(DOT11BE)
+#else
+#define IS_FEATURE_11BE_SUPPORTED_BY_FW 0
+#endif
 
 #define DPU_FEEDBACK_UNPROTECTED_ERROR 0x0F
 

+ 4 - 1
core/wma/src/wma_dev_if.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -2804,6 +2804,9 @@ QDF_STATUS wma_post_vdev_create_setup(struct wlan_objmgr_vdev *vdev)
 		wma_err("failed to set TX_STBC(status = %d)", status);
 
 	wma_set_vdev_mgmt_rate(wma_handle, vdev_id);
+	if (IS_FEATURE_11BE_SUPPORTED_BY_FW)
+		wma_set_eht_txbf_cfg(mac, vdev_id);
+
 	if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AX))
 		wma_set_he_txbf_cfg(mac, vdev_id);
 

+ 41 - 0
core/wma/src/wma_eht.c

@@ -25,6 +25,7 @@
 #include "wmi_unified.h"
 #include "service_ready_param.h"
 #include "target_if.h"
+#include "wma_internal.h"
 
 #if defined(WLAN_FEATURE_11BE)
 /**
@@ -497,4 +498,44 @@ void wma_set_peer_assoc_params_bw_320(struct peer_assoc_params *params,
 	if (ch_width == CH_WIDTH_320MHZ)
 		params->bw_320 = 1;
 }
+
+void wma_set_eht_txbf_cfg(struct mac_context *mac, uint8_t vdev_id)
+{
+	wma_set_eht_txbf_params(
+		vdev_id, mac->mlme_cfg->eht_caps.dot11_eht_cap.su_beamformer,
+		mac->mlme_cfg->eht_caps.dot11_eht_cap.su_beamformee,
+		mac->mlme_cfg->eht_caps.dot11_eht_cap.mu_bformer_le_80mhz ||
+		mac->mlme_cfg->eht_caps.dot11_eht_cap.mu_bformer_160mhz ||
+		mac->mlme_cfg->eht_caps.dot11_eht_cap.mu_bformer_320mhz);
+}
+
+void wma_set_eht_txbf_params(uint8_t vdev_id, bool su_bfer,
+			     bool su_bfee, bool mu_bfer)
+{
+	uint32_t ehtmu_mode = 0;
+	QDF_STATUS status;
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+
+	if (!wma)
+		return;
+
+	if (su_bfer)
+		WMI_VDEV_EHT_SUBFER_ENABLE(ehtmu_mode);
+	if (su_bfee) {
+		WMI_VDEV_EHT_SUBFEE_ENABLE(ehtmu_mode);
+		WMI_VDEV_EHT_MUBFEE_ENABLE(ehtmu_mode);
+	}
+	if (mu_bfer)
+		WMI_VDEV_EHT_MUBFER_ENABLE(ehtmu_mode);
+
+	WMI_VDEV_EHT_DLOFDMA_ENABLE(ehtmu_mode);
+	WMI_VDEV_EHT_ULOFDMA_ENABLE(ehtmu_mode);
+
+	status = wma_vdev_set_param(wma->wmi_handle, vdev_id,
+				    WMI_VDEV_PARAM_SET_EHT_MU_MODE, ehtmu_mode);
+	wma_debug("set EHTMU_MODE (ehtmu_mode = 0x%x)", ehtmu_mode);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		wma_err("failed to set EHTMU_MODE(status = %d)", status);
+}
 #endif

+ 33 - 0
core/wma/src/wma_eht.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -147,6 +148,27 @@ QDF_STATUS wma_get_eht_capabilities(struct eht_capability *eht_cap);
  */
 void wma_set_peer_assoc_params_bw_320(struct peer_assoc_params *params,
 				      enum phy_ch_width ch_width);
+
+/**
+ * wma_set_eht_txbf_cfg() - set EHT Tx beamforming mlme cfg to FW
+ * @mac: Global MAC context
+ * @vdev_id: VDEV id
+ *
+ * Return: None
+ */
+void wma_set_eht_txbf_cfg(struct mac_context *mac, uint8_t vdev_id);
+
+/**
+ * wma_set_eht_txbf_params() - set EHT Tx beamforming params to FW
+ * @vdev_id: VDEV id
+ * @su bfer: SU beamformer capability
+ * @su bfee: SU beamformee capability
+ * @mu bfer: MU beamformer capability
+ *
+ * Return: None
+ */
+void wma_set_eht_txbf_params(uint8_t vdev_id, bool su_bfer,
+			     bool su_bfee, bool mu_bfer);
 #else
 static inline void wma_eht_update_tgt_services(struct wmi_unified *wmi_handle,
 					       struct wma_tgt_services *cfg)
@@ -202,5 +224,16 @@ void wma_set_peer_assoc_params_bw_320(struct peer_assoc_params *params,
 				      enum phy_ch_width ch_width)
 {
 }
+
+static inline
+void wma_set_eht_txbf_cfg(struct mac_context *mac, uint8_t vdev_id)
+{
+}
+
+static inline
+void wma_set_eht_txbf_params(uint8_t vdev_id, bool su_bfer,
+			     bool su_bfee, bool mu_bfer)
+{
+}
 #endif
 #endif