In message <200311200326.hAK3Qqvf024651_at_green.bikeshed.org>, "Brian F. Feldman" writes: >Jeez, it's been broken a year and it's almost 5.2-RELEASE now. Does anyone >have ANY leads on these problems? I know precisely nothing about how my USB >hardware is supposed to work, but this OHCI+EHCI stuff definitely doesn't, >and it's really not uncommon at all. Is it unbroken in NetBSD currently? I had some success with this patch: Index: usb_mem.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/usb_mem.c,v retrieving revision 1.5 diff -u -r1.5 usb_mem.c --- usb_mem.c 4 Oct 2003 22:13:21 -0000 1.5 +++ usb_mem.c 27 Oct 2003 15:39:03 -0000 _at__at_ -142,7 +142,8 _at__at_ s = splusb(); /* First check the free list. */ for (p = LIST_FIRST(&usb_blk_freelist); p; p = LIST_NEXT(p, next)) { - if (p->tag == tag && p->size >= size && p->align >= align) { + if (p->tag == tag && p->size >= size && p->size < size * 2 && + p->align >= align) { LIST_REMOVE(p, next); usb_blk_nfree--; splx(s); It seems that since the conversion to busdma, the USB code can end up attempting to use contigmalloc() to allocate multi-page regions from an interrupt thread(!). The above doesn't fix that; it just prevents successful large (e.g 64k) contiguous allocations from being wasted when a much smaller amount of space is needed. With the above, I was able to use ohci+ehci fairly reliably on a Soekris box with a large USB2 disk attached via a cardbus USB2 adaptor. I also have a few other local patches that may help too - some of them are below: Ian Index: ohci.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/ohci.c,v retrieving revision 1.132 diff -u -r1.132 ohci.c --- ohci.c 24 Aug 2003 17:55:54 -0000 1.132 +++ ohci.c 21 Sep 2003 15:28:27 -0000 _at__at_ -1405,12 +1405,13 _at__at_ if (std->flags & OHCI_ADD_LEN) xfer->actlen += len; if (std->flags & OHCI_CALL_DONE) { + ohci_free_std(sc, std); /* XXX */ xfer->status = USBD_NORMAL_COMPLETION; s = splusb(); usb_transfer_complete(xfer); splx(s); - } - ohci_free_std(sc, std); + } else + ohci_free_std(sc, std); } else { /* * Endpoint is halted. First unlink all the TDs _at__at_ -2246,6 +2247,7 _at__at_ usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer); usb_transfer_complete(xfer); splx(s); + return; } if (xfer->device->bus->intr_context || !curproc) Index: usbdi.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/usbdi.c,v retrieving revision 1.82 diff -u -r1.82 usbdi.c --- usbdi.c 24 Aug 2003 17:55:55 -0000 1.82 +++ usbdi.c 21 Sep 2003 15:28:29 -0000 _at__at_ -751,6 +751,7 _at__at_ pipe, xfer, pipe->methods)); /* Make the HC abort it (and invoke the callback). */ pipe->methods->abort(xfer); + KASSERT(SIMPLEQ_FIRST(&pipe->queue) != xfer, ("usbd_ar_pipe")); /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ } pipe->aborting = 0; _at__at_ -763,8 +764,9 _at__at_ { usbd_pipe_handle pipe = xfer->pipe; usb_dma_t *dmap = &xfer->dmabuf; + usbd_status status; int repeat = pipe->repeat; - int polling; + int polling, xfer_flags; SPLUSBCHECK; _at__at_ -835,30 +837,33 _at__at_ xfer->status = USBD_SHORT_XFER; } - if (xfer->callback) - xfer->callback(xfer, xfer->priv, xfer->status); - -#ifdef DIAGNOSTIC - if (pipe->methods->done != NULL) + /* Copy any xfer fields in case the xfer goes away in the callback. */ + status = xfer->status; + xfer_flags = xfer->flags; + /* + * For repeat operations, call the callback first, as the xfer + * will not go away and the "done" method may modify it. Otherwise + * reverse the order in case the callback wants to free or reuse + * the xfer. + */ + if (repeat) { + if (xfer->callback) + xfer->callback(xfer, xfer->priv, status); pipe->methods->done(xfer); - else - printf("usb_transfer_complete: pipe->methods->done == NULL\n"); -#else - pipe->methods->done(xfer); -#endif - - if ((xfer->flags & USBD_SYNCHRONOUS) && !polling) - wakeup(xfer); + } else { + pipe->methods->done(xfer); + if (xfer->callback) + xfer->callback(xfer, xfer->priv, status); - if (!repeat) { /* XXX should we stop the queue on all errors? */ - if ((xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT) && + if ((status == USBD_CANCELLED || status == USBD_TIMEOUT) && pipe->iface != NULL) /* not control pipe */ pipe->running = 0; else usbd_start_next(pipe); } + if ((xfer_flags & USBD_SYNCHRONOUS) && !polling) + wakeup(xfer); } usbd_status _at__at_ -879,6 +884,7 _at__at_ xfer->busy_free = XFER_ONQU; #endif s = splusb(); + KASSERT(SIMPLEQ_FIRST(&pipe->queue) != xfer, ("usb_insert_transfer")); SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next); if (pipe->running) err = USBD_IN_PROGRESS; Index: usbdi_util.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/usbdi_util.c,v retrieving revision 1.31 diff -u -r1.31 usbdi_util.c --- usbdi_util.c 24 Aug 2003 17:55:55 -0000 1.31 +++ usbdi_util.c 21 Sep 2003 15:28:30 -0000 _at__at_ -440,7 +440,7 _at__at_ } usbd_get_xfer_status(xfer, NULL, NULL, size, &err); DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size)); - if (err) { + if (err == USBD_STALLED) { DPRINTF(("usbd_bulk_transfer: error=%d\n", err)); usbd_clear_endpoint_stall(pipe); }Received on Thu Nov 20 2003 - 00:12:04 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:30 UTC