diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c index 41be56987e3..5bed43d77ba 100644 --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -1085,16 +1085,16 @@ priv_ithread_execute_handler(struct proc *p, struct intr_handler *ih) } #endif -static void -ithread_execute_handlers(struct proc *p, struct intr_event *ie) +/* + * This is a public function for use by drivers that mux interrupt + * handlers for child devices from their interrupt handler. + */ +void +intr_event_execute_handlers(struct proc *p, struct intr_event *ie) { struct intr_handler *ih, *ihn; - /* Interrupt handlers should not sleep. */ - if (!(ie->ie_flags & IE_SOFT)) - THREAD_NO_SLEEPING(); TAILQ_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) { - /* * If this handler is marked for death, remove it from * the list of handlers and wake up the sleeper. @@ -1135,6 +1135,16 @@ ithread_execute_handlers(struct proc *p, struct intr_event *ie) if (!(ih->ih_flags & IH_MPSAFE)) mtx_unlock(&Giant); } +} + +static void +ithread_execute_handlers(struct proc *p, struct intr_event *ie) +{ + + /* Interrupt handlers should not sleep. */ + if (!(ie->ie_flags & IE_SOFT)) + THREAD_NO_SLEEPING(); + intr_event_execute_handlers(p, ie); if (!(ie->ie_flags & IE_SOFT)) THREAD_SLEEPING_OK(); diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h index be5d0f4710f..fed9020d0f8 100644 --- a/sys/sys/interrupt.h +++ b/sys/sys/interrupt.h @@ -90,6 +90,16 @@ struct intr_handler { * 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. + * + * Note that device drivers may also use interrupt events to manage + * multiplexing interrupt interrupt handler into handlers for child + * devices. In that case, the above hooks are not used. The device + * can create an event for its interrupt resource and register child + * event handlers with that event. It can then use + * intr_event_execute_handlers() to execute non-filter handlers. + * Currently filter handlers are not supported by this, but that can + * be added by splitting out the filter loop from intr_event_handle() + * if desired. */ struct intr_event { TAILQ_ENTRY(intr_event) ie_list; @@ -132,6 +142,8 @@ struct intr_event { #define SWI_TQ 6 #define SWI_TQ_GIANT 6 +struct proc; + extern struct intr_event *tty_intr_event; extern struct intr_event *clk_intr_event; extern void *softclock_ih; @@ -157,6 +169,7 @@ int intr_event_create(struct intr_event **event, void *source, int (*assign_cpu)(void *, u_char), const char *fmt, ...) __printflike(9, 10); int intr_event_destroy(struct intr_event *ie); +void intr_event_execute_handlers(struct proc *p, struct intr_event *ie); int intr_event_handle(struct intr_event *ie, struct trapframe *frame); int intr_event_remove_handler(void *cookie); int intr_getaffinity(int irq, void *mask);