Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fee5ebc4 authored by Paul Zhang's avatar Paul Zhang Committed by nshrivas
Browse files

qcacmn: resolve race issue accessing pm_conc_connection_list

While function policy_mgr_set_pcl_for_existing_combo posts event
SIR_HAL_PDEV_SET_PCL_TO_FW and before restores pm_conc_connection_list,
the function policy_mgr_get_valid_chan_weights is invoking and
accessing pm_conc_connection_list then race happens.

To resolve the issue, restore the pm_conc_connection_list before
calling SME function.

CRs-Fixed: 2370113
Change-Id: I8b30dc5084c4aae4bcc4b3b350d19c8be89338a9
parent 615009a4
Loading
Loading
Loading
Loading
+23 −37
Original line number Original line Diff line number Diff line
@@ -741,14 +741,15 @@ void policy_mgr_restore_deleted_conn_info(struct wlan_objmgr_psoc *psoc,
		return;
		return;
	}
	}


	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
	conn_index = policy_mgr_get_connection_count(psoc);
	conn_index = policy_mgr_get_connection_count(psoc);
	if (MAX_NUMBER_OF_CONC_CONNECTIONS <= conn_index) {
	if (MAX_NUMBER_OF_CONC_CONNECTIONS <= conn_index) {
		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
		policy_mgr_err("Failed to restore the deleted information %d/%d",
		policy_mgr_err("Failed to restore the deleted information %d/%d",
			conn_index, MAX_NUMBER_OF_CONC_CONNECTIONS);
			conn_index, MAX_NUMBER_OF_CONC_CONNECTIONS);
		return;
		return;
	}
	}


	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
	qdf_mem_copy(&pm_conc_connection_list[conn_index], info,
	qdf_mem_copy(&pm_conc_connection_list[conn_index], info,
			num_cxn_del * sizeof(*info));
			num_cxn_del * sizeof(*info));
	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
@@ -1193,31 +1194,14 @@ void policy_mgr_dump_current_concurrency(struct wlan_objmgr_psoc *psoc)
	return;
	return;
}
}


/**
QDF_STATUS policy_mgr_pdev_get_pcl(struct wlan_objmgr_psoc *psoc,
 * policy_mgr_pdev_set_pcl() - Sets PCL to FW
				   enum QDF_OPMODE mode,
 * @mode: adapter mode
				   struct policy_mgr_pcl_list *pcl)
 *
 * Fetches the PCL and sends the PCL to SME
 * module which in turn will send the WMI
 * command WMI_PDEV_SET_PCL_CMDID to the fw
 *
 * Return: None
 */
void policy_mgr_pdev_set_pcl(struct wlan_objmgr_psoc *psoc,
				enum QDF_OPMODE mode)
{
{
	QDF_STATUS status;
	QDF_STATUS status;
	enum policy_mgr_con_mode con_mode;
	enum policy_mgr_con_mode con_mode;
	struct policy_mgr_pcl_list pcl;
	struct policy_mgr_psoc_priv_obj *pm_ctx;


	pm_ctx = policy_mgr_get_context(psoc);
	pcl->pcl_len = 0;
	if (!pm_ctx) {
		policy_mgr_err("Invalid Context");
		return;
	}

	pcl.pcl_len = 0;


	switch (mode) {
	switch (mode) {
	case QDF_STA_MODE:
	case QDF_STA_MODE:
@@ -1237,24 +1221,18 @@ void policy_mgr_pdev_set_pcl(struct wlan_objmgr_psoc *psoc,
		break;
		break;
	default:
	default:
		policy_mgr_err("Unable to set PCL to FW: %d", mode);
		policy_mgr_err("Unable to set PCL to FW: %d", mode);
		return;
		return QDF_STATUS_E_FAILURE;
	}
	}


	policy_mgr_debug("get pcl to set it to the FW");
	policy_mgr_debug("get pcl to set it to the FW");


	status = policy_mgr_get_pcl(psoc, con_mode,
	status = policy_mgr_get_pcl(psoc, con_mode,
			pcl.pcl_list, &pcl.pcl_len,
			pcl->pcl_list, &pcl->pcl_len,
			pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
			pcl->weight_list, QDF_ARRAY_SIZE(pcl->weight_list));
	if (status != QDF_STATUS_SUCCESS) {
	if (status != QDF_STATUS_SUCCESS)
		policy_mgr_err("Unable to set PCL to FW, Get PCL failed");
		policy_mgr_err("Unable to set PCL to FW, Get PCL failed");
		return;
	}


	status = pm_ctx->sme_cbacks.sme_pdev_set_pcl(&pcl);
	return status;
	if (status != QDF_STATUS_SUCCESS)
		policy_mgr_err("Send soc set PCL to SME failed");
	else
		policy_mgr_debug("Set PCL to FW for mode:%d", mode);
}
}


/**
/**
@@ -1268,11 +1246,13 @@ void policy_mgr_pdev_set_pcl(struct wlan_objmgr_psoc *psoc,
void policy_mgr_set_pcl_for_existing_combo(
void policy_mgr_set_pcl_for_existing_combo(
		struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode)
		struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode)
{
{
	QDF_STATUS status;
	struct policy_mgr_conc_connection_info
	struct policy_mgr_conc_connection_info
			info[MAX_NUMBER_OF_CONC_CONNECTIONS] = { {0} };
			info[MAX_NUMBER_OF_CONC_CONNECTIONS] = { {0} };
	enum QDF_OPMODE pcl_mode;
	enum QDF_OPMODE pcl_mode;
	uint8_t num_cxn_del = 0;
	uint8_t num_cxn_del = 0;
	struct policy_mgr_psoc_priv_obj *pm_ctx;
	struct policy_mgr_psoc_priv_obj *pm_ctx;
	struct policy_mgr_pcl_list pcl;


	pm_ctx = policy_mgr_get_context(psoc);
	pm_ctx = policy_mgr_get_context(psoc);
	if (!pm_ctx) {
	if (!pm_ctx) {
@@ -1285,19 +1265,25 @@ void policy_mgr_set_pcl_for_existing_combo(
		return;
		return;
	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
	if (policy_mgr_mode_specific_connection_count(psoc, mode, NULL) > 0) {
	if (policy_mgr_mode_specific_connection_count(psoc, mode, NULL) > 0) {
		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
		/* Check, store and temp delete the mode's parameter */
		/* Check, store and temp delete the mode's parameter */
		policy_mgr_store_and_del_conn_info(psoc, mode, false,
		policy_mgr_store_and_del_conn_info(psoc, mode, false,
						info, &num_cxn_del);
						info, &num_cxn_del);
		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
		/* Set the PCL to the FW since connection got updated */
		/* Set the PCL to the FW since connection got updated */
		policy_mgr_pdev_set_pcl(psoc, pcl_mode);
		status = policy_mgr_pdev_get_pcl(psoc, pcl_mode, &pcl);
		policy_mgr_debug("Set PCL to FW for mode:%d", 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 */
		/* Restore the connection info */
		policy_mgr_restore_deleted_conn_info(psoc, info, num_cxn_del);
		policy_mgr_restore_deleted_conn_info(psoc, info, num_cxn_del);

		if (QDF_IS_STATUS_SUCCESS(status)) {
			status = pm_ctx->sme_cbacks.sme_pdev_set_pcl(&pcl);
			if (QDF_IS_STATUS_ERROR(status))
				policy_mgr_err("Send set PCL to SME failed");
		}
		}
	} else {
		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
	}
	}
}


static uint32_t pm_get_vdev_id_of_first_conn_idx(struct wlan_objmgr_psoc *psoc)
static uint32_t pm_get_vdev_id_of_first_conn_idx(struct wlan_objmgr_psoc *psoc)
{
{
+8 −4
Original line number Original line Diff line number Diff line
@@ -395,14 +395,18 @@ void policy_mgr_pdev_set_hw_mode_cb(uint32_t status,
void policy_mgr_dump_current_concurrency(struct wlan_objmgr_psoc *psoc);
void policy_mgr_dump_current_concurrency(struct wlan_objmgr_psoc *psoc);


/**
/**
 * policy_mgr_pdev_set_pcl() - SET PCL channel list and send to firmware
 * policy_mgr_pdev_get_pcl() - GET PCL channel list
 * @psoc: PSOC object information
 * @psoc: PSOC object information
 * @mode: Adapter mode
 * @mode: Adapter mode
 * @pcl: the pointer of pcl list
 *
 *
 * Return: None
 * Fetches the PCL.
 *
 * Return: QDF_STATUS
 */
 */
void policy_mgr_pdev_set_pcl(struct wlan_objmgr_psoc *psoc,
QDF_STATUS policy_mgr_pdev_get_pcl(struct wlan_objmgr_psoc *psoc,
			     enum QDF_OPMODE mode);
				   enum QDF_OPMODE mode,
				   struct policy_mgr_pcl_list *pcl);
void pm_dbs_opportunistic_timer_handler(void *data);
void pm_dbs_opportunistic_timer_handler(void *data);
enum policy_mgr_con_mode policy_mgr_get_mode(uint8_t type,
enum policy_mgr_con_mode policy_mgr_get_mode(uint8_t type,
		uint8_t subtype);
		uint8_t subtype);