Set the length of isochronous transfers as the sum of the frames lengths.
authormpi <mpi@openbsd.org>
Mon, 15 Jun 2015 15:45:28 +0000 (15:45 +0000)
committermpi <mpi@openbsd.org>
Mon, 15 Jun 2015 15:45:28 +0000 (15:45 +0000)
This reduces differences between non-isoch and isoch transfers submissions,
makes the generic DMA buffer overrun check work with isoch transfers and
will allow some code simplifications in HC drivers.

Since short-transfers were never checked for isoch transfers, we now need to
pass the USBD_SHORT_XFER_OK flag to not change this behavior.  This might be
revisited later.

ok ratchov@

sys/dev/usb/uaudio.c
sys/dev/usb/ugen.c
sys/dev/usb/usbdi.c

index e23915a..7bdce7a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uaudio.c,v 1.111 2015/05/11 06:46:22 ratchov Exp $ */
+/*     $OpenBSD: uaudio.c,v 1.112 2015/06/15 15:45:28 mpi Exp $ */
 /*     $NetBSD: uaudio.c,v 1.90 2004/10/29 17:12:53 kent Exp $ */
 
 /*
@@ -2938,10 +2938,8 @@ uaudio_chan_ptransfer(struct chan *ch)
 #endif
 
        DPRINTFN(5,("uaudio_chan_ptransfer: transfer xfer=%p\n", cb->xfer));
-       /* Fill the request */
-       usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
-                            ch->nframes, USBD_NO_COPY,
-                            uaudio_chan_pintr);
+       usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, ch->nframes,
+           USBD_NO_COPY | USBD_SHORT_XFER_OK, uaudio_chan_pintr);
 
        (void)usbd_transfer(cb->xfer);
 }
@@ -2996,9 +2994,9 @@ uaudio_chan_psync_transfer(struct chan *ch)
        sb->size = total;
 
        DPRINTFN(5,("%s: transfer xfer=%p\n", __func__, sb->xfer));
-       /* Fill the request */
        usbd_setup_isoc_xfer(sb->xfer, ch->sync_pipe, sb, sb->sizes,
-           ch->nsync_frames, USBD_NO_COPY, uaudio_chan_psync_intr);
+           ch->nsync_frames, USBD_NO_COPY | USBD_SHORT_XFER_OK,
+           uaudio_chan_psync_intr);
 
        (void)usbd_transfer(sb->xfer);
 }
@@ -3095,10 +3093,8 @@ uaudio_chan_rtransfer(struct chan *ch)
 #endif
 
        DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
-       /* Fill the request */
-       usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
-                            ch->nframes, USBD_NO_COPY,
-                            uaudio_chan_rintr);
+       usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, ch->nframes,
+           USBD_NO_COPY | USBD_SHORT_XFER_OK, uaudio_chan_rintr);
 
        (void)usbd_transfer(cb->xfer);
 }
index 22a6220..df31ad7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ugen.c,v 1.83 2015/05/25 11:52:15 mpi Exp $ */
+/*     $OpenBSD: ugen.c,v 1.84 2015/06/15 15:45:28 mpi Exp $ */
 /*     $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $       */
 
@@ -374,11 +374,10 @@ ugenopen(dev_t dev, int flag, int mode, struct proc *p)
                                sce->isoreqs[i].dmabuf = buf;
                                for(j = 0; j < UGEN_NISORFRMS; ++j)
                                        sce->isoreqs[i].sizes[j] = isize;
-                               usbd_setup_isoc_xfer
-                                       (xfer, sce->pipeh, &sce->isoreqs[i],
-                                        sce->isoreqs[i].sizes,
-                                        UGEN_NISORFRMS, USBD_NO_COPY,
-                                        ugen_isoc_rintr);
+                               usbd_setup_isoc_xfer(xfer, sce->pipeh,
+                                   &sce->isoreqs[i], sce->isoreqs[i].sizes,
+                                   UGEN_NISORFRMS, USBD_NO_COPY |
+                                   USBD_SHORT_XFER_OK, ugen_isoc_rintr);
                                (void)usbd_transfer(xfer);
                        }
                        DPRINTFN(5, ("ugenopen: isoc open done\n"));
@@ -874,7 +873,7 @@ ugen_isoc_rintr(struct usbd_xfer *xfer, void *addr, usbd_status status)
        }
 
        usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS,
-                            USBD_NO_COPY, ugen_isoc_rintr);
+           USBD_NO_COPY | USBD_SHORT_XFER_OK, ugen_isoc_rintr);
        (void)usbd_transfer(xfer);
 
        if (sce->state & UGEN_ASLP) {
index 833ed45..428d383 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdi.c,v 1.81 2015/03/14 03:38:50 jsg Exp $ */
+/*     $OpenBSD: usbdi.c,v 1.82 2015/06/15 15:45:28 mpi Exp $ */
 /*     $NetBSD: usbdi.c,v 1.103 2002/09/27 15:37:38 provos Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $      */
 
@@ -280,7 +280,6 @@ usbd_transfer(struct usbd_xfer *xfer)
 {
        struct usbd_pipe *pipe = xfer->pipe;
        usbd_status err;
-       u_int size;
        int flags, s;
 
        if (usbd_is_dying(pipe->device))
@@ -297,25 +296,23 @@ usbd_transfer(struct usbd_xfer *xfer)
        if (pipe->aborting)
                return (USBD_CANCELLED);
 
-       size = xfer->length;
        /* If there is no buffer, allocate one. */
-       if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
+       if ((xfer->rqflags & URQ_DEV_DMABUF) == 0) {
                struct usbd_bus *bus = pipe->device->bus;
 
 #ifdef DIAGNOSTIC
                if (xfer->rqflags & URQ_AUTO_DMABUF)
                        printf("usbd_transfer: has old buffer!\n");
 #endif
-               err = usb_allocmem(bus, size, 0, &xfer->dmabuf);
+               err = usb_allocmem(bus, xfer->length, 0, &xfer->dmabuf);
                if (err)
                        return (err);
                xfer->rqflags |= URQ_AUTO_DMABUF;
        }
 
        /* Copy data if going out. */
-       if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
-           !usbd_xfer_isread(xfer))
-               memcpy(KERNADDR(&xfer->dmabuf, 0), xfer->buffer, size);
+       if (((xfer->flags & USBD_NO_COPY) == 0) && !usbd_xfer_isread(xfer))
+               memcpy(KERNADDR(&xfer->dmabuf, 0), xfer->buffer, xfer->length);
 
        err = pipe->methods->transfer(xfer);
 
@@ -458,10 +455,14 @@ usbd_setup_isoc_xfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
     void *priv, u_int16_t *frlengths, u_int32_t nframes,
     u_int16_t flags, usbd_callback callback)
 {
+       int i;
+
        xfer->pipe = pipe;
        xfer->priv = priv;
        xfer->buffer = 0;
        xfer->length = 0;
+       for (i = 0; i < nframes; i++)
+               xfer->length += frlengths[i];
        xfer->actlen = 0;
        xfer->flags = flags;
        xfer->timeout = USBD_NO_TIMEOUT;
@@ -736,7 +737,7 @@ usb_transfer_complete(struct usbd_xfer *xfer)
                pipe->running = 0;
 
 #ifdef DIAGNOSTIC
-       if (xfer->actlen > xfer->length && xfer->length != 0) {
+       if (xfer->actlen > xfer->length) {
                printf("%s: actlen > len %u > %u\n", __func__, xfer->actlen,
                    xfer->length);
                xfer->actlen = xfer->length;