aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2006-06-26 03:27:03 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:32 -0400
commit1c8ce271fe707d26b7bca4e490067fe65694b363 (patch)
tree42fc5fa81161065874b9aa751773d15465a8de9b /drivers/char
parent50ec42edd9784fad6a37b05be03064ea24098db6 (diff)
[PATCH] Detaching fbcon: fix give_up_console()
To allow for detaching fbcon, it must be able to give up the console. However, the function give_up_console() is plain broken. It just sets the entries in the console driver map to NULL, it leaves the vt layer without a console driver, and does not decrement the module reference count. Calling give_up_console() is guaranteed to hang the machine.. To fix this problem, ensure that the virtual consoles are not left dangling without a driver. All systems have a default boot driver (either vgacon or dummycon) which is never unloaded. For those vt's that lost their driver, the default boot driver is reassigned back to them. Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/vt.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index eb27eed48a86..d7ff7fdb6fe3 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -100,6 +100,7 @@
100 100
101 101
102const struct consw *conswitchp; 102const struct consw *conswitchp;
103static struct consw *defcsw; /* default console */
103 104
104/* A bitmap for codes <32. A bit of 1 indicates that the code 105/* A bitmap for codes <32. A bit of 1 indicates that the code
105 * corresponding to that bit number invokes some special action 106 * corresponding to that bit number invokes some special action
@@ -2673,17 +2674,23 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
2673 if (!try_module_get(owner)) 2674 if (!try_module_get(owner))
2674 return -ENODEV; 2675 return -ENODEV;
2675 2676
2676 acquire_console_sem(); 2677 /* save default console, for possible recovery later on */
2678 if (!defcsw)
2679 defcsw = (struct consw *) conswitchp;
2677 2680
2681 acquire_console_sem();
2678 desc = csw->con_startup(); 2682 desc = csw->con_startup();
2683
2679 if (!desc) { 2684 if (!desc) {
2680 release_console_sem(); 2685 release_console_sem();
2681 module_put(owner); 2686 module_put(owner);
2682 return -ENODEV; 2687 return -ENODEV;
2683 } 2688 }
2689
2684 if (deflt) { 2690 if (deflt) {
2685 if (conswitchp) 2691 if (conswitchp)
2686 module_put(conswitchp->owner); 2692 module_put(conswitchp->owner);
2693
2687 __module_get(owner); 2694 __module_get(owner);
2688 conswitchp = csw; 2695 conswitchp = csw;
2689 } 2696 }
@@ -2701,6 +2708,7 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
2701 continue; 2708 continue;
2702 2709
2703 j = i; 2710 j = i;
2711
2704 if (CON_IS_VISIBLE(vc)) { 2712 if (CON_IS_VISIBLE(vc)) {
2705 k = i; 2713 k = i;
2706 save_screen(vc); 2714 save_screen(vc);
@@ -2709,10 +2717,8 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
2709 old_was_color = vc->vc_can_do_color; 2717 old_was_color = vc->vc_can_do_color;
2710 vc->vc_sw->con_deinit(vc); 2718 vc->vc_sw->con_deinit(vc);
2711 vc->vc_origin = (unsigned long)vc->vc_screenbuf; 2719 vc->vc_origin = (unsigned long)vc->vc_screenbuf;
2712 vc->vc_visible_origin = vc->vc_origin;
2713 vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
2714 vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
2715 visual_init(vc, i, 0); 2720 visual_init(vc, i, 0);
2721 set_origin(vc);
2716 update_attr(vc); 2722 update_attr(vc);
2717 2723
2718 /* If the console changed between mono <-> color, then 2724 /* If the console changed between mono <-> color, then
@@ -2741,22 +2747,29 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
2741 printk("to %s\n", desc); 2747 printk("to %s\n", desc);
2742 2748
2743 release_console_sem(); 2749 release_console_sem();
2744
2745 module_put(owner); 2750 module_put(owner);
2746 return 0; 2751 return 0;
2747} 2752}
2748 2753
2749void give_up_console(const struct consw *csw) 2754void give_up_console(const struct consw *csw)
2750{ 2755{
2751 int i; 2756 int i, first = -1, last = -1, deflt = 0;
2752 2757
2753 for(i = 0; i < MAX_NR_CONSOLES; i++) 2758 for (i = 0; i < MAX_NR_CONSOLES; i++)
2754 if (con_driver_map[i] == csw) { 2759 if (con_driver_map[i] == csw) {
2760 if (first == -1)
2761 first = i;
2762 last = i;
2755 module_put(csw->owner); 2763 module_put(csw->owner);
2756 con_driver_map[i] = NULL; 2764 con_driver_map[i] = NULL;
2757 } 2765 }
2758}
2759 2766
2767 if (first != -1 && defcsw) {
2768 if (first == 0 && last == MAX_NR_CONSOLES - 1)
2769 deflt = 1;
2770 take_over_console(defcsw, first, last, deflt);
2771 }
2772}
2760#endif 2773#endif
2761 2774
2762/* 2775/*