diff --git a/sys/x86/include/intr_machdep.h b/sys/x86/include/intr_machdep.h --- a/sys/x86/include/intr_machdep.h +++ b/sys/x86/include/intr_machdep.h @@ -78,7 +78,7 @@ struct pic { void (*pic_register_sources)(struct pic *); void (*pic_enable_source)(struct intsrc *); - void (*pic_disable_source)(struct intsrc *, int); + void (*pic_disable_source)(struct intsrc *); void (*pic_eoi_source)(struct intsrc *); void (*pic_enable_intr)(struct intsrc *); void (*pic_disable_intr)(struct intsrc *); @@ -92,12 +92,6 @@ TAILQ_ENTRY(pic) pics; }; -/* Flags for pic_disable_source() */ -enum { - PIC_EOI, - PIC_NO_EOI, -}; - /* * An interrupt source. The upper-layer code uses the PIC methods to * control a given source. The lower-layer PIC drivers can store additional diff --git a/sys/x86/isa/atpic.c b/sys/x86/isa/atpic.c --- a/sys/x86/isa/atpic.c +++ b/sys/x86/isa/atpic.c @@ -98,7 +98,7 @@ .pic_enable_source = atpic_enable_source, \ .pic_disable_source = atpic_disable_source, \ .pic_eoi_source = (eoi), \ - .pic_enable_intr = atpic_enable_intr, \ + .pic_enable_intr = atpic_enable_source, \ .pic_disable_intr = atpic_disable_intr, \ .pic_source_pending = atpic_source_pending, \ .pic_resume = atpic_resume, \ @@ -138,10 +138,9 @@ static void atpic_register_sources(struct pic *pic); static void atpic_enable_source(struct intsrc *isrc); -static void atpic_disable_source(struct intsrc *isrc, int eoi); +static void atpic_disable_source(struct intsrc *isrc); static void atpic_eoi_master(struct intsrc *isrc); static void atpic_eoi_slave(struct intsrc *isrc); -static void atpic_enable_intr(struct intsrc *isrc); static void atpic_disable_intr(struct intsrc *isrc); static int atpic_vector(struct intsrc *isrc); static void atpic_resume(struct pic *pic, bool suspend_cancelled); @@ -257,7 +256,7 @@ } static void -atpic_disable_source(struct intsrc *isrc, int eoi) +atpic_disable_source(struct intsrc *isrc) { struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc; struct atpic *ap = (struct atpic *)isrc->is_pic; @@ -273,12 +272,10 @@ * a function pointer. All of the referenced variables should * still be hot in the cache. */ - if (eoi == PIC_EOI) { - if (isrc->is_pic == &atpics[MASTER].at_pic) - _atpic_eoi_master(isrc); - else - _atpic_eoi_slave(isrc); - } + if (isrc->is_pic == &atpics[MASTER].at_pic) + _atpic_eoi_master(isrc); + else + _atpic_eoi_slave(isrc); spinlock_exit(); } @@ -303,14 +300,18 @@ #endif } -static void -atpic_enable_intr(struct intsrc *isrc) -{ -} - static void atpic_disable_intr(struct intsrc *isrc) { + struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc; + struct atpic *ap = (struct atpic *)isrc->is_pic; + + spinlock_enter(); + if (ai->at_trigger != INTR_TRIGGER_EDGE) { + ap->at_imen |= IMEN_MASK(ai); + outb(ap->at_ioaddr + ICU_IMR_OFFSET, ap->at_imen); + } + spinlock_exit(); } static int diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c --- a/sys/x86/x86/intr_machdep.c +++ b/sys/x86/x86/intr_machdep.c @@ -269,7 +269,6 @@ if (isrc->is_handlers == 1) { isrc->is_domain = domain; isrc->is_pic->pic_enable_intr(isrc); - isrc->is_pic->pic_enable_source(isrc); } sx_xunlock(&intrsrc_lock); } @@ -287,10 +286,8 @@ if (error == 0) { sx_xlock(&intrsrc_lock); isrc->is_handlers--; - if (isrc->is_handlers == 0) { - isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI); + if (isrc->is_handlers == 0) isrc->is_pic->pic_disable_intr(isrc); - } intrcnt_updatename(isrc); sx_xunlock(&intrsrc_lock); } @@ -311,7 +308,7 @@ struct intsrc *isrc; isrc = arg; - isrc->is_pic->pic_disable_source(isrc, PIC_EOI); + isrc->is_pic->pic_disable_source(isrc); } void @@ -344,7 +341,7 @@ * stray count, and log the condition. */ if (intr_event_handle(ie, frame) != 0) { - isrc->is_pic->pic_disable_source(isrc, PIC_EOI); + isrc->is_pic->pic_disable_source(isrc); (*isrc->is_straycount)++; if (*isrc->is_straycount < INTR_STRAY_LOG_MAX) log(LOG_ERR, "stray irq%d\n", vector); diff --git a/sys/x86/x86/io_apic.c b/sys/x86/x86/io_apic.c --- a/sys/x86/x86/io_apic.c +++ b/sys/x86/x86/io_apic.c @@ -113,7 +113,7 @@ static void ioapic_print_irq(struct ioapic_intsrc *intpin); static void ioapic_register_sources(struct pic *pic); static void ioapic_enable_source(struct intsrc *isrc); -static void ioapic_disable_source(struct intsrc *isrc, int eoi); +static void ioapic_disable_source(struct intsrc *isrc); static void ioapic_eoi_source(struct intsrc *isrc); static void ioapic_enable_intr(struct intsrc *isrc); static void ioapic_disable_intr(struct intsrc *isrc); @@ -275,7 +275,7 @@ } static void -ioapic_disable_source(struct intsrc *isrc, int eoi) +ioapic_disable_source(struct intsrc *isrc) { struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; struct ioapic *io = (struct ioapic *)isrc->is_pic; @@ -289,8 +289,7 @@ intpin->io_masked = 1; } - if (eoi == PIC_EOI) - _ioapic_eoi_source(isrc, 1); + _ioapic_eoi_source(isrc, 1); mtx_unlock_spin(&icu_lock); } @@ -505,14 +504,27 @@ panic("Couldn't find an APIC vector for IRQ %d", intpin->io_irq); apic_enable_vector(intpin->io_cpu, intpin->io_vector); + + ioapic_enable_source(isrc); } static void ioapic_disable_intr(struct intsrc *isrc) { struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; + struct ioapic *io = (struct ioapic *)isrc->is_pic; + uint32_t flags; u_int vector; + mtx_lock_spin(&icu_lock); + if (!intpin->io_masked && !intpin->io_edgetrigger) { + flags = intpin->io_lowreg | IOART_INTMSET; + ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), + flags); + intpin->io_masked = 1; + } + mtx_unlock_spin(&icu_lock); + if (intpin->io_vector != 0) { /* Mask this interrupt pin and free its APIC vector. */ vector = intpin->io_vector; diff --git a/sys/x86/x86/msi.c b/sys/x86/x86/msi.c --- a/sys/x86/x86/msi.c +++ b/sys/x86/x86/msi.c @@ -127,7 +127,6 @@ static void msi_create_source(void); static void msi_enable_source(struct intsrc *isrc); -static void msi_disable_source(struct intsrc *isrc, int eoi); static void msi_eoi_source(struct intsrc *isrc); static void msi_enable_intr(struct intsrc *isrc); static void msi_disable_intr(struct intsrc *isrc); @@ -138,7 +137,7 @@ struct pic msi_pic = { .pic_enable_source = msi_enable_source, - .pic_disable_source = msi_disable_source, + .pic_disable_source = msi_eoi_source, .pic_eoi_source = msi_eoi_source, .pic_enable_intr = msi_enable_intr, .pic_disable_intr = msi_disable_intr, @@ -183,14 +182,6 @@ { } -static void -msi_disable_source(struct intsrc *isrc, int eoi) -{ - - if (eoi == PIC_EOI) - lapic_eoi(); -} - static void msi_eoi_source(struct intsrc *isrc) { diff --git a/sys/x86/xen/xen_arch_intr.c b/sys/x86/xen/xen_arch_intr.c --- a/sys/x86/xen/xen_arch_intr.c +++ b/sys/x86/xen/xen_arch_intr.c @@ -158,7 +158,7 @@ * \param isrc The interrupt source to EOI. */ static void -xen_intr_pic_disable_source(struct intsrc *isrc, int eoi) +xen_intr_pic_disable_source(struct intsrc *isrc) { _Static_assert(offsetof(struct xenisrc, xi_arch.intsrc) == 0, @@ -188,6 +188,7 @@ _Static_assert(offsetof(struct xenisrc, xi_arch.intsrc) == 0, "xi_arch MUST be at top of xenisrc for x86"); + xen_intr_disable_source((struct xenisrc *)isrc); xen_intr_disable_intr((struct xenisrc *)isrc); }