tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: USB lockup



> 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



Home | Main Index | Thread Index | Old Index