aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ch341.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/ch341.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/ch341.c')
-rw-r--r--drivers/usb/serial/ch341.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 63f7cc45bcac..7b8815ddf368 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -486,12 +486,22 @@ static void ch341_read_int_callback(struct urb *urb)
486 if (actual_length >= 4) { 486 if (actual_length >= 4) {
487 struct ch341_private *priv = usb_get_serial_port_data(port); 487 struct ch341_private *priv = usb_get_serial_port_data(port);
488 unsigned long flags; 488 unsigned long flags;
489 u8 prev_line_status = priv->line_status;
489 490
490 spin_lock_irqsave(&priv->lock, flags); 491 spin_lock_irqsave(&priv->lock, flags);
491 priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; 492 priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT;
492 if ((data[1] & CH341_MULT_STAT)) 493 if ((data[1] & CH341_MULT_STAT))
493 priv->multi_status_change = 1; 494 priv->multi_status_change = 1;
494 spin_unlock_irqrestore(&priv->lock, flags); 495 spin_unlock_irqrestore(&priv->lock, flags);
496
497 if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) {
498 struct tty_struct *tty = tty_port_tty_get(&port->port);
499 if (tty)
500 usb_serial_handle_dcd_change(port, tty,
501 priv->line_status & CH341_BIT_DCD);
502 tty_kref_put(tty);
503 }
504
495 wake_up_interruptible(&priv->delta_msr_wait); 505 wake_up_interruptible(&priv->delta_msr_wait);
496 } 506 }
497 507