diff options
author | piso <piso@FreeBSD.org> | 2007-05-06 17:02:50 +0000 |
---|---|---|
committer | piso <piso@FreeBSD.org> | 2007-05-06 17:02:50 +0000 |
commit | 25c9d95cb5947382643fdb02dee7a6b99bb639a4 (patch) | |
tree | e66c2b004bab077c7727881fe5ffb706d78b575c /sys/i386 | |
parent | 5dbec163341730f1769c5939a5e146d429090527 (diff) | |
download | FreeBSD-src-25c9d95cb5947382643fdb02dee7a6b99bb639a4.zip FreeBSD-src-25c9d95cb5947382643fdb02dee7a6b99bb639a4.tar.gz |
Bring in the reminaing bits to make interrupt filtering work:
o push much of the i386 and amd64 MD interrupt handling code
(intr_machdep.c::intr_execute_handlers()) into MI code
(kern_intr.c::ithread_loop())
o move filter handling to kern_intr.c::intr_filter_loop()
o factor out the code necessary to mask and ack an interrupt event
(intr_machdep.c::intr_eoi_src() and intr_machdep.c::intr_disab_eoi_src()),
and make them part of 'struct intr_event', passing them as arguments to
kern_intr.c::intr_event_create().
o spawn a private ithread per handler (struct intr_handler::ih_thread)
with filter and ithread functions.
Approved by: re (implicit?)
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/i386/intr_machdep.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/sys/i386/i386/intr_machdep.c b/sys/i386/i386/intr_machdep.c index ee34570..9760070 100644 --- a/sys/i386/i386/intr_machdep.c +++ b/sys/i386/i386/intr_machdep.c @@ -65,6 +65,12 @@ static struct intsrc *interrupt_sources[NUM_IO_INTS]; static struct mtx intr_table_lock; static STAILQ_HEAD(, pic) pics; +#ifdef INTR_FILTER +static void intr_eoi_src(void *arg); +static void intr_disab_eoi_src(void *arg); +static void intr_event_stray(void *cookie); +#endif + #ifdef SMP static int assign_cpu; @@ -125,8 +131,14 @@ intr_register_source(struct intsrc *isrc) vector = isrc->is_pic->pic_vector(isrc); if (interrupt_sources[vector] != NULL) return (EEXIST); +#ifdef INTR_FILTER + error = intr_event_create(&isrc->is_event, isrc, 0, + (mask_fn)isrc->is_pic->pic_enable_source, + intr_eoi_src, intr_disab_eoi_src, "irq%d:", vector); +#else error = intr_event_create(&isrc->is_event, isrc, 0, (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector); +#endif if (error) return (error); mtx_lock_spin(&intr_table_lock); @@ -160,7 +172,7 @@ intr_add_handler(const char *name, int vector, driver_filter_t filter, if (isrc == NULL) return (EINVAL); error = intr_event_add_handler(isrc->is_event, name, filter, handler, - arg, intr_priority(flags), flags, cookiep); + arg, intr_priority(flags), flags, cookiep); if (error == 0) { intrcnt_updatename(isrc); mtx_lock_spin(&intr_table_lock); @@ -203,6 +215,77 @@ intr_config_intr(int vector, enum intr_trigger trig, enum intr_polarity pol) return (isrc->is_pic->pic_config_intr(isrc, trig, pol)); } +#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_LAZY_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)); +} + +static void +intr_eoi_src(void *arg) +{ + struct intsrc *isrc; + + isrc = arg; + isrc->is_pic->pic_eoi_source(isrc); +} + +static void +intr_disab_eoi_src(void *arg) +{ + struct intsrc *isrc; + + isrc = arg; + isrc->is_pic->pic_disable_source(isrc, PIC_EOI); +} +#else void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) { @@ -289,6 +372,7 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) } td->td_intr_nesting_level--; } +#endif void intr_resume(void) |