summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>2000-01-29 14:53:47 +0000
committern_hibma <n_hibma@FreeBSD.org>2000-01-29 14:53:47 +0000
commit46a154cb23043ade36c1e8a9adcbf5904807522d (patch)
tree749ec3a61b3fa9280cf66385ca2123bae55f869e /sys/dev/usb
parent8760ab7a11702ac115a8d6fa5b93c224c28531cd (diff)
downloadFreeBSD-src-46a154cb23043ade36c1e8a9adcbf5904807522d.zip
FreeBSD-src-46a154cb23043ade36c1e8a9adcbf5904807522d.tar.gz
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.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/ohci.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index cd08bb9..583e3fd 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
OpenPOWER on IntegriCloud