|
@@ -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:
|