From 18cd4a3e70a72f57998c6f2416fbc4151a9c0be2 Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Thu, 1 Sep 2022 11:25:17 +0800 Subject: [PATCH] video: rockchip: mpp: Add run begin/end Disable preempt when schedule task timeout work and start hardware. On heavy system burden case the kthread may be switched out between starting timeout work and real hardware starting operation and do not come back for a long time. This will cause unexpected task timeout. Signed-off-by: Herman Chen Change-Id: I636c80d5230eedd8ef98e1fd3219b83a0b99614a --- drivers/video/rockchip/mpp/mpp_av1dec.c | 10 +++++ drivers/video/rockchip/mpp/mpp_common.c | 44 ++++++++++++------- drivers/video/rockchip/mpp/mpp_common.h | 5 ++- drivers/video/rockchip/mpp/mpp_iep2.c | 9 ++++ drivers/video/rockchip/mpp/mpp_jpgdec.c | 6 +++ drivers/video/rockchip/mpp/mpp_rkvdec2.c | 6 +++ drivers/video/rockchip/mpp/mpp_rkvdec2_link.c | 25 ++++------- drivers/video/rockchip/mpp/mpp_rkvenc.c | 6 +++ drivers/video/rockchip/mpp/mpp_rkvenc2.c | 6 +++ drivers/video/rockchip/mpp/mpp_vdpu1.c | 6 +++ drivers/video/rockchip/mpp/mpp_vdpu2.c | 6 +++ drivers/video/rockchip/mpp/mpp_vepu1.c | 6 +++ drivers/video/rockchip/mpp/mpp_vepu2.c | 6 +++ 13 files changed, 109 insertions(+), 32 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_av1dec.c b/drivers/video/rockchip/mpp/mpp_av1dec.c index 797f2a870b0c..26ef14a3fe79 100644 --- a/drivers/video/rockchip/mpp/mpp_av1dec.c +++ b/drivers/video/rockchip/mpp/mpp_av1dec.c @@ -652,6 +652,7 @@ static int av1dec_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) struct av1dec_dev *dec = to_av1dec_dev(mpp); struct av1dec_hw_info *hw = dec->hw_info; struct av1dec_task *task = to_av1dec_task(mpp_task); + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); mpp_iommu_flush_tlb(mpp->iommu_info); @@ -687,10 +688,15 @@ static int av1dec_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Flush the register before the start the device */ wmb(); mpp_write(mpp, hw->en_base, en_val); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; @@ -879,6 +885,10 @@ static int av1dec_procfs_init(struct mpp_dev *mpp) dec->procfs = NULL; return -EIO; } + + /* for common mpp_dev options */ + mpp_procfs_create_common(dec->procfs, mpp); + /* for debug */ mpp_procfs_create_u32("aclk", 0644, dec->procfs, &dec->aclk_info.debug_rate_hz); diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index 295a6caec33c..3565926e64c1 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -36,7 +36,6 @@ #include "mpp_common.h" #include "mpp_iommu.h" -#define MPP_WORK_TIMEOUT_DELAY (500) #define MPP_WAIT_TIMEOUT_DELAY (2000) /* Use 'v' as magic number */ @@ -751,6 +750,35 @@ int mpp_dev_reset(struct mpp_dev *mpp) return 0; } +void mpp_task_run_begin(struct mpp_task *task, u32 timing_en, u32 timeout) +{ + preempt_disable(); + + set_bit(TASK_STATE_START, &task->state); + + mpp_time_record(task); + schedule_delayed_work(&task->timeout_work, msecs_to_jiffies(timeout)); + + if (timing_en) { + task->on_sched_timeout = ktime_get(); + set_bit(TASK_TIMING_TO_SCHED, &task->state); + } +} + +void mpp_task_run_end(struct mpp_task *task, u32 timing_en) +{ + if (timing_en) { + task->on_run_end = ktime_get(); + set_bit(TASK_TIMING_RUN_END, &task->state); + } + +#ifdef MODULE + preempt_enable(); +#else + preempt_enable_no_resched(); +#endif +} + static int mpp_task_run(struct mpp_dev *mpp, struct mpp_task *task) { @@ -791,23 +819,9 @@ static int mpp_task_run(struct mpp_dev *mpp, */ mpp_reset_down_read(mpp->reset_group); - set_bit(TASK_STATE_START, &task->state); - mpp_time_record(task); - schedule_delayed_work(&task->timeout_work, - msecs_to_jiffies(MPP_WORK_TIMEOUT_DELAY)); - - if (timing_en) { - task->on_sched_timeout = ktime_get(); - set_bit(TASK_TIMING_TO_SCHED, &task->state); - } - if (mpp->dev_ops->run) mpp->dev_ops->run(mpp, task); - if (timing_en) { - task->on_run_end = ktime_get(); - set_bit(TASK_TIMING_RUN_END, &task->state); - } mpp_debug_leave(); return 0; diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index 2a40521cdcad..cf62cc396dcf 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -25,7 +25,8 @@ #include #include -#define MHZ (1000 * 1000) +#define MHZ (1000 * 1000) +#define MPP_WORK_TIMEOUT_DELAY (500) #define MPP_MAX_MSG_NUM (16) #define MPP_MAX_REG_TRANS_NUM (60) @@ -662,6 +663,8 @@ int mpp_task_init(struct mpp_session *session, struct mpp_task *task); int mpp_task_finish(struct mpp_session *session, struct mpp_task *task); +void mpp_task_run_begin(struct mpp_task *task, u32 timing_en, u32 timeout); +void mpp_task_run_end(struct mpp_task *task, u32 timing_en); int mpp_task_finalize(struct mpp_session *session, struct mpp_task *task); int mpp_task_dump_mem_region(struct mpp_dev *mpp, diff --git a/drivers/video/rockchip/mpp/mpp_iep2.c b/drivers/video/rockchip/mpp/mpp_iep2.c index e92c68827704..74a72540a854 100644 --- a/drivers/video/rockchip/mpp/mpp_iep2.c +++ b/drivers/video/rockchip/mpp/mpp_iep2.c @@ -578,6 +578,7 @@ static int iep2_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) { struct iep_task *task = NULL; + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -598,11 +599,15 @@ static int iep2_run(struct mpp_dev *mpp, | IEP2_REG_OSD_MAX_EN | IEP2_REG_BUS_ERROR_EN); + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Last, flush the registers */ wmb(); /* start iep2 */ mpp_write(mpp, IEP2_REG_FRM_START, 1); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; @@ -767,6 +772,10 @@ static int iep2_procfs_init(struct mpp_dev *mpp) iep->procfs = NULL; return -EIO; } + + /* for common mpp_dev options */ + mpp_procfs_create_common(iep->procfs, mpp); + mpp_procfs_create_u32("aclk", 0644, iep->procfs, &iep->aclk_info.debug_rate_hz); mpp_procfs_create_u32("session_buffers", 0644, diff --git a/drivers/video/rockchip/mpp/mpp_jpgdec.c b/drivers/video/rockchip/mpp/mpp_jpgdec.c index 58e8b16222ec..4cdbceb22250 100644 --- a/drivers/video/rockchip/mpp/mpp_jpgdec.c +++ b/drivers/video/rockchip/mpp/mpp_jpgdec.c @@ -251,6 +251,7 @@ static int jpgdec_run(struct mpp_dev *mpp, u32 i; u32 reg_en; struct jpgdec_task *task = to_jpgdec_task(mpp_task); + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -265,11 +266,16 @@ static int jpgdec_run(struct mpp_dev *mpp, } /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Flush the register before the start the device */ wmb(); mpp_write(mpp, JPGDEC_REG_INT_EN_BASE, task->reg[reg_en] | JPGDEC_START_EN); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2.c b/drivers/video/rockchip/mpp/mpp_rkvdec2.c index 5acc6049b562..5c5ca8f38c90 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2.c @@ -318,6 +318,7 @@ static void *rkvdec2_rk3568_alloc_task(struct mpp_session *session, static int rkvdec2_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) { struct rkvdec2_task *task = to_rkvdec2_task(mpp_task); + u32 timing_en = mpp->srv->timing_en; u32 reg_en = mpp_task->hw_info->reg_en; /* set cache size */ u32 reg = RKVDEC_CACHE_PERMIT_CACHEABLE_ACCESS | @@ -352,10 +353,15 @@ static int rkvdec2_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Flush the register before the start the device */ wmb(); mpp_write(mpp, RKVDEC_REG_START_EN_BASE, task->reg[reg_en] | RKVDEC_START_EN); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c index 8396cb4622d6..0dd7c21d85af 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c @@ -458,6 +458,7 @@ static int rkvdec_link_send_task_to_hw(struct rkvdec_link_dev *dev, } if (!resend) { + u32 timing_en = dev->mpp->srv->timing_en; u32 i; for (i = 0; i < task_to_run; i++) { @@ -467,9 +468,8 @@ static int rkvdec_link_send_task_to_hw(struct rkvdec_link_dev *dev, if (!task_ddr) continue; - set_bit(TASK_STATE_START, &task_ddr->state); - schedule_delayed_work(&task_ddr->timeout_work, - msecs_to_jiffies(200)); + mpp_task_run_begin(task_ddr, timing_en, WORK_TIMEOUT_MS); + mpp_task_run_end(task_ddr, timing_en); } } else { if (task_total) @@ -1826,6 +1826,7 @@ static int rkvdec2_soft_ccu_enqueue(struct mpp_dev *mpp, struct mpp_task *mpp_ta u32 i, reg_en, reg; struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); struct rkvdec2_task *task = to_rkvdec2_task(mpp_task); + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -1865,12 +1866,17 @@ static int rkvdec2_soft_ccu_enqueue(struct mpp_dev *mpp, struct mpp_task *mpp_ta } /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + mpp->irq_status = 0; writel_relaxed(dec->core_mask, dec->ccu->reg_base + RKVDEC_CCU_CORE_STA_BASE); /* Flush the register before the start the device */ wmb(); mpp_write(mpp, RKVDEC_REG_START_EN_BASE, task->reg[reg_en] | RKVDEC_START_EN); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; @@ -1998,26 +2004,13 @@ get_task: mutex_unlock(&queue->pending_lock); set_bit(TASK_STATE_RUNNING, &mpp_task->state); - mpp_time_record(mpp_task); mpp_debug(DEBUG_TASK_INFO, "pid %d, start hw %s\n", mpp_task->session->pid, dev_name(mpp->dev)); - set_bit(TASK_STATE_START, &mpp_task->state); INIT_DELAYED_WORK(&mpp_task->timeout_work, rkvdec2_ccu_link_timeout_work); - schedule_delayed_work(&mpp_task->timeout_work, msecs_to_jiffies(WORK_TIMEOUT_MS)); - - if (timing_en) { - mpp_task->on_sched_timeout = ktime_get(); - set_bit(TASK_TIMING_TO_SCHED, &mpp_task->state); - } rkvdec2_ccu_power_on(queue, dec->ccu); rkvdec2_soft_ccu_enqueue(mpp, mpp_task); - if (timing_en) { - mpp_task->on_run_end = ktime_get(); - set_bit(TASK_TIMING_RUN_END, &mpp_task->state); - } - done: if (list_empty(&queue->running_list) && list_empty(&queue->pending_list)) diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc.c b/drivers/video/rockchip/mpp/mpp_rkvenc.c index e5370cd50071..3d142a05e8c9 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc.c @@ -439,6 +439,7 @@ static int rkvenc_run(struct mpp_dev *mpp, int i; struct mpp_request *req; u32 reg_en = mpp_task->hw_info->reg_en; + u32 timing_en = mpp->srv->timing_en; /* * Tips: ensure osd plt clock is 0 before setting register, @@ -468,9 +469,14 @@ static int rkvenc_run(struct mpp_dev *mpp, } /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Flush the register before the start the device */ wmb(); mpp_write(mpp, RKVENC_ENC_START_BASE, task->reg[reg_en]); + + mpp_task_run_end(mpp_task, timing_en); } break; case RKVENC_MODE_LINKTABLE_FIX: case RKVENC_MODE_LINKTABLE_UPDATE: diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc2.c b/drivers/video/rockchip/mpp/mpp_rkvenc2.c index 0358e5ca9c1c..8b2c2d4516a7 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc2.c @@ -1019,6 +1019,7 @@ static int rkvenc_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) struct rkvenc_dev *enc = to_rkvenc_dev(mpp); struct rkvenc_task *task = to_rkvenc_task(mpp_task); struct rkvenc_hw_info *hw = enc->hw_info; + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -1067,10 +1068,15 @@ static int rkvenc_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) /* init current task */ mpp->cur_task = mpp_task; + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Flush the register before the start the device */ wmb(); + mpp_write(mpp, enc->hw_info->enc_start_base, start_val); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; diff --git a/drivers/video/rockchip/mpp/mpp_vdpu1.c b/drivers/video/rockchip/mpp/mpp_vdpu1.c index 0d4bb9ee8c79..926be9d7834f 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu1.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu1.c @@ -390,6 +390,7 @@ static int vdpu_run(struct mpp_dev *mpp, u32 i; u32 reg_en; struct vdpu_task *task = to_vdpu_task(mpp_task); + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -406,11 +407,16 @@ static int vdpu_run(struct mpp_dev *mpp, } /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Flush the register before the start the device */ wmb(); mpp_write(mpp, VDPU1_REG_DEC_INT_EN, task->reg[reg_en] | VDPU1_DEC_START); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; diff --git a/drivers/video/rockchip/mpp/mpp_vdpu2.c b/drivers/video/rockchip/mpp/mpp_vdpu2.c index e3d78d710f59..b63fc48c4568 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu2.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu2.c @@ -343,6 +343,7 @@ static int vdpu_run(struct mpp_dev *mpp, u32 i; u32 reg_en; struct vdpu_task *task = to_vdpu_task(mpp_task); + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -359,11 +360,16 @@ static int vdpu_run(struct mpp_dev *mpp, } /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Flush the registers */ wmb(); mpp_write(mpp, VDPU2_REG_DEC_EN, task->reg[reg_en] | VDPU2_DEC_START); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; diff --git a/drivers/video/rockchip/mpp/mpp_vepu1.c b/drivers/video/rockchip/mpp/mpp_vepu1.c index 3bb51c963939..8c9782d78a1b 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu1.c +++ b/drivers/video/rockchip/mpp/mpp_vepu1.c @@ -264,6 +264,7 @@ static int vepu_run(struct mpp_dev *mpp, u32 i; u32 reg_en; struct vepu_task *task = to_vepu_task(mpp_task); + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -284,11 +285,16 @@ static int vepu_run(struct mpp_dev *mpp, } /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Last, flush start registers */ wmb(); mpp_write(mpp, VEPU1_REG_ENC_EN, task->reg[reg_en] | VEPU1_ENC_START); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0; diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index 02797ba1b182..cb61fc044b6a 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -352,6 +352,7 @@ static int vepu_run(struct mpp_dev *mpp, u32 i; u32 reg_en; struct vepu_task *task = to_vepu_task(mpp_task); + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -372,11 +373,16 @@ static int vepu_run(struct mpp_dev *mpp, } /* init current task */ mpp->cur_task = mpp_task; + + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); + /* Last, flush the registers */ wmb(); mpp_write(mpp, VEPU2_REG_ENC_EN, task->reg[reg_en] | VEPU2_ENC_START); + mpp_task_run_end(mpp_task, timing_en); + mpp_debug_leave(); return 0;