Skip to content

Commit c418fd6

Browse files
Rahi374gregkh
authored andcommitted
usb: gadget: musb: fix short isoc packets with inventra dma
Handling short packets (length < max packet size) in the Inventra DMA engine in the MUSB driver causes the MUSB DMA controller to hang. An example of a problem that is caused by this problem is when streaming video out of a UVC gadget, only the first video frame is transferred. For short packets (mode-0 or mode-1 DMA), MUSB_TXCSR_TXPKTRDY must be set manually by the driver. This was previously done in musb_g_tx (musb_gadget.c), but incorrectly (all csr flags were cleared, and only MUSB_TXCSR_MODE and MUSB_TXCSR_TXPKTRDY were set). Fixing that problem allows some requests to be transferred correctly, but multiple requests were often put together in one USB packet, and caused problems if the packet size was not a multiple of 4. Instead, set MUSB_TXCSR_TXPKTRDY in dma_controller_irq (musbhsdma.c), just like host mode transfers. This topic was originally tackled by Nicolas Boichat [0] [1] and is discussed further at [2] as part of his GSoC project [3]. [0] https://groups.google.com/forum/?hl=en#!topic/beagleboard-gsoc/k8Azwfp75CU [1] https://gitorious.org/beagleboard-usbsniffer/beagleboard-usbsniffer-kernel/commit/b0be3b6cc195ba732189b04f1d43ec843c3e54c9?p=beagleboard-usbsniffer:beagleboard-usbsniffer-kernel.git;a=patch;h=b0be3b6cc195ba732189b04f1d43ec843c3e54c9 [2] http://beagleboard-usbsniffer.blogspot.com/2010/07/musb-isochronous-transfers-fixed.html [3] http://elinux.org/BeagleBoard/GSoC/USBSniffer Fixes: 550a737 ("USB: Add MUSB and TUSB support") Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Signed-off-by: Bin Liu <b-liu@ti.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f17b5f0 commit c418fd6

File tree

2 files changed

+12
-22
lines changed

2 files changed

+12
-22
lines changed

drivers/usb/musb/musb_gadget.c

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -452,13 +452,10 @@ void musb_g_tx(struct musb *musb, u8 epnum)
452452
}
453453

454454
if (request) {
455-
u8 is_dma = 0;
456-
bool short_packet = false;
457455

458456
trace_musb_req_tx(req);
459457

460458
if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
461-
is_dma = 1;
462459
csr |= MUSB_TXCSR_P_WZC_BITS;
463460
csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
464461
MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
@@ -476,16 +473,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
476473
*/
477474
if ((request->zero && request->length)
478475
&& (request->length % musb_ep->packet_sz == 0)
479-
&& (request->actual == request->length))
480-
short_packet = true;
476+
&& (request->actual == request->length)) {
481477

482-
if ((musb_dma_inventra(musb) || musb_dma_ux500(musb)) &&
483-
(is_dma && (!dma->desired_mode ||
484-
(request->actual &
485-
(musb_ep->packet_sz - 1)))))
486-
short_packet = true;
487-
488-
if (short_packet) {
489478
/*
490479
* On DMA completion, FIFO may not be
491480
* available yet...

drivers/usb/musb/musbhsdma.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -346,12 +346,10 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
346346
channel->status = MUSB_DMA_STATUS_FREE;
347347

348348
/* completed */
349-
if ((devctl & MUSB_DEVCTL_HM)
350-
&& (musb_channel->transmit)
351-
&& ((channel->desired_mode == 0)
352-
|| (channel->actual_len &
353-
(musb_channel->max_packet_sz - 1)))
354-
) {
349+
if (musb_channel->transmit &&
350+
(!channel->desired_mode ||
351+
(channel->actual_len %
352+
musb_channel->max_packet_sz))) {
355353
u8 epnum = musb_channel->epnum;
356354
int offset = musb->io.ep_offset(epnum,
357355
MUSB_TXCSR);
@@ -363,11 +361,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
363361
*/
364362
musb_ep_select(mbase, epnum);
365363
txcsr = musb_readw(mbase, offset);
366-
txcsr &= ~(MUSB_TXCSR_DMAENAB
364+
if (channel->desired_mode == 1) {
365+
txcsr &= ~(MUSB_TXCSR_DMAENAB
367366
| MUSB_TXCSR_AUTOSET);
368-
musb_writew(mbase, offset, txcsr);
369-
/* Send out the packet */
370-
txcsr &= ~MUSB_TXCSR_DMAMODE;
367+
musb_writew(mbase, offset, txcsr);
368+
/* Send out the packet */
369+
txcsr &= ~MUSB_TXCSR_DMAMODE;
370+
txcsr |= MUSB_TXCSR_DMAENAB;
371+
}
371372
txcsr |= MUSB_TXCSR_TXPKTRDY;
372373
musb_writew(mbase, offset, txcsr);
373374
}

0 commit comments

Comments
 (0)