From 10d8cebc7abb514ed7a4c384a6d116af3275fcfa Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Mon, 27 Nov 2006 18:39:02 +0000 Subject: [PATCH] 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 --- sys/dev/usb/usbdi.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index 026e4f281720..a507eec61132 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) {