From eb966dcdee4e2760319a1124843ab7953024d417 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Tue, 19 Nov 2024 10:10:29 +0800 Subject: [PATCH] video: rockchip: rga3: fix hardware state has been cleared after timeout Change-Id: I15607f0af364bbb5947aba19024f0d582148016f Signed-off-by: Yu Qiaowei --- drivers/video/rockchip/rga3/rga2_reg_info.c | 28 +++++++++++++++------ drivers/video/rockchip/rga3/rga_job.c | 18 +++++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index c2af876a98db..49523d5d7e95 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -3120,23 +3120,35 @@ static int rga2_read_status(struct rga_job *job, struct rga_scheduler_t *schedul return 0; } -static int rga2_irq(struct rga_scheduler_t *scheduler) +static void rga2_clear_intr(struct rga_scheduler_t *scheduler) { - struct rga_job *job = scheduler->running_job; - - /*clear INTR */ rga_write(rga_read(RGA2_INT, scheduler) | (m_RGA2_INT_ERROR_CLEAR_MASK | m_RGA2_INT_ALL_CMD_DONE_INT_CLEAR | m_RGA2_INT_NOW_CMD_DONE_INT_CLEAR | m_RGA2_INT_LINE_RD_CLEAR | m_RGA2_INT_LINE_WR_CLEAR), RGA2_INT, scheduler); +} + +static int rga2_irq(struct rga_scheduler_t *scheduler) +{ + struct rga_job *job = scheduler->running_job; /* The hardware interrupt top-half don't need to lock the scheduler. */ - if (job == NULL) - return IRQ_HANDLED; + if (job == NULL) { + rga2_clear_intr(scheduler); + rga_err("core[%d], invalid job, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x], WORK_CYCLE[0x%x(%d)]\n", + scheduler->core, rga_read(RGA2_INT, scheduler), + rga_read(RGA2_STATUS2, scheduler), rga_read(RGA2_STATUS1, scheduler), + rga_read(RGA2_WORK_CNT, scheduler), rga_read(RGA2_WORK_CNT, scheduler)); + + return IRQ_HANDLED; + } + + if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) { + rga2_clear_intr(scheduler); - if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) return IRQ_WAKE_THREAD; + } scheduler->ops->read_status(job, scheduler); @@ -3158,6 +3170,8 @@ static int rga2_irq(struct rga_scheduler_t *scheduler) scheduler->ops->soft_reset(scheduler); } + rga2_clear_intr(scheduler); + return IRQ_WAKE_THREAD; } diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c index dd184821b373..7625ab33df1b 100644 --- a/drivers/video/rockchip/rga3/rga_job.c +++ b/drivers/video/rockchip/rga3/rga_job.c @@ -263,27 +263,29 @@ static int rga_job_timeout_query_state(struct rga_job *job, int orig_ret) { struct rga_scheduler_t *scheduler = job->scheduler; - if (scheduler->ops->read_status) { - scheduler->ops->read_status(job, scheduler); - rga_job_err(job, "core[%d]: INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x], WORK_CYCLE[0x%x(%d)]\n", - scheduler->core, - job->intr_status, job->hw_status, job->cmd_status, - job->work_cycle, job->work_cycle); - } - if (test_bit(RGA_JOB_STATE_DONE, &job->state) && test_bit(RGA_JOB_STATE_FINISH, &job->state)) { return orig_ret; } else if (!test_bit(RGA_JOB_STATE_DONE, &job->state) && test_bit(RGA_JOB_STATE_FINISH, &job->state)) { rga_job_err(job, "job hardware has finished, but the software has timeout!\n"); + return -EBUSY; } else if (!test_bit(RGA_JOB_STATE_DONE, &job->state) && !test_bit(RGA_JOB_STATE_FINISH, &job->state)) { rga_job_err(job, "job hardware has timeout.\n"); + + if (scheduler->ops->read_status) + scheduler->ops->read_status(job, scheduler); + return -EBUSY; } + rga_job_err(job, "timeout core[%d]: INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x], WORK_CYCLE[0x%x(%d)]\n", + scheduler->core, + job->intr_status, job->hw_status, job->cmd_status, + job->work_cycle, job->work_cycle); + return orig_ret; }