[COMMON] g2d: add extra information for debug
authorhyesoo.yu <hyesoo.yu@samsung.com>
Mon, 25 Sep 2017 00:12:30 +0000 (09:12 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:14 +0000 (20:22 +0300)
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 <hyesoo.yu@samsung.com>
drivers/gpu/exynos/g2d/g2d_debug.c
drivers/gpu/exynos/g2d/g2d_debug.h
drivers/gpu/exynos/g2d/g2d_drv.c
drivers/gpu/exynos/g2d/g2d_fence.c
drivers/gpu/exynos/g2d/g2d_task.c
drivers/gpu/exynos/g2d/g2d_uapi_process.c

index db33fd581d52a4277855cff52157d97e1c29c5e5..2e4099b11d75b5764674c0b0f816c801db4d166b 100644 (file)
@@ -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);
                }
index 7e3685ca1c8ce181d7b25cfa72dd241abbee2f20..f4baee04981cee14dd28a0bb2669e7900689157e 100644 (file)
@@ -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_ */
index 6b03d1bd3e77442499b2941fd5e9abd76769ba45..fe8d334ec0e629057f91b7aecf2e3418e4c3a452 100644 (file)
@@ -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;
 }
index 5a7138b401b8bcf6cbbf2e289bc9048178dac652..fd080451e77013e882ef4ac5610b64c036787adc 100644 (file)
@@ -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);
 };
index 287eefd77ae694591cf9e4283597d715c1832929..98ea760194bd37222ef011feeae2ba0b910eb321 100644 (file)
@@ -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);
 }
index f7b74ee46eaf45b4ef020c11807e956b5129447c..3e4f677ab2291659dc666a75e688016ba4964dc4 100644 (file)
@@ -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) {