Commit ff3fcac9 authored by Daniel Mack's avatar Daniel Mack Committed by Felipe Balbi

usb: musb: introduce dma_channel.rx_packet_done

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: default avatarDaniel Mack <zonque@gmail.com>
Acked-by: default avatarGeorge Cherian <george.cherian@ti.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 2ccc6d30
...@@ -139,6 +139,7 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) ...@@ -139,6 +139,7 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
cppi41_channel->channel.actual_len = cppi41_channel->channel.actual_len =
cppi41_channel->transferred; cppi41_channel->transferred;
cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE; 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); musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
} else { } else {
/* next iteration, reload */ /* next iteration, reload */
...@@ -450,6 +451,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel, ...@@ -450,6 +451,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
dma_desc->callback = cppi41_dma_callback; dma_desc->callback = cppi41_dma_callback;
dma_desc->callback_param = channel; dma_desc->callback_param = channel;
cppi41_channel->cookie = dma_desc->tx_submit(dma_desc); cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
cppi41_channel->channel.rx_packet_done = false;
save_rx_toggle(cppi41_channel); save_rx_toggle(cppi41_channel);
dma_async_issue_pending(dc); dma_async_issue_pending(dc);
......
...@@ -129,6 +129,7 @@ struct dma_channel { ...@@ -129,6 +129,7 @@ struct dma_channel {
size_t actual_len; size_t actual_len;
enum dma_channel_status status; enum dma_channel_status status;
bool desired_mode; bool desired_mode;
bool rx_packet_done;
}; };
/* /*
......
...@@ -1737,7 +1737,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) ...@@ -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 if urb buffer is full or short packet is recd */
done = (urb->actual_length + xfer_len >= done = (urb->actual_length + xfer_len >=
urb->transfer_buffer_length 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 */ /* send IN token for next packet, without AUTOREQ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment