Browse Source

qcacld-3.0: Save disconnected sta chan freq and check when sap restart

If AP1 on 2G unsafe channel (no valid 2g channel so can't move),
STA+AP2 on 5G unsafe channel doing SCC, when STA disconnect, 5G AP2
is expected to restart to another 5G safe channel, but 2G AP1 will
also be selected to restart to another 2g safe channel (not in acs
range), which is not supported to switch to different channel at same
time.

To fix this issue, save last disconnected sta channel frequency in
policy manager context, and find the AP which is doing SCC with this
sta, and restart this SAP to safe channel.
To avoid possible OOB write warning, enlarge the input array buffer
of policy_mgr_get_mode_specific_conn_info().

Change-Id: If6ddd889cc0fd8b00796d42e6aa4d1a98b6b1070
CRs-Fixed: 3145226
Will Huang 3 years ago
parent
commit
1135c6caf9

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

@@ -1565,8 +1565,8 @@ bool policy_mgr_is_sap_restart_required_after_sta_disconnect(
 		policy_mgr_sta_sap_scc_on_lte_coex_chan(psoc);
 	uint8_t sta_sap_scc_on_dfs_chnl_config_value = 0;
 	uint32_t cc_count, i, go_index_start, pcl_len = 0;
-	uint32_t op_ch_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
-	uint8_t vdev_id[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint32_t op_ch_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS * 2];
+	uint8_t vdev_id[MAX_NUMBER_OF_CONC_CONNECTIONS * 2];
 	enum policy_mgr_con_mode mode;
 	uint32_t pcl_channels[NUM_CHANNELS + 1];
 	uint8_t pcl_weight[NUM_CHANNELS + 1];
@@ -1613,8 +1613,9 @@ bool policy_mgr_is_sap_restart_required_after_sta_disconnect(
 			continue;
 		if (sta_sap_scc_on_dfs_chan &&
 		    (sta_sap_scc_on_dfs_chnl_config_value != 2) &&
-		    wlan_reg_is_dfs_for_freq(pm_ctx->pdev,
-					     op_ch_freq_list[i])) {
+		     wlan_reg_is_dfs_for_freq(pm_ctx->pdev,
+					      op_ch_freq_list[i]) &&
+		     pm_ctx->last_disconn_sta_freq == op_ch_freq_list[i]) {
 			sap_vdev_id = vdev_id[i];
 			curr_sap_freq = op_ch_freq_list[i];
 			policy_mgr_debug("sta_sap_scc_on_dfs_chan %u, sta_sap_scc_on_dfs_chnl_config_value %u, dfs sap_ch_freq %u",
@@ -1624,7 +1625,8 @@ bool policy_mgr_is_sap_restart_required_after_sta_disconnect(
 			break;
 		}
 		if (sta_sap_scc_on_lte_coex_chan &&
-		    !policy_mgr_is_safe_channel(psoc, op_ch_freq_list[i])) {
+		    !policy_mgr_is_safe_channel(psoc, op_ch_freq_list[i]) &&
+		    pm_ctx->last_disconn_sta_freq == op_ch_freq_list[i]) {
 			sap_vdev_id = vdev_id[i];
 			curr_sap_freq = op_ch_freq_list[i];
 			policy_mgr_debug("sta_sap_scc_on_lte_coex_chan %u unsafe sap_ch_freq %u",
@@ -2017,6 +2019,7 @@ void policy_mgr_check_sap_restart(struct wlan_objmgr_psoc *psoc,
 
 end:
 	pm_ctx->do_sap_unsafe_ch_check = false;
+	pm_ctx->last_disconn_sta_freq = 0;
 }
 
 static void __policy_mgr_check_sta_ap_concurrent_ch_intf(
@@ -2048,7 +2051,7 @@ static void __policy_mgr_check_sta_ap_concurrent_ch_intf(
 			work_info->go_plus_go_force_scc.ch_freq,
 			work_info->go_plus_go_force_scc.ch_width);
 		work_info->go_plus_go_force_scc.vdev_id = WLAN_UMAC_VDEV_ID_MAX;
-		return;
+		goto end;
 	}
 
 	mcc_to_scc_switch =
@@ -2104,6 +2107,7 @@ static void __policy_mgr_check_sta_ap_concurrent_ch_intf(
 
 end:
 	pm_ctx->do_sap_unsafe_ch_check = false;
+	pm_ctx->last_disconn_sta_freq = 0;
 }
 
 void policy_mgr_check_sta_ap_concurrent_ch_intf(void *data)

+ 61 - 10
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -2957,6 +2957,63 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc,
 	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 }
 
+/**
+ * policy_mgr_update_sta_scc_info_for_later_check() - function to update sta/sap
+ * scc channel frequency and later check flag.
+ * @pm_ctx: policy manager context pointer
+ * @mode: operation mode
+ * @vdev_id: vdev id
+ *
+ * Return: None
+ */
+static void policy_mgr_update_sta_scc_info_for_later_check(
+		struct policy_mgr_psoc_priv_obj *pm_ctx,
+		enum QDF_OPMODE mode,
+		uint8_t vdev_id)
+{
+	uint32_t conn_index = 0;
+	qdf_freq_t sta_freq = 0;
+
+	if (mode != QDF_STA_MODE && mode != QDF_P2P_CLIENT_MODE)
+		return;
+
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	while (PM_CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) {
+		if (vdev_id == pm_conc_connection_list[conn_index].vdev_id) {
+			sta_freq = pm_conc_connection_list[conn_index].freq;
+			break;
+		}
+		conn_index++;
+	}
+
+	if (!sta_freq)
+		goto release_mutex;
+
+	/*
+	 * When STA disconnected, we need to move DFS SAP
+	 * to Non-DFS if g_sta_sap_scc_on_dfs_chan enabled.
+	 * The same if g_sta_sap_scc_on_lte_coex_chan enabled,
+	 * need to move SAP on unsafe channel to safe channel.
+	 * The flag will be checked by
+	 * policy_mgr_is_sap_restart_required_after_sta_disconnect.
+	 */
+	conn_index = 0;
+	while (PM_CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) {
+		if (pm_conc_connection_list[conn_index].freq == sta_freq &&
+		    (pm_conc_connection_list[conn_index].mode == PM_SAP_MODE ||
+		    pm_conc_connection_list[conn_index].mode ==
+		    PM_P2P_GO_MODE)) {
+			pm_ctx->do_sap_unsafe_ch_check = true;
+			pm_ctx->last_disconn_sta_freq = sta_freq;
+			break;
+		}
+		conn_index++;
+	}
+
+release_mutex:
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+}
+
 QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc,
 				enum QDF_OPMODE mode,
 				uint8_t session_id)
@@ -2981,6 +3038,10 @@ QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc,
 		return qdf_status;
 	}
 
+	policy_mgr_update_sta_scc_info_for_later_check(pm_ctx,
+						       mode,
+						       session_id);
+
 	switch (mode) {
 	case QDF_STA_MODE:
 	case QDF_P2P_CLIENT_MODE:
@@ -3053,16 +3114,6 @@ QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc,
 		if (pm_ctx->dp_cbacks.hdd_ipa_set_mcc_mode_cb)
 			pm_ctx->dp_cbacks.hdd_ipa_set_mcc_mode_cb(mcc_mode);
 	}
-	/*
-	 * When STA disconnected, we need to move DFS SAP
-	 * to Non-DFS if g_sta_sap_scc_on_dfs_chan enabled.
-	 * The same if g_sta_sap_scc_on_lte_coex_chan enabled,
-	 * need to move SAP on unsafe channel to safe channel.
-	 * The flag will be checked by
-	 * policy_mgr_is_sap_restart_required_after_sta_disconnect.
-	 */
-	if (mode == QDF_STA_MODE || mode == QDF_P2P_CLIENT_MODE)
-		pm_ctx->do_sap_unsafe_ch_check = true;
 
 	if (mode == QDF_SAP_MODE || mode == QDF_P2P_GO_MODE ||
 	    mode == QDF_STA_MODE || mode == QDF_P2P_CLIENT_MODE)

+ 3 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h

@@ -308,6 +308,8 @@ struct policy_mgr_cfg {
  *                        regulatory/other considerations
  * @sap_mandatory_channels_len: Length of the SAP mandatory
  *                            channel list
+ * @do_sap_unsafe_ch_check: whether need check sap unsafe channel
+ * @last_disconn_sta_freq: last disconnected sta channel freq
  * @concurrency_mode: active concurrency combination
  * @no_of_open_sessions: Number of active vdevs
  * @no_of_active_sessions: Number of active connections
@@ -351,6 +353,7 @@ struct policy_mgr_psoc_priv_obj {
 	uint32_t sap_mandatory_channels[NUM_CHANNELS];
 	uint32_t sap_mandatory_channels_len;
 	bool do_sap_unsafe_ch_check;
+	qdf_freq_t last_disconn_sta_freq;
 	uint32_t concurrency_mode;
 	uint8_t no_of_open_sessions[QDF_MAX_NO_OF_MODE];
 	uint8_t no_of_active_sessions[QDF_MAX_NO_OF_MODE];