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