From 1cd9ac576c66bc52a7a0636c859d62fe96202cff Mon Sep 17 00:00:00 2001 From: "hyesoo.yu" Date: Wed, 1 Nov 2017 14:27:21 +0900 Subject: [PATCH] [COMMON] g2d: split the dump function In an abnormal state, there may not be any task to run even in mmu fault and error interrupt state, and this case might be accessed to NULL pointer on stamp function, so split the debugging message function from stamp function and print more information. Change-Id: Iadb1838c166cdfa3f4221a4ed30888734ba6303f Signed-off-by: hyesoo.yu --- drivers/gpu/exynos/g2d/g2d_debug.c | 52 ++++++++++++++++-------------- drivers/gpu/exynos/g2d/g2d_debug.h | 2 +- drivers/gpu/exynos/g2d/g2d_drv.c | 6 ++++ drivers/gpu/exynos/g2d/g2d_regs.c | 14 +++++++- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/exynos/g2d/g2d_debug.c b/drivers/gpu/exynos/g2d/g2d_debug.c index ff8bd8db7668..eab84c9597fe 100644 --- a/drivers/gpu/exynos/g2d/g2d_debug.c +++ b/drivers/gpu/exynos/g2d/g2d_debug.c @@ -145,9 +145,8 @@ static struct regs_info g2d_reg_info[] = { #define G2D_COMP_DEBUG_DATA_COUNT 16 -void g2d_dump_afbcdata(struct g2d_task *task) +void g2d_dump_afbcdata(struct g2d_device *g2d_dev) { - struct g2d_device *g2d_dev = task->g2d_dev; int i, cluster; u32 cfg; @@ -164,13 +163,12 @@ void g2d_dump_afbcdata(struct g2d_task *task) } } -void g2d_dump_task(struct g2d_task *task) +void g2d_dump_sfr(struct g2d_device *g2d_dev, struct g2d_task *task) { - struct g2d_device *g2d_dev = task->g2d_dev; unsigned int i, num_array; - struct g2d_reg *regs; - num_array = ARRAY_SIZE(g2d_reg_info) - G2D_MAX_IMAGES + task->num_source; + num_array = ARRAY_SIZE(g2d_reg_info) - G2D_MAX_IMAGES + + ((task) ? task->num_source : G2D_MAX_IMAGES); for (i = 0; i < num_array; i++) { pr_info("[%s: %04X .. %04X]\n", @@ -180,6 +178,15 @@ void g2d_dump_task(struct g2d_task *task) g2d_dev->reg + g2d_reg_info[i].start, g2d_reg_info[i].size, false); } +} + +void g2d_dump_cmd(struct g2d_task *task) +{ + unsigned int i; + struct g2d_reg *regs; + + if (!task) + return; regs = page_address(task->cmd_page); @@ -188,6 +195,17 @@ void g2d_dump_task(struct g2d_task *task) i, regs[i].offset, regs[i].value); } +/* + * If it happens error interrupts, mmu errors, and H/W timeouts, + * dump the SFR and job command list of task, AFBC debugging information + */ +void g2d_dump_info(struct g2d_device *g2d_dev, struct g2d_task *task) +{ + g2d_dump_cmd(task); + g2d_dump_sfr(g2d_dev, task); + g2d_dump_afbcdata(g2d_dev); +} + void g2d_stamp_task(struct g2d_task *task, u32 val, s32 info) { int ptr = atomic_inc_return(&p_stamp) & (G2D_MAX_STAMP_SIZE - 1); @@ -208,28 +226,12 @@ void g2d_stamp_task(struct g2d_task *task, u32 val, s32 info) stamp->cpu = smp_processor_id(); stamp->info = info; - /* - * If it happens error interrupts, mmu errors, and H/W timeouts, - * dump the SFR and job command list. However, debugging messages - * do not print in this case, that if the task is queued or suspended, - * or if the task has already been processed in the interrupt - * although H/W timeout happens. - */ - if ((stamp->val == G2D_STAMP_STATE_ERR_INT) || - (stamp->val == G2D_STAMP_STATE_MMUFAULT) || - ((stamp->val == G2D_STAMP_STATE_TIMEOUT_HW) && - ((stamp->info == G2D_JOB_STATE_RUNNING) || - is_task_state_active(task)))) { - g2d_dump_task(task); - g2d_dump_afbcdata(task); - } - - if (stamp->val == G2D_STAMP_STATE_DONE) { + if (task && (stamp->val == G2D_STAMP_STATE_DONE)) { if (g2d_debug == 1) { pr_info("Job #%x took %06d to H/W process\n", - task->job_id, info); + task->job_id, info); } else if (g2d_debug == 2) { - g2d_dump_task(task); + g2d_dump_info(task->g2d_dev, task); } } } diff --git a/drivers/gpu/exynos/g2d/g2d_debug.h b/drivers/gpu/exynos/g2d/g2d_debug.h index f4baee04981c..448328c2b6f5 100644 --- a/drivers/gpu/exynos/g2d/g2d_debug.h +++ b/drivers/gpu/exynos/g2d/g2d_debug.h @@ -44,5 +44,5 @@ enum g2d_stamp_id { 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, s32 info); -void g2d_dump_task(struct g2d_task *task); +void g2d_dump_info(struct g2d_device *g2d_dev, 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 fe8d334ec0e6..45afe0c19647 100644 --- a/drivers/gpu/exynos/g2d/g2d_drv.c +++ b/drivers/gpu/exynos/g2d/g2d_drv.c @@ -118,6 +118,8 @@ void g2d_hw_timeout_handler(unsigned long arg) /* Time out is not caused by this task */ goto out; + g2d_dump_info(g2d_dev, task); + mark_task_state_killed(task); g2d_hw_kill_task(g2d_dev, task->job_id); @@ -186,6 +188,8 @@ static irqreturn_t g2d_irq_handler(int irq, void *priv) g2d_stamp_task(task, G2D_STAMP_STATE_ERR_INT, errstatus); + g2d_dump_info(g2d_dev, task); + g2d_flush_all_tasks(g2d_dev); g2d_hw_global_reset(g2d_dev); @@ -214,6 +218,8 @@ 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_dump_info(g2d_dev, task); + g2d_stamp_task(task, G2D_STAMP_STATE_MMUFAULT, 0); return 0; diff --git a/drivers/gpu/exynos/g2d/g2d_regs.c b/drivers/gpu/exynos/g2d/g2d_regs.c index e943fa57e0df..1d1b35c4f159 100644 --- a/drivers/gpu/exynos/g2d/g2d_regs.c +++ b/drivers/gpu/exynos/g2d/g2d_regs.c @@ -60,7 +60,7 @@ void g2d_hw_push_task(struct g2d_device *g2d_dev, struct g2d_task *task) __func__, sec_task.cmd_count, sec_task.priority, sec_task.job_id, sec_task.secure_layer); - g2d_dump_task(task); + g2d_dump_info(g2d_dev, task); BUG(); } } @@ -118,6 +118,12 @@ u32 g2d_hw_errint_status(struct g2d_device *g2d_dev) return status; } +/* + * This is called when H/W is judged to be in operation, + * for example, when a sysmmu fault and an error interrupt occurs. + * If there is no task in progress, the status of all task on H/W + * is taken and print for debugging + */ int g2d_hw_get_current_task(struct g2d_device *g2d_dev) { int i, val; @@ -128,6 +134,12 @@ int g2d_hw_get_current_task(struct g2d_device *g2d_dev) return i; } + for (i = 0; i < G2D_MAX_JOBS; i++) { + val = readl_relaxed(g2d_dev->reg + G2D_JOB_IDn_STATE_REG(i)); + dev_err(g2d_dev->dev, + "G2D TASK[%03d] STATE : %d\n", i, val); + } + return -1; } -- 2.20.1