diff options
author | Ming Lei <tom.leiming@gmail.com> | 2010-09-24 14:44:14 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 21:21:56 +0400 |
commit | e7379aaa5ca12f9e011eb5a6bcba88e9bbbfbf87 (patch) | |
tree | 50509fa9b9da211ad2ce342d11e7a376544a8327 | |
parent | a6038ee76a29ea31f8aae4eb6c419794c739e077 (diff) | |
download | linux-e7379aaa5ca12f9e011eb5a6bcba88e9bbbfbf87.tar.xz |
usb: musb: gadget: fix ZLP sending in musb_g_tx(v1)
This patch fixes the problem reported by Sergei:
>how come? we need to send ZLP before giving back the request.
>Well, look at the code ionce again. We need to send ZLP *after*
>request->actual == request->length, but as the check is inserted
>after the ZLP send, ZLP *may* be sent once the first DMA completes,
>not the last.
The patch also has been discussed on the link below:
http://marc.info/?t=128454814900001&r=1&w=2
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Reported-by: Sergei Shtylyov <sshtylyov@mvista.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Anand Gadiyar <gadiyar@ti.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 59 |
1 files changed, 29 insertions, 30 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6a8c061b66f1..3f1cc5a8381f 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -477,40 +477,39 @@ void musb_g_tx(struct musb *musb, u8 epnum) epnum, csr, musb_ep->dma->actual_len, request); } - if (is_dma || request->actual == request->length) { - /* - * First, maybe a terminating short packet. Some DMA - * engines might handle this by themselves. - */ - if ((request->zero && request->length - && request->length % musb_ep->packet_sz == 0) + /* + * First, maybe a terminating short packet. Some DMA + * engines might handle this by themselves. + */ + if ((request->zero && request->length + && (request->length % musb_ep->packet_sz == 0) + && (request->actual == request->length)) #ifdef CONFIG_USB_INVENTRA_DMA - || (is_dma && (!dma->desired_mode || - (request->actual & - (musb_ep->packet_sz - 1)))) + || (is_dma && (!dma->desired_mode || + (request->actual & + (musb_ep->packet_sz - 1)))) #endif - ) { - /* - * On DMA completion, FIFO may not be - * available yet... - */ - if (csr & MUSB_TXCSR_TXPKTRDY) - return; + ) { + /* + * On DMA completion, FIFO may not be + * available yet... + */ + if (csr & MUSB_TXCSR_TXPKTRDY) + return; - DBG(4, "sending zero pkt\n"); - musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE - | MUSB_TXCSR_TXPKTRDY); - request->zero = 0; - } + DBG(4, "sending zero pkt\n"); + musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE + | MUSB_TXCSR_TXPKTRDY); + request->zero = 0; + } - if (request->actual == request->length) { - musb_g_giveback(musb_ep, request, 0); - request = musb_ep->desc ? next_request(musb_ep) : NULL; - if (!request) { - DBG(4, "%s idle now\n", - musb_ep->end_point.name); - return; - } + if (request->actual == request->length) { + musb_g_giveback(musb_ep, request, 0); + request = musb_ep->desc ? next_request(musb_ep) : NULL; + if (!request) { + DBG(4, "%s idle now\n", + musb_ep->end_point.name); + return; } } |