aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cypress_m8.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r--drivers/usb/serial/cypress_m8.c81
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);
174static void cypress_shutdown(struct usb_serial *serial); 174static void cypress_shutdown(struct usb_serial *serial);
175static int cypress_open(struct tty_struct *tty, 175static 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);
177static void cypress_close(struct tty_struct *tty, 177static void cypress_close(struct usb_serial_port *port);
178 struct usb_serial_port *port, struct file *filp); 178static void cypress_dtr_rts(struct usb_serial_port *port, int on);
179static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, 179static 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);
181static void cypress_send(struct usb_serial_port *port); 181static 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
700static 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
702static void cypress_close(struct tty_struct *tty, 715static 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",