]> Pileus Git - ~andy/linux/blobdiff - drivers/char/vt.c
Merge branch 'for-linus' of git://neil.brown.name/md
[~andy/linux] / drivers / char / vt.c
index 44f03ddd8871ae1d85940c26d850bbbd2537990d..c734f9b1263a7d020550f930e3619fb0f7759d80 100644 (file)
 #include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/kdb.h>
+#include <linux/ctype.h>
 
 #define MAX_NR_CON_DRIVER 16
 
@@ -286,8 +287,12 @@ static inline unsigned short *screenpos(struct vc_data *vc, int offset, int view
        return p;
 }
 
+/* Called  from the keyboard irq path.. */
 static inline void scrolldelta(int lines)
 {
+       /* FIXME */
+       /* scrolldelta needs some kind of consistency lock, but the BKL was
+          and still is not protecting versus the scheduled back end */
        scrollback_delta += lines;
        schedule_console_callback();
 }
@@ -704,7 +709,10 @@ void redraw_screen(struct vc_data *vc, int is_switch)
                        update_attr(vc);
                        clear_buffer_attributes(vc);
                }
-               if (update && vc->vc_mode != KD_GRAPHICS)
+
+               /* Forcibly update if we're panicing */
+               if ((update && vc->vc_mode != KD_GRAPHICS) ||
+                   vt_force_oops_output(vc))
                        do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
        }
        set_cursor(vc);
@@ -742,6 +750,7 @@ static void visual_init(struct vc_data *vc, int num, int init)
        vc->vc_hi_font_mask = 0;
        vc->vc_complement_mask = 0;
        vc->vc_can_do_color = 0;
+       vc->vc_panic_force_write = false;
        vc->vc_sw->con_init(vc, init);
        if (!vc->vc_complement_mask)
                vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
@@ -774,6 +783,7 @@ int vc_allocate(unsigned int currcons)      /* return 0 on success */
            if (!vc)
                return -ENOMEM;
            vc_cons[currcons].d = vc;
+           tty_port_init(&vc->port);
            INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
            visual_init(vc, currcons, 1);
            if (!*vc->vc_uni_pagedir_loc)
@@ -963,12 +973,12 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
  *     Resize a virtual console as seen from the console end of things. We
  *     use the common vc_do_resize methods to update the structures. The
  *     caller must hold the console sem to protect console internals and
- *     vc->vc_tty
+ *     vc->port.tty
  */
 
 int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
 {
-       return vc_do_resize(vc->vc_tty, vc, cols, rows);
+       return vc_do_resize(vc->port.tty, vc, cols, rows);
 }
 
 /**
@@ -1796,8 +1806,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                        vc->vc_state = ESnormal;
                return;
        case ESpalette:
-               if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
-                       vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0');
+               if (isxdigit(c)) {
+                       vc->vc_par[vc->vc_npar++] = hex_to_bin(c);
                        if (vc->vc_npar == 7) {
                                int i = vc->vc_par[0] * 3, j = 1;
                                vc->vc_palette[i] = 16 * vc->vc_par[j++];
@@ -2505,7 +2515,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
                goto quit;
        }
 
-       if (vc->vc_mode != KD_TEXT)
+       if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
                goto quit;
 
        /* undraw cursor first */
@@ -2611,8 +2621,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                return -EFAULT;
        ret = 0;
 
-       lock_kernel();
-
        switch (type)
        {
                case TIOCL_SETSEL:
@@ -2687,7 +2695,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        ret = -EINVAL;
                        break;
        }
-       unlock_kernel();
        return ret;
 }
 
@@ -2800,12 +2807,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
                        struct vc_data *vc = vc_cons[currcons].d;
 
                        /* Still being freed */
-                       if (vc->vc_tty) {
+                       if (vc->port.tty) {
                                release_console_sem();
                                return -ERESTARTSYS;
                        }
                        tty->driver_data = vc;
-                       vc->vc_tty = tty;
+                       vc->port.tty = tty;
 
                        if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
                                tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
@@ -2833,7 +2840,7 @@ static void con_shutdown(struct tty_struct *tty)
        struct vc_data *vc = tty->driver_data;
        BUG_ON(vc == NULL);
        acquire_console_sem();
-       vc->vc_tty = NULL;
+       vc->port.tty = NULL;
        release_console_sem();
        tty_shutdown(tty);
 }
@@ -2915,6 +2922,7 @@ static int __init con_init(void)
        for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
                vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
                INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
+               tty_port_init(&vc->port);
                visual_init(vc, currcons, 1);
                vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
                vc_init(vc, vc->vc_rows, vc->vc_cols,
@@ -3783,7 +3791,8 @@ void do_unblank_screen(int leaving_gfx)
                return;
        }
        vc = vc_cons[fg_console].d;
-       if (vc->vc_mode != KD_TEXT)
+       /* Try to unblank in oops case too */
+       if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
                return; /* but leave console_blanked != 0 */
 
        if (blankinterval) {
@@ -3792,7 +3801,7 @@ void do_unblank_screen(int leaving_gfx)
        }
 
        console_blanked = 0;
-       if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
+       if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc))
                /* Low-level driver cannot restore -> do it ourselves */
                update_screen(vc);
        if (console_blank_hook)