• Sebastian Andrzej Siewior's avatar
    usb: musb: musb_cppi41: handle pre-mature TX complete interrupt · a655f481
    Sebastian Andrzej Siewior authored
    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: default avatarBin Liu <b-liu@ti.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
    Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
    a655f481
musb_cppi41.c 17.5 KB