Ver código fonte

qcacld-3.0: Add TPC calculation logic to obtain max tx power

Add new lim api to calculate an array of tx power values. Include
hw limit from Fw and TPE values from IE along with existing
params to determine TPC power.
The new struct reg_tpc_obj in vdev_mlme object will contain max
tx power, center frequencies, number of power levels,
PSD power check, EIRP power, AP power type for 6G and TPE
power values and will be sent to FW via new WMI cmd
WMI_VDEV_SET_TPC_POWER_CMDID.

Change-Id: I80a2454c2ef0dbc3b1d69e8b233b1a56567ec1a1
CRs-Fixed: 2841873
Gururaj Pandurangi 4 anos atrás
pai
commit
4387c79bb5

+ 16 - 7
core/mac/src/pe/lim/lim_ft.c

@@ -534,7 +534,8 @@ void lim_fill_ft_session(struct mac_context *mac,
 	int8_t regMax;
 	tSchBeaconStruct *pBeaconStruct;
 	ePhyChanBondState cbEnabledMode;
-	struct lim_max_tx_pwr_attr tx_pwr_attr = {0};
+	struct vdev_mlme_obj *mlme_obj;
+	bool is_pwr_constraint;
 
 	pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct));
 	if (!pBeaconStruct)
@@ -696,15 +697,23 @@ void lim_fill_ft_session(struct mac_context *mac,
 		ft_session->shortSlotTimeSupported = true;
 	}
 
+	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
+	if (!mlme_obj) {
+		pe_err("vdev component object is NULL");
+		qdf_mem_free(pBeaconStruct);
+		return;
+	}
+
 	regMax = wlan_reg_get_channel_reg_power_for_freq(
 		mac->pdev, ft_session->curr_op_freq);
 	localPowerConstraint = regMax;
 	lim_extract_ap_capability(mac, (uint8_t *) pbssDescription->ieFields,
-
 		lim_get_ielen_from_bss_description(pbssDescription),
 		&ft_session->limCurrentBssQosCaps,
 		&currentBssUapsd,
-		&localPowerConstraint, ft_session);
+		&localPowerConstraint, ft_session, &is_pwr_constraint);
+	if (is_pwr_constraint)
+		localPowerConstraint = regMax - localPowerConstraint;
 
 	ft_session->limReassocBssQosCaps =
 		ft_session->limCurrentBssQosCaps;
@@ -721,12 +730,12 @@ void lim_fill_ft_session(struct mac_context *mac,
 	ft_session->isFastRoamIniFeatureEnabled =
 		pe_session->isFastRoamIniFeatureEnabled;
 
-	tx_pwr_attr.reg_max = regMax;
-	tx_pwr_attr.ap_tx_power = localPowerConstraint;
-	tx_pwr_attr.frequency = ft_session->curr_op_freq;
+	mlme_obj->reg_tpc_obj.reg_max[0] = regMax;
+	mlme_obj->reg_tpc_obj.ap_constraint_power = localPowerConstraint;
+	mlme_obj->reg_tpc_obj.frequency[0] = ft_session->curr_op_freq;
 
 #ifdef FEATURE_WLAN_ESE
-	ft_session->maxTxPower = lim_get_max_tx_power(mac, &tx_pwr_attr);
+	ft_session->maxTxPower = lim_get_max_tx_power(mac, mlme_obj);
 #else
 	ft_session->maxTxPower = QDF_MIN(regMax, (localPowerConstraint));
 #endif

+ 10 - 0
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -44,6 +44,8 @@
 #include "wlan_pmo_ucfg_api.h"
 #include "wlan_objmgr_vdev_obj.h"
 #include <wlan_cm_api.h>
+#include "wlan_reg_services_api.h"
+#include "wlan_lmac_if_def.h"
 
 static void lim_process_mlm_auth_req(struct mac_context *, uint32_t *);
 static void lim_process_mlm_assoc_req(struct mac_context *, uint32_t *);
@@ -235,6 +237,7 @@ lim_mlm_add_bss(struct mac_context *mac_ctx,
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
 	struct bss_params *addbss_param = NULL;
+	struct wlan_lmac_if_reg_tx_ops *tx_ops;
 
 	if (!wma)
 		return eSIR_SME_INVALID_PARAMETERS;
@@ -245,6 +248,7 @@ lim_mlm_add_bss(struct mac_context *mac_ctx,
 		return eSIR_SME_INVALID_PARAMETERS;
 	}
 
+	tx_ops = wlan_reg_get_tx_ops(mac_ctx->psoc);
 	qdf_mem_copy(mlme_obj->mgmt.generic.bssid, mlm_start_req->bssId,
 		     QDF_MAC_ADDR_SIZE);
 	if (lim_is_session_he_capable(session)) {
@@ -290,6 +294,12 @@ lim_mlm_add_bss(struct mac_context *mac_ctx,
 		goto peer_cleanup;
 	wma_post_vdev_start_setup(vdev_id);
 
+	lim_calculate_tpc(mac_ctx, session, false);
+
+	if (tx_ops->set_tpc_power)
+		tx_ops->set_tpc_power(mac_ctx->psoc, session->vdev_id,
+				      &mlme_obj->reg_tpc_obj);
+
 	return eSIR_SME_SUCCESS;
 
 peer_cleanup:

+ 22 - 1
core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2021 The Linux Foundation. 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
@@ -2657,6 +2657,9 @@ static void lim_process_switch_channel_join_req(
 	tLimMlmJoinCnf join_cnf;
 	uint8_t nontx_bss_id = 0;
 	struct bss_description *bss;
+	struct vdev_mlme_obj *mlme_obj;
+	struct wlan_lmac_if_reg_tx_ops *tx_ops;
+	bool tpe_change = false;
 
 	if (status != QDF_STATUS_SUCCESS) {
 		pe_err("Change channel failed!!");
@@ -2669,6 +2672,8 @@ static void lim_process_switch_channel_join_req(
 		goto error;
 	}
 
+	tx_ops = wlan_reg_get_tx_ops(mac_ctx->psoc);
+
 	bss = &session_entry->lim_join_req->bssDescription;
 	nontx_bss_id = bss->mbssid_info.profile_num;
 
@@ -2757,6 +2762,22 @@ static void lim_process_switch_channel_join_req(
 		goto error;
 	}
 
+	lim_process_tpe_ie_from_beacon(mac_ctx, session_entry, bss,
+				       &tpe_change);
+
+	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session_entry->vdev);
+	if (!mlme_obj) {
+		pe_err("vdev component object is NULL");
+		goto error;
+	}
+
+	lim_calculate_tpc(mac_ctx, session_entry, false);
+
+	if (tx_ops->set_tpc_power)
+		tx_ops->set_tpc_power(mac_ctx->psoc,
+				      session_entry->vdev_id,
+				      &mlme_obj->reg_tpc_obj);
+
 	/* include additional IE if there is */
 	lim_send_probe_req_mgmt_frame(mac_ctx, &ssId,
 		session_entry->pLimMlmJoinReq->bssDescription.bssId,

+ 216 - 22
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -60,6 +60,10 @@
 #include <wlan_action_oui_ucfg_api.h>
 #include <wlan_cm_api.h>
 #include <wlan_mlme_api.h>
+#include <wlan_mlme_ucfg_api.h>
+#include <wlan_reg_ucfg_api.h>
+#include "wlan_lmac_if_def.h"
+#include "wlan_reg_services_api.h"
 
 /* SME REQ processing function templates */
 static bool __lim_process_sme_sys_ready_ind(struct mac_context *, uint32_t *);
@@ -100,6 +104,20 @@ static void lim_process_update_add_ies(struct mac_context *mac, uint32_t *pMsg);
 static void lim_process_ext_change_channel(struct mac_context *mac_ctx,
 						uint32_t *msg);
 
+/**
+ * enum get_next_lower_bw - Get next higher bandwidth for a given BW.
+ * This enum is used in conjunction with
+ * wlan_reg_set_channel_params_for_freq API to fetch center frequencies
+ * for each BW starting from 20MHz upto Max BSS BW in case of non-PSD power.
+ *
+ */
+static const enum phy_ch_width get_next_higher_bw[] = {
+	[CH_WIDTH_20MHZ] = CH_WIDTH_40MHZ,
+	[CH_WIDTH_40MHZ] = CH_WIDTH_80MHZ,
+	[CH_WIDTH_80MHZ] = CH_WIDTH_160MHZ,
+	[CH_WIDTH_160MHZ] = CH_WIDTH_INVALID
+};
+
 /**
  * lim_process_set_hw_mode() - Send set HW mode command to WMA
  * @mac: Globacl MAC pointer
@@ -2498,8 +2516,9 @@ lim_fill_pe_session(struct mac_context *mac_ctx, struct pe_session *session,
 	ePhyChanBondState cb_mode;
 	const uint8_t *vendor_ie;
 	uint16_t ie_len;
-	int8_t local_power_constraint, reg_max;
-	struct lim_max_tx_pwr_attr tx_pwr_attr = {0};
+	int8_t local_power_constraint;
+	struct vdev_mlme_obj *mlme_obj;
+	bool is_pwr_constraint;
 	tSirMacCapabilityInfo *ap_cap_info;
 	uint8_t wmm_mode, value;
 	struct wlan_mlme_lfr_cfg *lfr = &mac_ctx->mlme_cfg->lfr;
@@ -2690,24 +2709,23 @@ lim_fill_pe_session(struct mac_context *mac_ctx, struct pe_session *session,
 
 	session->limCurrentBssCaps = bss_desc->capabilityInfo;
 
-	reg_max = wlan_reg_get_channel_reg_power_for_freq(
-		mac_ctx->pdev, session->curr_op_freq);
-	local_power_constraint = reg_max;
-
-	tx_pwr_attr.reg_max = reg_max;
-	tx_pwr_attr.ap_tx_power = local_power_constraint;
-	tx_pwr_attr.frequency = session->curr_op_freq;
-
-	session->maxTxPower = lim_get_max_tx_power(mac_ctx,
-						   &tx_pwr_attr);
-	session->def_max_tx_pwr = session->maxTxPower;
+	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
+	if (!mlme_obj) {
+		qdf_mem_free(ie_struct);
+		return QDF_STATUS_E_FAILURE;
+	}
 
 	lim_extract_ap_capability(mac_ctx,
 		(uint8_t *)bss_desc->ieFields,
 		lim_get_ielen_from_bss_description(bss_desc),
 		&session->limCurrentBssQosCaps,
 		&session->gLimCurrentBssUapsd,
-		&local_power_constraint, session);
+		&local_power_constraint, session, &is_pwr_constraint);
+
+	mlme_obj->reg_tpc_obj.ap_constraint_power = local_power_constraint;
+
+	session->maxTxPower = lim_get_max_tx_power(mac_ctx, mlme_obj);
+	session->def_max_tx_pwr = session->maxTxPower;
 
 	session->limRFBand = lim_get_rf_band(session->curr_op_freq);
 
@@ -3933,19 +3951,63 @@ end:
 }
 #endif
 
+uint32_t lim_get_num_pwr_levels(bool is_psd,
+				enum phy_ch_width ch_width)
+{
+	uint32_t num_pwr_levels = 0;
+
+	if (is_psd) {
+		switch (ch_width) {
+		case CH_WIDTH_20MHZ:
+			num_pwr_levels = 1;
+			break;
+		case CH_WIDTH_40MHZ:
+			num_pwr_levels = 2;
+			break;
+		case CH_WIDTH_80MHZ:
+			num_pwr_levels = 4;
+			break;
+		case CH_WIDTH_160MHZ:
+			num_pwr_levels = 8;
+			break;
+		default:
+			pe_err("Invalid channel width");
+			return 0;
+		}
+	} else {
+		switch (ch_width) {
+		case CH_WIDTH_20MHZ:
+			num_pwr_levels = 1;
+			break;
+		case CH_WIDTH_40MHZ:
+			num_pwr_levels = 2;
+			break;
+		case CH_WIDTH_80MHZ:
+			num_pwr_levels = 3;
+			break;
+		case CH_WIDTH_160MHZ:
+			num_pwr_levels = 4;
+			break;
+		default:
+			pe_err("Invalid channel width");
+			return 0;
+		}
+	}
+	return num_pwr_levels;
+}
+
 uint8_t lim_get_max_tx_power(struct mac_context *mac,
-			     struct lim_max_tx_pwr_attr *attr)
+			     struct vdev_mlme_obj *mlme_obj)
 {
 	uint8_t max_tx_power = 0;
 	uint8_t tx_power;
 
-	if (!attr)
-		return 0;
-
-	if (wlan_reg_get_fcc_constraint(mac->pdev, attr->frequency))
-		return attr->reg_max;
+	if (wlan_reg_get_fcc_constraint(mac->pdev,
+					mlme_obj->reg_tpc_obj.frequency[0]))
+		return mlme_obj->reg_tpc_obj.reg_max[0];
 
-	tx_power = QDF_MIN(attr->reg_max, attr->ap_tx_power);
+	tx_power = QDF_MIN(mlme_obj->reg_tpc_obj.reg_max[0],
+			   mlme_obj->reg_tpc_obj.ap_constraint_power);
 
 	if (tx_power >= MIN_TX_PWR_CAP && tx_power <= MAX_TX_PWR_CAP)
 		max_tx_power = tx_power;
@@ -3957,6 +4019,133 @@ uint8_t lim_get_max_tx_power(struct mac_context *mac,
 	return max_tx_power;
 }
 
+void lim_calculate_tpc(struct mac_context *mac,
+		       struct pe_session *session,
+		       bool is_pwr_constraint_absolute)
+{
+	bool is_psd_power = false;
+	bool is_tpe_present = false, is_6ghz_freq = false;
+	uint8_t i = 0;
+	int8_t max_tx_power;
+	uint16_t reg_max, eirp_power = 0;
+	uint16_t local_constraint, bw_val = 0;
+	uint32_t num_pwr_levels, ap_power_type_6g = 0;
+	qdf_freq_t oper_freq, start_freq = 0;
+	struct ch_params ch_params;
+	struct vdev_mlme_obj *mlme_obj;
+
+	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
+	if (!mlme_obj) {
+		pe_err("vdev component object is NULL");
+		return;
+	}
+
+	oper_freq = session->curr_op_freq;
+	bw_val = wlan_reg_get_bw_value(session->ch_width);
+
+	/* start frequency calculation */
+	wlan_reg_set_channel_params_for_freq(mac->pdev, oper_freq, 0,
+					     &ch_params);
+	start_freq = ch_params.mhz_freq_seg0 - bw_val / 2;
+
+	if (mlme_obj->reg_tpc_obj.num_pwr_levels) {
+		is_tpe_present = true;
+		num_pwr_levels = mlme_obj->reg_tpc_obj.num_pwr_levels;
+	} else {
+		is_psd_power = wlan_reg_is_6g_psd_power(mac->pdev);
+		num_pwr_levels = lim_get_num_pwr_levels(is_psd_power,
+							session->ch_width);
+	}
+
+	if (!wlan_reg_is_6ghz_chan_freq(oper_freq))
+		reg_max = wlan_reg_get_channel_reg_power_for_freq(mac->pdev,
+								  oper_freq);
+	else
+		is_6ghz_freq = true;
+
+	ch_params.ch_width = CH_WIDTH_20MHZ;
+
+	for (i = 0; i < num_pwr_levels; i++) {
+		if (is_tpe_present) {
+			if (is_6ghz_freq) {
+				ap_power_type_6g = session->ap_power_type;
+				wlan_reg_get_client_power_for_connecting_ap
+				(mac->pdev, ap_power_type_6g,
+				 mlme_obj->reg_tpc_obj.frequency[i],
+				 &is_psd_power, &reg_max, &eirp_power);
+			}
+		} else {
+			/* center frequency calculation */
+			if (is_psd_power) {
+				mlme_obj->reg_tpc_obj.frequency[i] =
+						start_freq + 10 + (20 * i);
+			} else {
+				wlan_reg_set_channel_params_for_freq
+					(mac->pdev, oper_freq, 0, &ch_params);
+				mlme_obj->reg_tpc_obj.frequency[i] =
+					ch_params.mhz_freq_seg0;
+				ch_params.ch_width =
+					get_next_higher_bw[ch_params.ch_width];
+			}
+			if (is_6ghz_freq) {
+				if (LIM_IS_STA_ROLE(session)) {
+					ap_power_type_6g =
+							session->ap_power_type;
+					wlan_reg_get_client_power_for_connecting_ap
+					(mac->pdev, ap_power_type_6g,
+					 mlme_obj->reg_tpc_obj.frequency[i],
+					 &is_psd_power, &reg_max, &eirp_power);
+				} else {
+					wlan_reg_get_6g_chan_ap_power
+					(mac->pdev,
+					 mlme_obj->reg_tpc_obj.frequency[i],
+					 &is_psd_power, &reg_max, &eirp_power);
+				}
+			}
+		}
+		mlme_obj->reg_tpc_obj.reg_max[i] = reg_max;
+		mlme_obj->reg_tpc_obj.chan_power_info[i].chan_cfreq =
+					mlme_obj->reg_tpc_obj.frequency[i];
+
+		/* max tx power calculation */
+		max_tx_power = mlme_obj->reg_tpc_obj.reg_max[i];
+		/* If AP local power constraint is present */
+		if (mlme_obj->reg_tpc_obj.ap_constraint_power) {
+			local_constraint =
+				mlme_obj->reg_tpc_obj.ap_constraint_power;
+			reg_max = mlme_obj->reg_tpc_obj.reg_max[i];
+			if (is_pwr_constraint_absolute)
+				max_tx_power = QDF_MIN(reg_max,
+						       local_constraint);
+			else
+				max_tx_power = reg_max - local_constraint;
+		}
+		/* If TPE is present */
+		if (is_tpe_present)
+			max_tx_power = QDF_MIN(max_tx_power, (int8_t)
+					       mlme_obj->reg_tpc_obj.tpe[i]);
+
+		/** If firmware updated max tx power is non zero,
+		 * then allocate the min of firmware updated ap tx
+		 * power and max power derived from above mentioned
+		 * parameters.
+		 */
+		if (mlme_obj->mgmt.generic.tx_pwrlimit)
+			max_tx_power =
+				QDF_MIN(max_tx_power, (int8_t)
+					mlme_obj->mgmt.generic.tx_pwrlimit);
+		else
+			pe_err("HW power limit from FW is zero");
+		mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power =
+						(uint8_t)max_tx_power;
+	}
+
+	mlme_obj->reg_tpc_obj.num_pwr_levels = num_pwr_levels;
+	mlme_obj->reg_tpc_obj.is_psd_power = is_psd_power;
+	mlme_obj->reg_tpc_obj.eirp_power = eirp_power;
+	mlme_obj->reg_tpc_obj.power_type_6g = ap_power_type_6g;
+}
+
 /**
  * __lim_process_sme_reassoc_req() - process reassoc req
  *
@@ -3989,6 +4178,7 @@ static void __lim_process_sme_reassoc_req(struct mac_context *mac_ctx,
 	tSirMacCapabilityInfo *ap_cap_info;
 	struct bss_description *bss_desc;
 	uint8_t wmm_mode, value;
+	bool is_pwr_constraint;
 
 	vdev_id = in_req->vdev_id;
 
@@ -4166,7 +4356,11 @@ static void __lim_process_sme_reassoc_req(struct mac_context *mac_ctx,
 			&session_entry->pLimReAssocReq->bssDescription),
 		&session_entry->limReassocBssQosCaps,
 		&session_entry->gLimCurrentBssUapsd,
-		&local_pwr_constraint, session_entry);
+		&local_pwr_constraint, session_entry,
+		&is_pwr_constraint);
+	if (is_pwr_constraint)
+		local_pwr_constraint = reg_max - local_pwr_constraint;
+
 	session_entry->maxTxPower = QDF_MIN(reg_max, (local_pwr_constraint));
 	session_entry->max_11h_pwr =
 		QDF_MIN(lim_get_cfg_max_tx_power(mac_ctx,

+ 5 - 2
core/mac/src/pe/lim/lim_prop_exts_utils.c

@@ -376,7 +376,8 @@ static void lim_check_peer_ldpc_and_update(struct pe_session *session,
 void lim_extract_ap_capability(struct mac_context *mac_ctx, uint8_t *p_ie,
 			       uint16_t ie_len, uint8_t *qos_cap,
 			       uint8_t *uapsd, int8_t *local_constraint,
-			       struct pe_session *session)
+			       struct pe_session *session,
+			       bool *is_pwr_constraint)
 {
 	tSirProbeRespBeacon *beacon_struct;
 	uint8_t ap_bcon_ch_width;
@@ -606,12 +607,14 @@ void lim_extract_ap_capability(struct mac_context *mac_ctx, uint8_t *p_ie,
 
 	if (mac_ctx->mlme_cfg->sta.allow_tpc_from_ap) {
 		if (beacon_struct->powerConstraintPresent) {
-			*local_constraint -=
+			*local_constraint =
 				beacon_struct->localPowerConstraint.
 					localPowerConstraints;
+			*is_pwr_constraint = true;
 		} else {
 			get_local_power_constraint_probe_response(
 				beacon_struct, local_constraint, session);
+			*is_pwr_constraint = false;
 		}
 	}
 

+ 4 - 2
core/mac/src/pe/lim/lim_prop_exts_utils.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2014, 2016, 2018-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, 2016, 2018-2021 The Linux Foundation. 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
@@ -43,6 +43,7 @@
  * @uapsd: pointer to uapsd
  * @local_constraint: Pointer to local power constraint.
  * @session: A pointer to session entry.
+ * @is_pwr_constraint: Check for Power constraint bit in beacon
  *
  * This function is called to extract AP's HCF/WME/WSM capability
  * from the IEs received from it in Beacon/Probe Response frames
@@ -52,7 +53,8 @@
 void
 lim_extract_ap_capability(struct mac_context *mac_ctx, uint8_t *p_ie,
 			  uint16_t ie_len, uint8_t *qos_cap, uint8_t *uapsd,
-			  int8_t *local_constraint, struct pe_session *session);
+			  int8_t *local_constraint, struct pe_session *session,
+			  bool *is_pwr_constraint);
 
 ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode);
 

+ 30 - 2
core/mac/src/pe/lim/lim_utils.h

@@ -147,10 +147,23 @@ QDF_STATUS lim_send_set_max_tx_power_req(struct mac_context *mac,
 		int8_t txPower,
 		struct pe_session *pe_session);
 
+/**
+ * lim_get_num_pwr_levels() - Utility to get number of tx power levels
+ * @is_psd: PSD power check
+ * @ch_width: BSS channel bandwidth
+ *
+ * This function is used to get the number of tx power levels based on
+ * channel bandwidth and psd power.
+ *
+ * Return: number of tx power levels
+ */
+uint32_t lim_get_num_pwr_levels(bool is_psd,
+				enum phy_ch_width ch_width);
+
 /**
  * lim_get_max_tx_power() - Utility to get maximum tx power
  * @mac: mac handle
- * @attr: pointer to buffer containing list of tx powers
+ * @mlme_obj: pointer to struct containing list of tx powers
  *
  * This function is used to get the maximum possible tx power from the list
  * of tx powers mentioned in @attr.
@@ -158,7 +171,22 @@ QDF_STATUS lim_send_set_max_tx_power_req(struct mac_context *mac,
  * Return: Max tx power
  */
 uint8_t lim_get_max_tx_power(struct mac_context *mac,
-			     struct lim_max_tx_pwr_attr *attr);
+			     struct vdev_mlme_obj *mlme_obj);
+/**
+ * lim_calculate_tpc() - Utility to get maximum tx power
+ * @mac: mac handle
+ * @session: PE Session Entry
+ * @is_pwr_constraint_absolute: If local power constraint is an absolute
+ * value or an offset value.
+ *
+ * This function is used to get the maximum possible tx power from the list
+ * of tx powers mentioned in @attr.
+ *
+ * Return: None
+ */
+void lim_calculate_tpc(struct mac_context *mac,
+		       struct pe_session *session,
+		       bool is_pwr_constraint_absolute);
 
 /* AID pool management functions */
 void lim_init_peer_idxpool(struct mac_context *, struct pe_session *);

+ 19 - 24
core/mac/src/pe/rrm/rrm_api.c

@@ -42,6 +42,8 @@
 #include "lim_send_messages.h"
 #include "rrm_global.h"
 #include "rrm_api.h"
+#include "wlan_lmac_if_def.h"
+#include "wlan_reg_services_api.h"
 
 /* -------------------------------------------------------------------- */
 /**
@@ -246,8 +248,8 @@ rrm_process_link_measurement_request(struct mac_context *mac,
 	tSirMacLinkReport LinkReport;
 	tpSirMacMgmtHdr pHdr;
 	int8_t currentRSSI = 0;
-	struct lim_max_tx_pwr_attr tx_pwr_attr = {0};
 	struct vdev_mlme_obj *mlme_obj;
+	struct wlan_lmac_if_reg_tx_ops *tx_ops;
 
 	pe_debug("Received Link measurement request");
 
@@ -257,31 +259,24 @@ rrm_process_link_measurement_request(struct mac_context *mac,
 	}
 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
 
-	tx_pwr_attr.reg_max = pe_session->def_max_tx_pwr;
-	tx_pwr_attr.ap_tx_power = pLinkReq->MaxTxPower.maxTxPower;
+	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
+	if (!mlme_obj) {
+		pe_err("vdev component object is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
 
-	LinkReport.txPower = lim_get_max_tx_power(mac, &tx_pwr_attr);
+	if (pLinkReq->MaxTxPower.maxTxPower !=
+			mlme_obj->reg_tpc_obj.ap_constraint_power) {
 
-	/** If firmware updated max tx power is non zero, respond to rrm link
-	 *  measurement request with min of firmware updated ap tx power and
-	 *  max power derived from lim_get_max_tx_power API.
-	 */
-	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
-	if (mlme_obj && mlme_obj->mgmt.generic.tx_pwrlimit)
-		LinkReport.txPower = QDF_MIN(LinkReport.txPower,
-					mlme_obj->mgmt.generic.tx_pwrlimit);
-
-	if ((LinkReport.txPower != (uint8_t) (pe_session->maxTxPower)) &&
-	    (QDF_STATUS_SUCCESS == rrm_send_set_max_tx_power_req(mac,
-							   LinkReport.txPower,
-							   pe_session))) {
-		pe_warn("maxTx power in link report is not same as local..."
-			" Local: %d Link Request TxPower: %d"
-			" Link Report TxPower: %d",
-			pe_session->maxTxPower, LinkReport.txPower,
-			pLinkReq->MaxTxPower.maxTxPower);
-		pe_session->maxTxPower =
-			LinkReport.txPower;
+		tx_ops = wlan_reg_get_tx_ops(mac->psoc);
+
+		mlme_obj->reg_tpc_obj.ap_constraint_power =
+					pLinkReq->MaxTxPower.maxTxPower;
+		lim_calculate_tpc(mac, pe_session, true);
+
+		if (tx_ops->set_tpc_power)
+			tx_ops->set_tpc_power(mac->psoc, pe_session->vdev_id,
+					      &mlme_obj->reg_tpc_obj);
 	}
 
 	LinkReport.dialogToken = pLinkReq->DialogToken.token;

+ 29 - 24
core/mac/src/pe/sch/sch_beacon_process.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2021 The Linux Foundation. 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
@@ -46,6 +46,9 @@
 
 #include "wma.h"
 
+#include "wlan_lmac_if_def.h"
+#include "wlan_reg_services_api.h"
+
 static void
 ap_beacon_process_5_ghz(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
 			tpSchBeaconStruct bcn_struct,
@@ -702,9 +705,11 @@ static void __sch_beacon_process_for_session(struct mac_context *mac_ctx,
 	tUpdateBeaconParams beaconParams;
 	uint8_t sendProbeReq = false;
 	tpSirMacMgmtHdr pMh = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
-	int8_t regMax = 0, maxTxPower = 0, local_constraint;
-	struct lim_max_tx_pwr_attr tx_pwr_attr = {0};
+	int8_t local_constraint = 0;
 	uint32_t chan_freq = 0;
+	struct vdev_mlme_obj *mlme_obj;
+	struct wlan_lmac_if_reg_tx_ops *tx_ops;
+	bool ap_constraint_change = false, tpe_change = false;
 
 	qdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams));
 	beaconParams.paramChangeBitmap = 0;
@@ -716,6 +721,7 @@ static void __sch_beacon_process_for_session(struct mac_context *mac_ctx,
 			return;
 	}
 
+	tx_ops = wlan_reg_get_tx_ops(mac_ctx->psoc);
 	/*
 	 * For vht session, if opermode ie or vht oper IE is present
 	 * bandwidth change will be taken care using these vht IEs.
@@ -729,39 +735,38 @@ static void __sch_beacon_process_for_session(struct mac_context *mac_ctx,
 	if (LIM_IS_STA_ROLE(session))
 		sch_bcn_process_sta_opmode(mac_ctx, bcn, rx_pkt_info, session,
 					    &beaconParams, &sendProbeReq, pMh);
-	/* Obtain the Max Tx power for the current regulatory  */
-	regMax = wlan_reg_get_channel_reg_power_for_freq(
-				mac_ctx->pdev, session->curr_op_freq);
 
-	local_constraint = regMax;
+	lim_parse_tpe_ie(mac_ctx, session, bcn->transmit_power_env,
+			 bcn->num_transmit_power_env, &bcn->he_op,
+			 &tpe_change);
+
+	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
+	if (!mlme_obj) {
+		pe_err("vdev component object is NULL");
+		return;
+	}
 
 	if (mac_ctx->mlme_cfg->sta.allow_tpc_from_ap) {
 		get_local_power_constraint_beacon(bcn, &local_constraint);
 
 		if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
-				bcn->powerConstraintPresent) {
-			local_constraint = regMax;
-			local_constraint -=
+				bcn->powerConstraintPresent)
+			local_constraint =
 				bcn->localPowerConstraint.localPowerConstraints;
-			}
 	}
 
-	tx_pwr_attr.reg_max = regMax;
-	tx_pwr_attr.ap_tx_power = local_constraint;
-	tx_pwr_attr.frequency = session->curr_op_freq;
+	if (local_constraint != mlme_obj->reg_tpc_obj.ap_constraint_power) {
+		mlme_obj->reg_tpc_obj.ap_constraint_power = local_constraint;
+		ap_constraint_change = true;
+	}
 
-	maxTxPower = lim_get_max_tx_power(mac_ctx, &tx_pwr_attr);
+	if (ap_constraint_change || tpe_change) {
+		lim_calculate_tpc(mac_ctx, session, false);
 
-	/* If maxTxPower is increased or decreased */
-	if (maxTxPower != session->maxTxPower) {
-		pe_debug("Local power constraint change, Updating new maxTx power %d from old pwr %d (regMax %d local %d)",
-			 maxTxPower, session->maxTxPower, regMax,
-			 local_constraint);
-		if (lim_send_set_max_tx_power_req(mac_ctx, maxTxPower, session)
-		    == QDF_STATUS_SUCCESS)
-			session->maxTxPower = maxTxPower;
+		if (tx_ops->set_tpc_power)
+			tx_ops->set_tpc_power(mac_ctx->psoc, session->vdev_id,
+					      &mlme_obj->reg_tpc_obj);
 	}
-
 	/* Indicate to LIM that Beacon is received */
 	if (bcn->HTInfo.present) {
 		chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev,

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

@@ -3446,22 +3446,6 @@ wma_vdev_set_bss_params(tp_wma_handle wma, int vdev_id,
 	if (QDF_IS_STATUS_ERROR(ret))
 		wma_err("failed to set WMI_VDEV_PARAM_DTIM_PERIOD");
 
-	if (!maxTxPower)
-		wma_warn("Setting Tx power limit to 0");
-
-	wma_nofl_debug("TXP[W][set_bss_params]: %d", maxTxPower);
-
-	if (maxTxPower != INVALID_TXPOWER) {
-		ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
-					 WMI_VDEV_PARAM_TX_PWRLIMIT,
-					 maxTxPower);
-		if (QDF_IS_STATUS_ERROR(ret))
-			wma_err("failed to set WMI_VDEV_PARAM_TX_PWRLIMIT");
-		else
-			mlme_set_max_reg_power(intr[vdev_id].vdev, maxTxPower);
-	} else {
-		wma_err("Invalid max Tx power");
-	}
 	/* Slot time */
 	if (shortSlotTimeSupported)
 		slot_time = WMI_VDEV_SLOT_TIME_SHORT;
@@ -3604,7 +3588,6 @@ QDF_STATUS wma_post_vdev_start_setup(uint8_t vdev_id)
 	struct wma_txrx_node *intr;
 	struct vdev_mlme_obj *mlme_obj;
 	struct wlan_objmgr_vdev *vdev;
-	uint8_t bss_power;
 
 	if (!wma)
 		return QDF_STATUS_E_FAILURE;
@@ -3638,14 +3621,12 @@ QDF_STATUS wma_post_vdev_start_setup(uint8_t vdev_id)
 		     vdev->vdev_mlme.des_chan,
 		     sizeof(struct wlan_channel));
 
-	bss_power = wlan_reg_get_channel_reg_power_for_freq(wma->pdev,
-							    vdev->vdev_mlme.bss_chan->ch_freq);
 	wma_vdev_set_bss_params(wma, vdev_id,
 				mlme_obj->proto.generic.beacon_interval,
 				mlme_obj->proto.generic.dtim_period,
 				mlme_obj->proto.generic.slot_time,
 				mlme_obj->proto.generic.protection_mode,
-				bss_power, 0);
+				0, 0);
 
 	wma_vdev_set_he_bss_params(wma, vdev_id,
 				   &mlme_obj->proto.he_ops_info);
@@ -3936,8 +3917,7 @@ QDF_STATUS wma_send_peer_assoc_req(struct bss_params *add_bss)
 				add_bss->beaconInterval,
 				add_bss->dtimPeriod,
 				add_bss->shortSlotTimeSupported,
-				add_bss->llbCoexist,
-				add_bss->maxTxPower,
+				add_bss->llbCoexist, 0,
 				add_bss->bss_max_idle_period);
 
 	mlme_obj = wlan_vdev_mlme_get_cmpt_obj(iface->vdev);
@@ -4334,7 +4314,6 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	struct wma_txrx_node *iface;
-	int8_t maxTxPower;
 	int ret = 0;
 	struct wma_target_req *msg;
 	bool peer_assoc_cnf = false;
@@ -4456,12 +4435,11 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params)
 			wma_set_peer_pmf_status(wma, params->bssId, true);
 		}
 	}
-	maxTxPower = params->maxTxPower;
+
 	wma_vdev_set_bss_params(wma, params->smesessionId,
 				iface->beaconInterval, iface->dtimPeriod,
 				iface->shortSlotTimeSupported,
-				iface->llbCoexist, maxTxPower,
-				iface->bss_max_idle_period);
+				iface->llbCoexist, 0, iface->bss_max_idle_period);
 
 	params->csaOffloadEnable = 0;
 	if (wmi_service_enabled(wma->wmi_handle,