Char: mxser_new, fix TIOCMIWAIT
There was schedule() missing in the TIOCMIWAIT ioctl. Solve it by moving the code to the wait_event_interruptible. Cc: Jan "Yenya" Kasprzak <kas@fi.muni.cz> Signed-off-by: Jiri Slaby <jirislaby@gmail.com> 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>
This commit is contained in:
parent
67d2bc58af
commit
b446a4a575
1 changed files with 9 additions and 29 deletions
|
@ -1758,43 +1758,23 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
|
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
|
||||||
* Caller should use TIOCGICOUNT to see which one it was
|
* Caller should use TIOCGICOUNT to see which one it was
|
||||||
*/
|
*/
|
||||||
case TIOCMIWAIT: {
|
case TIOCMIWAIT:
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
|
||||||
int ret;
|
|
||||||
spin_lock_irqsave(&info->slock, flags);
|
spin_lock_irqsave(&info->slock, flags);
|
||||||
cprev = info->icount; /* note the counters on entry */
|
cnow = info->icount; /* note the counters on entry */
|
||||||
spin_unlock_irqrestore(&info->slock, flags);
|
spin_unlock_irqrestore(&info->slock, flags);
|
||||||
|
|
||||||
add_wait_queue(&info->delta_msr_wait, &wait);
|
wait_event_interruptible(info->delta_msr_wait, ({
|
||||||
while (1) {
|
cprev = cnow;
|
||||||
spin_lock_irqsave(&info->slock, flags);
|
spin_lock_irqsave(&info->slock, flags);
|
||||||
cnow = info->icount; /* atomic copy */
|
cnow = info->icount; /* atomic copy */
|
||||||
spin_unlock_irqrestore(&info->slock, flags);
|
spin_unlock_irqrestore(&info->slock, flags);
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
|
||||||
if (((arg & TIOCM_RNG) &&
|
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
|
||||||
(cnow.rng != cprev.rng)) ||
|
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
|
||||||
((arg & TIOCM_DSR) &&
|
((arg & TIOCM_CTS) && (cnow.cts != cprev.cts));
|
||||||
(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;
|
break;
|
||||||
}
|
|
||||||
/* NOTREACHED */
|
|
||||||
/*
|
/*
|
||||||
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
||||||
* Return: write counters to the user passed counter struct
|
* Return: write counters to the user passed counter struct
|
||||||
|
|
Loading…
Reference in a new issue