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

usb: musb/cppi41: call musb_ep_select() before accessing an endpoint's CSR

Before accessing any of an endpoint's CSR registers, make sure the
correct endpoint is selected. Otherwise, data read from or written to
the registers is likely to affect the wrong endpoint as long as the
connected device has more than one endpoint.

This, of course, leads to all sorts of strange effects such as stream
starvation and driver internal state machine confusion due to spurious
interrupts.
Signed-off-by: default avatarDaniel Mack <zonque@gmail.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent ff3fcac9
...@@ -74,15 +74,18 @@ static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel) ...@@ -74,15 +74,18 @@ static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
static void update_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; u16 csr;
u8 toggle; u8 toggle;
if (cppi41_channel->is_tx) if (cppi41_channel->is_tx)
return; return;
if (!is_host_active(cppi41_channel->controller->musb)) if (!is_host_active(musb))
return; 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; toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
/* /*
...@@ -107,6 +110,7 @@ static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep) ...@@ -107,6 +110,7 @@ static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
void __iomem *epio = musb->endpoints[epnum].regs; void __iomem *epio = musb->endpoints[epnum].regs;
u16 csr; u16 csr;
musb_ep_select(musb->mregs, hw_ep->epnum);
csr = musb_readw(epio, MUSB_TXCSR); csr = musb_readw(epio, MUSB_TXCSR);
if (csr & MUSB_TXCSR_TXPKTRDY) if (csr & MUSB_TXCSR_TXPKTRDY)
return false; return false;
...@@ -173,6 +177,7 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) ...@@ -173,6 +177,7 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
dma_async_issue_pending(dc); dma_async_issue_pending(dc);
if (!cppi41_channel->is_tx) { if (!cppi41_channel->is_tx) {
musb_ep_select(musb->mregs, hw_ep->epnum);
csr = musb_readw(epio, MUSB_RXCSR); csr = musb_readw(epio, MUSB_RXCSR);
csr |= MUSB_RXCSR_H_REQPKT; csr |= MUSB_RXCSR_H_REQPKT;
musb_writew(epio, MUSB_RXCSR, csr); musb_writew(epio, MUSB_RXCSR, csr);
......
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