Kaynağa Gözat

qcacld-3.0: Update NO_IR flag of indoor channel dynamically

In current design of sta+sap scc on indoor channels, the NO_IR
flag of all the indoor channels are removed during init.
Then, based on the operations on the SAP interface, the
SAP concurrency will be decided in host driver.

However, some userspace p2p applications, do not query the
pcl list from driver, therefore standalone P2P GO are sometimes
brought up in indoor channels.

To fix this:
1. Upon STA connect: Remove the NO_IR flags only from the
indoor channels to which the STA is connected.
2. Upon STA disconnect: Add the NO_IR flag back to the
disconnected channel.
3. Upon STA roam/csa:
    a) Add the NO_IR to the new channel if it is indoor.
    b) Remove the NO_IR of the previously connected channel
       once the SAP/GO(if present) moves out of the indoor channel.
4. The NO_IR flags should be removed for all the bonded channels
on which the STA is active.
5. In indoor concurrency cases, add logic in the SAP start to
limit the channel width with the STA interface bandwidth. Since,
only the bonded channels are active channels.

Change-Id: Ib0b30e1f17d0eb944c72b26bb679bf7447b9032f
CRs-Fixed: 3296208
Surya Prakash Sivaraj 2 yıl önce
ebeveyn
işleme
9387f3974b

+ 51 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -2435,6 +2435,17 @@ bool policy_mgr_is_any_mode_active_on_band_along_with_session(
 		struct wlan_objmgr_psoc *psoc, uint8_t session_id,
 		enum policy_mgr_band band);
 
+/**
+ * policy_mgr_get_bw_by_session_id() - Get channel width for a given session ID
+ * @psoc: PSOC object information
+ * @session_id: Session ID
+ *
+ * Return: channel width of the session
+ */
+enum phy_ch_width
+policy_mgr_get_bw_by_session_id(struct wlan_objmgr_psoc *psoc,
+				uint8_t session_id);
+
 /**
  * policy_mgr_get_chan_by_session_id() - Get channel for a given session ID
  * @psoc: PSOC object information
@@ -4736,4 +4747,44 @@ qdf_freq_t policy_mgr_get_ll_sap_freq(struct wlan_objmgr_psoc *psoc);
 bool policy_mgr_is_ll_sap_concurrency_valid(struct wlan_objmgr_psoc *psoc,
 					    qdf_freq_t freq,
 					    enum policy_mgr_con_mode mode);
+
+/**
+ * policy_mgr_update_indoor_concurrency() - Function to update the indoor
+ * concurrency related regulatory changes
+ *
+ * @psoc: pointer to psoc
+ * @vdev_id: vdev id
+ * @discon_freq: disconnect frequency
+ * @type: enum indoor_conc_update_type
+ *
+ * Return: None
+ */
+void
+policy_mgr_update_indoor_concurrency(struct wlan_objmgr_psoc *psoc,
+				     uint8_t vdev_id,
+				     uint32_t discon_freq,
+				     enum indoor_conc_update_type type);
+/**
+ * policy_mgr_is_conc_sap_present_on_sta_freq() - Function to check if
+ * SAP or GO exists on the STA frequency
+ *
+ * @psoc: pointer to psoc
+ * @mode: interface mode
+ * @ch_freq: channel frequency
+ *
+ * Return: AP mode exists
+ */
+bool
+policy_mgr_is_conc_sap_present_on_sta_freq(struct wlan_objmgr_psoc *psoc,
+					   enum policy_mgr_con_mode mode,
+					   uint32_t ch_freq);
+
+/**
+ * policy_mgr_get_connection_count_with_ch_freq() - Get number of active
+ * connections on the channel frequecy
+ * @ch_freq: channel frequency
+ *
+ * Return: number of active connection on the specific frequency
+ */
+uint32_t policy_mgr_get_connection_count_with_ch_freq(uint32_t ch_freq);
 #endif /* __WLAN_POLICY_MGR_API_H */

+ 20 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h

@@ -1649,4 +1649,24 @@ struct sta_ap_intf_check_work_ctx {
 	struct sap_plus_go_force_scc sap_plus_go_force_scc;
 };
 
+/**
+ * enum indoor_conc_update_type - Indoor concurrency update type
+ * @CONNECT - On a new STA connection
+ * @DISCONNECT_WITHOUT_CONCURRENCY - On a STA disconnection with no active
+ * sessions on the same frequency
+ * @DISCONNECT_WITH_CONCURRENCY - On a STA disconnection with an active
+ * session on the same frequency
+ * @SWITCH_WITH_CONCURRENCY - On a STA roam or CSA to a different channel
+ * with a concurrent SAP on previous frequency
+ * @SWITCH_WITHOUT_CONCURRENCY - On a STA roam or CSA to a different channel
+ * without any concurrent SAP on previous frequency
+ */
+enum indoor_conc_update_type {
+	CONNECT,
+	DISCONNECT_WITHOUT_CONCURRENCY,
+	DISCONNECT_WITH_CONCURRENCY,
+	SWITCH_WITHOUT_CONCURRENCY,
+	SWITCH_WITH_CONCURRENCY,
+};
+
 #endif /* __WLAN_POLICY_MGR_PUBLIC_STRUCT_H */

+ 10 - 1
components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c

@@ -333,7 +333,7 @@ QDF_STATUS policy_mgr_update_connection_info(struct wlan_objmgr_psoc *psoc,
 					uint32_t vdev_id)
 {
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
-	uint32_t conn_index = 0, ch_freq;
+	uint32_t conn_index = 0, ch_freq, cur_freq;
 	bool found = false;
 	struct policy_mgr_vdev_entry_info conn_table_entry;
 	enum policy_mgr_chain_mode chain_mask = POLICY_MGR_ONE_ONE;
@@ -380,6 +380,8 @@ QDF_STATUS policy_mgr_update_connection_info(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	cur_freq = pm_conc_connection_list[conn_index].freq;
+
 	mode = policy_mgr_get_mode(conn_table_entry.type,
 					conn_table_entry.sub_type);
 	ch_freq = conn_table_entry.mhz;
@@ -411,6 +413,13 @@ QDF_STATUS policy_mgr_update_connection_info(struct wlan_objmgr_psoc *psoc,
 	policy_mgr_handle_ml_sta_links_on_vdev_up_csa(psoc,
 				policy_mgr_get_qdf_mode_from_pm(mode), vdev_id);
 
+	if (policy_mgr_is_conc_sap_present_on_sta_freq(psoc, mode, cur_freq))
+		policy_mgr_update_indoor_concurrency(psoc, vdev_id, 0,
+						     SWITCH_WITH_CONCURRENCY);
+	else
+		policy_mgr_update_indoor_concurrency(psoc, vdev_id, cur_freq,
+						     SWITCH_WITHOUT_CONCURRENCY);
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 176 - 2
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -43,6 +43,7 @@
 #include "wlan_mlo_mgr_sta.h"
 #include "wlan_cm_ucfg_api.h"
 #include "wlan_cm_roam_api.h"
+#include "wlan_mlme_ucfg_api.h"
 
 /* invalid channel id. */
 #define INVALID_CHANNEL_ID 0
@@ -3920,6 +3921,8 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc,
 
 	policy_mgr_dump_current_concurrency(psoc);
 
+	policy_mgr_update_indoor_concurrency(psoc, session_id, 0, CONNECT);
+
 	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 	policy_mgr_handle_ml_sta_links_on_vdev_up_csa(psoc, mode, session_id);
 }
@@ -3987,7 +3990,7 @@ QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc,
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
 	QDF_STATUS qdf_status;
 	bool mcc_mode;
-	uint32_t session_count;
+	uint32_t session_count, cur_freq;
 
 	pm_ctx = policy_mgr_get_context(psoc);
 	if (!pm_ctx) {
@@ -4011,7 +4014,6 @@ QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc,
 		policy_mgr_dump_current_concurrency(psoc);
 		return qdf_status;
 	}
-
 	policy_mgr_update_sta_scc_info_for_later_check(pm_ctx,
 						       mode,
 						       session_id);
@@ -4029,6 +4031,9 @@ QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc,
 	default:
 		break;
 	}
+
+	policy_mgr_get_chan_by_session_id(psoc, session_id, &cur_freq);
+
 	policy_mgr_decr_connection_count(psoc, session_id);
 	session_count = pm_ctx->no_of_active_sessions[mode];
 	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
@@ -4093,6 +4098,10 @@ QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc,
 	    mode == QDF_STA_MODE || mode == QDF_P2P_CLIENT_MODE)
 		policy_mgr_update_dfs_master_dynamic_enabled(psoc, session_id);
 
+	if (!pm_ctx->last_disconn_sta_freq)
+		policy_mgr_update_indoor_concurrency(psoc, session_id, cur_freq,
+						     DISCONNECT_WITHOUT_CONCURRENCY);
+
 	return qdf_status;
 }
 
@@ -7700,6 +7709,32 @@ send_status:
 	return status;
 }
 
+enum phy_ch_width
+policy_mgr_get_bw_by_session_id(struct wlan_objmgr_psoc *psoc,
+				uint8_t session_id)
+{
+	uint32_t i;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	enum hw_mode_bandwidth bw = HW_MODE_BW_NONE;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return CH_WIDTH_INVALID;
+	}
+
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (i = 0; i < MAX_NUMBER_OF_CONC_CONNECTIONS; i++) {
+		if (pm_conc_connection_list[i].vdev_id == session_id &&
+		    pm_conc_connection_list[i].in_use) {
+			bw = pm_conc_connection_list[i].bw;
+			break;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+	return policy_mgr_get_ch_width(bw);
+}
+
 QDF_STATUS policy_mgr_get_chan_by_session_id(struct wlan_objmgr_psoc *psoc,
 					     uint8_t session_id,
 					     uint32_t *ch_freq)
@@ -9403,3 +9438,142 @@ bool policy_mgr_is_ll_sap_concurrency_valid(struct wlan_objmgr_psoc *psoc,
 
 	return true;
 }
+
+void
+policy_mgr_update_indoor_concurrency(struct wlan_objmgr_psoc *psoc,
+				     uint8_t vdev_id,
+				     uint32_t discon_freq,
+				     enum indoor_conc_update_type type)
+{
+	uint32_t ch_freq;
+	enum QDF_OPMODE mode;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
+	bool indoor_support = false;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid pm context");
+		return;
+	}
+
+	ucfg_mlme_get_indoor_channel_support(psoc, &indoor_support);
+	if (indoor_support ||
+	    !policy_mgr_get_sta_sap_scc_allowed_on_indoor_chnl(psoc))
+		return;
+
+	mode = wlan_get_opmode_from_vdev_id(pm_ctx->pdev, vdev_id);
+
+	/**
+	 * DISCONNECT_WITH_CONCURRENCY update comes after SAP/GO CSA.
+	 * Whereas, all other updates come from STA/GC operation.
+	 */
+	if (type != DISCONNECT_WITH_CONCURRENCY &&
+	    (mode != QDF_STA_MODE && mode != QDF_P2P_CLIENT_MODE)) {
+		return;
+	} else if (type == DISCONNECT_WITH_CONCURRENCY &&
+		 (mode != QDF_SAP_MODE && mode != QDF_P2P_GO_MODE)) {
+		return;
+	}
+
+	switch (type) {
+	case CONNECT:
+	case SWITCH_WITHOUT_CONCURRENCY:
+	case SWITCH_WITH_CONCURRENCY:
+		policy_mgr_get_chan_by_session_id(psoc, vdev_id, &ch_freq);
+		ch_width = policy_mgr_get_bw_by_session_id(psoc, vdev_id);
+		break;
+	case DISCONNECT_WITHOUT_CONCURRENCY:
+	case DISCONNECT_WITH_CONCURRENCY:
+		ch_freq = discon_freq;
+		break;
+	default:
+		return;
+	}
+
+	if (type != SWITCH_WITHOUT_CONCURRENCY &&
+	    !(WLAN_REG_IS_5GHZ_CH_FREQ(ch_freq) &&
+	    wlan_reg_is_freq_indoor(pm_ctx->pdev, ch_freq))) {
+		return;
+	} else if (type == SWITCH_WITHOUT_CONCURRENCY) {
+		/* Either the previous frequency or the current
+		 * frequency can be indoor. Or both can be indoor.
+		 * Therefore, atleast one of the frequency must be
+		 * indoor in order to proceed for the update.
+		 */
+		if (!((WLAN_REG_IS_5GHZ_CH_FREQ(ch_freq) &&
+		       wlan_reg_is_freq_indoor(pm_ctx->pdev, ch_freq)) ||
+		      (WLAN_REG_IS_5GHZ_CH_FREQ(discon_freq) &&
+		       wlan_reg_is_freq_indoor(pm_ctx->pdev, discon_freq))))
+			return;
+	}
+
+	switch (type) {
+	case CONNECT:
+		wlan_reg_modify_indoor_concurrency(pm_ctx->pdev, vdev_id,
+						   ch_freq, ch_width, true);
+		break;
+	case DISCONNECT_WITHOUT_CONCURRENCY:
+		wlan_reg_modify_indoor_concurrency(pm_ctx->pdev, vdev_id,
+						   0, CH_WIDTH_INVALID, false);
+		break;
+	case SWITCH_WITHOUT_CONCURRENCY:
+		wlan_reg_modify_indoor_concurrency(pm_ctx->pdev, vdev_id, 0,
+						   CH_WIDTH_INVALID, false);
+		if (wlan_reg_is_freq_indoor(pm_ctx->pdev, ch_freq))
+			wlan_reg_modify_indoor_concurrency(pm_ctx->pdev,
+							   vdev_id, ch_freq,
+							   ch_width, true);
+		break;
+	case DISCONNECT_WITH_CONCURRENCY:
+		/*If there are other sessions, do not change current chan list*/
+		if (policy_mgr_get_connection_count_with_ch_freq(ch_freq) > 1)
+			return;
+		wlan_reg_modify_indoor_concurrency(pm_ctx->pdev,
+						   INVALID_VDEV_ID, ch_freq,
+						   CH_WIDTH_INVALID, false);
+		break;
+	case SWITCH_WITH_CONCURRENCY:
+		wlan_reg_modify_indoor_concurrency(pm_ctx->pdev, vdev_id,
+						   ch_freq, ch_width, true);
+		/*
+		 * The previous frequency removal and current channel list
+		 * recomputation will happen after SAP CSA
+		 */
+		return;
+	}
+	wlan_reg_recompute_current_chan_list(psoc, pm_ctx->pdev);
+}
+
+bool policy_mgr_is_conc_sap_present_on_sta_freq(struct wlan_objmgr_psoc *psoc,
+						enum policy_mgr_con_mode mode,
+						uint32_t ch_freq)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	uint8_t i;
+	bool sap_go_exists = false;
+	enum policy_mgr_con_mode cmode;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid pm context");
+		return false;
+	}
+
+	if (mode != PM_STA_MODE && mode != PM_P2P_CLIENT_MODE)
+		return false;
+
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (i = 0; i < MAX_NUMBER_OF_CONC_CONNECTIONS; i++) {
+		cmode = pm_conc_connection_list[i].mode;
+		if (pm_conc_connection_list[i].in_use &&
+		    ch_freq == pm_conc_connection_list[i].freq &&
+		    (cmode == PM_SAP_MODE || cmode == PM_P2P_GO_MODE)) {
+			sap_go_exists = true;
+			break;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	return sap_go_exists;
+}

+ 1 - 8
components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c

@@ -3722,14 +3722,7 @@ uint32_t policy_mgr_mode_specific_get_channel(
 	return freq;
 }
 
-/**
- * policy_mgr_get_connection_count_with_ch_freq() - Get number of active
- * connections on the channel frequecy
- * @ch_freq: channel frequency
- *
- * Return: number of active connection on the specific frequency
- */
-static uint32_t policy_mgr_get_connection_count_with_ch_freq(uint32_t ch_freq)
+uint32_t policy_mgr_get_connection_count_with_ch_freq(uint32_t ch_freq)
 {
 	uint32_t i;
 	uint32_t count = 0;

+ 8 - 0
core/sap/src/sap_api_link_cntl.c

@@ -131,9 +131,17 @@ void sap_config_acs_result(mac_handle_t mac_handle,
 {
 	struct ch_params ch_params = {0};
 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
+	enum phy_ch_width new_ch_width;
 
 	ch_params.ch_width = sap_ctx->acs_cfg->ch_width;
 	sap_acs_set_puncture_support(sap_ctx, &ch_params);
+
+	new_ch_width =
+		wlan_sap_get_concurrent_bw(mac_ctx->pdev, mac_ctx->psoc,
+					   sap_ctx->acs_cfg->pri_ch_freq,
+					   ch_params.ch_width);
+	ch_params.ch_width = new_ch_width;
+
 	wlan_reg_set_channel_params_for_pwrmode(
 			mac_ctx->pdev, sap_ctx->acs_cfg->pri_ch_freq,
 			sec_ch_freq, &ch_params, REG_CURRENT_PWR_MODE);

+ 21 - 7
core/sap/src/sap_module.c

@@ -613,8 +613,8 @@ enum phy_ch_width wlan_sap_get_concurrent_bw(struct wlan_objmgr_pdev *pdev,
 					     enum phy_ch_width channel_width)
 {
 	enum hw_mode_bandwidth sta_ch_width;
-	enum phy_ch_width sta_chan_width;
-	bool sta_present, is_con_chan_dfs = false;
+	enum phy_ch_width sta_chan_width = CH_WIDTH_20MHZ;
+	bool sta_present, is_con_chan_dfs = false, is_con_sta_indoor = false;
 	uint8_t sta_vdev_id;
 	uint8_t sta_sap_scc_on_dfs_chnl;
 
@@ -633,12 +633,18 @@ enum phy_ch_width wlan_sap_get_concurrent_bw(struct wlan_objmgr_pdev *pdev,
 		if (wlan_reg_is_dfs_for_freq(pdev, con_ch_freq) ||
 		    sta_chan_width == CH_WIDTH_160MHZ)
 			is_con_chan_dfs = true;
+		else if (WLAN_REG_IS_5GHZ_CH_FREQ(con_ch_freq) &&
+			 wlan_reg_is_freq_indoor(pdev, con_ch_freq))
+			is_con_sta_indoor = true;
 	}
 
-	if (policy_mgr_is_hw_dbs_capable(psoc)) {
-		if (is_con_chan_dfs)
-			channel_width = QDF_MIN(sta_chan_width, channel_width);
-		else if (sta_present && channel_width == CH_WIDTH_160MHZ)
+	if (!policy_mgr_is_hw_dbs_capable(psoc))
+		goto sap_ch_width_check;
+
+	if (is_con_chan_dfs) {
+		channel_width = QDF_MIN(sta_chan_width, channel_width);
+
+		if (sta_present && channel_width == CH_WIDTH_160MHZ)
 			channel_width = CH_WIDTH_80MHZ;
 
 		policy_mgr_get_sta_sap_scc_on_dfs_chnl(
@@ -665,8 +671,13 @@ enum phy_ch_width wlan_sap_get_concurrent_bw(struct wlan_objmgr_pdev *pdev,
 			return QDF_MIN(channel_width, CH_WIDTH_80MHZ);
 
 		return channel_width;
+	} else if (is_con_sta_indoor) {
+		sap_debug("Indoor STA channel width is %d", sta_chan_width);
+		return QDF_MIN(channel_width, sta_chan_width);
 	}
 
+sap_ch_width_check:
+
 	/* if no STA present return max of BW and 80MHZ */
 	if (!sta_present)
 		return CH_WIDTH_80MHZ;
@@ -1970,7 +1981,10 @@ QDF_STATUS wlansap_channel_change_request(struct sap_context *sap_ctx,
 		  sap_ctx->chan_freq, phy_mode, ch_params->ch_width,
 		  ch_params->sec_ch_offset, ch_params->center_freq_seg0,
 		  ch_params->center_freq_seg1);
-
+	policy_mgr_update_indoor_concurrency(mac_ctx->psoc,
+					     wlan_vdev_get_id(sap_ctx->vdev),
+					     sap_ctx->freq_before_ch_switch,
+					     DISCONNECT_WITH_CONCURRENCY);
 	return status;
 }