summaryrefslogtreecommitdiffstats
path: root/sys/alpha
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2000-11-01 18:40:02 +0000
committerjhb <jhb@FreeBSD.org>2000-11-01 18:40:02 +0000
commit9b0a561703be32661910f94cd90c9a84cac698c2 (patch)
tree0d34d554cc204c9a21f942e7d50b1ca8e7d6d4fc /sys/alpha
parent6465172ef0394f572ce797e9ca931a77d345299c (diff)
downloadFreeBSD-src-9b0a561703be32661910f94cd90c9a84cac698c2.zip
FreeBSD-src-9b0a561703be32661910f94cd90c9a84cac698c2.tar.gz
- Modify alpha_setup_intr() to take interrupt handler flags as an additional
argument. These flags include INTR_FAST, INTR_MPSAFE, etc. - Properly handle INTR_EXCL when it is passed in to allow an interrupt handler to claim exclusive ownership of an interrupt thread. - Add support for psuedo-fast interrupts on the alpha. For fast interrupts, we don't allocate an interrupt thread; instead, during dispatching of an interrupt, we run the handler directly instead of scheduling the thread to run. Note that the handler is currently run without Giant and must be MP safe. The only fast handler currently is for the sio driver. Requested by: dfr
Diffstat (limited to 'sys/alpha')
-rw-r--r--sys/alpha/alpha/interrupt.c77
-rw-r--r--sys/alpha/include/intr.h2
2 files changed, 61 insertions, 18 deletions
diff --git a/sys/alpha/alpha/interrupt.c b/sys/alpha/alpha/interrupt.c
index ebaf1e5..91f5745 100644
--- a/sys/alpha/alpha/interrupt.c
+++ b/sys/alpha/alpha/interrupt.c
@@ -337,8 +337,8 @@ static struct alpha_intr_list alpha_intr_hash[31];
int
alpha_setup_intr(const char *name, int vector, driver_intr_t *handler,
- void *arg, int pri, void **cookiep, volatile long *cntp,
- void (*disable)(int), void (*enable)(int))
+ void *arg, int pri, int flags, void **cookiep,
+ volatile long *cntp, void (*disable)(int), void (*enable)(int))
{
int h = HASHVEC(vector);
struct alpha_intr *i;
@@ -383,22 +383,48 @@ alpha_setup_intr(const char *name, int vector, driver_intr_t *handler,
}
/* Create a kernel thread if needed. */
- if (ithd->it_proc == NULL) {
- errcode = kthread_create(ithd_loop, NULL, &p,
- RFSTOPPED | RFHIGHPID, "intr: %s", name);
- if (errcode)
- panic(
+ if ((flags & INTR_FAST) == 0) {
+ if (ithd->it_proc == NULL) {
+ errcode = kthread_create(ithd_loop, NULL, &p,
+ RFSTOPPED | RFHIGHPID, "intr: %s", name);
+ if (errcode)
+ panic(
"alpha_setup_intr: Can't create interrupt thread");
- p->p_rtprio.type = RTP_PRIO_ITHREAD;
- p->p_stat = SWAIT; /* we're idle */
-
- /* Put in linkages. */
- ithd->it_proc = p;
- p->p_ithd = ithd;
- } else
- snprintf(ithd->it_proc->p_comm, MAXCOMLEN, "intr%03x: %s",
- vector, name);
- p->p_rtprio.prio = pri;
+ p->p_rtprio.type = RTP_PRIO_ITHREAD;
+ p->p_stat = SWAIT; /* we're idle */
+
+ /* Put in linkages. */
+ ithd->it_proc = p;
+ p->p_ithd = ithd;
+ } else
+ snprintf(ithd->it_proc->p_comm, MAXCOMLEN,
+ "intr: %s", name);
+ p->p_rtprio.prio = pri;
+ }
+ } else if ((flags & INTR_EXCL) != 0 ||
+ (ithd->it_ih->ih_flags & INTR_EXCL) != 0) {
+ /*
+ * We can't have more than one exclusive handler for a given
+ * interrupt.
+ */
+ if (bootverbose)
+ printf(
+ "\tdevice combination %s and %s doesn't support shared vector %x\n",
+ ithd->it_ih->ih_name, name, vector);
+ return EINVAL;
+ } else if ((flags & INTR_FAST) != 0) {
+ /* We can only have one fast interrupt by itself. */
+ if (bootverbose)
+ printf(
+ "\tCan't add fast interrupt %s to normal interrupt %s on vector %x\n",
+ name, ithd->it_ih->ih_name, vector);
+ return EINVAL;
+ } else if (ithd->it_proc == NULL) {
+ if (bootverbose)
+ printf(
+ "\tCan't add normal interrupt %s to fast interrupt %s on vector %x\n",
+ name, ithd->it_ih->ih_name, vector);
+ return EINVAL;
} else {
p = ithd->it_proc;
if (strlen(p->p_comm) + strlen(name) < MAXCOMLEN) {
@@ -417,6 +443,7 @@ alpha_setup_intr(const char *name, int vector, driver_intr_t *handler,
idesc->ih_handler = handler;
idesc->ih_argument = arg;
+ idesc->ih_flags = flags;
idesc->ih_name = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK);
if (idesc->ih_name == NULL) {
free(idesc, M_DEVBUF);
@@ -505,6 +532,22 @@ alpha_dispatch_intr(void *frame, unsigned long vector)
atomic_add_long(i->cntp, 1);
+ /*
+ * Handle a fast interrupt if there is no actual thread for this
+ * interrupt by calling the handler directly without Giant. Note
+ * that this means that any fast interrupt handler must be MP safe.
+ */
+ if (ithd->it_proc == NULL) {
+ KASSERT(ithd->it_ih->ih_flags & INTR_FAST != 0,
+ ("threaded interrupt without a thread"));
+ KASSERT(ithd->it_ih->ih_next == NULL,
+ ("fast interrupt with more than one handler"));
+
+ ithd->it_ih->ih_handler(ithd->it_ih->ih_argument);
+
+ return;
+ }
+
CTR3(KTR_INTR, "sched_ithd pid %d(%s) need=%d",
ithd->it_proc->p_pid, ithd->it_proc->p_comm, ithd->it_need);
diff --git a/sys/alpha/include/intr.h b/sys/alpha/include/intr.h
index e43010d..c34cc00 100644
--- a/sys/alpha/include/intr.h
+++ b/sys/alpha/include/intr.h
@@ -30,7 +30,7 @@
#define _MACHINE_INTR_H_
int alpha_setup_intr(const char *name, int vector,
- driver_intr_t *handle, void *arg, int pri,
+ driver_intr_t *handle, void *arg, int pri, int flags,
void **cookiep, volatile long *cntp,
void (*disable)(int), void (*enable)(int));
int alpha_teardown_intr(void *cookie);
OpenPOWER on IntegriCloud