aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ssu100.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-03-21 07:37:32 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-25 16:52:28 -0400
commitc24c838e8effd55ba330d1966d9846400af4bec8 (patch)
treeeda7652d5694dcf7ef4816a5a9ebf9a59392da6e /drivers/usb/serial/ssu100.c
parent31ecdb6befeab20d93b49b8dd640c081b48912d0 (diff)
USB: ssu100: switch to generic TIOCMIWAIT implementation
Switch to the generic TIOCMIWAIT implementation. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/ssu100.c')
-rw-r--r--drivers/usb/serial/ssu100.c50
1 files changed, 2 insertions, 48 deletions
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 8d94a5a7c4b6..5b62dbbdf996 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -337,49 +337,6 @@ static int get_serial_info(struct usb_serial_port *port,
337 return 0; 337 return 0;
338} 338}
339 339
340static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
341{
342 struct ssu100_port_private *priv = usb_get_serial_port_data(port);
343 struct async_icount prev, cur;
344 unsigned long flags;
345
346 spin_lock_irqsave(&priv->status_lock, flags);
347 prev = port->icount;
348 spin_unlock_irqrestore(&priv->status_lock, flags);
349
350 while (1) {
351 wait_event_interruptible(port->delta_msr_wait,
352 (port->serial->disconnected ||
353 (port->icount.rng != prev.rng) ||
354 (port->icount.dsr != prev.dsr) ||
355 (port->icount.dcd != prev.dcd) ||
356 (port->icount.cts != prev.cts)));
357
358 if (signal_pending(current))
359 return -ERESTARTSYS;
360
361 if (port->serial->disconnected)
362 return -EIO;
363
364 spin_lock_irqsave(&priv->status_lock, flags);
365 cur = port->icount;
366 spin_unlock_irqrestore(&priv->status_lock, flags);
367
368 if ((prev.rng == cur.rng) &&
369 (prev.dsr == cur.dsr) &&
370 (prev.dcd == cur.dcd) &&
371 (prev.cts == cur.cts))
372 return -EIO;
373
374 if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
375 (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
376 (arg & TIOCM_CD && (prev.dcd != cur.dcd)) ||
377 (arg & TIOCM_CTS && (prev.cts != cur.cts)))
378 return 0;
379 }
380 return 0;
381}
382
383static int ssu100_ioctl(struct tty_struct *tty, 340static int ssu100_ioctl(struct tty_struct *tty,
384 unsigned int cmd, unsigned long arg) 341 unsigned int cmd, unsigned long arg)
385{ 342{
@@ -391,10 +348,6 @@ static int ssu100_ioctl(struct tty_struct *tty,
391 case TIOCGSERIAL: 348 case TIOCGSERIAL:
392 return get_serial_info(port, 349 return get_serial_info(port,
393 (struct serial_struct __user *) arg); 350 (struct serial_struct __user *) arg);
394
395 case TIOCMIWAIT:
396 return wait_modem_info(port, arg);
397
398 default: 351 default:
399 break; 352 break;
400 } 353 }
@@ -509,7 +462,7 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
509 port->icount.dcd++; 462 port->icount.dcd++;
510 if (msr & UART_MSR_TERI) 463 if (msr & UART_MSR_TERI)
511 port->icount.rng++; 464 port->icount.rng++;
512 wake_up_interruptible(&port->delta_msr_wait); 465 wake_up_interruptible(&port->port.delta_msr_wait);
513 } 466 }
514} 467}
515 468
@@ -607,6 +560,7 @@ static struct usb_serial_driver ssu100_device = {
607 .process_read_urb = ssu100_process_read_urb, 560 .process_read_urb = ssu100_process_read_urb,
608 .tiocmget = ssu100_tiocmget, 561 .tiocmget = ssu100_tiocmget,
609 .tiocmset = ssu100_tiocmset, 562 .tiocmset = ssu100_tiocmset,
563 .tiocmiwait = usb_serial_generic_tiocmiwait,
610 .get_icount = usb_serial_generic_get_icount, 564 .get_icount = usb_serial_generic_get_icount,
611 .ioctl = ssu100_ioctl, 565 .ioctl = ssu100_ioctl,
612 .set_termios = ssu100_set_termios, 566 .set_termios = ssu100_set_termios,