[PATCH v1 2/2] usb: musb: introduce api for dma code to check compatibility with usb request

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

 



Gadget MUSB driver handles dma mappings in musb_gadget_queue(). Where as it is
possible for  dma code to reject the usb request later at ->channel_program()
called from txstate()/rxstate()

For example ->channel_program in tusb6010_omap.c:

static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
        u8 rndis_mode, dma_addr_t dma_addr, u32 len)
{
...
	if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
		return false;
...
	if (dma_addr & 0x2)
		return false;
...
}

In this case, usb request will be handled in PIO mode which renders dma mapping
operations unnecessary.

This patch adds an api to allow dma code to indicate incompatibility with usb
request. Gadget musb driver call this api, if available, before dma mappings to
avoid any unnecessary mapping operations.

Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@xxxxxxxxxxxxxx>
---
This patch is based on Greg's usb-next branch

Changelog from previous version:
	- API addition and use is combined into one patch
	- Arguments for is_compatable() are now similar to channel_program()

Althought the arguments for is_compatible() are now valid for both host and
gadget modes, there is currently no use of this API in host mode. As Sergei
mentioned, host mode buffers are mapped by the higher layers. Suggestions are
welcome on how to avoid unnecessary dma mappings for the host side.

 drivers/usb/musb/musb_dma.h    |    3 +++
 drivers/usb/musb/musb_gadget.c |   14 ++++++++++++++
 2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 916065b..3a97c4e 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -169,6 +169,9 @@ struct dma_controller {
 							dma_addr_t dma_addr,
 							u32 length);
 	int			(*channel_abort)(struct dma_channel *);
+	int			(*is_compatible)(struct dma_channel *channel,
+							u16 maxpacket,
+							void *buf, u32 length);
 };
 
 /* called after channel_program(), may indicate a fault */
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index a8dd64e..29b7cc5 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -100,11 +100,25 @@
 static inline void map_dma_buffer(struct musb_request *request,
 			struct musb *musb, struct musb_ep *musb_ep)
 {
+	int compatible = true;
+	struct dma_controller *dma = musb->dma_controller;
+
 	request->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_compatible)
+		compatible = dma->is_compatible(musb_ep->dma,
+				musb_ep->packet_sz, request->request.buf,
+				request->request.length);
+	if (!compatible)
+		return;
+
 	if (request->request.dma == DMA_ADDR_INVALID) {
 		request->request.dma = dma_map_single(
 				musb->controller,
-- 
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