summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Segal <dsegal@codeaurora.org>2014-04-08 10:49:55 +0300
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:23:36 -0700
commit060b80f220497ec52a0f400d54087e9bd42e3f56 (patch)
treeca2ca0f2817f672e695fbd940634a76b0857d22c
parentb0129f471bc9ff3e75998d86ede8aef430f7f79d (diff)
usb: gadget: Add support for DMA mapping optimization of request buffers
In order to improve performance, this patch enabled mapping of USB request buffers in advance, before queueing them to the HW. This can be used when there is a pool or pre-mapped request buffers so we don't need to map it again every time the request gets queued. Change-Id: Ic3a6db749343ef1345e0816210517755aee055b3 Signed-off-by: Danny Segal <dsegal@codeaurora.org> Signed-off-by: Mayank Rana <mrana@codeaurora.org>
-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);