> 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