--- //depot/projects/smpng/sys/amd64/amd64/intr_machdep.c 2008/03/18 12:54:14 +++ //depot/user/jhb/intr/amd64/amd64/intr_machdep.c 2008/03/18 15:16:36 @@ -85,9 +85,6 @@ 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,12 +235,11 @@ isrc->is_pic->pic_disable_source(isrc, PIC_EOI); } -#ifdef INTR_FILTER void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) { + struct intr_event *ie; struct thread *td; - struct intr_event *ie; int vector; td = curthread; @@ -267,64 +264,11 @@ 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; - - 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; - - /* - * 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 +277,8 @@ 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) --- //depot/projects/smpng/sys/arm/arm/intr.c 2008/03/18 12:54:14 +++ //depot/user/jhb/intr/arm/arm/intr.c 2008/03/18 15:16:36 @@ -72,7 +72,7 @@ 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 @@ { 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--; } --- //depot/projects/smpng/sys/i386/i386/intr_machdep.c 2008/03/18 12:54:14 +++ //depot/user/jhb/intr/i386/i386/intr_machdep.c 2008/03/18 15:16:36 @@ -76,9 +76,6 @@ 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,12 +226,11 @@ isrc->is_pic->pic_disable_source(isrc, PIC_EOI); } -#ifdef INTR_FILTER void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) { + struct intr_event *ie; struct thread *td; - struct intr_event *ie; int vector; td = curthread; @@ -258,64 +255,11 @@ 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; - - 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; - - /* - * 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,82 +268,20 @@ 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) { struct pic *pic; sx_xlock(&intr_table_lock); STAILQ_FOREACH(pic, &pics, pics) { if (pic->pic_resume != NULL) pic->pic_resume(pic); } sx_xunlock(&intr_table_lock); } void --- //depot/projects/smpng/sys/ia64/ia64/interrupt.c 2008/03/18 12:54:14 +++ //depot/user/jhb/intr/ia64/ia64/interrupt.c 2008/03/18 15:16:36 @@ -385,10 +385,6 @@ { 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 @@ ie = i->event; KASSERT(ie != NULL, ("%s: interrupt without event", __func__)); -#ifdef INTR_FILTER if (intr_event_handle(ie, frame) != 0) { + /* + * XXX: The pre-INTR_FILTER code didn't mask stray + * interrupts. + */ 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() - */ - 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 } #ifdef DDB --- //depot/projects/smpng/sys/kern/kern_intr.c 2008/03/18 12:54:14 +++ //depot/user/jhb/intr/kern/kern_intr.c 2008/03/24 22:50:26 @@ -95,9 +95,14 @@ 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 @@ 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 @@ 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; @@ -676,7 +682,7 @@ return (0); } -int +static int intr_event_schedule_thread(struct intr_event *ie) { struct intr_entropy entropy; @@ -833,7 +839,7 @@ return (0); } -int +static int intr_event_schedule_thread(struct intr_event *ie, struct intr_thread *it) { struct intr_entropy entropy; @@ -1075,8 +1081,8 @@ * 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 @@ -1163,6 +1169,95 @@ 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 the interrupt was fully served, send it an EOI but leave + * it unmasked. Otherwise, mask the source as well as sending + * it an EOI. + */ + 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. @@ -1278,7 +1373,7 @@ * scheduled. */ -int +static int intr_filter_loop(struct intr_event *ie, struct trapframe *frame, struct intr_thread **ithd) { @@ -1362,11 +1457,11 @@ * it an EOI. */ 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(); --- //depot/projects/smpng/sys/powerpc/powerpc/intr_machdep.c 2008/03/18 12:54:14 +++ //depot/user/jhb/intr/powerpc/powerpc/intr_machdep.c 2008/03/18 15:16:36 @@ -277,10 +277,6 @@ { 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) @@ -291,55 +287,15 @@ 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); --- //depot/projects/smpng/sys/sparc64/sparc64/intr_machdep.c 2008/03/18 12:54:14 +++ //depot/user/jhb/intr/sparc64/sparc64/intr_machdep.c 2008/03/19 21:00:10 @@ -248,57 +248,9 @@ 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) - intr_enable_eoi(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 (intr_event_handle(iv->iv_event, NULL) != 0) -#endif + if (iv->iv_ic == NULL || intr_event_handle(iv->iv_event, NULL) != 0) intr_stray_vector(iv); } @@ -329,8 +281,8 @@ * CPU as long as the source of a level sensitive interrupt is * not cleared. */ - error = intr_event_create(&ie, iv, 0, ic->ic_disable, intr_enable_eoi, - ic->ic_eoi, NULL, "vec%d:", vec); + error = intr_event_create(&ie, iv, 0, NULL, intr_enable_eoi, + intr_enable_eoi, NULL, "vec%d:", vec); if (error != 0) return (error); mtx_lock_spin(&intr_table_lock); --- //depot/projects/smpng/sys/sun4v/sun4v/intr_machdep.c 2008/03/19 21:22:58 +++ //depot/user/jhb/intr/sun4v/sun4v/intr_machdep.c 2008/03/19 21:55:15 @@ -101,12 +101,6 @@ 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,65 +270,25 @@ } 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 inthand_add(const char *name, int vec, driver_filter_t *filt, void (*handler)(void *), void *arg, int flags, void **cookiep) @@ -342,9 +296,9 @@ struct intr_vector *iv; struct intr_event *ie; /* descriptor for the IRQ */ struct intr_event *orphan; - struct ithread_vector_handler *ivh; int errcode, pil; + /* XXX: It is with INTR_FILTER */ if (filt != NULL && handler != NULL) { printf("both filt and handler set is not valid\n"); return (EINVAL); @@ -359,7 +313,7 @@ mtx_unlock_spin(&intr_table_lock); if (ie == NULL) { errcode = intr_event_create(&ie, (void *)(intptr_t)vec, 0, NULL, - NULL, 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 +328,12 @@ } } - 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); --- //depot/projects/smpng/sys/sys/interrupt.h 2008/03/18 12:54:14 +++ //depot/user/jhb/intr/sys/interrupt.h 2008/03/24 22:50:26 @@ -63,6 +63,33 @@ /* * 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 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 @@ #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); int swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler, void *arg, int pri, enum intr_type flags,