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.
This commit is contained in:
Marcel Moolenaar 2011-02-08 01:49:30 +00:00
parent 292e1140d1
commit 078b894c69

View File

@ -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