aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2014-01-02 16:49:27 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-03 15:42:24 -0500
commitab62a585a02af4dae2d615d4476e1bf493ff1be8 (patch)
treefb0d53574c22b318d0a550f0e6fc0ca9281d658f
parent7603381e3e7ffebe8c0b46c416fe0f88e13b4d34 (diff)
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>
-rw-r--r--drivers/usb/serial/cypress_m8.c63
1 files changed, 16 insertions, 47 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 07e003398613..763d1c59f8fc 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -113,7 +113,7 @@ struct cypress_private {
113 int baud_rate; /* stores current baud rate in 113 int baud_rate; /* stores current baud rate in
114 integer form */ 114 integer form */
115 int isthrottled; /* if throttled, discard reads */ 115 int isthrottled; /* if throttled, discard reads */
116 char prev_status, diff_status; /* used for TIOCMIWAIT */ 116 char prev_status; /* used for TIOCMIWAIT */
117 /* we pass a pointer to this as the argument sent to 117 /* we pass a pointer to this as the argument sent to
118 cypress_set_termios old_termios */ 118 cypress_set_termios old_termios */
119 struct ktermios tmp_termios; /* stores the old termios settings */ 119 struct ktermios tmp_termios; /* stores the old termios settings */
@@ -136,7 +136,6 @@ static void cypress_set_termios(struct tty_struct *tty,
136static int cypress_tiocmget(struct tty_struct *tty); 136static int cypress_tiocmget(struct tty_struct *tty);
137static int cypress_tiocmset(struct tty_struct *tty, 137static int cypress_tiocmset(struct tty_struct *tty,
138 unsigned int set, unsigned int clear); 138 unsigned int set, unsigned int clear);
139static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg);
140static int cypress_chars_in_buffer(struct tty_struct *tty); 139static int cypress_chars_in_buffer(struct tty_struct *tty);
141static void cypress_throttle(struct tty_struct *tty); 140static void cypress_throttle(struct tty_struct *tty);
142static void cypress_unthrottle(struct tty_struct *tty); 141static void cypress_unthrottle(struct tty_struct *tty);
@@ -162,7 +161,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
162 .set_termios = cypress_set_termios, 161 .set_termios = cypress_set_termios,
163 .tiocmget = cypress_tiocmget, 162 .tiocmget = cypress_tiocmget,
164 .tiocmset = cypress_tiocmset, 163 .tiocmset = cypress_tiocmset,
165 .tiocmiwait = cypress_tiocmiwait, 164 .tiocmiwait = usb_serial_generic_tiocmiwait,
166 .chars_in_buffer = cypress_chars_in_buffer, 165 .chars_in_buffer = cypress_chars_in_buffer,
167 .throttle = cypress_throttle, 166 .throttle = cypress_throttle,
168 .unthrottle = cypress_unthrottle, 167 .unthrottle = cypress_unthrottle,
@@ -188,7 +187,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
188 .set_termios = cypress_set_termios, 187 .set_termios = cypress_set_termios,
189 .tiocmget = cypress_tiocmget, 188 .tiocmget = cypress_tiocmget,
190 .tiocmset = cypress_tiocmset, 189 .tiocmset = cypress_tiocmset,
191 .tiocmiwait = cypress_tiocmiwait, 190 .tiocmiwait = usb_serial_generic_tiocmiwait,
192 .chars_in_buffer = cypress_chars_in_buffer, 191 .chars_in_buffer = cypress_chars_in_buffer,
193 .throttle = cypress_throttle, 192 .throttle = cypress_throttle,
194 .unthrottle = cypress_unthrottle, 193 .unthrottle = cypress_unthrottle,
@@ -214,7 +213,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
214 .set_termios = cypress_set_termios, 213 .set_termios = cypress_set_termios,
215 .tiocmget = cypress_tiocmget, 214 .tiocmget = cypress_tiocmget,
216 .tiocmset = cypress_tiocmset, 215 .tiocmset = cypress_tiocmset,
217 .tiocmiwait = cypress_tiocmiwait, 216 .tiocmiwait = usb_serial_generic_tiocmiwait,
218 .chars_in_buffer = cypress_chars_in_buffer, 217 .chars_in_buffer = cypress_chars_in_buffer,
219 .throttle = cypress_throttle, 218 .throttle = cypress_throttle,
220 .unthrottle = cypress_unthrottle, 219 .unthrottle = cypress_unthrottle,
@@ -864,45 +863,6 @@ static int cypress_tiocmset(struct tty_struct *tty,
864 return cypress_write(tty, port, NULL, 0); 863 return cypress_write(tty, port, NULL, 0);
865} 864}
866 865
867
868static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg)
869{
870 struct usb_serial_port *port = tty->driver_data;
871 struct cypress_private *priv = usb_get_serial_port_data(port);
872 char diff;
873
874 for (;;) {
875 interruptible_sleep_on(&port->port.delta_msr_wait);
876 /* see if a signal did it */
877 if (signal_pending(current))
878 return -ERESTARTSYS;
879
880 if (port->serial->disconnected)
881 return -EIO;
882
883 diff = priv->diff_status;
884 if (diff == 0)
885 return -EIO; /* no change => error */
886
887 /* consume all events */
888 priv->diff_status = 0;
889
890 /* return 0 if caller wanted to know about
891 these bits */
892 if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
893 ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
894 ((arg & TIOCM_CD) && (diff & UART_CD)) ||
895 ((arg & TIOCM_CTS) && (diff & UART_CTS)))
896 return 0;
897 /* otherwise caller can't care less about what
898 * happened, and so we continue to wait for
899 * more events.
900 */
901 }
902
903 return 0;
904}
905
906static void cypress_set_termios(struct tty_struct *tty, 866static void cypress_set_termios(struct tty_struct *tty,
907 struct usb_serial_port *port, struct ktermios *old_termios) 867 struct usb_serial_port *port, struct ktermios *old_termios)
908{ 868{
@@ -1185,11 +1145,20 @@ static void cypress_read_int_callback(struct urb *urb)
1185 spin_lock_irqsave(&priv->lock, flags); 1145 spin_lock_irqsave(&priv->lock, flags);
1186 /* check to see if status has changed */ 1146 /* check to see if status has changed */
1187 if (priv->current_status != priv->prev_status) { 1147 if (priv->current_status != priv->prev_status) {
1188 priv->diff_status |= priv->current_status ^ 1148 u8 delta = priv->current_status ^ priv->prev_status;
1189 priv->prev_status; 1149
1150 if (delta & UART_MSR_MASK) {
1151 if (delta & UART_CTS)
1152 port->icount.cts++;
1153 if (delta & UART_DSR)
1154 port->icount.dsr++;
1155 if (delta & UART_RI)
1156 port->icount.rng++;
1157 if (delta & UART_CD)
1158 port->icount.dcd++;
1190 1159
1191 if (priv->diff_status & UART_MSR_MASK)
1192 wake_up_interruptible(&port->port.delta_msr_wait); 1160 wake_up_interruptible(&port->port.delta_msr_wait);
1161 }
1193 1162
1194 priv->prev_status = priv->current_status; 1163 priv->prev_status = priv->current_status;
1195 } 1164 }