Similiar to [1], this patch uses the USBD_NO_COPY flag to utilize the DMA
buffer directly within ugen_do_write() of ugen(4).

Grant

References
1. MARC.info - 'do bulk reads with one transfer in ugen(4)' thread
http://marc.info/?t=144114650800001&r=1&w=2

Index: ugen.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ugen.c,v
retrieving revision 1.86
diff -u -p -d -r1.86 ugen.c
--- ugen.c      3 Sep 2015 07:50:22 -0000       1.86
+++ ugen.c      3 Sep 2015 20:43:57 -0000
@@ -645,6 +645,7 @@ ugen_do_write(struct ugen_softc *sc, int
        u_int32_t n;
        int flags, error = 0;
        char buf[UGEN_BBSIZE];
+       void *ptr = 0;
        struct usbd_xfer *xfer;
        usbd_status err;
 
@@ -666,7 +667,7 @@ ugen_do_write(struct ugen_softc *sc, int
                return (EIO);
        }
 #endif
-       flags = USBD_SYNCHRONOUS;
+       flags = USBD_SYNCHRONOUS | USBD_NO_COPY;
        if (sce->timeout == 0)
                flags |= USBD_CATCH;
 
@@ -675,12 +676,17 @@ ugen_do_write(struct ugen_softc *sc, int
                xfer = usbd_alloc_xfer(sc->sc_udev);
                if (xfer == 0)
                        return (EIO);
-               while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
-                       error = uiomovei(buf, n, uio);
+               if ((n = uio->uio_resid) != 0) {
+                       ptr = usbd_alloc_buffer(xfer, n);
+                       if (ptr == NULL) {
+                               error = ENOMEM;
+                               goto done;
+                       }
+                       error = uiomovei(ptr, n, uio);
                        if (error)
-                               break;
+                               goto done;
                        DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
-                       usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
+                       usbd_setup_xfer(xfer, sce->pipeh, 0, NULL, n,
                            flags, sce->timeout, NULL);
                        err = usbd_transfer(xfer);
                        if (err) {
@@ -691,9 +697,9 @@ ugen_do_write(struct ugen_softc *sc, int
                                        error = ETIMEDOUT;
                                else
                                        error = EIO;
-                               break;
                        }
                }
+       done:
                usbd_free_xfer(xfer);
                break;
        case UE_INTERRUPT:

Reply via email to