can: sja1000: Prepare the use of a threaded handler
authorMiquel Raynal <miquel.raynal@bootlin.com>
Fri, 16 Jun 2023 13:45:52 +0000 (15:45 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Thu, 22 Jun 2023 07:41:32 +0000 (09:41 +0200)
In order to support a flavor of the sja1000 which sometimes freezes, it
will be needed upon certain interrupts to perform a soft reset. The soft
reset operation takes a bit of time, so better not do it within the hard
interrupt handler but rather in a threaded handler. Let's prepare the
possibility for sja1000_err() to request "interrupting" the current flow
and request the threaded handler to be run while keeping the interrupt
line low.

There is no functional change.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/all/20230616134553.2786391-1-miquel.raynal@bootlin.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/sja1000/sja1000.c

index aac5956..4719806 100644 (file)
@@ -501,7 +501,8 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
        struct sja1000_priv *priv = netdev_priv(dev);
        struct net_device_stats *stats = &dev->stats;
        uint8_t isrc, status;
-       int n = 0;
+       irqreturn_t ret = 0;
+       int n = 0, err;
 
        if (priv->pre_irq)
                priv->pre_irq(priv);
@@ -546,19 +547,23 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                }
                if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
                        /* error interrupt */
-                       if (sja1000_err(dev, isrc, status))
+                       err = sja1000_err(dev, isrc, status);
+                       if (err)
                                break;
                }
                n++;
        }
 out:
+       if (!ret)
+               ret = (n) ? IRQ_HANDLED : IRQ_NONE;
+
        if (priv->post_irq)
                priv->post_irq(priv);
 
        if (n >= SJA1000_MAX_IRQ)
                netdev_dbg(dev, "%d messages handled in ISR", n);
 
-       return (n) ? IRQ_HANDLED : IRQ_NONE;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(sja1000_interrupt);