Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 151319
b: refs/heads/master
c: 895f28b
h: refs/heads/master
i:
  151317: 84ec1ff
  151315: ebe0b89
  151311: 3801eb3
v: v3
  • Loading branch information
Mark Adamson authored and Greg Kroah-Hartman committed Jun 16, 2009
1 parent bc6dac4 commit ccd61f5
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 094c2e6db4be381f708ad8a2e0532d7782f05ea4
refs/heads/master: 895f28badce96cd903026b0076966e3571b6968e
56 changes: 48 additions & 8 deletions trunk/drivers/usb/serial/ftdi_sio.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ struct ftdi_private {
unsigned long tx_bytes;
unsigned long tx_outstanding_bytes;
unsigned long tx_outstanding_urbs;
unsigned short max_packet_size;
};

/* struct ftdi_sio_quirk is used by devices requiring special attention. */
Expand Down Expand Up @@ -703,7 +704,6 @@ static const char *ftdi_chip_name[] = {

/* Constants for read urb and write urb */
#define BUFSZ 512
#define PKTSZ 64

/* rx_flags */
#define THROTTLED 0x01
Expand Down Expand Up @@ -1296,6 +1296,45 @@ static void ftdi_determine_type(struct usb_serial_port *port)
}


/* Determine the maximum packet size for the device. This depends on the chip
* type and the USB host capabilities. The value should be obtained from the
* device descriptor as the chip will use the appropriate values for the host.*/
static void ftdi_set_max_packet_size(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
struct usb_device *udev = serial->dev;

struct usb_interface *interface = serial->interface;
struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;

unsigned num_endpoints;
int i = 0;

num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);

/* NOTE: some customers have programmed FT232R/FT245R devices
* with an endpoint size of 0 - not good. In this case, we
* want to override the endpoint descriptor setting and use a
* value of 64 for wMaxPacketSize */
for (i = 0; i < num_endpoints; i++) {
dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
ep_desc = &interface->cur_altsetting->endpoint[i].desc;
if (ep_desc->wMaxPacketSize == 0) {
ep_desc->wMaxPacketSize = cpu_to_le16(0x40);
dev_info(&udev->dev, "Overriding wMaxPacketSize on endpoint %d\n", i);
}
}

/* set max packet size based on descriptor */
priv->max_packet_size = ep_desc->wMaxPacketSize;

dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
}


/*
* ***************************************************************************
* Sysfs Attribute
Expand Down Expand Up @@ -1485,6 +1524,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
usb_set_serial_port_data(port, priv);

ftdi_determine_type(port);
ftdi_set_max_packet_size(port);
read_latency_timer(port);
create_sysfs_attrs(port);
return 0;
Expand Down Expand Up @@ -1740,8 +1780,8 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
if (data_offset > 0) {
/* Original sio needs control bytes too... */
transfer_size += (data_offset *
((count + (PKTSZ - 1 - data_offset)) /
(PKTSZ - data_offset)));
((count + (priv->max_packet_size - 1 - data_offset)) /
(priv->max_packet_size - data_offset)));
}

buffer = kmalloc(transfer_size, GFP_ATOMIC);
Expand All @@ -1763,7 +1803,7 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
if (data_offset > 0) {
/* Original sio requires control byte at start of
each packet. */
int user_pktsz = PKTSZ - data_offset;
int user_pktsz = priv->max_packet_size - data_offset;
int todo = count;
unsigned char *first_byte = buffer;
const unsigned char *current_position = buf;
Expand Down Expand Up @@ -1859,7 +1899,7 @@ static void ftdi_write_bulk_callback(struct urb *urb)
data_offset = priv->write_offset;
if (data_offset > 0) {
/* Subtract the control bytes */
countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ));
countback -= (data_offset * DIV_ROUND_UP(countback, priv->max_packet_size));
}
spin_lock_irqsave(&priv->tx_lock, flags);
--priv->tx_outstanding_urbs;
Expand Down Expand Up @@ -1961,7 +2001,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)

/* count data bytes, but not status bytes */
countread = urb->actual_length;
countread -= 2 * DIV_ROUND_UP(countread, PKTSZ);
countread -= 2 * DIV_ROUND_UP(countread, priv->max_packet_size);
spin_lock_irqsave(&priv->rx_lock, flags);
priv->rx_bytes += countread;
spin_unlock_irqrestore(&priv->rx_lock, flags);
Expand Down Expand Up @@ -2034,7 +2074,7 @@ static void ftdi_process_read(struct work_struct *work)

need_flip = 0;
for (packet_offset = priv->rx_processed;
packet_offset < urb->actual_length; packet_offset += PKTSZ) {
packet_offset < urb->actual_length; packet_offset += priv->max_packet_size) {
int length;

/* Compare new line status to the old one, signal if different/
Expand All @@ -2049,7 +2089,7 @@ static void ftdi_process_read(struct work_struct *work)
priv->prev_status = new_status;
}

length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2;
length = min_t(u32, priv->max_packet_size, urb->actual_length-packet_offset)-2;
if (length < 0) {
dev_err(&port->dev, "%s - bad packet length: %d\n",
__func__, length+2);
Expand Down

0 comments on commit ccd61f5

Please sign in to comment.