In message <[EMAIL PROTECTED]>, "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
@@ -142,7 +142,8 @@
        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
@@ -1405,12 +1405,13 @@
                        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
@@ -2246,6 +2247,7 @@
                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
@@ -751,6 +751,7 @@
                            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;
@@ -763,8 +764,9 @@
 {
        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;
 
@@ -835,30 +837,33 @@
                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
@@ -879,6 +884,7 @@
        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
@@ -440,7 +440,7 @@
        }
        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);
        }
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to