Commit 0ae52d54 authored by Anand Gadiyar's avatar Anand Gadiyar Committed by Felipe Balbi

usb: musb: Enable DMA mode1 RX for transfers without short packets

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: default avatarAnand Gadiyar <gadiyar@ti.com>
Signed-off-by: default avatarMoiz Sonasath <m-sonasath@ti.com>
Signed-off-by: default avatarVikram Pandita <vikram.pandita@ti.com>
Tested-by: default avatarVikram Pandita <vikram.pandita@ti.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent b3c3dc22
...@@ -634,6 +634,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -634,6 +634,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
u16 len; u16 len;
u16 csr = musb_readw(epio, MUSB_RXCSR); u16 csr = musb_readw(epio, MUSB_RXCSR);
struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
u8 use_mode_1;
if (hw_ep->is_shared_fifo) if (hw_ep->is_shared_fifo)
musb_ep = &hw_ep->ep_in; musb_ep = &hw_ep->ep_in;
...@@ -683,6 +684,18 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -683,6 +684,18 @@ static void rxstate(struct musb *musb, struct musb_request *req)
if (csr & MUSB_RXCSR_RXPKTRDY) { if (csr & MUSB_RXCSR_RXPKTRDY) {
len = musb_readw(epio, MUSB_RXCOUNT); 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) { if (request->actual < request->length) {
#ifdef CONFIG_USB_INVENTRA_DMA #ifdef CONFIG_USB_INVENTRA_DMA
if (is_buffer_mapped(req)) { if (is_buffer_mapped(req)) {
...@@ -714,37 +727,41 @@ static void rxstate(struct musb *musb, struct musb_request *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... * then becomes usable as a runtime "use mode 1" hint...
*/ */
csr |= MUSB_RXCSR_DMAENAB; /* Experimental: Mode1 works with mass storage use cases */
#ifdef USE_MODE1 if (use_mode_1) {
csr |= MUSB_RXCSR_AUTOCLEAR; csr |= MUSB_RXCSR_AUTOCLEAR;
/* csr |= MUSB_RXCSR_DMAMODE; */ musb_writew(epio, MUSB_RXCSR, csr);
csr |= MUSB_RXCSR_DMAENAB;
musb_writew(epio, MUSB_RXCSR, csr);
/* this special sequence (enabling and then /*
* this special sequence (enabling and then
* disabling MUSB_RXCSR_DMAMODE) is required * disabling MUSB_RXCSR_DMAMODE) is required
* to get DMAReq to activate * to get DMAReq to activate
*/ */
musb_writew(epio, MUSB_RXCSR, musb_writew(epio, MUSB_RXCSR,
csr | MUSB_RXCSR_DMAMODE); csr | MUSB_RXCSR_DMAMODE);
#else musb_writew(epio, MUSB_RXCSR, csr);
} else {
if (!musb_ep->hb_mult && if (!musb_ep->hb_mult &&
musb_ep->hw_ep->rx_double_buffered) musb_ep->hw_ep->rx_double_buffered)
csr |= MUSB_RXCSR_AUTOCLEAR; csr |= MUSB_RXCSR_AUTOCLEAR;
#endif csr |= MUSB_RXCSR_DMAENAB;
musb_writew(epio, MUSB_RXCSR, csr); musb_writew(epio, MUSB_RXCSR, csr);
}
if (request->actual < request->length) { if (request->actual < request->length) {
int transfer_size = 0; int transfer_size = 0;
#ifdef USE_MODE1 if (use_mode_1) {
transfer_size = min(request->length - request->actual, transfer_size = min(request->length - request->actual,
channel->max_len); channel->max_len);
#else musb_ep->dma->desired_mode = 1;
} else {
transfer_size = min(request->length - request->actual, transfer_size = min(request->length - request->actual,
(unsigned)len); (unsigned)len);
#endif
if (transfer_size <= musb_ep->packet_sz)
musb_ep->dma->desired_mode = 0; musb_ep->dma->desired_mode = 0;
else }
musb_ep->dma->desired_mode = 1;
use_dma = c->channel_program( use_dma = c->channel_program(
channel, channel,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment