diff options
Diffstat (limited to '')
| -rw-r--r-- | drivers/usb/gadget/udc/udc-core.c | 10 | ||||
| -rw-r--r-- | include/linux/usb/gadget.h | 6 |
2 files changed, 14 insertions, 2 deletions
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index f660afba715d..c148a4fdfe99 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -76,7 +76,7 @@ int usb_gadget_map_request(struct usb_gadget *gadget, } req->num_mapped_sgs = mapped; - } else { + } else if (!req->dma_pre_mapped) { req->dma = dma_map_single(dev, req->buf, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); @@ -101,9 +101,15 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->num_mapped_sgs = 0; - } else { + } else if (!req->dma_pre_mapped && req->dma != DMA_ERROR_CODE) { + /* + * If the DMA address has not been mapped by a higher layer, + * then unmap it here. Otherwise, the DMA address will be + * unmapped by the upper layer (where the request was queued). + */ dma_unmap_single(gadget->dev.parent, req->dma, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + req->dma = DMA_ERROR_CODE; } } EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 3f572d5dc16d..ab06d2988505 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -118,6 +118,11 @@ struct gsi_channel_info { * by adding a zero length packet as needed; * @short_not_ok: When reading data, makes short packets be * treated as errors (queue stops advancing till cleanup). + * @dma_pre_mapped: Tells the USB core driver whether this request should be + * DMA-mapped before it is queued to the USB HW. When set to true, it means + * that the request has already been mapped in advance and therefore the + * USB core driver does NOT need to do DMA-mapping when the request is + * queued to the USB HW. * @complete: Function called when request completes, so this request and * its buffer may be re-used. The function will always be called with * interrupts disabled, and it must not sleep. @@ -174,6 +179,7 @@ struct usb_request { unsigned no_interrupt:1; unsigned zero:1; unsigned short_not_ok:1; + unsigned dma_pre_mapped:1; void (*complete)(struct usb_ep *ep, struct usb_request *req); |
