summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/usb/gadget/udc/udc-core.c10
-rw-r--r--include/linux/usb/gadget.h6
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);