Skip to content

Commit

Permalink
staging: quatech_usb2: Potential lost wakeup scenario in TIOCMIWAIT
Browse files Browse the repository at this point in the history
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@gmail.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Kautuk Consul authored and Greg Kroah-Hartman committed Sep 19, 2011
1 parent e228b74 commit e8df167
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions drivers/staging/quatech_usb2/quatech_usb2.c
Original file line number Diff line number Diff line change
Expand Up @@ -916,19 +916,23 @@ static int qt2_ioctl(struct tty_struct *tty,
dbg("%s() port %d, cmd == TIOCMIWAIT enter",
__func__, port->number);
prev_msr_value = port_extra->shadowMSR & QT2_SERIAL_MSR_MASK;
barrier();
__set_current_state(TASK_INTERRUPTIBLE);
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);
remove_wait_queue(&port_extra->wait, &wait);
/* 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))) ||
Expand All @@ -941,6 +945,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 */
Expand Down

0 comments on commit e8df167

Please sign in to comment.