Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Feb 2011 01:49:30 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r218427 - head/sys/arm/mv
Message-ID:  <201102080149.p181nUY8029614@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcel
Date: Tue Feb  8 01:49:30 2011
New Revision: 218427
URL: http://svn.freebsd.org/changeset/base/218427

Log:
  In arm_get_next_irq(), use the last IRQ argument in order to prevent
  a hard hang due to an interrupt storm or stuck interrupt pin. We
  return the next IRQ that is larger than the last one returned and
  in doing so give all interrupts a fair chance of being handled.
  Consequently, we're able to break into the kernel debugger in such
  an event.

Modified:
  head/sys/arm/mv/ic.c

Modified: head/sys/arm/mv/ic.c
==============================================================================
--- head/sys/arm/mv/ic.c	Tue Feb  8 01:43:45 2011	(r218426)
+++ head/sys/arm/mv/ic.c	Tue Feb  8 01:49:30 2011	(r218427)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/kernel.h>
+#include <sys/ktr.h>
 #include <sys/module.h>
 #include <sys/rman.h>
 #include <machine/bus.h>
@@ -143,27 +144,38 @@ static devclass_t mv_ic_devclass;
 DRIVER_MODULE(ic, simplebus, mv_ic_driver, mv_ic_devclass, 0, 0);
 
 int
-arm_get_next_irq(int last __unused)
+arm_get_next_irq(int last)
 {
-	int irq;
+	u_int filt, irq;
+	int next;
 
+	filt = ~((last >= 0) ? (2 << last) - 1 : 0);
 	irq = mv_ic_get_cause() & mv_ic_get_mask();
-	if (irq)
-		return (ffs(irq) - 1);
-
+	if (irq & filt) {
+		next = ffs(irq & filt) - 1;
+		goto out;
+	}
 	if (mv_ic_sc->ic_high_regs) {
+		filt = ~((last >= 32) ? (2 << (last - 32)) - 1 : 0);
 		irq = mv_ic_get_cause_hi() & mv_ic_get_mask_hi();
-		if (irq)
-			return (ffs(irq) + 31);
+		if (irq & filt) {
+			next = ffs(irq & filt) + 31;
+			goto out;
+		}
 	}
-
 	if (mv_ic_sc->ic_error_regs) {
+		filt = ~((last >= 64) ? (2 << (last - 64)) - 1 : 0);
 		irq = mv_ic_get_cause_error() & mv_ic_get_mask_error();
-		if (irq)
-			return (ffs(irq) + 63);
+		if (irq & filt) {
+			next = ffs(irq & filt) + 63;
+			goto out;
+		}
 	}
+	next = -1;
 
-	return (-1);
+ out:
+	CTR3(KTR_INTR, "%s: last=%d, next=%d", __func__, last, next);
+	return (next);
 }
 
 static void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201102080149.p181nUY8029614>