[PATCH RFC] USB: MUSB: Add support for DMA Mode1 RX for gadget mode

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

 



Enable Mode1 for RX transfers.
This should give a boost of about 30% with g_file_storage.

Add a module param to enable this mode - by default, we keep
the old way (Mode0) so as not to break anything.

To enable this, `echo 1 > /sys/module/musb_hdrc/parameters/dma_mode1_rx`.
To change back, echo 0 to the same node.

NYET-Signed-off-by: Anand Gadiyar <gadiyar@xxxxxx>
NYET-Signed-off-by: Maulik Mankad <x0082077@xxxxxx>
CC: Cliff Cai <cliffcai.sh@xxxxxxxxx>
---

 drivers/usb/musb/musb_gadget.c |   67 +++++++++++++++++++++++++++++------------
 1 file changed, 48 insertions(+), 19 deletions(-)

Index: kernel-omap3-dev/drivers/usb/musb/musb_gadget.c
===================================================================
--- kernel-omap3-dev.orig/drivers/usb/musb/musb_gadget.c
+++ kernel-omap3-dev/drivers/usb/musb/musb_gadget.c
@@ -561,6 +561,19 @@ void musb_g_tx(struct musb *musb, u8 epn
 #endif
 
 /*
+ * Enable DMA Mode 1 for RX transfers. This works reliably only
+ * with g_file_storage at the moment. Enabling this feature will
+ * result in a performance gain of about 30% for at least
+ * g_file_storage use cases.
+ * Making it a module parameter for overriding the short_not_ok check.
+ * so that this can be tested with g_zero, etc.
+ */
+static int musb_use_dma_mode1_rx;
+module_param_named(dma_mode1_rx, musb_use_dma_mode1_rx, bool,
+						S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dma_mode1_rx, "Enable Mode 1 for RX transfers. Default = n");
+
+/*
  * Context: controller locked, IRQs blocked, endpoint selected
  */
 static void rxstate(struct musb *musb, struct musb_request *req)
@@ -572,6 +585,7 @@ static void rxstate(struct musb *musb, s
 	unsigned		fifo_count = 0;
 	u16			len = musb_ep->packet_sz;
 	u16			csr = musb_readw(epio, MUSB_RXCSR);
+	int			use_mode_1 = 0;
 
 	/* We shouldn't get here while DMA is active, but we do... */
 	if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
@@ -614,6 +628,20 @@ static void rxstate(struct musb *musb, s
 
 	if (csr & MUSB_RXCSR_RXPKTRDY) {
 		len = musb_readw(epio, MUSB_RXCOUNT);
+
+		/*
+		 * Alternatively, we can check request->short_not_ok,
+		 * which is true only for g_file_storage. This way
+		 * we use mode1 for the only gadget where it works
+		 * reliably, and all others use mode0
+		 *
+		 * This module param way is only for testing.
+		 */
+		if (musb_use_dma_mode1_rx && len == musb_ep->packet_sz)
+			use_mode_1 = 1;
+		else
+			use_mode_1 = 0;
+
 		if (request->actual < request->length) {
 #ifdef CONFIG_USB_INVENTRA_DMA
 			if (is_dma_capable() && musb_ep->dma) {
@@ -645,28 +673,29 @@ static void rxstate(struct musb *musb, s
 	 * then becomes usable as a runtime "use mode 1" hint...
 	 */
 
-				csr |= MUSB_RXCSR_DMAENAB;
-#ifdef USE_MODE1
-				csr |= MUSB_RXCSR_AUTOCLEAR;
-				/* csr |= MUSB_RXCSR_DMAMODE; */
-
-				/* this special sequence (enabling and then
-				 * disabling MUSB_RXCSR_DMAMODE) is required
-				 * to get DMAReq to activate
-				 */
-				musb_writew(epio, MUSB_RXCSR,
-					csr | MUSB_RXCSR_DMAMODE);
-#endif
-				musb_writew(epio, MUSB_RXCSR, csr);
+		/*
+		 * Experimental: Mode1 works with g_file_storage use cases
+		 * For other drivers, it appears that sometimes an end-point
+		 * interrupt is received before the DMA completion interrupt
+		 *
+		 */
+				if (use_mode_1) {
+					csr |= MUSB_RXCSR_AUTOCLEAR;
+					csr |= MUSB_RXCSR_DMAENAB;
+					musb_writew(epio, MUSB_RXCSR, csr);
+					csr |= MUSB_RXCSR_DMAMODE;
+					musb_writew(epio, MUSB_RXCSR, csr);
+				} else {
+					csr |= MUSB_RXCSR_DMAENAB;
+					musb_writew(epio, MUSB_RXCSR, csr);
+				}
 
 				if (request->actual < request->length) {
 					int transfer_size = 0;
-#ifdef USE_MODE1
-					transfer_size = min(request->length,
-							channel->max_len);
-#else
-					transfer_size = len;
-#endif
+					transfer_size = use_mode_1 ?
+							min(request->length,
+							channel->max_len) : len;
+
 					if (transfer_size <= musb_ep->packet_sz)
 						musb_ep->dma->desired_mode = 0;
 					else
--
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