video: rockchip: mpp: fix some issue for ccu flow

1. Simplify some code.
2. Use mpp_time_diff_with_hw_time to get hw time.
3. Loop to get task from pending list after task enqueue hw
successfully.

Signed-off-by: Yandong Lin <yandong.lin@rock-chips.com>
Change-Id: Icfecbc6b620efbf410076ca3765fb921d1665260
This commit is contained in:
Yandong Lin 2023-03-20 14:54:15 +08:00 committed by Tao Huang
parent b01336f37d
commit 95949accd3

View File

@ -1385,7 +1385,8 @@ static void rkvdec2_ccu_timeout_work(struct work_struct *work_s)
return;
}
mpp = mpp_get_task_used_device(task, task->session);
mpp_err("%s, task timeout\n", dev_name(mpp->dev));
mpp_err("%s, task %d state %#lx timeout\n", dev_name(mpp->dev),
task->task_index, task->state);
set_bit(TASK_STATE_TIMEOUT, &task->state);
atomic_inc(&mpp->reset_request);
atomic_inc(&mpp->queue->reset_request);
@ -1878,73 +1879,70 @@ void rkvdec2_soft_ccu_worker(struct kthread_work *work_s)
mpp_debug_enter();
/* process all finished task in running list */
/* 1. process all finished task in running list */
rkvdec2_soft_ccu_dequeue(queue);
/* process reset request */
/* 2. process reset request */
if (atomic_read(&queue->reset_request)) {
if (rkvdec2_core_working(queue))
goto out;
rkvdec2_ccu_power_on(queue, dec->ccu);
rkvdec2_soft_ccu_reset(queue, dec->ccu);
if (!rkvdec2_core_working(queue)) {
rkvdec2_ccu_power_on(queue, dec->ccu);
rkvdec2_soft_ccu_reset(queue, dec->ccu);
}
}
get_task:
/* get one task form pending list */
mutex_lock(&queue->pending_lock);
mpp_task = list_first_entry_or_null(&queue->pending_list,
struct mpp_task, queue_link);
mutex_unlock(&queue->pending_lock);
if (!mpp_task)
goto done;
if (test_bit(TASK_STATE_ABORT, &mpp_task->state)) {
/* 3. process pending task */
while (1) {
if (atomic_read(&queue->reset_request))
break;
/* get one task form pending list */
mutex_lock(&queue->pending_lock);
list_del_init(&mpp_task->queue_link);
set_bit(TASK_STATE_ABORT_READY, &mpp_task->state);
set_bit(TASK_STATE_PROC_DONE, &mpp_task->state);
mpp_task = list_first_entry_or_null(&queue->pending_list,
struct mpp_task, queue_link);
mutex_unlock(&queue->pending_lock);
wake_up(&mpp_task->wait);
kref_put(&mpp_task->ref, rkvdec2_link_free_task);
goto get_task;
}
/* find one core is idle */
mpp = rkvdec2_get_idle_core(queue, mpp_task);
if (!mpp)
goto out;
if (!mpp_task)
break;
if (timing_en) {
mpp_task->on_run = ktime_get();
set_bit(TASK_TIMING_RUN, &mpp_task->state);
if (test_bit(TASK_STATE_ABORT, &mpp_task->state)) {
mutex_lock(&queue->pending_lock);
list_del_init(&mpp_task->queue_link);
set_bit(TASK_STATE_ABORT_READY, &mpp_task->state);
set_bit(TASK_STATE_PROC_DONE, &mpp_task->state);
mutex_unlock(&queue->pending_lock);
wake_up(&mpp_task->wait);
kref_put(&mpp_task->ref, rkvdec2_link_free_task);
continue;
}
/* find one core is idle */
mpp = rkvdec2_get_idle_core(queue, mpp_task);
if (!mpp)
break;
if (timing_en) {
mpp_task->on_run = ktime_get();
set_bit(TASK_TIMING_RUN, &mpp_task->state);
}
/* set session index */
rkvdec2_set_core_info(mpp_task->reg, mpp_task->session->index);
/* set rcb buffer */
mpp_set_rcbbuf(mpp, mpp_task->session, mpp_task);
INIT_DELAYED_WORK(&mpp_task->timeout_work, rkvdec2_ccu_timeout_work);
rkvdec2_ccu_power_on(queue, dec->ccu);
rkvdec2_soft_ccu_enqueue(mpp, mpp_task);
/* pending to running */
mpp_taskqueue_pending_to_run(queue, mpp_task);
set_bit(TASK_STATE_RUNNING, &mpp_task->state);
}
/* set session index */
rkvdec2_set_core_info(mpp_task->reg, mpp_task->session->index);
/* set rcb buffer */
mpp_set_rcbbuf(mpp, mpp_task->session, mpp_task);
/* pending to running */
mutex_lock(&queue->pending_lock);
list_move_tail(&mpp_task->queue_link, &queue->running_list);
mutex_unlock(&queue->pending_lock);
set_bit(TASK_STATE_RUNNING, &mpp_task->state);
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_timeout_work);
schedule_delayed_work(&mpp_task->timeout_work, msecs_to_jiffies(WORK_TIMEOUT_MS));
rkvdec2_ccu_power_on(queue, dec->ccu);
rkvdec2_soft_ccu_enqueue(mpp, mpp_task);
done:
/* 4. poweroff when running and pending list are empty */
if (list_empty(&queue->running_list) &&
list_empty(&queue->pending_list))
rkvdec2_ccu_power_off(queue, dec->ccu);
out:
/* session detach out of queue */
/* 5. check session detach out of queue */
rkvdec2_ccu_link_session_detach(mpp, queue);
mpp_debug_leave();
@ -2089,9 +2087,12 @@ static int rkvdec2_hard_ccu_dequeue(struct mpp_taskqueue *queue,
ccu_decoded_num, ccu_total_dec_num);
if (irq_status || timeout_flag || abort_flag) {
struct rkvdec2_dev *dec = to_rkvdec2_dev(queue->cores[0]);
set_bit(TASK_STATE_HANDLE, &mpp_task->state);
cancel_delayed_work(&mpp_task->timeout_work);
mpp_time_diff(mpp_task);
mpp_task->hw_cycles = tb_reg[hw->tb_reg_cycle];
mpp_time_diff_with_hw_time(mpp_task, dec->cycle_clk->real_rate_hz);
task->irq_status = irq_status;
if (irq_status)
@ -2309,6 +2310,7 @@ static int rkvdec2_hard_ccu_enqueue(struct rkvdec2_ccu *ccu,
{
u32 ccu_en, work_mode, link_mode;
struct rkvdec2_task *task = to_rkvdec2_task(mpp_task);
u32 timing_en = mpp->srv->timing_en;
mpp_debug_enter();
@ -2358,20 +2360,15 @@ static int rkvdec2_hard_ccu_enqueue(struct rkvdec2_ccu *ccu,
mpp_iommu_flush_tlb(mpp->iommu_info);
/* wmb */
wmb();
INIT_DELAYED_WORK(&mpp_task->timeout_work, rkvdec2_ccu_timeout_work);
mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY);
/* configure done */
writel(RKVDEC_CCU_BIT_CFG_DONE, ccu->reg_base + RKVDEC_CCU_CFG_DONE_BASE);
mpp_task_run_end(mpp_task, timing_en);
mpp_time_record(mpp_task);
set_bit(TASK_STATE_START, &mpp_task->state);
INIT_DELAYED_WORK(&mpp_task->timeout_work, rkvdec2_ccu_timeout_work);
schedule_delayed_work(&mpp_task->timeout_work, msecs_to_jiffies(WORK_TIMEOUT_MS));
/* pending to running */
if (!test_bit(TASK_STATE_RUNNING, &mpp_task->state)) {
mutex_lock(&queue->pending_lock);
set_bit(TASK_STATE_RUNNING, &mpp_task->state);
list_move_tail(&mpp_task->queue_link, &queue->running_list);
mutex_unlock(&queue->pending_lock);
}
set_bit(TASK_STATE_RUNNING, &mpp_task->state);
mpp_taskqueue_pending_to_run(queue, mpp_task);
mpp_dbg_ccu("session %d task %d iova=%08x task->state=%lx link_mode=%08x\n",
mpp_task->session->index, mpp_task->task_index,
(u32)task->table->iova, mpp_task->state,
@ -2488,10 +2485,10 @@ void rkvdec2_hard_ccu_worker(struct kthread_work *work_s)
mpp_debug_enter();
/* process all finished task in running list */
/* 1. process all finished task in running list */
rkvdec2_hard_ccu_dequeue(queue, dec->ccu, dec->link_dec->info);
/* process reset request */
/* 2. process reset request */
if (atomic_read(&queue->reset_request) &&
(list_empty(&queue->running_list) || !dec->ccu->ccu_core_work_mode)) {
/*
@ -2516,41 +2513,44 @@ void rkvdec2_hard_ccu_worker(struct kthread_work *work_s)
if (!list_empty(&queue->running_list))
rkvdec2_hard_ccu_resend_tasks(mpp, queue);
}
get_task:
/* get one task form pending list */
mutex_lock(&queue->pending_lock);
mpp_task = list_first_entry_or_null(&queue->pending_list,
struct mpp_task, queue_link);
mutex_unlock(&queue->pending_lock);
if (!mpp_task)
goto done;
if (test_bit(TASK_STATE_ABORT, &mpp_task->state)) {
/* 3. process pending task */
while (1) {
if (atomic_read(&queue->reset_request))
break;
/* get one task form pending list */
mutex_lock(&queue->pending_lock);
list_del_init(&mpp_task->queue_link);
mpp_task = list_first_entry_or_null(&queue->pending_list,
struct mpp_task, queue_link);
mutex_unlock(&queue->pending_lock);
kref_put(&mpp_task->ref, mpp_free_task);
goto get_task;
if (!mpp_task)
break;
if (test_bit(TASK_STATE_ABORT, &mpp_task->state)) {
mutex_lock(&queue->pending_lock);
list_del_init(&mpp_task->queue_link);
mutex_unlock(&queue->pending_lock);
kref_put(&mpp_task->ref, mpp_free_task);
continue;
}
mpp_task = rkvdec2_hard_ccu_prepare(mpp_task, dec->ccu, dec->link_dec->info);
if (!mpp_task)
break;
rkvdec2_ccu_power_on(queue, dec->ccu);
rkvdec2_hard_ccu_enqueue(dec->ccu, mpp_task, queue, mpp);
}
if (atomic_read(&queue->reset_request))
mpp_task = NULL;
else
mpp_task = rkvdec2_hard_ccu_prepare(mpp_task, dec->ccu, dec->link_dec->info);
if (!mpp_task)
goto done;
rkvdec2_ccu_power_on(queue, dec->ccu);
rkvdec2_hard_ccu_enqueue(dec->ccu, mpp_task, queue, mpp);
done:
/* 4. poweroff when running and pending list are empty */
mutex_lock(&queue->pending_lock);
if (list_empty(&queue->running_list) &&
list_empty(&queue->pending_list))
rkvdec2_ccu_power_off(queue, dec->ccu);
mutex_unlock(&queue->pending_lock);
/* session detach out of queue */
/* 5. check session detach out of queue */
mpp_session_cleanup_detach(queue, work_s);
mpp_debug_leave();