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

Commit 7f25abfd authored by Vikram Sharma's avatar Vikram Sharma Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: cdm: handle dead lock scenario



This change handles a race condition in which cdm workqueue is
scheduled on one of the cores and cdm flush is executing on
another core. We come across a dead lock between fifo_lock and
hw_mutex lock.

CRs-Fixed: 3049531
Change-Id: Ie0b8982a7e55218fc5655f8e3d08a952fd852ed7
Signed-off-by: default avatarVikram Sharma <vikramsa@codeaurora.org>
parent 981b2405
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -180,12 +180,10 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
			(struct cam_cdm_bl_cb_request_entry *)data;

		client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl);
		mutex_lock(&cdm_hw->hw_mutex);
		client = core->clients[client_idx];
		if ((!client) || (client->handle != node->client_hdl)) {
			CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
				node->client_hdl);
			mutex_unlock(&cdm_hw->hw_mutex);
			return;
		}
		cam_cdm_get_client_refcount(client);
@@ -204,7 +202,6 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
		}
		mutex_unlock(&client->lock);
		cam_cdm_put_client_refcount(client);
		mutex_unlock(&cdm_hw->hw_mutex);
		return;
	} else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE ||
			status == CAM_CDM_CB_STATUS_HW_FLUSH ||
@@ -242,7 +239,6 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,

	for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) {
		if (core->clients[i] != NULL) {
			mutex_lock(&cdm_hw->hw_mutex);
			client = core->clients[i];
			cam_cdm_get_client_refcount(client);
			mutex_lock(&client->lock);
@@ -265,7 +261,6 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
			}
			mutex_unlock(&client->lock);
			cam_cdm_put_client_refcount(client);
			mutex_unlock(&cdm_hw->hw_mutex);
		}
	}
}
+6 −1
Original line number Diff line number Diff line
@@ -1238,6 +1238,7 @@ static void cam_hw_cdm_work(struct work_struct *work)
			return;
		}

		mutex_lock(&cdm_hw->hw_mutex);
		mutex_lock(&core->bl_fifo[fifo_idx].fifo_lock);

		if (atomic_read(&core->bl_fifo[fifo_idx].work_record))
@@ -1251,6 +1252,7 @@ static void cam_hw_cdm_work(struct work_struct *work)
				core->arbitration);
			mutex_unlock(&core->bl_fifo[fifo_idx]
					.fifo_lock);
			mutex_unlock(&cdm_hw->hw_mutex);
			return;
		}

@@ -1289,6 +1291,7 @@ static void cam_hw_cdm_work(struct work_struct *work)
		}
		mutex_unlock(&core->bl_fifo[payload->fifo_idx]
			.fifo_lock);
		mutex_unlock(&cdm_hw->hw_mutex);
	}

	if (payload->irq_status &
@@ -1405,9 +1408,9 @@ static void cam_hw_cdm_iommu_fault_handler(struct cam_smmu_pf_info *pf_info)
				cdm_hw->soc_info.index);
		for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++)
			mutex_unlock(&core->bl_fifo[i].fifo_lock);
		mutex_unlock(&cdm_hw->hw_mutex);
		cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT,
			(void *)pf_info->iova);
		mutex_unlock(&cdm_hw->hw_mutex);
		clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status);
	} else {
		CAM_ERR(CAM_CDM, "Invalid token");
@@ -1806,9 +1809,11 @@ int cam_hw_cdm_handle_error_info(

	if (node != NULL) {
		if (node->request_type == CAM_HW_CDM_BL_CB_CLIENT) {
			mutex_lock(&cdm_hw->hw_mutex);
			cam_cdm_notify_clients(cdm_hw,
					CAM_CDM_CB_STATUS_HW_ERROR,
					(void *)node);
			mutex_unlock(&cdm_hw->hw_mutex);
		} else if (node->request_type == CAM_HW_CDM_BL_CB_INTERNAL) {
			CAM_ERR(CAM_CDM, "Invalid node=%pK %d", node,
					node->request_type);