aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ftdi_sio.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2010-05-05 17:44:17 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:42 -0400
commitd3901a064cfedf892c00704aa4e51d119f04a65e (patch)
tree5c80f8903db255cefee628697cb8e6038765320a /drivers/usb/serial/ftdi_sio.c
parente07afd3fb906647d37108206075834f8c670b7e3 (diff)
USB: ftdi_sio: switch to generic write implementation
Switch to the generic, multi-urb, write implementation. Note that this will also make it fairly easy to use the generic fifo-based write implementation: simply unset the multi_urb_write flag and modify prepare_write_buffer (or unset if not using a legacy SIO device). This may be desirable for instance on an embedded system where optimal throughput at high baudrates may not be as important as other factors (e.g. no allocations during runtime and less pressure on host stack). Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r--drivers/usb/serial/ftdi_sio.c191
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
56static int debug; 58static 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);
784static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port); 783static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port);
785static void ftdi_close(struct usb_serial_port *port); 784static void ftdi_close(struct usb_serial_port *port);
786static void ftdi_dtr_rts(struct usb_serial_port *port, int on); 785static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
787static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
788 const unsigned char *buf, int count);
789static int ftdi_write_room(struct tty_struct *tty);
790static int ftdi_chars_in_buffer(struct tty_struct *tty);
791static void ftdi_write_bulk_callback(struct urb *urb);
792static void ftdi_process_read_urb(struct urb *urb); 786static void ftdi_process_read_urb(struct urb *urb);
787static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
788 void **dest, size_t size, const void *buf, size_t count);
793static void ftdi_set_termios(struct tty_struct *tty, 789static 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);
795static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); 791static 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 */
1764static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, 1755static 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;
1873error:
1874 usb_free_urb(urb);
1875error_no_urb:
1876 kfree(buffer);
1877error_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 */
1885static 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
1923static 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
1947static 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
1967static int ftdi_process_packet(struct tty_struct *tty, 1814static 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)