From 0675311f4167b662f9dd1bc851f63be80319de39 Mon Sep 17 00:00:00 2001 From: Cho KyongHo Date: Fri, 1 Dec 2017 00:30:44 +0900 Subject: [PATCH] g2d: add debugfs node of details of open contexts Change-Id: Ic9cf4c397cbc2815223a536c0a1e125a22737210 Signed-off-by: Cho KyongHo --- drivers/gpu/exynos/g2d/g2d.h | 6 +++ drivers/gpu/exynos/g2d/g2d_debug.c | 60 ++++++++++++++++++++++++++++++ drivers/gpu/exynos/g2d/g2d_drv.c | 16 ++++++++ 3 files changed, 82 insertions(+) diff --git a/drivers/gpu/exynos/g2d/g2d.h b/drivers/gpu/exynos/g2d/g2d.h index c7546cdd0293..a764b1dbb6ee 100644 --- a/drivers/gpu/exynos/g2d/g2d.h +++ b/drivers/gpu/exynos/g2d/g2d.h @@ -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; diff --git a/drivers/gpu/exynos/g2d/g2d_debug.c b/drivers/gpu/exynos/g2d/g2d_debug.c index 9f662e49d677..5703c14b5fcf 100644 --- a/drivers/gpu/exynos/g2d/g2d_debug.c +++ b/drivers/gpu/exynos/g2d/g2d_debug.c @@ -16,6 +16,7 @@ #include #include #include +#include #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) diff --git a/drivers/gpu/exynos/g2d/g2d_drv.c b/drivers/gpu/exynos/g2d/g2d_drv.c index 1376b43a4b9d..a4ec50458168 100644 --- a/drivers/gpu/exynos/g2d/g2d_drv.c +++ b/drivers/gpu/exynos/g2d/g2d_drv.c @@ -25,6 +25,7 @@ #include #include #include +#include #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); -- 2.20.1