g2d: add debugfs node of details of open contexts
authorCho KyongHo <pullip.cho@samsung.com>
Thu, 30 Nov 2017 15:30:44 +0000 (00:30 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:28:07 +0000 (14:28 +0900)
Change-Id: Ic9cf4c397cbc2815223a536c0a1e125a22737210
Signed-off-by: Cho KyongHo <pullip.cho@samsung.com>
drivers/gpu/exynos/g2d/g2d.h
drivers/gpu/exynos/g2d/g2d_debug.c
drivers/gpu/exynos/g2d/g2d_drv.c

index c7546cdd0293f02d4d32bbaaca0575c420c7b164..a764b1dbb6ee40f650aeff57fca02987f0296aee 100644 (file)
@@ -90,6 +90,9 @@ struct g2d_device {
        atomic_t                fence_timeline;
        spinlock_t              fence_lock;
 
+       spinlock_t              lock_ctx_list;
+       struct list_head        ctx_list;
+
        /* task management */
        spinlock_t              lock_task;
        struct g2d_task         *tasks;
@@ -105,6 +108,7 @@ struct g2d_device {
        struct dentry *debug_root;
        struct dentry *debug;
        struct dentry *debug_logs;
+       struct dentry *debug_contexts;
 
        atomic_t        prior_stats[G2D_PRIORITY_END];
 
@@ -119,10 +123,12 @@ struct g2d_device {
 #define G2D_AUTHORITY_HIGHUSER 1
 
 struct g2d_context {
+       struct list_head        node;
        struct g2d_device       *g2d_dev;
        struct shared_buffer_info *hwfc_info;
        u32 priority;
        int authority;
+       struct task_struct      *owner;
 
        struct delayed_work dwork;
 
index 9f662e49d677860cc629038efe1affa880e5b0d4..5703c14b5fcfbffb9e8e61053c0fa044d5807f00 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/debugfs.h>
+#include <linux/sched/task.h>
 
 #include "g2d.h"
 #include "g2d_task.h"
@@ -80,6 +81,56 @@ static const struct file_operations g2d_debug_logs_fops = {
        .release = single_release,
 };
 
+static int g2d_debug_contexts_show(struct seq_file *s, void *unused)
+{
+       struct g2d_device *g2d_dev = s->private;
+       struct g2d_context *ctx;
+
+       seq_printf(s, "%16s %6s %4s %6s %10s %10s\n",
+               "task", "pid", "prio", "dev", "read_bw", "write_bw");
+       seq_puts(s, "------------------------------------------------------\n");
+
+       spin_lock(&g2d_dev->lock_ctx_list);
+
+       list_for_each_entry(ctx, &g2d_dev->ctx_list, node) {
+               task_lock(ctx->owner);
+               seq_printf(s, "%16s %6u %4d %6s %10llu %10llu\n",
+                       ctx->owner->comm, ctx->owner->pid, ctx->priority,
+                       g2d_dev->misc[(ctx->authority + 1) & 1].name,
+                       ctx->r_bw, ctx->w_bw);
+
+               task_unlock(ctx->owner);
+       }
+
+       spin_unlock(&g2d_dev->lock_ctx_list);
+
+       seq_puts(s, "------------------------------------------------------\n");
+
+       seq_puts(s, "priorities:\n");
+       seq_printf(s, "\tlow(0)    : %d\n",
+                  atomic_read(&g2d_dev->prior_stats[G2D_LOW_PRIORITY]));
+       seq_printf(s, "\tmedium(1) : %d\n",
+                  atomic_read(&g2d_dev->prior_stats[G2D_MEDIUM_PRIORITY]));
+       seq_printf(s, "\thigh(2)   : %d\n",
+                  atomic_read(&g2d_dev->prior_stats[G2D_HIGH_PRIORITY]));
+       seq_printf(s, "\thighest(3): %d\n",
+                  atomic_read(&g2d_dev->prior_stats[G2D_HIGHEST_PRIORITY]));
+
+       return 0;
+}
+
+static int g2d_debug_contexts_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, g2d_debug_contexts_show, inode->i_private);
+}
+
+static const struct file_operations g2d_debug_contexts_fops = {
+       .open = g2d_debug_contexts_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
 void g2d_init_debug(struct g2d_device *g2d_dev)
 {
        atomic_set(&p_stamp, -1);
@@ -103,6 +154,15 @@ void g2d_init_debug(struct g2d_device *g2d_dev)
                dev_err(g2d_dev->dev, "debugfs : failed to create debug logs file\n");
                return;
        }
+
+       g2d_dev->debug_contexts = debugfs_create_file("contexts",
+                                       0400, g2d_dev->debug_root, g2d_dev,
+                                       &g2d_debug_contexts_fops);
+       if (!g2d_dev->debug_logs) {
+               dev_err(g2d_dev->dev,
+                       "debugfs : failed to create debug contexts file\n");
+               return;
+       }
 }
 
 void g2d_destroy_debug(struct g2d_device *g2d_dev)
index 1376b43a4b9d1ab29265eb430196f8352f30a674..a4ec50458168abf0f66f0bbb7fee2522127a0cf8 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/compat.h>
+#include <linux/sched/task.h>
 
 #include "g2d.h"
 #include "g2d_regs.h"
@@ -282,6 +283,13 @@ static int g2d_open(struct inode *inode, struct file *filp)
        g2d_ctx->priority = G2D_DEFAULT_PRIORITY;
        atomic_inc(&g2d_dev->prior_stats[g2d_ctx->priority]);
 
+       get_task_struct(current->group_leader);
+       g2d_ctx->owner = current->group_leader;
+
+       spin_lock(&g2d_dev->lock_ctx_list);
+       list_add(&g2d_ctx->node, &g2d_dev->ctx_list);
+       spin_unlock(&g2d_dev->lock_ctx_list);
+
        INIT_LIST_HEAD(&g2d_ctx->qos_node);
        INIT_DELAYED_WORK(&(g2d_ctx->dwork), g2d_timeout_perf_work);
 
@@ -305,6 +313,12 @@ static int g2d_release(struct inode *inode, struct file *filp)
 
        g2d_put_performance(g2d_ctx, true);
 
+       spin_lock(&g2d_dev->lock_ctx_list);
+       list_del(&g2d_ctx->node);
+       spin_unlock(&g2d_dev->lock_ctx_list);
+
+       put_task_struct(g2d_ctx->owner);
+
        kfree(g2d_ctx);
 
        return 0;
@@ -866,12 +880,14 @@ static int g2d_probe(struct platform_device *pdev)
        }
 
        spin_lock_init(&g2d_dev->lock_task);
+       spin_lock_init(&g2d_dev->lock_ctx_list);
 
        INIT_LIST_HEAD(&g2d_dev->tasks_free);
        INIT_LIST_HEAD(&g2d_dev->tasks_free_hwfc);
        INIT_LIST_HEAD(&g2d_dev->tasks_prepared);
        INIT_LIST_HEAD(&g2d_dev->tasks_active);
        INIT_LIST_HEAD(&g2d_dev->qos_contexts);
+       INIT_LIST_HEAD(&g2d_dev->ctx_list);
 
        mutex_init(&g2d_dev->lock_qos);