瀏覽代碼

qcacld-3.0: Disable puncture in US LPI mode

Disable puncture in US LPI mode per FCC request.
If bad FCC AP is detected, send WMI_VDEV_PARAM_CHWIDTH_WITH_NOTIFY with
reduced bw after setkey is done.

Also add the same bad FCC AP detection logic in HDD where bw increase req
from SS framework is handled.

When handle beacon update, also FCC AP detection logic to avoid wrong
channel switch.
If the AP removes or reduces puncturing pattern in new beacon, send
WMI_VDEV_PARAM_CHWIDTH_WITH_NOTIFY with increased bw.

For roaming case, after roaming, host will receive new beacon with new
bpcc, same as beacon update, use the same bad FCC AP detection logic and
send WMI_VDEV_PARAM_CHWIDTH_WITH_NOTIFY with updted bw right away or after
setkey is done (in case of hybrid roaming like OWE).

Change-Id: I6e85de879575d5c0a1960527f9018b4b33bf18d6
CRs-Fixed: 3631634
Jianmin Zhu 1 年之前
父節點
當前提交
213929b71e

+ 20 - 0
components/mlme/core/inc/wlan_mlme_main.h

@@ -825,6 +825,7 @@ struct enhance_roam_info {
  *				operation on bss color collision detection
  * @bss_color_change_runtime_lock: runtime lock to complete bss color change
  * @disconnect_runtime_lock: runtime lock to complete disconnection
+ * @best_6g_power_type: best 6g power type
  */
 struct mlme_legacy_priv {
 	bool chan_switch_in_progress;
@@ -896,6 +897,7 @@ struct mlme_legacy_priv {
 	qdf_wake_lock_t bss_color_change_wakelock;
 	qdf_runtime_lock_t bss_color_change_runtime_lock;
 	qdf_runtime_lock_t disconnect_runtime_lock;
+	enum reg_6g_ap_type best_6g_power_type;
 };
 
 /**
@@ -1116,6 +1118,24 @@ void mlme_set_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev, bool flag);
  */
 bool mlme_get_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * mlme_set_best_6g_power_type() - Set best 6g power type
+ * @vdev: vdev pointer
+ * @best_6g_power_type: best 6g power type
+ *
+ * Return: None
+ */
+void mlme_set_best_6g_power_type(struct wlan_objmgr_vdev *vdev,
+				 enum reg_6g_ap_type best_6g_power_type);
+
+/**
+ * mlme_get_best_6g_power_type() - Get best 6g power type
+ * @vdev: vdev pointer
+ *
+ * Return: value of best 6g power type
+ */
+enum reg_6g_ap_type mlme_get_best_6g_power_type(struct wlan_objmgr_vdev *vdev);
+
 /**
  * mlme_set_reconn_after_assoc_timeout_flag() - Set reconn after assoc timeout
  * flag

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

@@ -4299,6 +4299,33 @@ bool mlme_get_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev)
 	return mlme_priv->follow_ap_edca;
 }
 
+void mlme_set_best_6g_power_type(struct wlan_objmgr_vdev *vdev,
+				 enum reg_6g_ap_type best_6g_power_type)
+{
+	struct mlme_legacy_priv *mlme_priv;
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv) {
+		mlme_legacy_err("vdev legacy private object is NULL");
+		return;
+	}
+
+	mlme_priv->best_6g_power_type = best_6g_power_type;
+}
+
+enum reg_6g_ap_type mlme_get_best_6g_power_type(struct wlan_objmgr_vdev *vdev)
+{
+	struct mlme_legacy_priv *mlme_priv;
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv) {
+		mlme_legacy_err("vdev legacy private object is NULL");
+		return REG_VERY_LOW_POWER_AP;
+	}
+
+	return mlme_priv->best_6g_power_type;
+}
+
 void mlme_set_reconn_after_assoc_timeout_flag(struct wlan_objmgr_psoc *psoc,
 					      uint8_t vdev_id, bool flag)
 {

+ 43 - 0
components/mlme/dispatcher/inc/wlan_mlme_api.h

@@ -1318,6 +1318,33 @@ bool wlan_mlme_get_usr_disable_sta_eht(struct wlan_objmgr_psoc *psoc);
  */
 void wlan_mlme_set_usr_disable_sta_eht(struct wlan_objmgr_psoc *psoc,
 				       bool disable);
+
+/**
+ * wlan_mlme_update_bw_no_punct() - update connected VDEV
+ * channel bandwidth without puncture bitmap for FCC requirement
+ * @psoc: pointer to SOC object
+ * @vdev_id: vdev id
+ *
+ * Return: none
+ */
+QDF_STATUS
+wlan_mlme_update_bw_no_punct(struct wlan_objmgr_psoc *psoc,
+			     uint8_t vdev_id);
+
+/**
+ * wlan_mlme_get_bw_no_punct() - Get connected VDEV
+ * channel bandwidth without puncture bitmap for FCC requirement
+ * @psoc: pointer to SOC object
+ * @vdev: pointer to vdev
+ * @bss_chan: bss chan with puncture
+ * @new_ch_width: pointer to new channel bandwidth without puncture
+ * Return: none
+ */
+QDF_STATUS
+wlan_mlme_get_bw_no_punct(struct wlan_objmgr_psoc *psoc,
+			  struct wlan_objmgr_vdev *vdev,
+			  struct wlan_channel *bss_chan,
+			  enum phy_ch_width *new_ch_width);
 #else
 static inline
 bool wlan_mlme_get_epcs_capability(struct wlan_objmgr_psoc *psoc)
@@ -1341,6 +1368,22 @@ void wlan_mlme_set_usr_disable_sta_eht(struct wlan_objmgr_psoc *psoc,
 				       bool disable)
 {
 }
+
+static inline QDF_STATUS
+wlan_mlme_update_bw_no_punct(struct wlan_objmgr_psoc *psoc,
+			     uint8_t vdev_id)
+{
+	return QDF_STATUS_E_INVAL;
+}
+
+static inline QDF_STATUS
+wlan_mlme_get_bw_no_punct(struct wlan_objmgr_psoc *psoc,
+			  struct wlan_objmgr_vdev *vdev,
+			  struct wlan_channel *bss_chan,
+			  enum phy_ch_width *new_ch_width)
+{
+	return QDF_STATUS_E_INVAL;
+}
 #endif
 
 /**

+ 91 - 0
components/mlme/dispatcher/src/wlan_mlme_api.c

@@ -39,6 +39,7 @@
 #include "wmi_unified_vdev_api.h"
 #include "wlan_mlme_api.h"
 #include "../../core/src/wlan_cp_stats_defs.h"
+#include "wlan_reg_services_api.h"
 
 /* quota in milliseconds */
 #define MCC_DUTY_CYCLE 70
@@ -8003,3 +8004,93 @@ wlan_mlme_send_csa_event_status_ind(struct wlan_objmgr_vdev *vdev,
 {
 	return wlan_mlme_send_csa_event_status_ind_cmd(vdev, csa_status);
 }
+
+#ifdef WLAN_FEATURE_11BE
+QDF_STATUS
+wlan_mlme_get_bw_no_punct(struct wlan_objmgr_psoc *psoc,
+			  struct wlan_objmgr_vdev *vdev,
+			  struct wlan_channel *bss_chan,
+			  enum phy_ch_width *new_ch_width)
+{
+	uint16_t new_punct_bitmap = 0;
+	enum phy_ch_width ch_width;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	uint8_t country[REG_ALPHA2_LEN + 1];
+
+	wlan_reg_read_current_country(psoc, country);
+
+	if (!wlan_reg_is_6ghz_chan_freq(bss_chan->ch_freq) ||
+	    !bss_chan->puncture_bitmap ||
+	    qdf_mem_cmp(country, "US", REG_ALPHA2_LEN) ||
+	    mlme_get_best_6g_power_type(vdev) != REG_INDOOR_AP ||
+	    !IS_WLAN_PHYMODE_EHT(bss_chan->ch_phymode))
+		goto err;
+
+	ch_width = bss_chan->ch_width;
+
+	while (ch_width != CH_WIDTH_INVALID) {
+		status = wlan_reg_extract_puncture_by_bw(bss_chan->ch_width,
+							 bss_chan->puncture_bitmap,
+							 bss_chan->ch_freq,
+							 bss_chan->ch_cfreq2,
+							 ch_width,
+							 &new_punct_bitmap);
+		if (QDF_IS_STATUS_SUCCESS(status) && new_punct_bitmap)
+			ch_width = wlan_get_next_lower_bandwidth(ch_width);
+		else
+			break;
+	}
+
+	if (ch_width == bss_chan->ch_width)
+		return QDF_STATUS_E_FAILURE;
+
+	mlme_debug("freq %d ccfs2 %d punct 0x%x BW old %d, new %d",
+		   bss_chan->ch_freq, bss_chan->ch_cfreq2, bss_chan->puncture_bitmap,
+		   bss_chan->ch_width, ch_width);
+
+	*new_ch_width = ch_width;
+	bss_chan->puncture_bitmap = 0;
+err:
+	return status;
+}
+
+QDF_STATUS
+wlan_mlme_update_bw_no_punct(struct wlan_objmgr_psoc *psoc,
+			     uint8_t vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	enum phy_ch_width new_ch_width;
+	struct wlan_objmgr_pdev *pdev;
+
+	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
+					  WLAN_MLME_NB_ID);
+	if (!pdev) {
+		sme_err("pdev is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
+						    WLAN_MLME_NB_ID);
+	if (!vdev) {
+		mlme_err("VDEV not found for vdev id : %d", vdev_id);
+		goto rel_pdev;
+	}
+
+	status = wlan_mlme_get_bw_no_punct(psoc, vdev,
+					   wlan_vdev_mlme_get_des_chan(vdev),
+					   &new_ch_width);
+	if (QDF_IS_STATUS_ERROR(status))
+		goto rel_vdev;
+
+	status = wlan_mlme_send_ch_width_update_with_notify(psoc,
+							    vdev,
+							    vdev_id,
+							    new_ch_width);
+rel_vdev:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
+rel_pdev:
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_MLME_NB_ID);
+
+	return status;
+}
+#endif

+ 9 - 0
components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c

@@ -424,6 +424,7 @@ ucfg_mlme_send_ch_width_update_with_notify(struct wlan_objmgr_psoc *psoc,
 	struct wlan_objmgr_vdev *link_vdev;
 	bool is_mlo_link = false;
 	uint8_t link_vdev_id;
+	enum phy_ch_width new_ch_width;
 
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
 						    WLAN_MLME_OBJMGR_ID);
@@ -450,11 +451,19 @@ ucfg_mlme_send_ch_width_update_with_notify(struct wlan_objmgr_psoc *psoc,
 		}
 		is_mlo_link = true;
 		link_vdev_id = wlan_vdev_get_id(link_vdev);
+
+		status = wlan_mlme_get_bw_no_punct(psoc,
+						   link_vdev,
+						   wlan_vdev_mlme_get_des_chan(link_vdev),
+						   &new_ch_width);
+		if (QDF_IS_STATUS_SUCCESS(status) && ch_width > new_ch_width)
+			ch_width = new_ch_width;
 	} else {
 		link_vdev = vdev;
 		link_vdev_id = vdev_id;
 		mlme_legacy_debug("vdev mlme is not mlo vdev");
 	}
+
 	status = wlan_mlme_send_ch_width_update_with_notify(psoc, link_vdev,
 							    link_vdev_id,
 							    ch_width);

+ 38 - 6
core/mac/src/pe/lim/lim_process_beacon_frame.c

@@ -302,6 +302,7 @@ void lim_process_beacon_eht_op(struct pe_session *session,
 {
 	uint16_t ori_punc = 0;
 	enum phy_ch_width ori_bw = CH_WIDTH_INVALID;
+	enum phy_ch_width ori_bw_no_punct = CH_WIDTH_INVALID;
 	uint8_t cb_mode;
 	enum phy_ch_width new_bw;
 	bool update_allow;
@@ -316,6 +317,10 @@ void lim_process_beacon_eht_op(struct pe_session *session,
 	tDot11fIEhe_op *he_op;
 	uint8_t  ch_width;
 	uint8_t chan_id;
+	struct wlan_channel bss_chan = {0};
+	struct wlan_channel *current_chan = NULL;
+	uint8_t band_mask;
+	uint32_t ch_cfreq2 = 0;
 
 	if (!bcn_ptr || !session || !session->mac_ctx || !session->vdev) {
 		pe_err("invalid input parameters");
@@ -342,17 +347,44 @@ void lim_process_beacon_eht_op(struct pe_session *session,
 		return;
 	}
 	/* handle beacon IE for 11be non-mlo case */
-	if (eht_op->disabled_sub_chan_bitmap_present) {
-		ori_punc = QDF_GET_BITS(
-		    eht_op->disabled_sub_chan_bitmap[0][0], 0, 8);
-		ori_punc |= QDF_GET_BITS(
-		    eht_op->disabled_sub_chan_bitmap[0][1], 0, 8) << 8;
-	}
 	if (eht_op->eht_op_information_present) {
 		ori_bw = wlan_mlme_convert_eht_op_bw_to_phy_ch_width(
 						eht_op->channel_width);
 		ccfs0 = eht_op->ccfs0;
 		ccfs1 = eht_op->ccfs1;
+		if (eht_op->disabled_sub_chan_bitmap_present) {
+			ori_punc = QDF_GET_BITS(eht_op->disabled_sub_chan_bitmap[0][0], 0, 8);
+			ori_punc |= QDF_GET_BITS(eht_op->disabled_sub_chan_bitmap[0][1], 0, 8) << 8;
+
+			bss_chan.ch_freq = bcn_ptr->chan_freq;
+			bss_chan.puncture_bitmap = ori_punc;
+			bss_chan.ch_width = ori_bw;
+			bss_chan.ch_phymode = WLAN_PHYMODE_11BEA_EHT160;
+
+			if (ori_bw == CH_WIDTH_320MHZ &&
+			    WLAN_REG_IS_6GHZ_CHAN_FREQ(bcn_ptr->chan_freq)) {
+				band_mask = BIT(REG_BAND_6G);
+				ch_cfreq2 = wlan_reg_chan_band_to_freq(mac_ctx->pdev,
+								       ccfs1,
+								       band_mask);
+				bss_chan.ch_cfreq2 = ch_cfreq2;
+			}
+
+			status = wlan_mlme_get_bw_no_punct(mac_ctx->psoc,
+							   vdev,
+							   &bss_chan,
+							   &ori_bw_no_punct);
+			current_chan = wlan_vdev_mlme_get_bss_chan(vdev);
+			if (QDF_IS_STATUS_SUCCESS(status)) {
+				if (ori_bw_no_punct != current_chan->ch_width) {
+					status = wlan_mlme_send_ch_width_update_with_notify(mac_ctx->psoc,
+											    vdev,
+											    session->vdev_id,
+											    ori_bw_no_punct);
+				}
+				return;
+			}
+		}
 	} else if (he_op->vht_oper_present) {
 		ch_width = he_op->vht_oper.info.chan_width;
 		ccfs0 = he_op->vht_oper.info.center_freq_seg0;

+ 3 - 0
core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c

@@ -48,6 +48,7 @@
 #include "wlan_mlo_mgr_sta.h"
 #include "utils_mlo.h"
 #include "wlan_mlo_mgr_roam.h"
+#include "wlan_mlme_api.h"
 
 #define MAX_SUPPORTED_PEERS_WEP 16
 
@@ -1297,6 +1298,8 @@ void lim_process_mlm_set_keys_cnf(struct mac_context *mac, uint32_t *msg_buf)
 				     1,
 				     (tSirResultCodes) pMlmSetKeysCnf->resultCode,
 				     pe_session, pe_session->smeSessionId);
+
+	wlan_mlme_update_bw_no_punct(mac->psoc, pe_session->vdev_id);
 } /*** end lim_process_mlm_set_keys_cnf() ***/
 
 void lim_update_lost_link_rssi(struct mac_context *mac, uint32_t rssi)

+ 2 - 0
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -73,6 +73,7 @@
 #include "wlan_psoc_mlme_api.h"
 #include "wma_he.h"
 #include "wlan_mlo_mgr_sta.h"
+#include "wlan_mlme_main.h"
 #ifdef WLAN_FEATURE_11BE_MLO
 #include <wlan_mlo_mgr_peer.h>
 #endif
@@ -3442,6 +3443,7 @@ lim_fill_pe_session(struct mac_context *mac_ctx, struct pe_session *session,
 			goto send;
 		}
 		session->best_6g_power_type = power_type_6g;
+		mlme_set_best_6g_power_type(session->vdev, power_type_6g);
 
 		lim_iterate_triplets(ie_struct->Country);
 

+ 4 - 28
core/mac/src/pe/lim/lim_utils.c

@@ -10987,28 +10987,14 @@ static void lim_update_ap_puncture(struct pe_session *session,
 	}
 }
 
-/**
- * lim_update_des_chan_puncture() - set puncture_bitmap of des_chan
- * @des_chan: pointer to wlan_channel
- * @ch_params: pointer to ch_params
- *
- * Return: void
- */
-static void lim_update_des_chan_puncture(struct wlan_channel *des_chan,
-					 struct ch_params *ch_params)
+void lim_update_des_chan_puncture(struct wlan_channel *des_chan,
+				  struct ch_params *ch_params)
 {
 	des_chan->puncture_bitmap = ch_params->reg_punc_bitmap;
 }
 
-/**
- * lim_overwrite_sta_puncture() - overwrite STA puncture with AP puncture
- * @session: session
- * @@ch_param: pointer to ch_params
- *
- * Return: void
- */
-static void lim_overwrite_sta_puncture(struct pe_session *session,
-				       struct ch_params *ch_param)
+void lim_overwrite_sta_puncture(struct pe_session *session,
+				struct ch_params *ch_param)
 {
 	uint16_t new_punc = 0;
 
@@ -11028,16 +11014,6 @@ static void lim_update_ap_puncture(struct pe_session *session,
 				   struct ch_params *ch_params)
 {
 }
-
-static void lim_update_des_chan_puncture(struct wlan_channel *des_chan,
-					 struct ch_params *ch_params)
-{
-}
-
-static void lim_overwrite_sta_puncture(struct pe_session *session,
-				       struct ch_params *ch_params)
-{
-}
 #endif
 
 QDF_STATUS lim_pre_vdev_start(struct mac_context *mac,

+ 32 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -2139,6 +2139,26 @@ bool lim_is_session_chwidth_320mhz(struct pe_session *session);
  */
 void
 lim_update_eht_caps_mcs(struct mac_context *mac, struct pe_session *session);
+
+/**
+ * lim_update_des_chan_puncture() - set puncture_bitmap of des_chan
+ * @des_chan: pointer to wlan_channel
+ * @ch_params: pointer to ch_params
+ *
+ * Return: void
+ */
+void lim_update_des_chan_puncture(struct wlan_channel *des_chan,
+				  struct ch_params *ch_params);
+
+/**
+ * lim_overwrite_sta_puncture() - overwrite STA puncture with AP puncture
+ * @session: session
+ * @@ch_param: pointer to ch_params
+ *
+ * Return: void
+ */
+void lim_overwrite_sta_puncture(struct pe_session *session,
+				struct ch_params *ch_param);
 #else
 static inline
 void lim_update_tdls_sta_eht_capable(struct mac_context *mac,
@@ -2328,6 +2348,18 @@ static inline void
 lim_update_eht_caps_mcs(struct mac_context *mac, struct pe_session *session)
 {
 }
+
+static inline void
+lim_update_des_chan_puncture(struct wlan_channel *des_chan,
+			     struct ch_params *ch_params)
+{
+}
+
+static inline void
+lim_overwrite_sta_puncture(struct pe_session *session,
+			   struct ch_params *ch_param)
+{
+}
 #endif /* WLAN_FEATURE_11BE */
 
 #ifdef WLAN_FEATURE_11BE_MLO

+ 2 - 0
core/mac/src/pe/sch/sch_beacon_process.c

@@ -51,6 +51,7 @@
 #include "wlan_lmac_if_def.h"
 #include "wlan_reg_services_api.h"
 #include "wlan_mlo_mgr_sta.h"
+#include "wlan_mlme_main.h"
 
 static void
 ap_beacon_process_5_ghz(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
@@ -685,6 +686,7 @@ static void __sch_beacon_process_for_session(struct mac_context *mac_ctx,
 			return;
 
 		session->best_6g_power_type = pwr_type_6g;
+		mlme_set_best_6g_power_type(session->vdev, pwr_type_6g);
 	}
 
 	/*