diff options
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r-- | drivers/usb/serial/cypress_m8.c | 81 |
1 files changed, 23 insertions, 58 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index e568710b263f..669f93848539 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -174,8 +174,8 @@ static int cypress_ca42v2_startup(struct usb_serial *serial); | |||
174 | static void cypress_shutdown(struct usb_serial *serial); | 174 | static void cypress_shutdown(struct usb_serial *serial); |
175 | static int cypress_open(struct tty_struct *tty, | 175 | static int cypress_open(struct tty_struct *tty, |
176 | struct usb_serial_port *port, struct file *filp); | 176 | struct usb_serial_port *port, struct file *filp); |
177 | static void cypress_close(struct tty_struct *tty, | 177 | static void cypress_close(struct usb_serial_port *port); |
178 | struct usb_serial_port *port, struct file *filp); | 178 | static void cypress_dtr_rts(struct usb_serial_port *port, int on); |
179 | static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, | 179 | static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, |
180 | const unsigned char *buf, int count); | 180 | const unsigned char *buf, int count); |
181 | static void cypress_send(struct usb_serial_port *port); | 181 | static void cypress_send(struct usb_serial_port *port); |
@@ -218,6 +218,7 @@ static struct usb_serial_driver cypress_earthmate_device = { | |||
218 | .shutdown = cypress_shutdown, | 218 | .shutdown = cypress_shutdown, |
219 | .open = cypress_open, | 219 | .open = cypress_open, |
220 | .close = cypress_close, | 220 | .close = cypress_close, |
221 | .dtr_rts = cypress_dtr_rts, | ||
221 | .write = cypress_write, | 222 | .write = cypress_write, |
222 | .write_room = cypress_write_room, | 223 | .write_room = cypress_write_room, |
223 | .ioctl = cypress_ioctl, | 224 | .ioctl = cypress_ioctl, |
@@ -244,6 +245,7 @@ static struct usb_serial_driver cypress_hidcom_device = { | |||
244 | .shutdown = cypress_shutdown, | 245 | .shutdown = cypress_shutdown, |
245 | .open = cypress_open, | 246 | .open = cypress_open, |
246 | .close = cypress_close, | 247 | .close = cypress_close, |
248 | .dtr_rts = cypress_dtr_rts, | ||
247 | .write = cypress_write, | 249 | .write = cypress_write, |
248 | .write_room = cypress_write_room, | 250 | .write_room = cypress_write_room, |
249 | .ioctl = cypress_ioctl, | 251 | .ioctl = cypress_ioctl, |
@@ -270,6 +272,7 @@ static struct usb_serial_driver cypress_ca42v2_device = { | |||
270 | .shutdown = cypress_shutdown, | 272 | .shutdown = cypress_shutdown, |
271 | .open = cypress_open, | 273 | .open = cypress_open, |
272 | .close = cypress_close, | 274 | .close = cypress_close, |
275 | .dtr_rts = cypress_dtr_rts, | ||
273 | .write = cypress_write, | 276 | .write = cypress_write, |
274 | .write_room = cypress_write_room, | 277 | .write_room = cypress_write_room, |
275 | .ioctl = cypress_ioctl, | 278 | .ioctl = cypress_ioctl, |
@@ -656,11 +659,7 @@ static int cypress_open(struct tty_struct *tty, | |||
656 | priv->rx_flags = 0; | 659 | priv->rx_flags = 0; |
657 | spin_unlock_irqrestore(&priv->lock, flags); | 660 | spin_unlock_irqrestore(&priv->lock, flags); |
658 | 661 | ||
659 | /* raise both lines and set termios */ | 662 | /* Set termios */ |
660 | spin_lock_irqsave(&priv->lock, flags); | ||
661 | priv->line_control = CONTROL_DTR | CONTROL_RTS; | ||
662 | priv->cmd_ctrl = 1; | ||
663 | spin_unlock_irqrestore(&priv->lock, flags); | ||
664 | result = cypress_write(tty, port, NULL, 0); | 663 | result = cypress_write(tty, port, NULL, 0); |
665 | 664 | ||
666 | if (result) { | 665 | if (result) { |
@@ -694,76 +693,42 @@ static int cypress_open(struct tty_struct *tty, | |||
694 | __func__, result); | 693 | __func__, result); |
695 | cypress_set_dead(port); | 694 | cypress_set_dead(port); |
696 | } | 695 | } |
697 | 696 | port->port.drain_delay = 256; | |
698 | return result; | 697 | return result; |
699 | } /* cypress_open */ | 698 | } /* cypress_open */ |
700 | 699 | ||
700 | static void cypress_dtr_rts(struct usb_serial_port *port, int on) | ||
701 | { | ||
702 | struct cypress_private *priv = usb_get_serial_port_data(port); | ||
703 | /* drop dtr and rts */ | ||
704 | priv = usb_get_serial_port_data(port); | ||
705 | spin_lock_irq(&priv->lock); | ||
706 | if (on == 0) | ||
707 | priv->line_control = 0; | ||
708 | else | ||
709 | priv->line_control = CONTROL_DTR | CONTROL_RTS; | ||
710 | priv->cmd_ctrl = 1; | ||
711 | spin_unlock_irq(&priv->lock); | ||
712 | cypress_write(NULL, port, NULL, 0); | ||
713 | } | ||
701 | 714 | ||
702 | static void cypress_close(struct tty_struct *tty, | 715 | static void cypress_close(struct usb_serial_port *port) |
703 | struct usb_serial_port *port, struct file *filp) | ||
704 | { | 716 | { |
705 | struct cypress_private *priv = usb_get_serial_port_data(port); | 717 | struct cypress_private *priv = usb_get_serial_port_data(port); |
706 | unsigned int c_cflag; | ||
707 | int bps; | ||
708 | long timeout; | ||
709 | wait_queue_t wait; | ||
710 | 718 | ||
711 | dbg("%s - port %d", __func__, port->number); | 719 | dbg("%s - port %d", __func__, port->number); |
712 | 720 | ||
713 | /* wait for data to drain from buffer */ | ||
714 | spin_lock_irq(&priv->lock); | ||
715 | timeout = CYPRESS_CLOSING_WAIT; | ||
716 | init_waitqueue_entry(&wait, current); | ||
717 | add_wait_queue(&tty->write_wait, &wait); | ||
718 | for (;;) { | ||
719 | set_current_state(TASK_INTERRUPTIBLE); | ||
720 | if (cypress_buf_data_avail(priv->buf) == 0 | ||
721 | || timeout == 0 || signal_pending(current) | ||
722 | /* without mutex, allowed due to harmless failure mode */ | ||
723 | || port->serial->disconnected) | ||
724 | break; | ||
725 | spin_unlock_irq(&priv->lock); | ||
726 | timeout = schedule_timeout(timeout); | ||
727 | spin_lock_irq(&priv->lock); | ||
728 | } | ||
729 | set_current_state(TASK_RUNNING); | ||
730 | remove_wait_queue(&tty->write_wait, &wait); | ||
731 | /* clear out any remaining data in the buffer */ | ||
732 | cypress_buf_clear(priv->buf); | ||
733 | spin_unlock_irq(&priv->lock); | ||
734 | |||
735 | /* writing is potentially harmful, lock must be taken */ | 721 | /* writing is potentially harmful, lock must be taken */ |
736 | mutex_lock(&port->serial->disc_mutex); | 722 | mutex_lock(&port->serial->disc_mutex); |
737 | if (port->serial->disconnected) { | 723 | if (port->serial->disconnected) { |
738 | mutex_unlock(&port->serial->disc_mutex); | 724 | mutex_unlock(&port->serial->disc_mutex); |
739 | return; | 725 | return; |
740 | } | 726 | } |
741 | /* wait for characters to drain from device */ | 727 | cypress_buf_clear(priv->buf); |
742 | if (tty) { | ||
743 | bps = tty_get_baud_rate(tty); | ||
744 | if (bps > 1200) | ||
745 | timeout = max((HZ * 2560) / bps, HZ / 10); | ||
746 | else | ||
747 | timeout = 2 * HZ; | ||
748 | schedule_timeout_interruptible(timeout); | ||
749 | } | ||
750 | |||
751 | dbg("%s - stopping urbs", __func__); | 728 | dbg("%s - stopping urbs", __func__); |
752 | usb_kill_urb(port->interrupt_in_urb); | 729 | usb_kill_urb(port->interrupt_in_urb); |
753 | usb_kill_urb(port->interrupt_out_urb); | 730 | usb_kill_urb(port->interrupt_out_urb); |
754 | 731 | ||
755 | if (tty) { | ||
756 | c_cflag = tty->termios->c_cflag; | ||
757 | if (c_cflag & HUPCL) { | ||
758 | /* drop dtr and rts */ | ||
759 | priv = usb_get_serial_port_data(port); | ||
760 | spin_lock_irq(&priv->lock); | ||
761 | priv->line_control = 0; | ||
762 | priv->cmd_ctrl = 1; | ||
763 | spin_unlock_irq(&priv->lock); | ||
764 | cypress_write(tty, port, NULL, 0); | ||
765 | } | ||
766 | } | ||
767 | 732 | ||
768 | if (stats) | 733 | if (stats) |
769 | dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", | 734 | dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", |