aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Adamson <mark.adamson@ftdichip.com>2009-05-01 06:48:45 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:41 -0400
commit895f28badce96cd903026b0076966e3571b6968e (patch)
tree30881e196227ba32ff78fae9f6ebc37f89dff455
parent094c2e6db4be381f708ad8a2e0532d7782f05ea4 (diff)
USB: ftdi_sio: fix hi-speed device packet size calculation
Added a function to set the packet size to be used based on the value from the device endpoint descriptor. The FT2232H and FT4232H hi-speed devices will have wMaxPacketSize of 512 bytes when connected to a USB 2.0 hi-speed host, but will use alternative descriptors with wMaxPacketSize of 64 bytes if connected to a USB 1.1 host or hub. All other FTDI devices have wMaxPacketSize of 64 bytes, except some FT232R and FT245R devices which customers have mistakenly programmed to have wMaxPacketSize of 0 - this is an error and will be overridden to use wMaxPacketSize of 64 bytes. The packet size used is important as it determines where the driver removes the status bytes from the incoming data. If it is incorrect, it will lead to data corruption. Signed-off-by: Mark J. Adamson <mark.adamson@ftdichip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/serial/ftdi_sio.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 80ccfa13e0b3..74cc3c831604 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -95,6 +95,7 @@ struct ftdi_private {
95 unsigned long tx_bytes; 95 unsigned long tx_bytes;
96 unsigned long tx_outstanding_bytes; 96 unsigned long tx_outstanding_bytes;
97 unsigned long tx_outstanding_urbs; 97 unsigned long tx_outstanding_urbs;
98 unsigned short max_packet_size;
98}; 99};
99 100
100/* struct ftdi_sio_quirk is used by devices requiring special attention. */ 101/* struct ftdi_sio_quirk is used by devices requiring special attention. */
@@ -703,7 +704,6 @@ static const char *ftdi_chip_name[] = {
703 704
704/* Constants for read urb and write urb */ 705/* Constants for read urb and write urb */
705#define BUFSZ 512 706#define BUFSZ 512
706#define PKTSZ 64
707 707
708/* rx_flags */ 708/* rx_flags */
709#define THROTTLED 0x01 709#define THROTTLED 0x01
@@ -1296,6 +1296,45 @@ static void ftdi_determine_type(struct usb_serial_port *port)
1296} 1296}
1297 1297
1298 1298
1299/* Determine the maximum packet size for the device. This depends on the chip
1300 * type and the USB host capabilities. The value should be obtained from the
1301 * device descriptor as the chip will use the appropriate values for the host.*/
1302static void ftdi_set_max_packet_size(struct usb_serial_port *port)
1303{
1304 struct ftdi_private *priv = usb_get_serial_port_data(port);
1305 struct usb_serial *serial = port->serial;
1306 struct usb_device *udev = serial->dev;
1307
1308 struct usb_interface *interface = serial->interface;
1309 struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
1310
1311 unsigned num_endpoints;
1312 int i = 0;
1313
1314 num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
1315 dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
1316
1317 /* NOTE: some customers have programmed FT232R/FT245R devices
1318 * with an endpoint size of 0 - not good. In this case, we
1319 * want to override the endpoint descriptor setting and use a
1320 * value of 64 for wMaxPacketSize */
1321 for (i = 0; i < num_endpoints; i++) {
1322 dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
1323 interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
1324 ep_desc = &interface->cur_altsetting->endpoint[i].desc;
1325 if (ep_desc->wMaxPacketSize == 0) {
1326 ep_desc->wMaxPacketSize = cpu_to_le16(0x40);
1327 dev_info(&udev->dev, "Overriding wMaxPacketSize on endpoint %d\n", i);
1328 }
1329 }
1330
1331 /* set max packet size based on descriptor */
1332 priv->max_packet_size = ep_desc->wMaxPacketSize;
1333
1334 dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
1335}
1336
1337
1299/* 1338/*
1300 * *************************************************************************** 1339 * ***************************************************************************
1301 * Sysfs Attribute 1340 * Sysfs Attribute
@@ -1485,6 +1524,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1485 usb_set_serial_port_data(port, priv); 1524 usb_set_serial_port_data(port, priv);
1486 1525
1487 ftdi_determine_type(port); 1526 ftdi_determine_type(port);
1527 ftdi_set_max_packet_size(port);
1488 read_latency_timer(port); 1528 read_latency_timer(port);
1489 create_sysfs_attrs(port); 1529 create_sysfs_attrs(port);
1490 return 0; 1530 return 0;
@@ -1740,8 +1780,8 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
1740 if (data_offset > 0) { 1780 if (data_offset > 0) {
1741 /* Original sio needs control bytes too... */ 1781 /* Original sio needs control bytes too... */
1742 transfer_size += (data_offset * 1782 transfer_size += (data_offset *
1743 ((count + (PKTSZ - 1 - data_offset)) / 1783 ((count + (priv->max_packet_size - 1 - data_offset)) /
1744 (PKTSZ - data_offset))); 1784 (priv->max_packet_size - data_offset)));
1745 } 1785 }
1746 1786
1747 buffer = kmalloc(transfer_size, GFP_ATOMIC); 1787 buffer = kmalloc(transfer_size, GFP_ATOMIC);
@@ -1763,7 +1803,7 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
1763 if (data_offset > 0) { 1803 if (data_offset > 0) {
1764 /* Original sio requires control byte at start of 1804 /* Original sio requires control byte at start of
1765 each packet. */ 1805 each packet. */
1766 int user_pktsz = PKTSZ - data_offset; 1806 int user_pktsz = priv->max_packet_size - data_offset;
1767 int todo = count; 1807 int todo = count;
1768 unsigned char *first_byte = buffer; 1808 unsigned char *first_byte = buffer;
1769 const unsigned char *current_position = buf; 1809 const unsigned char *current_position = buf;
@@ -1859,7 +1899,7 @@ static void ftdi_write_bulk_callback(struct urb *urb)
1859 data_offset = priv->write_offset; 1899 data_offset = priv->write_offset;
1860 if (data_offset > 0) { 1900 if (data_offset > 0) {
1861 /* Subtract the control bytes */ 1901 /* Subtract the control bytes */
1862 countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ)); 1902 countback -= (data_offset * DIV_ROUND_UP(countback, priv->max_packet_size));
1863 } 1903 }
1864 spin_lock_irqsave(&priv->tx_lock, flags); 1904 spin_lock_irqsave(&priv->tx_lock, flags);
1865 --priv->tx_outstanding_urbs; 1905 --priv->tx_outstanding_urbs;
@@ -1961,7 +2001,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)
1961 2001
1962 /* count data bytes, but not status bytes */ 2002 /* count data bytes, but not status bytes */
1963 countread = urb->actual_length; 2003 countread = urb->actual_length;
1964 countread -= 2 * DIV_ROUND_UP(countread, PKTSZ); 2004 countread -= 2 * DIV_ROUND_UP(countread, priv->max_packet_size);
1965 spin_lock_irqsave(&priv->rx_lock, flags); 2005 spin_lock_irqsave(&priv->rx_lock, flags);
1966 priv->rx_bytes += countread; 2006 priv->rx_bytes += countread;
1967 spin_unlock_irqrestore(&priv->rx_lock, flags); 2007 spin_unlock_irqrestore(&priv->rx_lock, flags);
@@ -2034,7 +2074,7 @@ static void ftdi_process_read(struct work_struct *work)
2034 2074
2035 need_flip = 0; 2075 need_flip = 0;
2036 for (packet_offset = priv->rx_processed; 2076 for (packet_offset = priv->rx_processed;
2037 packet_offset < urb->actual_length; packet_offset += PKTSZ) { 2077 packet_offset < urb->actual_length; packet_offset += priv->max_packet_size) {
2038 int length; 2078 int length;
2039 2079
2040 /* Compare new line status to the old one, signal if different/ 2080 /* Compare new line status to the old one, signal if different/
@@ -2049,7 +2089,7 @@ static void ftdi_process_read(struct work_struct *work)
2049 priv->prev_status = new_status; 2089 priv->prev_status = new_status;
2050 } 2090 }
2051 2091
2052 length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2; 2092 length = min_t(u32, priv->max_packet_size, urb->actual_length-packet_offset)-2;
2053 if (length < 0) { 2093 if (length < 0) {
2054 dev_err(&port->dev, "%s - bad packet length: %d\n", 2094 dev_err(&port->dev, "%s - bad packet length: %d\n",
2055 __func__, length+2); 2095 __func__, length+2);