• Anssi Hannula's avatar
    can: xilinx_can: keep only 1-2 frames in TX FIFO to fix TX accounting · 620050d9
    Anssi Hannula authored
    The xilinx_can driver assumes that the TXOK interrupt only clears after
    it has been acknowledged as many times as there have been successfully
    sent frames.
    
    However, the documentation does not mention such behavior, instead
    saying just that the interrupt is cleared when the clear bit is set.
    
    Similarly, testing seems to also suggest that it is immediately cleared
    regardless of the amount of frames having been sent. Performing some
    heavy TX load and then going back to idle has the tx_head drifting
    further away from tx_tail over time, steadily reducing the amount of
    frames the driver keeps in the TX FIFO (but not to zero, as the TXOK
    interrupt always frees up space for 1 frame from the driver's
    perspective, so frames continue to be sent) and delaying the local echo
    frames.
    
    The TX FIFO tracking is also otherwise buggy as it does not account for
    TX FIFO being cleared after software resets, causing
      BUG!, TX FIFO full when queue awake!
    messages to be output.
    
    There does not seem to be any way to accurately track the state of the
    TX FIFO for local echo support while using the full TX FIFO.
    
    The Zynq version of the HW (but not the soft-AXI version) has watermark
    programming support and with it an additional TX-FIFO-empty interrupt
    bit.
    
    Modify the driver to only put 1 frame into TX FIFO at a time on soft-AXI
    and 2 frames at a time on Zynq. On Zynq the TXFEMP interrupt bit is used
    to detect whether 1 or 2 frames have been sent at interrupt processing
    time.
    
    Tested with the integrated CAN on Zynq-7000 SoC. The 1-frame-FIFO mode
    was also tested.
    
    An alternative way to solve this would be to drop local echo support but
    keep using the full TX FIFO.
    
    v2: Add FIFO space check before TX queue wake with locking to
    synchronize with queue stop. This avoids waking the queue when xmit()
    had just filled it.
    
    v3: Keep local echo support and reduce the amount of frames in FIFO
    instead as suggested by Marc Kleine-Budde.
    
    Fixes: b1201e44 ("can: xilinx CAN controller support")
    Signed-off-by: default avatarAnssi Hannula <anssi.hannula@bitwise.fi>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
    620050d9
xilinx_can.c 39.5 KB