]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
can: xilinx_can: fix incorrect clear of non-processed interrupts
authorAnssi Hannula <anssi.hannula@bitwise.fi>
Mon, 26 Feb 2018 12:39:59 +0000 (14:39 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Mon, 23 Jul 2018 12:34:46 +0000 (14:34 +0200)
xcan_interrupt() clears ERROR|RXOFLV|BSOFF|ARBLST interrupts if any of
them is asserted. This does not take into account that some of them
could have been asserted between interrupt status read and interrupt
clear, therefore clearing them without handling them.

Fix the code to only clear those interrupts that it knows are asserted
and therefore going to be processed in xcan_err_interrupt().

Fixes: b1201e44f50b ("can: xilinx CAN controller support")
Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/xilinx_can.c

index ea9f9d1a5ba775f7b67c5984763e3f5ba63e0b80..cb80a9aa72818b82b4716b46b7f64a2f031e4687 100644 (file)
@@ -938,6 +938,7 @@ static irqreturn_t xcan_interrupt(int irq, void *dev_id)
        struct net_device *ndev = (struct net_device *)dev_id;
        struct xcan_priv *priv = netdev_priv(ndev);
        u32 isr, ier;
+       u32 isr_errors;
 
        /* Get the interrupt status from Xilinx CAN */
        isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
@@ -956,11 +957,10 @@ static irqreturn_t xcan_interrupt(int irq, void *dev_id)
                xcan_tx_interrupt(ndev, isr);
 
        /* Check for the type of error interrupt and Processing it */
-       if (isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK |
-                       XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK)) {
-               priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_ERROR_MASK |
-                               XCAN_IXR_RXOFLW_MASK | XCAN_IXR_BSOFF_MASK |
-                               XCAN_IXR_ARBLST_MASK));
+       isr_errors = isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK |
+                           XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK);
+       if (isr_errors) {
+               priv->write_reg(priv, XCAN_ICR_OFFSET, isr_errors);
                xcan_err_interrupt(ndev, isr);
        }