[PATCH 7/7] usb: musb/cppi41: read data toggle from right endpoint

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

 



The fixup for Advisory 1.0.13 ("USB: data may be lost when USB subsystem
is operating in DMA mode and more than one endpoint is transferring
data") reads the USB data toggle each time a packet is given back from
the DMA controller. It does so in order to detect mismatches and
restoring the DATA1 toggle which might have erroneously been dropped, as
described as a workaround in the errata.

However, as the endpoint is not explictly selected before reading the
CSR register, the code operates on wrong register data and detects
mismatches where none are. By fixing up in such occasions, the toggle
mechanism is confused, and the controller drops packets that are out of
sync.

Fix this by calling musb_ep_select() in those functions.

Signed-off-by: Daniel Mack <zonque@xxxxxxxxx>
---
 drivers/usb/musb/musb_cppi41.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index e568930..38fd1d1 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -58,14 +58,17 @@ struct cppi41_dma_controller {
 
 static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
 {
+	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+	struct musb *musb = hw_ep->musb;
 	u16 csr;
 	u8 toggle;
 
 	if (cppi41_channel->is_tx)
 		return;
-	if (!is_host_active(cppi41_channel->controller->musb))
+	if (!is_host_active(musb))
 		return;
 
+	musb_ep_select(musb->mregs, hw_ep->epnum);
 	csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
 	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
 
@@ -74,15 +77,18 @@ static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
 
 static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
 {
+	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+	struct musb *musb = hw_ep->musb;
 	u16 csr;
 	u8 toggle;
 
 	if (cppi41_channel->is_tx)
 		return;
-	if (!is_host_active(cppi41_channel->controller->musb))
+	if (!is_host_active(musb))
 		return;
 
-	csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
+	musb_ep_select(musb->mregs, hw_ep->epnum);
+	csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
 	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
 
 	/*
-- 
1.9.0

--
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