Date: Mon, 4 Dec 2006 16:00:01 +0100 From: Paolo Pisati <piso@freebsd.org> To: powerpc@freebsd.org Cc: Peter Grehan <grehan@freebsd.org> Subject: [patch] Shared interrupts with fast handlers Message-ID: <20061204150001.GA45877@tin.it>
next in thread | raw e-mail | index | archive | help
--xHFwDpU9dbj6ez1V Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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! --xHFwDpU9dbj6ez1V Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="intr_machdep.powerpc.patch" --- 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); -} --xHFwDpU9dbj6ez1V--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20061204150001.GA45877>