diff options
author | jhb <jhb@FreeBSD.org> | 2000-11-01 18:40:02 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2000-11-01 18:40:02 +0000 |
commit | 9b0a561703be32661910f94cd90c9a84cac698c2 (patch) | |
tree | 0d34d554cc204c9a21f942e7d50b1ca8e7d6d4fc /sys/alpha | |
parent | 6465172ef0394f572ce797e9ca931a77d345299c (diff) | |
download | FreeBSD-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.c | 77 | ||||
-rw-r--r-- | sys/alpha/include/intr.h | 2 |
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); |