diff options
author | marius <marius@FreeBSD.org> | 2006-11-27 18:39:02 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2006-11-27 18:39:02 +0000 |
commit | b92c02c4c737fdf42c084a51fde89a9bafc1cf7e (patch) | |
tree | 2875c8fef4ae52f7b74a86fa304c7b3deeb50140 /sys/dev/usb | |
parent | 2300703ff0d27c5cb6d468e069be12a286688555 (diff) | |
download | FreeBSD-src-b92c02c4c737fdf42c084a51fde89a9bafc1cf7e.zip FreeBSD-src-b92c02c4c737fdf42c084a51fde89a9bafc1cf7e.tar.gz |
Refine the previous change to only call bus_dmamap_sync() in case of
an URQ_REQUEST when DMA segments are passed to usbd_start_transfer();
when the request doesn't include the optional data buffer the size of
the transfer (xfer->length) is 0, in which case usbd_transfer() won't
create a DMA map but call usbd_start_transfer() with no DMA segments.
With the previous change this could result in the bus_dmamap_sync()
implementation dereferencing the NULL-pointer passed as the DMA map
argument.
While at it fix what appears to be a typo in usbd_start_transfer();
in order to determine wheter usbd_start_transfer() was called with
DMA segments check whether the number of segments is > 0 rather than
the pointer to them being > 0.
OK'ed by: imp
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/usbdi.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index 026e4f2..a507eec 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -371,19 +371,26 @@ usbd_start_transfer(void *arg, bus_dma_segment_t *segs, int nseg, int error) } dmap->nsegs = nseg; - if (segs > 0 && !usbd_xfer_isread(xfer)) { - /* Copy data if it is not already in the correct buffer. */ - if (!(xfer->flags & USBD_NO_COPY) && xfer->allocbuf != NULL && - xfer->buffer != xfer->allocbuf) - memcpy(xfer->allocbuf, xfer->buffer, xfer->length); - bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE); - } else { - /* - * Even if we have no data portion we still need to sync the - * dmamap for the request data in the SETUP packet - */ - if (xfer->rqflags & URQ_REQUEST) + if (nseg > 0) { + if (!usbd_xfer_isread(xfer)) { + /* + * Copy data if it is not already in the correct + * buffer. + */ + if (!(xfer->flags & USBD_NO_COPY) && + xfer->allocbuf != NULL && + xfer->buffer != xfer->allocbuf) + memcpy(xfer->allocbuf, xfer->buffer, + xfer->length); bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE); + } else if (xfer->rqflags & URQ_REQUEST) { + /* + * Even if we have no data portion we still need to + * sync the dmamap for the request data in the SETUP + * packet. + */ + bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE); + } } err = pipe->methods->transfer(xfer); if (err != USBD_IN_PROGRESS && err) { |