1 1.4 riastrad /* $NetBSD: drm_debugfs.c,v 1.5 2021/12/18 23:44:57 riastradh Exp $ */ 2 1.4 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Created: Sun Dec 21 13:08:50 2008 by bgamari (at) gmail.com 5 1.1 riastrad * 6 1.1 riastrad * Copyright 2008 Ben Gamari <bgamari (at) gmail.com> 7 1.1 riastrad * 8 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 9 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 10 1.1 riastrad * to deal in the Software without restriction, including without limitation 11 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 13 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 14 1.1 riastrad * 15 1.1 riastrad * The above copyright notice and this permission notice (including the next 16 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 17 1.1 riastrad * Software. 18 1.1 riastrad * 19 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 1.1 riastrad * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 1.1 riastrad * OTHER DEALINGS IN THE SOFTWARE. 26 1.1 riastrad */ 27 1.1 riastrad 28 1.4 riastrad #include <sys/cdefs.h> 29 1.4 riastrad __KERNEL_RCSID(0, "$NetBSD: drm_debugfs.c,v 1.5 2021/12/18 23:44:57 riastradh Exp $"); 30 1.4 riastrad 31 1.1 riastrad #include <linux/debugfs.h> 32 1.5 riastrad #include <linux/export.h> 33 1.1 riastrad #include <linux/seq_file.h> 34 1.1 riastrad #include <linux/slab.h> 35 1.5 riastrad #include <linux/uaccess.h> 36 1.5 riastrad 37 1.5 riastrad #include <drm/drm_atomic.h> 38 1.5 riastrad #include <drm/drm_auth.h> 39 1.5 riastrad #include <drm/drm_client.h> 40 1.5 riastrad #include <drm/drm_debugfs.h> 41 1.5 riastrad #include <drm/drm_device.h> 42 1.5 riastrad #include <drm/drm_drv.h> 43 1.4 riastrad #include <drm/drm_edid.h> 44 1.5 riastrad #include <drm/drm_file.h> 45 1.5 riastrad #include <drm/drm_gem.h> 46 1.5 riastrad 47 1.5 riastrad #include "drm_crtc_internal.h" 48 1.4 riastrad #include "drm_internal.h" 49 1.1 riastrad 50 1.1 riastrad #if defined(CONFIG_DEBUG_FS) 51 1.1 riastrad 52 1.1 riastrad /*************************************************** 53 1.1 riastrad * Initialization, etc. 54 1.1 riastrad **************************************************/ 55 1.1 riastrad 56 1.5 riastrad static int drm_name_info(struct seq_file *m, void *data) 57 1.5 riastrad { 58 1.5 riastrad struct drm_info_node *node = (struct drm_info_node *) m->private; 59 1.5 riastrad struct drm_minor *minor = node->minor; 60 1.5 riastrad struct drm_device *dev = minor->dev; 61 1.5 riastrad struct drm_master *master; 62 1.5 riastrad 63 1.5 riastrad mutex_lock(&dev->master_mutex); 64 1.5 riastrad master = dev->master; 65 1.5 riastrad seq_printf(m, "%s", dev->driver->name); 66 1.5 riastrad if (dev->dev) 67 1.5 riastrad seq_printf(m, " dev=%s", dev_name(dev->dev)); 68 1.5 riastrad if (master && master->unique) 69 1.5 riastrad seq_printf(m, " master=%s", master->unique); 70 1.5 riastrad if (dev->unique) 71 1.5 riastrad seq_printf(m, " unique=%s", dev->unique); 72 1.5 riastrad seq_printf(m, "\n"); 73 1.5 riastrad mutex_unlock(&dev->master_mutex); 74 1.5 riastrad 75 1.5 riastrad return 0; 76 1.5 riastrad } 77 1.5 riastrad 78 1.5 riastrad static int drm_clients_info(struct seq_file *m, void *data) 79 1.5 riastrad { 80 1.5 riastrad struct drm_info_node *node = (struct drm_info_node *) m->private; 81 1.5 riastrad struct drm_device *dev = node->minor->dev; 82 1.5 riastrad struct drm_file *priv; 83 1.5 riastrad kuid_t uid; 84 1.5 riastrad 85 1.5 riastrad seq_printf(m, 86 1.5 riastrad "%20s %5s %3s master a %5s %10s\n", 87 1.5 riastrad "command", 88 1.5 riastrad "pid", 89 1.5 riastrad "dev", 90 1.5 riastrad "uid", 91 1.5 riastrad "magic"); 92 1.5 riastrad 93 1.5 riastrad /* dev->filelist is sorted youngest first, but we want to present 94 1.5 riastrad * oldest first (i.e. kernel, servers, clients), so walk backwardss. 95 1.5 riastrad */ 96 1.5 riastrad mutex_lock(&dev->filelist_mutex); 97 1.5 riastrad list_for_each_entry_reverse(priv, &dev->filelist, lhead) { 98 1.5 riastrad struct task_struct *task; 99 1.5 riastrad 100 1.5 riastrad rcu_read_lock(); /* locks pid_task()->comm */ 101 1.5 riastrad task = pid_task(priv->pid, PIDTYPE_PID); 102 1.5 riastrad uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; 103 1.5 riastrad seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n", 104 1.5 riastrad task ? task->comm : "<unknown>", 105 1.5 riastrad pid_vnr(priv->pid), 106 1.5 riastrad priv->minor->index, 107 1.5 riastrad drm_is_current_master(priv) ? 'y' : 'n', 108 1.5 riastrad priv->authenticated ? 'y' : 'n', 109 1.5 riastrad from_kuid_munged(seq_user_ns(m), uid), 110 1.5 riastrad priv->magic); 111 1.5 riastrad rcu_read_unlock(); 112 1.5 riastrad } 113 1.5 riastrad mutex_unlock(&dev->filelist_mutex); 114 1.5 riastrad return 0; 115 1.5 riastrad } 116 1.5 riastrad 117 1.5 riastrad static int drm_gem_one_name_info(int id, void *ptr, void *data) 118 1.5 riastrad { 119 1.5 riastrad struct drm_gem_object *obj = ptr; 120 1.5 riastrad struct seq_file *m = data; 121 1.5 riastrad 122 1.5 riastrad seq_printf(m, "%6d %8zd %7d %8d\n", 123 1.5 riastrad obj->name, obj->size, 124 1.5 riastrad obj->handle_count, 125 1.5 riastrad kref_read(&obj->refcount)); 126 1.5 riastrad return 0; 127 1.5 riastrad } 128 1.5 riastrad 129 1.5 riastrad static int drm_gem_name_info(struct seq_file *m, void *data) 130 1.5 riastrad { 131 1.5 riastrad struct drm_info_node *node = (struct drm_info_node *) m->private; 132 1.5 riastrad struct drm_device *dev = node->minor->dev; 133 1.5 riastrad 134 1.5 riastrad seq_printf(m, " name size handles refcount\n"); 135 1.5 riastrad 136 1.5 riastrad mutex_lock(&dev->object_name_lock); 137 1.5 riastrad idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); 138 1.5 riastrad mutex_unlock(&dev->object_name_lock); 139 1.5 riastrad 140 1.5 riastrad return 0; 141 1.5 riastrad } 142 1.5 riastrad 143 1.3 riastrad static const struct drm_info_list drm_debugfs_list[] = { 144 1.1 riastrad {"name", drm_name_info, 0}, 145 1.1 riastrad {"clients", drm_clients_info, 0}, 146 1.1 riastrad {"gem_names", drm_gem_name_info, DRIVER_GEM}, 147 1.1 riastrad }; 148 1.1 riastrad #define DRM_DEBUGFS_ENTRIES ARRAY_SIZE(drm_debugfs_list) 149 1.1 riastrad 150 1.1 riastrad 151 1.1 riastrad static int drm_debugfs_open(struct inode *inode, struct file *file) 152 1.1 riastrad { 153 1.1 riastrad struct drm_info_node *node = inode->i_private; 154 1.1 riastrad 155 1.1 riastrad return single_open(file, node->info_ent->show, node); 156 1.1 riastrad } 157 1.1 riastrad 158 1.1 riastrad 159 1.1 riastrad static const struct file_operations drm_debugfs_fops = { 160 1.1 riastrad .owner = THIS_MODULE, 161 1.1 riastrad .open = drm_debugfs_open, 162 1.1 riastrad .read = seq_read, 163 1.1 riastrad .llseek = seq_lseek, 164 1.1 riastrad .release = single_release, 165 1.1 riastrad }; 166 1.1 riastrad 167 1.1 riastrad 168 1.1 riastrad /** 169 1.5 riastrad * drm_debugfs_create_files - Initialize a given set of debugfs files for DRM 170 1.5 riastrad * minor 171 1.5 riastrad * @files: The array of files to create 172 1.5 riastrad * @count: The number of files given 173 1.5 riastrad * @root: DRI debugfs dir entry. 174 1.5 riastrad * @minor: device minor number 175 1.1 riastrad * 176 1.1 riastrad * Create a given set of debugfs files represented by an array of 177 1.5 riastrad * &struct drm_info_list in the given root directory. These files will be removed 178 1.5 riastrad * automatically on drm_debugfs_cleanup(). 179 1.1 riastrad */ 180 1.3 riastrad int drm_debugfs_create_files(const struct drm_info_list *files, int count, 181 1.1 riastrad struct dentry *root, struct drm_minor *minor) 182 1.1 riastrad { 183 1.1 riastrad struct drm_device *dev = minor->dev; 184 1.1 riastrad struct drm_info_node *tmp; 185 1.5 riastrad int i; 186 1.1 riastrad 187 1.1 riastrad for (i = 0; i < count; i++) { 188 1.1 riastrad u32 features = files[i].driver_features; 189 1.1 riastrad 190 1.1 riastrad if (features != 0 && 191 1.1 riastrad (dev->driver->driver_features & features) != features) 192 1.1 riastrad continue; 193 1.1 riastrad 194 1.1 riastrad tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); 195 1.5 riastrad if (tmp == NULL) 196 1.5 riastrad continue; 197 1.1 riastrad 198 1.1 riastrad tmp->minor = minor; 199 1.5 riastrad tmp->dent = debugfs_create_file(files[i].name, 200 1.5 riastrad S_IFREG | S_IRUGO, root, tmp, 201 1.5 riastrad &drm_debugfs_fops); 202 1.1 riastrad tmp->info_ent = &files[i]; 203 1.1 riastrad 204 1.1 riastrad mutex_lock(&minor->debugfs_lock); 205 1.1 riastrad list_add(&tmp->list, &minor->debugfs_list); 206 1.1 riastrad mutex_unlock(&minor->debugfs_lock); 207 1.1 riastrad } 208 1.1 riastrad return 0; 209 1.1 riastrad } 210 1.1 riastrad EXPORT_SYMBOL(drm_debugfs_create_files); 211 1.1 riastrad 212 1.1 riastrad int drm_debugfs_init(struct drm_minor *minor, int minor_id, 213 1.1 riastrad struct dentry *root) 214 1.1 riastrad { 215 1.1 riastrad struct drm_device *dev = minor->dev; 216 1.1 riastrad char name[64]; 217 1.1 riastrad int ret; 218 1.1 riastrad 219 1.1 riastrad INIT_LIST_HEAD(&minor->debugfs_list); 220 1.1 riastrad mutex_init(&minor->debugfs_lock); 221 1.2 christos snprintf(name, sizeof(name), "%d", minor_id); 222 1.1 riastrad minor->debugfs_root = debugfs_create_dir(name, root); 223 1.1 riastrad 224 1.1 riastrad ret = drm_debugfs_create_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, 225 1.1 riastrad minor->debugfs_root, minor); 226 1.1 riastrad if (ret) { 227 1.1 riastrad debugfs_remove(minor->debugfs_root); 228 1.1 riastrad minor->debugfs_root = NULL; 229 1.1 riastrad DRM_ERROR("Failed to create core drm debugfs files\n"); 230 1.1 riastrad return ret; 231 1.1 riastrad } 232 1.1 riastrad 233 1.5 riastrad if (drm_drv_uses_atomic_modeset(dev)) { 234 1.5 riastrad ret = drm_atomic_debugfs_init(minor); 235 1.5 riastrad if (ret) { 236 1.5 riastrad DRM_ERROR("Failed to create atomic debugfs files\n"); 237 1.5 riastrad return ret; 238 1.5 riastrad } 239 1.5 riastrad } 240 1.5 riastrad 241 1.5 riastrad if (drm_core_check_feature(dev, DRIVER_MODESET)) { 242 1.5 riastrad ret = drm_framebuffer_debugfs_init(minor); 243 1.5 riastrad if (ret) { 244 1.5 riastrad DRM_ERROR("Failed to create framebuffer debugfs file\n"); 245 1.5 riastrad return ret; 246 1.5 riastrad } 247 1.5 riastrad 248 1.5 riastrad ret = drm_client_debugfs_init(minor); 249 1.5 riastrad if (ret) { 250 1.5 riastrad DRM_ERROR("Failed to create client debugfs file\n"); 251 1.5 riastrad return ret; 252 1.5 riastrad } 253 1.5 riastrad } 254 1.5 riastrad 255 1.1 riastrad if (dev->driver->debugfs_init) { 256 1.1 riastrad ret = dev->driver->debugfs_init(minor); 257 1.1 riastrad if (ret) { 258 1.1 riastrad DRM_ERROR("DRM: Driver failed to initialize " 259 1.1 riastrad "/sys/kernel/debug/dri.\n"); 260 1.1 riastrad return ret; 261 1.1 riastrad } 262 1.1 riastrad } 263 1.1 riastrad return 0; 264 1.1 riastrad } 265 1.1 riastrad 266 1.1 riastrad 267 1.3 riastrad int drm_debugfs_remove_files(const struct drm_info_list *files, int count, 268 1.1 riastrad struct drm_minor *minor) 269 1.1 riastrad { 270 1.1 riastrad struct list_head *pos, *q; 271 1.1 riastrad struct drm_info_node *tmp; 272 1.1 riastrad int i; 273 1.1 riastrad 274 1.1 riastrad mutex_lock(&minor->debugfs_lock); 275 1.1 riastrad for (i = 0; i < count; i++) { 276 1.1 riastrad list_for_each_safe(pos, q, &minor->debugfs_list) { 277 1.1 riastrad tmp = list_entry(pos, struct drm_info_node, list); 278 1.1 riastrad if (tmp->info_ent == &files[i]) { 279 1.1 riastrad debugfs_remove(tmp->dent); 280 1.1 riastrad list_del(pos); 281 1.1 riastrad kfree(tmp); 282 1.1 riastrad } 283 1.1 riastrad } 284 1.1 riastrad } 285 1.1 riastrad mutex_unlock(&minor->debugfs_lock); 286 1.1 riastrad return 0; 287 1.1 riastrad } 288 1.1 riastrad EXPORT_SYMBOL(drm_debugfs_remove_files); 289 1.1 riastrad 290 1.5 riastrad static void drm_debugfs_remove_all_files(struct drm_minor *minor) 291 1.1 riastrad { 292 1.5 riastrad struct drm_info_node *node, *tmp; 293 1.5 riastrad 294 1.5 riastrad mutex_lock(&minor->debugfs_lock); 295 1.5 riastrad list_for_each_entry_safe(node, tmp, &minor->debugfs_list, list) { 296 1.5 riastrad debugfs_remove(node->dent); 297 1.5 riastrad list_del(&node->list); 298 1.5 riastrad kfree(node); 299 1.5 riastrad } 300 1.5 riastrad mutex_unlock(&minor->debugfs_lock); 301 1.5 riastrad } 302 1.1 riastrad 303 1.5 riastrad void drm_debugfs_cleanup(struct drm_minor *minor) 304 1.5 riastrad { 305 1.1 riastrad if (!minor->debugfs_root) 306 1.5 riastrad return; 307 1.1 riastrad 308 1.5 riastrad drm_debugfs_remove_all_files(minor); 309 1.1 riastrad 310 1.5 riastrad debugfs_remove_recursive(minor->debugfs_root); 311 1.1 riastrad minor->debugfs_root = NULL; 312 1.1 riastrad } 313 1.1 riastrad 314 1.4 riastrad static int connector_show(struct seq_file *m, void *data) 315 1.4 riastrad { 316 1.4 riastrad struct drm_connector *connector = m->private; 317 1.4 riastrad 318 1.5 riastrad seq_printf(m, "%s\n", drm_get_connector_force_name(connector->force)); 319 1.4 riastrad 320 1.4 riastrad return 0; 321 1.4 riastrad } 322 1.4 riastrad 323 1.4 riastrad static int connector_open(struct inode *inode, struct file *file) 324 1.4 riastrad { 325 1.4 riastrad struct drm_connector *dev = inode->i_private; 326 1.4 riastrad 327 1.4 riastrad return single_open(file, connector_show, dev); 328 1.4 riastrad } 329 1.4 riastrad 330 1.4 riastrad static ssize_t connector_write(struct file *file, const char __user *ubuf, 331 1.4 riastrad size_t len, loff_t *offp) 332 1.4 riastrad { 333 1.4 riastrad struct seq_file *m = file->private_data; 334 1.4 riastrad struct drm_connector *connector = m->private; 335 1.4 riastrad char buf[12]; 336 1.4 riastrad 337 1.4 riastrad if (len > sizeof(buf) - 1) 338 1.4 riastrad return -EINVAL; 339 1.4 riastrad 340 1.4 riastrad if (copy_from_user(buf, ubuf, len)) 341 1.4 riastrad return -EFAULT; 342 1.4 riastrad 343 1.4 riastrad buf[len] = '\0'; 344 1.4 riastrad 345 1.4 riastrad if (!strcmp(buf, "on")) 346 1.4 riastrad connector->force = DRM_FORCE_ON; 347 1.4 riastrad else if (!strcmp(buf, "digital")) 348 1.4 riastrad connector->force = DRM_FORCE_ON_DIGITAL; 349 1.4 riastrad else if (!strcmp(buf, "off")) 350 1.4 riastrad connector->force = DRM_FORCE_OFF; 351 1.4 riastrad else if (!strcmp(buf, "unspecified")) 352 1.4 riastrad connector->force = DRM_FORCE_UNSPECIFIED; 353 1.4 riastrad else 354 1.4 riastrad return -EINVAL; 355 1.4 riastrad 356 1.4 riastrad return len; 357 1.4 riastrad } 358 1.4 riastrad 359 1.4 riastrad static int edid_show(struct seq_file *m, void *data) 360 1.4 riastrad { 361 1.4 riastrad struct drm_connector *connector = m->private; 362 1.4 riastrad struct drm_property_blob *edid = connector->edid_blob_ptr; 363 1.4 riastrad 364 1.4 riastrad if (connector->override_edid && edid) 365 1.4 riastrad seq_write(m, edid->data, edid->length); 366 1.4 riastrad 367 1.4 riastrad return 0; 368 1.4 riastrad } 369 1.4 riastrad 370 1.4 riastrad static int edid_open(struct inode *inode, struct file *file) 371 1.4 riastrad { 372 1.4 riastrad struct drm_connector *dev = inode->i_private; 373 1.4 riastrad 374 1.4 riastrad return single_open(file, edid_show, dev); 375 1.4 riastrad } 376 1.4 riastrad 377 1.4 riastrad static ssize_t edid_write(struct file *file, const char __user *ubuf, 378 1.4 riastrad size_t len, loff_t *offp) 379 1.4 riastrad { 380 1.4 riastrad struct seq_file *m = file->private_data; 381 1.4 riastrad struct drm_connector *connector = m->private; 382 1.4 riastrad char *buf; 383 1.4 riastrad struct edid *edid; 384 1.4 riastrad int ret; 385 1.4 riastrad 386 1.4 riastrad buf = memdup_user(ubuf, len); 387 1.4 riastrad if (IS_ERR(buf)) 388 1.4 riastrad return PTR_ERR(buf); 389 1.4 riastrad 390 1.4 riastrad edid = (struct edid *) buf; 391 1.4 riastrad 392 1.4 riastrad if (len == 5 && !strncmp(buf, "reset", 5)) { 393 1.4 riastrad connector->override_edid = false; 394 1.5 riastrad ret = drm_connector_update_edid_property(connector, NULL); 395 1.4 riastrad } else if (len < EDID_LENGTH || 396 1.4 riastrad EDID_LENGTH * (1 + edid->extensions) > len) 397 1.4 riastrad ret = -EINVAL; 398 1.4 riastrad else { 399 1.4 riastrad connector->override_edid = false; 400 1.5 riastrad ret = drm_connector_update_edid_property(connector, edid); 401 1.4 riastrad if (!ret) 402 1.4 riastrad connector->override_edid = true; 403 1.4 riastrad } 404 1.4 riastrad 405 1.4 riastrad kfree(buf); 406 1.4 riastrad 407 1.4 riastrad return (ret) ? ret : len; 408 1.4 riastrad } 409 1.4 riastrad 410 1.4 riastrad static const struct file_operations drm_edid_fops = { 411 1.4 riastrad .owner = THIS_MODULE, 412 1.4 riastrad .open = edid_open, 413 1.4 riastrad .read = seq_read, 414 1.4 riastrad .llseek = seq_lseek, 415 1.4 riastrad .release = single_release, 416 1.4 riastrad .write = edid_write 417 1.4 riastrad }; 418 1.4 riastrad 419 1.4 riastrad 420 1.4 riastrad static const struct file_operations drm_connector_fops = { 421 1.4 riastrad .owner = THIS_MODULE, 422 1.4 riastrad .open = connector_open, 423 1.4 riastrad .read = seq_read, 424 1.4 riastrad .llseek = seq_lseek, 425 1.4 riastrad .release = single_release, 426 1.4 riastrad .write = connector_write 427 1.4 riastrad }; 428 1.4 riastrad 429 1.5 riastrad void drm_debugfs_connector_add(struct drm_connector *connector) 430 1.4 riastrad { 431 1.4 riastrad struct drm_minor *minor = connector->dev->primary; 432 1.5 riastrad struct dentry *root; 433 1.4 riastrad 434 1.4 riastrad if (!minor->debugfs_root) 435 1.5 riastrad return; 436 1.4 riastrad 437 1.4 riastrad root = debugfs_create_dir(connector->name, minor->debugfs_root); 438 1.4 riastrad connector->debugfs_entry = root; 439 1.4 riastrad 440 1.4 riastrad /* force */ 441 1.5 riastrad debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector, 442 1.5 riastrad &drm_connector_fops); 443 1.4 riastrad 444 1.4 riastrad /* edid */ 445 1.5 riastrad debugfs_create_file("edid_override", S_IRUGO | S_IWUSR, root, connector, 446 1.5 riastrad &drm_edid_fops); 447 1.5 riastrad } 448 1.4 riastrad 449 1.5 riastrad void drm_debugfs_connector_remove(struct drm_connector *connector) 450 1.5 riastrad { 451 1.5 riastrad if (!connector->debugfs_entry) 452 1.5 riastrad return; 453 1.4 riastrad 454 1.4 riastrad debugfs_remove_recursive(connector->debugfs_entry); 455 1.5 riastrad 456 1.4 riastrad connector->debugfs_entry = NULL; 457 1.4 riastrad } 458 1.4 riastrad 459 1.5 riastrad void drm_debugfs_crtc_add(struct drm_crtc *crtc) 460 1.4 riastrad { 461 1.5 riastrad struct drm_minor *minor = crtc->dev->primary; 462 1.5 riastrad struct dentry *root; 463 1.5 riastrad char *name; 464 1.5 riastrad 465 1.5 riastrad name = kasprintf(GFP_KERNEL, "crtc-%d", crtc->index); 466 1.5 riastrad if (!name) 467 1.4 riastrad return; 468 1.4 riastrad 469 1.5 riastrad root = debugfs_create_dir(name, minor->debugfs_root); 470 1.5 riastrad kfree(name); 471 1.5 riastrad 472 1.5 riastrad crtc->debugfs_entry = root; 473 1.5 riastrad 474 1.5 riastrad drm_debugfs_crtc_crc_add(crtc); 475 1.5 riastrad } 476 1.4 riastrad 477 1.5 riastrad void drm_debugfs_crtc_remove(struct drm_crtc *crtc) 478 1.5 riastrad { 479 1.5 riastrad debugfs_remove_recursive(crtc->debugfs_entry); 480 1.5 riastrad crtc->debugfs_entry = NULL; 481 1.4 riastrad } 482 1.4 riastrad 483 1.1 riastrad #endif /* CONFIG_DEBUG_FS */ 484