at master 23 kB view raw
1/* 2 * Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com 3 * 4 * Copyright 2008 Ben Gamari <bgamari@gmail.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26#include <linux/debugfs.h> 27#include <linux/export.h> 28#include <linux/seq_file.h> 29#include <linux/slab.h> 30#include <linux/uaccess.h> 31 32#include <drm/drm_atomic.h> 33#include <drm/drm_auth.h> 34#include <drm/drm_bridge.h> 35#include <drm/drm_debugfs.h> 36#include <drm/drm_device.h> 37#include <drm/drm_drv.h> 38#include <drm/drm_edid.h> 39#include <drm/drm_file.h> 40#include <drm/drm_gem.h> 41#include <drm/drm_managed.h> 42#include <drm/drm_gpuvm.h> 43 44#include "drm_crtc_internal.h" 45#include "drm_internal.h" 46 47static struct dentry *accel_debugfs_root; 48static struct dentry *drm_debugfs_root; 49 50/*************************************************** 51 * Initialization, etc. 52 **************************************************/ 53 54static int drm_name_info(struct seq_file *m, void *data) 55{ 56 struct drm_debugfs_entry *entry = m->private; 57 struct drm_device *dev = entry->dev; 58 struct drm_master *master; 59 60 mutex_lock(&dev->master_mutex); 61 master = dev->master; 62 seq_printf(m, "%s", dev->driver->name); 63 if (dev->dev) 64 seq_printf(m, " dev=%s", dev_name(dev->dev)); 65 if (master && master->unique) 66 seq_printf(m, " master=%s", master->unique); 67 if (dev->unique) 68 seq_printf(m, " unique=%s", dev->unique); 69 seq_printf(m, "\n"); 70 mutex_unlock(&dev->master_mutex); 71 72 return 0; 73} 74 75static int drm_clients_info(struct seq_file *m, void *data) 76{ 77 struct drm_debugfs_entry *entry = m->private; 78 struct drm_device *dev = entry->dev; 79 struct drm_file *priv; 80 kuid_t uid; 81 82 seq_printf(m, 83 "%20s %5s %3s master a %5s %10s %*s %20s\n", 84 "command", 85 "tgid", 86 "dev", 87 "uid", 88 "magic", 89 DRM_CLIENT_NAME_MAX_LEN, 90 "name", 91 "id"); 92 93 /* dev->filelist is sorted youngest first, but we want to present 94 * oldest first (i.e. kernel, servers, clients), so walk backwardss. 95 */ 96 mutex_lock(&dev->filelist_mutex); 97 list_for_each_entry_reverse(priv, &dev->filelist, lhead) { 98 bool is_current_master = drm_is_current_master(priv); 99 struct task_struct *task; 100 struct pid *pid; 101 102 mutex_lock(&priv->client_name_lock); 103 rcu_read_lock(); /* Locks priv->pid and pid_task()->comm! */ 104 pid = rcu_dereference(priv->pid); 105 task = pid_task(pid, PIDTYPE_TGID); 106 uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; 107 seq_printf(m, "%20s %5d %3d %c %c %5d %10u %*s %20llu\n", 108 task ? task->comm : "<unknown>", 109 pid_vnr(pid), 110 priv->minor->index, 111 is_current_master ? 'y' : 'n', 112 priv->authenticated ? 'y' : 'n', 113 from_kuid_munged(seq_user_ns(m), uid), 114 priv->magic, 115 DRM_CLIENT_NAME_MAX_LEN, 116 priv->client_name ? priv->client_name : "<unset>", 117 priv->client_id); 118 rcu_read_unlock(); 119 mutex_unlock(&priv->client_name_lock); 120 } 121 mutex_unlock(&dev->filelist_mutex); 122 return 0; 123} 124 125static int drm_gem_one_name_info(int id, void *ptr, void *data) 126{ 127 struct drm_gem_object *obj = ptr; 128 struct seq_file *m = data; 129 130 seq_printf(m, "%6d %8zd %7d %8d\n", 131 obj->name, obj->size, 132 obj->handle_count, 133 kref_read(&obj->refcount)); 134 return 0; 135} 136 137static int drm_gem_name_info(struct seq_file *m, void *data) 138{ 139 struct drm_debugfs_entry *entry = m->private; 140 struct drm_device *dev = entry->dev; 141 142 seq_printf(m, " name size handles refcount\n"); 143 144 mutex_lock(&dev->object_name_lock); 145 idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); 146 mutex_unlock(&dev->object_name_lock); 147 148 return 0; 149} 150 151static const struct drm_debugfs_info drm_debugfs_list[] = { 152 {"name", drm_name_info, 0}, 153 {"clients", drm_clients_info, 0}, 154 {"gem_names", drm_gem_name_info, DRIVER_GEM}, 155}; 156#define DRM_DEBUGFS_ENTRIES ARRAY_SIZE(drm_debugfs_list) 157 158 159static int drm_debugfs_open(struct inode *inode, struct file *file) 160{ 161 struct drm_info_node *node = inode->i_private; 162 163 if (!device_is_registered(node->minor->kdev)) 164 return -ENODEV; 165 166 return single_open(file, node->info_ent->show, node); 167} 168 169static int drm_debugfs_entry_open(struct inode *inode, struct file *file) 170{ 171 struct drm_debugfs_entry *entry = inode->i_private; 172 struct drm_debugfs_info *node = &entry->file; 173 struct drm_minor *minor = entry->dev->primary ?: entry->dev->accel; 174 175 if (!device_is_registered(minor->kdev)) 176 return -ENODEV; 177 178 return single_open(file, node->show, entry); 179} 180 181static const struct file_operations drm_debugfs_entry_fops = { 182 .owner = THIS_MODULE, 183 .open = drm_debugfs_entry_open, 184 .read = seq_read, 185 .llseek = seq_lseek, 186 .release = single_release, 187}; 188 189static const struct file_operations drm_debugfs_fops = { 190 .owner = THIS_MODULE, 191 .open = drm_debugfs_open, 192 .read = seq_read, 193 .llseek = seq_lseek, 194 .release = single_release, 195}; 196 197/** 198 * drm_debugfs_gpuva_info - dump the given DRM GPU VA space 199 * @m: pointer to the &seq_file to write 200 * @gpuvm: the &drm_gpuvm representing the GPU VA space 201 * 202 * Dumps the GPU VA mappings of a given DRM GPU VA manager. 203 * 204 * For each DRM GPU VA space drivers should call this function from their 205 * &drm_info_list's show callback. 206 * 207 * Returns: 0 on success, -ENODEV if the &gpuvm is not initialized 208 */ 209int drm_debugfs_gpuva_info(struct seq_file *m, 210 struct drm_gpuvm *gpuvm) 211{ 212 struct drm_gpuva *va, *kva = &gpuvm->kernel_alloc_node; 213 214 if (!gpuvm->name) 215 return -ENODEV; 216 217 seq_printf(m, "DRM GPU VA space (%s) [0x%016llx;0x%016llx]\n", 218 gpuvm->name, gpuvm->mm_start, gpuvm->mm_start + gpuvm->mm_range); 219 seq_printf(m, "Kernel reserved node [0x%016llx;0x%016llx]\n", 220 kva->va.addr, kva->va.addr + kva->va.range); 221 seq_puts(m, "\n"); 222 seq_puts(m, " VAs | start | range | end | object | object offset\n"); 223 seq_puts(m, "-------------------------------------------------------------------------------------------------------------\n"); 224 drm_gpuvm_for_each_va(va, gpuvm) { 225 if (unlikely(va == kva)) 226 continue; 227 228 seq_printf(m, " | 0x%016llx | 0x%016llx | 0x%016llx | 0x%016llx | 0x%016llx\n", 229 va->va.addr, va->va.range, va->va.addr + va->va.range, 230 (u64)(uintptr_t)va->gem.obj, va->gem.offset); 231 } 232 233 return 0; 234} 235EXPORT_SYMBOL(drm_debugfs_gpuva_info); 236 237/** 238 * drm_debugfs_create_files - Initialize a given set of debugfs files for DRM 239 * minor 240 * @files: The array of files to create 241 * @count: The number of files given 242 * @root: DRI debugfs dir entry. 243 * @minor: device minor number 244 * 245 * Create a given set of debugfs files represented by an array of 246 * &struct drm_info_list in the given root directory. These files will be removed 247 * automatically on drm_debugfs_dev_fini(). 248 */ 249void drm_debugfs_create_files(const struct drm_info_list *files, int count, 250 struct dentry *root, struct drm_minor *minor) 251{ 252 struct drm_device *dev = minor->dev; 253 struct drm_info_node *tmp; 254 int i; 255 256 for (i = 0; i < count; i++) { 257 u32 features = files[i].driver_features; 258 259 if (features && !drm_core_check_all_features(dev, features)) 260 continue; 261 262 tmp = drmm_kzalloc(dev, sizeof(*tmp), GFP_KERNEL); 263 if (tmp == NULL) 264 continue; 265 266 tmp->minor = minor; 267 tmp->dent = debugfs_create_file(files[i].name, 268 0444, root, tmp, 269 &drm_debugfs_fops); 270 tmp->info_ent = &files[i]; 271 } 272} 273EXPORT_SYMBOL(drm_debugfs_create_files); 274 275int drm_debugfs_remove_files(const struct drm_info_list *files, int count, 276 struct dentry *root, struct drm_minor *minor) 277{ 278 int i; 279 280 for (i = 0; i < count; i++) { 281 struct dentry *dent = debugfs_lookup(files[i].name, root); 282 283 if (!dent) 284 continue; 285 286 drmm_kfree(minor->dev, d_inode(dent)->i_private); 287 debugfs_remove(dent); 288 } 289 return 0; 290} 291EXPORT_SYMBOL(drm_debugfs_remove_files); 292 293void drm_debugfs_bridge_params(void) 294{ 295 drm_bridge_debugfs_params(drm_debugfs_root); 296} 297 298void drm_debugfs_init_root(void) 299{ 300 drm_debugfs_root = debugfs_create_dir("dri", NULL); 301#if IS_ENABLED(CONFIG_DRM_ACCEL) 302 accel_debugfs_root = debugfs_create_dir("accel", NULL); 303#endif 304} 305 306void drm_debugfs_remove_root(void) 307{ 308#if IS_ENABLED(CONFIG_DRM_ACCEL) 309 debugfs_remove(accel_debugfs_root); 310#endif 311 debugfs_remove(drm_debugfs_root); 312} 313 314static int drm_debugfs_proc_info_show(struct seq_file *m, void *unused) 315{ 316 struct pid *pid; 317 struct task_struct *task; 318 struct drm_file *file = m->private; 319 320 if (!file) 321 return -EINVAL; 322 323 rcu_read_lock(); 324 pid = rcu_dereference(file->pid); 325 task = pid_task(pid, PIDTYPE_TGID); 326 327 seq_printf(m, "pid: %d\n", task ? task->pid : 0); 328 seq_printf(m, "comm: %s\n", task ? task->comm : "Unset"); 329 rcu_read_unlock(); 330 return 0; 331} 332 333static int drm_debufs_proc_info_open(struct inode *inode, struct file *file) 334{ 335 return single_open(file, drm_debugfs_proc_info_show, inode->i_private); 336} 337 338static const struct file_operations drm_debugfs_proc_info_fops = { 339 .owner = THIS_MODULE, 340 .open = drm_debufs_proc_info_open, 341 .read = seq_read, 342 .llseek = seq_lseek, 343 .release = single_release, 344}; 345 346/** 347 * drm_debugfs_clients_add - Add a per client debugfs directory 348 * @file: drm_file for a client 349 * 350 * Create the debugfs directory for each client. This will be used to populate 351 * driver specific data for each client. 352 * 353 * Also add the process information debugfs file for each client to tag 354 * which client belongs to which process. 355 */ 356void drm_debugfs_clients_add(struct drm_file *file) 357{ 358 char *client; 359 360 client = kasprintf(GFP_KERNEL, "client-%llu", file->client_id); 361 if (!client) 362 return; 363 364 /* Create a debugfs directory for the client in root on drm debugfs */ 365 file->debugfs_client = debugfs_create_dir(client, drm_debugfs_root); 366 kfree(client); 367 368 debugfs_create_file("proc_info", 0444, file->debugfs_client, file, 369 &drm_debugfs_proc_info_fops); 370 371 client = kasprintf(GFP_KERNEL, "../%s", file->minor->dev->unique); 372 if (!client) 373 return; 374 375 /* Create a link from client_id to the drm device this client id belongs to */ 376 debugfs_create_symlink("device", file->debugfs_client, client); 377 kfree(client); 378} 379 380/** 381 * drm_debugfs_clients_remove - removes all debugfs directories and files 382 * @file: drm_file for a client 383 * 384 * Removes the debugfs directories recursively from the client directory. 385 * 386 * There is also a possibility that debugfs files are open while the drm_file 387 * is released. 388 */ 389void drm_debugfs_clients_remove(struct drm_file *file) 390{ 391 debugfs_remove_recursive(file->debugfs_client); 392 file->debugfs_client = NULL; 393} 394 395/** 396 * drm_debugfs_dev_init - create debugfs directory for the device 397 * @dev: the device which we want to create the directory for 398 * 399 * Creates the debugfs directory for the device under the given root directory. 400 */ 401void drm_debugfs_dev_init(struct drm_device *dev) 402{ 403 if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL)) 404 dev->debugfs_root = debugfs_create_dir(dev->unique, accel_debugfs_root); 405 else 406 dev->debugfs_root = debugfs_create_dir(dev->unique, drm_debugfs_root); 407} 408 409/** 410 * drm_debugfs_dev_fini - cleanup debugfs directory 411 * @dev: the device to cleanup the debugfs stuff 412 * 413 * Remove the debugfs directory, might be called multiple times. 414 */ 415void drm_debugfs_dev_fini(struct drm_device *dev) 416{ 417 debugfs_remove_recursive(dev->debugfs_root); 418 dev->debugfs_root = NULL; 419} 420 421void drm_debugfs_dev_register(struct drm_device *dev) 422{ 423 drm_debugfs_add_files(dev, drm_debugfs_list, DRM_DEBUGFS_ENTRIES); 424 425 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 426 drm_framebuffer_debugfs_init(dev); 427 drm_client_debugfs_init(dev); 428 } 429 if (drm_drv_uses_atomic_modeset(dev)) 430 drm_atomic_debugfs_init(dev); 431} 432 433int drm_debugfs_register(struct drm_minor *minor, int minor_id) 434{ 435 struct drm_device *dev = minor->dev; 436 char name[64]; 437 438 sprintf(name, "%d", minor_id); 439 minor->debugfs_symlink = debugfs_create_symlink(name, drm_debugfs_root, 440 dev->unique); 441 442 /* TODO: Only for compatibility with drivers */ 443 minor->debugfs_root = dev->debugfs_root; 444 445 if (dev->driver->debugfs_init && dev->render != minor) 446 dev->driver->debugfs_init(minor); 447 448 return 0; 449} 450 451void drm_debugfs_unregister(struct drm_minor *minor) 452{ 453 debugfs_remove(minor->debugfs_symlink); 454 minor->debugfs_symlink = NULL; 455} 456 457/** 458 * drm_debugfs_add_file - Add a given file to the DRM device debugfs file list 459 * @dev: drm device for the ioctl 460 * @name: debugfs file name 461 * @show: show callback 462 * @data: driver-private data, should not be device-specific 463 * 464 * Add a given file entry to the DRM device debugfs file list to be created on 465 * drm_debugfs_init. 466 */ 467void drm_debugfs_add_file(struct drm_device *dev, const char *name, 468 int (*show)(struct seq_file*, void*), void *data) 469{ 470 struct drm_debugfs_entry *entry = drmm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); 471 472 if (!entry) 473 return; 474 475 entry->file.name = name; 476 entry->file.show = show; 477 entry->file.data = data; 478 entry->dev = dev; 479 480 debugfs_create_file(name, 0444, dev->debugfs_root, entry, 481 &drm_debugfs_entry_fops); 482} 483EXPORT_SYMBOL(drm_debugfs_add_file); 484 485/** 486 * drm_debugfs_add_files - Add an array of files to the DRM device debugfs file list 487 * @dev: drm device for the ioctl 488 * @files: The array of files to create 489 * @count: The number of files given 490 * 491 * Add a given set of debugfs files represented by an array of 492 * &struct drm_debugfs_info in the DRM device debugfs file list. 493 */ 494void drm_debugfs_add_files(struct drm_device *dev, const struct drm_debugfs_info *files, int count) 495{ 496 int i; 497 498 for (i = 0; i < count; i++) 499 drm_debugfs_add_file(dev, files[i].name, files[i].show, files[i].data); 500} 501EXPORT_SYMBOL(drm_debugfs_add_files); 502 503static int connector_show(struct seq_file *m, void *data) 504{ 505 struct drm_connector *connector = m->private; 506 507 seq_printf(m, "%s\n", drm_get_connector_force_name(connector->force)); 508 509 return 0; 510} 511 512static int connector_open(struct inode *inode, struct file *file) 513{ 514 struct drm_connector *dev = inode->i_private; 515 516 return single_open(file, connector_show, dev); 517} 518 519static ssize_t connector_write(struct file *file, const char __user *ubuf, 520 size_t len, loff_t *offp) 521{ 522 struct seq_file *m = file->private_data; 523 struct drm_connector *connector = m->private; 524 char buf[12]; 525 526 if (len > sizeof(buf) - 1) 527 return -EINVAL; 528 529 if (copy_from_user(buf, ubuf, len)) 530 return -EFAULT; 531 532 buf[len] = '\0'; 533 534 if (sysfs_streq(buf, "on")) 535 connector->force = DRM_FORCE_ON; 536 else if (sysfs_streq(buf, "digital")) 537 connector->force = DRM_FORCE_ON_DIGITAL; 538 else if (sysfs_streq(buf, "off")) 539 connector->force = DRM_FORCE_OFF; 540 else if (sysfs_streq(buf, "unspecified")) 541 connector->force = DRM_FORCE_UNSPECIFIED; 542 else 543 return -EINVAL; 544 545 return len; 546} 547 548static int edid_show(struct seq_file *m, void *data) 549{ 550 return drm_edid_override_show(m->private, m); 551} 552 553static int edid_open(struct inode *inode, struct file *file) 554{ 555 struct drm_connector *dev = inode->i_private; 556 557 return single_open(file, edid_show, dev); 558} 559 560static ssize_t edid_write(struct file *file, const char __user *ubuf, 561 size_t len, loff_t *offp) 562{ 563 struct seq_file *m = file->private_data; 564 struct drm_connector *connector = m->private; 565 char *buf; 566 int ret; 567 568 buf = memdup_user(ubuf, len); 569 if (IS_ERR(buf)) 570 return PTR_ERR(buf); 571 572 if (len == 5 && !strncmp(buf, "reset", 5)) 573 ret = drm_edid_override_reset(connector); 574 else 575 ret = drm_edid_override_set(connector, buf, len); 576 577 kfree(buf); 578 579 return ret ? ret : len; 580} 581 582/* 583 * Returns the min and max vrr vfreq through the connector's debugfs file. 584 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range 585 */ 586static int vrr_range_show(struct seq_file *m, void *data) 587{ 588 struct drm_connector *connector = m->private; 589 590 if (connector->status != connector_status_connected) 591 return -ENODEV; 592 593 seq_printf(m, "Min: %u\n", connector->display_info.monitor_range.min_vfreq); 594 seq_printf(m, "Max: %u\n", connector->display_info.monitor_range.max_vfreq); 595 596 return 0; 597} 598DEFINE_SHOW_ATTRIBUTE(vrr_range); 599 600/* 601 * Returns Connector's max supported bpc through debugfs file. 602 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc 603 */ 604static int output_bpc_show(struct seq_file *m, void *data) 605{ 606 struct drm_connector *connector = m->private; 607 608 if (connector->status != connector_status_connected) 609 return -ENODEV; 610 611 seq_printf(m, "Maximum: %u\n", connector->display_info.bpc); 612 613 return 0; 614} 615DEFINE_SHOW_ATTRIBUTE(output_bpc); 616 617static const struct file_operations drm_edid_fops = { 618 .owner = THIS_MODULE, 619 .open = edid_open, 620 .read = seq_read, 621 .llseek = seq_lseek, 622 .release = single_release, 623 .write = edid_write 624}; 625 626 627static const struct file_operations drm_connector_fops = { 628 .owner = THIS_MODULE, 629 .open = connector_open, 630 .read = seq_read, 631 .llseek = seq_lseek, 632 .release = single_release, 633 .write = connector_write 634}; 635 636static ssize_t 637audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) 638{ 639 struct drm_connector_hdmi_infoframe *infoframe; 640 struct drm_connector *connector; 641 union hdmi_infoframe *frame; 642 u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)]; 643 ssize_t len = 0; 644 645 connector = filp->private_data; 646 mutex_lock(&connector->hdmi.infoframes.lock); 647 648 infoframe = &connector->hdmi.infoframes.audio; 649 if (!infoframe->set) 650 goto out; 651 652 frame = &infoframe->data; 653 len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); 654 if (len < 0) 655 goto out; 656 657 len = simple_read_from_buffer(ubuf, count, ppos, buf, len); 658 659out: 660 mutex_unlock(&connector->hdmi.infoframes.lock); 661 return len; 662} 663 664static const struct file_operations audio_infoframe_fops = { 665 .owner = THIS_MODULE, 666 .open = simple_open, 667 .read = audio_infoframe_read, 668}; 669 670static int create_hdmi_audio_infoframe_file(struct drm_connector *connector, 671 struct dentry *parent) 672{ 673 struct dentry *file; 674 675 file = debugfs_create_file("audio", 0400, parent, connector, &audio_infoframe_fops); 676 if (IS_ERR(file)) 677 return PTR_ERR(file); 678 679 return 0; 680} 681 682#define DEFINE_INFOFRAME_FILE(_f) \ 683static ssize_t _f##_read_infoframe(struct file *filp, \ 684 char __user *ubuf, \ 685 size_t count, \ 686 loff_t *ppos) \ 687{ \ 688 struct drm_connector_hdmi_infoframe *infoframe; \ 689 struct drm_connector_state *conn_state; \ 690 struct drm_connector *connector; \ 691 union hdmi_infoframe *frame; \ 692 struct drm_device *dev; \ 693 u8 buf[HDMI_INFOFRAME_SIZE(MAX)]; \ 694 ssize_t len = 0; \ 695 \ 696 connector = filp->private_data; \ 697 dev = connector->dev; \ 698 \ 699 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); \ 700 \ 701 conn_state = connector->state; \ 702 infoframe = &conn_state->hdmi.infoframes._f; \ 703 if (!infoframe->set) \ 704 goto out; \ 705 \ 706 frame = &infoframe->data; \ 707 len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); \ 708 if (len < 0) \ 709 goto out; \ 710 \ 711 len = simple_read_from_buffer(ubuf, count, ppos, buf, len); \ 712 \ 713out: \ 714 drm_modeset_unlock(&dev->mode_config.connection_mutex); \ 715 return len; \ 716} \ 717\ 718static const struct file_operations _f##_infoframe_fops = { \ 719 .owner = THIS_MODULE, \ 720 .open = simple_open, \ 721 .read = _f##_read_infoframe, \ 722}; \ 723\ 724static int create_hdmi_## _f ## _infoframe_file(struct drm_connector *connector, \ 725 struct dentry *parent) \ 726{ \ 727 struct dentry *file; \ 728 \ 729 file = debugfs_create_file(#_f, 0400, parent, connector, &_f ## _infoframe_fops); \ 730 if (IS_ERR(file)) \ 731 return PTR_ERR(file); \ 732 \ 733 return 0; \ 734} 735 736DEFINE_INFOFRAME_FILE(avi); 737DEFINE_INFOFRAME_FILE(hdmi); 738DEFINE_INFOFRAME_FILE(hdr_drm); 739DEFINE_INFOFRAME_FILE(spd); 740 741static int create_hdmi_infoframe_files(struct drm_connector *connector, 742 struct dentry *parent) 743{ 744 int ret; 745 746 ret = create_hdmi_audio_infoframe_file(connector, parent); 747 if (ret) 748 return ret; 749 750 ret = create_hdmi_avi_infoframe_file(connector, parent); 751 if (ret) 752 return ret; 753 754 ret = create_hdmi_hdmi_infoframe_file(connector, parent); 755 if (ret) 756 return ret; 757 758 ret = create_hdmi_hdr_drm_infoframe_file(connector, parent); 759 if (ret) 760 return ret; 761 762 ret = create_hdmi_spd_infoframe_file(connector, parent); 763 if (ret) 764 return ret; 765 766 return 0; 767} 768 769static void hdmi_debugfs_add(struct drm_connector *connector) 770{ 771 struct dentry *dir; 772 773 if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || 774 connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) 775 return; 776 777 dir = debugfs_create_dir("infoframes", connector->debugfs_entry); 778 if (IS_ERR(dir)) 779 return; 780 781 create_hdmi_infoframe_files(connector, dir); 782} 783 784void drm_debugfs_connector_add(struct drm_connector *connector) 785{ 786 struct drm_device *dev = connector->dev; 787 struct dentry *root; 788 789 if (!dev->debugfs_root) 790 return; 791 792 root = debugfs_create_dir(connector->name, dev->debugfs_root); 793 connector->debugfs_entry = root; 794 795 /* force */ 796 debugfs_create_file("force", 0644, root, connector, 797 &drm_connector_fops); 798 799 /* edid */ 800 debugfs_create_file("edid_override", 0644, root, connector, 801 &drm_edid_fops); 802 803 /* vrr range */ 804 debugfs_create_file("vrr_range", 0444, root, connector, 805 &vrr_range_fops); 806 807 /* max bpc */ 808 debugfs_create_file("output_bpc", 0444, root, connector, 809 &output_bpc_fops); 810 811 hdmi_debugfs_add(connector); 812 813 if (connector->funcs->debugfs_init) 814 connector->funcs->debugfs_init(connector, root); 815} 816 817void drm_debugfs_connector_remove(struct drm_connector *connector) 818{ 819 if (!connector->debugfs_entry) 820 return; 821 822 debugfs_remove_recursive(connector->debugfs_entry); 823 824 connector->debugfs_entry = NULL; 825} 826 827void drm_debugfs_crtc_add(struct drm_crtc *crtc) 828{ 829 struct drm_device *dev = crtc->dev; 830 struct dentry *root; 831 char *name; 832 833 name = kasprintf(GFP_KERNEL, "crtc-%d", crtc->index); 834 if (!name) 835 return; 836 837 root = debugfs_create_dir(name, dev->debugfs_root); 838 kfree(name); 839 840 crtc->debugfs_entry = root; 841 842 drm_debugfs_crtc_crc_add(crtc); 843} 844 845void drm_debugfs_crtc_remove(struct drm_crtc *crtc) 846{ 847 debugfs_remove_recursive(crtc->debugfs_entry); 848 crtc->debugfs_entry = NULL; 849} 850 851void drm_debugfs_encoder_add(struct drm_encoder *encoder) 852{ 853 struct drm_minor *minor = encoder->dev->primary; 854 struct dentry *root; 855 char *name; 856 857 name = kasprintf(GFP_KERNEL, "encoder-%d", encoder->index); 858 if (!name) 859 return; 860 861 root = debugfs_create_dir(name, minor->debugfs_root); 862 kfree(name); 863 864 encoder->debugfs_entry = root; 865 866 drm_bridge_debugfs_encoder_params(root, encoder); 867 868 if (encoder->funcs && encoder->funcs->debugfs_init) 869 encoder->funcs->debugfs_init(encoder, root); 870} 871 872void drm_debugfs_encoder_remove(struct drm_encoder *encoder) 873{ 874 debugfs_remove_recursive(encoder->debugfs_entry); 875 encoder->debugfs_entry = NULL; 876}