From 8010b90dc64a8d030c5a46921a503a7783e9afb8 Mon Sep 17 00:00:00 2001 From: Nick Hibma Date: Sat, 29 Jan 2000 14:53:47 +0000 Subject: [PATCH] First part of the fix for ohci_hash_find_td panic. Some controllers submit bogus pointers to the Done queue. ohci_hash_find_td fails to find these in its hash and panics. Instead of panicing we now assume the whole done queue is lost and let the timeout code to clean up the mess after us. --- sys/dev/usb/ohci.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index cd08bb984f5a..583e3fd1b733 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1102,9 +1102,24 @@ ohci_process_done(sc, done) DPRINTFN(10,("ohci_process_done: done=0x%08lx\n", (u_long)done)); - /* Reverse the done list. */ - for (sdone = 0; done; done = LE(std->td.td_nexttd)) { - std = ohci_hash_find_td(sc, done); + /* Reverse the done list and store the reversed list in sdone */ + sdone = NULL; + for (; done; done = LE(std->td.td_nexttd)) { + std = ohci_hash_find_td(sc, done & LE(OHCI_TAILMASK)); + if (std == NULL) { +#ifdef OHCI_DEBUG + DPRINTF(("%s: Invalid done queue 0x%08x", + USBDEVNAME(sc->sc_bus.bdev), done)); + ohci_dumpregs(sc); +#endif + /* XXX Should we compare the list of active TDs with + * the list of TDs queued at EDs to handle the ones that + * are not listed on any of the ED queues and therefore + * must be finished? + */ + return; + } + std->dnext = sdone; sdone = std; } @@ -1572,7 +1587,9 @@ ohci_hash_find_td(sc, a) if (std->physaddr == a) return (std); - panic("ohci_hash_find_td: addr 0x%08lx not found\n", (u_long)a); + DPRINTF(("%s: ohci_hash_find_td: addr 0x%08lx not found\n", + USBDEVNAME(sc->sc_bus.bdev), (u_long) a)); + return NULL; } void