Skip to content

Commit fca5430

Browse files
nomisgregkh
authored andcommitted
USB: ftdi_sio: fix status line change handling for TIOCMIWAIT and TIOCGICOUNT
Handling of TIOCMIWAIT was changed by commit 1d749f9 USB: ftdi_sio.c: Use ftdi async_icount structure for TIOCMIWAIT, as in other drivers FTDI_STATUS_B0_MASK does not indicate the changed modem status lines, it indicates the value of the current modem status lines. An xor is still required to determine which lines have changed. The count was only being incremented if the line was high. The only reason TIOCMIWAIT still worked was because the status packet is repeated every 1ms, so the count was always changing. The wakeup itself still ran based on the status lines changing. This change fixes handling of updates to the modem status lines and allows multiple processes to use TIOCMIWAIT concurrently. Tested with two processes waiting on different status lines being toggled independently. Signed-off-by: Simon Arlott <[email protected]> Cc: Uwe Bonnes <[email protected]> Cc: stable <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent cd4376e commit fca5430

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

drivers/usb/serial/ftdi_sio.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ struct ftdi_private {
7575
unsigned long last_dtr_rts; /* saved modem control outputs */
7676
struct async_icount icount;
7777
wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
78-
char prev_status, diff_status; /* Used for TIOCMIWAIT */
78+
char prev_status; /* Used for TIOCMIWAIT */
7979
char transmit_empty; /* If transmitter is empty or not */
8080
struct usb_serial_port *port;
8181
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
@@ -1982,17 +1982,19 @@ static int ftdi_process_packet(struct tty_struct *tty,
19821982
N.B. packet may be processed more than once, but differences
19831983
are only processed once. */
19841984
status = packet[0] & FTDI_STATUS_B0_MASK;
1985-
if (status & FTDI_RS0_CTS)
1986-
priv->icount.cts++;
1987-
if (status & FTDI_RS0_DSR)
1988-
priv->icount.dsr++;
1989-
if (status & FTDI_RS0_RI)
1990-
priv->icount.rng++;
1991-
if (status & FTDI_RS0_RLSD)
1992-
priv->icount.dcd++;
19931985
if (status != priv->prev_status) {
1994-
priv->diff_status |= status ^ priv->prev_status;
1995-
wake_up_interruptible(&priv->delta_msr_wait);
1986+
char diff_status = status ^ priv->prev_status;
1987+
1988+
if (diff_status & FTDI_RS0_CTS)
1989+
priv->icount.cts++;
1990+
if (diff_status & FTDI_RS0_DSR)
1991+
priv->icount.dsr++;
1992+
if (diff_status & FTDI_RS0_RI)
1993+
priv->icount.rng++;
1994+
if (diff_status & FTDI_RS0_RLSD)
1995+
priv->icount.dcd++;
1996+
1997+
wake_up_interruptible_all(&priv->delta_msr_wait);
19961998
priv->prev_status = status;
19971999
}
19982000

0 commit comments

Comments
 (0)