From f33380f1828c21262133e60112422c7493498f26 Mon Sep 17 00:00:00 2001 From: zhuo Date: Tue, 4 Jan 2022 10:54:30 +0800 Subject: [PATCH] msm: camera: cdm: Fix workqueue timing issue Due to workqueue does not process the work in order, so sometimes the later work will be processed earlier. Such as, when submit request order: 1/2/3, cdm interrupt come order: 1/2/3, workqueue process order: 2/1/3, when process 2 request, which currently will notify 1/2 CDM clients and remove 1/2 from submit list. After that, when process 1 request, will notify 3, actually 3 is not done at the moment, which maybe cause smmu page fault issue. And sometimes, when there is a delay in handling interrupts, then HLOS handles two interrupts as one only. This change only notify the request less than and equal to the interrupt request. CRs-Fixed: 3130447 Change-Id: I0fd0e8adee48767e5ab7db1921a8284d107c2f40 Signed-off-by: zhuo --- drivers/cam_cdm/cam_cdm.h | 3 +++ drivers/cam_cdm/cam_cdm_hw_core.c | 39 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index dc2c164e0b2c..df19116abab6 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -1,6 +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. */ #ifndef _CAM_CDM_H_ @@ -68,6 +69,8 @@ #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 bd1e938a0d0f..901f84c3e034 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1,6 +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. */ #include @@ -1263,26 +1264,30 @@ 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->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) { + 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; + } kfree(node); node = NULL; - break; } - kfree(node); - node = NULL; } } else { CAM_INFO(CAM_CDM,