diff options
Diffstat (limited to 'drivers/usb/serial/quatech2.c')
| -rw-r--r-- | drivers/usb/serial/quatech2.c | 135 |
1 files changed, 61 insertions, 74 deletions
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 2cdfdcc90b37..ffcfc962ab10 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c | |||
| @@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb); | |||
| 143 | 143 | ||
| 144 | static void qt2_release(struct usb_serial *serial) | 144 | static void qt2_release(struct usb_serial *serial) |
| 145 | { | 145 | { |
| 146 | int i; | 146 | struct qt2_serial_private *serial_priv; |
| 147 | 147 | ||
| 148 | kfree(usb_get_serial_data(serial)); | 148 | serial_priv = usb_get_serial_data(serial); |
| 149 | 149 | ||
| 150 | for (i = 0; i < serial->num_ports; i++) | 150 | usb_free_urb(serial_priv->read_urb); |
| 151 | kfree(usb_get_serial_port_data(serial->port[i])); | 151 | kfree(serial_priv); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | static inline int calc_baud_divisor(int baudrate) | 154 | static inline int calc_baud_divisor(int baudrate) |
| @@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port) | |||
| 423 | port_priv->is_open = false; | 423 | port_priv->is_open = false; |
| 424 | 424 | ||
| 425 | spin_lock_irqsave(&port_priv->urb_lock, flags); | 425 | spin_lock_irqsave(&port_priv->urb_lock, flags); |
| 426 | if (port_priv->write_urb->status == -EINPROGRESS) | 426 | usb_kill_urb(port_priv->write_urb); |
| 427 | usb_kill_urb(port_priv->write_urb); | ||
| 428 | port_priv->urb_in_use = false; | 427 | port_priv->urb_in_use = false; |
| 429 | spin_unlock_irqrestore(&port_priv->urb_lock, flags); | 428 | spin_unlock_irqrestore(&port_priv->urb_lock, flags); |
| 430 | 429 | ||
| 430 | mutex_lock(&port->serial->disc_mutex); | ||
| 431 | if (port->serial->disconnected) { | ||
| 432 | mutex_unlock(&port->serial->disc_mutex); | ||
| 433 | return; | ||
| 434 | } | ||
| 435 | |||
| 431 | /* flush the port transmit buffer */ | 436 | /* flush the port transmit buffer */ |
| 432 | i = usb_control_msg(serial->dev, | 437 | i = usb_control_msg(serial->dev, |
| 433 | usb_rcvctrlpipe(serial->dev, 0), | 438 | usb_rcvctrlpipe(serial->dev, 0), |
| @@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port) | |||
| 459 | dev_err(&port->dev, "%s - close port failed %i\n", | 464 | dev_err(&port->dev, "%s - close port failed %i\n", |
| 460 | __func__, i); | 465 | __func__, i); |
| 461 | 466 | ||
| 467 | mutex_unlock(&port->serial->disc_mutex); | ||
| 462 | } | 468 | } |
| 463 | 469 | ||
| 464 | static void qt2_disconnect(struct usb_serial *serial) | 470 | static void qt2_disconnect(struct usb_serial *serial) |
| 465 | { | 471 | { |
| 466 | struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); | 472 | struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); |
| 467 | struct qt2_port_private *port_priv; | ||
| 468 | int i; | ||
| 469 | |||
| 470 | if (serial_priv->read_urb->status == -EINPROGRESS) | ||
| 471 | usb_kill_urb(serial_priv->read_urb); | ||
| 472 | |||
| 473 | usb_free_urb(serial_priv->read_urb); | ||
| 474 | 473 | ||
| 475 | for (i = 0; i < serial->num_ports; i++) { | 474 | usb_kill_urb(serial_priv->read_urb); |
| 476 | port_priv = usb_get_serial_port_data(serial->port[i]); | ||
| 477 | |||
| 478 | if (port_priv->write_urb->status == -EINPROGRESS) | ||
| 479 | usb_kill_urb(port_priv->write_urb); | ||
| 480 | usb_free_urb(port_priv->write_urb); | ||
| 481 | } | ||
| 482 | } | 475 | } |
| 483 | 476 | ||
| 484 | static int get_serial_info(struct usb_serial_port *port, | 477 | static int get_serial_info(struct usb_serial_port *port, |
| @@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb) | |||
| 773 | 766 | ||
| 774 | static int qt2_setup_urbs(struct usb_serial *serial) | 767 | static int qt2_setup_urbs(struct usb_serial *serial) |
| 775 | { | 768 | { |
| 776 | struct usb_serial_port *port; | ||
| 777 | struct usb_serial_port *port0; | 769 | struct usb_serial_port *port0; |
| 778 | struct qt2_serial_private *serial_priv; | 770 | struct qt2_serial_private *serial_priv; |
| 779 | struct qt2_port_private *port_priv; | 771 | int status; |
| 780 | int pcount, status; | ||
| 781 | 772 | ||
| 782 | port0 = serial->port[0]; | 773 | port0 = serial->port[0]; |
| 783 | 774 | ||
| @@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial) | |||
| 795 | sizeof(serial_priv->read_buffer), | 786 | sizeof(serial_priv->read_buffer), |
| 796 | qt2_read_bulk_callback, serial); | 787 | qt2_read_bulk_callback, serial); |
| 797 | 788 | ||
| 798 | /* setup write_urb for each port */ | ||
| 799 | for (pcount = 0; pcount < serial->num_ports; pcount++) { | ||
| 800 | |||
| 801 | port = serial->port[pcount]; | ||
| 802 | port_priv = usb_get_serial_port_data(port); | ||
| 803 | |||
| 804 | port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 805 | if (!port_priv->write_urb) { | ||
| 806 | dev_err(&serial->dev->dev, | ||
| 807 | "failed to alloc write_urb for port %i\n", | ||
| 808 | pcount); | ||
| 809 | return -ENOMEM; | ||
| 810 | } | ||
| 811 | |||
| 812 | usb_fill_bulk_urb(port_priv->write_urb, | ||
| 813 | serial->dev, | ||
| 814 | usb_sndbulkpipe(serial->dev, | ||
| 815 | port0-> | ||
| 816 | bulk_out_endpointAddress), | ||
| 817 | port_priv->write_buffer, | ||
| 818 | sizeof(port_priv->write_buffer), | ||
| 819 | qt2_write_bulk_callback, port); | ||
| 820 | } | ||
| 821 | |||
| 822 | status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL); | 789 | status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL); |
| 823 | if (status != 0) { | 790 | if (status != 0) { |
| 824 | dev_err(&serial->dev->dev, | 791 | dev_err(&serial->dev->dev, |
| 825 | "%s - submit read urb failed %i\n", __func__, status); | 792 | "%s - submit read urb failed %i\n", __func__, status); |
| 793 | usb_free_urb(serial_priv->read_urb); | ||
| 826 | return status; | 794 | return status; |
| 827 | } | 795 | } |
| 828 | 796 | ||
| 829 | return 0; | 797 | return 0; |
| 830 | |||
| 831 | } | 798 | } |
| 832 | 799 | ||
| 833 | static int qt2_attach(struct usb_serial *serial) | 800 | static int qt2_attach(struct usb_serial *serial) |
| 834 | { | 801 | { |
| 835 | struct qt2_serial_private *serial_priv; | 802 | struct qt2_serial_private *serial_priv; |
| 836 | struct qt2_port_private *port_priv; | 803 | int status; |
| 837 | int status, pcount; | ||
| 838 | 804 | ||
| 839 | /* power on unit */ | 805 | /* power on unit */ |
| 840 | status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 806 | status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
| @@ -854,26 +820,6 @@ static int qt2_attach(struct usb_serial *serial) | |||
| 854 | 820 | ||
| 855 | usb_set_serial_data(serial, serial_priv); | 821 | usb_set_serial_data(serial, serial_priv); |
| 856 | 822 | ||
| 857 | for (pcount = 0; pcount < serial->num_ports; pcount++) { | ||
| 858 | port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); | ||
| 859 | if (!port_priv) { | ||
| 860 | dev_err(&serial->dev->dev, | ||
| 861 | "%s- kmalloc(%Zd) failed.\n", __func__, | ||
| 862 | sizeof(*port_priv)); | ||
| 863 | pcount--; | ||
| 864 | status = -ENOMEM; | ||
| 865 | goto attach_failed; | ||
| 866 | } | ||
| 867 | |||
| 868 | spin_lock_init(&port_priv->lock); | ||
| 869 | spin_lock_init(&port_priv->urb_lock); | ||
| 870 | init_waitqueue_head(&port_priv->delta_msr_wait); | ||
| 871 | |||
| 872 | port_priv->port = serial->port[pcount]; | ||
| 873 | |||
| 874 | usb_set_serial_port_data(serial->port[pcount], port_priv); | ||
| 875 | } | ||
| 876 | |||
| 877 | status = qt2_setup_urbs(serial); | 823 | status = qt2_setup_urbs(serial); |
| 878 | if (status != 0) | 824 | if (status != 0) |
| 879 | goto attach_failed; | 825 | goto attach_failed; |
| @@ -881,14 +827,53 @@ static int qt2_attach(struct usb_serial *serial) | |||
| 881 | return 0; | 827 | return 0; |
| 882 | 828 | ||
| 883 | attach_failed: | 829 | attach_failed: |
| 884 | for (/* empty */; pcount >= 0; pcount--) { | ||
| 885 | port_priv = usb_get_serial_port_data(serial->port[pcount]); | ||
| 886 | kfree(port_priv); | ||
| 887 | } | ||
| 888 | kfree(serial_priv); | 830 | kfree(serial_priv); |
| 889 | return status; | 831 | return status; |
| 890 | } | 832 | } |
| 891 | 833 | ||
| 834 | static int qt2_port_probe(struct usb_serial_port *port) | ||
| 835 | { | ||
| 836 | struct usb_serial *serial = port->serial; | ||
| 837 | struct qt2_port_private *port_priv; | ||
| 838 | u8 bEndpointAddress; | ||
| 839 | |||
| 840 | port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); | ||
| 841 | if (!port_priv) | ||
| 842 | return -ENOMEM; | ||
| 843 | |||
| 844 | spin_lock_init(&port_priv->lock); | ||
| 845 | spin_lock_init(&port_priv->urb_lock); | ||
| 846 | init_waitqueue_head(&port_priv->delta_msr_wait); | ||
| 847 | port_priv->port = port; | ||
| 848 | |||
| 849 | port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 850 | if (!port_priv->write_urb) { | ||
| 851 | kfree(port_priv); | ||
| 852 | return -ENOMEM; | ||
| 853 | } | ||
| 854 | bEndpointAddress = serial->port[0]->bulk_out_endpointAddress; | ||
| 855 | usb_fill_bulk_urb(port_priv->write_urb, serial->dev, | ||
| 856 | usb_sndbulkpipe(serial->dev, bEndpointAddress), | ||
| 857 | port_priv->write_buffer, | ||
| 858 | sizeof(port_priv->write_buffer), | ||
| 859 | qt2_write_bulk_callback, port); | ||
| 860 | |||
| 861 | usb_set_serial_port_data(port, port_priv); | ||
| 862 | |||
| 863 | return 0; | ||
| 864 | } | ||
| 865 | |||
| 866 | static int qt2_port_remove(struct usb_serial_port *port) | ||
| 867 | { | ||
| 868 | struct qt2_port_private *port_priv; | ||
| 869 | |||
| 870 | port_priv = usb_get_serial_port_data(port); | ||
| 871 | usb_free_urb(port_priv->write_urb); | ||
| 872 | kfree(port_priv); | ||
| 873 | |||
| 874 | return 0; | ||
| 875 | } | ||
| 876 | |||
| 892 | static int qt2_tiocmget(struct tty_struct *tty) | 877 | static int qt2_tiocmget(struct tty_struct *tty) |
| 893 | { | 878 | { |
| 894 | struct usb_serial_port *port = tty->driver_data; | 879 | struct usb_serial_port *port = tty->driver_data; |
| @@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = { | |||
| 1127 | .attach = qt2_attach, | 1112 | .attach = qt2_attach, |
| 1128 | .release = qt2_release, | 1113 | .release = qt2_release, |
| 1129 | .disconnect = qt2_disconnect, | 1114 | .disconnect = qt2_disconnect, |
| 1115 | .port_probe = qt2_port_probe, | ||
| 1116 | .port_remove = qt2_port_remove, | ||
| 1130 | .dtr_rts = qt2_dtr_rts, | 1117 | .dtr_rts = qt2_dtr_rts, |
| 1131 | .break_ctl = qt2_break_ctl, | 1118 | .break_ctl = qt2_break_ctl, |
| 1132 | .tiocmget = qt2_tiocmget, | 1119 | .tiocmget = qt2_tiocmget, |
