Re: [PATCH v2 5/6] usb: musb: introduce dma_channel.packet_done

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 5/23/2014 3:01 PM, Daniel Mack wrote:
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.
Can you explain a bit more. Doesn't it checks for
actual_length + xfer_len >= transfer_buffer_length ?

This check is also failing?

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, which currently has no
way of knowing what the last packet size was, as long as DMA and a glue
layer is involved. Hence, it won't give the urb back, effectively
starving the data stream.

Fix this by introducing a new boolean flag in 'struct dma_channel'
which, 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@xxxxxxxxx>
---
  drivers/usb/musb/musb_cppi41.c | 2 ++
  drivers/usb/musb/musb_dma.h    | 1 +
  drivers/usb/musb/musb_host.c   | 3 ++-
  3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index 7b8bbf5..a11bbb6 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -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.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.packet_done = false;
save_rx_toggle(cppi41_channel);
  	dma_async_issue_pending(dc);
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 1345a4f..7253358 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -129,6 +129,7 @@ struct dma_channel {
  	size_t			actual_len;
  	enum dma_channel_status	status;
  	bool			desired_mode;
+	bool			packet_done;
  };
/*
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 9d3a5b2..6531426 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1738,7 +1738,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->packet_done);
  		}
/* send IN token for next packet, without AUTOREQ */


--
-George

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux