Everyone who has seen the ohci_hash_find_td not found panic should try this one and let me know whether the machine panics or not and where. This patch is against CURRENT. It looks like the hardware kind of deviates from the OHCI spec when putting things on the Done queue in case of an error. Important: Your system will panic and completely destroy your filesystem. If it doesn't you got lucky. Cheers, Nick -- [EMAIL PROTECTED] [EMAIL PROTECTED] USB project http://www.etla.net/~n_hibma/
Index: ohci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/ohci.c,v retrieving revision 1.36 diff -w -u -r1.36 ohci.c --- ohci.c 2000/01/29 16:25:55 1.36 +++ ohci.c 2000/01/29 17:04:44 @@ -91,7 +91,7 @@ #ifdef OHCI_DEBUG #define DPRINTF(x) if (ohcidebug) logprintf x #define DPRINTFN(n,x) if (ohcidebug>(n)) logprintf x -int ohcidebug = 0; +int ohcidebug = 1; #else #define DPRINTF(x) #define DPRINTFN(n,x) @@ -417,6 +417,7 @@ usbd_status err; int i, offs; usb_dma_t dma; + int s; if (sc->sc_freetds == NULL) { DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n")); @@ -436,6 +437,11 @@ sc->sc_freetds = std->nexttd; memset(&std->td, 0, sizeof(ohci_td_t)); std->nexttd = NULL; + + s = splusb(); + ohci_hash_add_td(sc, std); + splx(s); + return (std); } @@ -444,6 +450,12 @@ ohci_softc_t *sc; ohci_soft_td_t *std; { + int s; + + s = splusb(); + ohci_hash_rem_td(sc, std); + splx(s); + std->nexttd = sc->sc_freetds; sc->sc_freetds = std; } @@ -1127,7 +1139,8 @@ #ifdef OHCI_DEBUG if (ohcidebug > 10) { DPRINTF(("ohci_process_done: TD done:\n")); - ohci_dump_tds(sdone); + for (std = sdone; std; std = std->dnext) + ohci_dump_td(sdone); } #endif @@ -1135,7 +1148,16 @@ xfer = std->xfer; stdnext = std->dnext; DPRINTFN(5, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n", - std, xfer, xfer->hcpriv)); + std, xfer, (xfer? xfer->hcpriv:NULL))); + if (xfer == NULL || (std->flags & OHCI_TD_HANDLED)) { + /* xfer == NULL: There seems to be no xfer associated + * with this TD. It is tailp that happened to end up on + * the done queue. + * flags & OHCI_TD_HANDLED: The TD has already been + * handled by process_done and should not be done again. + */ + continue; + } cc = OHCI_TD_GET_CC(LE(std->td.td_flags)); usb_untimeout(ohci_timeout, xfer, xfer->timo_handle); if (xfer->status == USBD_CANCELLED || @@ -1156,7 +1178,6 @@ xfer->status = USBD_NORMAL_COMPLETION; usb_transfer_complete(xfer); } - ohci_hash_rem_td(sc, std); ohci_free_std(sc, std); } else { /* @@ -1172,16 +1193,23 @@ OHCI_TD_GET_CC(LE(std->td.td_flags)), ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td.td_flags))], xfer)); + + /* Mark all the TDs in the done queue for the current + * xfer as handled + */ + for (p = stdnext; p; p = p->dnext) { + if (p->xfer == xfer) + p->flags |= OHCI_TD_HANDLED; + } - /* remove TDs */ + /* remove TDs for the current xfer from the ED */ for (p = std; p->xfer == xfer; p = n) { n = p->nexttd; - ohci_hash_rem_td(sc, p); ohci_free_std(sc, p); } - - /* clear halt */ opipe->sed->ed.ed_headp = LE(p->physaddr); + + /* XXX why is this being done? Why not OHCI_BLF too */ OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); if (cc == OHCI_CC_STALL) @@ -1462,10 +1490,6 @@ /* Insert ED in schedule */ s = splusb(); - ohci_hash_add_td(sc, setup); - if (len != 0) - ohci_hash_add_td(sc, data); - ohci_hash_add_td(sc, stat); sed->ed.ed_tailp = LE(tail->physaddr); opipe->tail.td = tail; OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); @@ -1870,7 +1894,6 @@ #endif for (; p->xfer == xfer; p = n) { n = p->nexttd; - ohci_hash_rem_td(sc, p); ohci_free_std(sc, p); } Index: ohcivar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/ohcivar.h,v retrieving revision 1.15 diff -w -u -r1.15 ohcivar.h --- ohcivar.h 2000/01/27 23:25:58 1.15 +++ ohcivar.h 2000/01/29 12:28:25 @@ -57,6 +57,7 @@ u_int16_t flags; #define OHCI_CALL_DONE 0x0001 #define OHCI_ADD_LEN 0x0002 +#define OHCI_TD_HANDLED 0x0004 /* signal process_done has seen it */ } 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