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        int ret;
 116
 117        ret = mutex_lock_interruptible(&priv->mm_lock);
 118        if (ret)
 119                return ret;
 120
 121        if (gpu) {
 122                seq_printf(m, "Active Objects (%s):\n", gpu->name);
 123                msm_gem_describe_objects(&gpu->active_list, m);
 124        }
 125
 126        seq_printf(m, "Inactive Objects:\n");
 127        msm_gem_describe_objects(&priv->inactive_dontneed, m);
 128        msm_gem_describe_objects(&priv->inactive_willneed, m);
 129
 130        mutex_unlock(&priv->mm_lock);
 131
 132        return 0;
 133}
 134
 135static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
 136{
 137        struct drm_printer p = drm_seq_file_printer(m);
 138
 139        drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p);
 140
 141        return 0;
 142}
 143
 144static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
 145{
 146        struct msm_drm_private *priv = dev->dev_private;
 147        struct drm_framebuffer *fb, *fbdev_fb = NULL;
 148
 149        if (priv->fbdev) {
 150                seq_printf(m, "fbcon ");
 151                fbdev_fb = priv->fbdev->fb;
 152                msm_framebuffer_describe(fbdev_fb, m);
 153        }
 154
 155        mutex_lock(&dev->mode_config.fb_lock);
 156        list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 157                if (fb == fbdev_fb)
 158                        continue;
 159
 160                seq_printf(m, "user ");
 161                msm_framebuffer_describe(fb, m);
 162        }
 163        mutex_unlock(&dev->mode_config.fb_lock);
 164
 165        return 0;
 166}
 167
 168static int show_locked(struct seq_file *m, void *arg)
 169{
 170        struct drm_info_node *node = (struct drm_info_node *) m->private;
 171        struct drm_device *dev = node->minor->dev;
 172        int (*show)(struct drm_device *dev, struct seq_file *m) =
 173                        node->info_ent->data;
 174        int ret;
 175
 176        ret = mutex_lock_interruptible(&dev->struct_mutex);
 177        if (ret)
 178                return ret;
 179
 180        ret = show(dev, m);
 181
 182        mutex_unlock(&dev->struct_mutex);
 183
 184        return ret;
 185}
 186
 187static struct drm_info_list msm_debugfs_list[] = {
 188                {"gem", show_locked, 0, msm_gem_show},
 189                { "mm", show_locked, 0, msm_mm_show },
 190                { "fb", show_locked, 0, msm_fb_show },
 191};
 192
 193static int late_init_minor(struct drm_minor *minor)
 194{
 195        int ret;
 196
 197        if (!minor)
 198                return 0;
 199
 200        ret = msm_rd_debugfs_init(minor);
 201        if (ret) {
 202                DRM_DEV_ERROR(minor->dev->dev, "could not install rd debugfs\n");
 203                return ret;
 204        }
 205
 206        ret = msm_perf_debugfs_init(minor);
 207        if (ret) {
 208                DRM_DEV_ERROR(minor->dev->dev, "could not install perf debugfs\n");
 209                return ret;
 210        }
 211
 212        return 0;
 213}
 214
 215int msm_debugfs_late_init(struct drm_device *dev)
 216{
 217        int ret;
 218        ret = late_init_minor(dev->primary);
 219        if (ret)
 220                return ret;
 221        ret = late_init_minor(dev->render);
 222        return ret;
 223}
 224
 225void msm_debugfs_init(struct drm_minor *minor)
 226{
 227        struct drm_device *dev = minor->dev;
 228        struct msm_drm_private *priv = dev->dev_private;
 229
 230        drm_debugfs_create_files(msm_debugfs_list,
 231                                 ARRAY_SIZE(msm_debugfs_list),
 232                                 minor->debugfs_root, minor);
 233
 234        debugfs_create_file("gpu", S_IRUSR, minor->debugfs_root,
 235                dev, &msm_gpu_fops);
 236
 237        if (priv->kms && priv->kms->funcs->debugfs_init)
 238                priv->kms->funcs->debugfs_init(priv->kms, minor);
 239}
 240#endif
 241
 242