Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2013-2016 Red Hat
0004  * Author: Rob Clark <robdclark@gmail.com>
0005  */
0006 
0007 #ifdef CONFIG_DEBUG_FS
0008 
0009 #include <linux/debugfs.h>
0010 
0011 #include <drm/drm_debugfs.h>
0012 #include <drm/drm_file.h>
0013 #include <drm/drm_framebuffer.h>
0014 
0015 #include "msm_drv.h"
0016 #include "msm_gpu.h"
0017 #include "msm_kms.h"
0018 #include "msm_debugfs.h"
0019 #include "disp/msm_disp_snapshot.h"
0020 
0021 /*
0022  * GPU Snapshot:
0023  */
0024 
0025 struct msm_gpu_show_priv {
0026     struct msm_gpu_state *state;
0027     struct drm_device *dev;
0028 };
0029 
0030 static int msm_gpu_show(struct seq_file *m, void *arg)
0031 {
0032     struct drm_printer p = drm_seq_file_printer(m);
0033     struct msm_gpu_show_priv *show_priv = m->private;
0034     struct msm_drm_private *priv = show_priv->dev->dev_private;
0035     struct msm_gpu *gpu = priv->gpu;
0036     int ret;
0037 
0038     ret = mutex_lock_interruptible(&gpu->lock);
0039     if (ret)
0040         return ret;
0041 
0042     drm_printf(&p, "%s Status:\n", gpu->name);
0043     gpu->funcs->show(gpu, show_priv->state, &p);
0044 
0045     mutex_unlock(&gpu->lock);
0046 
0047     return 0;
0048 }
0049 
0050 static int msm_gpu_release(struct inode *inode, struct file *file)
0051 {
0052     struct seq_file *m = file->private_data;
0053     struct msm_gpu_show_priv *show_priv = m->private;
0054     struct msm_drm_private *priv = show_priv->dev->dev_private;
0055     struct msm_gpu *gpu = priv->gpu;
0056 
0057     mutex_lock(&gpu->lock);
0058     gpu->funcs->gpu_state_put(show_priv->state);
0059     mutex_unlock(&gpu->lock);
0060 
0061     kfree(show_priv);
0062 
0063     return single_release(inode, file);
0064 }
0065 
0066 static int msm_gpu_open(struct inode *inode, struct file *file)
0067 {
0068     struct drm_device *dev = inode->i_private;
0069     struct msm_drm_private *priv = dev->dev_private;
0070     struct msm_gpu *gpu = priv->gpu;
0071     struct msm_gpu_show_priv *show_priv;
0072     int ret;
0073 
0074     if (!gpu || !gpu->funcs->gpu_state_get)
0075         return -ENODEV;
0076 
0077     show_priv = kmalloc(sizeof(*show_priv), GFP_KERNEL);
0078     if (!show_priv)
0079         return -ENOMEM;
0080 
0081     ret = mutex_lock_interruptible(&gpu->lock);
0082     if (ret)
0083         goto free_priv;
0084 
0085     pm_runtime_get_sync(&gpu->pdev->dev);
0086     msm_gpu_hw_init(gpu);
0087     show_priv->state = gpu->funcs->gpu_state_get(gpu);
0088     pm_runtime_put_sync(&gpu->pdev->dev);
0089 
0090     mutex_unlock(&gpu->lock);
0091 
0092     if (IS_ERR(show_priv->state)) {
0093         ret = PTR_ERR(show_priv->state);
0094         goto free_priv;
0095     }
0096 
0097     show_priv->dev = dev;
0098 
0099     ret = single_open(file, msm_gpu_show, show_priv);
0100     if (ret)
0101         goto free_priv;
0102 
0103     return 0;
0104 
0105 free_priv:
0106     kfree(show_priv);
0107     return ret;
0108 }
0109 
0110 static const struct file_operations msm_gpu_fops = {
0111     .owner = THIS_MODULE,
0112     .open = msm_gpu_open,
0113     .read = seq_read,
0114     .llseek = seq_lseek,
0115     .release = msm_gpu_release,
0116 };
0117 
0118 /*
0119  * Display Snapshot:
0120  */
0121 
0122 static int msm_kms_show(struct seq_file *m, void *arg)
0123 {
0124     struct drm_printer p = drm_seq_file_printer(m);
0125     struct msm_disp_state *state = m->private;
0126 
0127     msm_disp_state_print(state, &p);
0128 
0129     return 0;
0130 }
0131 
0132 static int msm_kms_release(struct inode *inode, struct file *file)
0133 {
0134     struct seq_file *m = file->private_data;
0135     struct msm_disp_state *state = m->private;
0136 
0137     msm_disp_state_free(state);
0138 
0139     return single_release(inode, file);
0140 }
0141 
0142 static int msm_kms_open(struct inode *inode, struct file *file)
0143 {
0144     struct drm_device *dev = inode->i_private;
0145     struct msm_drm_private *priv = dev->dev_private;
0146     struct msm_disp_state *state;
0147     int ret;
0148 
0149     if (!priv->kms)
0150         return -ENODEV;
0151 
0152     ret = mutex_lock_interruptible(&priv->kms->dump_mutex);
0153     if (ret)
0154         return ret;
0155 
0156     state = msm_disp_snapshot_state_sync(priv->kms);
0157 
0158     mutex_unlock(&priv->kms->dump_mutex);
0159 
0160     if (IS_ERR(state)) {
0161         return PTR_ERR(state);
0162     }
0163 
0164     ret = single_open(file, msm_kms_show, state);
0165     if (ret) {
0166         msm_disp_state_free(state);
0167         return ret;
0168     }
0169 
0170     return 0;
0171 }
0172 
0173 static const struct file_operations msm_kms_fops = {
0174     .owner = THIS_MODULE,
0175     .open = msm_kms_open,
0176     .read = seq_read,
0177     .llseek = seq_lseek,
0178     .release = msm_kms_release,
0179 };
0180 
0181 /*
0182  * Other debugfs:
0183  */
0184 
0185 static unsigned long last_shrink_freed;
0186 
0187 static int
0188 shrink_get(void *data, u64 *val)
0189 {
0190     *val = last_shrink_freed;
0191 
0192     return 0;
0193 }
0194 
0195 static int
0196 shrink_set(void *data, u64 val)
0197 {
0198     struct drm_device *dev = data;
0199 
0200     last_shrink_freed = msm_gem_shrinker_shrink(dev, val);
0201 
0202     return 0;
0203 }
0204 
0205 DEFINE_DEBUGFS_ATTRIBUTE(shrink_fops,
0206              shrink_get, shrink_set,
0207              "0x%08llx\n");
0208 
0209 
0210 static int msm_gem_show(struct seq_file *m, void *arg)
0211 {
0212     struct drm_info_node *node = (struct drm_info_node *) m->private;
0213     struct drm_device *dev = node->minor->dev;
0214     struct msm_drm_private *priv = dev->dev_private;
0215     int ret;
0216 
0217     ret = mutex_lock_interruptible(&priv->obj_lock);
0218     if (ret)
0219         return ret;
0220 
0221     msm_gem_describe_objects(&priv->objects, m);
0222 
0223     mutex_unlock(&priv->obj_lock);
0224 
0225     return 0;
0226 }
0227 
0228 static int msm_mm_show(struct seq_file *m, void *arg)
0229 {
0230     struct drm_info_node *node = (struct drm_info_node *) m->private;
0231     struct drm_device *dev = node->minor->dev;
0232     struct drm_printer p = drm_seq_file_printer(m);
0233 
0234     drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p);
0235 
0236     return 0;
0237 }
0238 
0239 static int msm_fb_show(struct seq_file *m, void *arg)
0240 {
0241     struct drm_info_node *node = (struct drm_info_node *) m->private;
0242     struct drm_device *dev = node->minor->dev;
0243     struct msm_drm_private *priv = dev->dev_private;
0244     struct drm_framebuffer *fb, *fbdev_fb = NULL;
0245 
0246     if (priv->fbdev) {
0247         seq_printf(m, "fbcon ");
0248         fbdev_fb = priv->fbdev->fb;
0249         msm_framebuffer_describe(fbdev_fb, m);
0250     }
0251 
0252     mutex_lock(&dev->mode_config.fb_lock);
0253     list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
0254         if (fb == fbdev_fb)
0255             continue;
0256 
0257         seq_printf(m, "user ");
0258         msm_framebuffer_describe(fb, m);
0259     }
0260     mutex_unlock(&dev->mode_config.fb_lock);
0261 
0262     return 0;
0263 }
0264 
0265 static struct drm_info_list msm_debugfs_list[] = {
0266         {"gem", msm_gem_show},
0267         { "mm", msm_mm_show },
0268         { "fb", msm_fb_show },
0269 };
0270 
0271 static int late_init_minor(struct drm_minor *minor)
0272 {
0273     int ret;
0274 
0275     if (!minor)
0276         return 0;
0277 
0278     ret = msm_rd_debugfs_init(minor);
0279     if (ret) {
0280         DRM_DEV_ERROR(minor->dev->dev, "could not install rd debugfs\n");
0281         return ret;
0282     }
0283 
0284     ret = msm_perf_debugfs_init(minor);
0285     if (ret) {
0286         DRM_DEV_ERROR(minor->dev->dev, "could not install perf debugfs\n");
0287         return ret;
0288     }
0289 
0290     return 0;
0291 }
0292 
0293 int msm_debugfs_late_init(struct drm_device *dev)
0294 {
0295     int ret;
0296     ret = late_init_minor(dev->primary);
0297     if (ret)
0298         return ret;
0299     ret = late_init_minor(dev->render);
0300     return ret;
0301 }
0302 
0303 void msm_debugfs_init(struct drm_minor *minor)
0304 {
0305     struct drm_device *dev = minor->dev;
0306     struct msm_drm_private *priv = dev->dev_private;
0307 
0308     drm_debugfs_create_files(msm_debugfs_list,
0309                  ARRAY_SIZE(msm_debugfs_list),
0310                  minor->debugfs_root, minor);
0311 
0312     debugfs_create_file("gpu", S_IRUSR, minor->debugfs_root,
0313         dev, &msm_gpu_fops);
0314 
0315     debugfs_create_file("kms", S_IRUSR, minor->debugfs_root,
0316         dev, &msm_kms_fops);
0317 
0318     debugfs_create_u32("hangcheck_period_ms", 0600, minor->debugfs_root,
0319         &priv->hangcheck_period);
0320 
0321     debugfs_create_bool("disable_err_irq", 0600, minor->debugfs_root,
0322         &priv->disable_err_irq);
0323 
0324     debugfs_create_file("shrink", S_IRWXU, minor->debugfs_root,
0325         dev, &shrink_fops);
0326 
0327     if (priv->kms && priv->kms->funcs->debugfs_init)
0328         priv->kms->funcs->debugfs_init(priv->kms, minor);
0329 }
0330 #endif
0331