Date: Tue, 19 May 2009 19:45:37 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r192406 - in stable/7/sys: . amd64/amd64 arm/arm contrib/pf dev/ath/ath_hal dev/cxgb i386/i386 ia64/ia64 kern powerpc/powerpc sparc64/sparc64 sun4v/sun4v sys Message-ID: <200905191945.n4JJjb0Q008111@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Tue May 19 19:45:36 2009 New Revision: 192406 URL: http://svn.freebsd.org/changeset/base/192406 Log: MFC: Add a MI intr_event_handle() routine for the non-INTR_FILTER case. This allows all the INTR_FILTER #ifdef's to be removed from the MD interrupt code. Modified: stable/7/sys/ (props changed) stable/7/sys/amd64/amd64/intr_machdep.c stable/7/sys/arm/arm/intr.c stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/i386/i386/intr_machdep.c stable/7/sys/ia64/ia64/interrupt.c stable/7/sys/kern/kern_intr.c stable/7/sys/powerpc/powerpc/intr_machdep.c stable/7/sys/sparc64/sparc64/intr_machdep.c stable/7/sys/sun4v/sun4v/intr_machdep.c stable/7/sys/sys/interrupt.h Modified: stable/7/sys/amd64/amd64/intr_machdep.c ============================================================================== --- stable/7/sys/amd64/amd64/intr_machdep.c Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/amd64/amd64/intr_machdep.c Tue May 19 19:45:36 2009 (r192406) @@ -85,9 +85,6 @@ static void intr_assign_next_cpu(struct static int intr_assign_cpu(void *arg, u_char cpu); static void intr_disable_src(void *arg); -#ifdef INTR_FILTER -static void intr_event_stray(void *cookie); -#endif static void intr_init(void *__dummy); static int intr_pic_registered(struct pic *pic); static void intrcnt_setname(const char *name, int index); @@ -238,66 +235,12 @@ intr_disable_src(void *arg) isrc->is_pic->pic_disable_source(isrc, PIC_EOI); } -#ifdef INTR_FILTER void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) { - struct thread *td; struct intr_event *ie; - int vector; - - td = curthread; - - /* - * We count software interrupts when we process them. The - * code here follows previous practice, but there's an - * argument for counting hardware interrupts when they're - * processed too. - */ - (*isrc->is_count)++; - PCPU_INC(cnt.v_intr); - - ie = isrc->is_event; - - /* - * XXX: We assume that IRQ 0 is only used for the ISA timer - * device (clk). - */ - vector = isrc->is_pic->pic_vector(isrc); - if (vector == 0) - clkintr_pending = 1; - - if (intr_event_handle(ie, frame) != 0) - intr_event_stray(isrc); -} - -static void -intr_event_stray(void *cookie) -{ - struct intsrc *isrc; - - isrc = cookie; - /* - * For stray interrupts, mask and EOI the source, bump the - * stray count, and log the condition. - */ - isrc->is_pic->pic_disable_source(isrc, PIC_EOI); - (*isrc->is_straycount)++; - if (*isrc->is_straycount < MAX_STRAY_LOG) - log(LOG_ERR, "stray irq%d\n", isrc->is_pic->pic_vector(isrc)); - else if (*isrc->is_straycount == MAX_STRAY_LOG) - log(LOG_CRIT, - "too many stray irq %d's: not logging anymore\n", - isrc->is_pic->pic_vector(isrc)); -} -#else -void -intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) -{ struct thread *td; - struct intr_event *ie; - struct intr_handler *ih; - int error, vector, thread, ret; + int vector; td = curthread; @@ -324,7 +267,7 @@ intr_execute_handlers(struct intsrc *isr * For stray interrupts, mask and EOI the source, bump the * stray count, and log the condition. */ - if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers)) { + if (intr_event_handle(ie, frame) != 0) { isrc->is_pic->pic_disable_source(isrc, PIC_EOI); (*isrc->is_straycount)++; if (*isrc->is_straycount < MAX_STRAY_LOG) @@ -333,60 +276,8 @@ intr_execute_handlers(struct intsrc *isr log(LOG_CRIT, "too many stray irq %d's: not logging anymore\n", vector); - return; } - - /* - * Execute fast interrupt handlers directly. - * To support clock handlers, if a handler registers - * with a NULL argument, then we pass it a pointer to - * a trapframe as its argument. - */ - td->td_intr_nesting_level++; - ret = 0; - thread = 0; - critical_enter(); - TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { - if (ih->ih_filter == NULL) { - thread = 1; - continue; - } - CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, - ih->ih_filter, ih->ih_argument == NULL ? frame : - ih->ih_argument, ih->ih_name); - if (ih->ih_argument == NULL) - ret = ih->ih_filter(frame); - else - ret = ih->ih_filter(ih->ih_argument); - /* - * Wrapper handler special case: see - * i386/intr_machdep.c::intr_execute_handlers() - */ - if (!thread) { - if (ret == FILTER_SCHEDULE_THREAD) - thread = 1; - } - } - - /* - * If there are any threaded handlers that need to run, - * mask the source as well as sending it an EOI. Otherwise, - * just send it an EOI but leave it unmasked. - */ - if (thread) - isrc->is_pic->pic_disable_source(isrc, PIC_EOI); - else - isrc->is_pic->pic_eoi_source(isrc); - - /* Schedule the ithread if needed. */ - if (thread) { - error = intr_event_schedule_thread(ie); - KASSERT(error == 0, ("bad stray interrupt")); - } - critical_exit(); - td->td_intr_nesting_level--; } -#endif void intr_resume(void) Modified: stable/7/sys/arm/arm/intr.c ============================================================================== --- stable/7/sys/arm/arm/intr.c Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/arm/arm/intr.c Tue May 19 19:45:36 2009 (r192406) @@ -72,7 +72,7 @@ arm_setup_irqhandler(const char *name, d if (event == NULL) { error = intr_event_create(&event, (void *)irq, 0, (mask_fn)arm_mask_irq, (mask_fn)arm_unmask_irq, - (mask_fn)arm_unmask_irq, NULL, "intr%d:", irq); + NULL, NULL, "intr%d:", irq); if (error) return; intr_events[irq] = event; @@ -106,57 +106,17 @@ arm_handler_execute(struct trapframe *fr { struct intr_event *event; struct thread *td = curthread; -#ifdef INTR_FILTER int i; -#else - int i, thread, ret; - struct intr_handler *ih; -#endif PCPU_INC(cnt.v_intr); td->td_intr_nesting_level++; while ((i = arm_get_next_irq()) != -1) { -#ifndef INTR_FILTER - arm_mask_irq(i); -#endif intrcnt[intrcnt_tab[i]]++; event = intr_events[i]; - if (!event || TAILQ_EMPTY(&event->ie_handlers)) { -#ifdef INTR_FILTER + if (intr_event_handle(event, frame) != 0) { + /* XXX: Log stray IRQs */ arm_mask_irq(i); -#endif - continue; } - -#ifdef INTR_FILTER - intr_event_handle(event, frame); - /* XXX: Log stray IRQs */ -#else - /* Execute fast handlers. */ - ret = 0; - thread = 0; - TAILQ_FOREACH(ih, &event->ie_handlers, ih_next) { - if (ih->ih_filter == NULL) - thread = 1; - else - ret = ih->ih_filter(ih->ih_argument ? - ih->ih_argument : frame); - /* - * Wrapper handler special case: see - * i386/intr_machdep.c::intr_execute_handlers() - */ - if (!thread) { - if (ret == FILTER_SCHEDULE_THREAD) - thread = 1; - } - } - - /* Schedule thread if needed. */ - if (thread) - intr_event_schedule_thread(event); - else - arm_unmask_irq(i); -#endif } td->td_intr_nesting_level--; } Modified: stable/7/sys/i386/i386/intr_machdep.c ============================================================================== --- stable/7/sys/i386/i386/intr_machdep.c Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/i386/i386/intr_machdep.c Tue May 19 19:45:36 2009 (r192406) @@ -76,9 +76,6 @@ static void intr_assign_next_cpu(struct static int intr_assign_cpu(void *arg, u_char cpu); static void intr_disable_src(void *arg); -#ifdef INTR_FILTER -static void intr_event_stray(void *cookie); -#endif static void intr_init(void *__dummy); static int intr_pic_registered(struct pic *pic); static void intrcnt_setname(const char *name, int index); @@ -229,66 +226,12 @@ intr_disable_src(void *arg) isrc->is_pic->pic_disable_source(isrc, PIC_EOI); } -#ifdef INTR_FILTER void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) { - struct thread *td; struct intr_event *ie; - int vector; - - td = curthread; - - /* - * We count software interrupts when we process them. The - * code here follows previous practice, but there's an - * argument for counting hardware interrupts when they're - * processed too. - */ - (*isrc->is_count)++; - PCPU_INC(cnt.v_intr); - - ie = isrc->is_event; - - /* - * XXX: We assume that IRQ 0 is only used for the ISA timer - * device (clk). - */ - vector = isrc->is_pic->pic_vector(isrc); - if (vector == 0) - clkintr_pending = 1; - - if (intr_event_handle(ie, frame) != 0) - intr_event_stray(isrc); -} - -static void -intr_event_stray(void *cookie) -{ - struct intsrc *isrc; - - isrc = cookie; - /* - * For stray interrupts, mask and EOI the source, bump the - * stray count, and log the condition. - */ - isrc->is_pic->pic_disable_source(isrc, PIC_EOI); - (*isrc->is_straycount)++; - if (*isrc->is_straycount < MAX_STRAY_LOG) - log(LOG_ERR, "stray irq%d\n", isrc->is_pic->pic_vector(isrc)); - else if (*isrc->is_straycount == MAX_STRAY_LOG) - log(LOG_CRIT, - "too many stray irq %d's: not logging anymore\n", - isrc->is_pic->pic_vector(isrc)); -} -#else -void -intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) -{ struct thread *td; - struct intr_event *ie; - struct intr_handler *ih; - int error, vector, thread, ret; + int vector; td = curthread; @@ -315,7 +258,7 @@ intr_execute_handlers(struct intsrc *isr * For stray interrupts, mask and EOI the source, bump the * stray count, and log the condition. */ - if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers)) { + if (intr_event_handle(ie, frame) != 0) { isrc->is_pic->pic_disable_source(isrc, PIC_EOI); (*isrc->is_straycount)++; if (*isrc->is_straycount < MAX_STRAY_LOG) @@ -324,70 +267,8 @@ intr_execute_handlers(struct intsrc *isr log(LOG_CRIT, "too many stray irq %d's: not logging anymore\n", vector); - return; } - - /* - * Execute fast interrupt handlers directly. - * To support clock handlers, if a handler registers - * with a NULL argument, then we pass it a pointer to - * a trapframe as its argument. - */ - td->td_intr_nesting_level++; - ret = 0; - thread = 0; - critical_enter(); - TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { - if (ih->ih_filter == NULL) { - thread = 1; - continue; - } - CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, - ih->ih_filter, ih->ih_argument == NULL ? frame : - ih->ih_argument, ih->ih_name); - if (ih->ih_argument == NULL) - ret = ih->ih_filter(frame); - else - ret = ih->ih_filter(ih->ih_argument); - /* - * Wrapper handler special handling: - * - * in some particular cases (like pccard and pccbb), - * the _real_ device handler is wrapped in a couple of - * functions - a filter wrapper and an ithread wrapper. - * In this case (and just in this case), the filter wrapper - * could ask the system to schedule the ithread and mask - * the interrupt source if the wrapped handler is composed - * of just an ithread handler. - * - * TODO: write a generic wrapper to avoid people rolling - * their own - */ - if (!thread) { - if (ret == FILTER_SCHEDULE_THREAD) - thread = 1; - } - } - - /* - * If there are any threaded handlers that need to run, - * mask the source as well as sending it an EOI. Otherwise, - * just send it an EOI but leave it unmasked. - */ - if (thread) - isrc->is_pic->pic_disable_source(isrc, PIC_EOI); - else - isrc->is_pic->pic_eoi_source(isrc); - - /* Schedule the ithread if needed. */ - if (thread) { - error = intr_event_schedule_thread(ie); - KASSERT(error == 0, ("bad stray interrupt")); - } - critical_exit(); - td->td_intr_nesting_level--; } -#endif void intr_resume(void) Modified: stable/7/sys/ia64/ia64/interrupt.c ============================================================================== --- stable/7/sys/ia64/ia64/interrupt.c Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/ia64/ia64/interrupt.c Tue May 19 19:45:36 2009 (r192406) @@ -385,10 +385,6 @@ ia64_dispatch_intr(void *frame, u_int ve { struct ia64_intr *i; struct intr_event *ie; /* our interrupt event */ -#ifndef INTR_FILTER - struct intr_handler *ih; - int error, thread, ret; -#endif /* * Find the interrupt thread for this vector. @@ -401,52 +397,14 @@ ia64_dispatch_intr(void *frame, u_int ve ie = i->event; KASSERT(ie != NULL, ("%s: interrupt without event", __func__)); -#ifdef INTR_FILTER if (intr_event_handle(ie, frame) != 0) { - ia64_intr_mask((void *)(uintptr_t)vector); - log(LOG_ERR, "stray irq%u\n", i->irq); - } -#else - /* - * As an optimization, if an event has no handlers, don't - * schedule it to run. - */ - if (TAILQ_EMPTY(&ie->ie_handlers)) - return; - - /* - * Execute all fast interrupt handlers directly without Giant. Note - * that this means that any fast interrupt handler must be MP safe. - */ - ret = 0; - thread = 0; - critical_enter(); - TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { - if (ih->ih_filter == NULL) { - thread = 1; - continue; - } - CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, - ih->ih_filter, ih->ih_argument, ih->ih_name); - ret = ih->ih_filter(ih->ih_argument); /* - * Wrapper handler special case: see - * i386/intr_machdep.c::intr_execute_handlers() + * XXX: The pre-INTR_FILTER code didn't mask stray + * interrupts. */ - if (!thread) { - if (ret == FILTER_SCHEDULE_THREAD) - thread = 1; - } - } - - if (thread) { ia64_intr_mask((void *)(uintptr_t)vector); - error = intr_event_schedule_thread(ie); - KASSERT(error == 0, ("%s: impossible stray", __func__)); - } else - ia64_intr_eoi((void *)(uintptr_t)vector); - critical_exit(); -#endif + log(LOG_ERR, "stray irq%u\n", i->irq); + } } #ifdef DDB Modified: stable/7/sys/kern/kern_intr.c ============================================================================== --- stable/7/sys/kern/kern_intr.c Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/kern/kern_intr.c Tue May 19 19:45:36 2009 (r192406) @@ -94,9 +94,14 @@ static TAILQ_HEAD(, intr_event) event_li static void intr_event_update(struct intr_event *ie); #ifdef INTR_FILTER +static int intr_event_schedule_thread(struct intr_event *ie, + struct intr_thread *ithd); +static int intr_filter_loop(struct intr_event *ie, + struct trapframe *frame, struct intr_thread **ithd); static struct intr_thread *ithread_create(const char *name, struct intr_handler *ih); #else +static int intr_event_schedule_thread(struct intr_event *ie); static struct intr_thread *ithread_create(const char *name); #endif static void ithread_destroy(struct intr_thread *ithread); @@ -240,8 +245,9 @@ intr_event_update(struct intr_event *ie) int intr_event_create(struct intr_event **event, void *source,int flags, - void (*disable)(void *), void (*enable)(void *), void (*eoi)(void *), - int (*assign_cpu)(void *, u_char), const char *fmt, ...) + void (*pre_ithread)(void *), void (*post_ithread)(void *), + void (*post_filter)(void *), int (*assign_cpu)(void *, u_char), + const char *fmt, ...) { struct intr_event *ie; va_list ap; @@ -251,9 +257,9 @@ intr_event_create(struct intr_event **ev return (EINVAL); ie = malloc(sizeof(struct intr_event), M_ITHREAD, M_WAITOK | M_ZERO); ie->ie_source = source; - ie->ie_disable = disable; - ie->ie_enable = enable; - ie->ie_eoi = eoi; + ie->ie_pre_ithread = pre_ithread; + ie->ie_post_ithread = post_ithread; + ie->ie_post_filter = post_filter; ie->ie_assign_cpu = assign_cpu; ie->ie_flags = flags; ie->ie_cpu = NOCPU; @@ -678,7 +684,7 @@ ok: return (0); } -int +static int intr_event_schedule_thread(struct intr_event *ie) { struct intr_entropy entropy; @@ -835,7 +841,7 @@ ok: return (0); } -int +static int intr_event_schedule_thread(struct intr_event *ie, struct intr_thread *it) { struct intr_entropy entropy; @@ -1078,8 +1084,8 @@ ithread_execute_handlers(struct proc *p, * Now that all the handlers have had a chance to run, reenable * the interrupt source. */ - if (ie->ie_enable != NULL) - ie->ie_enable(ie->ie_source); + if (ie->ie_post_ithread != NULL) + ie->ie_post_ithread(ie->ie_source); } #ifndef INTR_FILTER @@ -1166,6 +1172,90 @@ ithread_loop(void *arg) thread_unlock(td); } } + +/* + * Main interrupt handling body. + * + * Input: + * o ie: the event connected to this interrupt. + * o frame: some archs (i.e. i386) pass a frame to some. + * handlers as their main argument. + * Return value: + * o 0: everything ok. + * o EINVAL: stray interrupt. + */ +int +intr_event_handle(struct intr_event *ie, struct trapframe *frame) +{ + struct intr_handler *ih; + struct thread *td; + int error, ret, thread; + + td = curthread; + + /* An interrupt with no event or handlers is a stray interrupt. */ + if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers)) + return (EINVAL); + + /* + * Execute fast interrupt handlers directly. + * To support clock handlers, if a handler registers + * with a NULL argument, then we pass it a pointer to + * a trapframe as its argument. + */ + td->td_intr_nesting_level++; + thread = 0; + ret = 0; + critical_enter(); + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (ih->ih_filter == NULL) { + thread = 1; + continue; + } + CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, + ih->ih_filter, ih->ih_argument == NULL ? frame : + ih->ih_argument, ih->ih_name); + if (ih->ih_argument == NULL) + ret = ih->ih_filter(frame); + else + ret = ih->ih_filter(ih->ih_argument); + /* + * Wrapper handler special handling: + * + * in some particular cases (like pccard and pccbb), + * the _real_ device handler is wrapped in a couple of + * functions - a filter wrapper and an ithread wrapper. + * In this case (and just in this case), the filter wrapper + * could ask the system to schedule the ithread and mask + * the interrupt source if the wrapped handler is composed + * of just an ithread handler. + * + * TODO: write a generic wrapper to avoid people rolling + * their own + */ + if (!thread) { + if (ret == FILTER_SCHEDULE_THREAD) + thread = 1; + } + } + + if (thread) { + if (ie->ie_pre_ithread != NULL) + ie->ie_pre_ithread(ie->ie_source); + } else { + if (ie->ie_post_filter != NULL) + ie->ie_post_filter(ie->ie_source); + } + + /* Schedule the ithread if needed. */ + if (thread) { + error = intr_event_schedule_thread(ie); + KASSERT(error == 0, ("bad stray interrupt")); + } + critical_exit(); + td->td_intr_nesting_level--; + return (0); +} #else /* * This is the main code for interrupt threads. @@ -1281,7 +1371,7 @@ ithread_loop(void *arg) * scheduled. */ -int +static int intr_filter_loop(struct intr_event *ie, struct trapframe *frame, struct intr_thread **ithd) { @@ -1357,19 +1447,13 @@ intr_event_handle(struct intr_event *ie, td->td_intr_nesting_level++; thread = 0; critical_enter(); - thread = intr_filter_loop(ie, frame, &ithd); - - /* - * If the interrupt was fully served, send it an EOI but leave - * it unmasked. Otherwise, mask the source as well as sending - * it an EOI. - */ + thread = intr_filter_loop(ie, frame, &ithd); if (thread & FILTER_HANDLED) { - if (ie->ie_eoi != NULL) - ie->ie_eoi(ie->ie_source); + if (ie->ie_post_filter != NULL) + ie->ie_post_filter(ie->ie_source); } else { - if (ie->ie_disable != NULL) - ie->ie_disable(ie->ie_source); + if (ie->ie_pre_ithread != NULL) + ie->ie_pre_ithread(ie->ie_source); } critical_exit(); Modified: stable/7/sys/powerpc/powerpc/intr_machdep.c ============================================================================== --- stable/7/sys/powerpc/powerpc/intr_machdep.c Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/powerpc/powerpc/intr_machdep.c Tue May 19 19:45:36 2009 (r192406) @@ -228,10 +228,6 @@ powerpc_dispatch_intr(u_int vector, stru { struct powerpc_intr *i; struct intr_event *ie; -#ifndef INTR_FILTER - struct intr_handler *ih; - int error, sched, ret; -#endif i = powerpc_intrs[vector]; if (i == NULL) @@ -242,55 +238,15 @@ powerpc_dispatch_intr(u_int vector, stru ie = i->event; KASSERT(ie != NULL, ("%s: interrupt without an event", __func__)); -#ifdef INTR_FILTER if (intr_event_handle(ie, tf) != 0) { - PIC_MASK(pic, i->irq); - log(LOG_ERR, "stray irq%u\n", i->irq); - } -#else - if (TAILQ_EMPTY(&ie->ie_handlers)) goto stray; - - /* - * Execute all fast interrupt handlers directly without Giant. Note - * that this means that any fast interrupt handler must be MP safe. - */ - ret = 0; - sched = 0; - critical_enter(); - TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { - if (ih->ih_filter == NULL) { - sched = 1; - continue; - } - CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, - ih->ih_filter, ih->ih_argument, ih->ih_name); - ret = ih->ih_filter(ih->ih_argument); - /* - * Wrapper handler special case: see - * i386/intr_machdep.c::intr_execute_handlers() - */ - if (!sched) { - if (ret == FILTER_SCHEDULE_THREAD) - sched = 1; - } } - - if (sched) { - PIC_MASK(pic, i->irq); - error = intr_event_schedule_thread(ie); - KASSERT(error == 0, ("%s: impossible stray interrupt", - __func__)); - } else - PIC_EOI(pic, i->irq); - critical_exit(); -#endif return; stray: stray_count++; if (stray_count <= MAX_STRAY_LOG) { - printf("stray irq %d\n", i->irq); + printf("stray irq %d\n", i ? i->irq : -1); if (stray_count >= MAX_STRAY_LOG) { printf("got %d stray interrupts, not logging anymore\n", MAX_STRAY_LOG); Modified: stable/7/sys/sparc64/sparc64/intr_machdep.c ============================================================================== --- stable/7/sys/sparc64/sparc64/intr_machdep.c Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/sparc64/sparc64/intr_machdep.c Tue May 19 19:45:36 2009 (r192406) @@ -275,57 +275,9 @@ static void intr_execute_handlers(void *cookie) { struct intr_vector *iv; -#ifndef INTR_FILTER - struct intr_event *ie; - struct intr_handler *ih; - int error, thread, ret; -#endif iv = cookie; -#ifndef INTR_FILTER - ie = iv->iv_event; - if (iv->iv_ic == NULL || ie == NULL) { - intr_stray_vector(iv); - return; - } - - /* Execute fast interrupt handlers directly. */ - ret = 0; - thread = 0; - critical_enter(); - TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { - if (ih->ih_filter == NULL) { - thread = 1; - continue; - } - MPASS(ih->ih_filter != NULL && ih->ih_argument != NULL); - CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__, - ih->ih_filter, ih->ih_argument); - ret = ih->ih_filter(ih->ih_argument); - /* - * Wrapper handler special case: see - * i386/intr_machdep.c::intr_execute_handlers() - */ - if (!thread) { - if (ret == FILTER_SCHEDULE_THREAD) - thread = 1; - } - } - if (!thread) - iv->iv_ic->ic_clear(iv); - - /* Schedule a heavyweight interrupt process. */ - if (thread) - error = intr_event_schedule_thread(ie); - else if (TAILQ_EMPTY(&ie->ie_handlers)) - error = EINVAL; - else - error = 0; - critical_exit(); - if (error == EINVAL) -#else if (iv->iv_ic == NULL || intr_event_handle(iv->iv_event, NULL) != 0) -#endif intr_stray_vector(iv); } Modified: stable/7/sys/sun4v/sun4v/intr_machdep.c ============================================================================== --- stable/7/sys/sun4v/sun4v/intr_machdep.c Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/sun4v/sun4v/intr_machdep.c Tue May 19 19:45:36 2009 (r192406) @@ -101,12 +101,6 @@ struct intr_vector intr_vectors[IV_MAX]; uint16_t intr_countp[IV_MAX]; static u_long intr_stray_count[IV_MAX]; -struct ithread_vector_handler { - iv_func_t *ivh_handler; - void *ivh_arg; - u_int ivh_vec; -}; - static char *pil_names[] = { "stray", "low", /* PIL_LOW */ @@ -276,63 +270,23 @@ intr_init(void) } SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL); +static void +intr_enable(void *cookie) +{ + int vec; + + vec = (uintptr_t)cookie; + hv_intr_setstate(vec, HV_INTR_IDLE_STATE); +} static void intr_execute_handlers(void *cookie) { struct intr_vector *iv; - struct intr_event *ie; - struct intr_handler *ih; - int fast, thread, ret; iv = cookie; - ie = iv->iv_event; - if (ie == NULL) { - intr_stray_vector(iv); - return; - } - - ret = 0; - fast = thread = 0; - TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { - if (ih->ih_filter == NULL) { - thread = 1; - continue; - } - MPASS(ih->ih_filter != NULL && ih->ih_argument != NULL); - CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__, - ih->ih_filter, ih->ih_argument); - ret = ih->ih_filter(ih->ih_argument); - fast = 1; - /* - * Wrapper handler special case: see - * i386/intr_machdep.c::intr_execute_handlers() - */ - if (!thread) { - if (ret == FILTER_SCHEDULE_THREAD) - thread = 1; - } - } - - /* Schedule a heavyweight interrupt process. */ - if (thread) - intr_event_schedule_thread(ie); - else if (TAILQ_EMPTY(&ie->ie_handlers)) + if (intr_event_handle(iv->iv_event, NULL) != 0) intr_stray_vector(iv); - - if (fast) - hv_intr_setstate(iv->iv_vec, HV_INTR_IDLE_STATE); - -} - -static void -ithread_wrapper(void *arg) -{ - struct ithread_vector_handler *ivh = (struct ithread_vector_handler *)arg; - - ivh->ivh_handler(ivh->ivh_arg); - /* re-enable interrupt */ - hv_intr_setstate(ivh->ivh_vec, HV_INTR_IDLE_STATE); } int @@ -342,13 +296,8 @@ inthand_add(const char *name, int vec, d struct intr_vector *iv; struct intr_event *ie; /* descriptor for the IRQ */ struct intr_event *orphan; - struct ithread_vector_handler *ivh; int errcode, pil; - if (filt != NULL && handler != NULL) { - printf("both filt and handler set is not valid\n"); - return (EINVAL); - } /* * Work around a race where more than one CPU may be registering * handlers on the same IRQ at the same time. @@ -359,7 +308,7 @@ inthand_add(const char *name, int vec, d mtx_unlock_spin(&intr_table_lock); if (ie == NULL) { errcode = intr_event_create(&ie, (void *)(intptr_t)vec, 0, NULL, - NULL, "vec%d:", vec); + intr_enable, intr_enable, NULL, "vec%d:", vec); if (errcode) return (errcode); mtx_lock_spin(&intr_table_lock); @@ -374,26 +323,12 @@ inthand_add(const char *name, int vec, d } } - if (filt == NULL) { - ivh = (struct ithread_vector_handler *) - malloc(sizeof(struct ithread_vector_handler), M_DEVBUF, M_WAITOK); - ivh->ivh_handler = (driver_intr_t *)handler; - ivh->ivh_arg = arg; - ivh->ivh_vec = vec; - errcode = intr_event_add_handler(ie, name, NULL, ithread_wrapper, ivh, - intr_priority(flags), flags, cookiep); - } else { - ivh = NULL; - errcode = intr_event_add_handler(ie, name, filt, NULL, arg, - intr_priority(flags), flags, - cookiep); - } + errcode = intr_event_add_handler(ie, name, filt, handler, arg, + intr_priority(flags), flags, cookiep); - if (errcode) { - if (ivh) - free(ivh, M_DEVBUF); + if (errcode) return (errcode); - } + pil = (filt != NULL) ? PIL_FAST : PIL_ITHREAD; intr_setup(pil, intr_fast, vec, intr_execute_handlers, iv); Modified: stable/7/sys/sys/interrupt.h ============================================================================== --- stable/7/sys/sys/interrupt.h Tue May 19 19:27:07 2009 (r192405) +++ stable/7/sys/sys/interrupt.h Tue May 19 19:45:36 2009 (r192406) @@ -63,6 +63,33 @@ struct intr_handler { /* * Describe an interrupt event. An event holds a list of handlers. + * The 'pre_ithread', 'post_ithread', 'post_filter', and 'assign_cpu' + * hooks are used to invoke MD code for certain operations. + * + * The 'pre_ithread' hook is called when an interrupt thread for + * handlers without filters is scheduled. It is responsible for + * ensuring that 1) the system won't be swamped with an interrupt + * storm from the associated source while the ithread runs and 2) the + * current CPU is able to receive interrupts from other interrupt + * sources. The first is usually accomplished by disabling + * level-triggered interrupts until the ithread completes. The second + * is accomplished on some platforms by acknowledging the interrupt + * via an EOI. + * + * The 'post_ithread' hook is invoked when an ithread finishes. It is + * responsible for ensuring that the associated interrupt source will + * trigger an interrupt when it is asserted in the future. Usually + * this is implemented by enabling a level-triggered interrupt that + * was previously disabled via the 'pre_ithread' hook. + * + * The 'post_filter' hook is invoked when a filter handles an + * interrupt. It is responsible for ensuring that the current CPU is + * able to receive interrupts again. On some platforms this is done + * by acknowledging the interrupts via an EOI. + * + * 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. */ struct intr_event { TAILQ_ENTRY(intr_event) ie_list; @@ -72,9 +99,9 @@ struct intr_event { struct mtx ie_lock; void *ie_source; /* Cookie used by MD code. */ struct intr_thread *ie_thread; /* Thread we are connected to. */ - void (*ie_disable)(void *); - void (*ie_enable)(void *); - void (*ie_eoi)(void *); + void (*ie_pre_ithread)(void *); + void (*ie_post_ithread)(void *); + void (*ie_post_filter)(void *); int (*ie_assign_cpu)(void *, u_char); int ie_flags; int ie_count; /* Loop counter. */ @@ -118,29 +145,19 @@ extern char intrnames[]; /* string tabl #ifdef DDB void db_dump_intr_event(struct intr_event *ie, int handlers); #endif -#ifdef INTR_FILTER -int intr_filter_loop(struct intr_event *ie, struct trapframe *frame, - struct intr_thread **ithd); -int intr_event_handle(struct intr_event *ie, struct trapframe *frame); -#endif u_char intr_priority(enum intr_type flags); int intr_event_add_handler(struct intr_event *ie, const char *name, driver_filter_t filter, driver_intr_t handler, void *arg, u_char pri, enum intr_type flags, void **cookiep); int intr_event_bind(struct intr_event *ie, u_char cpu); int intr_event_create(struct intr_event **event, void *source, - int flags, void (*disable)(void *), void (*enable)(void *), - void (*eoi)(void *), int (*assign_cpu)(void *, u_char), - const char *fmt, ...) + int flags, void (*pre_ithread)(void *), + void (*post_ithread)(void *), void (*post_filter)(void *), + int (*assign_cpu)(void *, u_char), const char *fmt, ...) __printflike(8, 9); int intr_event_destroy(struct intr_event *ie); +int intr_event_handle(struct intr_event *ie, struct trapframe *frame); int intr_event_remove_handler(void *cookie); -#ifndef INTR_FILTER -int intr_event_schedule_thread(struct intr_event *ie); -#else -int intr_event_schedule_thread(struct intr_event *ie, - struct intr_thread *ithd); -#endif void *intr_handler_source(void *cookie); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905191945.n4JJjb0Q008111>