diff options
Diffstat (limited to 'drivers/gpu/drm/drm_debugfs.c')
-rw-r--r-- | drivers/gpu/drm/drm_debugfs.c | 162 |
1 files changed, 73 insertions, 89 deletions
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 2de43ff3ce0a..34c7d1a580e3 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -150,6 +150,9 @@ static int drm_debugfs_open(struct inode *inode, struct file *file) { struct drm_info_node *node = inode->i_private; + if (!device_is_registered(node->minor->kdev)) + return -ENODEV; + return single_open(file, node->info_ent->show, node); } @@ -157,6 +160,10 @@ static int drm_debugfs_entry_open(struct inode *inode, struct file *file) { struct drm_debugfs_entry *entry = inode->i_private; struct drm_debugfs_info *node = &entry->file; + struct drm_minor *minor = entry->dev->primary ?: entry->dev->accel; + + if (!device_is_registered(minor->kdev)) + return -ENODEV; return single_open(file, node->show, entry); } @@ -227,7 +234,7 @@ EXPORT_SYMBOL(drm_debugfs_gpuva_info); * * Create a given set of debugfs files represented by an array of * &struct drm_info_list in the given root directory. These files will be removed - * automatically on drm_debugfs_cleanup(). + * automatically on drm_debugfs_dev_fini(). */ void drm_debugfs_create_files(const struct drm_info_list *files, int count, struct dentry *root, struct drm_minor *minor) @@ -242,7 +249,7 @@ void drm_debugfs_create_files(const struct drm_info_list *files, int count, if (features && !drm_core_check_all_features(dev, features)) continue; - tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); + tmp = drmm_kzalloc(dev, sizeof(*tmp), GFP_KERNEL); if (tmp == NULL) continue; @@ -251,111 +258,89 @@ void drm_debugfs_create_files(const struct drm_info_list *files, int count, 0444, root, tmp, &drm_debugfs_fops); tmp->info_ent = &files[i]; - - mutex_lock(&minor->debugfs_lock); - list_add(&tmp->list, &minor->debugfs_list); - mutex_unlock(&minor->debugfs_lock); } } EXPORT_SYMBOL(drm_debugfs_create_files); -int drm_debugfs_init(struct drm_minor *minor, int minor_id, - struct dentry *root) +int drm_debugfs_remove_files(const struct drm_info_list *files, int count, + struct dentry *root, struct drm_minor *minor) { - struct drm_device *dev = minor->dev; - struct drm_debugfs_entry *entry, *tmp; - char name[64]; - - INIT_LIST_HEAD(&minor->debugfs_list); - mutex_init(&minor->debugfs_lock); - sprintf(name, "%d", minor_id); - minor->debugfs_root = debugfs_create_dir(name, root); - - drm_debugfs_add_files(minor->dev, drm_debugfs_list, DRM_DEBUGFS_ENTRIES); - - if (drm_drv_uses_atomic_modeset(dev)) { - drm_atomic_debugfs_init(minor); - drm_bridge_debugfs_init(minor); - } - - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - drm_framebuffer_debugfs_init(minor); + int i; - drm_client_debugfs_init(minor); - } + for (i = 0; i < count; i++) { + struct dentry *dent = debugfs_lookup(files[i].name, root); - if (dev->driver->debugfs_init) - dev->driver->debugfs_init(minor); + if (!dent) + continue; - list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) { - debugfs_create_file(entry->file.name, 0444, - minor->debugfs_root, entry, &drm_debugfs_entry_fops); - list_del(&entry->list); + drmm_kfree(minor->dev, d_inode(dent)->i_private); + debugfs_remove(dent); } - return 0; } +EXPORT_SYMBOL(drm_debugfs_remove_files); -void drm_debugfs_late_register(struct drm_device *dev) +/** + * drm_debugfs_dev_init - create debugfs directory for the device + * @dev: the device which we want to create the directory for + * @root: the parent directory depending on the device type + * + * Creates the debugfs directory for the device under the given root directory. + */ +void drm_debugfs_dev_init(struct drm_device *dev, struct dentry *root) { - struct drm_minor *minor = dev->primary; - struct drm_debugfs_entry *entry, *tmp; - - if (!minor) - return; - - list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) { - debugfs_create_file(entry->file.name, 0444, - minor->debugfs_root, entry, &drm_debugfs_entry_fops); - list_del(&entry->list); - } + dev->debugfs_root = debugfs_create_dir(dev->unique, root); } -int drm_debugfs_remove_files(const struct drm_info_list *files, int count, - struct drm_minor *minor) +/** + * drm_debugfs_dev_fini - cleanup debugfs directory + * @dev: the device to cleanup the debugfs stuff + * + * Remove the debugfs directory, might be called multiple times. + */ +void drm_debugfs_dev_fini(struct drm_device *dev) { - struct list_head *pos, *q; - struct drm_info_node *tmp; - int i; - - mutex_lock(&minor->debugfs_lock); - for (i = 0; i < count; i++) { - list_for_each_safe(pos, q, &minor->debugfs_list) { - tmp = list_entry(pos, struct drm_info_node, list); - if (tmp->info_ent == &files[i]) { - debugfs_remove(tmp->dent); - list_del(pos); - kfree(tmp); - } - } - } - mutex_unlock(&minor->debugfs_lock); - return 0; + debugfs_remove_recursive(dev->debugfs_root); + dev->debugfs_root = NULL; } -EXPORT_SYMBOL(drm_debugfs_remove_files); -static void drm_debugfs_remove_all_files(struct drm_minor *minor) +void drm_debugfs_dev_register(struct drm_device *dev) { - struct drm_info_node *node, *tmp; + drm_debugfs_add_files(dev, drm_debugfs_list, DRM_DEBUGFS_ENTRIES); - mutex_lock(&minor->debugfs_lock); - list_for_each_entry_safe(node, tmp, &minor->debugfs_list, list) { - debugfs_remove(node->dent); - list_del(&node->list); - kfree(node); + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + drm_framebuffer_debugfs_init(dev); + drm_client_debugfs_init(dev); + } + if (drm_drv_uses_atomic_modeset(dev)) { + drm_atomic_debugfs_init(dev); + drm_bridge_debugfs_init(dev); } - mutex_unlock(&minor->debugfs_lock); } -void drm_debugfs_cleanup(struct drm_minor *minor) +int drm_debugfs_register(struct drm_minor *minor, int minor_id, + struct dentry *root) { - if (!minor->debugfs_root) - return; + struct drm_device *dev = minor->dev; + char name[64]; + + sprintf(name, "%d", minor_id); + minor->debugfs_symlink = debugfs_create_symlink(name, root, + dev->unique); - drm_debugfs_remove_all_files(minor); + /* TODO: Only for compatibility with drivers */ + minor->debugfs_root = dev->debugfs_root; - debugfs_remove_recursive(minor->debugfs_root); - minor->debugfs_root = NULL; + if (dev->driver->debugfs_init && dev->render != minor) + dev->driver->debugfs_init(minor); + + return 0; +} + +void drm_debugfs_unregister(struct drm_minor *minor) +{ + debugfs_remove(minor->debugfs_symlink); + minor->debugfs_symlink = NULL; } /** @@ -381,9 +366,8 @@ void drm_debugfs_add_file(struct drm_device *dev, const char *name, entry->file.data = data; entry->dev = dev; - mutex_lock(&dev->debugfs_mutex); - list_add(&entry->list, &dev->debugfs_list); - mutex_unlock(&dev->debugfs_mutex); + debugfs_create_file(name, 0444, dev->debugfs_root, entry, + &drm_debugfs_entry_fops); } EXPORT_SYMBOL(drm_debugfs_add_file); @@ -540,13 +524,13 @@ static const struct file_operations drm_connector_fops = { void drm_debugfs_connector_add(struct drm_connector *connector) { - struct drm_minor *minor = connector->dev->primary; + struct drm_device *dev = connector->dev; struct dentry *root; - if (!minor->debugfs_root) + if (!dev->debugfs_root) return; - root = debugfs_create_dir(connector->name, minor->debugfs_root); + root = debugfs_create_dir(connector->name, dev->debugfs_root); connector->debugfs_entry = root; /* force */ @@ -581,7 +565,7 @@ void drm_debugfs_connector_remove(struct drm_connector *connector) void drm_debugfs_crtc_add(struct drm_crtc *crtc) { - struct drm_minor *minor = crtc->dev->primary; + struct drm_device *dev = crtc->dev; struct dentry *root; char *name; @@ -589,7 +573,7 @@ void drm_debugfs_crtc_add(struct drm_crtc *crtc) if (!name) return; - root = debugfs_create_dir(name, minor->debugfs_root); + root = debugfs_create_dir(name, dev->debugfs_root); kfree(name); crtc->debugfs_entry = root; |