linux/drivers/gpu/drm/msm/msm_debugfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2013-2016 Red Hat
   4 * Author: Rob Clark <robdclark@gmail.com>
   5 */
   6
   7#ifdef CONFIG_DEBUG_FS
   8
   9#include <linux/debugfs.h>
  10
  11#include <drm/drm_debugfs.h>
  12#include <drm/drm_file.h>
  13
  14#include "msm_drv.h"
  15#include "msm_gpu.h"
  16#include "msm_kms.h"
  17#include "msm_debugfs.h"
  18
  19struct msm_gpu_show_priv {
  20        struct msm_gpu_state *state;
  21        struct drm_device *dev;
  22};
  23
  24static int msm_gpu_show(struct seq_file *m, void *arg)
  25{
  26        struct drm_printer p = drm_seq_file_printer(m);
  27        struct msm_gpu_show_priv *show_priv = m->private;
  28        struct msm_drm_private *priv = show_priv->dev->dev_private;
  29        struct msm_gpu *gpu = priv->gpu;
  30        int ret;
  31
  32        ret = mutex_lock_interruptible(&show_priv->dev->struct_mutex);
  33        if (ret)
  34                return ret;
  35
  36        drm_printf(&p, "%s Status:\n", gpu->name);
  37        gpu->funcs->show(gpu, show_priv->state, &p);
  38
  39        mutex_unlock(&show_priv->dev->struct_mutex);
  40
  41        return 0;
  42}
  43
  44static int msm_gpu_release(struct inode *inode, struct file *file)
  45{
  46        struct seq_file *m = file->private_data;
  47        struct msm_gpu_show_priv *show_priv = m->private;
  48        struct msm_drm_private *priv = show_priv->dev->dev_private;
  49        struct msm_gpu *gpu = priv->gpu;
  50
  51        mutex_lock(&show_priv->dev->struct_mutex);
  52        gpu->funcs->gpu_state_put(show_priv->state);
  53        mutex_unlock(&show_priv->dev->struct_mutex);
  54
  55        kfree(show_priv);
  56
  57        return single_release(inode, file);
  58}
  59
  60static int msm_gpu_open(struct inode *inode, struct file *file)
  61{
  62        struct drm_device *dev = inode->i_private;
  63        struct msm_drm_private *priv = dev->dev_private;
  64        struct msm_gpu *gpu = priv->gpu;
  65        struct msm_gpu_show_priv *show_priv;
  66        int ret;
  67
  68        if (!gpu || !gpu->funcs->gpu_state_get)
  69                return -ENODEV;
  70
  71        show_priv = kmalloc(sizeof(*show_priv), GFP_KERNEL);
  72        if (!show_priv)
  73                return -ENOMEM;
  74
  75        ret = mutex_lock_interruptible(&dev->struct_mutex);
  76        if (ret)
  77                goto free_priv;
  78
  79        pm_runtime_get_sync(&gpu->pdev->dev);
  80        show_priv->state = gpu->funcs->gpu_state_get(gpu);
  81        pm_runtime_put_sync(&gpu->pdev->dev);
  82
  83        mutex_unlock(&dev->struct_mutex);
  84
  85        if (IS_ERR(show_priv->state)) {
  86                ret = PTR_ERR(show_priv->state);
  87                goto free_priv;
  88        }
  89
  90        show_priv->dev = dev;
  91
  92        ret = single_open(file, msm_gpu_show, show_priv);
  93        if (ret)
  94                goto free_priv;
  95
  96        return 0;
  97
  98free_priv:
  99        kfree(show_priv);
 100        return ret;
 101}
 102
 103static const struct file_operations msm_gpu_fops = {
 104        .owner = THIS_MODULE,
 105        .open = msm_gpu_open,
 106        .read = seq_read,
 107        .llseek = seq_lseek,
 108        .release = msm_gpu_release,
 109};
 110
 111static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
 112{
 113        struct msm_drm_private *priv = dev->dev_private;
 114        struct msm_gpu *gpu = priv->gpu;
 115
 116        if (gpu) {
 117                seq_printf(m, "Active Objects (%s):\n", gpu->name);
 118                msm_gem_describe_objects(&gpu->active_list, m);
 119        }
 120
 121        seq_printf(m, "Inactive Objects:\n");
 122        msm_gem_describe_objects(&priv->inactive_list, m);
 123
 124        return 0;
 125}
 126
 127static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
 128{
 129        struct drm_printer p = drm_seq_file_printer(m);
 130
 131        drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p);
 132
 133        return 0;
 134}
 135
 136static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
 137{
 138        struct msm_drm_private *priv = dev->dev_private;
 139        struct drm_framebuffer *fb, *fbdev_fb = NULL;
 140
 141        if (priv->fbdev) {
 142                seq_printf(m, "fbcon ");
 143                fbdev_fb = priv->fbdev->fb;
 144                msm_framebuffer_describe(fbdev_fb, m);
 145        }
 146
 147        mutex_lock(&dev->mode_config.fb_lock);
 148        list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 149                if (fb == fbdev_fb)
 150                        continue;
 151
 152                seq_printf(m, "user ");
 153                msm_framebuffer_describe(fb, m);
 154        }
 155        mutex_unlock(&dev->mode_config.fb_lock);
 156
 157        return 0;
 158}
 159
 160static int show_locked(struct seq_file *m, void *arg)
 161{
 162        struct drm_info_node *node = (struct drm_info_node *) m->private;
 163        struct drm_device *dev = node->minor->dev;
 164        int (*show)(struct drm_device *dev, struct seq_file *m) =
 165                        node->info_ent->data;
 166        int ret;
 167
 168        ret = mutex_lock_interruptible(&dev->struct_mutex);
 169        if (ret)
 170                return ret;
 171
 172        ret = show(dev, m);
 173
 174        mutex_unlock(&dev->struct_mutex);
 175
 176        return ret;
 177}
 178
 179static struct drm_info_list msm_debugfs_list[] = {
 180                {"gem", show_locked, 0, msm_gem_show},
 181                { "mm", show_locked, 0, msm_mm_show },
 182                { "fb", show_locked, 0, msm_fb_show },
 183};
 184
 185static int late_init_minor(struct drm_minor *minor)
 186{
 187        int ret;
 188
 189        if (!minor)
 190                return 0;
 191
 192        ret = msm_rd_debugfs_init(minor);
 193        if (ret) {
 194                DRM_DEV_ERROR(minor->dev->dev, "could not install rd debugfs\n");
 195                return ret;
 196        }
 197
 198        ret = msm_perf_debugfs_init(minor);
 199        if (ret) {
 200                DRM_DEV_ERROR(minor->dev->dev, "could not install perf debugfs\n");
 201                return ret;
 202        }
 203
 204        return 0;
 205}
 206
 207int msm_debugfs_late_init(struct drm_device *dev)
 208{
 209        int ret;
 210        ret = late_init_minor(dev->primary);
 211        if (ret)
 212                return ret;
 213        ret = late_init_minor(dev->render);
 214        return ret;
 215}
 216
 217void msm_debugfs_init(struct drm_minor *minor)
 218{
 219        struct drm_device *dev = minor->dev;
 220        struct msm_drm_private *priv = dev->dev_private;
 221
 222        drm_debugfs_create_files(msm_debugfs_list,
 223                                 ARRAY_SIZE(msm_debugfs_list),
 224                                 minor->debugfs_root, minor);
 225
 226        debugfs_create_file("gpu", S_IRUSR, minor->debugfs_root,
 227                dev, &msm_gpu_fops);
 228
 229        if (priv->kms && priv->kms->funcs->debugfs_init)
 230                priv->kms->funcs->debugfs_init(priv->kms, minor);
 231}
 232#endif
 233
 234