diff options
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 191 |
1 files changed, 19 insertions, 172 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 6e437f9e4b9b..a41974e17687 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * USB FTDI SIO driver | 2 | * USB FTDI SIO driver |
3 | * | 3 | * |
4 | * Copyright (C) 2009 - 2010 | ||
5 | * Johan Hovold (jhovold@gmail.com) | ||
4 | * Copyright (C) 1999 - 2001 | 6 | * Copyright (C) 1999 - 2001 |
5 | * Greg Kroah-Hartman (greg@kroah.com) | 7 | * Greg Kroah-Hartman (greg@kroah.com) |
6 | * Bill Ryder (bryder@sgi.com) | 8 | * Bill Ryder (bryder@sgi.com) |
@@ -49,8 +51,8 @@ | |||
49 | /* | 51 | /* |
50 | * Version Information | 52 | * Version Information |
51 | */ | 53 | */ |
52 | #define DRIVER_VERSION "v1.5.0" | 54 | #define DRIVER_VERSION "v1.6.0" |
53 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>, Andreas Mohr" | 55 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>, Andreas Mohr, Johan Hovold <jhovold@gmail.com>" |
54 | #define DRIVER_DESC "USB FTDI Serial Converters Driver" | 56 | #define DRIVER_DESC "USB FTDI Serial Converters Driver" |
55 | 57 | ||
56 | static int debug; | 58 | static int debug; |
@@ -87,9 +89,6 @@ struct ftdi_private { | |||
87 | be enabled */ | 89 | be enabled */ |
88 | 90 | ||
89 | unsigned int latency; /* latency setting in use */ | 91 | unsigned int latency; /* latency setting in use */ |
90 | spinlock_t tx_lock; /* spinlock for transmit state */ | ||
91 | unsigned long tx_outstanding_bytes; | ||
92 | unsigned long tx_outstanding_urbs; | ||
93 | unsigned short max_packet_size; | 92 | unsigned short max_packet_size; |
94 | struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() and change_speed() */ | 93 | struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() and change_speed() */ |
95 | }; | 94 | }; |
@@ -784,12 +783,9 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port); | |||
784 | static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port); | 783 | static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port); |
785 | static void ftdi_close(struct usb_serial_port *port); | 784 | static void ftdi_close(struct usb_serial_port *port); |
786 | static void ftdi_dtr_rts(struct usb_serial_port *port, int on); | 785 | static void ftdi_dtr_rts(struct usb_serial_port *port, int on); |
787 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
788 | const unsigned char *buf, int count); | ||
789 | static int ftdi_write_room(struct tty_struct *tty); | ||
790 | static int ftdi_chars_in_buffer(struct tty_struct *tty); | ||
791 | static void ftdi_write_bulk_callback(struct urb *urb); | ||
792 | static void ftdi_process_read_urb(struct urb *urb); | 786 | static void ftdi_process_read_urb(struct urb *urb); |
787 | static int ftdi_prepare_write_buffer(struct usb_serial_port *port, | ||
788 | void **dest, size_t size, const void *buf, size_t count); | ||
793 | static void ftdi_set_termios(struct tty_struct *tty, | 789 | static void ftdi_set_termios(struct tty_struct *tty, |
794 | struct usb_serial_port *port, struct ktermios *old); | 790 | struct usb_serial_port *port, struct ktermios *old); |
795 | static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); | 791 | static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); |
@@ -816,6 +812,8 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
816 | .id_table = id_table_combined, | 812 | .id_table = id_table_combined, |
817 | .num_ports = 1, | 813 | .num_ports = 1, |
818 | .bulk_in_size = 512, | 814 | .bulk_in_size = 512, |
815 | /* Must modify prepare_write_buffer if multi_urb_write is changed. */ | ||
816 | .multi_urb_write = 1, | ||
819 | .probe = ftdi_sio_probe, | 817 | .probe = ftdi_sio_probe, |
820 | .port_probe = ftdi_sio_port_probe, | 818 | .port_probe = ftdi_sio_port_probe, |
821 | .port_remove = ftdi_sio_port_remove, | 819 | .port_remove = ftdi_sio_port_remove, |
@@ -824,11 +822,8 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
824 | .dtr_rts = ftdi_dtr_rts, | 822 | .dtr_rts = ftdi_dtr_rts, |
825 | .throttle = usb_serial_generic_throttle, | 823 | .throttle = usb_serial_generic_throttle, |
826 | .unthrottle = usb_serial_generic_unthrottle, | 824 | .unthrottle = usb_serial_generic_unthrottle, |
827 | .write = ftdi_write, | ||
828 | .write_room = ftdi_write_room, | ||
829 | .chars_in_buffer = ftdi_chars_in_buffer, | ||
830 | .process_read_urb = ftdi_process_read_urb, | 825 | .process_read_urb = ftdi_process_read_urb, |
831 | .write_bulk_callback = ftdi_write_bulk_callback, | 826 | .prepare_write_buffer = ftdi_prepare_write_buffer, |
832 | .tiocmget = ftdi_tiocmget, | 827 | .tiocmget = ftdi_tiocmget, |
833 | .tiocmset = ftdi_tiocmset, | 828 | .tiocmset = ftdi_tiocmset, |
834 | .ioctl = ftdi_ioctl, | 829 | .ioctl = ftdi_ioctl, |
@@ -844,9 +839,6 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
844 | #define HIGH 1 | 839 | #define HIGH 1 |
845 | #define LOW 0 | 840 | #define LOW 0 |
846 | 841 | ||
847 | /* number of outstanding urbs to prevent userspace DoS from happening */ | ||
848 | #define URB_UPPER_LIMIT 42 | ||
849 | |||
850 | /* | 842 | /* |
851 | * *************************************************************************** | 843 | * *************************************************************************** |
852 | * Utility functions | 844 | * Utility functions |
@@ -1536,7 +1528,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1536 | } | 1528 | } |
1537 | 1529 | ||
1538 | kref_init(&priv->kref); | 1530 | kref_init(&priv->kref); |
1539 | spin_lock_init(&priv->tx_lock); | ||
1540 | mutex_init(&priv->cfg_lock); | 1531 | mutex_init(&priv->cfg_lock); |
1541 | init_waitqueue_head(&priv->delta_msr_wait); | 1532 | init_waitqueue_head(&priv->delta_msr_wait); |
1542 | 1533 | ||
@@ -1761,31 +1752,15 @@ static void ftdi_close(struct usb_serial_port *port) | |||
1761 | * | 1752 | * |
1762 | * The new devices do not require this byte | 1753 | * The new devices do not require this byte |
1763 | */ | 1754 | */ |
1764 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | 1755 | static int ftdi_prepare_write_buffer(struct usb_serial_port *port, |
1765 | const unsigned char *buf, int count) | 1756 | void **dest, size_t size, const void *src, size_t count) |
1766 | { | 1757 | { |
1767 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1758 | struct ftdi_private *priv; |
1768 | struct urb *urb; | ||
1769 | unsigned char *buffer; | 1759 | unsigned char *buffer; |
1770 | int data_offset ; /* will be 1 for the SIO and 0 otherwise */ | 1760 | int data_offset ; /* will be 1 for the SIO and 0 otherwise */ |
1771 | int status; | ||
1772 | int transfer_size; | 1761 | int transfer_size; |
1773 | unsigned long flags; | ||
1774 | |||
1775 | dbg("%s port %d, %d bytes", __func__, port->number, count); | ||
1776 | 1762 | ||
1777 | if (count == 0) { | 1763 | priv = usb_get_serial_port_data(port); |
1778 | dbg("write request of 0 bytes"); | ||
1779 | return 0; | ||
1780 | } | ||
1781 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1782 | if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) { | ||
1783 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1784 | dbg("%s - write limit hit", __func__); | ||
1785 | return 0; | ||
1786 | } | ||
1787 | priv->tx_outstanding_urbs++; | ||
1788 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1789 | 1764 | ||
1790 | data_offset = priv->write_offset; | 1765 | data_offset = priv->write_offset; |
1791 | dbg("data_offset set to %d", data_offset); | 1766 | dbg("data_offset set to %d", data_offset); |
@@ -1801,17 +1776,9 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1801 | 1776 | ||
1802 | buffer = kmalloc(transfer_size, GFP_ATOMIC); | 1777 | buffer = kmalloc(transfer_size, GFP_ATOMIC); |
1803 | if (!buffer) { | 1778 | if (!buffer) { |
1804 | dev_err(&port->dev, | 1779 | dev_err(&port->dev, "%s - could not allocate buffer\n", |
1805 | "%s ran out of kernel memory for urb ...\n", __func__); | 1780 | __func__); |
1806 | count = -ENOMEM; | 1781 | return -ENOMEM; |
1807 | goto error_no_buffer; | ||
1808 | } | ||
1809 | |||
1810 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
1811 | if (!urb) { | ||
1812 | dev_err(&port->dev, "%s - no more free urbs\n", __func__); | ||
1813 | count = -ENOMEM; | ||
1814 | goto error_no_urb; | ||
1815 | } | 1782 | } |
1816 | 1783 | ||
1817 | /* Copy data */ | 1784 | /* Copy data */ |
@@ -1821,7 +1788,7 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1821 | int user_pktsz = priv->max_packet_size - data_offset; | 1788 | int user_pktsz = priv->max_packet_size - data_offset; |
1822 | int todo = count; | 1789 | int todo = count; |
1823 | unsigned char *first_byte = buffer; | 1790 | unsigned char *first_byte = buffer; |
1824 | const unsigned char *current_position = buf; | 1791 | const unsigned char *current_position = src; |
1825 | 1792 | ||
1826 | while (todo > 0) { | 1793 | while (todo > 0) { |
1827 | if (user_pktsz > todo) | 1794 | if (user_pktsz > todo) |
@@ -1836,134 +1803,14 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1836 | todo -= user_pktsz; | 1803 | todo -= user_pktsz; |
1837 | } | 1804 | } |
1838 | } else { | 1805 | } else { |
1839 | /* No control byte required. */ | 1806 | memcpy(buffer, src, count); |
1840 | /* Copy in the data to send */ | ||
1841 | memcpy(buffer, buf, count); | ||
1842 | } | 1807 | } |
1843 | 1808 | ||
1844 | usb_serial_debug_data(debug, &port->dev, __func__, | 1809 | *dest = buffer; |
1845 | transfer_size, buffer); | ||
1846 | |||
1847 | /* fill the buffer and send it */ | ||
1848 | usb_fill_bulk_urb(urb, port->serial->dev, | ||
1849 | usb_sndbulkpipe(port->serial->dev, | ||
1850 | port->bulk_out_endpointAddress), | ||
1851 | buffer, transfer_size, | ||
1852 | ftdi_write_bulk_callback, port); | ||
1853 | |||
1854 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
1855 | if (status) { | ||
1856 | dev_err(&port->dev, | ||
1857 | "%s - failed submitting write urb, error %d\n", | ||
1858 | __func__, status); | ||
1859 | count = status; | ||
1860 | goto error; | ||
1861 | } else { | ||
1862 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1863 | priv->tx_outstanding_bytes += count; | ||
1864 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1865 | } | ||
1866 | 1810 | ||
1867 | /* we are done with this urb, so let the host driver | ||
1868 | * really free it when it is finished with it */ | ||
1869 | usb_free_urb(urb); | ||
1870 | |||
1871 | dbg("%s write returning: %d", __func__, count); | ||
1872 | return count; | ||
1873 | error: | ||
1874 | usb_free_urb(urb); | ||
1875 | error_no_urb: | ||
1876 | kfree(buffer); | ||
1877 | error_no_buffer: | ||
1878 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1879 | priv->tx_outstanding_urbs--; | ||
1880 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1881 | return count; | 1811 | return count; |
1882 | } | 1812 | } |
1883 | 1813 | ||
1884 | /* This function may get called when the device is closed */ | ||
1885 | static void ftdi_write_bulk_callback(struct urb *urb) | ||
1886 | { | ||
1887 | unsigned long flags; | ||
1888 | struct usb_serial_port *port = urb->context; | ||
1889 | struct ftdi_private *priv; | ||
1890 | int data_offset; /* will be 1 for the SIO and 0 otherwise */ | ||
1891 | unsigned long countback; | ||
1892 | int status = urb->status; | ||
1893 | |||
1894 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
1895 | kfree(urb->transfer_buffer); | ||
1896 | |||
1897 | dbg("%s - port %d", __func__, port->number); | ||
1898 | |||
1899 | priv = usb_get_serial_port_data(port); | ||
1900 | if (!priv) { | ||
1901 | dbg("%s - bad port private data pointer - exiting", __func__); | ||
1902 | return; | ||
1903 | } | ||
1904 | /* account for transferred data */ | ||
1905 | countback = urb->transfer_buffer_length; | ||
1906 | data_offset = priv->write_offset; | ||
1907 | if (data_offset > 0) { | ||
1908 | /* Subtract the control bytes */ | ||
1909 | countback -= (data_offset * DIV_ROUND_UP(countback, priv->max_packet_size)); | ||
1910 | } | ||
1911 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1912 | --priv->tx_outstanding_urbs; | ||
1913 | priv->tx_outstanding_bytes -= countback; | ||
1914 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1915 | |||
1916 | if (status) { | ||
1917 | dbg("nonzero write bulk status received: %d", status); | ||
1918 | } | ||
1919 | |||
1920 | usb_serial_port_softint(port); | ||
1921 | } | ||
1922 | |||
1923 | static int ftdi_write_room(struct tty_struct *tty) | ||
1924 | { | ||
1925 | struct usb_serial_port *port = tty->driver_data; | ||
1926 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1927 | int room; | ||
1928 | unsigned long flags; | ||
1929 | |||
1930 | dbg("%s - port %d", __func__, port->number); | ||
1931 | |||
1932 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1933 | if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) { | ||
1934 | /* | ||
1935 | * We really can take anything the user throws at us | ||
1936 | * but let's pick a nice big number to tell the tty | ||
1937 | * layer that we have lots of free space | ||
1938 | */ | ||
1939 | room = 2048; | ||
1940 | } else { | ||
1941 | room = 0; | ||
1942 | } | ||
1943 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1944 | return room; | ||
1945 | } | ||
1946 | |||
1947 | static int ftdi_chars_in_buffer(struct tty_struct *tty) | ||
1948 | { | ||
1949 | struct usb_serial_port *port = tty->driver_data; | ||
1950 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1951 | int buffered; | ||
1952 | unsigned long flags; | ||
1953 | |||
1954 | dbg("%s - port %d", __func__, port->number); | ||
1955 | |||
1956 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1957 | buffered = (int)priv->tx_outstanding_bytes; | ||
1958 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1959 | if (buffered < 0) { | ||
1960 | dev_err(&port->dev, "%s outstanding tx bytes is negative!\n", | ||
1961 | __func__); | ||
1962 | buffered = 0; | ||
1963 | } | ||
1964 | return buffered; | ||
1965 | } | ||
1966 | |||
1967 | static int ftdi_process_packet(struct tty_struct *tty, | 1814 | static int ftdi_process_packet(struct tty_struct *tty, |
1968 | struct usb_serial_port *port, struct ftdi_private *priv, | 1815 | struct usb_serial_port *port, struct ftdi_private *priv, |
1969 | char *packet, int len) | 1816 | char *packet, int len) |