diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2007-04-23 17:41:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-24 11:23:08 -0400 |
commit | fc83815c3afe1bd8d0f0961a668a96caabb049be (patch) | |
tree | 9086ca9ec97e19a07d3f68a6ecec300dbb19ba9b /drivers/char/mxser.c | |
parent | b446a4a5757fe1287bf3472efcdde6b59dfd63ad (diff) |
Char: mxser, fix TIOCMIWAIT
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>
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r-- | drivers/char/mxser.c | 48 |
1 files changed, 14 insertions, 34 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index a61fb6da5d03..80a01150b86c 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -1338,43 +1338,23 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c | |||
1338 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) | 1338 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) |
1339 | * Caller should use TIOCGICOUNT to see which one it was | 1339 | * Caller should use TIOCGICOUNT to see which one it was |
1340 | */ | 1340 | */ |
1341 | case TIOCMIWAIT: { | 1341 | case TIOCMIWAIT: |
1342 | DECLARE_WAITQUEUE(wait, current); | 1342 | spin_lock_irqsave(&info->slock, flags); |
1343 | int ret; | 1343 | cnow = info->icount; /* note the counters on entry */ |
1344 | spin_unlock_irqrestore(&info->slock, flags); | ||
1345 | |||
1346 | wait_event_interruptible(info->delta_msr_wait, ({ | ||
1347 | cprev = cnow; | ||
1344 | spin_lock_irqsave(&info->slock, flags); | 1348 | spin_lock_irqsave(&info->slock, flags); |
1345 | cprev = info->icount; /* note the counters on entry */ | 1349 | cnow = info->icount; /* atomic copy */ |
1346 | spin_unlock_irqrestore(&info->slock, flags); | 1350 | spin_unlock_irqrestore(&info->slock, flags); |
1347 | 1351 | ||
1348 | add_wait_queue(&info->delta_msr_wait, &wait); | 1352 | ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || |
1349 | while (1) { | 1353 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || |
1350 | spin_lock_irqsave(&info->slock, flags); | 1354 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || |
1351 | cnow = info->icount; /* atomic copy */ | 1355 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)); |
1352 | spin_unlock_irqrestore(&info->slock, flags); | 1356 | })); |
1353 | 1357 | break; | |
1354 | set_current_state(TASK_INTERRUPTIBLE); | ||
1355 | if (((arg & TIOCM_RNG) && | ||
1356 | (cnow.rng != cprev.rng)) || | ||
1357 | ((arg & TIOCM_DSR) && | ||
1358 | (cnow.dsr != cprev.dsr)) || | ||
1359 | ((arg & TIOCM_CD) && | ||
1360 | (cnow.dcd != cprev.dcd)) || | ||
1361 | ((arg & TIOCM_CTS) && | ||
1362 | (cnow.cts != cprev.cts))) { | ||
1363 | ret = 0; | ||
1364 | break; | ||
1365 | } | ||
1366 | /* see if a signal did it */ | ||
1367 | if (signal_pending(current)) { | ||
1368 | ret = -ERESTARTSYS; | ||
1369 | break; | ||
1370 | } | ||
1371 | cprev = cnow; | ||
1372 | } | ||
1373 | current->state = TASK_RUNNING; | ||
1374 | remove_wait_queue(&info->delta_msr_wait, &wait); | ||
1375 | break; | ||
1376 | } | ||
1377 | /* NOTREACHED */ | ||
1378 | /* | 1358 | /* |
1379 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | 1359 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) |
1380 | * Return: write counters to the user passed counter struct | 1360 | * Return: write counters to the user passed counter struct |