ChangeSet 1.1352.1.2, 2003/10/13 16:21:20-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. - 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...). - Removed some now-pointless usage drivers/usb/host/ehci-dbg.c | 10 ++++++---- drivers/usb/host/ehci-q.c | 30 ++++++++++++++++-------------- drivers/usb/host/ehci.h | 16 +--------------- 3 files changed, 23 insertions(+), 33 deletions(-) diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c --- a/drivers/usb/host/ehci-dbg.c Wed Oct 15 11:08:15 2003 +++ b/drivers/usb/host/ehci-dbg.c Wed Oct 15 11:08:15 2003 @@ -465,7 +465,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]); @@ -495,7 +495,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); struct ehci_qtd *qtd; @@ -528,8 +528,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 Wed Oct 15 11:08:15 2003 +++ b/drivers/usb/host/ehci-q.c Wed Oct 15 11:08:15 2003 @@ -184,7 +184,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--; @@ -224,7 +224,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) { @@ -377,10 +377,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. @@ -461,7 +465,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; @@ -564,11 +568,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. * @@ -728,7 +727,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; @@ -744,6 +743,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. @@ -778,12 +779,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); @@ -797,7 +799,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; } /* usb_clear_halt() means qh data toggle gets reset */ @@ -833,7 +835,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 Wed Oct 15 11:08:15 2003 +++ b/drivers/usb/host/ehci.h Wed Oct 15 11:08:15 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; }; @@ -469,26 +470,11 @@ /*-------------------------------------------------------------------------*/ -#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32) - -#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb) -#define STUB_DEBUG_FILES - -static inline int hcd_register_root (struct usb_hcd *hcd) -{ - return usb_new_device (hcd_to_bus (hcd)->root_hub); -} - -#else /* LINUX_VERSION_CODE */ - #define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags) #ifndef DEBUG #define STUB_DEBUG_FILES #endif /* DEBUG */ - -#endif /* LINUX_VERSION_CODE */ /*-------------------------------------------------------------------------*/