On Tue, 29 Dec 2009, Sean wrote: > Alan, > > Thanks for the debug patch. I'll send you the dmesg.log output in > another email. It is 2MB. Got it. It's not good enough; the initial error occurred before the start of your extract. Here's yet another version of the patch; this one will stop printing the debug messages when an error is first detected so maybe it won't overrun your log buffer. Alan Stern Index: usb-2.6/drivers/usb/host/ohci-hcd.c =================================================================== --- usb-2.6.orig/drivers/usb/host/ohci-hcd.c +++ usb-2.6/drivers/usb/host/ohci-hcd.c @@ -201,7 +201,7 @@ static int ohci_urb_enqueue ( /* allocate the TDs (deferring hash chain updates) */ for (i = 0; i < size; i++) { - urb_priv->td [i] = td_alloc (ohci, mem_flags); + urb_priv->td [i] = td_alloc (ohci, mem_flags, urb->dev, urb->ep); if (!urb_priv->td [i]) { urb_priv->length = i; urb_free_priv (ohci, urb_priv); @@ -580,6 +580,7 @@ static int ohci_run (struct ohci_hcd *oh struct usb_hcd *hcd = ohci_to_hcd(ohci); disable (ohci); + ohci->testing = 1; /* boot firmware should have set this up (5.1.1.3.1) */ if (first) { Index: usb-2.6/drivers/usb/host/ohci-mem.c =================================================================== --- usb-2.6.orig/drivers/usb/host/ohci-mem.c +++ usb-2.6/drivers/usb/host/ohci-mem.c @@ -82,7 +82,8 @@ dma_to_td (struct ohci_hcd *hc, dma_addr /* TDs ... */ static struct td * -td_alloc (struct ohci_hcd *hc, gfp_t mem_flags) +td_alloc (struct ohci_hcd *hc, gfp_t mem_flags, struct usb_device *udev, + struct usb_host_endpoint *ep) { dma_addr_t dma; struct td *td; @@ -94,6 +95,9 @@ td_alloc (struct ohci_hcd *hc, gfp_t mem td->hwNextTD = cpu_to_hc32 (hc, dma); td->td_dma = dma; /* hashed in td_fill */ + if (hc->testing) + ohci_dbg(hc, "td alloc for %s ep%x: %p\n", + udev->devpath, ep->desc.bEndpointAddress, td); } return td; } @@ -101,14 +105,32 @@ td_alloc (struct ohci_hcd *hc, gfp_t mem static void td_free (struct ohci_hcd *hc, struct td *td) { - struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)]; - - while (*prev && *prev != td) + int hash = TD_HASH_FUNC(td->td_dma); + struct td **prev = &hc->td_hash[hash]; + int n = 0; + + if (hc->testing) + ohci_dbg(hc, "td free %p\n", td); + while (*prev && *prev != td) { + if ((unsigned long) *prev == 0xa7a7a7a7) { + ohci_dbg(hc, "poisoned hash at %p (%d %d) %p\n", prev, + hash, n, hc->td_hash[hash]); + return; + } prev = &(*prev)->td_hash; - if (*prev) + ++n; + } + if (*prev) { *prev = td->td_hash; - else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0) - ohci_dbg (hc, "no hash for td %p\n", td); + if (hc->testing) { + ohci_dbg(hc, "(%d %d) %p -> %p\n", hash, n, prev, *prev); + if (td->td_hash == td) + hc->testing = 0; + } + } else { + ohci_dbg(hc, "no hash for td %p: %d %p\n", td, + hash, hc->td_hash[hash]); + } dma_pool_free (hc->td_cache, td, td->td_dma); } Index: usb-2.6/drivers/usb/host/ohci-q.c =================================================================== --- usb-2.6.orig/drivers/usb/host/ohci-q.c +++ usb-2.6/drivers/usb/host/ohci-q.c @@ -406,7 +406,7 @@ static struct ed *ed_get ( } /* dummy td; end of td list for ed */ - td = td_alloc (ohci, GFP_ATOMIC); + td = td_alloc (ohci, GFP_ATOMIC, udev, ep); if (!td) { /* out of memory */ ed_free (ohci, ed); @@ -560,6 +560,11 @@ td_fill (struct ohci_hcd *ohci, u32 info hash = TD_HASH_FUNC (td->td_dma); td->td_hash = ohci->td_hash [hash]; ohci->td_hash [hash] = td; + if (ohci->testing) { + ohci_dbg(ohci, "hash %p to %d -> %p\n", td, hash, td->td_hash); + if (td->td_hash == td) + ohci->testing = 0; + } /* HC might read the TD (or cachelines) right away ... */ wmb (); Index: usb-2.6/drivers/usb/host/ohci.h =================================================================== --- usb-2.6.orig/drivers/usb/host/ohci.h +++ usb-2.6/drivers/usb/host/ohci.h @@ -346,6 +346,7 @@ typedef struct urb_priv { struct ohci_hcd { spinlock_t lock; + int testing; /* * I/O memory used to communicate with the HC (dma-consistent) -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html