From 95949accd3b4f5ef3c1de71e4067cc4a92650f76 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Mon, 20 Mar 2023 14:54:15 +0800 Subject: [PATCH] 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 Change-Id: Icfecbc6b620efbf410076ca3765fb921d1665260 --- drivers/video/rockchip/mpp/mpp_rkvdec2_link.c | 184 +++++++++--------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c index c21687925081..eb0e62097460 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c @@ -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();