summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Reindl <martin@cvs.openbsd.org>2007-04-21 21:37:10 +0000
committerMartin Reindl <martin@cvs.openbsd.org>2007-04-21 21:37:10 +0000
commitf1962253191567e6c9f7d4960a64a3e32d8319d3 (patch)
tree2bd4cda95b3b79ff1990c7883748f73f525c4ab3
parent988dbc62ab7af0c06ac315a0b9e13c3999bee2d0 (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.c79
-rw-r--r--sys/arch/alpha/include/_types.h3
-rw-r--r--sys/arch/alpha/include/intr.h28
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. */