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
This commit is contained in:
Liangwei Dong 2017-05-05 05:29:07 -04:00 committed by pramod kotreshappa
parent 05328bb022
commit 0027e3f02b
2 changed files with 32 additions and 3 deletions

View File

@ -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);
}
/**

View File

@ -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++) {