diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 118 |
1 files changed, 91 insertions, 27 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 051c3a77b41b..3bfcc7b9f861 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -264,7 +264,7 @@ | |||
264 | /* | 264 | /* |
265 | * Version Information | 265 | * Version Information |
266 | */ | 266 | */ |
267 | #define DRIVER_VERSION "v1.4.1" | 267 | #define DRIVER_VERSION "v1.4.2" |
268 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>" | 268 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>" |
269 | #define DRIVER_DESC "USB FTDI Serial Converters Driver" | 269 | #define DRIVER_DESC "USB FTDI Serial Converters Driver" |
270 | 270 | ||
@@ -687,6 +687,8 @@ struct ftdi_private { | |||
687 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ | 687 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ |
688 | __u8 rx_flags; /* receive state flags (throttling) */ | 688 | __u8 rx_flags; /* receive state flags (throttling) */ |
689 | spinlock_t rx_lock; /* spinlock for receive state */ | 689 | spinlock_t rx_lock; /* spinlock for receive state */ |
690 | struct work_struct rx_work; | ||
691 | int rx_processed; | ||
690 | 692 | ||
691 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ | 693 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ |
692 | 694 | ||
@@ -717,7 +719,7 @@ static int ftdi_write_room (struct usb_serial_port *port); | |||
717 | static int ftdi_chars_in_buffer (struct usb_serial_port *port); | 719 | static int ftdi_chars_in_buffer (struct usb_serial_port *port); |
718 | static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs); | 720 | static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs); |
719 | static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs); | 721 | static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs); |
720 | static void ftdi_process_read (struct usb_serial_port *port); | 722 | static void ftdi_process_read (void *param); |
721 | static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); | 723 | static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); |
722 | static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); | 724 | static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); |
723 | static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); | 725 | static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); |
@@ -1387,6 +1389,8 @@ static int ftdi_common_startup (struct usb_serial *serial) | |||
1387 | port->read_urb->transfer_buffer_length = BUFSZ; | 1389 | port->read_urb->transfer_buffer_length = BUFSZ; |
1388 | } | 1390 | } |
1389 | 1391 | ||
1392 | INIT_WORK(&priv->rx_work, ftdi_process_read, port); | ||
1393 | |||
1390 | /* Free port's existing write urb and transfer buffer. */ | 1394 | /* Free port's existing write urb and transfer buffer. */ |
1391 | if (port->write_urb) { | 1395 | if (port->write_urb) { |
1392 | usb_free_urb (port->write_urb); | 1396 | usb_free_urb (port->write_urb); |
@@ -1617,6 +1621,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) | |||
1617 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 1621 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
1618 | 1622 | ||
1619 | /* Start reading from the device */ | 1623 | /* Start reading from the device */ |
1624 | priv->rx_processed = 0; | ||
1620 | usb_fill_bulk_urb(port->read_urb, dev, | 1625 | usb_fill_bulk_urb(port->read_urb, dev, |
1621 | usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), | 1626 | usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), |
1622 | port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, | 1627 | port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, |
@@ -1667,6 +1672,10 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) | |||
1667 | err("Error from RTS LOW urb"); | 1672 | err("Error from RTS LOW urb"); |
1668 | } | 1673 | } |
1669 | } /* Note change no line if hupcl is off */ | 1674 | } /* Note change no line if hupcl is off */ |
1675 | |||
1676 | /* cancel any scheduled reading */ | ||
1677 | cancel_delayed_work(&priv->rx_work); | ||
1678 | flush_scheduled_work(); | ||
1670 | 1679 | ||
1671 | /* shutdown our bulk read */ | 1680 | /* shutdown our bulk read */ |
1672 | if (port->read_urb) | 1681 | if (port->read_urb) |
@@ -1862,23 +1871,14 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1862 | return; | 1871 | return; |
1863 | } | 1872 | } |
1864 | 1873 | ||
1865 | /* If throttled, delay receive processing until unthrottled. */ | ||
1866 | spin_lock(&priv->rx_lock); | ||
1867 | if (priv->rx_flags & THROTTLED) { | ||
1868 | dbg("Deferring read urb processing until unthrottled"); | ||
1869 | priv->rx_flags |= ACTUALLY_THROTTLED; | ||
1870 | spin_unlock(&priv->rx_lock); | ||
1871 | return; | ||
1872 | } | ||
1873 | spin_unlock(&priv->rx_lock); | ||
1874 | |||
1875 | ftdi_process_read(port); | 1874 | ftdi_process_read(port); |
1876 | 1875 | ||
1877 | } /* ftdi_read_bulk_callback */ | 1876 | } /* ftdi_read_bulk_callback */ |
1878 | 1877 | ||
1879 | 1878 | ||
1880 | static void ftdi_process_read (struct usb_serial_port *port) | 1879 | static void ftdi_process_read (void *param) |
1881 | { /* ftdi_process_read */ | 1880 | { /* ftdi_process_read */ |
1881 | struct usb_serial_port *port = (struct usb_serial_port*)param; | ||
1882 | struct urb *urb; | 1882 | struct urb *urb; |
1883 | struct tty_struct *tty; | 1883 | struct tty_struct *tty; |
1884 | struct ftdi_private *priv; | 1884 | struct ftdi_private *priv; |
@@ -1889,6 +1889,7 @@ static void ftdi_process_read (struct usb_serial_port *port) | |||
1889 | int result; | 1889 | int result; |
1890 | int need_flip; | 1890 | int need_flip; |
1891 | int packet_offset; | 1891 | int packet_offset; |
1892 | unsigned long flags; | ||
1892 | 1893 | ||
1893 | dbg("%s - port %d", __FUNCTION__, port->number); | 1894 | dbg("%s - port %d", __FUNCTION__, port->number); |
1894 | 1895 | ||
@@ -1915,12 +1916,18 @@ static void ftdi_process_read (struct usb_serial_port *port) | |||
1915 | 1916 | ||
1916 | data = urb->transfer_buffer; | 1917 | data = urb->transfer_buffer; |
1917 | 1918 | ||
1918 | /* The first two bytes of every read packet are status */ | 1919 | if (priv->rx_processed) { |
1919 | if (urb->actual_length > 2) { | 1920 | dbg("%s - already processed: %d bytes, %d remain", __FUNCTION__, |
1920 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 1921 | priv->rx_processed, |
1922 | urb->actual_length - priv->rx_processed); | ||
1921 | } else { | 1923 | } else { |
1922 | dbg("Status only: %03oo %03oo",data[0],data[1]); | 1924 | /* The first two bytes of every read packet are status */ |
1923 | } | 1925 | if (urb->actual_length > 2) { |
1926 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | ||
1927 | } else { | ||
1928 | dbg("Status only: %03oo %03oo",data[0],data[1]); | ||
1929 | } | ||
1930 | } | ||
1924 | 1931 | ||
1925 | 1932 | ||
1926 | /* TO DO -- check for hung up line and handle appropriately: */ | 1933 | /* TO DO -- check for hung up line and handle appropriately: */ |
@@ -1929,8 +1936,12 @@ static void ftdi_process_read (struct usb_serial_port *port) | |||
1929 | /* if CD is dropped and the line is not CLOCAL then we should hangup */ | 1936 | /* if CD is dropped and the line is not CLOCAL then we should hangup */ |
1930 | 1937 | ||
1931 | need_flip = 0; | 1938 | need_flip = 0; |
1932 | for (packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ) { | 1939 | for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) { |
1940 | int length; | ||
1941 | |||
1933 | /* Compare new line status to the old one, signal if different */ | 1942 | /* Compare new line status to the old one, signal if different */ |
1943 | /* N.B. packet may be processed more than once, but differences | ||
1944 | * are only processed once. */ | ||
1934 | if (priv != NULL) { | 1945 | if (priv != NULL) { |
1935 | char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK; | 1946 | char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK; |
1936 | if (new_status != priv->prev_status) { | 1947 | if (new_status != priv->prev_status) { |
@@ -1940,6 +1951,35 @@ static void ftdi_process_read (struct usb_serial_port *port) | |||
1940 | } | 1951 | } |
1941 | } | 1952 | } |
1942 | 1953 | ||
1954 | length = min(PKTSZ, urb->actual_length-packet_offset)-2; | ||
1955 | if (length < 0) { | ||
1956 | err("%s - bad packet length: %d", __FUNCTION__, length+2); | ||
1957 | length = 0; | ||
1958 | } | ||
1959 | |||
1960 | /* have to make sure we don't overflow the buffer | ||
1961 | with tty_insert_flip_char's */ | ||
1962 | if (tty->flip.count+length > TTY_FLIPBUF_SIZE) { | ||
1963 | tty_flip_buffer_push(tty); | ||
1964 | need_flip = 0; | ||
1965 | |||
1966 | if (tty->flip.count != 0) { | ||
1967 | /* flip didn't work, this happens when ftdi_process_read() is | ||
1968 | * called from ftdi_unthrottle, because TTY_DONT_FLIP is set */ | ||
1969 | dbg("%s - flip buffer push failed", __FUNCTION__); | ||
1970 | break; | ||
1971 | } | ||
1972 | } | ||
1973 | if (priv->rx_flags & THROTTLED) { | ||
1974 | dbg("%s - throttled", __FUNCTION__); | ||
1975 | break; | ||
1976 | } | ||
1977 | if (tty->ldisc.receive_room(tty)-tty->flip.count < length) { | ||
1978 | /* break out & wait for throttling/unthrottling to happen */ | ||
1979 | dbg("%s - receive room low", __FUNCTION__); | ||
1980 | break; | ||
1981 | } | ||
1982 | |||
1943 | /* Handle errors and break */ | 1983 | /* Handle errors and break */ |
1944 | error_flag = TTY_NORMAL; | 1984 | error_flag = TTY_NORMAL; |
1945 | /* Although the device uses a bitmask and hence can have multiple */ | 1985 | /* Although the device uses a bitmask and hence can have multiple */ |
@@ -1962,13 +2002,8 @@ static void ftdi_process_read (struct usb_serial_port *port) | |||
1962 | error_flag = TTY_FRAME; | 2002 | error_flag = TTY_FRAME; |
1963 | dbg("FRAMING error"); | 2003 | dbg("FRAMING error"); |
1964 | } | 2004 | } |
1965 | if (urb->actual_length > packet_offset + 2) { | 2005 | if (length > 0) { |
1966 | for (i = 2; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length); ++i) { | 2006 | for (i = 2; i < length+2; i++) { |
1967 | /* have to make sure we don't overflow the buffer | ||
1968 | with tty_insert_flip_char's */ | ||
1969 | if(tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
1970 | tty_flip_buffer_push(tty); | ||
1971 | } | ||
1972 | /* Note that the error flag is duplicated for | 2007 | /* Note that the error flag is duplicated for |
1973 | every character received since we don't know | 2008 | every character received since we don't know |
1974 | which character it applied to */ | 2009 | which character it applied to */ |
@@ -2005,6 +2040,35 @@ static void ftdi_process_read (struct usb_serial_port *port) | |||
2005 | tty_flip_buffer_push(tty); | 2040 | tty_flip_buffer_push(tty); |
2006 | } | 2041 | } |
2007 | 2042 | ||
2043 | if (packet_offset < urb->actual_length) { | ||
2044 | /* not completely processed - record progress */ | ||
2045 | priv->rx_processed = packet_offset; | ||
2046 | dbg("%s - incomplete, %d bytes processed, %d remain", | ||
2047 | __FUNCTION__, packet_offset, | ||
2048 | urb->actual_length - packet_offset); | ||
2049 | /* check if we were throttled while processing */ | ||
2050 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
2051 | if (priv->rx_flags & THROTTLED) { | ||
2052 | priv->rx_flags |= ACTUALLY_THROTTLED; | ||
2053 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
2054 | dbg("%s - deferring remainder until unthrottled", | ||
2055 | __FUNCTION__); | ||
2056 | return; | ||
2057 | } | ||
2058 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
2059 | /* if the port is closed stop trying to read */ | ||
2060 | if (port->open_count > 0){ | ||
2061 | /* delay processing of remainder */ | ||
2062 | schedule_delayed_work(&priv->rx_work, 1); | ||
2063 | } else { | ||
2064 | dbg("%s - port is closed", __FUNCTION__); | ||
2065 | } | ||
2066 | return; | ||
2067 | } | ||
2068 | |||
2069 | /* urb is completely processed */ | ||
2070 | priv->rx_processed = 0; | ||
2071 | |||
2008 | /* if the port is closed stop trying to read */ | 2072 | /* if the port is closed stop trying to read */ |
2009 | if (port->open_count > 0){ | 2073 | if (port->open_count > 0){ |
2010 | /* Continue trying to always read */ | 2074 | /* Continue trying to always read */ |
@@ -2444,7 +2508,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port) | |||
2444 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 2508 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
2445 | 2509 | ||
2446 | if (actually_throttled) | 2510 | if (actually_throttled) |
2447 | ftdi_process_read(port); | 2511 | schedule_work(&priv->rx_work); |
2448 | } | 2512 | } |
2449 | 2513 | ||
2450 | static int __init ftdi_init (void) | 2514 | static int __init ftdi_init (void) |