diff --git a/drivers/video/rockchip/mpp/mpp_av1dec.c b/drivers/video/rockchip/mpp/mpp_av1dec.c index 2d2055afc1a4..f64de732c716 100644 --- a/drivers/video/rockchip/mpp/mpp_av1dec.c +++ b/drivers/video/rockchip/mpp/mpp_av1dec.c @@ -1009,7 +1009,7 @@ static int av1dec_probe(struct platform_device *pdev) dec->reg_base[AV1DEC_CLASS_VCD] = mpp->reg_base; ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index 84c3502f9103..bfe7d9715088 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -517,9 +517,9 @@ void mpp_free_task(struct kref *ref) } session = task->session; - mpp_debug_func(DEBUG_TASK_INFO, "task %d:%d free state 0x%lx abort %d\n", - session->index, task->task_id, task->state, - atomic_read(&task->abort_request)); + mpp_debug_func(DEBUG_TASK_INFO, "session %d:%d task %d state 0x%lx abort %d\n", + session->device_type, session->index, task->task_index, + task->state, atomic_read(&task->abort_request)); mpp = mpp_get_task_used_device(task, session); if (mpp->dev_ops->free_task) @@ -532,62 +532,34 @@ void mpp_free_task(struct kref *ref) static void mpp_task_timeout_work(struct work_struct *work_s) { - struct mpp_dev *mpp; - struct mpp_session *session; struct mpp_task *task = container_of(to_delayed_work(work_s), struct mpp_task, timeout_work); + struct mpp_dev *mpp; + struct mpp_session *session = task->session; - if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { - mpp_err("task has been handled\n"); - return; - } - - if (!task->session) { + if (!session) { mpp_err("task %p, task->session is null.\n", task); return; } - session = task->session; - mpp_err("task %d:%d:%d processing time out!\n", session->pid, - session->index, task->task_id); - - if (!session->mpp) { - mpp_err("session %d:%d, session mpp is null.\n", session->pid, - session->index); + mpp = mpp_get_task_used_device(task, session); + if (!mpp) { + mpp_err("session %d:%d mpp is null\n", session->device_type, session->index); return; } + disable_irq(mpp->irq); + if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { + mpp_err("task has been handled\n"); + return; + } + mpp_err("session %d:%d task %d processing time out!\n", + session->device_type, session->index, task->task_index); mpp_task_dump_timing(task, ktime_us_delta(ktime_get(), task->on_create)); - - mpp = mpp_get_task_used_device(task, session); - - /* disable core irq */ - disable_irq(mpp->irq); - /* disable mmu irq */ - if (mpp->iommu_info && mpp->iommu_info->got_irq) - disable_irq(mpp->iommu_info->irq); - - /* hardware maybe dead, reset it */ - mpp_reset_up_read(mpp->reset_group); - mpp_dev_reset(mpp); - mpp_power_off(mpp); - - mpp_iommu_dev_deactivate(mpp->iommu_info, mpp); set_bit(TASK_STATE_TIMEOUT, &task->state); - set_bit(TASK_STATE_DONE, &task->state); - /* Wake up the GET thread */ - wake_up(&task->wait); - /* remove task from taskqueue running list */ - mpp_taskqueue_pop_running(mpp->queue, task); - - /* enable core irq */ enable_irq(mpp->irq); - /* enable mmu irq */ - if (mpp->iommu_info && mpp->iommu_info->got_irq) - enable_irq(mpp->iommu_info->irq); - mpp_taskqueue_trigger_work(mpp); } @@ -648,6 +620,9 @@ static int mpp_process_task_default(struct mpp_session *session, */ atomic_inc(&session->task_count); mpp_session_push_pending(session, task); + mpp_debug_func(DEBUG_TASK_INFO, "session %d:%d task %d state 0x%lx\n", + session->device_type, session->index, + task->task_index, task->state); return 0; } @@ -713,6 +688,9 @@ int mpp_dev_reset(struct mpp_dev *mpp) { dev_info(mpp->dev, "resetting...\n"); + disable_irq(mpp->irq); + if (mpp->iommu_info && mpp->iommu_info->got_irq) + disable_irq(mpp->iommu_info->irq); /* * before running, we have to switch grf ctrl bit to ensure * working in current hardware @@ -741,6 +719,10 @@ int mpp_dev_reset(struct mpp_dev *mpp) mpp_reset_up_write(mpp->reset_group); mpp_iommu_up_write(mpp->iommu_info); + enable_irq(mpp->irq); + if (mpp->iommu_info && mpp->iommu_info->got_irq) + enable_irq(mpp->iommu_info->irq); + dev_info(mpp->dev, "reset done\n"); return 0; @@ -780,6 +762,7 @@ static int mpp_task_run(struct mpp_dev *mpp, { int ret; u32 timing_en; + struct mpp_session *session = task->session; mpp_debug_enter(); @@ -820,8 +803,9 @@ static int mpp_task_run(struct mpp_dev *mpp, } mpp_power_on(mpp); - mpp_debug_func(DEBUG_TASK_INFO, "pid %d run %s\n", - task->session->pid, dev_name(mpp->dev)); + mpp_debug_func(DEBUG_TASK_INFO, "%s session %d:%d task %d state 0x%lx\n", + dev_name(mpp->dev), session->device_type, + session->index, task->task_index, task->state); if (mpp->auto_freq_en && mpp->hw_ops->set_freq) mpp->hw_ops->set_freq(mpp, task); @@ -835,6 +819,36 @@ static int mpp_task_run(struct mpp_dev *mpp, return 0; } +static void try_process_running_task(struct mpp_dev *mpp) +{ + struct mpp_task *mpp_task, *n; + struct mpp_taskqueue *queue = mpp->queue; + + /* try process running task */ + list_for_each_entry_safe(mpp_task, n, &queue->running_list, queue_link) { + mpp = mpp_get_task_used_device(mpp_task, mpp_task->session); + disable_irq(mpp->irq); + if (!test_bit(TASK_STATE_HANDLE, &mpp_task->state)) { + enable_irq(mpp->irq); + continue; + } + + /* process timeout task */ + if (test_bit(TASK_STATE_TIMEOUT, &mpp_task->state)) { + atomic_inc(&mpp->reset_request); + mpp_iommu_dev_deactivate(mpp->iommu_info, mpp); + } + + if (mpp->auto_freq_en && mpp->hw_ops->reduce_freq && + list_empty(&mpp->queue->pending_list)) + mpp->hw_ops->reduce_freq(mpp); + + if (mpp->dev_ops->isr) + mpp->dev_ops->isr(mpp); + enable_irq(mpp->irq); + } +} + static void mpp_task_worker_default(struct kthread_work *work_s) { struct mpp_task *task; @@ -843,6 +857,7 @@ static void mpp_task_worker_default(struct kthread_work *work_s) mpp_debug_enter(); + try_process_running_task(mpp); again: task = mpp_taskqueue_get_pending_task(queue); if (!task) @@ -2245,60 +2260,39 @@ irqreturn_t mpp_dev_irq(int irq, void *param) if (mpp->dev_ops->irq) irq_ret = mpp->dev_ops->irq(mpp); - if (task) { - if (irq_ret == IRQ_WAKE_THREAD) { - /* if wait or delayed work timeout, abort request will turn on, - * isr should not to response, and handle it in delayed work - */ - if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { - mpp_err("error, task has been handled, irq_status %08x\n", - mpp->irq_status); - irq_ret = IRQ_HANDLED; - goto done; - } - if (timing_en) { - task->on_cancel_timeout = ktime_get(); - set_bit(TASK_TIMING_TO_CANCEL, &task->state); - } - cancel_delayed_work(&task->timeout_work); - /* normal condition, set state and wake up isr thread */ - set_bit(TASK_STATE_IRQ, &task->state); - } - - if (irq_ret == IRQ_WAKE_THREAD) - mpp_iommu_dev_deactivate(mpp->iommu_info, mpp); - } else { + if (!task) { mpp_debug(DEBUG_IRQ_CHECK, "error, task is null\n"); + irq_ret = IRQ_HANDLED; + goto done; } + + if (irq_ret == IRQ_WAKE_THREAD) { + /* if wait or delayed work timeout, abort request will turn on, + * isr should not to response, and handle it in delayed work + */ + if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { + dev_err(mpp->dev, "error, task %d has been handled, irq_status %#x\n", + task->task_index, mpp->irq_status); + irq_ret = IRQ_HANDLED; + goto done; + } + if (timing_en) { + task->on_cancel_timeout = ktime_get(); + set_bit(TASK_TIMING_TO_CANCEL, &task->state); + } + cancel_delayed_work(&task->timeout_work); + /* normal condition, set state and wake up isr thread */ + set_bit(TASK_STATE_IRQ, &task->state); + task->irq_status = mpp->irq_status; + mpp_iommu_dev_deactivate(mpp->iommu_info, mpp); + irq_ret = IRQ_HANDLED; + mpp_taskqueue_trigger_work(mpp); + } + done: return irq_ret; } -irqreturn_t mpp_dev_isr_sched(int irq, void *param) -{ - irqreturn_t ret = IRQ_NONE; - struct mpp_dev *mpp = param; - struct mpp_task *task = mpp->cur_task; - - if (task && mpp->srv->timing_en) { - task->on_isr = ktime_get(); - set_bit(TASK_TIMING_ISR, &task->state); - } - - if (mpp->auto_freq_en && - mpp->hw_ops->reduce_freq && - list_empty(&mpp->queue->pending_list)) - mpp->hw_ops->reduce_freq(mpp); - - if (mpp->dev_ops->isr) - ret = mpp->dev_ops->isr(mpp); - - /* trigger current queue to run next task */ - mpp_taskqueue_trigger_work(mpp); - - return ret; -} - u32 mpp_get_grf(struct mpp_grf_info *grf_info) { u32 val = 0; @@ -2417,7 +2411,6 @@ void mpp_task_dump_timing(struct mpp_task *task, s64 time_diff) LOG_TIMING(state, TASK_TIMING_RUN_END, "run end", task->on_run_end, s); LOG_TIMING(state, TASK_TIMING_IRQ, "irq", task->on_irq, s); LOG_TIMING(state, TASK_TIMING_TO_CANCEL, "timeout cancel", task->on_cancel_timeout, s); - LOG_TIMING(state, TASK_TIMING_ISR, "isr", task->on_isr, s); LOG_TIMING(state, TASK_TIMING_FINISH, "finish", task->on_finish, s); } diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index 43b62e8e7df6..fdf893c790cc 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -395,8 +395,7 @@ enum mpp_task_state { TASK_TIMING_RUN_END = 21, TASK_TIMING_IRQ = 22, TASK_TIMING_TO_CANCEL = 23, - TASK_TIMING_ISR = 24, - TASK_TIMING_FINISH = 25, + TASK_TIMING_FINISH = 24, }; /* The context for the a task */ @@ -435,7 +434,6 @@ struct mpp_task { ktime_t on_run_end; ktime_t on_irq; ktime_t on_cancel_timeout; - ktime_t on_isr; ktime_t on_finish; /* hardware info for current task */ @@ -443,6 +441,7 @@ struct mpp_task { u32 task_index; u32 task_id; u32 *reg; + u32 irq_status; /* event for session wait thread */ wait_queue_head_t wait; @@ -660,7 +659,6 @@ int mpp_power_off(struct mpp_dev *mpp); int mpp_dev_reset(struct mpp_dev *mpp); irqreturn_t mpp_dev_irq(int irq, void *param); -irqreturn_t mpp_dev_isr_sched(int irq, void *param); struct reset_control *mpp_reset_control_get(struct mpp_dev *mpp, enum MPP_RESET_TYPE type, diff --git a/drivers/video/rockchip/mpp/mpp_iep2.c b/drivers/video/rockchip/mpp/mpp_iep2.c index 15c2d4f9bf0a..8e4a0050384e 100644 --- a/drivers/video/rockchip/mpp/mpp_iep2.c +++ b/drivers/video/rockchip/mpp/mpp_iep2.c @@ -1001,7 +1001,7 @@ static int iep2_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_jpgdec.c b/drivers/video/rockchip/mpp/mpp_jpgdec.c index b88daee1c7e5..b9d415eda21f 100644 --- a/drivers/video/rockchip/mpp/mpp_jpgdec.c +++ b/drivers/video/rockchip/mpp/mpp_jpgdec.c @@ -617,7 +617,7 @@ static int jpgdec_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_jpgenc.c b/drivers/video/rockchip/mpp/mpp_jpgenc.c index a494ab5e3aa3..62f8e2f2a37f 100644 --- a/drivers/video/rockchip/mpp/mpp_jpgenc.c +++ b/drivers/video/rockchip/mpp/mpp_jpgenc.c @@ -612,7 +612,7 @@ static int jpgenc_probe(struct platform_device *pdev) return -EINVAL; } - ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, mpp_dev_isr_sched, + ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec.c b/drivers/video/rockchip/mpp/mpp_rkvdec.c index b060e12b20a8..d8628e0db099 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -1886,7 +1886,7 @@ static int rkvdec_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2.c b/drivers/video/rockchip/mpp/mpp_rkvdec2.c index 7f6a4d89cd3a..20eda6bb693c 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2.c @@ -1879,6 +1879,7 @@ static int rkvdec2_probe_default(struct platform_device *pdev) struct rkvdec2_dev *dec = NULL; struct mpp_dev *mpp = NULL; const struct of_device_id *match = NULL; + irq_handler_t irq_proc = NULL; int ret = 0; dec = devm_kzalloc(dev, sizeof(*dec), GFP_KERNEL); @@ -1903,20 +1904,18 @@ static int rkvdec2_probe_default(struct platform_device *pdev) rkvdec2_alloc_rcbbuf(pdev, dec); rkvdec2_link_init(pdev, dec); + irq_proc = mpp_dev_irq; if (dec->link_dec && (mpp->task_capacity > 1)) { - ret = devm_request_threaded_irq(dev, mpp->irq, - rkvdec2_link_irq_proc, NULL, - IRQF_SHARED, dev_name(dev), mpp); + irq_proc = rkvdec2_link_irq_proc; mpp->dev_ops->process_task = rkvdec2_link_process_task; mpp->dev_ops->wait_result = rkvdec2_link_wait_result; mpp->dev_ops->task_worker = rkvdec2_link_worker; mpp->dev_ops->deinit = rkvdec2_link_session_deinit; kthread_init_work(&mpp->work, rkvdec2_link_worker); - } else { - ret = devm_request_threaded_irq(dev, mpp->irq, - mpp_dev_irq, mpp_dev_isr_sched, - IRQF_SHARED, dev_name(dev), mpp); } + + ret = devm_request_threaded_irq(dev, mpp->irq, irq_proc, NULL, + IRQF_SHARED, dev_name(dev), mpp); if (ret) { dev_err(dev, "register interrupter runtime failed\n"); return -EINVAL; diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c index 80aab857d783..5b7fd442d132 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c @@ -1631,9 +1631,6 @@ static int rkvdec2_soft_ccu_dequeue(struct mpp_taskqueue *queue) mpp_task->on_cancel_timeout = mpp_task->on_irq; set_bit(TASK_TIMING_TO_CANCEL, &mpp_task->state); - - mpp_task->on_isr = mpp_task->on_irq; - set_bit(TASK_TIMING_ISR, &mpp_task->state); } set_bit(TASK_STATE_HANDLE, &mpp_task->state); diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc.c b/drivers/video/rockchip/mpp/mpp_rkvenc.c index 3e02712b0f60..f5bf49355165 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc.c @@ -1420,7 +1420,7 @@ static int rkvenc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc2.c b/drivers/video/rockchip/mpp/mpp_rkvenc2.c index df543a2b0efb..25c4d42539a7 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc2.c @@ -2784,7 +2784,7 @@ static int rkvenc_core_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_ONESHOT, dev_name(dev), mpp); if (ret) { @@ -2833,7 +2833,7 @@ static int rkvenc_probe_default(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_service.c b/drivers/video/rockchip/mpp/mpp_service.c index cc5968e1689e..e523fd125ed7 100644 --- a/drivers/video/rockchip/mpp/mpp_service.c +++ b/drivers/video/rockchip/mpp/mpp_service.c @@ -380,7 +380,7 @@ static int mpp_service_probe(struct platform_device *pdev) kthread_init_worker(&queue->worker); queue->kworker_task = kthread_run(kthread_worker_fn, &queue->worker, - "queue_work%d", i); + "mpp_worker_%d", i); srv->task_queues[i] = queue; } diff --git a/drivers/video/rockchip/mpp/mpp_vdpp.c b/drivers/video/rockchip/mpp/mpp_vdpp.c index ea6f51c28461..e24687c41a74 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpp.c +++ b/drivers/video/rockchip/mpp/mpp_vdpp.c @@ -784,7 +784,7 @@ static int vdpp_probe(struct platform_device *pdev) /* get irq */ ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_vdpu1.c b/drivers/video/rockchip/mpp/mpp_vdpu1.c index 6ddf5dae73f3..e6a76d230d71 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu1.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu1.c @@ -926,7 +926,7 @@ static int vdpu_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_vdpu2.c b/drivers/video/rockchip/mpp/mpp_vdpu2.c index d5a6a3017208..0a165fa5d0f6 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu2.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu2.c @@ -762,7 +762,7 @@ static int vdpu_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_vepu1.c b/drivers/video/rockchip/mpp/mpp_vepu1.c index 18f685a2e948..4ebd0a57d74d 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu1.c +++ b/drivers/video/rockchip/mpp/mpp_vepu1.c @@ -754,7 +754,7 @@ static int vepu_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index fb5f5e5c28e3..05a5556e0f8d 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -1135,7 +1135,7 @@ static int vepu_core_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) { @@ -1185,7 +1185,7 @@ static int vepu_probe_default(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, - mpp_dev_isr_sched, + NULL, IRQF_SHARED, dev_name(dev), mpp); if (ret) {