From 2cb1de1151f2737a54c8563258ee7761fc30e97a Mon Sep 17 00:00:00 2001 From: "hyesoo.yu" Date: Mon, 25 Sep 2017 09:12:30 +0900 Subject: [PATCH] [COMMON] g2d: add extra information for debug First, we add the time from user request to H/W start, and from H/W start to H/W finishing. Second, we record H/W status on error interrupt or H/W timeout without exception. Third, we record whether the task has compressed format or not when acquire fence timeout happens due to possibility to read without writing all. Change-Id: Idd0b274f23f6221af1e652482f23957d7931bf4e Signed-off-by: hyesoo.yu --- drivers/gpu/exynos/g2d/g2d_debug.c | 12 +++--- drivers/gpu/exynos/g2d/g2d_debug.h | 18 ++++----- drivers/gpu/exynos/g2d/g2d_drv.c | 46 +++++++++++++---------- drivers/gpu/exynos/g2d/g2d_fence.c | 13 ++++++- drivers/gpu/exynos/g2d/g2d_task.c | 23 ++++++------ drivers/gpu/exynos/g2d/g2d_uapi_process.c | 4 +- 6 files changed, 67 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/exynos/g2d/g2d_debug.c b/drivers/gpu/exynos/g2d/g2d_debug.c index db33fd581d52..2e4099b11d75 100644 --- a/drivers/gpu/exynos/g2d/g2d_debug.c +++ b/drivers/gpu/exynos/g2d/g2d_debug.c @@ -32,6 +32,7 @@ static struct g2d_stamp { u32 state; u32 job_id; u32 val; + s32 info; u8 cpu; } g2d_stamp_list[G2D_MAX_STAMP_SIZE]; @@ -53,9 +54,9 @@ static int g2d_stamp_show(struct seq_file *s, void *unused) while (1) { stamp = &g2d_stamp_list[i]; - seq_printf(s, "[%d] %u:%u@%u (0x%x) %06llu\n", i++, + seq_printf(s, "[%4d] %u:%2u@%u (0x%2x) %6d %06llu\n", i++, stamp->cpu, stamp->job_id, stamp->val, stamp->state, - ktime_to_us(stamp->time)); + stamp->info, ktime_to_us(stamp->time)); i &= (G2D_MAX_STAMP_SIZE - 1); @@ -165,7 +166,7 @@ void g2d_dump_task(struct g2d_task *task) i, regs[i].offset, regs[i].value); } -void g2d_stamp_task(struct g2d_task *task, u32 val) +void g2d_stamp_task(struct g2d_task *task, u32 val, s32 info) { int ptr = atomic_inc_return(&p_stamp) & (G2D_MAX_STAMP_SIZE - 1); struct g2d_stamp *stamp = &g2d_stamp_list[ptr]; @@ -181,6 +182,7 @@ void g2d_stamp_task(struct g2d_task *task, u32 val) stamp->time = ktime_get(); stamp->val = val; stamp->cpu = smp_processor_id(); + stamp->info = info; /* when error status, dump the task */ if ((stamp->val == G2D_STAMP_STATE_TIMEOUT_HW) || @@ -190,8 +192,8 @@ void g2d_stamp_task(struct g2d_task *task, u32 val) if (stamp->val == G2D_STAMP_STATE_DONE) { if (g2d_debug == 1) { - pr_info("Job #%x took %06llu to H/W process\n", - task->job_id, ktime_us_delta(task->ktime_end, task->ktime_begin)); + pr_info("Job #%x took %06d to H/W process\n", + task->job_id, info); } else if (g2d_debug == 2) { g2d_dump_task(task); } diff --git a/drivers/gpu/exynos/g2d/g2d_debug.h b/drivers/gpu/exynos/g2d/g2d_debug.h index 7e3685ca1c8c..f4baee04981c 100644 --- a/drivers/gpu/exynos/g2d/g2d_debug.h +++ b/drivers/gpu/exynos/g2d/g2d_debug.h @@ -25,28 +25,24 @@ struct regs_info { }; enum g2d_stamp_id { - G2D_STAMP_STATE_ALLOC, + G2D_STAMP_STATE_RUNTIME_PM, + G2D_STAMP_STATE_TASK_RESOURCE, G2D_STAMP_STATE_BEGIN, - G2D_STAMP_STATE_PM_RESUME, G2D_STAMP_STATE_PUSH, + G2D_STAMP_STATE_INT, G2D_STAMP_STATE_DONE, - G2D_STAMP_STATE_PM_SUSPEND, - G2D_STAMP_STATE_FREE, G2D_STAMP_STATE_TIMEOUT_FENCE, G2D_STAMP_STATE_TIMEOUT_HW, G2D_STAMP_STATE_ERR_INT, G2D_STAMP_STATE_MMUFAULT, - G2D_STAMP_STATE_SHUTDOWN_S, - G2D_STAMP_STATE_SHUTDOWN_E, - G2D_STAMP_STATE_SUSPEND_S, - G2D_STAMP_STATE_SUSPEND_E, - G2D_STAMP_STATE_RESUME_S, - G2D_STAMP_STATE_RESUME_E, + G2D_STAMP_STATE_SHUTDOWN, + G2D_STAMP_STATE_SUSPEND, + G2D_STAMP_STATE_RESUME, G2D_STAMP_STATE_HWFCBUF, }; void g2d_init_debug(struct g2d_device *dev); void g2d_destroy_debug(struct g2d_device *dev); -void g2d_stamp_task(struct g2d_task *task, u32 val); +void g2d_stamp_task(struct g2d_task *task, u32 val, s32 info); void g2d_dump_task(struct g2d_task *task); #endif /* __EXYNOS_G2D_HELPER_H_ */ diff --git a/drivers/gpu/exynos/g2d/g2d_drv.c b/drivers/gpu/exynos/g2d/g2d_drv.c index 6b03d1bd3e77..fe8d334ec0e6 100644 --- a/drivers/gpu/exynos/g2d/g2d_drv.c +++ b/drivers/gpu/exynos/g2d/g2d_drv.c @@ -74,12 +74,15 @@ void g2d_hw_timeout_handler(unsigned long arg) unsigned long flags; u32 job_state; - /* TODO: Dump of internal state of G2D */ + spin_lock_irqsave(&g2d_dev->lock_task, flags); - dev_err(g2d_dev->dev, "%s: Time is up: %d msec for job %d\n", - __func__, G2D_HW_TIMEOUT_MSEC, task->job_id); + job_state = g2d_hw_get_job_state(g2d_dev, task->job_id); - spin_lock_irqsave(&g2d_dev->lock_task, flags); + g2d_stamp_task(task, G2D_STAMP_STATE_TIMEOUT_HW, job_state); + + dev_err(g2d_dev->dev, "%s: Time is up: %d msec for job %u %lu %u\n", + __func__, G2D_HW_TIMEOUT_MSEC, + task->job_id, task->state, job_state); if (!is_task_state_active(task)) /* @@ -88,7 +91,6 @@ void g2d_hw_timeout_handler(unsigned long arg) */ goto out; - job_state = g2d_hw_get_job_state(g2d_dev, task->job_id); if (job_state == G2D_JOB_STATE_DONE) /* * The task timed out is not currently running in H/W. @@ -116,8 +118,6 @@ void g2d_hw_timeout_handler(unsigned long arg) /* Time out is not caused by this task */ goto out; - g2d_stamp_task(task, G2D_STAMP_STATE_TIMEOUT_HW); - mark_task_state_killed(task); g2d_hw_kill_task(g2d_dev, task->job_id); @@ -130,7 +130,13 @@ int g2d_device_run(struct g2d_device *g2d_dev, struct g2d_task *task) { g2d_hw_push_task(g2d_dev, task); - g2d_stamp_task(task, G2D_STAMP_STATE_PUSH); + task->ktime_end = ktime_get(); + + /* record the time between user request and H/W push */ + g2d_stamp_task(task, G2D_STAMP_STATE_PUSH, + (int)ktime_us_delta(task->ktime_end, task->ktime_begin)); + + task->ktime_begin = ktime_get(); if (IS_HWFC(task->flags)) hwfc_set_valid_buffer(task->job_id, task->job_id); @@ -147,6 +153,9 @@ static irqreturn_t g2d_irq_handler(int irq, void *priv) spin_lock(&g2d_dev->lock_task); intflags = g2d_hw_finished_job_ids(g2d_dev); + + g2d_stamp_task(NULL, G2D_STAMP_STATE_INT, intflags); + if (intflags != 0) { for (id = 0; id < G2D_MAX_JOBS; id++) { if ((intflags & (1 << id)) == 0) @@ -164,19 +173,18 @@ static irqreturn_t g2d_irq_handler(int irq, void *priv) struct g2d_task *task = g2d_get_active_task_from_id(g2d_dev, job_id); - if (job_id < 0) { + if (job_id < 0) dev_err(g2d_dev->dev, "No task is running in HW\n"); - } else if (task == NULL) { + else if (task == NULL) dev_err(g2d_dev->dev, "%s: Current job %d in HW is not active\n", __func__, job_id); - } else { + else dev_err(g2d_dev->dev, "%s: Error occurred during running job %d\n", __func__, job_id); - g2d_stamp_task(task, G2D_STAMP_STATE_ERR_INT); - } + g2d_stamp_task(task, G2D_STAMP_STATE_ERR_INT, errstatus); g2d_flush_all_tasks(g2d_dev); @@ -206,7 +214,7 @@ static int g2d_iommu_fault_handler(struct iommu_domain *domain, task = g2d_get_active_task_from_id(g2d_dev, job_id); spin_unlock_irqrestore(&g2d_dev->lock_task, flags); - g2d_stamp_task(task, G2D_STAMP_STATE_MMUFAULT); + g2d_stamp_task(task, G2D_STAMP_STATE_MMUFAULT, 0); return 0; } @@ -373,7 +381,7 @@ static long g2d_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } - g2d_stamp_task(task, G2D_STAMP_STATE_BEGIN); + g2d_stamp_task(task, G2D_STAMP_STATE_BEGIN, task->priority); g2d_start_task(task); @@ -864,7 +872,7 @@ static void g2d_shutdown(struct platform_device *pdev) { struct g2d_device *g2d_dev = platform_get_drvdata(pdev); - g2d_stamp_task(NULL, G2D_STAMP_STATE_SHUTDOWN_S); + g2d_stamp_task(NULL, G2D_STAMP_STATE_SHUTDOWN, 0); g2d_prepare_suspend(g2d_dev); wait_event(g2d_dev->freeze_wait, list_empty(&g2d_dev->tasks_active)); @@ -872,7 +880,7 @@ static void g2d_shutdown(struct platform_device *pdev) if (test_and_set_bit(G2D_DEVICE_STATE_IOVMM_DISABLED, &g2d_dev->state)) iovmm_deactivate(g2d_dev->dev); - g2d_stamp_task(NULL, G2D_STAMP_STATE_SHUTDOWN_E); + g2d_stamp_task(NULL, G2D_STAMP_STATE_SHUTDOWN, 1); } static int g2d_remove(struct platform_device *pdev) @@ -896,7 +904,7 @@ static int g2d_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int g2d_runtime_resume(struct device *dev) { - g2d_stamp_task(NULL, G2D_STAMP_STATE_PM_RESUME); + g2d_stamp_task(NULL, G2D_STAMP_STATE_RUNTIME_PM, 0); return 0; } @@ -906,7 +914,7 @@ static int g2d_runtime_suspend(struct device *dev) struct g2d_device *g2d_dev = dev_get_drvdata(dev); clk_unprepare(g2d_dev->clock); - g2d_stamp_task(NULL, G2D_STAMP_STATE_PM_SUSPEND); + g2d_stamp_task(NULL, G2D_STAMP_STATE_RUNTIME_PM, 1); return 0; } diff --git a/drivers/gpu/exynos/g2d/g2d_fence.c b/drivers/gpu/exynos/g2d/g2d_fence.c index 5a7138b401b8..fd080451e770 100644 --- a/drivers/gpu/exynos/g2d/g2d_fence.c +++ b/drivers/gpu/exynos/g2d/g2d_fence.c @@ -33,6 +33,7 @@ void g2d_fence_timeout_handler(unsigned long arg) unsigned long flags; char name[32]; int i; + s32 afbc = 0; for (i = 0; i < task->num_source; i++) { fence = task->source[i].fence; @@ -106,7 +107,17 @@ void g2d_fence_timeout_handler(unsigned long arg) if (fence) dma_fence_remove_callback(fence, &task->target.fence_cb); - g2d_stamp_task(task, G2D_STAMP_STATE_TIMEOUT_FENCE); + /* check compressed buffer because crashed buffer makes recovery */ + for (i = 0; i < task->num_source; i++) { + if (IS_AFBC( + task->source[i].commands[G2DSFR_IMG_COLORMODE].value)) + afbc |= 1 << i; + } + + if (IS_AFBC(task->target.commands[G2DSFR_IMG_COLORMODE].value)) + afbc |= 1 << G2D_MAX_IMAGES; + + g2d_stamp_task(task, G2D_STAMP_STATE_TIMEOUT_FENCE, afbc); g2d_queuework_task(&task->starter); }; diff --git a/drivers/gpu/exynos/g2d/g2d_task.c b/drivers/gpu/exynos/g2d/g2d_task.c index 287eefd77ae6..98ea760194bd 100644 --- a/drivers/gpu/exynos/g2d/g2d_task.c +++ b/drivers/gpu/exynos/g2d/g2d_task.c @@ -123,7 +123,10 @@ static void g2d_finish_task(struct g2d_device *g2d_dev, { list_del_init(&task->node); - g2d_stamp_task(task, G2D_STAMP_STATE_DONE); + task->ktime_end = ktime_get(); + + g2d_stamp_task(task, G2D_STAMP_STATE_DONE, + (int)ktime_us_delta(task->ktime_end, task->ktime_begin)); del_timer(&task->timer); @@ -151,8 +154,6 @@ void g2d_finish_task_with_id(struct g2d_device *g2d_dev, success = false; } - task->ktime_end = ktime_get(); - g2d_finish_task(g2d_dev, task, success); } @@ -182,8 +183,6 @@ static void g2d_execute_task(struct g2d_device *g2d_dev, struct g2d_task *task) list_move_tail(&task->node, &g2d_dev->tasks_active); change_task_state_active(task); - task->ktime_begin = ktime_get(); - setup_timer(&task->timer, g2d_hw_timeout_handler, (unsigned long)task); @@ -207,9 +206,9 @@ void g2d_prepare_suspend(struct g2d_device *g2d_dev) set_bit(G2D_DEVICE_STATE_SUSPEND, &g2d_dev->state); spin_unlock_irq(&g2d_dev->lock_task); - g2d_stamp_task(NULL, G2D_STAMP_STATE_SUSPEND_S); + g2d_stamp_task(NULL, G2D_STAMP_STATE_SUSPEND, 0); wait_event(g2d_dev->freeze_wait, list_empty(&g2d_dev->tasks_active)); - g2d_stamp_task(NULL, G2D_STAMP_STATE_SUSPEND_E); + g2d_stamp_task(NULL, G2D_STAMP_STATE_SUSPEND, 1); } void g2d_suspend_finish(struct g2d_device *g2d_dev) @@ -218,7 +217,7 @@ void g2d_suspend_finish(struct g2d_device *g2d_dev) spin_lock_irq(&g2d_dev->lock_task); - g2d_stamp_task(NULL, G2D_STAMP_STATE_RESUME_S); + g2d_stamp_task(NULL, G2D_STAMP_STATE_RESUME, 0); clear_bit(G2D_DEVICE_STATE_SUSPEND, &g2d_dev->state); while (!list_empty(&g2d_dev->tasks_prepared)) { @@ -229,7 +228,7 @@ void g2d_suspend_finish(struct g2d_device *g2d_dev) } spin_unlock_irq(&g2d_dev->lock_task); - g2d_stamp_task(NULL, G2D_STAMP_STATE_RESUME_E); + g2d_stamp_task(NULL, G2D_STAMP_STATE_RESUME, 1); } static void g2d_schedule_task(struct g2d_task *task) @@ -306,6 +305,8 @@ void g2d_start_task(struct g2d_task *task) mod_timer(&task->timer, jiffies + msecs_to_jiffies(G2D_FENCE_TIMEOUT_MSEC)); + task->ktime_begin = ktime_get(); + kref_put(&task->starter, g2d_queuework_task); } @@ -348,7 +349,7 @@ struct g2d_task *g2d_get_free_task(struct g2d_device *g2d_dev, g2d_init_commands(task); - g2d_stamp_task(task, G2D_STAMP_STATE_ALLOC); + g2d_stamp_task(task, G2D_STAMP_STATE_TASK_RESOURCE, 0); spin_unlock_irqrestore(&g2d_dev->lock_task, flags); @@ -371,7 +372,7 @@ void g2d_put_free_task(struct g2d_device *g2d_dev, struct g2d_task *task) list_add(&task->node, &g2d_dev->tasks_free); } - g2d_stamp_task(task, G2D_STAMP_STATE_FREE); + g2d_stamp_task(task, G2D_STAMP_STATE_TASK_RESOURCE, 1); spin_unlock_irqrestore(&g2d_dev->lock_task, flags); } diff --git a/drivers/gpu/exynos/g2d/g2d_uapi_process.c b/drivers/gpu/exynos/g2d/g2d_uapi_process.c index f7b74ee46eaf..3e4f677ab229 100644 --- a/drivers/gpu/exynos/g2d/g2d_uapi_process.c +++ b/drivers/gpu/exynos/g2d/g2d_uapi_process.c @@ -691,6 +691,8 @@ static int g2d_get_target(struct g2d_device *g2d_dev, struct g2d_context *ctx, ptask = ptask->next; } + g2d_stamp_task(task, G2D_STAMP_STATE_HWFCBUF, idx); + task->job_id = idx; spin_unlock_irqrestore(&task->g2d_dev->lock_task, flags); @@ -698,8 +700,6 @@ static int g2d_get_target(struct g2d_device *g2d_dev, struct g2d_context *ctx, data->num_buffers = 1; data->buffer[0].dmabuf.offset = 0; data->buffer[0].length = ctx->hwfc_info->bufs[idx]->size; - - g2d_stamp_task(task, G2D_STAMP_STATE_HWFCBUF); } if (target->buffer_type == G2D_BUFTYPE_EMPTY) { -- 2.20.1