ChangeSet 1.1148.6.11, 2003/10/14 16:48:33-07:00, david-b@pacbell.net [PATCH] USB: ehci-hcd, misc bugfixes This fixes some bugs observed in the EHCI code: - Byte-order confusion caused the wrong address to be set on big-endian hardware (reported last week on PPC and SPARC). That bug's been there for about a year, with no problem reports ... hmm. (a while less on 2.4) - Used the wrong bitmask to determine max packet size for interrupt transfers, so they were limited to 1023 bytes (not 1024 bytes) at high speed. - Because those two problems related to the masking, I sanity checked it and moved more of byteswapping to compile time. - Removes some oopsing in the (debug) periodic schedule dump, seen with patches that add more interesting behaviors (which folk are finally trying...). drivers/usb/host/ehci-dbg.c | 10 ++++++---- drivers/usb/host/ehci-q.c | 30 ++++++++++++++++-------------- drivers/usb/host/ehci.h | 1 + 3 files changed, 23 insertions(+), 18 deletions(-) diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c --- a/drivers/usb/host/ehci-dbg.c Fri Oct 24 17:01:01 2003 +++ b/drivers/usb/host/ehci-dbg.c Fri Oct 24 17:01:01 2003 @@ -471,7 +471,7 @@ spin_lock_irqsave (&ehci->lock, flags); for (i = 0; i < ehci->periodic_size; i++) { p = ehci->pshadow [i]; - if (!p.ptr) + if (likely (!p.ptr)) continue; tag = Q_NEXT_TYPE (ehci->periodic [i]); @@ -491,7 +491,7 @@ break; } /* show more info the first time around */ - if (temp == seen_count) { + if (temp == seen_count && p.ptr) { u32 scratch = cpu_to_le32p ( &p.qh->hw_info1); @@ -509,8 +509,10 @@ seen [seen_count++].qh = p.qh; } else temp = 0; - tag = Q_NEXT_TYPE (p.qh->hw_next); - p = p.qh->qh_next; + if (p.qh) { + tag = Q_NEXT_TYPE (p.qh->hw_next); + p = p.qh->qh_next; + } break; case Q_TYPE_FSTN: temp = snprintf (next, size, diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c Fri Oct 24 17:01:01 2003 +++ b/drivers/usb/host/ehci-q.c Fri Oct 24 17:01:01 2003 @@ -189,7 +189,7 @@ struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw_info2 & cpu_to_le32 (0x00ff)) != 0) { + if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--; @@ -257,7 +257,7 @@ * Chases up to qh->hw_current. Returns number of completions called, * indicating how much "real" work we did. */ -#define HALT_BIT cpu_to_le32(QTD_STS_HALT) +#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT) static unsigned qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs) { @@ -410,10 +410,14 @@ return count; } -#undef HALT_BIT /*-------------------------------------------------------------------------*/ +// high bandwidth multiplier, as encoded in highspeed endpoint descriptors +#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) +// ... and packet size, for any kind of endpoint descriptor +#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) + /* * reverse of qh_urb_transaction: free a list of TDs. * used for cleanup after errors, before HC sees an URB's TDs. @@ -494,7 +498,7 @@ token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ - maxpacket = usb_maxpacket (urb->dev, urb->pipe, !is_input) & 0x03ff; + maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); /* * buffer gets wrapped in one or more qtds; @@ -597,11 +601,6 @@ // That'd mean updating how usbcore talks to HCDs. (2.5?) -// high bandwidth multiplier, as encoded in highspeed endpoint descriptors -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -// ... and packet size, for any kind of endpoint descriptor -#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x03ff) - /* * Each QH holds a qtd list; a QH is used for everything except iso. * @@ -766,7 +765,7 @@ } } - qh->hw_token &= ~__constant_cpu_to_le32 (QTD_STS_HALT); + qh->hw_token &= ~HALT_BIT; /* splice right after start */ qh->qh_next = head->qh_next; @@ -782,6 +781,8 @@ /*-------------------------------------------------------------------------*/ +#define QH_ADDR_MASK __constant_le32_to_cpu(0x7f) + /* * For control/bulk/interrupt, return QH with these TDs appended. * Allocates and initializes the QH if necessary. @@ -816,12 +817,13 @@ /* control qh may need patching after enumeration */ if (unlikely (epnum == 0)) { /* set_address changes the address */ - if (le32_to_cpu (qh->hw_info1 & 0x7f) == 0) + if ((qh->hw_info1 & QH_ADDR_MASK) == 0) qh->hw_info1 |= cpu_to_le32 ( usb_pipedevice (urb->pipe)); /* for full speed, ep0 maxpacket can grow */ - else if (!(qh->hw_info1 & cpu_to_le32 (0x3 << 12))) { + else if (!(qh->hw_info1 + & __constant_cpu_to_le32 (0x3 << 12))) { u32 info, max; info = le32_to_cpu (qh->hw_info1); @@ -835,7 +837,7 @@ /* usb_reset_device() briefly reverts to address 0 */ if (usb_pipedevice (urb->pipe) == 0) - qh->hw_info1 &= cpu_to_le32(~0x7f); + qh->hw_info1 &= ~QH_ADDR_MASK; } /* NOTE: changing config or interface setting is not @@ -875,7 +877,7 @@ * HC is allowed to fetch the old dummy (4.10.2). */ token = qtd->hw_token; - qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); + qtd->hw_token = HALT_BIT; wmb (); dummy = qh->dummy; diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h --- a/drivers/usb/host/ehci.h Fri Oct 24 17:01:01 2003 +++ b/drivers/usb/host/ehci.h Fri Oct 24 17:01:01 2003 @@ -325,6 +325,7 @@ struct ehci_itd *itd; /* Q_TYPE_ITD */ struct ehci_sitd *sitd; /* Q_TYPE_SITD */ struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ + u32 *hw_next; /* (all types) */ void *ptr; };