vt: clear selection before resizing
[pandora-kernel.git] / drivers / tty / vt / vt.c
index e716839..1c469ad 100644 (file)
@@ -499,6 +499,7 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
 #endif
        if (DO_UPDATE(vc))
                do_update_region(vc, (unsigned long) p, count);
+       notify_update(vc);
 }
 
 /* used by selection: complement pointer position */
@@ -515,6 +516,7 @@ void complement_pos(struct vc_data *vc, int offset)
                scr_writew(old, screenpos(vc, old_offset, 1));
                if (DO_UPDATE(vc))
                        vc->vc_sw->con_putc(vc, old, oldy, oldx);
+               notify_update(vc);
        }
 
        old_offset = offset;
@@ -532,8 +534,8 @@ void complement_pos(struct vc_data *vc, int offset)
                        oldy = (offset >> 1) / vc->vc_cols;
                        vc->vc_sw->con_putc(vc, new, oldy, oldx);
                }
+               notify_update(vc);
        }
-
 }
 
 static void insert_char(struct vc_data *vc, unsigned int nr)
@@ -657,7 +659,7 @@ static inline void save_screen(struct vc_data *vc)
  *     Redrawing of screen
  */
 
-static void clear_buffer_attributes(struct vc_data *vc)
+void clear_buffer_attributes(struct vc_data *vc)
 {
        unsigned short *p = (unsigned short *)vc->vc_origin;
        int count = vc->vc_screenbuf_size / 2;
@@ -880,10 +882,15 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
                return 0;
 
+       if (new_screen_size > (4 << 20))
+               return -EINVAL;
        newscreen = kmalloc(new_screen_size, GFP_USER);
        if (!newscreen)
                return -ENOMEM;
 
+       if (vc == sel_cons)
+               clear_selection();
+
        old_rows = vc->vc_rows;
        old_row_size = vc->vc_size_row;
 
@@ -1195,7 +1202,7 @@ static void csi_J(struct vc_data *vc, int vpar)
                        break;
                case 3: /* erase scroll-back buffer (and whole display) */
                        scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
-                                   vc->vc_screenbuf_size >> 1);
+                                   vc->vc_screenbuf_size);
                        set_origin(vc);
                        if (CON_IS_VISIBLE(vc))
                                update_screen(vc);
@@ -3016,7 +3023,7 @@ int __init vty_init(const struct file_operations *console_fops)
 
 static struct class *vtconsole_class;
 
-static int bind_con_driver(const struct consw *csw, int first, int last,
+static int do_bind_con_driver(const struct consw *csw, int first, int last,
                           int deflt)
 {
        struct module *owner = csw->owner;
@@ -3027,7 +3034,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
        if (!try_module_get(owner))
                return -ENODEV;
 
-       console_lock();
+       WARN_CONSOLE_UNLOCKED();
 
        /* check if driver is registered */
        for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
@@ -3112,11 +3119,22 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
 
        retval = 0;
 err:
-       console_unlock();
        module_put(owner);
        return retval;
 };
 
+
+static int bind_con_driver(const struct consw *csw, int first, int last,
+                          int deflt)
+{
+       int ret;
+
+       console_lock();
+       ret = do_bind_con_driver(csw, first, last, deflt);
+       console_unlock();
+       return ret;
+}
+
 #ifdef CONFIG_VT_HW_CONSOLE_BINDING
 static int con_is_graphics(const struct consw *csw, int first, int last)
 {
@@ -3152,6 +3170,18 @@ static int con_is_graphics(const struct consw *csw, int first, int last)
  * or 0 on success.
  */
 int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
+{
+       int retval;
+
+       console_lock();
+       retval = do_unbind_con_driver(csw, first, last, deflt);
+       console_unlock();
+       return retval;
+}
+EXPORT_SYMBOL(unbind_con_driver);
+
+/* unlocked version of unbind_con_driver() */
+int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
 {
        struct module *owner = csw->owner;
        const struct consw *defcsw = NULL;
@@ -3161,7 +3191,7 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
        if (!try_module_get(owner))
                return -ENODEV;
 
-       console_lock();
+       WARN_CONSOLE_UNLOCKED();
 
        /* check if driver is registered and if it is unbindable */
        for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
@@ -3174,10 +3204,8 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
                }
        }
 
-       if (retval) {
-               console_unlock();
+       if (retval)
                goto err;
-       }
 
        retval = -ENODEV;
 
@@ -3193,15 +3221,11 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
                }
        }
 
-       if (retval) {
-               console_unlock();
+       if (retval)
                goto err;
-       }
 
-       if (!con_is_bound(csw)) {
-               console_unlock();
+       if (!con_is_bound(csw))
                goto err;
-       }
 
        first = max(first, con_driver->first);
        last = min(last, con_driver->last);
@@ -3228,15 +3252,14 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
        if (!con_is_bound(csw))
                con_driver->flag &= ~CON_DRIVER_FLAG_INIT;
 
-       console_unlock();
        /* ignore return value, binding should not fail */
-       bind_con_driver(defcsw, first, last, deflt);
+       do_bind_con_driver(defcsw, first, last, deflt);
 err:
        module_put(owner);
        return retval;
 
 }
-EXPORT_SYMBOL(unbind_con_driver);
+EXPORT_SYMBOL_GPL(do_unbind_con_driver);
 
 static int vt_bind(struct con_driver *con)
 {
@@ -3508,28 +3531,18 @@ int con_debug_leave(void)
 }
 EXPORT_SYMBOL_GPL(con_debug_leave);
 
-/**
- * register_con_driver - register console driver to console layer
- * @csw: console driver
- * @first: the first console to take over, minimum value is 0
- * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
- *
- * DESCRIPTION: This function registers a console driver which can later
- * bind to a range of consoles specified by @first and @last. It will
- * also initialize the console driver by calling con_startup().
- */
-int register_con_driver(const struct consw *csw, int first, int last)
+static int do_register_con_driver(const struct consw *csw, int first, int last)
 {
        struct module *owner = csw->owner;
        struct con_driver *con_driver;
        const char *desc;
        int i, retval = 0;
 
+       WARN_CONSOLE_UNLOCKED();
+
        if (!try_module_get(owner))
                return -ENODEV;
 
-       console_lock();
-
        for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
                con_driver = &registered_con_driver[i];
 
@@ -3542,9 +3555,10 @@ int register_con_driver(const struct consw *csw, int first, int last)
                goto err;
 
        desc = csw->con_startup();
-
-       if (!desc)
+       if (!desc) {
+               retval = -ENODEV;
                goto err;
+       }
 
        retval = -EINVAL;
 
@@ -3582,10 +3596,29 @@ int register_con_driver(const struct consw *csw, int first, int last)
        }
 
 err:
-       console_unlock();
        module_put(owner);
        return retval;
 }
+
+/**
+ * register_con_driver - register console driver to console layer
+ * @csw: console driver
+ * @first: the first console to take over, minimum value is 0
+ * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
+ *
+ * DESCRIPTION: This function registers a console driver which can later
+ * bind to a range of consoles specified by @first and @last. It will
+ * also initialize the console driver by calling con_startup().
+ */
+int register_con_driver(const struct consw *csw, int first, int last)
+{
+       int retval;
+
+       console_lock();
+       retval = do_register_con_driver(csw, first, last);
+       console_unlock();
+       return retval;
+}
 EXPORT_SYMBOL(register_con_driver);
 
 /**
@@ -3601,9 +3634,18 @@ EXPORT_SYMBOL(register_con_driver);
  */
 int unregister_con_driver(const struct consw *csw)
 {
-       int i, retval = -ENODEV;
+       int retval;
 
        console_lock();
+       retval = do_unregister_con_driver(csw);
+       console_unlock();
+       return retval;
+}
+EXPORT_SYMBOL(unregister_con_driver);
+
+int do_unregister_con_driver(const struct consw *csw)
+{
+       int i, retval = -ENODEV;
 
        /* cannot unregister a bound driver */
        if (con_is_bound(csw))
@@ -3629,27 +3671,53 @@ int unregister_con_driver(const struct consw *csw)
                }
        }
 err:
-       console_unlock();
        return retval;
 }
-EXPORT_SYMBOL(unregister_con_driver);
+EXPORT_SYMBOL_GPL(do_unregister_con_driver);
 
 /*
  *     If we support more console drivers, this function is used
  *     when a driver wants to take over some existing consoles
  *     and become default driver for newly opened ones.
  *
- *      take_over_console is basically a register followed by unbind
+ *     take_over_console is basically a register followed by unbind
+ */
+int do_take_over_console(const struct consw *csw, int first, int last, int deflt)
+{
+       int err;
+
+       err = do_register_con_driver(csw, first, last);
+       /*
+        * If we get an busy error we still want to bind the console driver
+        * and return success, as we may have unbound the console driver
+        * but not unregistered it.
+        */
+       if (err == -EBUSY)
+               err = 0;
+       if (!err)
+               do_bind_con_driver(csw, first, last, deflt);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(do_take_over_console);
+
+/*
+ *     If we support more console drivers, this function is used
+ *     when a driver wants to take over some existing consoles
+ *     and become default driver for newly opened ones.
+ *
+ *     take_over_console is basically a register followed by unbind
  */
 int take_over_console(const struct consw *csw, int first, int last, int deflt)
 {
        int err;
 
        err = register_con_driver(csw, first, last);
-       /* if we get an busy error we still want to bind the console driver
+       /*
+        * If we get an busy error we still want to bind the console driver
         * and return success, as we may have unbound the console driver
-        * but not unregistered it.
-       */
+        * but not unregistered it.
+        */
        if (err == -EBUSY)
                err = 0;
        if (!err)