ソースを参照

qcacmn: Fix hotspot starting failure

When softap is stopping, there are two threads
accessing the "conc_connection_list".
hostapd thread (__wlan_hdd_cfg80211_stop_ap) read
and modify it by cds_decr_session_set_pcl.
cds_mc_thread thread (cds_get_valid_chan_weights)
read and modify it by cds_store_and_del_conn_info
and cds_restore_deleted_conn_info.

They are not protected,which causes two same
station connection info saved to the
"conc_connection_list".

This fix is to acquire lock before read/modify
the list.

Change-Id: I5f1becef711363f659044c46e69fab1cd6d07d81
CRs-Fixed: 2038000
Liangwei Dong 8 年 前
コミット
f45a0df7e2

+ 11 - 1
umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c

@@ -1207,6 +1207,13 @@ void policy_mgr_set_pcl_for_existing_combo(
 			info[MAX_NUMBER_OF_CONC_CONNECTIONS] = { {0} };
 	enum tQDF_ADAPTER_MODE pcl_mode;
 	uint8_t num_cxn_del = 0;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return;
+	}
 
 	switch (mode) {
 	case PM_STA_MODE:
@@ -1228,17 +1235,20 @@ void policy_mgr_set_pcl_for_existing_combo(
 		policy_mgr_err("Invalid mode to set PCL");
 		return;
 	};
-
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 	if (policy_mgr_mode_specific_connection_count(psoc, mode, NULL) > 0) {
 		/* Check, store and temp delete the mode's parameter */
 		policy_mgr_store_and_del_conn_info(psoc, mode, false,
 						info, &num_cxn_del);
+		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 		/* Set the PCL to the FW since connection got updated */
 		policy_mgr_pdev_set_pcl(psoc, pcl_mode);
 		policy_mgr_debug("Set PCL to FW for mode:%d", mode);
+		qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 		/* Restore the connection info */
 		policy_mgr_restore_deleted_conn_info(psoc, info, num_cxn_del);
 	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 }
 
 /**

+ 21 - 2
umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c

@@ -76,20 +76,30 @@ QDF_STATUS policy_mgr_get_pcl_for_existing_conn(struct wlan_objmgr_psoc *psoc,
 	uint8_t num_cxn_del = 0;
 
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
 
 	policy_mgr_debug("get pcl for existing conn:%d", mode);
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return QDF_STATUS_E_FAILURE;
+	}
 
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 	if (policy_mgr_mode_specific_connection_count(psoc, mode, NULL) > 0) {
 		/* Check, store and temp delete the mode's parameter */
 		policy_mgr_store_and_del_conn_info(psoc, mode,
 				all_matching_cxn_to_del, info, &num_cxn_del);
+		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 		/* Get the PCL */
 		status = policy_mgr_get_pcl(psoc, mode, pcl_ch, len,
 					pcl_weight, weight_len);
 		policy_mgr_debug("Get PCL to FW for mode:%d", mode);
+		qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 		/* Restore the connection info */
 		policy_mgr_restore_deleted_conn_info(psoc, info, num_cxn_del);
 	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 
 	return status;
 }
@@ -1599,6 +1609,13 @@ QDF_STATUS policy_mgr_get_valid_chan_weights(struct wlan_objmgr_psoc *psoc,
 	struct policy_mgr_conc_connection_info
 			info[MAX_NUMBER_OF_CONC_CONNECTIONS] = { {0} };
 	uint8_t num_cxn_del = 0;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return QDF_STATUS_E_FAILURE;
+	}
 
 	if (!weight->pcl_list) {
 		policy_mgr_err("Invalid pcl");
@@ -1617,7 +1634,7 @@ QDF_STATUS policy_mgr_get_valid_chan_weights(struct wlan_objmgr_psoc *psoc,
 
 	qdf_mem_set(weight->weighed_valid_list, QDF_MAX_NUM_CHAN,
 		    WEIGHT_OF_DISALLOWED_CHANNELS);
-
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 	if (policy_mgr_mode_specific_connection_count(
 		psoc, PM_STA_MODE, NULL) > 0) {
 		/*
@@ -1628,6 +1645,7 @@ QDF_STATUS policy_mgr_get_valid_chan_weights(struct wlan_objmgr_psoc *psoc,
 		 */
 		policy_mgr_store_and_del_conn_info(psoc, PM_STA_MODE, false,
 						info, &num_cxn_del);
+		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 		/*
 		 * There is a small window between releasing the above lock
 		 * and acquiring the same in policy_mgr_allow_concurrency,
@@ -1641,10 +1659,11 @@ QDF_STATUS policy_mgr_get_valid_chan_weights(struct wlan_objmgr_psoc *psoc,
 					WEIGHT_OF_NON_PCL_CHANNELS;
 			}
 		}
-
+		qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 		/* Restore the connection info */
 		policy_mgr_restore_deleted_conn_info(psoc, info, num_cxn_del);
 	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 
 	for (i = 0; i < weight->saved_num_chan; i++) {
 		for (j = 0; j < weight->pcl_len; j++) {