1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2013-2016 Red Hat
9 #include <linux/debugfs.h>
11 #include <drm/drm_debugfs.h>
12 #include <drm/drm_file.h>
17 #include "msm_debugfs.h"
18 #include "disp/msm_disp_snapshot.h"
24 struct msm_gpu_show_priv {
25 struct msm_gpu_state *state;
26 struct drm_device *dev;
29 static int msm_gpu_show(struct seq_file *m, void *arg)
31 struct drm_printer p = drm_seq_file_printer(m);
32 struct msm_gpu_show_priv *show_priv = m->private;
33 struct msm_drm_private *priv = show_priv->dev->dev_private;
34 struct msm_gpu *gpu = priv->gpu;
37 ret = mutex_lock_interruptible(&gpu->lock);
41 drm_printf(&p, "%s Status:\n", gpu->name);
42 gpu->funcs->show(gpu, show_priv->state, &p);
44 mutex_unlock(&gpu->lock);
49 static int msm_gpu_release(struct inode *inode, struct file *file)
51 struct seq_file *m = file->private_data;
52 struct msm_gpu_show_priv *show_priv = m->private;
53 struct msm_drm_private *priv = show_priv->dev->dev_private;
54 struct msm_gpu *gpu = priv->gpu;
56 mutex_lock(&gpu->lock);
57 gpu->funcs->gpu_state_put(show_priv->state);
58 mutex_unlock(&gpu->lock);
62 return single_release(inode, file);
65 static int msm_gpu_open(struct inode *inode, struct file *file)
67 struct drm_device *dev = inode->i_private;
68 struct msm_drm_private *priv = dev->dev_private;
69 struct msm_gpu *gpu = priv->gpu;
70 struct msm_gpu_show_priv *show_priv;
73 if (!gpu || !gpu->funcs->gpu_state_get)
76 show_priv = kmalloc(sizeof(*show_priv), GFP_KERNEL);
80 ret = mutex_lock_interruptible(&gpu->lock);
84 pm_runtime_get_sync(&gpu->pdev->dev);
86 show_priv->state = gpu->funcs->gpu_state_get(gpu);
87 pm_runtime_put_sync(&gpu->pdev->dev);
89 mutex_unlock(&gpu->lock);
91 if (IS_ERR(show_priv->state)) {
92 ret = PTR_ERR(show_priv->state);
98 ret = single_open(file, msm_gpu_show, show_priv);
109 static const struct file_operations msm_gpu_fops = {
110 .owner = THIS_MODULE,
111 .open = msm_gpu_open,
114 .release = msm_gpu_release,
121 static int msm_kms_show(struct seq_file *m, void *arg)
123 struct drm_printer p = drm_seq_file_printer(m);
124 struct msm_disp_state *state = m->private;
126 msm_disp_state_print(state, &p);
131 static int msm_kms_release(struct inode *inode, struct file *file)
133 struct seq_file *m = file->private_data;
134 struct msm_disp_state *state = m->private;
136 msm_disp_state_free(state);
138 return single_release(inode, file);
141 static int msm_kms_open(struct inode *inode, struct file *file)
143 struct drm_device *dev = inode->i_private;
144 struct msm_drm_private *priv = dev->dev_private;
145 struct msm_disp_state *state;
151 ret = mutex_lock_interruptible(&priv->kms->dump_mutex);
155 state = msm_disp_snapshot_state_sync(priv->kms);
157 mutex_unlock(&priv->kms->dump_mutex);
160 return PTR_ERR(state);
163 ret = single_open(file, msm_kms_show, state);
165 msm_disp_state_free(state);
172 static const struct file_operations msm_kms_fops = {
173 .owner = THIS_MODULE,
174 .open = msm_kms_open,
177 .release = msm_kms_release,
184 static unsigned long last_shrink_freed;
187 shrink_get(void *data, u64 *val)
189 *val = last_shrink_freed;
195 shrink_set(void *data, u64 val)
197 struct drm_device *dev = data;
199 last_shrink_freed = msm_gem_shrinker_shrink(dev, val);
204 DEFINE_SIMPLE_ATTRIBUTE(shrink_fops,
205 shrink_get, shrink_set,
209 static int msm_gem_show(struct seq_file *m, void *arg)
211 struct drm_info_node *node = (struct drm_info_node *) m->private;
212 struct drm_device *dev = node->minor->dev;
213 struct msm_drm_private *priv = dev->dev_private;
216 ret = mutex_lock_interruptible(&priv->obj_lock);
220 msm_gem_describe_objects(&priv->objects, m);
222 mutex_unlock(&priv->obj_lock);
227 static int msm_mm_show(struct seq_file *m, void *arg)
229 struct drm_info_node *node = (struct drm_info_node *) m->private;
230 struct drm_device *dev = node->minor->dev;
231 struct drm_printer p = drm_seq_file_printer(m);
233 drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p);
238 static int msm_fb_show(struct seq_file *m, void *arg)
240 struct drm_info_node *node = (struct drm_info_node *) m->private;
241 struct drm_device *dev = node->minor->dev;
242 struct msm_drm_private *priv = dev->dev_private;
243 struct drm_framebuffer *fb, *fbdev_fb = NULL;
246 seq_printf(m, "fbcon ");
247 fbdev_fb = priv->fbdev->fb;
248 msm_framebuffer_describe(fbdev_fb, m);
251 mutex_lock(&dev->mode_config.fb_lock);
252 list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
256 seq_printf(m, "user ");
257 msm_framebuffer_describe(fb, m);
259 mutex_unlock(&dev->mode_config.fb_lock);
264 static struct drm_info_list msm_debugfs_list[] = {
265 {"gem", msm_gem_show},
266 { "mm", msm_mm_show },
267 { "fb", msm_fb_show },
270 static int late_init_minor(struct drm_minor *minor)
277 ret = msm_rd_debugfs_init(minor);
279 DRM_DEV_ERROR(minor->dev->dev, "could not install rd debugfs\n");
283 ret = msm_perf_debugfs_init(minor);
285 DRM_DEV_ERROR(minor->dev->dev, "could not install perf debugfs\n");
292 int msm_debugfs_late_init(struct drm_device *dev)
295 ret = late_init_minor(dev->primary);
298 ret = late_init_minor(dev->render);
302 void msm_debugfs_init(struct drm_minor *minor)
304 struct drm_device *dev = minor->dev;
305 struct msm_drm_private *priv = dev->dev_private;
307 drm_debugfs_create_files(msm_debugfs_list,
308 ARRAY_SIZE(msm_debugfs_list),
309 minor->debugfs_root, minor);
311 debugfs_create_file("gpu", S_IRUSR, minor->debugfs_root,
314 debugfs_create_file("kms", S_IRUSR, minor->debugfs_root,
317 debugfs_create_u32("hangcheck_period_ms", 0600, minor->debugfs_root,
318 &priv->hangcheck_period);
320 debugfs_create_bool("disable_err_irq", 0600, minor->debugfs_root,
321 &priv->disable_err_irq);
323 debugfs_create_file("shrink", S_IRWXU, minor->debugfs_root,
326 if (priv->kms && priv->kms->funcs->debugfs_init)
327 priv->kms->funcs->debugfs_init(priv->kms, minor);