diff options
author | Martin Reindl <martin@cvs.openbsd.org> | 2007-04-21 21:37:10 +0000 |
---|---|---|
committer | Martin Reindl <martin@cvs.openbsd.org> | 2007-04-21 21:37:10 +0000 |
commit | f1962253191567e6c9f7d4960a64a3e32d8319d3 (patch) | |
tree | 2bd4cda95b3b79ff1990c7883748f73f525c4ab3 | |
parent | 988dbc62ab7af0c06ac315a0b9e13c3999bee2d0 (diff) |
fix generic soft interrupts; improve establishing and disestablishing of
soft interrupts
from NetBSD, 'reads good art@', also tested by robert@
-rw-r--r-- | sys/arch/alpha/alpha/interrupt.c | 79 | ||||
-rw-r--r-- | sys/arch/alpha/include/_types.h | 3 | ||||
-rw-r--r-- | sys/arch/alpha/include/intr.h | 28 |
3 files changed, 75 insertions, 35 deletions
diff --git a/sys/arch/alpha/alpha/interrupt.c b/sys/arch/alpha/alpha/interrupt.c index 6dc85203c96..cc6ea1638a1 100644 --- a/sys/arch/alpha/alpha/interrupt.c +++ b/sys/arch/alpha/alpha/interrupt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interrupt.c,v 1.20 2006/06/15 20:08:29 brad Exp $ */ +/* $OpenBSD: interrupt.c,v 1.21 2007/04/21 21:37:09 martin Exp $ */ /* $NetBSD: interrupt.c,v 1.46 2000/06/03 20:47:36 thorpej Exp $ */ /*- @@ -528,9 +528,9 @@ softintr_init() for (i = 0; i < IPL_NSOFT; i++) { asi = &alpha_soft_intrs[i]; - LIST_INIT(&asi->softintr_q); + TAILQ_INIT(&asi->softintr_q); simple_lock_init(&asi->softintr_slock); - asi->softintr_ipl = i; + asi->softintr_siq = i; } /* XXX Establish legacy software interrupt handlers. */ @@ -556,26 +556,57 @@ softintr_dispatch() for (i = 0; i < IPL_NSOFT; i++) { if ((n & (1 << i)) == 0) continue; + asi = &alpha_soft_intrs[i]; - /* Already at splsoft() */ - simple_lock(&asi->softintr_slock); + for (;;) { + (void) alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); + simple_lock(&asi->softintr_slock); - for (sih = LIST_FIRST(&asi->softintr_q); - sih != NULL; - sih = LIST_NEXT(sih, sih_q)) { - if (sih->sih_pending) { - uvmexp.softs++; + sih = TAILQ_FIRST(&asi->softintr_q); + if (sih != NULL) { + TAILQ_REMOVE(&asi->softintr_q, sih, + sih_q); sih->sih_pending = 0; - (*sih->sih_fn)(sih->sih_arg); } - } - simple_unlock(&asi->softintr_slock); + simple_unlock(&asi->softintr_slock); + (void) alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT); + + if (sih == NULL) + break; + + uvmexp.softs++; + (*sih->sih_fn)(sih->sih_arg); + } } } } +static int +ipl2si(int ipl) +{ + int si; + + switch (ipl) { + case IPL_SOFTSERIAL: + si = SI_SOFTSERIAL; + break; + case IPL_SOFTNET: + si = SI_SOFTNET; + break; + case IPL_SOFTCLOCK: + si = SI_SOFTCLOCK; + break; + case IPL_SOFT: + si = SI_SOFT; + break; + default: + panic("ipl2si: %d", ipl); + } + return si; +} + /* * softintr_establish: [interface] * @@ -586,12 +617,10 @@ softintr_establish(int ipl, void (*func)(void *), void *arg) { struct alpha_soft_intr *asi; struct alpha_soft_intrhand *sih; - int s; + int si; - if (__predict_false(ipl >= IPL_NSOFT || ipl < 0)) - panic("softintr_establish"); - - asi = &alpha_soft_intrs[ipl]; + si = ipl2si(ipl); + asi = &alpha_soft_intrs[si]; sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT); if (__predict_true(sih != NULL)) { @@ -599,11 +628,6 @@ softintr_establish(int ipl, void (*func)(void *), void *arg) sih->sih_fn = func; sih->sih_arg = arg; sih->sih_pending = 0; - s = splsoft(); - simple_lock(&asi->softintr_slock); - LIST_INSERT_HEAD(&asi->softintr_q, sih, sih_q); - simple_unlock(&asi->softintr_slock); - splx(s); } return (sih); } @@ -620,11 +644,12 @@ softintr_disestablish(void *arg) struct alpha_soft_intr *asi = sih->sih_intrhead; int s; - (void) asi; /* XXX Unused if simple locks are noops. */ - - s = splsoft(); + s = splhigh(); simple_lock(&asi->softintr_slock); - LIST_REMOVE(sih, sih_q); + if (sih->sih_pending) { + TAILQ_REMOVE(&asi->softintr_q, sih, sih_q); + sih->sih_pending = 0; + } simple_unlock(&asi->softintr_slock); splx(s); diff --git a/sys/arch/alpha/include/_types.h b/sys/arch/alpha/include/_types.h index eb1f22cd310..6f005758e56 100644 --- a/sys/arch/alpha/include/_types.h +++ b/sys/arch/alpha/include/_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: _types.h,v 1.2 2007/04/12 14:38:36 martin Exp $ */ +/* $OpenBSD: _types.h,v 1.3 2007/04/21 21:37:09 martin Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -121,5 +121,6 @@ typedef void * __wctype_t; /* Feature test macros */ #define __HAVE_DEVICE_REGISTER #define __HAVE_CPUINFO +#define __HAVE_GENERIC_SOFT_INTERRUPTS #endif /* _ALPHA__TYPES_H_ */ diff --git a/sys/arch/alpha/include/intr.h b/sys/arch/alpha/include/intr.h index ea6c5b7e708..48faadc1497 100644 --- a/sys/arch/alpha/include/intr.h +++ b/sys/arch/alpha/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.25 2007/04/13 08:31:50 martin Exp $ */ +/* $OpenBSD: intr.h,v 1.26 2007/04/21 21:37:09 martin Exp $ */ /* $NetBSD: intr.h,v 1.26 2000/06/03 20:47:41 thorpej Exp $ */ /*- @@ -135,6 +135,11 @@ struct scbvec { #define IST_EDGE 2 /* edge-triggered */ #define IST_LEVEL 3 /* level-triggered */ +#define SI_SOFTSERIAL 0 +#define SI_SOFTNET 1 +#define SI_SOFTCLOCK 2 +#define SI_SOFT 3 + #ifdef _KERNEL /* SPL asserts */ @@ -223,9 +228,8 @@ extern unsigned long ssir; #define setsoft(x) atomic_setbits_ulong(&ssir, 1 << (x)) -#define __GENERIC_SOFT_INTERRUPTS struct alpha_soft_intrhand { - LIST_ENTRY(alpha_soft_intrhand) + TAILQ_ENTRY(alpha_soft_intrhand) sih_q; struct alpha_soft_intr *sih_intrhead; void (*sih_fn)(void *); @@ -234,10 +238,10 @@ struct alpha_soft_intrhand { }; struct alpha_soft_intr { - LIST_HEAD(, alpha_soft_intrhand) + TAILQ_HEAD(, alpha_soft_intrhand) softintr_q; struct simplelock softintr_slock; - unsigned long softintr_ipl; + unsigned long softintr_siq; }; void *softintr_establish(int, void (*)(void *), void *); @@ -248,8 +252,18 @@ void softintr_dispatch(void); #define softintr_schedule(arg) \ do { \ struct alpha_soft_intrhand *__sih = (arg); \ - __sih->sih_pending = 1; \ - setsoft(__sih->sih_intrhead->softintr_ipl); \ + struct alpha_soft_intr *__si = __sih->sih_intrhead; \ + int __s; \ + \ + __s = splhigh(); \ + simple_lock(&__si->softintr_slock); \ + if (__sih->sih_pending == 0) { \ + TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q); \ + __sih->sih_pending = 1; \ + setsoft(__si->softintr_siq); \ + } \ + simple_unlock(&__si->softintr_slock); \ + splx(__s); \ } while (0) /* XXX For legacy software interrupts. */ |