drm: cleanup drm_core_{init,exit}()

Various cleanups to the DRM core initialization and exit handlers:

 - Register chrdev last: Once register_chrdev() returns, open() will
   succeed on the given chrdevs. This is usually not an issue, as no
   chardevs are registered, yet. However, nodes can be created by
   user-space via mknod(2), even though such major/minor combinations are
   unknown to the kernel. Avoid calling into drm_stub_open() in those
   cases.
   Again, drm_stub_open() would just bail out as the inode is unknown,
   but it's really non-obvious if you hack on drm_stub_open().

 - Unify error-paths into just one label. All the error-path helpers can
   be called even though the constructors were not called yet, or failed.
   Hence, just call all cleanups unconditionally.

 - Call into drm_global_release(). This is a no-op, but provides
   debugging helpers in case there're GLOBALS left on module unload. This
   function was unused until now.

 - Use DRM_ERROR() instead of printk(), and also print the error-code on
   failure (even if it is static!).

 - Don't throw away error-codes of register_chrdev()!

 - Don't hardcode -1 as errno. This is just plain wrong.

 - Order exit-handlers in the exact reverse order of initialization
   (except if the order actually matters for syncing-reasons, which is
   not the case here, though).

v2:
 - Call drm_core_exit() directly from the init-error-handler. Requires to
   drop __exit annotation, though.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20160901124837.680-7-dh.herrmann@gmail.com
This commit is contained in:
David Herrmann 2016-09-01 14:48:37 +02:00 committed by Daniel Vetter
parent 82d5e73f6b
commit 2cc107dc5b

View file

@ -820,52 +820,48 @@ static const struct file_operations drm_stub_fops = {
.llseek = noop_llseek, .llseek = noop_llseek,
}; };
static void drm_core_exit(void)
{
unregister_chrdev(DRM_MAJOR, "drm");
debugfs_remove(drm_debugfs_root);
drm_sysfs_destroy();
idr_destroy(&drm_minors_idr);
drm_connector_ida_destroy();
drm_global_release();
}
static int __init drm_core_init(void) static int __init drm_core_init(void)
{ {
int ret = -ENOMEM; int ret;
drm_global_init(); drm_global_init();
drm_connector_ida_init(); drm_connector_ida_init();
idr_init(&drm_minors_idr); idr_init(&drm_minors_idr);
if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
goto err_p1;
ret = drm_sysfs_init(); ret = drm_sysfs_init();
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "DRM: Error creating drm class.\n"); DRM_ERROR("Cannot create DRM class: %d\n", ret);
goto err_p2; goto error;
} }
drm_debugfs_root = debugfs_create_dir("dri", NULL); drm_debugfs_root = debugfs_create_dir("dri", NULL);
if (!drm_debugfs_root) { if (!drm_debugfs_root) {
DRM_ERROR("Cannot create /sys/kernel/debug/dri\n"); ret = -ENOMEM;
ret = -1; DRM_ERROR("Cannot create debugfs-root: %d\n", ret);
goto err_p3; goto error;
} }
ret = register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops);
if (ret < 0)
goto error;
DRM_INFO("Initialized\n"); DRM_INFO("Initialized\n");
return 0; return 0;
err_p3:
drm_sysfs_destroy();
err_p2:
unregister_chrdev(DRM_MAJOR, "drm");
idr_destroy(&drm_minors_idr); error:
err_p1: drm_core_exit();
return ret; return ret;
} }
static void __exit drm_core_exit(void)
{
debugfs_remove(drm_debugfs_root);
drm_sysfs_destroy();
unregister_chrdev(DRM_MAJOR, "drm");
drm_connector_ida_destroy();
idr_destroy(&drm_minors_idr);
}
module_init(drm_core_init); module_init(drm_core_init);
module_exit(drm_core_exit); module_exit(drm_core_exit);