mirror of https://gitee.com/openkylin/linux.git
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: 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>
This commit is contained in:
parent
b3c3dc2236
commit
0ae52d5458
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue