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 <[email protected]>
This commit is contained in:
zhuo 2022-01-04 10:54:30 +08:00
commit f33380f182
2 changed files with 25 additions and 17 deletions

View file

@ -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

View file

@ -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 <linux/delay.h>
@ -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,