diff options
author | jhb <jhb@FreeBSD.org> | 2008-09-15 22:19:44 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2008-09-15 22:19:44 +0000 |
commit | a55e334c2b95f0796667f2ecdd2434e08fe6f8fc (patch) | |
tree | 2045b32008303953d8acb3b05bfee0ce28955f1b | |
parent | be294ffd1c90512a25d1e1246249a832151d76b7 (diff) | |
download | FreeBSD-src-a55e334c2b95f0796667f2ecdd2434e08fe6f8fc.zip FreeBSD-src-a55e334c2b95f0796667f2ecdd2434e08fe6f8fc.tar.gz |
Expose a new public routine intr_event_execute_handlers() which executes
all the non-filter handlers attached to an interrupt event. This can be
used by device drivers which multiplex their interrupt onto the interrupt
handlers for child devices.
-rw-r--r-- | sys/kern/kern_intr.c | 22 | ||||
-rw-r--r-- | sys/sys/interrupt.h | 13 |
2 files changed, 29 insertions, 6 deletions
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c index 41be569..5bed43d 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 be5d0f4..fed9020 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); |