usb: musb: introduce dma_channel.rx_packet_done
authorDaniel Mack <zonque@gmail.com>
Mon, 26 May 2014 12:52:38 +0000 (14:52 +0200)
committerFelipe Balbi <balbi@ti.com>
Mon, 30 Jun 2014 19:26:24 +0000 (14:26 -0500)
The musb/cppi41 glue layer is capable of handling transactions that span
over more than one USB packet by reloading the DMA descriptors
partially. An urb is considered completed when either its transfer
buffer has been filled entirely (actual_length ==
transfer_buffer_length) or if a packet in the stream has less bytes than
the endpoint's wMaxPacketSize.

Once one of the above conditions is met, musb_dma_completion() is called
from cppi41_trans_done(). However, the final decision whether or not to
return the urb to its owner is made by the core and its determination of
the variable 'done' in musb_host_rx(). This code has currently no way of
knowing what the size of the last packet was, and whether or not to
give back the urb due to a short read.

Fix this by introducing a new boolean flag in 'struct dma_channel', and
set it from musb_cppi41.c. If set, it will make the core do what the
DMA layer decided and complete the urb.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: George Cherian <george.cherian@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_dma.h
drivers/usb/musb/musb_host.c

index 7b8bbf53127e114c5615fa7c90ae75a0485f6779..4187ef1fab294b2636c91de3c4b40772636b40d8 100644 (file)
@@ -139,6 +139,7 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
                cppi41_channel->channel.actual_len =
                        cppi41_channel->transferred;
                cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
+               cppi41_channel->channel.rx_packet_done = true;
                musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
        } else {
                /* next iteration, reload */
@@ -450,6 +451,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
        dma_desc->callback = cppi41_dma_callback;
        dma_desc->callback_param = channel;
        cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
+       cppi41_channel->channel.rx_packet_done = false;
 
        save_rx_toggle(cppi41_channel);
        dma_async_issue_pending(dc);
index 1345a4ff041a00380eb539f1a1c5bae2f9db13f4..1d44faa8625254577e55c2292a39a7093a926a2f 100644 (file)
@@ -129,6 +129,7 @@ struct dma_channel {
        size_t                  actual_len;
        enum dma_channel_status status;
        bool                    desired_mode;
+       bool                    rx_packet_done;
 };
 
 /*
index 3381fa56db294215db9edcd528843e7d2e3221ad..88435cd7fe3da4cab611b681470e657ea2464deb 100644 (file)
@@ -1737,7 +1737,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
                /* done if urb buffer is full or short packet is recd */
                done = (urb->actual_length + xfer_len >=
                                urb->transfer_buffer_length
-                       || dma->actual_len < qh->maxpacket);
+                       || dma->actual_len < qh->maxpacket
+                       || dma->rx_packet_done);
                }
 
                /* send IN token for next packet, without AUTOREQ */