Skip to content

Commit

Permalink
usb: musb: Enable DMA mode1 RX for transfers without short packets
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Anand Gadiyar authored and Felipe Balbi committed Sep 9, 2011
1 parent b3c3dc2 commit 0ae52d5
Showing 1 changed file with 43 additions and 26 deletions.
69 changes: 43 additions & 26 deletions drivers/usb/musb/musb_gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 0ae52d5

Please sign in to comment.