From 53152ba8cdb3313c3387a72c09af1d9aabd8964c Mon Sep 17 00:00:00 2001 From: Shivakumar Malke Date: Wed, 22 Feb 2023 17:30:09 +0530 Subject: [PATCH 1/3] msm: camera: ope: Avoid deadlock in OPE PF handling In OPE fault handler, while dumping pf info ctx_mutex is acquired and corresponding page fault ops is called. In pagefault ops same mutex is getting acquired again causing a dead lock. This commit avoids locking the same mutex again. CRs-Fixed: 3419490 Change-Id: I2e37f725865d091f2cb682fc62f5d21278b93959 Signed-off-by: Shivakumar Malke --- drivers/cam_ope/cam_ope_context.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cam_ope/cam_ope_context.c b/drivers/cam_ope/cam_ope_context.c index c8be0da353d4..de93c02a0eab 100644 --- a/drivers/cam_ope/cam_ope_context.c +++ b/drivers/cam_ope/cam_ope_context.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -39,7 +40,6 @@ static int cam_ope_context_dump_active_request(void *data, return -EINVAL; } - mutex_lock(&ctx->ctx_mutex); if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) { CAM_ERR(CAM_OPE, "Invalid state ope ctx %d state %d", ctx->ctx_id, ctx->state); @@ -65,7 +65,6 @@ static int cam_ope_context_dump_active_request(void *data, } end: - mutex_unlock(&ctx->ctx_mutex); return rc; } From 9b3f91ecabd6a069bfe6026cecbdadc6795fd8d6 Mon Sep 17 00:00:00 2001 From: Yash Upadhyay Date: Tue, 14 Mar 2023 21:38:14 +0530 Subject: [PATCH 2/3] msm: camera: cdm: check irq status on hang detection Problem: Check IRQ status on hang detection if the inline IRQ is set then the cdm has triggered IRQ but there is a workqueue scheduling delay which is causing the cdm's config timeout. Solution: To prevent the timeout due to scheduling delay check the work record and irq status and return true if its delay. CRs-Fixed: 3433175 Change-Id: Iaa34f8ff9b57e7da9f80677a7da9b4f9a53dad14 Signed-off-by: Yash Upadhyay --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 40 ++++++++++----------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index e5342bd95163..6f25c913b352 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -2648,6 +2648,7 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, struct cam_tfe_hw_mgr_ctx *ctx; struct cam_isp_prepare_hw_update_data *hw_update_data; bool cdm_hang_detect = false; + unsigned long rem_jiffies = 0; if (!hw_mgr_priv || !config_hw_args) { CAM_ERR(CAM_ISP, "Invalid arguments"); @@ -2814,12 +2815,13 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, goto end; for (i = 0; i < CAM_TFE_HW_CONFIG_WAIT_MAX_TRY; i++) { - rc = wait_for_completion_timeout( + rem_jiffies = wait_for_completion_timeout( &ctx->config_done_complete, msecs_to_jiffies( CAM_TFE_HW_CONFIG_TIMEOUT)); - if (rc <= 0) { - if (!cam_cdm_detect_hang_error(ctx->cdm_handle)) { + if (rem_jiffies <= 0) { + rc = cam_cdm_detect_hang_error(ctx->cdm_handle); + if (rc == 0) { CAM_ERR(CAM_ISP, "CDM workqueue delay detected, wait for some more time req_id=%llu rc=%d ctx_index %d", cfg->request_id, rc, @@ -2831,24 +2833,19 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, CAM_DEFAULT_VALUE, CAM_DEFAULT_VALUE, rc); continue; - } - - CAM_ERR(CAM_ISP, - "config done completion timeout for req_id=%llu rc=%d ctx_index %d", - cfg->request_id, rc, - ctx->ctx_index); - - cam_req_mgr_debug_delay_detect(); - trace_cam_delay_detect("ISP", - "config done completion timeout", - cfg->request_id, ctx->ctx_index, - CAM_DEFAULT_VALUE, CAM_DEFAULT_VALUE, - rc); - - if (rc == 0) + } else { + CAM_ERR(CAM_ISP, + "config done completion timeout, cdm_hang=%d on req_id=%llu ctx_index %d", + true, cfg->request_id, ctx->ctx_index); + cam_req_mgr_debug_delay_detect(); + trace_cam_delay_detect("ISP", + "config done completion timeout", + cfg->request_id, ctx->ctx_index, + CAM_DEFAULT_VALUE, CAM_DEFAULT_VALUE, + rc); rc = -ETIMEDOUT; - - goto end; + break; + } } else { rc = 0; CAM_DBG(CAM_ISP, @@ -2859,7 +2856,8 @@ static int cam_tfe_mgr_config_hw(void *hw_mgr_priv, } if ((i == CAM_TFE_HW_CONFIG_WAIT_MAX_TRY) && (rc == 0)) - rc = -ETIMEDOUT; + CAM_DBG(CAM_ISP, + "Wq delayed but IRQ CDM done"); end: CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id); From 68373c033159111f7d597ee9227c4080f81f5faa Mon Sep 17 00:00:00 2001 From: zhuo Date: Thu, 23 Mar 2023 17:22:13 +0800 Subject: [PATCH 3/3] msm: camera: cdm: Making WQ to have inflight works to be one For requests with multiple BL tags,in a corner case, cdm work notifies out of order requests to client as difference in bl_tags is greater than boundary check. This commit avoids out of order request processing by making number of inflight work to be 1 and increasing the priority of workqueue. And therefore removed all checks that are not required. CRs-Fixed: 3453131 Change-Id: I6db3e9379b2474347cff1618ea6ad705ca3561fb Signed-off-by: zhuo Signed-off-by: Shivakumar Malke --- drivers/cam_cdm/cam_cdm.h | 6 ++--- drivers/cam_cdm/cam_cdm_hw_core.c | 42 ++++++++++++++----------------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index df19116abab6..b78568dbd969 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_CDM_H_ @@ -24,7 +24,7 @@ #define CAM_MAX_SW_CDM_VERSION_SUPPORTED 1 #define CAM_SW_CDM_INDEX 0 -#define CAM_CDM_INFLIGHT_WORKS 5 +#define CAM_CDM_INFLIGHT_WORKS 1 #define CAM_CDM_HW_RESET_TIMEOUT 300 /* @@ -69,8 +69,6 @@ #define CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT 0x40 #define CAM_CDM_BL_FIFO_LENGTH_CFG_SHIFT 0x10 #define CAM_CDM_BL_FIFO_FLUSH_SHIFT 0x3 -#define CAM_CDM_BL_FIFO_BOUNDARY_CHECK \ - (CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT / 2) #define CAM_CDM_BL_FIFO_REQ_SIZE_MAX 0x00 #define CAM_CDM_BL_FIFO_REQ_SIZE_MAX_DIV2 0x01 diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index 901f84c3e034..857e7cc1b82d 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1264,30 +1264,26 @@ static void cam_hw_cdm_work(struct work_struct *work) list_for_each_entry_safe(node, tnode, &core->bl_fifo[fifo_idx].bl_request_list, entry) { - if ((node->bl_tag <= payload->irq_data) || - ((node->bl_tag - payload->irq_data) > - CAM_CDM_BL_FIFO_BOUNDARY_CHECK)) { - if (node->request_type == - CAM_HW_CDM_BL_CB_CLIENT) { - cam_cdm_notify_clients(cdm_hw, - CAM_CDM_CB_STATUS_BL_SUCCESS, - (void *)node); - } else if (node->request_type == - CAM_HW_CDM_BL_CB_INTERNAL) { - CAM_ERR(CAM_CDM, - "Invalid node=%pK %d", - node, - node->request_type); - } - list_del_init(&node->entry); - if (node->bl_tag == payload->irq_data) { - kfree(node); - node = NULL; - break; - } + if (node->request_type == + CAM_HW_CDM_BL_CB_CLIENT) { + cam_cdm_notify_clients(cdm_hw, + CAM_CDM_CB_STATUS_BL_SUCCESS, + (void *)node); + } else if (node->request_type == + CAM_HW_CDM_BL_CB_INTERNAL) { + CAM_ERR(CAM_CDM, + "Invalid node=%pK %d", + node, + node->request_type); + } + list_del_init(&node->entry); + if (node->bl_tag == payload->irq_data) { kfree(node); node = NULL; + break; } + kfree(node); + node = NULL; } } else { CAM_INFO(CAM_CDM, @@ -2232,7 +2228,7 @@ static int cam_hw_cdm_component_bind(struct device *dev, sizeof(cdm_core->name)); snprintf(work_q_name + len, sizeof(work_q_name) - len, "%d", i); cdm_core->bl_fifo[i].work_queue = alloc_workqueue(work_q_name, - WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS | WQ_HIGHPRI, CAM_CDM_INFLIGHT_WORKS); if (!cdm_core->bl_fifo[i].work_queue) { CAM_ERR(CAM_CDM,