0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <linux/debugfs.h>
0027 #include <linux/export.h>
0028 #include <linux/seq_file.h>
0029 #include <linux/slab.h>
0030 #include <linux/uaccess.h>
0031
0032 #include <drm/drm_atomic.h>
0033 #include <drm/drm_auth.h>
0034 #include <drm/drm_client.h>
0035 #include <drm/drm_debugfs.h>
0036 #include <drm/drm_device.h>
0037 #include <drm/drm_drv.h>
0038 #include <drm/drm_edid.h>
0039 #include <drm/drm_file.h>
0040 #include <drm/drm_gem.h>
0041
0042 #include "drm_crtc_internal.h"
0043 #include "drm_internal.h"
0044
0045 #if defined(CONFIG_DEBUG_FS)
0046
0047
0048
0049
0050
0051 static int drm_name_info(struct seq_file *m, void *data)
0052 {
0053 struct drm_info_node *node = (struct drm_info_node *) m->private;
0054 struct drm_minor *minor = node->minor;
0055 struct drm_device *dev = minor->dev;
0056 struct drm_master *master;
0057
0058 mutex_lock(&dev->master_mutex);
0059 master = dev->master;
0060 seq_printf(m, "%s", dev->driver->name);
0061 if (dev->dev)
0062 seq_printf(m, " dev=%s", dev_name(dev->dev));
0063 if (master && master->unique)
0064 seq_printf(m, " master=%s", master->unique);
0065 if (dev->unique)
0066 seq_printf(m, " unique=%s", dev->unique);
0067 seq_printf(m, "\n");
0068 mutex_unlock(&dev->master_mutex);
0069
0070 return 0;
0071 }
0072
0073 static int drm_clients_info(struct seq_file *m, void *data)
0074 {
0075 struct drm_info_node *node = (struct drm_info_node *) m->private;
0076 struct drm_device *dev = node->minor->dev;
0077 struct drm_file *priv;
0078 kuid_t uid;
0079
0080 seq_printf(m,
0081 "%20s %5s %3s master a %5s %10s\n",
0082 "command",
0083 "pid",
0084 "dev",
0085 "uid",
0086 "magic");
0087
0088
0089
0090
0091 mutex_lock(&dev->filelist_mutex);
0092 list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
0093 struct task_struct *task;
0094 bool is_current_master = drm_is_current_master(priv);
0095
0096 rcu_read_lock();
0097 task = pid_task(priv->pid, PIDTYPE_PID);
0098 uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
0099 seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n",
0100 task ? task->comm : "<unknown>",
0101 pid_vnr(priv->pid),
0102 priv->minor->index,
0103 is_current_master ? 'y' : 'n',
0104 priv->authenticated ? 'y' : 'n',
0105 from_kuid_munged(seq_user_ns(m), uid),
0106 priv->magic);
0107 rcu_read_unlock();
0108 }
0109 mutex_unlock(&dev->filelist_mutex);
0110 return 0;
0111 }
0112
0113 static int drm_gem_one_name_info(int id, void *ptr, void *data)
0114 {
0115 struct drm_gem_object *obj = ptr;
0116 struct seq_file *m = data;
0117
0118 seq_printf(m, "%6d %8zd %7d %8d\n",
0119 obj->name, obj->size,
0120 obj->handle_count,
0121 kref_read(&obj->refcount));
0122 return 0;
0123 }
0124
0125 static int drm_gem_name_info(struct seq_file *m, void *data)
0126 {
0127 struct drm_info_node *node = (struct drm_info_node *) m->private;
0128 struct drm_device *dev = node->minor->dev;
0129
0130 seq_printf(m, " name size handles refcount\n");
0131
0132 mutex_lock(&dev->object_name_lock);
0133 idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
0134 mutex_unlock(&dev->object_name_lock);
0135
0136 return 0;
0137 }
0138
0139 static const struct drm_info_list drm_debugfs_list[] = {
0140 {"name", drm_name_info, 0},
0141 {"clients", drm_clients_info, 0},
0142 {"gem_names", drm_gem_name_info, DRIVER_GEM},
0143 };
0144 #define DRM_DEBUGFS_ENTRIES ARRAY_SIZE(drm_debugfs_list)
0145
0146
0147 static int drm_debugfs_open(struct inode *inode, struct file *file)
0148 {
0149 struct drm_info_node *node = inode->i_private;
0150
0151 return single_open(file, node->info_ent->show, node);
0152 }
0153
0154
0155 static const struct file_operations drm_debugfs_fops = {
0156 .owner = THIS_MODULE,
0157 .open = drm_debugfs_open,
0158 .read = seq_read,
0159 .llseek = seq_lseek,
0160 .release = single_release,
0161 };
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 void drm_debugfs_create_files(const struct drm_info_list *files, int count,
0177 struct dentry *root, struct drm_minor *minor)
0178 {
0179 struct drm_device *dev = minor->dev;
0180 struct drm_info_node *tmp;
0181 int i;
0182
0183 for (i = 0; i < count; i++) {
0184 u32 features = files[i].driver_features;
0185
0186 if (features && !drm_core_check_all_features(dev, features))
0187 continue;
0188
0189 tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
0190 if (tmp == NULL)
0191 continue;
0192
0193 tmp->minor = minor;
0194 tmp->dent = debugfs_create_file(files[i].name,
0195 S_IFREG | S_IRUGO, root, tmp,
0196 &drm_debugfs_fops);
0197 tmp->info_ent = &files[i];
0198
0199 mutex_lock(&minor->debugfs_lock);
0200 list_add(&tmp->list, &minor->debugfs_list);
0201 mutex_unlock(&minor->debugfs_lock);
0202 }
0203 }
0204 EXPORT_SYMBOL(drm_debugfs_create_files);
0205
0206 int drm_debugfs_init(struct drm_minor *minor, int minor_id,
0207 struct dentry *root)
0208 {
0209 struct drm_device *dev = minor->dev;
0210 char name[64];
0211
0212 INIT_LIST_HEAD(&minor->debugfs_list);
0213 mutex_init(&minor->debugfs_lock);
0214 sprintf(name, "%d", minor_id);
0215 minor->debugfs_root = debugfs_create_dir(name, root);
0216
0217 drm_debugfs_create_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES,
0218 minor->debugfs_root, minor);
0219
0220 if (drm_drv_uses_atomic_modeset(dev)) {
0221 drm_atomic_debugfs_init(minor);
0222 }
0223
0224 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
0225 drm_framebuffer_debugfs_init(minor);
0226
0227 drm_client_debugfs_init(minor);
0228 }
0229
0230 if (dev->driver->debugfs_init)
0231 dev->driver->debugfs_init(minor);
0232
0233 return 0;
0234 }
0235
0236
0237 int drm_debugfs_remove_files(const struct drm_info_list *files, int count,
0238 struct drm_minor *minor)
0239 {
0240 struct list_head *pos, *q;
0241 struct drm_info_node *tmp;
0242 int i;
0243
0244 mutex_lock(&minor->debugfs_lock);
0245 for (i = 0; i < count; i++) {
0246 list_for_each_safe(pos, q, &minor->debugfs_list) {
0247 tmp = list_entry(pos, struct drm_info_node, list);
0248 if (tmp->info_ent == &files[i]) {
0249 debugfs_remove(tmp->dent);
0250 list_del(pos);
0251 kfree(tmp);
0252 }
0253 }
0254 }
0255 mutex_unlock(&minor->debugfs_lock);
0256 return 0;
0257 }
0258 EXPORT_SYMBOL(drm_debugfs_remove_files);
0259
0260 static void drm_debugfs_remove_all_files(struct drm_minor *minor)
0261 {
0262 struct drm_info_node *node, *tmp;
0263
0264 mutex_lock(&minor->debugfs_lock);
0265 list_for_each_entry_safe(node, tmp, &minor->debugfs_list, list) {
0266 debugfs_remove(node->dent);
0267 list_del(&node->list);
0268 kfree(node);
0269 }
0270 mutex_unlock(&minor->debugfs_lock);
0271 }
0272
0273 void drm_debugfs_cleanup(struct drm_minor *minor)
0274 {
0275 if (!minor->debugfs_root)
0276 return;
0277
0278 drm_debugfs_remove_all_files(minor);
0279
0280 debugfs_remove_recursive(minor->debugfs_root);
0281 minor->debugfs_root = NULL;
0282 }
0283
0284 static int connector_show(struct seq_file *m, void *data)
0285 {
0286 struct drm_connector *connector = m->private;
0287
0288 seq_printf(m, "%s\n", drm_get_connector_force_name(connector->force));
0289
0290 return 0;
0291 }
0292
0293 static int connector_open(struct inode *inode, struct file *file)
0294 {
0295 struct drm_connector *dev = inode->i_private;
0296
0297 return single_open(file, connector_show, dev);
0298 }
0299
0300 static ssize_t connector_write(struct file *file, const char __user *ubuf,
0301 size_t len, loff_t *offp)
0302 {
0303 struct seq_file *m = file->private_data;
0304 struct drm_connector *connector = m->private;
0305 char buf[12];
0306
0307 if (len > sizeof(buf) - 1)
0308 return -EINVAL;
0309
0310 if (copy_from_user(buf, ubuf, len))
0311 return -EFAULT;
0312
0313 buf[len] = '\0';
0314
0315 if (sysfs_streq(buf, "on"))
0316 connector->force = DRM_FORCE_ON;
0317 else if (sysfs_streq(buf, "digital"))
0318 connector->force = DRM_FORCE_ON_DIGITAL;
0319 else if (sysfs_streq(buf, "off"))
0320 connector->force = DRM_FORCE_OFF;
0321 else if (sysfs_streq(buf, "unspecified"))
0322 connector->force = DRM_FORCE_UNSPECIFIED;
0323 else
0324 return -EINVAL;
0325
0326 return len;
0327 }
0328
0329 static int edid_show(struct seq_file *m, void *data)
0330 {
0331 struct drm_connector *connector = m->private;
0332 struct drm_property_blob *edid = connector->edid_blob_ptr;
0333
0334 if (connector->override_edid && edid)
0335 seq_write(m, edid->data, edid->length);
0336
0337 return 0;
0338 }
0339
0340 static int edid_open(struct inode *inode, struct file *file)
0341 {
0342 struct drm_connector *dev = inode->i_private;
0343
0344 return single_open(file, edid_show, dev);
0345 }
0346
0347 static ssize_t edid_write(struct file *file, const char __user *ubuf,
0348 size_t len, loff_t *offp)
0349 {
0350 struct seq_file *m = file->private_data;
0351 struct drm_connector *connector = m->private;
0352 char *buf;
0353 int ret;
0354
0355 buf = memdup_user(ubuf, len);
0356 if (IS_ERR(buf))
0357 return PTR_ERR(buf);
0358
0359 if (len == 5 && !strncmp(buf, "reset", 5))
0360 ret = drm_edid_override_reset(connector);
0361 else
0362 ret = drm_edid_override_set(connector, buf, len);
0363
0364 kfree(buf);
0365
0366 return ret ? ret : len;
0367 }
0368
0369
0370
0371
0372
0373 static int vrr_range_show(struct seq_file *m, void *data)
0374 {
0375 struct drm_connector *connector = m->private;
0376
0377 if (connector->status != connector_status_connected)
0378 return -ENODEV;
0379
0380 seq_printf(m, "Min: %u\n", connector->display_info.monitor_range.min_vfreq);
0381 seq_printf(m, "Max: %u\n", connector->display_info.monitor_range.max_vfreq);
0382
0383 return 0;
0384 }
0385 DEFINE_SHOW_ATTRIBUTE(vrr_range);
0386
0387
0388
0389
0390
0391 static int output_bpc_show(struct seq_file *m, void *data)
0392 {
0393 struct drm_connector *connector = m->private;
0394
0395 if (connector->status != connector_status_connected)
0396 return -ENODEV;
0397
0398 seq_printf(m, "Maximum: %u\n", connector->display_info.bpc);
0399
0400 return 0;
0401 }
0402 DEFINE_SHOW_ATTRIBUTE(output_bpc);
0403
0404 static const struct file_operations drm_edid_fops = {
0405 .owner = THIS_MODULE,
0406 .open = edid_open,
0407 .read = seq_read,
0408 .llseek = seq_lseek,
0409 .release = single_release,
0410 .write = edid_write
0411 };
0412
0413
0414 static const struct file_operations drm_connector_fops = {
0415 .owner = THIS_MODULE,
0416 .open = connector_open,
0417 .read = seq_read,
0418 .llseek = seq_lseek,
0419 .release = single_release,
0420 .write = connector_write
0421 };
0422
0423 void drm_debugfs_connector_add(struct drm_connector *connector)
0424 {
0425 struct drm_minor *minor = connector->dev->primary;
0426 struct dentry *root;
0427
0428 if (!minor->debugfs_root)
0429 return;
0430
0431 root = debugfs_create_dir(connector->name, minor->debugfs_root);
0432 connector->debugfs_entry = root;
0433
0434
0435 debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector,
0436 &drm_connector_fops);
0437
0438
0439 debugfs_create_file("edid_override", S_IRUGO | S_IWUSR, root, connector,
0440 &drm_edid_fops);
0441
0442
0443 debugfs_create_file("vrr_range", S_IRUGO, root, connector,
0444 &vrr_range_fops);
0445
0446
0447 debugfs_create_file("output_bpc", 0444, root, connector,
0448 &output_bpc_fops);
0449
0450 if (connector->funcs->debugfs_init)
0451 connector->funcs->debugfs_init(connector, root);
0452 }
0453
0454 void drm_debugfs_connector_remove(struct drm_connector *connector)
0455 {
0456 if (!connector->debugfs_entry)
0457 return;
0458
0459 debugfs_remove_recursive(connector->debugfs_entry);
0460
0461 connector->debugfs_entry = NULL;
0462 }
0463
0464 void drm_debugfs_crtc_add(struct drm_crtc *crtc)
0465 {
0466 struct drm_minor *minor = crtc->dev->primary;
0467 struct dentry *root;
0468 char *name;
0469
0470 name = kasprintf(GFP_KERNEL, "crtc-%d", crtc->index);
0471 if (!name)
0472 return;
0473
0474 root = debugfs_create_dir(name, minor->debugfs_root);
0475 kfree(name);
0476
0477 crtc->debugfs_entry = root;
0478
0479 drm_debugfs_crtc_crc_add(crtc);
0480 }
0481
0482 void drm_debugfs_crtc_remove(struct drm_crtc *crtc)
0483 {
0484 debugfs_remove_recursive(crtc->debugfs_entry);
0485 crtc->debugfs_entry = NULL;
0486 }
0487
0488 #endif