On Thu, 24 Apr 2014, Matteo Fortini wrote:
After some time, we finally had another hangup on kernel 3.14.
@Alan: Here's the info we got in the files you mentioned. At any rate,
we're keeping the board in the same state so that we can run/produce any
other needed info.
http://pastebin.com/DZPAqjcd
To find out exactly what's going wrong, I need more information. Below
is a patch you can apply that will add more data to the "registers"
file in the /sys/kernel/debug/usb/ohci/* directory.
Run with the patched kernel, and the next time you get a similar hang,
see what's in the "registers" file. In fact, since the contents change
over time, make two copies of the file, a few seconds apart.
Alan Stern
Index: usb-3.14/drivers/usb/host/ohci-dbg.c
===================================================================
--- usb-3.14.orig/drivers/usb/host/ohci-dbg.c
+++ usb-3.14/drivers/usb/host/ohci-dbg.c
@@ -108,6 +108,9 @@ ohci_dump_status (struct ohci_hcd *contr
0x03 & (temp >> 4), (temp & 0x0f),
(temp & 0x0100) ? "with" : "NO",
rh_state_string(controller));
+ ohci_dbg_sw(controller, next, size,
+ "WDH count %u SF count %u\n",
+ controller->wdh_count, controller->sf_count);
temp = ohci_readl (controller, ®s->control);
ohci_dbg_sw (controller, next, size,
@@ -354,6 +357,48 @@ ohci_dump_ed (const struct ohci_hcd *ohc
}
}
+static void ohci_dump_ed_rm_list(struct ohci_hcd *ohci,
+ char **next, unsigned *size)
+{
+ unsigned temp;
+ struct ed *ed;
+ struct td *td, *td2;
+ unsigned tdptr, tdptr2;
+ unsigned tddma, tddma2;
+ unsigned info;
+
+ temp = scnprintf(*next, *size, "ed_rm_list:\n");
+ *size -= temp;
+ *next += temp;
+
+ for (ed = ohci->ed_rm_list; ed; ed = ed->ed_next) {
+ info = hc32_to_cpu(ohci, ed->hwINFO);
+ tdptr = tdptr2 = 0;
+ tddma = tddma2 = 0;
+ if (!list_empty(&ed->td_list)) {
+ td = list_first_entry(&ed->td_list, struct td, td_list);
+ tdptr = hc32_to_cpu(ohci, ed->hwHeadP) & TD_MASK;
+ tddma = (unsigned) td->td_dma;
+
+ if (list_is_last(&td->td_list, &ed->td_list))
+ td2 = ed->dummy;
+ else
+ td2 = list_first_entry(&td->td_list,
+ struct td, td_list);
+ tdptr2 = hc32_to_cpu(ohci, td->hwNextTD) & TD_MASK;
+ tddma2 = (unsigned) td2->td_dma;
+ }
+
+ temp = scnprintf(*next, *size,
+ " ED dev %d ep %x(%d) tick %04x td1 %x %x td2 %x %x\n",
+ info & 0x7f, (info >> 7) & 0xf,
+ (info >> 11) & 0x3,
+ ed->tick, tddma, tdptr, tddma2, tdptr2);
+ *size -= temp;
+ *next += temp;
+ }
+}
+
/*-------------------------------------------------------------------------*/
static int debug_async_open(struct inode *, struct file *);
@@ -652,6 +697,8 @@ static ssize_t fill_registers_buffer(str
/* roothub */
ohci_dump_roothub (ohci, 1, &next, &size);
+ ohci_dump_ed_rm_list(ohci, &next, &size);
+
done:
spin_unlock_irqrestore (&ohci->lock, flags);
Index: usb-3.14/drivers/usb/host/ohci-hcd.c
===================================================================
--- usb-3.14.orig/drivers/usb/host/ohci-hcd.c
+++ usb-3.14/drivers/usb/host/ohci-hcd.c
@@ -866,6 +866,7 @@ static irqreturn_t ohci_irq (struct usb_
if (ints & OHCI_INTR_WDH) {
spin_lock (&ohci->lock);
dl_done_list (ohci);
+ ++ohci->wdh_count;
spin_unlock (&ohci->lock);
}
@@ -902,6 +903,8 @@ static irqreturn_t ohci_irq (struct usb_
spin_lock (&ohci->lock);
if (ohci->ed_rm_list)
finish_unlinks (ohci, ohci_frame_no(ohci));
+ if (ints & OHCI_INTR_SF)
+ ++ohci->sf_count;
if ((ints & OHCI_INTR_SF) != 0
&& !ohci->ed_rm_list
&& !ohci->ed_to_check
Index: usb-3.14/drivers/usb/host/ohci.h
===================================================================
--- usb-3.14.orig/drivers/usb/host/ohci.h
+++ usb-3.14/drivers/usb/host/ohci.h
@@ -415,6 +415,8 @@ struct ohci_hcd {
struct ed *ed_to_check;
unsigned zf_delay;
+ unsigned sf_count, wdh_count;
+
struct dentry *debug_dir;
struct dentry *debug_async;
struct dentry *debug_periodic;