Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab62a585 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

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: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarJohan Hovold <jhovold@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7603381e
Loading
Loading
Loading
Loading
+16 −47
Original line number Diff line number Diff line
@@ -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;
	}