aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-06-05 10:29:56 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-06-06 16:19:32 -0400
commitd9c660e750fdf982e1e2bdd0e76c1e6c4db4217b (patch)
tree60a016b9ecc5964759a22f8967b75c872e36d06d
parent249f7b3e1383d6889889927351b7b018532d2ca1 (diff)
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: David Herrmann <dh.herrmann@gmail.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/tty/vt/vt.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index ea600f482eeb..5077fe87324d 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3573,17 +3573,20 @@ err:
3573 */ 3573 */
3574int do_unregister_con_driver(const struct consw *csw) 3574int do_unregister_con_driver(const struct consw *csw)
3575{ 3575{
3576 int i, retval = -ENODEV; 3576 int i;
3577 3577
3578 /* cannot unregister a bound driver */ 3578 /* cannot unregister a bound driver */
3579 if (con_is_bound(csw)) 3579 if (con_is_bound(csw))
3580 goto err; 3580 return -EBUSY;
3581
3582 if (csw == conswitchp)
3583 return -EINVAL;
3581 3584
3582 for (i = 0; i < MAX_NR_CON_DRIVER; i++) { 3585 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
3583 struct con_driver *con_driver = &registered_con_driver[i]; 3586 struct con_driver *con_driver = &registered_con_driver[i];
3584 3587
3585 if (con_driver->con == csw && 3588 if (con_driver->con == csw &&
3586 con_driver->flag & CON_DRIVER_FLAG_MODULE) { 3589 con_driver->flag & CON_DRIVER_FLAG_INIT) {
3587 vtconsole_deinit_device(con_driver); 3590 vtconsole_deinit_device(con_driver);
3588 device_destroy(vtconsole_class, 3591 device_destroy(vtconsole_class,
3589 MKDEV(0, con_driver->node)); 3592 MKDEV(0, con_driver->node));
@@ -3594,12 +3597,11 @@ int do_unregister_con_driver(const struct consw *csw)
3594 con_driver->flag = 0; 3597 con_driver->flag = 0;
3595 con_driver->first = 0; 3598 con_driver->first = 0;
3596 con_driver->last = 0; 3599 con_driver->last = 0;
3597 retval = 0; 3600 return 0;
3598 break;
3599 } 3601 }
3600 } 3602 }
3601err: 3603
3602 return retval; 3604 return -ENODEV;
3603} 3605}
3604EXPORT_SYMBOL_GPL(do_unregister_con_driver); 3606EXPORT_SYMBOL_GPL(do_unregister_con_driver);
3605 3607