From 7f25abfda5dc2f637aa9d52566a58a87f3528bf9 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 11 Oct 2021 19:43:00 +0530 Subject: [PATCH] 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: Vikram Sharma --- drivers/cam_cdm/cam_cdm_core_common.c | 5 ----- drivers/cam_cdm/cam_cdm_hw_core.c | 7 ++++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index fd84b8d6866b..6ca94e740013 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -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); } } } diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 37f2a0a10967..583963a0d6e2 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -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 @@ handle_cdm_pf: 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);