From a11227325372000eec0b89bd415ad5febf2cc8ce Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Fri, 6 Aug 2021 15:43:29 +0800 Subject: [PATCH] video: rockchip: mpp: fix hw hang issue When the CPU is busy, there may be a situation: 1. After the software timeout task of the current task is mounted 2. Than the thread is cut away for too long, and the hardware is not configured at this time, 3. The software timeout is triggered to go to reset and poweroff. 4. The thread switches back to configure the hardware 5. The hardware is stuck. Solution: In the software timeout processing function, judge whether the hardware at this time has been configured to start. Signed-off-by: Yandong Lin Change-Id: I00c0794bb2f27690ab8a2341b3bee2d3f942adf8 --- drivers/video/rockchip/mpp/mpp_common.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index 1e78ce91fd2d..101497223bd0 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -452,8 +452,10 @@ static void mpp_task_timeout_work(struct work_struct *work_s) struct mpp_task, timeout_work); - if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { - mpp_err("task has been handled\n"); + if (!test_bit(TASK_STATE_START, &task->state)) { + mpp_err("task has not start\n"); + schedule_delayed_work(&task->timeout_work, + msecs_to_jiffies(MPP_WORK_TIMEOUT_DELAY)); return; } @@ -470,6 +472,13 @@ static void mpp_task_timeout_work(struct work_struct *work_s) } mpp = session->mpp; + synchronize_hardirq(mpp->irq); + + if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { + mpp_err("task has been handled\n"); + return; + } + /* hardware maybe dead, reset it */ mpp_reset_up_read(mpp->reset_group); mpp_dev_reset(mpp); @@ -674,11 +683,11 @@ static int mpp_task_run(struct mpp_dev *mpp, */ mpp_reset_down_read(mpp->reset_group); - set_bit(TASK_STATE_START, &task->state); schedule_delayed_work(&task->timeout_work, msecs_to_jiffies(MPP_WORK_TIMEOUT_DELAY)); if (mpp->dev_ops->run) mpp->dev_ops->run(mpp, task); + set_bit(TASK_STATE_START, &task->state); mpp_debug_leave();