Pull ec into release branch
[pandora-kernel.git] / drivers / char / vt_ioctl.c
index ac5d60e..c9f2dd6 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/kbd_diacr.h>
 #include <linux/selection.h>
 
-static char vt_dont_switch;
+char vt_dont_switch;
 extern struct tty_driver *console_driver;
 
 #define VT_IS_IN_USE(i)        (console_driver->ttys[i] && console_driver->ttys[i]->count)
@@ -129,7 +129,7 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str
                            !capable(CAP_SYS_RESOURCE))
                                return -EPERM;
 
-                       key_map = (ushort *) kmalloc(sizeof(plain_map),
+                       key_map = kmalloc(sizeof(plain_map),
                                                     GFP_KERNEL);
                        if (!key_map)
                                return -ENOMEM;
@@ -259,7 +259,7 @@ do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
                    sz = 256;
                    while (sz < funcbufsize - funcbufleft + delta)
                      sz <<= 1;
-                   fnw = (char *) kmalloc(sz, GFP_KERNEL);
+                   fnw = kmalloc(sz, GFP_KERNEL);
                    if(!fnw) {
                      ret = -ENOMEM;
                      goto reterr;
@@ -672,7 +672,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                vc->vt_mode = tmp;
                /* the frsig is ignored, so we set it to 0 */
                vc->vt_mode.frsig = 0;
-               put_pid(xchg(&vc->vt_pid, get_pid(task_pid(current))));
+               put_pid(vc->vt_pid);
+               vc->vt_pid = get_pid(task_pid(current));
                /* no switch is required -- saw@shade.msu.ru */
                vc->vt_newvt = -1;
                release_console_sem();
@@ -1038,10 +1039,22 @@ int vt_waitactive(int vt)
 
        add_wait_queue(&vt_activate_queue, &wait);
        for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
                retval = 0;
-               if (vt == fg_console)
+
+               /*
+                * Synchronize with redraw_screen(). By acquiring the console
+                * semaphore we make sure that the console switch is completed
+                * before we return. If we didn't wait for the semaphore, we
+                * could return at a point where fg_console has already been
+                * updated, but the console switch hasn't been completed.
+                */
+               acquire_console_sem();
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (vt == fg_console) {
+                       release_console_sem();
                        break;
+               }
+               release_console_sem();
                retval = -EINTR;
                if (signal_pending(current))
                        break;
@@ -1063,12 +1076,35 @@ void reset_vc(struct vc_data *vc)
        vc->vt_mode.relsig = 0;
        vc->vt_mode.acqsig = 0;
        vc->vt_mode.frsig = 0;
-       put_pid(xchg(&vc->vt_pid, NULL));
+       put_pid(vc->vt_pid);
+       vc->vt_pid = NULL;
        vc->vt_newvt = -1;
        if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
                reset_palette(vc);
 }
 
+void vc_SAK(struct work_struct *work)
+{
+       struct vc *vc_con =
+               container_of(work, struct vc, SAK_work);
+       struct vc_data *vc;
+       struct tty_struct *tty;
+
+       acquire_console_sem();
+       vc = vc_con->d;
+       if (vc) {
+               tty = vc->vc_tty;
+               /*
+                * SAK should also work in all raw modes and reset
+                * them properly.
+                */
+               if (tty)
+                       __do_SAK(tty);
+               reset_vc(vc);
+       }
+       release_console_sem();
+}
+
 /*
  * Performs the back end of a vt switch
  */
@@ -1087,7 +1123,7 @@ static void complete_change_console(struct vc_data *vc)
        switch_screen(vc);
 
        /*
-        * This can't appear below a successful kill_proc().  If it did,
+        * This can't appear below a successful kill_pid().  If it did,
         * then the *blank_screen operation could occur while X, having
         * received acqsig, is waking up on another processor.  This
         * condition can lead to overlapping accesses to the VGA range
@@ -1110,7 +1146,7 @@ static void complete_change_console(struct vc_data *vc)
         */
        if (vc->vt_mode.mode == VT_PROCESS) {
                /*
-                * Send the signal as privileged - kill_proc() will
+                * Send the signal as privileged - kill_pid() will
                 * tell us if the process has gone or something else
                 * is awry
                 */
@@ -1170,7 +1206,7 @@ void change_console(struct vc_data *new_vc)
        vc = vc_cons[fg_console].d;
        if (vc->vt_mode.mode == VT_PROCESS) {
                /*
-                * Send the signal as privileged - kill_proc() will
+                * Send the signal as privileged - kill_pid() will
                 * tell us if the process has gone or something else
                 * is awry
                 */