USB: cypress_m8: switch to generic TIOCMIWAIT implementation

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 <arnd@arndb.de>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Johan Hovold 2014-01-02 22:49:27 +01:00 коммит произвёл Greg Kroah-Hartman
Родитель 7603381e3e
Коммит ab62a585a0
1 изменённых файлов: 16 добавлений и 47 удалений

Просмотреть файл

@ -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 */
@ -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);
@ -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,
@ -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,
@ -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,
@ -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)
{
@ -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;
}