usb: musb: Enable DMA mode1 RX for transfers without short packets
authorAnand Gadiyar <gadiyar@ti.com>
Wed, 20 Jul 2011 05:11:58 +0000 (22:11 -0700)
committerFelipe Balbi <balbi@ti.com>
Fri, 9 Sep 2011 10:08:17 +0000 (13:08 +0300)
This patch enables DMA mode1 for the RX path when we know
there won't be any short packets. We check that by looking
into the short_no_ok flag, if it's true we enable mode1, otherwise
we use mode0 to transfer the data.

This will result in a throughput performance gain of around
40% for USB mass-storage/mtp use cases.

[ balbi@ti.com : updated commit log and code comments slightly ]

Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
Tested-by: Vikram Pandita <vikram.pandita@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/musb/musb_gadget.c

index 44b331a..82434dd 100644 (file)
@@ -634,6 +634,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
        u16                     len;
        u16                     csr = musb_readw(epio, MUSB_RXCSR);
        struct musb_hw_ep       *hw_ep = &musb->endpoints[epnum];
+       u8                      use_mode_1;
 
        if (hw_ep->is_shared_fifo)
                musb_ep = &hw_ep->ep_in;
@@ -683,6 +684,18 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 
        if (csr & MUSB_RXCSR_RXPKTRDY) {
                len = musb_readw(epio, MUSB_RXCOUNT);
+
+               /*
+                * Enable Mode 1 on RX transfers only when short_not_ok flag
+                * is set. Currently short_not_ok flag is set only from
+                * file_storage and f_mass_storage drivers
+                */
+
+               if (request->short_not_ok && 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_buffer_mapped(req)) {
@@ -714,37 +727,41 @@ static void rxstate(struct musb *musb, struct musb_request *req)
         * 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);
-#else
-                               if (!musb_ep->hb_mult &&
-                                       musb_ep->hw_ep->rx_double_buffered)
+                               /* Experimental: Mode1 works with mass storage use cases */
+                               if (use_mode_1) {
                                        csr |= MUSB_RXCSR_AUTOCLEAR;
-#endif
-                               musb_writew(epio, MUSB_RXCSR, csr);
+                                       musb_writew(epio, MUSB_RXCSR, csr);
+                                       csr |= MUSB_RXCSR_DMAENAB;
+                                       musb_writew(epio, MUSB_RXCSR, csr);
+
+                                       /*
+                                        * 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);
+                                       musb_writew(epio, MUSB_RXCSR, csr);
+
+                               } else {
+                                       if (!musb_ep->hb_mult &&
+                                               musb_ep->hw_ep->rx_double_buffered)
+                                               csr |= MUSB_RXCSR_AUTOCLEAR;
+                                       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 - request->actual,
-                                                       channel->max_len);
-#else
-                                       transfer_size = min(request->length - request->actual,
-                                                       (unsigned)len);
-#endif
-                                       if (transfer_size <= musb_ep->packet_sz)
-                                               musb_ep->dma->desired_mode = 0;
-                                       else
+                                       if (use_mode_1) {
+                                               transfer_size = min(request->length - request->actual,
+                                                               channel->max_len);
                                                musb_ep->dma->desired_mode = 1;
+                                       } else {
+                                               transfer_size = min(request->length - request->actual,
+                                                               (unsigned)len);
+                                               musb_ep->dma->desired_mode = 0;
+                                       }
 
                                        use_dma = c->channel_program(
                                                        channel,