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