> 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

Reply via email to