[PATCH 2/3] usb: musb: move dma mapping operations to separate functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Moreover, instead of keeping a boolean musb_request.mapped state, three states
are maintained. This allows the unmap operation to be called from more than one
place and to keep track if the mapping is done by the musb driver or anyone
else.

DMA mappings are done after checking musb_ep->dma so where applicable checks for
it are removed. And where possible, checks for is_dma_capable() are merged with
map state check

Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@xxxxxxxxxxxxxx>
---
This patch is based on git://gitorious.org/usb/usb.git musb-hw

 drivers/usb/musb/musb_gadget.c |  122 +++++++++++++++++++++++++---------------
 drivers/usb/musb/musb_gadget.h |    8 ++-
 2 files changed, 84 insertions(+), 46 deletions(-)

diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index edff014..7ee8467 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -92,6 +92,75 @@
 
 /* ----------------------------------------------------------------------- */
 
+#define is_req_mapped(req) (is_dma_capable() && (req->map_state != UN_MAPPED))
+
+static void musb_dma_map_request(struct musb *musb,
+	struct musb_ep *musb_ep, struct musb_request *req)
+{
+	int compatible = true;
+	struct dma_controller *dma = musb->dma_controller;
+
+	req->map_state = UN_MAPPED;
+
+	if (!is_dma_capable() || !musb_ep->dma)
+		return;
+
+	/* Check if DMA engine can handle this request.
+	 * DMA code must reject the USB request explicitly.
+	 * Default behaviour is to map the request.
+	 */
+	if (dma->is_req_compatible)
+		compatible = dma->is_req_compatible(dma, musb_ep,
+							&req->request);
+
+	if (!compatible)
+		return;
+
+	if (req->request.dma == DMA_ADDR_INVALID) {
+		req->request.dma = dma_map_single(
+						musb->controller,
+						req->request.buf,
+						req->request.length,
+						req->tx
+							? DMA_TO_DEVICE
+							: DMA_FROM_DEVICE);
+		req->map_state = MUSB_MAPPED;
+	} else {
+		dma_sync_single_for_device(musb->controller,
+						req->request.dma,
+						req->request.length,
+						req->tx
+							? DMA_TO_DEVICE
+							: DMA_FROM_DEVICE);
+		req->map_state = PRE_MAPPED;
+	}
+}
+
+static void musb_dma_unmap_request(struct musb *musb, struct musb_request *req)
+{
+	if (!is_req_mapped(req))
+		return;
+
+	if (req->map_state == MUSB_MAPPED) {
+		dma_unmap_single(musb->controller,
+				req->request.dma,
+				req->request.length,
+				req->tx
+					? DMA_TO_DEVICE
+					: DMA_FROM_DEVICE);
+		req->request.dma = DMA_ADDR_INVALID;
+	} else { /* PRE_MAPPED */
+		dma_sync_single_for_cpu(musb->controller,
+				req->request.dma,
+				req->request.length,
+				req->tx
+					? DMA_TO_DEVICE
+					: DMA_FROM_DEVICE);
+	}
+
+	req->map_state = UN_MAPPED;
+}
+
 /*
  * Immediately complete a request.
  *
@@ -119,24 +188,9 @@ __acquires(ep->musb->lock)
 
 	ep->busy = 1;
 	spin_unlock(&musb->lock);
-	if (is_dma_capable()) {
-		if (req->mapped) {
-			dma_unmap_single(musb->controller,
-					req->request.dma,
-					req->request.length,
-					req->tx
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-			req->request.dma = DMA_ADDR_INVALID;
-			req->mapped = 0;
-		} else if (req->request.dma != DMA_ADDR_INVALID)
-			dma_sync_single_for_cpu(musb->controller,
-					req->request.dma,
-					req->request.length,
-					req->tx
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-	}
+
+	musb_dma_unmap_request(musb, req);
+
 	if (request->status == 0)
 		DBG(5, "%s done request %p,  %d/%d\n",
 				ep->end_point.name, request,
@@ -298,7 +352,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
 			csr);
 
 #ifndef	CONFIG_MUSB_PIO_ONLY
-	if (is_dma_capable() && musb_ep->dma) {
+	if (is_req_mapped(req)) {
 		struct dma_controller	*c = musb->dma_controller;
 		size_t request_size;
 
@@ -583,7 +637,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 		return;
 	}
 
-	if (is_cppi_enabled() && musb_ep->dma) {
+	if (is_cppi_enabled() && is_req_mapped(req)) {
 		struct dma_controller	*c = musb->dma_controller;
 		struct dma_channel	*channel = musb_ep->dma;
 
@@ -614,7 +668,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 		len = musb_readw(epio, MUSB_RXCOUNT);
 		if (request->actual < request->length) {
 #ifdef CONFIG_USB_INVENTRA_DMA
-			if (is_dma_capable() && musb_ep->dma) {
+			if (is_req_mapped(req)) {
 				struct dma_controller	*c;
 				struct dma_channel	*channel;
 				int			use_dma = 0;
@@ -696,7 +750,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 			fifo_count = min_t(unsigned, len, fifo_count);
 
 #ifdef	CONFIG_USB_TUSB_OMAP_DMA
-			if (tusb_dma_omap() && musb_ep->dma) {
+			if (tusb_dma_omap() && is_req_mapped(req)) {
 				struct dma_controller *c = musb->dma_controller;
 				struct dma_channel *channel = musb_ep->dma;
 				u32 dma_addr = request->dma + request->actual;
@@ -1150,29 +1204,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 	request->epnum = musb_ep->current_epnum;
 	request->tx = musb_ep->is_in;
 
-	if (is_dma_capable() && musb_ep->dma) {
-		if (request->request.dma == DMA_ADDR_INVALID) {
-			request->request.dma = dma_map_single(
-					musb->controller,
-					request->request.buf,
-					request->request.length,
-					request->tx
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-			request->mapped = 1;
-		} else {
-			dma_sync_single_for_device(musb->controller,
-					request->request.dma,
-					request->request.length,
-					request->tx
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-			request->mapped = 0;
-		}
-	} else if (!req->buf) {
-		return -ENODATA;
-	} else
-		request->mapped = 0;
+	musb_dma_map_request(musb, musb_ep, request);
 
 	spin_lock_irqsave(&musb->lock, lockflags);
 
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
index dec8dc0..e481cc8 100644
--- a/drivers/usb/musb/musb_gadget.h
+++ b/drivers/usb/musb/musb_gadget.h
@@ -35,13 +35,19 @@
 #ifndef __MUSB_GADGET_H
 #define __MUSB_GADGET_H
 
+enum dma_map_state {
+	UN_MAPPED = 0,
+	PRE_MAPPED,
+	MUSB_MAPPED
+};
+
 struct musb_request {
 	struct usb_request	request;
 	struct musb_ep		*ep;
 	struct musb		*musb;
 	u8 tx;			/* endpoint direction */
 	u8 epnum;
-	u8 mapped;
+	enum dma_map_state map_state;
 };
 
 static inline struct musb_request *to_musb_request(struct usb_request *req)
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux