> Really hard to help without seeing the full ohcidebug usbhist log. I replaced the panic with abreak out of the done loop. Find attached my diff plus the usbhist from where I first started the offending command (which locks up the second time called). I didn't look into the log myself yet.
Index: ohcivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ohcivar.h,v
retrieving revision 1.58.10.1
diff -u -r1.58.10.1 ohcivar.h
--- ohcivar.h 25 Aug 2018 11:29:52 -0000 1.58.10.1
+++ ohcivar.h 27 Nov 2020 12:08:49 -0000
@@ -59,6 +59,9 @@
uint16_t flags;
#define OHCI_CALL_DONE 0x0001
#define OHCI_ADD_LEN 0x0002
+#ifdef OHCI_DEBUG
+ int beenthere; /* loop detection */
+#endif
} ohci_soft_td_t;
#define OHCI_STD_SIZE ((sizeof(struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN)
#define OHCI_STD_CHUNK 128
@@ -75,6 +78,9 @@
struct usbd_xfer *xfer;
uint16_t flags;
bool isdone; /* used only when DIAGNOSTIC is defined */
+#ifdef OHCI_DEBUG
+ int beenthere; /* loop detection */
+#endif
} ohci_soft_itd_t;
#define OHCI_SITD_SIZE ((sizeof(struct ohci_soft_itd) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN)
#define OHCI_SITD_CHUNK 64
Index: ohci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ohci.c,v
retrieving revision 1.273.6.6
diff -u -r1.273.6.6 ohci.c
--- ohci.c 25 Feb 2020 18:52:44 -0000 1.273.6.6
+++ ohci.c 27 Nov 2020 12:09:01 -0000
@@ -230,6 +230,8 @@
Static void ohci_dump_ed(ohci_softc_t *, ohci_soft_ed_t *);
Static void ohci_dump_itd(ohci_softc_t *, ohci_soft_itd_t *);
Static void ohci_dump_itds(ohci_softc_t *, ohci_soft_itd_t *);
+
+static int ohci_beenthere = 0; /* td list loop detection */
#endif
#define OBARR(sc) bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \
@@ -693,6 +695,13 @@
DPRINTFN(2, "add 0 xfer", 0, 0, 0, 0);
}
+#ifdef OHCI_DEBUG
+ DPRINTFN(10, "--- dump start ---", 0, 0, 0, 0);
+ if (ohcidebug >= 10)
+ ohci_dump_td(sc, sp);
+ DPRINTFN(10, "--- dump end ---", 0, 0, 0, 0);
+#endif
+
/* Last TD gets usb_syncmem'ed by caller */
*ep = cur;
}
@@ -1410,9 +1419,25 @@
OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_WDH);
/* Reverse the done list. */
+#ifdef OHCI_DEBUG
+ ohci_beenthere++;
+#endif
for (sdone = NULL, sidone = NULL; done != 0; ) {
+ DPRINTFN(10, "done=%#jx", (uintptr_t)done, 0, 0, 0);
std = ohci_hash_find_td(sc, done);
if (std != NULL) {
+#ifdef OHCI_DEBUG
+ if (ohcidebug >= 10)
+ ohci_dump_td(sc, std);
+ if (std->beenthere == ohci_beenthere) {
+ DPRINTFN(1, "circular sdone: %#jx->%#jx", (uintptr_t)sdone, (uintptr_t)std, 0, 0);
+#if 0
+ panic("circular sdone");
+#endif
+ break;
+ }
+ std->beenthere = ohci_beenthere;
+#endif
usb_syncmem(&std->dma, std->offs, sizeof(std->td),
BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
std->dnext = sdone;
@@ -1423,6 +1448,20 @@
}
sitd = ohci_hash_find_itd(sc, done);
if (sitd != NULL) {
+#ifdef OHCI_DEBUG
+/* XXX no ohci_dump_itd() yet
+ if (ohcidebug >= 10)
+ ohci_dump_itd(sc, sitd);
+*/
+ if (sitd->beenthere == ohci_beenthere) {
+ DPRINTFN(1, "circular sidone: %#jx->%#jx", (uintptr_t)sidone, (uintptr_t)sitd, 0, 0);
+#if 0
+ panic("circular sidone");
+#endif
+ break;
+ }
+ sitd->beenthere = ohci_beenthere;
+#endif
usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sitd->dnext = sidone;
@@ -1445,6 +1484,7 @@
for (std = sdone; std; std = std->dnext)
ohci_dump_td(sc, std);
}
+/* XXX dump sidone list */
#endif
DPRINTFN(10, "--- TD dump end ---", 0, 0, 0, 0);
@@ -1838,6 +1878,15 @@
KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
+#ifdef OHCI_DEBUG
+ for (ohci_soft_td_t *std2 = LIST_FIRST(&sc->sc_hash_tds[h]);
+ std2 != NULL;
+ std2 = LIST_NEXT(std2, hnext)) {
+ if (std2->physaddr == std->physaddr)
+ panic("OHCI: duplicate physaddr");
+ }
+#endif
+
LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext);
}
@@ -1945,7 +1994,11 @@
void
ohci_dump_tds(ohci_softc_t *sc, ohci_soft_td_t *std)
{
+ ohci_beenthere++;
for (; std; std = std->nexttd) {
+ if (std->beenthere == ohci_beenthere)
+ panic("circular tds");
+ std->beenthere = ohci_beenthere;
ohci_dump_td(sc, std);
KASSERTMSG(std->nexttd == NULL || std != std->nexttd,
"std %p next %p", std, std->nexttd);
@@ -1973,6 +2026,7 @@
(u_long)O32TOH(std->td.td_cbp),
(u_long)O32TOH(std->td.td_nexttd),
(u_long)O32TOH(std->td.td_be), 0);
+ DPRINTF(" nexttd=%#jx", (uintptr_t)std->nexttd, 0, 0, 0);
}
void
Attachment:
usbhist.gz
Description: application/gunzip