summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/intr_machdep.c113
-rw-r--r--sys/arm/arm/intr.c46
-rw-r--r--sys/i386/i386/intr_machdep.c123
-rw-r--r--sys/ia64/ia64/interrupt.c50
-rw-r--r--sys/kern/kern_intr.c126
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c46
-rw-r--r--sys/sparc64/sparc64/intr_machdep.c54
-rw-r--r--sys/sun4v/sun4v/intr_machdep.c93
-rw-r--r--sys/sys/interrupt.h51
9 files changed, 168 insertions, 534 deletions
diff --git a/sys/amd64/amd64/intr_machdep.c b/sys/amd64/amd64/intr_machdep.c
index 0d95928..0f57958 100644
--- a/sys/amd64/amd64/intr_machdep.c
+++ b/sys/amd64/amd64/intr_machdep.c
@@ -85,9 +85,6 @@ static void intr_assign_next_cpu(struct intsrc *isrc);
static int intr_assign_cpu(void *arg, u_char cpu);
static void intr_disable_src(void *arg);
-#ifdef INTR_FILTER
-static void intr_event_stray(void *cookie);
-#endif
static void intr_init(void *__dummy);
static int intr_pic_registered(struct pic *pic);
static void intrcnt_setname(const char *name, int index);
@@ -238,66 +235,12 @@ intr_disable_src(void *arg)
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
}
-#ifdef INTR_FILTER
void
intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
{
- struct thread *td;
struct intr_event *ie;
- int vector;
-
- td = curthread;
-
- /*
- * We count software interrupts when we process them. The
- * code here follows previous practice, but there's an
- * argument for counting hardware interrupts when they're
- * processed too.
- */
- (*isrc->is_count)++;
- PCPU_INC(cnt.v_intr);
-
- ie = isrc->is_event;
-
- /*
- * XXX: We assume that IRQ 0 is only used for the ISA timer
- * device (clk).
- */
- vector = isrc->is_pic->pic_vector(isrc);
- if (vector == 0)
- clkintr_pending = 1;
-
- if (intr_event_handle(ie, frame) != 0)
- intr_event_stray(isrc);
-}
-
-static void
-intr_event_stray(void *cookie)
-{
- struct intsrc *isrc;
-
- isrc = cookie;
- /*
- * For stray interrupts, mask and EOI the source, bump the
- * stray count, and log the condition.
- */
- isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
- (*isrc->is_straycount)++;
- if (*isrc->is_straycount < MAX_STRAY_LOG)
- log(LOG_ERR, "stray irq%d\n", isrc->is_pic->pic_vector(isrc));
- else if (*isrc->is_straycount == MAX_STRAY_LOG)
- log(LOG_CRIT,
- "too many stray irq %d's: not logging anymore\n",
- isrc->is_pic->pic_vector(isrc));
-}
-#else
-void
-intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
-{
struct thread *td;
- struct intr_event *ie;
- struct intr_handler *ih;
- int error, vector, thread, ret;
+ int vector;
td = curthread;
@@ -324,7 +267,7 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
* For stray interrupts, mask and EOI the source, bump the
* stray count, and log the condition.
*/
- if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers)) {
+ if (intr_event_handle(ie, frame) != 0) {
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
(*isrc->is_straycount)++;
if (*isrc->is_straycount < MAX_STRAY_LOG)
@@ -333,60 +276,8 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
log(LOG_CRIT,
"too many stray irq %d's: not logging anymore\n",
vector);
- return;
}
-
- /*
- * Execute fast interrupt handlers directly.
- * To support clock handlers, if a handler registers
- * with a NULL argument, then we pass it a pointer to
- * a trapframe as its argument.
- */
- td->td_intr_nesting_level++;
- ret = 0;
- thread = 0;
- critical_enter();
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (ih->ih_filter == NULL) {
- thread = 1;
- continue;
- }
- CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
- ih->ih_filter, ih->ih_argument == NULL ? frame :
- ih->ih_argument, ih->ih_name);
- if (ih->ih_argument == NULL)
- ret = ih->ih_filter(frame);
- else
- ret = ih->ih_filter(ih->ih_argument);
- /*
- * Wrapper handler special case: see
- * i386/intr_machdep.c::intr_execute_handlers()
- */
- if (!thread) {
- if (ret == FILTER_SCHEDULE_THREAD)
- thread = 1;
- }
- }
-
- /*
- * If there are any threaded handlers that need to run,
- * mask the source as well as sending it an EOI. Otherwise,
- * just send it an EOI but leave it unmasked.
- */
- if (thread)
- isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
- else
- isrc->is_pic->pic_eoi_source(isrc);
-
- /* Schedule the ithread if needed. */
- if (thread) {
- error = intr_event_schedule_thread(ie);
- KASSERT(error == 0, ("bad stray interrupt"));
- }
- critical_exit();
- td->td_intr_nesting_level--;
}
-#endif
void
intr_resume(void)
diff --git a/sys/arm/arm/intr.c b/sys/arm/arm/intr.c
index ecc9770..5fbdce7 100644
--- a/sys/arm/arm/intr.c
+++ b/sys/arm/arm/intr.c
@@ -72,7 +72,7 @@ arm_setup_irqhandler(const char *name, driver_filter_t *filt,
if (event == NULL) {
error = intr_event_create(&event, (void *)irq, 0,
(mask_fn)arm_mask_irq, (mask_fn)arm_unmask_irq,
- (mask_fn)arm_unmask_irq, NULL, "intr%d:", irq);
+ NULL, NULL, "intr%d:", irq);
if (error)
return;
intr_events[irq] = event;
@@ -106,57 +106,17 @@ arm_handler_execute(struct trapframe *frame, int irqnb)
{
struct intr_event *event;
struct thread *td = curthread;
-#ifdef INTR_FILTER
int i;
-#else
- int i, thread, ret;
- struct intr_handler *ih;
-#endif
PCPU_INC(cnt.v_intr);
td->td_intr_nesting_level++;
while ((i = arm_get_next_irq()) != -1) {
-#ifndef INTR_FILTER
- arm_mask_irq(i);
-#endif
intrcnt[intrcnt_tab[i]]++;
event = intr_events[i];
- if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
-#ifdef INTR_FILTER
+ if (intr_event_handle(event, frame) != 0) {
+ /* XXX: Log stray IRQs */
arm_mask_irq(i);
-#endif
- continue;
}
-
-#ifdef INTR_FILTER
- intr_event_handle(event, frame);
- /* XXX: Log stray IRQs */
-#else
- /* Execute fast handlers. */
- ret = 0;
- thread = 0;
- TAILQ_FOREACH(ih, &event->ie_handlers, ih_next) {
- if (ih->ih_filter == NULL)
- thread = 1;
- else
- ret = ih->ih_filter(ih->ih_argument ?
- ih->ih_argument : frame);
- /*
- * Wrapper handler special case: see
- * i386/intr_machdep.c::intr_execute_handlers()
- */
- if (!thread) {
- if (ret == FILTER_SCHEDULE_THREAD)
- thread = 1;
- }
- }
-
- /* Schedule thread if needed. */
- if (thread)
- intr_event_schedule_thread(event);
- else
- arm_unmask_irq(i);
-#endif
}
td->td_intr_nesting_level--;
}
diff --git a/sys/i386/i386/intr_machdep.c b/sys/i386/i386/intr_machdep.c
index 89f247c..a2b8a1d 100644
--- a/sys/i386/i386/intr_machdep.c
+++ b/sys/i386/i386/intr_machdep.c
@@ -76,9 +76,6 @@ static void intr_assign_next_cpu(struct intsrc *isrc);
static int intr_assign_cpu(void *arg, u_char cpu);
static void intr_disable_src(void *arg);
-#ifdef INTR_FILTER
-static void intr_event_stray(void *cookie);
-#endif
static void intr_init(void *__dummy);
static int intr_pic_registered(struct pic *pic);
static void intrcnt_setname(const char *name, int index);
@@ -229,66 +226,12 @@ intr_disable_src(void *arg)
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
}
-#ifdef INTR_FILTER
void
intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
{
- struct thread *td;
struct intr_event *ie;
- int vector;
-
- td = curthread;
-
- /*
- * We count software interrupts when we process them. The
- * code here follows previous practice, but there's an
- * argument for counting hardware interrupts when they're
- * processed too.
- */
- (*isrc->is_count)++;
- PCPU_INC(cnt.v_intr);
-
- ie = isrc->is_event;
-
- /*
- * XXX: We assume that IRQ 0 is only used for the ISA timer
- * device (clk).
- */
- vector = isrc->is_pic->pic_vector(isrc);
- if (vector == 0)
- clkintr_pending = 1;
-
- if (intr_event_handle(ie, frame) != 0)
- intr_event_stray(isrc);
-}
-
-static void
-intr_event_stray(void *cookie)
-{
- struct intsrc *isrc;
-
- isrc = cookie;
- /*
- * For stray interrupts, mask and EOI the source, bump the
- * stray count, and log the condition.
- */
- isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
- (*isrc->is_straycount)++;
- if (*isrc->is_straycount < MAX_STRAY_LOG)
- log(LOG_ERR, "stray irq%d\n", isrc->is_pic->pic_vector(isrc));
- else if (*isrc->is_straycount == MAX_STRAY_LOG)
- log(LOG_CRIT,
- "too many stray irq %d's: not logging anymore\n",
- isrc->is_pic->pic_vector(isrc));
-}
-#else
-void
-intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
-{
struct thread *td;
- struct intr_event *ie;
- struct intr_handler *ih;
- int error, vector, thread, ret;
+ int vector;
td = curthread;
@@ -315,7 +258,7 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
* For stray interrupts, mask and EOI the source, bump the
* stray count, and log the condition.
*/
- if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers)) {
+ if (intr_event_handle(ie, frame) != 0) {
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
(*isrc->is_straycount)++;
if (*isrc->is_straycount < MAX_STRAY_LOG)
@@ -324,70 +267,8 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
log(LOG_CRIT,
"too many stray irq %d's: not logging anymore\n",
vector);
- return;
}
-
- /*
- * Execute fast interrupt handlers directly.
- * To support clock handlers, if a handler registers
- * with a NULL argument, then we pass it a pointer to
- * a trapframe as its argument.
- */
- td->td_intr_nesting_level++;
- ret = 0;
- thread = 0;
- critical_enter();
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (ih->ih_filter == NULL) {
- thread = 1;
- continue;
- }
- CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
- ih->ih_filter, ih->ih_argument == NULL ? frame :
- ih->ih_argument, ih->ih_name);
- if (ih->ih_argument == NULL)
- ret = ih->ih_filter(frame);
- else
- ret = ih->ih_filter(ih->ih_argument);
- /*
- * Wrapper handler special handling:
- *
- * in some particular cases (like pccard and pccbb),
- * the _real_ device handler is wrapped in a couple of
- * functions - a filter wrapper and an ithread wrapper.
- * In this case (and just in this case), the filter wrapper
- * could ask the system to schedule the ithread and mask
- * the interrupt source if the wrapped handler is composed
- * of just an ithread handler.
- *
- * TODO: write a generic wrapper to avoid people rolling
- * their own
- */
- if (!thread) {
- if (ret == FILTER_SCHEDULE_THREAD)
- thread = 1;
- }
- }
-
- /*
- * If there are any threaded handlers that need to run,
- * mask the source as well as sending it an EOI. Otherwise,
- * just send it an EOI but leave it unmasked.
- */
- if (thread)
- isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
- else
- isrc->is_pic->pic_eoi_source(isrc);
-
- /* Schedule the ithread if needed. */
- if (thread) {
- error = intr_event_schedule_thread(ie);
- KASSERT(error == 0, ("bad stray interrupt"));
- }
- critical_exit();
- td->td_intr_nesting_level--;
}
-#endif
void
intr_resume(void)
diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c
index 720e5f9..c0e4ae3 100644
--- a/sys/ia64/ia64/interrupt.c
+++ b/sys/ia64/ia64/interrupt.c
@@ -385,10 +385,6 @@ ia64_dispatch_intr(void *frame, u_int vector)
{
struct ia64_intr *i;
struct intr_event *ie; /* our interrupt event */
-#ifndef INTR_FILTER
- struct intr_handler *ih;
- int error, thread, ret;
-#endif
/*
* Find the interrupt thread for this vector.
@@ -401,52 +397,14 @@ ia64_dispatch_intr(void *frame, u_int vector)
ie = i->event;
KASSERT(ie != NULL, ("%s: interrupt without event", __func__));
-#ifdef INTR_FILTER
if (intr_event_handle(ie, frame) != 0) {
- ia64_intr_mask((void *)(uintptr_t)vector);
- log(LOG_ERR, "stray irq%u\n", i->irq);
- }
-#else
- /*
- * As an optimization, if an event has no handlers, don't
- * schedule it to run.
- */
- if (TAILQ_EMPTY(&ie->ie_handlers))
- return;
-
- /*
- * Execute all fast interrupt handlers directly without Giant. Note
- * that this means that any fast interrupt handler must be MP safe.
- */
- ret = 0;
- thread = 0;
- critical_enter();
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (ih->ih_filter == NULL) {
- thread = 1;
- continue;
- }
- CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
- ih->ih_filter, ih->ih_argument, ih->ih_name);
- ret = ih->ih_filter(ih->ih_argument);
/*
- * Wrapper handler special case: see
- * i386/intr_machdep.c::intr_execute_handlers()
+ * XXX: The pre-INTR_FILTER code didn't mask stray
+ * interrupts.
*/
- if (!thread) {
- if (ret == FILTER_SCHEDULE_THREAD)
- thread = 1;
- }
- }
-
- if (thread) {
ia64_intr_mask((void *)(uintptr_t)vector);
- error = intr_event_schedule_thread(ie);
- KASSERT(error == 0, ("%s: impossible stray", __func__));
- } else
- ia64_intr_eoi((void *)(uintptr_t)vector);
- critical_exit();
-#endif
+ log(LOG_ERR, "stray irq%u\n", i->irq);
+ }
}
#ifdef DDB
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index 75234b6..6bd434d 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -94,9 +94,14 @@ static TAILQ_HEAD(, intr_event) event_list =
static void intr_event_update(struct intr_event *ie);
#ifdef INTR_FILTER
+static int intr_event_schedule_thread(struct intr_event *ie,
+ struct intr_thread *ithd);
+static int intr_filter_loop(struct intr_event *ie,
+ struct trapframe *frame, struct intr_thread **ithd);
static struct intr_thread *ithread_create(const char *name,
struct intr_handler *ih);
#else
+static int intr_event_schedule_thread(struct intr_event *ie);
static struct intr_thread *ithread_create(const char *name);
#endif
static void ithread_destroy(struct intr_thread *ithread);
@@ -239,8 +244,9 @@ intr_event_update(struct intr_event *ie)
int
intr_event_create(struct intr_event **event, void *source,int flags,
- void (*disable)(void *), void (*enable)(void *), void (*eoi)(void *),
- int (*assign_cpu)(void *, u_char), const char *fmt, ...)
+ void (*pre_ithread)(void *), void (*post_ithread)(void *),
+ void (*post_filter)(void *), int (*assign_cpu)(void *, u_char),
+ const char *fmt, ...)
{
struct intr_event *ie;
va_list ap;
@@ -250,9 +256,9 @@ intr_event_create(struct intr_event **event, void *source,int flags,
return (EINVAL);
ie = malloc(sizeof(struct intr_event), M_ITHREAD, M_WAITOK | M_ZERO);
ie->ie_source = source;
- ie->ie_disable = disable;
- ie->ie_enable = enable;
- ie->ie_eoi = eoi;
+ ie->ie_pre_ithread = pre_ithread;
+ ie->ie_post_ithread = post_ithread;
+ ie->ie_post_filter = post_filter;
ie->ie_assign_cpu = assign_cpu;
ie->ie_flags = flags;
ie->ie_cpu = NOCPU;
@@ -675,7 +681,7 @@ ok:
return (0);
}
-int
+static int
intr_event_schedule_thread(struct intr_event *ie)
{
struct intr_entropy entropy;
@@ -832,7 +838,7 @@ ok:
return (0);
}
-int
+static int
intr_event_schedule_thread(struct intr_event *ie, struct intr_thread *it)
{
struct intr_entropy entropy;
@@ -1084,8 +1090,8 @@ ithread_execute_handlers(struct proc *p, struct intr_event *ie)
* Now that all the handlers have had a chance to run, reenable
* the interrupt source.
*/
- if (ie->ie_enable != NULL)
- ie->ie_enable(ie->ie_source);
+ if (ie->ie_post_ithread != NULL)
+ ie->ie_post_ithread(ie->ie_source);
}
#ifndef INTR_FILTER
@@ -1172,6 +1178,90 @@ ithread_loop(void *arg)
thread_unlock(td);
}
}
+
+/*
+ * Main interrupt handling body.
+ *
+ * Input:
+ * o ie: the event connected to this interrupt.
+ * o frame: some archs (i.e. i386) pass a frame to some.
+ * handlers as their main argument.
+ * Return value:
+ * o 0: everything ok.
+ * o EINVAL: stray interrupt.
+ */
+int
+intr_event_handle(struct intr_event *ie, struct trapframe *frame)
+{
+ struct intr_handler *ih;
+ struct thread *td;
+ int error, ret, thread;
+
+ td = curthread;
+
+ /* An interrupt with no event or handlers is a stray interrupt. */
+ if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers))
+ return (EINVAL);
+
+ /*
+ * Execute fast interrupt handlers directly.
+ * To support clock handlers, if a handler registers
+ * with a NULL argument, then we pass it a pointer to
+ * a trapframe as its argument.
+ */
+ td->td_intr_nesting_level++;
+ thread = 0;
+ ret = 0;
+ critical_enter();
+ TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ if (ih->ih_filter == NULL) {
+ thread = 1;
+ continue;
+ }
+ CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
+ ih->ih_filter, ih->ih_argument == NULL ? frame :
+ ih->ih_argument, ih->ih_name);
+ if (ih->ih_argument == NULL)
+ ret = ih->ih_filter(frame);
+ else
+ ret = ih->ih_filter(ih->ih_argument);
+ /*
+ * Wrapper handler special handling:
+ *
+ * in some particular cases (like pccard and pccbb),
+ * the _real_ device handler is wrapped in a couple of
+ * functions - a filter wrapper and an ithread wrapper.
+ * In this case (and just in this case), the filter wrapper
+ * could ask the system to schedule the ithread and mask
+ * the interrupt source if the wrapped handler is composed
+ * of just an ithread handler.
+ *
+ * TODO: write a generic wrapper to avoid people rolling
+ * their own
+ */
+ if (!thread) {
+ if (ret == FILTER_SCHEDULE_THREAD)
+ thread = 1;
+ }
+ }
+
+ if (thread) {
+ if (ie->ie_pre_ithread != NULL)
+ ie->ie_pre_ithread(ie->ie_source);
+ } else {
+ if (ie->ie_post_filter != NULL)
+ ie->ie_post_filter(ie->ie_source);
+ }
+
+ /* Schedule the ithread if needed. */
+ if (thread) {
+ error = intr_event_schedule_thread(ie);
+ KASSERT(error == 0, ("bad stray interrupt"));
+ }
+ critical_exit();
+ td->td_intr_nesting_level--;
+ return (0);
+}
#else
/*
* This is the main code for interrupt threads.
@@ -1287,7 +1377,7 @@ ithread_loop(void *arg)
* scheduled.
*/
-int
+static int
intr_filter_loop(struct intr_event *ie, struct trapframe *frame,
struct intr_thread **ithd)
{
@@ -1363,19 +1453,13 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
td->td_intr_nesting_level++;
thread = 0;
critical_enter();
- thread = intr_filter_loop(ie, frame, &ithd);
-
- /*
- * If the interrupt was fully served, send it an EOI but leave
- * it unmasked. Otherwise, mask the source as well as sending
- * it an EOI.
- */
+ thread = intr_filter_loop(ie, frame, &ithd);
if (thread & FILTER_HANDLED) {
- if (ie->ie_eoi != NULL)
- ie->ie_eoi(ie->ie_source);
+ if (ie->ie_post_filter != NULL)
+ ie->ie_post_filter(ie->ie_source);
} else {
- if (ie->ie_disable != NULL)
- ie->ie_disable(ie->ie_source);
+ if (ie->ie_pre_ithread != NULL)
+ ie->ie_pre_ithread(ie->ie_source);
}
critical_exit();
diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c
index 990ba51..5f1a651 100644
--- a/sys/powerpc/powerpc/intr_machdep.c
+++ b/sys/powerpc/powerpc/intr_machdep.c
@@ -277,10 +277,6 @@ powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
{
struct powerpc_intr *i;
struct intr_event *ie;
-#ifndef INTR_FILTER
- struct intr_handler *ih;
- int error, sched, ret;
-#endif
i = powerpc_intrs[vector];
if (i == NULL)
@@ -291,55 +287,15 @@ powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
ie = i->event;
KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
-#ifdef INTR_FILTER
if (intr_event_handle(ie, tf) != 0) {
- PIC_MASK(pic, i->irq);
- log(LOG_ERR, "stray irq%u\n", i->irq);
- }
-#else
- if (TAILQ_EMPTY(&ie->ie_handlers))
goto stray;
-
- /*
- * Execute all fast interrupt handlers directly without Giant. Note
- * that this means that any fast interrupt handler must be MP safe.
- */
- ret = 0;
- sched = 0;
- critical_enter();
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (ih->ih_filter == NULL) {
- sched = 1;
- continue;
- }
- CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
- ih->ih_filter, ih->ih_argument, ih->ih_name);
- ret = ih->ih_filter(ih->ih_argument);
- /*
- * Wrapper handler special case: see
- * i386/intr_machdep.c::intr_execute_handlers()
- */
- if (!sched) {
- if (ret == FILTER_SCHEDULE_THREAD)
- sched = 1;
- }
}
-
- if (sched) {
- PIC_MASK(pic, i->irq);
- error = intr_event_schedule_thread(ie);
- KASSERT(error == 0, ("%s: impossible stray interrupt",
- __func__));
- } else
- PIC_EOI(pic, i->irq);
- critical_exit();
-#endif
return;
stray:
stray_count++;
if (stray_count <= MAX_STRAY_LOG) {
- printf("stray irq %d\n", i->irq);
+ printf("stray irq %d\n", i ? i->irq : -1);
if (stray_count >= MAX_STRAY_LOG) {
printf("got %d stray interrupts, not logging anymore\n",
MAX_STRAY_LOG);
diff --git a/sys/sparc64/sparc64/intr_machdep.c b/sys/sparc64/sparc64/intr_machdep.c
index 115d486..d5e3e04 100644
--- a/sys/sparc64/sparc64/intr_machdep.c
+++ b/sys/sparc64/sparc64/intr_machdep.c
@@ -248,57 +248,9 @@ static void
intr_execute_handlers(void *cookie)
{
struct intr_vector *iv;
-#ifndef INTR_FILTER
- struct intr_event *ie;
- struct intr_handler *ih;
- int error, thread, ret;
-#endif
iv = cookie;
-#ifndef INTR_FILTER
- ie = iv->iv_event;
- if (iv->iv_ic == NULL || ie == NULL) {
- intr_stray_vector(iv);
- return;
- }
-
- /* Execute fast interrupt handlers directly. */
- ret = 0;
- thread = 0;
- critical_enter();
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (ih->ih_filter == NULL) {
- thread = 1;
- continue;
- }
- MPASS(ih->ih_filter != NULL && ih->ih_argument != NULL);
- CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__,
- ih->ih_filter, ih->ih_argument);
- ret = ih->ih_filter(ih->ih_argument);
- /*
- * Wrapper handler special case: see
- * i386/intr_machdep.c::intr_execute_handlers()
- */
- if (!thread) {
- if (ret == FILTER_SCHEDULE_THREAD)
- thread = 1;
- }
- }
- if (!thread)
- intr_enable_eoi(iv);
-
- /* Schedule a heavyweight interrupt process. */
- if (thread)
- error = intr_event_schedule_thread(ie);
- else if (TAILQ_EMPTY(&ie->ie_handlers))
- error = EINVAL;
- else
- error = 0;
- critical_exit();
- if (error == EINVAL)
-#else
- if (intr_event_handle(iv->iv_event, NULL) != 0)
-#endif
+ if (iv->iv_ic == NULL || intr_event_handle(iv->iv_event, NULL) != 0)
intr_stray_vector(iv);
}
@@ -329,8 +281,8 @@ intr_controller_register(int vec, const struct intr_controller *ic,
* CPU as long as the source of a level sensitive interrupt is
* not cleared.
*/
- error = intr_event_create(&ie, iv, 0, ic->ic_disable, intr_enable_eoi,
- ic->ic_eoi, NULL, "vec%d:", vec);
+ error = intr_event_create(&ie, iv, 0, NULL, intr_enable_eoi,
+ intr_enable_eoi, NULL, "vec%d:", vec);
if (error != 0)
return (error);
mtx_lock_spin(&intr_table_lock);
diff --git a/sys/sun4v/sun4v/intr_machdep.c b/sys/sun4v/sun4v/intr_machdep.c
index cdc933e..9dcfd3e 100644
--- a/sys/sun4v/sun4v/intr_machdep.c
+++ b/sys/sun4v/sun4v/intr_machdep.c
@@ -101,12 +101,6 @@ struct intr_vector intr_vectors[IV_MAX];
uint16_t intr_countp[IV_MAX];
static u_long intr_stray_count[IV_MAX];
-struct ithread_vector_handler {
- iv_func_t *ivh_handler;
- void *ivh_arg;
- u_int ivh_vec;
-};
-
static char *pil_names[] = {
"stray",
"low", /* PIL_LOW */
@@ -276,63 +270,23 @@ intr_init(void)
}
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
+static void
+intr_enable(void *cookie)
+{
+ int vec;
+
+ vec = (uintptr_t)cookie;
+ hv_intr_setstate(vec, HV_INTR_IDLE_STATE);
+}
static void
intr_execute_handlers(void *cookie)
{
struct intr_vector *iv;
- struct intr_event *ie;
- struct intr_handler *ih;
- int fast, thread, ret;
iv = cookie;
- ie = iv->iv_event;
- if (ie == NULL) {
- intr_stray_vector(iv);
- return;
- }
-
- ret = 0;
- fast = thread = 0;
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (ih->ih_filter == NULL) {
- thread = 1;
- continue;
- }
- MPASS(ih->ih_filter != NULL && ih->ih_argument != NULL);
- CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__,
- ih->ih_filter, ih->ih_argument);
- ret = ih->ih_filter(ih->ih_argument);
- fast = 1;
- /*
- * Wrapper handler special case: see
- * i386/intr_machdep.c::intr_execute_handlers()
- */
- if (!thread) {
- if (ret == FILTER_SCHEDULE_THREAD)
- thread = 1;
- }
- }
-
- /* Schedule a heavyweight interrupt process. */
- if (thread)
- intr_event_schedule_thread(ie);
- else if (TAILQ_EMPTY(&ie->ie_handlers))
+ if (intr_event_handle(iv->iv_event, NULL) != 0)
intr_stray_vector(iv);
-
- if (fast)
- hv_intr_setstate(iv->iv_vec, HV_INTR_IDLE_STATE);
-
-}
-
-static void
-ithread_wrapper(void *arg)
-{
- struct ithread_vector_handler *ivh = (struct ithread_vector_handler *)arg;
-
- ivh->ivh_handler(ivh->ivh_arg);
- /* re-enable interrupt */
- hv_intr_setstate(ivh->ivh_vec, HV_INTR_IDLE_STATE);
}
int
@@ -342,13 +296,8 @@ inthand_add(const char *name, int vec, driver_filter_t *filt,
struct intr_vector *iv;
struct intr_event *ie; /* descriptor for the IRQ */
struct intr_event *orphan;
- struct ithread_vector_handler *ivh;
int errcode, pil;
- if (filt != NULL && handler != NULL) {
- printf("both filt and handler set is not valid\n");
- return (EINVAL);
- }
/*
* Work around a race where more than one CPU may be registering
* handlers on the same IRQ at the same time.
@@ -359,7 +308,7 @@ inthand_add(const char *name, int vec, driver_filter_t *filt,
mtx_unlock_spin(&intr_table_lock);
if (ie == NULL) {
errcode = intr_event_create(&ie, (void *)(intptr_t)vec, 0, NULL,
- NULL, NULL, NULL, "vec%d:", vec);
+ intr_enable, intr_enable, NULL, "vec%d:", vec);
if (errcode)
return (errcode);
mtx_lock_spin(&intr_table_lock);
@@ -374,26 +323,12 @@ inthand_add(const char *name, int vec, driver_filter_t *filt,
}
}
- if (filt == NULL) {
- ivh = (struct ithread_vector_handler *)
- malloc(sizeof(struct ithread_vector_handler), M_DEVBUF, M_WAITOK);
- ivh->ivh_handler = (driver_intr_t *)handler;
- ivh->ivh_arg = arg;
- ivh->ivh_vec = vec;
- errcode = intr_event_add_handler(ie, name, NULL, ithread_wrapper, ivh,
- intr_priority(flags), flags, cookiep);
- } else {
- ivh = NULL;
- errcode = intr_event_add_handler(ie, name, filt, NULL, arg,
- intr_priority(flags), flags,
- cookiep);
- }
+ errcode = intr_event_add_handler(ie, name, filt, handler, arg,
+ intr_priority(flags), flags, cookiep);
- if (errcode) {
- if (ivh)
- free(ivh, M_DEVBUF);
+ if (errcode)
return (errcode);
- }
+
pil = (filt != NULL) ? PIL_FAST : PIL_ITHREAD;
intr_setup(pil, intr_fast, vec, intr_execute_handlers, iv);
diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h
index 319c49c..f47bb26 100644
--- a/sys/sys/interrupt.h
+++ b/sys/sys/interrupt.h
@@ -63,6 +63,33 @@ struct intr_handler {
/*
* Describe an interrupt event. An event holds a list of handlers.
+ * The 'pre_ithread', 'post_ithread', 'post_filter', and 'assign_cpu'
+ * hooks are used to invoke MD code for certain operations.
+ *
+ * The 'pre_ithread' hook is called when an interrupt thread for
+ * handlers without filters is scheduled. It is responsible for
+ * ensuring that 1) the system won't be swamped with an interrupt
+ * storm from the associated source while the ithread runs and 2) the
+ * current CPU is able to receive interrupts from other interrupt
+ * sources. The first is usually accomplished by disabling
+ * level-triggered interrupts until the ithread completes. The second
+ * is accomplished on some platforms by acknowledging the interrupt
+ * via an EOI.
+ *
+ * The 'post_ithread' hook is invoked when an ithread finishes. It is
+ * responsible for ensuring that the associated interrupt source will
+ * trigger an interrupt when it is asserted in the future. Usually
+ * this is implemented by enabling a level-triggered interrupt that
+ * was previously disabled via the 'pre_ithread' hook.
+ *
+ * The 'post_filter' hook is invoked when a filter handles an
+ * interrupt. It is responsible for ensuring that the current CPU is
+ * able to receive interrupts again. On some platforms this is done
+ * by acknowledging the interrupts via an EOI.
+ *
+ * The 'assign_cpu' hook is used to bind an interrupt source to a
+ * specific CPU. If the interrupt cannot be bound, this function may
+ * return an error.
*/
struct intr_event {
TAILQ_ENTRY(intr_event) ie_list;
@@ -72,9 +99,9 @@ struct intr_event {
struct mtx ie_lock;
void *ie_source; /* Cookie used by MD code. */
struct intr_thread *ie_thread; /* Thread we are connected to. */
- void (*ie_disable)(void *);
- void (*ie_enable)(void *);
- void (*ie_eoi)(void *);
+ void (*ie_pre_ithread)(void *);
+ void (*ie_post_ithread)(void *);
+ void (*ie_post_filter)(void *);
int (*ie_assign_cpu)(void *, u_char);
int ie_flags;
int ie_count; /* Loop counter. */
@@ -118,29 +145,19 @@ extern char intrnames[]; /* string table containing device names */
#ifdef DDB
void db_dump_intr_event(struct intr_event *ie, int handlers);
#endif
-#ifdef INTR_FILTER
-int intr_filter_loop(struct intr_event *ie, struct trapframe *frame,
- struct intr_thread **ithd);
-int intr_event_handle(struct intr_event *ie, struct trapframe *frame);
-#endif
u_char intr_priority(enum intr_type flags);
int intr_event_add_handler(struct intr_event *ie, const char *name,
driver_filter_t filter, driver_intr_t handler, void *arg,
u_char pri, enum intr_type flags, void **cookiep);
int intr_event_bind(struct intr_event *ie, u_char cpu);
int intr_event_create(struct intr_event **event, void *source,
- int flags, void (*disable)(void *), void (*enable)(void *),
- void (*eoi)(void *), int (*assign_cpu)(void *, u_char),
- const char *fmt, ...)
+ int flags, void (*pre_ithread)(void *),
+ void (*post_ithread)(void *), void (*post_filter)(void *),
+ int (*assign_cpu)(void *, u_char), const char *fmt, ...)
__printflike(8, 9);
int intr_event_destroy(struct intr_event *ie);
+int intr_event_handle(struct intr_event *ie, struct trapframe *frame);
int intr_event_remove_handler(void *cookie);
-#ifndef INTR_FILTER
-int intr_event_schedule_thread(struct intr_event *ie);
-#else
-int intr_event_schedule_thread(struct intr_event *ie,
- struct intr_thread *ithd);
-#endif
void *intr_handler_source(void *cookie);
int swi_add(struct intr_event **eventp, const char *name,
driver_intr_t handler, void *arg, int pri, enum intr_type flags,
OpenPOWER on IntegriCloud