summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrahnds <rahnds@openbsd.org>1998-06-28 04:35:17 +0000
committerrahnds <rahnds@openbsd.org>1998-06-28 04:35:17 +0000
commit73a31ae4548a62ee99dda01948154d49298c7c18 (patch)
tree136c2de6fa5ec3c61f66d9a2e2592558fbf9475a
parentindent (diff)
downloadwireguard-openbsd-73a31ae4548a62ee99dda01948154d49298c7c18.tar.xz
wireguard-openbsd-73a31ae4548a62ee99dda01948154d49298c7c18.zip
Stability fix for powerpc openfirmware system.
Actually implement interrupt masking as appropriate for the openfirmware drivers. This problem was caused by the use of the X86 style of interrupt handling introduced to the powerpc some time back. A problem may still exist in the non-openfirmware drivers: soft_net functions may get called when going from splhigh -> splclock using splx when the soft functions should not be called. Also look into SINT_CLOCK handling (where is this set). Possibly real work can now be done...
-rw-r--r--sys/arch/powerpc/powerpc/ofw_machdep.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/sys/arch/powerpc/powerpc/ofw_machdep.c b/sys/arch/powerpc/powerpc/ofw_machdep.c
index a544b97850e..4e6184afe79 100644
--- a/sys/arch/powerpc/powerpc/ofw_machdep.c
+++ b/sys/arch/powerpc/powerpc/ofw_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofw_machdep.c,v 1.5 1998/05/29 04:15:40 rahnds Exp $ */
+/* $OpenBSD: ofw_machdep.c,v 1.6 1998/06/28 04:35:17 rahnds Exp $ */
/* $NetBSD: ofw_machdep.c,v 1.1 1996/09/30 16:34:50 ws Exp $ */
/*
@@ -100,6 +100,7 @@ extern void_f *pending_int_f;
void ofw_do_pending_int();
extern int system_type;
+void ofw_intr_init();
void
ofrootfound()
{
@@ -113,9 +114,40 @@ ofrootfound()
panic("ofroot not configured");
if (system_type == OFWMACH) {
pending_int_f = ofw_do_pending_int;
+ ofw_intr_init();
}
}
void
+ofw_intr_init()
+{
+ /*
+ * There are tty, network and disk drivers that use free() at interrupt
+ * time, so imp > (tty | net | bio).
+ */
+ /* with openfirmware drivers all levels block clock
+ * (have to block polling)
+ */
+ imask[IPL_IMP] = SPL_CLOCK;
+ imask[IPL_TTY] = SPL_CLOCK | SINT_TTY;
+ imask[IPL_NET] = SPL_CLOCK | SINT_NET;
+ imask[IPL_BIO] = SPL_CLOCK;
+ imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO];
+
+ /*
+ * Enforce a hierarchy that gives slow devices a better chance at not
+ * dropping data.
+ */
+ imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO];
+ imask[IPL_NET] |= imask[IPL_BIO];
+
+ /*
+ * These are pseudo-levels.
+ */
+ imask[IPL_NONE] = 0x00000000;
+ imask[IPL_HIGH] = 0xffffffff;
+
+}
+void
ofw_do_pending_int()
{
struct intrhand *ih;
@@ -133,12 +165,13 @@ static int processing;
dmsr = emsr & ~PSL_EE;
__asm__ volatile("mtmsr %0" :: "r"(dmsr));
+
pcpl = splhigh(); /* Turn off all */
- if(ipending & SINT_CLOCK) {
+ if((ipending & SINT_CLOCK) && (pcpl & imask[IPL_CLOCK] == 0)) {
ipending &= ~SINT_CLOCK;
softclock();
}
- if(ipending & SINT_NET) {
+ if((ipending & SINT_NET) && ((pcpl & imask[IPL_NET]) == 0) ) {
extern int netisr;
int pisr = netisr;
netisr = 0;