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 Diff line number Diff line
@@ -741,14 +741,15 @@ void policy_mgr_restore_deleted_conn_info(struct wlan_objmgr_psoc *psoc,
		return;
	}

	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
	conn_index = policy_mgr_get_connection_count(psoc);
	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",
			conn_index, MAX_NUMBER_OF_CONC_CONNECTIONS);
		return;
	}

	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
	qdf_mem_copy(&pm_conc_connection_list[conn_index], info,
			num_cxn_del * sizeof(*info));
	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;
}

/**
 * policy_mgr_pdev_set_pcl() - Sets PCL to FW
 * @mode: adapter mode
 *
 * 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 policy_mgr_pdev_get_pcl(struct wlan_objmgr_psoc *psoc,
				   enum QDF_OPMODE mode,
				   struct policy_mgr_pcl_list *pcl)
{
	QDF_STATUS status;
	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);
	if (!pm_ctx) {
		policy_mgr_err("Invalid Context");
		return;
	}

	pcl.pcl_len = 0;
	pcl->pcl_len = 0;

	switch (mode) {
	case QDF_STA_MODE:
@@ -1237,24 +1221,18 @@ void policy_mgr_pdev_set_pcl(struct wlan_objmgr_psoc *psoc,
		break;
	default:
		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");

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

	status = pm_ctx->sme_cbacks.sme_pdev_set_pcl(&pcl);
	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);
	return status;
}

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

	pm_ctx = policy_mgr_get_context(psoc);
	if (!pm_ctx) {
@@ -1285,19 +1265,25 @@ void policy_mgr_set_pcl_for_existing_combo(
		return;
	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
	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 */
		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);
		status = policy_mgr_pdev_get_pcl(psoc, pcl_mode, &pcl);
		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);

		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);
	}
}

static uint32_t pm_get_vdev_id_of_first_conn_idx(struct wlan_objmgr_psoc *psoc)
{
+8 −4
Original line number 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);

/**
 * 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
 * @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,
			     enum QDF_OPMODE mode);
QDF_STATUS policy_mgr_pdev_get_pcl(struct wlan_objmgr_psoc *psoc,
				   enum QDF_OPMODE mode,
				   struct policy_mgr_pcl_list *pcl);
void pm_dbs_opportunistic_timer_handler(void *data);
enum policy_mgr_con_mode policy_mgr_get_mode(uint8_t type,
		uint8_t subtype);