X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fchar%2Fvt_ioctl.c;h=c9f2dd620e877391373034eba491fb0789a2c425;hb=03feb0524660bcd890674d11d29a1873ca14d13c;hp=ac5d60edbafaadda7d58dd13601fb70e9ac70a82;hpb=44f549217cd26daf7063984ae4ee6e46beca9c41;p=pandora-kernel.git diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index ac5d60edbafa..c9f2dd620e87 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -34,7 +34,7 @@ #include #include -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 */