diff options
author | Dale S. Rahn <rahnds@cvs.openbsd.org> | 1998-06-28 04:35:18 +0000 |
---|---|---|
committer | Dale S. Rahn <rahnds@cvs.openbsd.org> | 1998-06-28 04:35:18 +0000 |
commit | 37276203429b8712d224da288edfa446c32e6589 (patch) | |
tree | 52b915408ab608d4aadfcdfa05db2f1e1e6063a0 /sys/arch/powerpc | |
parent | b2abda949db3ed1f65f7dfb096bf19ae3de1fa6e (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.c | 39 |
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; |