Commit d9c660e7 authored by Daniel Vetter's avatar Daniel Vetter

vt: Fix up unregistration of vt drivers

A bunch of issues:
- We should not kick out the default console (which is tracked in
  conswitchp), so check for that.
- Add better error codes so callers can differentiate between "something
  went wrong" and "your driver isn't registered already". i915 needs
  that so it doesn't fall over when reloading the driver and hence
  vga_con is already unregistered.
- There's a mess with the driver flags: What we need to check for is
  that the driver isn't used any more, i.e. unbound completely (FLAG_INIT).
  And not whether it's the boot console or not (which is the only one
  which doesn't have FLAG_MODULE). Otherwise there's no way to kick
  out the boot console, which i915 wants to do to prevent havoc with
  vga_con interferring (which tends to hang machines).

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.cz>
Reviewed-by: default avatarDavid Herrmann <dh.herrmann@gmail.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 249f7b3e
...@@ -3573,17 +3573,20 @@ static int do_register_con_driver(const struct consw *csw, int first, int last) ...@@ -3573,17 +3573,20 @@ static int do_register_con_driver(const struct consw *csw, int first, int last)
*/ */
int do_unregister_con_driver(const struct consw *csw) int do_unregister_con_driver(const struct consw *csw)
{ {
int i, retval = -ENODEV; int i;
/* cannot unregister a bound driver */ /* cannot unregister a bound driver */
if (con_is_bound(csw)) if (con_is_bound(csw))
goto err; return -EBUSY;
if (csw == conswitchp)
return -EINVAL;
for (i = 0; i < MAX_NR_CON_DRIVER; i++) { for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
struct con_driver *con_driver = &registered_con_driver[i]; struct con_driver *con_driver = &registered_con_driver[i];
if (con_driver->con == csw && if (con_driver->con == csw &&
con_driver->flag & CON_DRIVER_FLAG_MODULE) { con_driver->flag & CON_DRIVER_FLAG_INIT) {
vtconsole_deinit_device(con_driver); vtconsole_deinit_device(con_driver);
device_destroy(vtconsole_class, device_destroy(vtconsole_class,
MKDEV(0, con_driver->node)); MKDEV(0, con_driver->node));
...@@ -3594,12 +3597,11 @@ int do_unregister_con_driver(const struct consw *csw) ...@@ -3594,12 +3597,11 @@ int do_unregister_con_driver(const struct consw *csw)
con_driver->flag = 0; con_driver->flag = 0;
con_driver->first = 0; con_driver->first = 0;
con_driver->last = 0; con_driver->last = 0;
retval = 0; return 0;
break;
} }
} }
err:
return retval; return -ENODEV;
} }
EXPORT_SYMBOL_GPL(do_unregister_con_driver); EXPORT_SYMBOL_GPL(do_unregister_con_driver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment