summaryrefslogtreecommitdiff
path: root/sys/arch/powerpc
diff options
context:
space:
mode:
authorDale S. Rahn <rahnds@cvs.openbsd.org>1998-06-28 04:35:18 +0000
committerDale S. Rahn <rahnds@cvs.openbsd.org>1998-06-28 04:35:18 +0000
commit37276203429b8712d224da288edfa446c32e6589 (patch)
tree52b915408ab608d4aadfcdfa05db2f1e1e6063a0 /sys/arch/powerpc
parentb2abda949db3ed1f65f7dfb096bf19ae3de1fa6e (diff)
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...
Diffstat (limited to 'sys/arch/powerpc')
-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;