[patch] Shared interrupts with fast handlers
Paolo Pisati
piso at freebsd.org
Mon Dec 4 07:00:17 PST 2006
Hi list,
attached is my patch to let ppc share different fast handlers
on the same irq line.
It's slightly different from the patch i sent to Peter back then, and
form the code in my p4 tree, with much _less_ code churn.
If Peter/Marcel/anyone can test it, and i works, please feel free
to commit it.
Thanks.
--
Paolo
Piso's first law: nothing works as expected!
-------------- next part --------------
--- sys/powerpc/include/intr_machdep.h.orig Sun Dec 3 17:50:52 2006
+++ sys/powerpc/include/intr_machdep.h Mon Dec 4 12:46:30 2006
@@ -33,11 +33,8 @@
struct intr_event;
struct ppc_intr_handler {
- ih_func_t *ih_func;
- void *ih_arg;
struct intr_event *ih_event;
u_int ih_irq;
- u_int ih_flags;
u_int ih_index;
u_long *ih_count;
u_long *ih_straycount;
--- sys/powerpc/powerpc/intr_machdep.c.orig Sun Dec 3 17:50:52 2006
+++ sys/powerpc/powerpc/intr_machdep.c Mon Dec 4 15:13:13 2006
@@ -66,6 +66,7 @@
#include <sys/queue.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
+#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
@@ -82,10 +83,8 @@
MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
-static int intr_initialized = 0;
-
static u_int intr_nirq;
-static struct ppc_intr_handler *intr_handlers;
+static struct ppc_intr_handler *intr_handlers = NULL;
static struct mtx intr_table_lock;
@@ -94,7 +93,6 @@
static int intrcnt_index;
static ih_func_t intr_stray_handler;
-static ih_func_t sched_ithd;
static void (*irq_enable)(uintptr_t);
static void (*irq_disable)(uintptr_t);
@@ -139,25 +137,18 @@
int i;
u_int32_t msr;
- if (intr_initialized != 0)
+ if (intr_handlers != NULL)
panic("intr_init: interrupts intialized twice\n");
- intr_initialized++;
-
intr_nirq = nirq;
intr_handlers = malloc(nirq * sizeof(struct ppc_intr_handler), M_INTR,
M_NOWAIT|M_ZERO);
if (intr_handlers == NULL)
panic("intr_init: unable to allocate interrupt handler array");
- for (i = 0; i < nirq; i++) {
- intr_handlers[i].ih_func = intr_stray_handler;
- intr_handlers[i].ih_arg = &intr_handlers[i];
- intr_handlers[i].ih_irq = i;
- intr_handlers[i].ih_flags = 0;
- /* mux all initial stray irqs onto same count... */
+ /* mux all initial stray irqs onto same count... */
+ for (i = 0; i < nirq; i++)
intr_handlers[i].ih_straycount = &intrcnt[0];
- }
intrcnt_setname("???", 0);
intrcnt_index = 1;
@@ -175,22 +166,6 @@
mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
}
-void
-intr_setup(u_int irq, ih_func_t *ihf, void *iha, u_int flags)
-{
- u_int32_t msr;
-
- msr = mfmsr();
- mtmsr(msr & ~PSL_EE);
-
- intr_handlers[irq].ih_func = ihf;
- intr_handlers[irq].ih_arg = iha;
- intr_handlers[irq].ih_irq = irq;
- intr_handlers[irq].ih_flags = flags;
-
- mtmsr(msr);
-}
-
int
inthand_add(const char *name, u_int irq, void (*handler)(void *), void *arg,
int flags, void **cookiep)
@@ -198,7 +173,6 @@
struct ppc_intr_handler *ih;
struct intr_event *event, *orphan;
int error = 0;
- int created_event = 0;
/*
* Work around a race where more than one CPU may be registering
@@ -218,7 +192,6 @@
if (ih->ih_event == NULL) {
ih->ih_event = event;
- created_event++;
mtx_unlock_spin(&intr_table_lock);
} else {
orphan = event;
@@ -228,21 +201,12 @@
}
}
- /* XXX: Should probably fix support for multiple FAST. */
- if (flags & INTR_FAST)
- flags |= INTR_EXCL;
error = intr_event_add_handler(event, name, handler, arg,
intr_priority(flags), flags, cookiep);
- if ((flags & INTR_FAST) == 0 || error)
- intr_setup(irq, sched_ithd, ih, flags);
-
if (error)
return (error);
- if (flags & INTR_FAST)
- intr_setup(irq, handler, arg, flags);
-
intrcnt_register(ih);
return (0);
@@ -251,37 +215,42 @@
int
inthand_remove(u_int irq, void *cookie)
{
- struct ppc_intr_handler *ih;
- int error;
-
- error = intr_event_remove_handler(cookie);
-
- if (error == 0) {
- ih = &intr_handlers[irq];
-
- mtx_lock_spin(&intr_table_lock);
-
- if (ih->ih_event == NULL) {
- intr_setup(irq, intr_stray_handler, ih, 0);
- } else {
- intr_setup(irq, sched_ithd, ih, 0);
- }
-
- mtx_unlock_spin(&intr_table_lock);
- }
-
- return (error);
+ return (intr_event_remove_handler(cookie));
}
void
intr_handle(u_int irq)
{
- atomic_add_long(intr_handlers[irq].ih_count, 1);
- intr_handlers[irq].ih_func(intr_handlers[irq].ih_arg);
+ struct ppc_intr_handler *ppc_ih = &intr_handlers[irq];
+ struct intr_event *ie = ppc_ih->ih_event;
+ struct intr_handler *ih;
+ int error = 0, thread;
+
+ if (ie == NULL) {
+ intr_stray_handler(ppc_ih);
+ return;
+ }
+
+ atomic_add_long(ppc_ih->ih_count, 1);
+
+ /* Execute fast interrupt handlers directly. */
+ thread = 0;
+ TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ if (!(ih->ih_flags & IH_FAST)) {
+ thread = 1;
+ continue;
+ }
+ CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__,
+ ih->ih_handler, ih->ih_argument);
+ ih->ih_handler(ih->ih_argument);
+ }
+
+ /* Schedule a heavyweight interrupt process. */
+ if (thread)
+ error = intr_event_schedule_thread(ie);
- /* XXX wrong thing when using pre-emption ? */
- if ((intr_handlers[irq].ih_flags & INTR_FAST) != 0)
- irq_enable(irq);
+ if (error == EINVAL)
+ intr_stray_handler(ppc_ih);
}
static void
@@ -301,16 +270,3 @@
}
}
-static void
-sched_ithd(void *cookie)
-{
- struct ppc_intr_handler *ih;
- int error;
-
- ih = (struct ppc_intr_handler *)cookie;
-
- error = intr_event_schedule_thread(ih->ih_event);
-
- if (error == EINVAL)
- intr_stray_handler(ih);
-}
More information about the freebsd-ppc
mailing list