summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-09-15 22:19:44 +0000
committerjhb <jhb@FreeBSD.org>2008-09-15 22:19:44 +0000
commita55e334c2b95f0796667f2ecdd2434e08fe6f8fc (patch)
tree2045b32008303953d8acb3b05bfee0ce28955f1b
parentbe294ffd1c90512a25d1e1246249a832151d76b7 (diff)
downloadFreeBSD-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.c22
-rw-r--r--sys/sys/interrupt.h13
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);
OpenPOWER on IntegriCloud