Char: mxser, fix TIOCMIWAIT
authorJiri Slaby <jirislaby@gmail.com>
Mon, 23 Apr 2007 21:41:04 +0000 (14:41 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 24 Apr 2007 15:23:08 +0000 (08:23 -0700)
There was schedule() missing in the TIOCMIWAIT ioctl. Solve it by moving
the code to the wait_event_interruptible.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Jan Yenya Kasprzak <kas@fi.muni.cz>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/mxser.c

index a61fb6da5d03f0b757b93c45893f01a8d031ddc8..80a01150b86c40674d9f0158062b2e91bdbff676 100644 (file)
@@ -1338,43 +1338,23 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
                 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
                 * Caller should use TIOCGICOUNT to see which one it was
                 */
-       case TIOCMIWAIT: {
-                       DECLARE_WAITQUEUE(wait, current);
-                       int ret;
+       case TIOCMIWAIT:
+               spin_lock_irqsave(&info->slock, flags);
+               cnow = info->icount;    /* note the counters on entry */
+               spin_unlock_irqrestore(&info->slock, flags);
+
+               wait_event_interruptible(info->delta_msr_wait, ({
+                       cprev = cnow;
                        spin_lock_irqsave(&info->slock, flags);
-                       cprev = info->icount;   /* note the counters on entry */
+                       cnow = info->icount;    /* atomic copy */
                        spin_unlock_irqrestore(&info->slock, flags);
 
-                       add_wait_queue(&info->delta_msr_wait, &wait);
-                       while (1) {
-                               spin_lock_irqsave(&info->slock, flags);
-                               cnow = info->icount;    /* atomic copy */
-                               spin_unlock_irqrestore(&info->slock, flags);
-
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               if (((arg & TIOCM_RNG) &&
-                                               (cnow.rng != cprev.rng)) ||
-                                               ((arg & TIOCM_DSR) &&
-                                               (cnow.dsr != cprev.dsr)) ||
-                                               ((arg & TIOCM_CD) &&
-                                               (cnow.dcd != cprev.dcd)) ||
-                                               ((arg & TIOCM_CTS) &&
-                                               (cnow.cts != cprev.cts))) {
-                                       ret = 0;
-                                       break;
-                               }
-                               /* see if a signal did it */
-                               if (signal_pending(current)) {
-                                       ret = -ERESTARTSYS;
-                                       break;
-                               }
-                               cprev = cnow;
-                       }
-                       current->state = TASK_RUNNING;
-                       remove_wait_queue(&info->delta_msr_wait, &wait);
-                       break;
-               }
-               /* NOTREACHED */
+                       ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+                       ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+                       ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+                       ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts));
+               }));
+               break;
                /*
                 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
                 * Return: write counters to the user passed counter struct