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:
