diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2011-04-15 20:52:58 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2011-04-15 20:52:58 +0000 |
commit | 41664536ca087a7e316bcdae0d145df6461e98f9 (patch) | |
tree | 2dc1e4e8dcdf69e57c75edf55963d67c98389fc8 | |
parent | 6c79978cbce731e6dd4f90352a13cdd25a500eeb (diff) |
More than a decade ago, interrupt handlers on sparc started returning 0
(interrupt was not for me), 1 (positive interrupt was for me), or -1
(i am not sure...). We have continued with this practice in as many
drivers as possible, throughout the tree.
This makes some of the architectures use that information in their
interrupt handler calling code -- if 1 is returned (and we know
this specific machine does not have edge-shared interrupts), we
finish servicing other possible handlers on the same pin. If the
interrupt pin remains asserted (from a different device), we will
end up back in the interrupt servicing code of course... but this is
cheaper than calling all the chained interrupts on a pin.
This does of course count on shared level interrupts being properly
sorted by IPL.
There have been some concerns about starvation of drivers which
incorrectly return 1. Those drivers should be hunted down so that
they return -1.
ok drahn
-rw-r--r-- | sys/arch/macppc/dev/macintr.c | 12 | ||||
-rw-r--r-- | sys/arch/macppc/dev/openpic.c | 11 | ||||
-rw-r--r-- | sys/arch/macppc/include/powerpc.h | 4 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/machdep.c | 8 |
4 files changed, 27 insertions, 8 deletions
diff --git a/sys/arch/macppc/dev/macintr.c b/sys/arch/macppc/dev/macintr.c index 9f277f0c08c..9a2438f9e33 100644 --- a/sys/arch/macppc/dev/macintr.c +++ b/sys/arch/macppc/dev/macintr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: macintr.c,v 1.41 2011/01/08 18:10:22 deraadt Exp $ */ +/* $OpenBSD: macintr.c,v 1.42 2011/04/15 20:52:55 deraadt Exp $ */ /*- * Copyright (c) 1995 Per Fogelstrom @@ -251,6 +251,8 @@ printf("vI %d ", irq); m_intrtype[irq] = type; break; case IST_EDGE: + intr_shared_edge = 1; + /* FALLTHROUGH */ case IST_LEVEL: if (type == m_intrtype[irq]) break; @@ -499,7 +501,7 @@ mac_ext_intr() { int irq = 0; int o_imen, r_imen; - int pcpl; + int pcpl, ret; struct cpu_info *ci = curcpu(); struct intrhand *ih; volatile unsigned long int_state; @@ -526,8 +528,12 @@ start: ih = m_intrhand[irq]; while (ih) { - if ((*ih->ih_fun)(ih->ih_arg)) + ret = ((*ih->ih_fun)(ih->ih_arg)); + if (ret) { ih->ih_count.ec_count++; + if (intr_shared_edge == 0 && ret == 1) + break; + } ih = ih->ih_next; } diff --git a/sys/arch/macppc/dev/openpic.c b/sys/arch/macppc/dev/openpic.c index c3bb6df2ecd..15e389be898 100644 --- a/sys/arch/macppc/dev/openpic.c +++ b/sys/arch/macppc/dev/openpic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: openpic.c,v 1.63 2011/01/08 18:10:22 deraadt Exp $ */ +/* $OpenBSD: openpic.c,v 1.64 2011/04/15 20:52:55 deraadt Exp $ */ /*- * Copyright (c) 1995 Per Fogelstrom @@ -253,6 +253,8 @@ printf("vI %d ", irq); o_intrtype[irq] = type; break; case IST_EDGE: + intr_shared_edge = 1; + /* FALLTHROUGH */ case IST_LEVEL: if (type == o_intrtype[irq]) break; @@ -679,7 +681,7 @@ ext_intr_openpic() { struct cpu_info *ci = curcpu(); int irq, realirq; - int r_imen; + int r_imen, ret; int pcpl, ocpl; struct intrhand *ih; @@ -725,11 +727,14 @@ ext_intr_openpic() ppc_intr_enable(1); KERNEL_LOCK(); - if ((*ih->ih_fun)(ih->ih_arg)) + ret = (*ih->ih_fun)(ih->ih_arg); + if (ret) ih->ih_count.ec_count++; KERNEL_UNLOCK(); (void)ppc_intr_disable(); + if (intr_shared_edge == 00 && ret == 1) + break; ih = ih->ih_next; } diff --git a/sys/arch/macppc/include/powerpc.h b/sys/arch/macppc/include/powerpc.h index 8395bd297c0..014a3403313 100644 --- a/sys/arch/macppc/include/powerpc.h +++ b/sys/arch/macppc/include/powerpc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: powerpc.h,v 1.8 2005/12/17 07:31:26 miod Exp $ */ +/* $OpenBSD: powerpc.h,v 1.9 2011/04/15 20:52:56 deraadt Exp $ */ /* $NetBSD: powerpc.h,v 1.1 1996/09/30 16:34:30 ws Exp $ */ /* @@ -82,6 +82,8 @@ void install_extint(void (*handler) (void)); void ppc_intr_enable(int enable); int ppc_intr_disable(void); +extern int intr_shared_edge; + struct dumpmem { vaddr_t start; vsize_t end; diff --git a/sys/arch/macppc/macppc/machdep.c b/sys/arch/macppc/macppc/machdep.c index 9dfd408df65..78da19010bc 100644 --- a/sys/arch/macppc/macppc/machdep.c +++ b/sys/arch/macppc/macppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.124 2011/04/15 04:52:39 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.125 2011/04/15 20:52:57 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -1009,6 +1009,12 @@ systype(char *name) int ppc_configed_intr_cnt = 0; struct intrhand ppc_configed_intr[MAX_PRECONF_INTR]; +/* + * True if the system has any non-level interrupts which are shared + * on the same pin. + */ +int intr_shared_edge; + void * ppc_intr_establish(void *lcv, pci_intr_handle_t ih, int type, int level, int (*func)(void *), void *arg, const char *name) |