diff options
author | Ming Lei <tom.leiming@gmail.com> | 2010-09-24 06:44:14 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 13:21:56 -0400 |
commit | e7379aaa5ca12f9e011eb5a6bcba88e9bbbfbf87 (patch) | |
tree | 50509fa9b9da211ad2ce342d11e7a376544a8327 /drivers/usb/musb | |
parent | a6038ee76a29ea31f8aae4eb6c419794c739e077 (diff) |
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>
Diffstat (limited to 'drivers/usb/musb')
-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) | |||
477 | epnum, csr, musb_ep->dma->actual_len, request); | 477 | epnum, csr, musb_ep->dma->actual_len, request); |
478 | } | 478 | } |
479 | 479 | ||
480 | if (is_dma || request->actual == request->length) { | 480 | /* |
481 | /* | 481 | * First, maybe a terminating short packet. Some DMA |
482 | * First, maybe a terminating short packet. Some DMA | 482 | * engines might handle this by themselves. |
483 | * engines might handle this by themselves. | 483 | */ |
484 | */ | 484 | if ((request->zero && request->length |
485 | if ((request->zero && request->length | 485 | && (request->length % musb_ep->packet_sz == 0) |
486 | && request->length % musb_ep->packet_sz == 0) | 486 | && (request->actual == request->length)) |
487 | #ifdef CONFIG_USB_INVENTRA_DMA | 487 | #ifdef CONFIG_USB_INVENTRA_DMA |
488 | || (is_dma && (!dma->desired_mode || | 488 | || (is_dma && (!dma->desired_mode || |
489 | (request->actual & | 489 | (request->actual & |
490 | (musb_ep->packet_sz - 1)))) | 490 | (musb_ep->packet_sz - 1)))) |
491 | #endif | 491 | #endif |
492 | ) { | 492 | ) { |
493 | /* | 493 | /* |
494 | * On DMA completion, FIFO may not be | 494 | * On DMA completion, FIFO may not be |
495 | * available yet... | 495 | * available yet... |
496 | */ | 496 | */ |
497 | if (csr & MUSB_TXCSR_TXPKTRDY) | 497 | if (csr & MUSB_TXCSR_TXPKTRDY) |
498 | return; | 498 | return; |
499 | 499 | ||
500 | DBG(4, "sending zero pkt\n"); | 500 | DBG(4, "sending zero pkt\n"); |
501 | musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE | 501 | musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE |
502 | | MUSB_TXCSR_TXPKTRDY); | 502 | | MUSB_TXCSR_TXPKTRDY); |
503 | request->zero = 0; | 503 | request->zero = 0; |
504 | } | 504 | } |
505 | 505 | ||
506 | if (request->actual == request->length) { | 506 | if (request->actual == request->length) { |
507 | musb_g_giveback(musb_ep, request, 0); | 507 | musb_g_giveback(musb_ep, request, 0); |
508 | request = musb_ep->desc ? next_request(musb_ep) : NULL; | 508 | request = musb_ep->desc ? next_request(musb_ep) : NULL; |
509 | if (!request) { | 509 | if (!request) { |
510 | DBG(4, "%s idle now\n", | 510 | DBG(4, "%s idle now\n", |
511 | musb_ep->end_point.name); | 511 | musb_ep->end_point.name); |
512 | return; | 512 | return; |
513 | } | ||
514 | } | 513 | } |
515 | } | 514 | } |
516 | 515 | ||