[PATCH 1/1] quatech_usb2: Potential lost wakeup scenario in TIOCMIWAIT
Kautuk Consul
consul.kautuk at gmail.com
Mon Sep 12 22:53:34 PDT 2011
If the usermode app does an ioctl over this serial device by
using TIOCMIWAIT, then the code will wait by setting the current
task state to TASK_INTERRUPTIBLE and then calling schedule().
This will be woken up by the qt2_process_modem_status on URB
completion when the port_extra->shadowMSR is set to the new
modem status.
However, this could result in a lost wakeup scenario due to a race
in the logic in the qt2_ioctl(TIOCMIWAIT) loop and the URB completion
for new modem status in qt2_process_modem_status.
Due to this, the usermode app's task will continue to sleep despite a
change in the modem status.
Signed-off-by: Kautuk Consul <consul.kautuk at gmail.com>
---
drivers/staging/quatech_usb2/quatech_usb2.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c
index ca098ca..af7cba2 100644
--- a/drivers/staging/quatech_usb2/quatech_usb2.c
+++ b/drivers/staging/quatech_usb2/quatech_usb2.c
@@ -915,10 +915,10 @@ static int qt2_ioctl(struct tty_struct *tty,
} else if (cmd == TIOCMIWAIT) {
dbg("%s() port %d, cmd == TIOCMIWAIT enter",
__func__, port->number);
+ set_current_state(TASK_INTERRUPTIBLE);
prev_msr_value = port_extra->shadowMSR & QT2_SERIAL_MSR_MASK;
while (1) {
add_wait_queue(&port_extra->wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
schedule();
dbg("%s(): port %d, cmd == TIOCMIWAIT here\n",
__func__, port->number);
@@ -926,9 +926,12 @@ static int qt2_ioctl(struct tty_struct *tty,
/* see if a signal woke us up */
if (signal_pending(current))
return -ERESTARTSYS;
+ set_current_state(TASK_INTERRUPTIBLE);
msr_value = port_extra->shadowMSR & QT2_SERIAL_MSR_MASK;
- if (msr_value == prev_msr_value)
+ if (msr_value == prev_msr_value) {
+ __set_current_state(TASK_RUNNING);
return -EIO; /* no change - error */
+ }
if ((arg & TIOCM_RNG &&
((prev_msr_value & QT2_SERIAL_MSR_RI) ==
(msr_value & QT2_SERIAL_MSR_RI))) ||
@@ -941,6 +944,7 @@ static int qt2_ioctl(struct tty_struct *tty,
(arg & TIOCM_CTS &&
((prev_msr_value & QT2_SERIAL_MSR_CTS) ==
(msr_value & QT2_SERIAL_MSR_CTS)))) {
+ __set_current_state(TASK_RUNNING);
return 0;
}
} /* end inifinite while */
--
1.7.6
More information about the devel
mailing list