summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2008-02-08 15:08:44 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-24 21:16:35 -0700
commitcaa9ef672a045ba0b19184cd3f872b583f066771 (patch)
treef55bc5f1e2597c947b00d813d9c7568a2d0af02b /drivers/usb
parente01e7fe3886715f083313da409c5850472455d06 (diff)
USB: ehci tolerates some buggy devices
This teaches EHCI how to to work around bugs in certain high speed devices, by accomodating "bulk" packets that exceed the 512 byte constant value required by the USB 2.0 specification. (Have a look at section 5.8.3, paragraphs 1 and 3.) It also makes the descriptor parsing code warn when it encounters such bugs. (We've had reports of maybe two or three such devices, all pretty recent.) Such devices are nonconformant. The proper fix is have the vendors of those devices do the simple, obvious, and correct thing ... which will let them be used with USB hosts that don't have workarounds for this particular vendor bug. But unless/until they do, we can at least have one of the high speed HCDs work with such buggy devices. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/config.c17
-rw-r--r--drivers/usb/host/ehci-q.c16
2 files changed, 32 insertions, 1 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index a92122a216b..568244c99bd 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -145,6 +145,23 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
}
+ /*
+ * Some buggy high speed devices have bulk endpoints using
+ * maxpacket sizes other than 512. High speed HCDs may not
+ * be able to handle that particular bug, so let's warn...
+ */
+ if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
+ && usb_endpoint_xfer_bulk(d)) {
+ unsigned maxp;
+
+ maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff;
+ if (maxp != 512)
+ dev_warn(ddev, "config %d interface %d altsetting %d "
+ "bulk endpoint 0x%X has invalid maxpacket %d\n",
+ cfgno, inum, asnum, d->bEndpointAddress,
+ maxp);
+ }
+
/* Skip over any Class Specific or Vendor Specific descriptors;
* find the next endpoint or interface descriptor */
endpoint->extra = buffer;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 2e49de820b1..c0e752cffc6 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -657,6 +657,14 @@ qh_make (
type = usb_pipetype (urb->pipe);
maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input);
+ /* 1024 byte maxpacket is a hardware ceiling. High bandwidth
+ * acts like up to 3KB, but is built from smaller packets.
+ */
+ if (max_packet(maxp) > 1024) {
+ ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp));
+ goto done;
+ }
+
/* Compute interrupt scheduling parameters just once, and save.
* - allowing for high bandwidth, how many nsec/uframe are used?
* - split transactions need a second CSPLIT uframe; same question
@@ -757,7 +765,13 @@ qh_make (
info2 |= (EHCI_TUNE_MULT_HS << 30);
} else if (type == PIPE_BULK) {
info1 |= (EHCI_TUNE_RL_HS << 28);
- info1 |= 512 << 16; /* usb2 fixed maxpacket */
+ /* The USB spec says that high speed bulk endpoints
+ * always use 512 byte maxpacket. But some device
+ * vendors decided to ignore that, and MSFT is happy
+ * to help them do so. So now people expect to use
+ * such nonconformant devices with Linux too; sigh.
+ */
+ info1 |= max_packet(maxp) << 16;
info2 |= (EHCI_TUNE_MULT_HS << 30);
} else { /* PIPE_INTERRUPT */
info1 |= max_packet (maxp) << 16;