From: Ming Lei <tom.leiming@xxxxxxxxx> 1, In Rx double buffer case, FIFO may have two packets, so rxstate should be called to unload fifo if RXPKTRDY is set even the current request has not been completed. 2, Commit 490e5fbe8ccb198fb719ae49eaa0c7071273e016 [usb: musb:gadget: enable autoclear for OUT transfer in both DMA 0 and DMA 1] introduces autoclear to support double buffer in dma mode 0, so remove clearing RXPKTRDY manually for dma mode 0. 3, Felipe's patch[usb: musb: gadget: only enable AUTOCLEAR in double buffered case] may break dma mode 1 for non-doublebuffer endpoint, fix it. With this patch, either usbtest #5 or g_file_storage(writing file to device in usb host) or g_ether have been tested OK in double buffer case(using fifo mode 3). Also, this patch has been verified that single buffer case can't be broken. Cc: Felipe Balbi <balbi@xxxxxx> Cc: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx> Cc: Anand Gadiyar <gadiyar@xxxxxx> Cc: Mike Frysinger <vapier@xxxxxxxxxx> Cc: Sergei Shtylyov <sshtylyov@xxxxxxxxxxxxx> Signed-off-by: Ming Lei <tom.leiming@xxxxxxxxx> --- drivers/usb/musb/musb_gadget.c | 23 +++++++++++++++++------ 1 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 5d81504..9038b08 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -644,10 +644,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) */ csr |= MUSB_RXCSR_DMAENAB; - if (!musb_ep->hb_mult && - musb_ep->hw_ep->rx_double_buffered) - csr |= MUSB_RXCSR_AUTOCLEAR; #ifdef USE_MODE1 + csr |= MUSB_RXCSR_AUTOCLEAR; /* csr |= MUSB_RXCSR_DMAMODE; */ /* this special sequence (enabling and then @@ -656,6 +654,10 @@ static void rxstate(struct musb *musb, struct musb_request *req) */ musb_writew(epio, MUSB_RXCSR, csr | MUSB_RXCSR_DMAMODE); +#else + if (!musb_ep->hb_mult && + musb_ep->hw_ep->rx_double_buffered) + csr |= MUSB_RXCSR_AUTOCLEAR; #endif musb_writew(epio, MUSB_RXCSR, csr); @@ -807,7 +809,7 @@ void musb_g_rx(struct musb *musb, u8 epnum) #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) /* Autoclear doesn't clear RxPktRdy for short packets */ - if ((dma->desired_mode == 0) + if ((dma->desired_mode == 0 && !hw_ep->rx_double_buffered) || (dma->actual_len & (musb_ep->packet_sz - 1))) { /* ack the read! */ @@ -818,8 +820,17 @@ void musb_g_rx(struct musb *musb, u8 epnum) /* incomplete, and not short? wait for next IN packet */ if ((request->actual < request->length) && (musb_ep->dma->actual_len - == musb_ep->packet_sz)) + == musb_ep->packet_sz)) { + /* + * In double buffer case, continue to unload FIFO if + * there is Rx packet in FIFO. + */ + csr = musb_readw(epio, MUSB_RXCSR); + if ((csr & MUSB_RXCSR_RXPKTRDY) && + hw_ep->rx_double_buffered) + goto receive; return; + } #endif musb_g_giveback(musb_ep, request, 0); @@ -827,7 +838,7 @@ void musb_g_rx(struct musb *musb, u8 epnum) if (!request) return; } - +receive: /* Analyze request */ rxstate(musb, to_musb_request(request)); } -- 1.7.3 -- 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