aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/pl2303.c
diff options
context:
space:
mode:
authorLibor Pechacek <lpechacek@suse.cz>2011-01-14 08:30:21 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-01-22 21:53:26 -0500
commitd14fc1a74e846d7851f24fc9519fe87dc12a1231 (patch)
tree9d014b0200d4f2ba94c6d5ed1002c46027147fae /drivers/usb/serial/pl2303.c
parentca9cfea09fc5802074f79d086547c6363ddc894b (diff)
USB: serial: handle Data Carrier Detect changes
Alan's commit 335f8514f200e63d689113d29cb7253a5c282967 introduced .carrier_raised function in several drivers. That also means tty_port_block_til_ready can now suspend the process trying to open the serial port when Carrier Detect is low and put it into tty_port.open_wait queue. We need to wake up the process when Carrier Detect goes high and trigger TTY hangup when CD goes low. Some of the devices do not report modem status line changes, or at least we don't understand the status message, so for those we remove .carrier_raised again. Signed-off-by: Libor Pechacek <lpechacek@suse.cz> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
-rw-r--r--drivers/usb/serial/pl2303.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 45c40e6e9737..08c9181b8e48 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -678,9 +678,11 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
678{ 678{
679 679
680 struct pl2303_private *priv = usb_get_serial_port_data(port); 680 struct pl2303_private *priv = usb_get_serial_port_data(port);
681 struct tty_struct *tty;
681 unsigned long flags; 682 unsigned long flags;
682 u8 status_idx = UART_STATE; 683 u8 status_idx = UART_STATE;
683 u8 length = UART_STATE + 1; 684 u8 length = UART_STATE + 1;
685 u8 prev_line_status;
684 u16 idv, idp; 686 u16 idv, idp;
685 687
686 idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); 688 idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
@@ -702,11 +704,20 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
702 704
703 /* Save off the uart status for others to look at */ 705 /* Save off the uart status for others to look at */
704 spin_lock_irqsave(&priv->lock, flags); 706 spin_lock_irqsave(&priv->lock, flags);
707 prev_line_status = priv->line_status;
705 priv->line_status = data[status_idx]; 708 priv->line_status = data[status_idx];
706 spin_unlock_irqrestore(&priv->lock, flags); 709 spin_unlock_irqrestore(&priv->lock, flags);
707 if (priv->line_status & UART_BREAK_ERROR) 710 if (priv->line_status & UART_BREAK_ERROR)
708 usb_serial_handle_break(port); 711 usb_serial_handle_break(port);
709 wake_up_interruptible(&priv->delta_msr_wait); 712 wake_up_interruptible(&priv->delta_msr_wait);
713
714 tty = tty_port_tty_get(&port->port);
715 if (!tty)
716 return;
717 if ((priv->line_status ^ prev_line_status) & UART_DCD)
718 usb_serial_handle_dcd_change(port, tty,
719 priv->line_status & UART_DCD);
720 tty_kref_put(tty);
710} 721}
711 722
712static void pl2303_read_int_callback(struct urb *urb) 723static void pl2303_read_int_callback(struct urb *urb)