mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
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 <herman.chen@rock-chips.com> Change-Id: I636c80d5230eedd8ef98e1fd3219b83a0b99614a
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <soc/rockchip/pm_domains.h>
|
||||
|
||||
#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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user