[COMMON] g2d: split the dump function
authorhyesoo.yu <hyesoo.yu@samsung.com>
Wed, 1 Nov 2017 05:27:21 +0000 (14:27 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:27:53 +0000 (14:27 +0900)
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 <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_regs.c

index ff8bd8db76684f53178d0a437498c3db7fde1664..eab84c9597feb3466b14a5d6cc7edd244cc2ea6b 100644 (file)
@@ -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);
                }
        }
 }
index f4baee04981cee14dd28a0bb2669e7900689157e..448328c2b6f5317dc7440a46afd311f2f85d215c 100644 (file)
@@ -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_ */
index fe8d334ec0e629057f91b7aecf2e3418e4c3a452..45afe0c1964789750b49f237280e19ee25ec222f 100644 (file)
@@ -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;
index e943fa57e0df7731963b129ca604d03b1d6f9d18..1d1b35c4f159398092812fe47970aa0d705328e7 100644 (file)
@@ -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;
 }