If no interrupt handler claims to have dealt with a level-triggered

GPIO interrupt, check the GPIO interrupt status register after clearing
it down to see if the interrupt source has disappeared. If it does,
assume it was a spurious event. Otherwise, panic.
This commit is contained in:
scw 2003-10-08 19:31:17 +00:00
parent 80649e0513
commit ecc5fec473
1 changed files with 19 additions and 11 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ixp425_intr.c,v 1.4 2003/10/08 14:55:04 scw Exp $ */
/* $NetBSD: ixp425_intr.c,v 1.5 2003/10/08 19:31:17 scw Exp $ */
/*
* Copyright (c) 2003
@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ixp425_intr.c,v 1.4 2003/10/08 14:55:04 scw Exp $");
__KERNEL_RCSID(0, "$NetBSD: ixp425_intr.c,v 1.5 2003/10/08 19:31:17 scw Exp $");
#ifndef EVBARM_SPL_NOINLINE
#define EVBARM_SPL_NOINLINE
@ -439,8 +439,6 @@ ixp425_intr_establish(int irq, int ipl, int (*func)(void *), void *arg)
/* All IXP425 interrupts are level-triggered. */
iq->iq_ist = IST_LEVEL; /* XXX */
IXPREG(IXP425_GPIO_VBASE + IXP425_GPIO_GPISR) = ixp425_irq2gpio_bit(irq);
oldirqstate = disable_interrupts(I32_bit);
TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list);
@ -522,19 +520,29 @@ ixp425_intr_dispatch(struct clockframe *frame)
}
restore_interrupts(oldirqstate);
#if 0 /* XXX: There's a spurious interrupt coming from somewhere... */
if (handled == 0 && iq->iq_ist == IST_LEVEL) {
panic("ixp425_intr_dispatch: unhandled level-triggered"
" interrupt: irq %d", irq);
}
#endif
/* Clear down level triggered GPIO interrupts now */
if ((ibit & IXP425_INT_GPIOMASK) && iq->iq_ist == IST_LEVEL) {
IXPREG(IXP425_GPIO_VBASE + IXP425_GPIO_GPISR) =
ixp425_irq2gpio_bit(irq);
}
if (handled == 0 && iq->iq_ist == IST_LEVEL) {
/*
* Let's see if the interrupt really did clear down.
* We sometimes see spurious (GPIO) interrupts from
* some PCIbus cards on certain boards.
*/
if ((ibit & IXP425_INT_GPIOMASK) == 0 ||
IXPREG(IXP425_GPIO_VBASE + IXP425_GPIO_GPISR) &
ixp425_irq2gpio_bit(irq)) {
/*
* Nope, still asserted. We're toast.
*/
panic("ixp425_intr_dispatch: unhandled "
"level-triggered interrupt: irq %d", irq);
}
}
current_spl_level = pcpl;
/* Re-enable this interrupt now that's it's cleared. */