Merge remote-tracking branches 'asoc/fix/arizona', 'asoc/fix/fsl', 'asoc/fix/fsl...
[cascardo/linux.git] / drivers / tty / amiserial.c
index 71630a2..979e7c3 100644 (file)
@@ -1248,6 +1248,8 @@ static int rs_ioctl(struct tty_struct *tty,
        struct async_icount cprev, cnow;        /* kernel counter temps */
        void __user *argp = (void __user *)arg;
        unsigned long flags;
+       DEFINE_WAIT(wait);
+       int ret;
 
        if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
                return -ENODEV;
@@ -1288,25 +1290,33 @@ static int rs_ioctl(struct tty_struct *tty,
                        cprev = info->icount;
                        local_irq_restore(flags);
                        while (1) {
-                               interruptible_sleep_on(&info->tport.delta_msr_wait);
-                               /* see if a signal did it */
-                               if (signal_pending(current))
-                                       return -ERESTARTSYS;
+                               prepare_to_wait(&info->tport.delta_msr_wait,
+                                               &wait, TASK_INTERRUPTIBLE);
                                local_irq_save(flags);
                                cnow = info->icount; /* atomic copy */
                                local_irq_restore(flags);
                                if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
-                                   cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                                       return -EIO; /* no change => error */
+                                   cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+                                       ret = -EIO; /* no change => error */
+                                       break;
+                               }
                                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)) ) {
-                                       return 0;
+                                       ret = 0;
+                                       break;
+                               }
+                               schedule();
+                               /* see if a signal did it */
+                               if (signal_pending(current)) {
+                                       ret = -ERESTARTSYS;
+                                       break;
                                }
                                cprev = cnow;
                        }
-                       /* NOTREACHED */
+                       finish_wait(&info->tport.delta_msr_wait, &wait);
+                       return ret;
 
                case TIOCSERGWILD:
                case TIOCSERSWILD: