Reading the interrupt register `SUN4I_REG_INT_ADDR` causes all of its bits to be reset. If we ever reach the condition of handling more than `SUN4I_CAN_MAX_IRQ` IRQs, we will have read the register and reset all its bits but without actually handling the interrupt inside of the loop body.
This may, among other issues, cause us to never `netif_wake_queue()` again after a transmission interrupt.
Fixes: 0738eff14d81 ("can: Allwinner A10/A20 CAN Controller support - Kernel module") Cc: stable@vger.kernel.org Co-developed-by: Thomas Mühlbacher tmuehlbacher@posteo.net Signed-off-by: Thomas Mühlbacher tmuehlbacher@posteo.net Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de --- I've ported the fix from the sja1000 driver to the sun4i_can, which based on the sja1000 driver. --- drivers/net/can/sun4i_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 53bfd873de9b..0a7ba0942839 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -657,8 +657,8 @@ static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id) u8 isrc, status; int n = 0;
- while ((isrc = readl(priv->base + SUN4I_REG_INT_ADDR)) && - (n < SUN4I_CAN_MAX_IRQ)) { + while ((n < SUN4I_CAN_MAX_IRQ) && + (isrc = readl(priv->base + SUN4I_REG_INT_ADDR))) { n++; status = readl(priv->base + SUN4I_REG_STA_ADDR);
--- base-commit: 5442a9da69789741bfda39f34ee7f69552bf0c56 change-id: 20251116-sun4i-fix-loop-f265621b6a99
Best regards, -- Marc Kleine-Budde mkl@pengutronix.de