Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2fea6cd3 authored by Oliver Hartkopp's avatar Oliver Hartkopp Committed by Marc Kleine-Budde
Browse files

can: sja1000: fix {pre,post}_irq() handling and IRQ handler return value



This patch fixes the issue that the sja1000_interrupt() function may have
returned IRQ_NONE without processing the optional pre_irq() and post_irq()
function before. Further the irq processing counter 'n' is moved to the end of
the while statement to return correct IRQ_[NONE|HANDLED] values at error
conditions.

Reported-by: default avatarWolfgang Grandegger <wg@grandegger.com>
Acked-by: default avatarWolfgang Grandegger <wg@grandegger.com>
Signed-off-by: default avatarOliver Hartkopp <socketcan@hartkopp.net>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 2c7a9dc1
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -494,20 +494,20 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
	uint8_t isrc, status;
	int n = 0;

	/* Shared interrupts and IRQ off? */
	if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
		return IRQ_NONE;

	if (priv->pre_irq)
		priv->pre_irq(priv);

	/* Shared interrupts and IRQ off? */
	if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
		goto out;

	while ((isrc = priv->read_reg(priv, SJA1000_IR)) &&
	       (n < SJA1000_MAX_IRQ)) {
		n++;

		status = priv->read_reg(priv, SJA1000_SR);
		/* check for absent controller due to hw unplug */
		if (status == 0xFF && sja1000_is_absent(priv))
			return IRQ_NONE;
			goto out;

		if (isrc & IRQ_WUI)
			netdev_warn(dev, "wakeup interrupt\n");
@@ -535,7 +535,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
				status = priv->read_reg(priv, SJA1000_SR);
				/* check for absent controller */
				if (status == 0xFF && sja1000_is_absent(priv))
					return IRQ_NONE;
					goto out;
			}
		}
		if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
@@ -543,8 +543,9 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
			if (sja1000_err(dev, isrc, status))
				break;
		}
		n++;
	}

out:
	if (priv->post_irq)
		priv->post_irq(priv);