mfd: AB3100 register access change to abx500 API
[safe/jmp/linux-2.6] / drivers / char / vt.c
index a5af607..7cdb6ee 100644 (file)
 #include <linux/mutex.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
+#include <linux/smp_lock.h>
 #include <linux/tiocl.h>
 #include <linux/kbd_kern.h>
 #include <linux/consolemap.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
-#include <linux/bootmem.h>
 #include <linux/pm.h>
 #include <linux/font.h>
 #include <linux/bitops.h>
@@ -161,6 +161,11 @@ static void set_palette(struct vc_data *vc);
 static int printable;          /* Is console ready for printing? */
 int default_utf8 = true;
 module_param(default_utf8, int, S_IRUGO | S_IWUSR);
+int global_cursor_default = -1;
+module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);
+
+static int cur_default = CUR_DEFAULT;
+module_param(cur_default, int, S_IRUGO | S_IWUSR);
 
 /*
  * ignore_poke: don't unblank the screen when things are typed.  This is
@@ -172,8 +177,9 @@ int do_poke_blanked_console;
 int console_blanked;
 
 static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
-static int blankinterval = 10*60*HZ;
 static int vesa_off_interval;
+static int blankinterval = 10*60;
+core_param(consoleblank, blankinterval, int, 0444);
 
 static DECLARE_WORK(console_work, console_callback);
 
@@ -181,12 +187,10 @@ static DECLARE_WORK(console_work, console_callback);
  * fg_console is the current virtual console,
  * last_console is the last used one,
  * want_console is the console we want to switch to,
- * kmsg_redirect is the console for kernel messages,
  */
 int fg_console;
 int last_console;
 int want_console = -1;
-int kmsg_redirect;
 
 /*
  * For each existing display, we have a pointer to console currently visible
@@ -251,7 +255,6 @@ static void notify_update(struct vc_data *vc)
        struct vt_notifier_param param = { .vc = vc };
        atomic_notifier_call_chain(&vt_notifier_list, VT_UPDATE, &param);
 }
-
 /*
  *     Low-Level Functions
  */
@@ -769,15 +772,20 @@ int vc_allocate(unsigned int currcons)    /* return 0 on success */
            visual_init(vc, currcons, 1);
            if (!*vc->vc_uni_pagedir_loc)
                con_set_default_unimap(vc);
-           if (!vc->vc_kmalloced)
-               vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+           vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
            if (!vc->vc_screenbuf) {
                kfree(vc);
                vc_cons[currcons].d = NULL;
                return -ENOMEM;
            }
-           vc->vc_kmalloced = 1;
+
+           /* If no drivers have overridden us and the user didn't pass a
+              boot option, default to displaying the cursor */
+           if (global_cursor_default == -1)
+                   global_cursor_default = 1;
+
            vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
+           vcs_make_sysfs(currcons);
            atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
        }
        return 0;
@@ -813,14 +821,14 @@ static inline int resize_screen(struct vc_data *vc, int width, int height,
  *
  *     Resize a virtual console, clipping according to the actual constraints.
  *     If the caller passes a tty structure then update the termios winsize
- *     information and perform any neccessary signal handling.
+ *     information and perform any necessary signal handling.
  *
  *     Caller must hold the console semaphore. Takes the termios mutex and
  *     ctrl_lock of the tty IFF a tty is passed.
  */
 
-static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
-               struct vc_data *vc, unsigned int cols, unsigned int lines)
+static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
+                               unsigned int cols, unsigned int lines)
 {
        unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
        unsigned int old_cols, old_rows, old_row_size, old_screen_size;
@@ -911,10 +919,8 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
        if (new_scr_end > new_origin)
                scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
                            new_scr_end - new_origin);
-       if (vc->vc_kmalloced)
-               kfree(vc->vc_screenbuf);
+       kfree(vc->vc_screenbuf);
        vc->vc_screenbuf = newscreen;
-       vc->vc_kmalloced = 1;
        vc->vc_screenbuf_size = new_screen_size;
        set_origin(vc);
 
@@ -932,11 +938,12 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
                ws.ws_row = vc->vc_rows;
                ws.ws_col = vc->vc_cols;
                ws.ws_ypixel = vc->vc_scan_lines;
-               tty_do_resize(tty, real_tty, &ws);
+               tty_do_resize(tty, &ws);
        }
 
        if (CON_IS_VISIBLE(vc))
                update_screen(vc);
+       vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
        return err;
 }
 
@@ -954,13 +961,12 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
 
 int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
 {
-       return vc_do_resize(vc->vc_tty, vc->vc_tty, vc, cols, rows);
+       return vc_do_resize(vc->vc_tty, vc, cols, rows);
 }
 
 /**
  *     vt_resize               -       resize a VT
  *     @tty: tty to resize
- *     @real_tty: tty if a pty/tty pair
  *     @ws: winsize attributes
  *
  *     Resize a virtual terminal. This is called by the tty layer as we
@@ -970,15 +976,13 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
  *     Takes the console sem and the called methods then take the tty
  *     termios_mutex and the tty ctrl_lock in that order.
  */
-
-int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty,
-       struct winsize *ws)
+static int vt_resize(struct tty_struct *tty, struct winsize *ws)
 {
        struct vc_data *vc = tty->driver_data;
        int ret;
 
        acquire_console_sem();
-       ret = vc_do_resize(tty, real_tty, vc, ws->ws_col, ws->ws_row);
+       ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row);
        release_console_sem();
        return ret;
 }
@@ -990,12 +994,13 @@ void vc_deallocate(unsigned int currcons)
        if (vc_cons_allocated(currcons)) {
                struct vc_data *vc = vc_cons[currcons].d;
                struct vt_notifier_param param = { .vc = vc };
+
                atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
+               vcs_remove_sysfs(currcons);
                vc->vc_sw->con_deinit(vc);
                put_pid(vc->vt_pid);
                module_put(vc->vc_sw->owner);
-               if (vc->vc_kmalloced)
-                       kfree(vc->vc_screenbuf);
+               kfree(vc->vc_screenbuf);
                if (currcons >= MIN_NR_CONSOLES)
                        kfree(vc);
                vc_cons[currcons].d = NULL;
@@ -1486,7 +1491,7 @@ static void setterm_command(struct vc_data *vc)
                        update_attr(vc);
                        break;
                case 9: /* set blanking interval */
-                       blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
+                       blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60;
                        poke_blanked_console();
                        break;
                case 10: /* set bell frequency in Hz */
@@ -1620,7 +1625,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
        vc->vc_decscnm          = 0;
        vc->vc_decom            = 0;
        vc->vc_decawm           = 1;
-       vc->vc_deccm            = 1;
+       vc->vc_deccm            = global_cursor_default;
        vc->vc_decim            = 0;
 
        set_kbd(vc, decarm);
@@ -1634,7 +1639,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
        /* do not do set_leds here because this causes an endless tasklet loop
           when the keyboard hasn't been initialized yet */
 
-       vc->vc_cursor_type = CUR_DEFAULT;
+       vc->vc_cursor_type = cur_default;
        vc->vc_complement_mask = vc->vc_s_complement_mask;
 
        default_attr(vc);
@@ -1836,7 +1841,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                                if (vc->vc_par[0])
                                        vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);
                                else
-                                       vc->vc_cursor_type = CUR_DEFAULT;
+                                       vc->vc_cursor_type = cur_default;
                                return;
                        }
                        break;
@@ -2114,8 +2119,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
        uint8_t inverse;
        uint8_t width;
        u16 himask, charmask;
-       const unsigned char *orig_buf = NULL;
-       int orig_count;
 
        if (in_interrupt())
                return count;
@@ -2133,16 +2136,10 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
        currcons = vc->vc_num;
        if (!vc_cons_allocated(currcons)) {
            /* could this happen? */
-           static int error = 0;
-           if (!error) {
-               error = 1;
-               printk("con_write: tty %d not allocated\n", currcons+1);
-           }
+               printk_once("con_write: tty %d not allocated\n", currcons+1);
            release_console_sem();
            return 0;
        }
-       orig_buf = buf;
-       orig_count = count;
 
        himask = vc->vc_hi_font_mask;
        charmask = himask ? 0x1ff : 0xff;
@@ -2434,6 +2431,37 @@ struct tty_driver *console_driver;
 
 #ifdef CONFIG_VT_CONSOLE
 
+/**
+ * vt_kmsg_redirect() - Sets/gets the kernel message console
+ * @new:       The new virtual terminal number or -1 if the console should stay
+ *             unchanged
+ *
+ * By default, the kernel messages are always printed on the current virtual
+ * console. However, the user may modify that default with the
+ * TIOCL_SETKMSGREDIRECT ioctl call.
+ *
+ * This function sets the kernel message console to be @new. It returns the old
+ * virtual console number. The virtual terminal number 0 (both as parameter and
+ * return value) means no redirection (i.e. always printed on the currently
+ * active console).
+ *
+ * The parameter -1 means that only the current console is returned, but the
+ * value is not modified. You may use the macro vt_get_kmsg_redirect() in that
+ * case to make the code more understandable.
+ *
+ * When the kernel is compiled without CONFIG_VT_CONSOLE, this function ignores
+ * the parameter and always returns 0.
+ */
+int vt_kmsg_redirect(int new)
+{
+       static int kmsg_con;
+
+       if (new != -1)
+               return xchg(&kmsg_con, new);
+       else
+               return kmsg_con;
+}
+
 /*
  *     Console on virtual terminal
  *
@@ -2448,6 +2476,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        const ushort *start;
        ushort cnt = 0;
        ushort myx;
+       int kmsg_console;
 
        /* console busy or not yet initialized */
        if (!printable)
@@ -2455,8 +2484,9 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        if (!spin_trylock(&printing_lock))
                return;
 
-       if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
-               vc = vc_cons[kmsg_redirect - 1].d;
+       kmsg_console = vt_get_kmsg_redirect();
+       if (kmsg_console && vc_cons_allocated(kmsg_console - 1))
+               vc = vc_cons[kmsg_console - 1].d;
 
        /* read `x' only after setting currcons properly (otherwise
           the `x' macro will read the x of the foreground console). */
@@ -2613,7 +2643,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        ret = set_vesa_blanking(p);
                        break;
                case TIOCL_GETKMSGREDIRECT:
-                       data = kmsg_redirect;
+                       data = vt_get_kmsg_redirect();
                        ret = __put_user(data, p);
                        break;
                case TIOCL_SETKMSGREDIRECT:
@@ -2623,7 +2653,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                                if (get_user(data, p+1))
                                        ret = -EFAULT;
                                else
-                                       kmsg_redirect = data;
+                                       vt_kmsg_redirect(data);
                        }
                        break;
                case TIOCL_GETFGCONSOLE:
@@ -2679,7 +2709,7 @@ static int con_write_room(struct tty_struct *tty)
 {
        if (tty->stopped)
                return 0;
-       return 4096;            /* No limit, really; we're not buffering */
+       return 32768;           /* No limit, really; we're not buffering */
 }
 
 static int con_chars_in_buffer(struct tty_struct *tty)
@@ -2778,7 +2808,6 @@ static int con_open(struct tty_struct *tty, struct file *filp)
                                tty->termios->c_iflag |= IUTF8;
                        else
                                tty->termios->c_iflag &= ~IUTF8;
-                       vcs_make_sysfs(tty);
                        release_console_sem();
                        return ret;
                }
@@ -2798,7 +2827,6 @@ static void con_shutdown(struct tty_struct *tty)
        BUG_ON(vc == NULL);
        acquire_console_sem();
        vc->vc_tty = NULL;
-       vcs_remove_sysfs(tty);
        release_console_sem();
        tty_shutdown(tty);
 }
@@ -2874,18 +2902,14 @@ static int __init con_init(void)
 
        if (blankinterval) {
                blank_state = blank_normal_wait;
-               mod_timer(&console_timer, jiffies + blankinterval);
+               mod_timer(&console_timer, jiffies + (blankinterval * HZ));
        }
 
-       /*
-        * kmalloc is not running yet - we use the bootmem allocator.
-        */
        for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
-               vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data));
+               vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
                INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
                visual_init(vc, currcons, 1);
-               vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size);
-               vc->vc_kmalloced = 0;
+               vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
                vc_init(vc, vc->vc_rows, vc->vc_cols,
                        currcons || !vc->vc_sw->con_save_screen);
        }
@@ -2920,6 +2944,9 @@ static const struct tty_operations con_ops = {
        .flush_chars = con_flush_chars,
        .chars_in_buffer = con_chars_in_buffer,
        .ioctl = vt_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = vt_compat_ioctl,
+#endif
        .stop = con_stop,
        .start = con_start,
        .throttle = con_throttle,
@@ -2958,9 +2985,6 @@ int __init vty_init(const struct file_operations *console_fops)
                panic("Couldn't register console driver\n");
        kbd_init();
        console_map_init();
-#ifdef CONFIG_PROM_CONSOLE
-       prom_con_init();
-#endif
 #ifdef CONFIG_MDA_CONSOLE
        mda_console_init();
 #endif
@@ -2968,7 +2992,6 @@ int __init vty_init(const struct file_operations *console_fops)
 }
 
 #ifndef VT_SINGLE_DRIVER
-#include <linux/device.h>
 
 static struct class *vtconsole_class;
 
@@ -3651,6 +3674,7 @@ void do_blank_screen(int entering_gfx)
                blank_state = blank_vesa_wait;
                mod_timer(&console_timer, jiffies + vesa_off_interval);
        }
+       vt_event_post(VT_EVENT_BLANK, vc->vc_num, vc->vc_num);
 }
 EXPORT_SYMBOL(do_blank_screen);
 
@@ -3683,7 +3707,7 @@ void do_unblank_screen(int leaving_gfx)
                return; /* but leave console_blanked != 0 */
 
        if (blankinterval) {
-               mod_timer(&console_timer, jiffies + blankinterval);
+               mod_timer(&console_timer, jiffies + (blankinterval * HZ));
                blank_state = blank_normal_wait;
        }
 
@@ -3695,6 +3719,7 @@ void do_unblank_screen(int leaving_gfx)
                console_blank_hook(0);
        set_palette(vc);
        set_cursor(vc);
+       vt_event_post(VT_EVENT_UNBLANK, vc->vc_num, vc->vc_num);
 }
 EXPORT_SYMBOL(do_unblank_screen);
 
@@ -3717,7 +3742,7 @@ void unblank_screen(void)
 static void blank_screen_t(unsigned long dummy)
 {
        if (unlikely(!keventd_up())) {
-               mod_timer(&console_timer, jiffies + blankinterval);
+               mod_timer(&console_timer, jiffies + (blankinterval * HZ));
                return;
        }
        blank_timer_expired = 1;
@@ -3747,7 +3772,7 @@ void poke_blanked_console(void)
        if (console_blanked)
                unblank_screen();
        else if (blankinterval) {
-               mod_timer(&console_timer, jiffies + blankinterval);
+               mod_timer(&console_timer, jiffies + (blankinterval * HZ));
                blank_state = blank_normal_wait;
        }
 }
@@ -3942,13 +3967,9 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
        font.charcount = op->charcount;
        font.height = op->height;
        font.width = op->width;
-       font.data = kmalloc(size, GFP_KERNEL);
-       if (!font.data)
-               return -ENOMEM;
-       if (copy_from_user(font.data, op->data, size)) {
-               kfree(font.data);
-               return -EFAULT;
-       }
+       font.data = memdup_user(op->data, size);
+       if (IS_ERR(font.data))
+               return PTR_ERR(font.data);
        acquire_console_sem();
        if (vc->vc_sw->con_font_set)
                rc = vc->vc_sw->con_font_set(vc, &font, op->flags);
@@ -4091,6 +4112,7 @@ EXPORT_SYMBOL(fg_console);
 EXPORT_SYMBOL(console_blank_hook);
 EXPORT_SYMBOL(console_blanked);
 EXPORT_SYMBOL(vc_cons);
+EXPORT_SYMBOL(global_cursor_default);
 #ifndef VT_SINGLE_DRIVER
 EXPORT_SYMBOL(take_over_console);
 EXPORT_SYMBOL(give_up_console);