- 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
This commit is contained in:
jhb 2000-11-01 18:40:02 +00:00
parent f4546b7184
commit 0d90af5b3b
2 changed files with 60 additions and 17 deletions

View File

@ -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 */
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;
/* 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);

View File

@ -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);