From ce7ecde8a3b3be10658611b34f09d9ebd3c68623 Mon Sep 17 00:00:00 2001 From: thorpej Date: Mon, 9 Dec 1996 03:04:46 +0000 Subject: [PATCH] Dynamically compute the PSL value for spl{bio,net,tty,imp}() calls. --- sys/arch/hp300/hp300/isr.c | 111 +++++++++++++++++++++++++++++++-- sys/arch/hp300/hp300/isr.h | 15 ++++- sys/arch/hp300/include/param.h | 21 +++++-- 3 files changed, 135 insertions(+), 12 deletions(-) diff --git a/sys/arch/hp300/hp300/isr.c b/sys/arch/hp300/hp300/isr.c index 34bb12033cfa..afbc73730a78 100644 --- a/sys/arch/hp300/hp300/isr.c +++ b/sys/arch/hp300/hp300/isr.c @@ -1,4 +1,4 @@ -/* $NetBSD: isr.c,v 1.3 1996/10/13 03:14:29 christos Exp $ */ +/* $NetBSD: isr.c,v 1.4 1996/12/09 03:04:46 thorpej Exp $ */ /* * Copyright (c) 1995, 1996 Jason R. Thorpe. @@ -46,16 +46,21 @@ #include #include #include -#include #include +#include + #include typedef LIST_HEAD(, isr) isr_list_t; isr_list_t isr_list[NISR]; +u_short hp300_bioipl, hp300_netipl, hp300_ttyipl, hp300_impipl; + extern int intrcnt[]; /* from locore.s */ +void isrcomputeipl __P((void)); + void isrinit() { @@ -65,13 +70,90 @@ isrinit() for (i = 0; i < NISR; ++i) { LIST_INIT(&isr_list[i]); } + + /* Default interrupt priorities. */ + hp300_bioipl = hp300_netipl = hp300_ttyipl = hp300_impipl = + (PSL_S|PSL_IPL3); +} + +/* + * Scan all of the ISRs, recomputing the interrupt levels for the spl*() + * calls. This doesn't have to be fast. + */ +void +isrcomputeipl() +{ + struct isr *isr; + int ipl; + + /* Start with low values. */ + hp300_bioipl = hp300_netipl = hp300_ttyipl = hp300_impipl = + (PSL_S|PSL_IPL3); + + for (ipl = 0; ipl < NISR; ipl++) { + for (isr = isr_list[ipl].lh_first; isr != NULL; + isr = isr->isr_link.le_next) { + /* + * Bump up the level for a given priority, + * if necessary. + */ + switch (isr->isr_priority) { + case ISRPRI_BIO: + if (ipl > PSLTOIPL(hp300_bioipl)) + hp300_bioipl = IPLTOPSL(ipl); + break; + + case ISRPRI_NET: + if (ipl > PSLTOIPL(hp300_netipl)) + hp300_netipl = IPLTOPSL(ipl); + break; + + case ISRPRI_TTY: + case ISRPRI_TTYNOBUF: + if (ipl > PSLTOIPL(hp300_ttyipl)) + hp300_ttyipl = IPLTOPSL(ipl); + break; + + default: + printf("priority = %d\n", isr->isr_priority); + panic("isrcomputeipl: bad priority"); + } + } + } + + /* + * Enforce `bio <= net <= tty <= imp' + */ + + if (hp300_netipl < hp300_bioipl) + hp300_netipl = hp300_bioipl; + + if (hp300_ttyipl < hp300_netipl) + hp300_ttyipl = hp300_netipl; + + if (hp300_impipl < hp300_ttyipl) + hp300_impipl = hp300_ttyipl; +} + +void +isrprintlevels() +{ + +#ifdef DEBUG + printf("psl: bio = 0x%x, net = 0x%x, tty = 0x%x, imp = 0x%x\n", + hp300_bioipl, hp300_netipl, hp300_ttyipl, hp300_impipl); +#endif + + printf("interrupt levels: bio = %d, net = %d, tty = %d\n", + PSLTOIPL(hp300_bioipl), PSLTOIPL(hp300_netipl), + PSLTOIPL(hp300_ttyipl)); } /* * Establish an interrupt handler. * Called by driver attach functions. */ -void +void * isrlink(func, arg, ipl, priority) int (*func) __P((void *)); void *arg; @@ -120,7 +202,7 @@ isrlink(func, arg, ipl, priority) list = &isr_list[ipl]; if (list->lh_first == NULL) { LIST_INSERT_HEAD(list, newisr, isr_link); - return; + goto compute; } /* @@ -132,7 +214,7 @@ isrlink(func, arg, ipl, priority) curisr = curisr->isr_link.le_next) { if (newisr->isr_priority > curisr->isr_priority) { LIST_INSERT_BEFORE(curisr, newisr, isr_link); - return; + goto compute; } } @@ -141,6 +223,25 @@ isrlink(func, arg, ipl, priority) * on the end. */ LIST_INSERT_AFTER(curisr, newisr, isr_link); + + compute: + /* Compute new interrupt levels. */ + isrcomputeipl(); + return (newisr); +} + +/* + * Disestablish an interrupt handler. + */ +void +isrunlink(arg) + void *arg; +{ + struct isr *isr = arg; + + LIST_REMOVE(isr, isr_link); + free(isr, M_DEVBUF); + isrcomputeipl(); } /* diff --git a/sys/arch/hp300/hp300/isr.h b/sys/arch/hp300/hp300/isr.h index 3bf7d4043881..3d5967d21df4 100644 --- a/sys/arch/hp300/hp300/isr.h +++ b/sys/arch/hp300/hp300/isr.h @@ -1,4 +1,4 @@ -/* $NetBSD: isr.h,v 1.6 1996/02/28 01:03:53 thorpej Exp $ */ +/* $NetBSD: isr.h,v 1.7 1996/12/09 03:04:47 thorpej Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -55,12 +55,23 @@ struct isr { /* * ISR priorities. These are not the same as interrupt levels. + * These serve 2 purposes: + * - properly order ISRs in the list + * - compute levels for spl*() calls. */ #define ISRPRI_BIO 0 #define ISRPRI_NET 1 #define ISRPRI_TTY 2 #define ISRPRI_TTYNOBUF 3 +/* + * Convert PSL values to IPLs and vice-versa. + */ +#define PSLTOIPL(x) (((x) >> 8) & 0xf) +#define IPLTOPSL(x) ((((x) & 0xf) << 8) | PSL_S) + void isrinit __P((void)); -void isrlink __P((int (*)(void *), void *, int, int)); +void *isrlink __P((int (*)(void *), void *, int, int)); +void isrunlink __P((void *)); void isrdispatch __P((int)); +void isrprintlevels __P((void)); diff --git a/sys/arch/hp300/include/param.h b/sys/arch/hp300/include/param.h index 11d963389d12..9d2e11574302 100644 --- a/sys/arch/hp300/include/param.h +++ b/sys/arch/hp300/include/param.h @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.26 1996/05/17 15:38:08 thorpej Exp $ */ +/* $NetBSD: param.h,v 1.27 1996/12/09 03:04:48 thorpej Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -163,12 +163,23 @@ #define spl6() _spl(PSL_S|PSL_IPL6) #define spl7() _spl(PSL_S|PSL_IPL7) +#if defined(_KERNEL) && !defined(_LOCORE) +/* + * These four globals contain the appropriate PSL_S|PSL_IPL? values + * to raise interrupt priority to the requested level. + */ +extern unsigned short hp300_bioipl; +extern unsigned short hp300_netipl; +extern unsigned short hp300_ttyipl; +extern unsigned short hp300_impipl; +#endif /* _KERNEL && !_LOCORE */ + #define splsoftclock() spl1() #define splsoftnet() spl1() -#define splbio() spl5() -#define splnet() spl5() -#define spltty() spl5() -#define splimp() spl5() +#define splbio() _spl(hp300_bioipl) +#define splnet() _spl(hp300_netipl) +#define spltty() _spl(hp300_ttyipl) +#define splimp() _spl(hp300_impipl) #define splclock() spl6() #define splstatclock() spl6() #define splvm() spl6()