Skip to content

Commit

Permalink
USB: cypress_m8: switch to generic TIOCMIWAIT implementation
Browse files Browse the repository at this point in the history
Switch to the generic TIOCMIWAIT implementation which does not suffer
from the races involved when using the deprecated sleep_on functions.

Acked-by: Arnd Bergmann <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
jhovold authored and gregkh committed Jan 3, 2014
1 parent 7603381 commit ab62a58
Showing 1 changed file with 16 additions and 47 deletions.
63 changes: 16 additions & 47 deletions drivers/usb/serial/cypress_m8.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct cypress_private {
int baud_rate; /* stores current baud rate in
integer form */
int isthrottled; /* if throttled, discard reads */
char prev_status, diff_status; /* used for TIOCMIWAIT */
char prev_status; /* used for TIOCMIWAIT */
/* we pass a pointer to this as the argument sent to
cypress_set_termios old_termios */
struct ktermios tmp_termios; /* stores the old termios settings */
Expand All @@ -136,7 +136,6 @@ static void cypress_set_termios(struct tty_struct *tty,
static int cypress_tiocmget(struct tty_struct *tty);
static int cypress_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg);
static int cypress_chars_in_buffer(struct tty_struct *tty);
static void cypress_throttle(struct tty_struct *tty);
static void cypress_unthrottle(struct tty_struct *tty);
Expand All @@ -162,7 +161,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
.tiocmiwait = cypress_tiocmiwait,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
Expand All @@ -188,7 +187,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
.tiocmiwait = cypress_tiocmiwait,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
Expand All @@ -214,7 +213,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
.tiocmiwait = cypress_tiocmiwait,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
Expand Down Expand Up @@ -864,45 +863,6 @@ static int cypress_tiocmset(struct tty_struct *tty,
return cypress_write(tty, port, NULL, 0);
}


static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
char diff;

for (;;) {
interruptible_sleep_on(&port->port.delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;

if (port->serial->disconnected)
return -EIO;

diff = priv->diff_status;
if (diff == 0)
return -EIO; /* no change => error */

/* consume all events */
priv->diff_status = 0;

/* return 0 if caller wanted to know about
these bits */
if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
((arg & TIOCM_CD) && (diff & UART_CD)) ||
((arg & TIOCM_CTS) && (diff & UART_CTS)))
return 0;
/* otherwise caller can't care less about what
* happened, and so we continue to wait for
* more events.
*/
}

return 0;
}

static void cypress_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
Expand Down Expand Up @@ -1185,11 +1145,20 @@ static void cypress_read_int_callback(struct urb *urb)
spin_lock_irqsave(&priv->lock, flags);
/* check to see if status has changed */
if (priv->current_status != priv->prev_status) {
priv->diff_status |= priv->current_status ^
priv->prev_status;
u8 delta = priv->current_status ^ priv->prev_status;

if (delta & UART_MSR_MASK) {
if (delta & UART_CTS)
port->icount.cts++;
if (delta & UART_DSR)
port->icount.dsr++;
if (delta & UART_RI)
port->icount.rng++;
if (delta & UART_CD)
port->icount.dcd++;

if (priv->diff_status & UART_MSR_MASK)
wake_up_interruptible(&port->port.delta_msr_wait);
}

priv->prev_status = priv->current_status;
}
Expand Down

0 comments on commit ab62a58

Please sign in to comment.