summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_debugfs.c')
-rw-r--r--drivers/gpu/drm/drm_debugfs.c162
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;