diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2013-11-12 16:37:47 +0100 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-11-25 10:54:14 -0600 |
commit | a655f481d83d6d37bec0a2ddfdd24c30ff8f541f (patch) | |
tree | 6f1c0217ababbd4c3fd0bd167a4793503d5023ba /drivers/usb/gadget/composite.c | |
parent | d373a8534d5e1e7a350e40d3c11961a7cd8d530b (diff) | |
download | op-kernel-dev-a655f481d83d6d37bec0a2ddfdd24c30ff8f541f.zip op-kernel-dev-a655f481d83d6d37bec0a2ddfdd24c30ff8f541f.tar.gz |
usb: musb: musb_cppi41: handle pre-mature TX complete interrupt
The TX-complete interrupt of the CPPI41 on AM335x fires too early.
Adding a loop and counting how long it takes until the
MUSB_TXCSR_TXPKTRDY bit is cleared I see
FS:
|musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=64, mode=0, dma_addr=0xadc54002, len=1514 is_tx=1
|cppi41_dma_callback() 74 loops
|musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=64, mode=0, dma_addr=0xadcd8802, len=1514 is_tx=1
|cppi41_dma_callback() 66 loops
|musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=64, mode=0, dma_addr=0xadcd8002, len=1514 is_tx=1
|cppi41_dma_callback() 136 loops
|musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=64, mode=0, dma_addr=0xadf55802, len=1514 is_tx=1
|cppi41_dma_callback() 136 loops
avg: 110 - 150us
HS:
|musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=512, mode=0, dma_addr=0xaca6f002, len=1514 is_tx=1
|cppi41_dma_callback() 0 loops
|musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=512, mode=0, dma_addr=0xadd6f802, len=1514 is_tx=1
|cppi41_dma_callback() 2 loops
|musb-hdrc musb-hdrc.0.auto: configure ep1/80 packet_sz=512, mode=0, dma_addr=0xadd6f002, len=1514 is_tx=1
|cppi41_dma_callback() 13 loops
avg: 2us
for the same test case. One loop means a udelay(1). The delay seems to
depend on the packet size. On HS the bit is always cleared for small
packet sizes while on FS it is never the case, it mostly around 110us.
This testing has been performed with g_ether (musb as device) and using BULK
transfers.
INTR transfers are way more fun: during init the gadget sends a INT
packet to the host and cppi41 says "transfer done" shortly after. The
MUSB_TXCSR_TXPKTRDY bit is set even seconds later. The reason is that the host
did not try to receive it, it does so after the interface (on host side) has
been configured. Until this happens, that packet remains in musb's FIFO.
To fix this, two things are done:
- No DMA transfers for INT based endpoints. These transfer are usually
very small and rare so it is likely better to skip the DMA engine and
stuff the four bytes directly into the FIFO
- on HS we poll up to 25us and hope that bit goes away. If not we setup
a hrtimer to poll for it. The 140us delay is a rule of thumb. In FS
the command
| ping 10.10.10.10 -c1 -s65130
creates about 44 1514bytes transfers. About 19 of them need a second
timer to complete.
Reported-by: Bin Liu <b-liu@ti.com>
Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/composite.c')
0 files changed, 0 insertions, 0 deletions