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.c92
1 files changed, 28 insertions, 64 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index e568710b263f..9734085fd2fe 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -171,11 +171,11 @@ struct cypress_buf {
171static int cypress_earthmate_startup(struct usb_serial *serial); 171static int cypress_earthmate_startup(struct usb_serial *serial);
172static int cypress_hidcom_startup(struct usb_serial *serial); 172static int cypress_hidcom_startup(struct usb_serial *serial);
173static int cypress_ca42v2_startup(struct usb_serial *serial); 173static int cypress_ca42v2_startup(struct usb_serial *serial);
174static void cypress_shutdown(struct usb_serial *serial); 174static void cypress_release(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);
@@ -215,9 +215,10 @@ static struct usb_serial_driver cypress_earthmate_device = {
215 .id_table = id_table_earthmate, 215 .id_table = id_table_earthmate,
216 .num_ports = 1, 216 .num_ports = 1,
217 .attach = cypress_earthmate_startup, 217 .attach = cypress_earthmate_startup,
218 .shutdown = cypress_shutdown, 218 .release = cypress_release,
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,
@@ -241,9 +242,10 @@ static struct usb_serial_driver cypress_hidcom_device = {
241 .id_table = id_table_cyphidcomrs232, 242 .id_table = id_table_cyphidcomrs232,
242 .num_ports = 1, 243 .num_ports = 1,
243 .attach = cypress_hidcom_startup, 244 .attach = cypress_hidcom_startup,
244 .shutdown = cypress_shutdown, 245 .release = cypress_release,
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,
@@ -267,9 +269,10 @@ static struct usb_serial_driver cypress_ca42v2_device = {
267 .id_table = id_table_nokiaca42v2, 269 .id_table = id_table_nokiaca42v2,
268 .num_ports = 1, 270 .num_ports = 1,
269 .attach = cypress_ca42v2_startup, 271 .attach = cypress_ca42v2_startup,
270 .shutdown = cypress_shutdown, 272 .release = cypress_release,
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,
@@ -613,7 +616,7 @@ static int cypress_ca42v2_startup(struct usb_serial *serial)
613} /* cypress_ca42v2_startup */ 616} /* cypress_ca42v2_startup */
614 617
615 618
616static void cypress_shutdown(struct usb_serial *serial) 619static void cypress_release(struct usb_serial *serial)
617{ 620{
618 struct cypress_private *priv; 621 struct cypress_private *priv;
619 622
@@ -626,7 +629,6 @@ static void cypress_shutdown(struct usb_serial *serial)
626 if (priv) { 629 if (priv) {
627 cypress_buf_free(priv->buf); 630 cypress_buf_free(priv->buf);
628 kfree(priv); 631 kfree(priv);
629 usb_set_serial_port_data(serial->port[0], NULL);
630 } 632 }
631} 633}
632 634
@@ -656,11 +658,7 @@ static int cypress_open(struct tty_struct *tty,
656 priv->rx_flags = 0; 658 priv->rx_flags = 0;
657 spin_unlock_irqrestore(&priv->lock, flags); 659 spin_unlock_irqrestore(&priv->lock, flags);
658 660
659 /* raise both lines and set termios */ 661 /* 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); 662 result = cypress_write(tty, port, NULL, 0);
665 663
666 if (result) { 664 if (result) {
@@ -694,76 +692,42 @@ static int cypress_open(struct tty_struct *tty,
694 __func__, result); 692 __func__, result);
695 cypress_set_dead(port); 693 cypress_set_dead(port);
696 } 694 }
697 695 port->port.drain_delay = 256;
698 return result; 696 return result;
699} /* cypress_open */ 697} /* cypress_open */
700 698
699static void cypress_dtr_rts(struct usb_serial_port *port, int on)
700{
701 struct cypress_private *priv = usb_get_serial_port_data(port);
702 /* drop dtr and rts */
703 priv = usb_get_serial_port_data(port);
704 spin_lock_irq(&priv->lock);
705 if (on == 0)
706 priv->line_control = 0;
707 else
708 priv->line_control = CONTROL_DTR | CONTROL_RTS;
709 priv->cmd_ctrl = 1;
710 spin_unlock_irq(&priv->lock);
711 cypress_write(NULL, port, NULL, 0);
712}
701 713
702static void cypress_close(struct tty_struct *tty, 714static void cypress_close(struct usb_serial_port *port)
703 struct usb_serial_port *port, struct file *filp)
704{ 715{
705 struct cypress_private *priv = usb_get_serial_port_data(port); 716 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 717
711 dbg("%s - port %d", __func__, port->number); 718 dbg("%s - port %d", __func__, port->number);
712 719
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 */ 720 /* writing is potentially harmful, lock must be taken */
736 mutex_lock(&port->serial->disc_mutex); 721 mutex_lock(&port->serial->disc_mutex);
737 if (port->serial->disconnected) { 722 if (port->serial->disconnected) {
738 mutex_unlock(&port->serial->disc_mutex); 723 mutex_unlock(&port->serial->disc_mutex);
739 return; 724 return;
740 } 725 }
741 /* wait for characters to drain from device */ 726 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__); 727 dbg("%s - stopping urbs", __func__);
752 usb_kill_urb(port->interrupt_in_urb); 728 usb_kill_urb(port->interrupt_in_urb);
753 usb_kill_urb(port->interrupt_out_urb); 729 usb_kill_urb(port->interrupt_out_urb);
754 730
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 731
768 if (stats) 732 if (stats)
769 dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", 733 dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",