diff options
| -rw-r--r-- | sys/amd64/amd64/intr_machdep.c | 65 | ||||
| -rw-r--r-- | sys/amd64/amd64/io_apic.c | 22 | ||||
| -rw-r--r-- | sys/amd64/amd64/local_apic.c | 12 | ||||
| -rw-r--r-- | sys/amd64/amd64/msi.c | 128 | ||||
| -rw-r--r-- | sys/amd64/amd64/nexus.c | 26 | ||||
| -rw-r--r-- | sys/amd64/include/apicvar.h | 1 | ||||
| -rw-r--r-- | sys/amd64/include/intr_machdep.h | 9 | ||||
| -rw-r--r-- | sys/amd64/isa/atpic.c | 14 | ||||
| -rw-r--r-- | sys/i386/i386/intr_machdep.c | 65 | ||||
| -rw-r--r-- | sys/i386/i386/io_apic.c | 22 | ||||
| -rw-r--r-- | sys/i386/i386/local_apic.c | 13 | ||||
| -rw-r--r-- | sys/i386/i386/msi.c | 128 | ||||
| -rw-r--r-- | sys/i386/i386/nexus.c | 26 | ||||
| -rw-r--r-- | sys/i386/include/apicvar.h | 1 | ||||
| -rw-r--r-- | sys/i386/include/intr_machdep.h | 9 | ||||
| -rw-r--r-- | sys/i386/isa/atpic.c | 14 |
16 files changed, 339 insertions, 216 deletions
diff --git a/sys/amd64/amd64/intr_machdep.c b/sys/amd64/amd64/intr_machdep.c index 12191db74825..2864868d731d 100644 --- a/sys/amd64/amd64/intr_machdep.c +++ b/sys/amd64/amd64/intr_machdep.c @@ -43,13 +43,14 @@ #include <sys/param.h> #include <sys/bus.h> #include <sys/interrupt.h> -#include <sys/lock.h> #include <sys/ktr.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/mutex.h> #include <sys/proc.h> #include <sys/syslog.h> #include <sys/systm.h> +#include <sys/sx.h> #include <machine/clock.h> #include <machine/intr_machdep.h> #include <machine/smp.h> @@ -71,7 +72,8 @@ typedef void (*mask_fn)(void *); static int intrcnt_index; static struct intsrc *interrupt_sources[NUM_IO_INTS]; -static struct mtx intr_table_lock; +static struct sx intr_table_lock; +static struct mtx intrcnt_lock; static STAILQ_HEAD(, pic) pics; #ifdef INTR_FILTER @@ -115,14 +117,14 @@ intr_register_pic(struct pic *pic) { int error; - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); if (intr_pic_registered(pic)) error = EBUSY; else { STAILQ_INSERT_TAIL(&pics, pic, pics); error = 0; } - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); return (error); } @@ -150,16 +152,16 @@ intr_register_source(struct intsrc *isrc) #endif if (error) return (error); - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); if (interrupt_sources[vector] != NULL) { - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); intr_event_destroy(isrc->is_event); return (EEXIST); } intrcnt_register(isrc); interrupt_sources[vector] = isrc; - isrc->is_enabled = 0; - mtx_unlock_spin(&intr_table_lock); + isrc->is_handlers = 0; + sx_xunlock(&intr_table_lock); return (0); } @@ -183,19 +185,18 @@ intr_add_handler(const char *name, int vector, driver_filter_t filter, error = intr_event_add_handler(isrc->is_event, name, filter, handler, arg, intr_priority(flags), flags, cookiep); if (error == 0) { + sx_xlock(&intr_table_lock); intrcnt_updatename(isrc); - mtx_lock_spin(&intr_table_lock); - if (!isrc->is_enabled) { - isrc->is_enabled = 1; + isrc->is_handlers++; + if (isrc->is_handlers == 1) { #ifdef SMP if (assign_cpu) intr_assign_next_cpu(isrc); #endif - mtx_unlock_spin(&intr_table_lock); isrc->is_pic->pic_enable_intr(isrc); - } else - mtx_unlock_spin(&intr_table_lock); - isrc->is_pic->pic_enable_source(isrc); + isrc->is_pic->pic_enable_source(isrc); + } + sx_xunlock(&intr_table_lock); } return (error); } @@ -208,8 +209,16 @@ intr_remove_handler(void *cookie) isrc = intr_handler_source(cookie); error = intr_event_remove_handler(cookie); - if (error == 0) + if (error == 0) { + sx_xlock(&intr_table_lock); + isrc->is_handlers--; + if (isrc->is_handlers == 0) { + isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI); + isrc->is_pic->pic_disable_intr(isrc); + } intrcnt_updatename(isrc); + sx_xunlock(&intr_table_lock); + } return (error); } @@ -391,12 +400,12 @@ intr_resume(void) #ifndef DEV_ATPIC atpic_reset(); #endif - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); STAILQ_FOREACH(pic, &pics, pics) { if (pic->pic_resume != NULL) pic->pic_resume(pic); } - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); } void @@ -404,12 +413,12 @@ intr_suspend(void) { struct pic *pic; - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); STAILQ_FOREACH(pic, &pics, pics) { if (pic->pic_suspend != NULL) pic->pic_suspend(pic); } - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); } static void @@ -432,8 +441,8 @@ intrcnt_register(struct intsrc *is) { char straystr[MAXCOMLEN + 1]; - /* mtx_assert(&intr_table_lock, MA_OWNED); */ KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__)); + mtx_lock_spin(&intrcnt_lock); is->is_index = intrcnt_index; intrcnt_index += 2; snprintf(straystr, MAXCOMLEN + 1, "stray irq%d", @@ -442,17 +451,18 @@ intrcnt_register(struct intsrc *is) is->is_count = &intrcnt[is->is_index]; intrcnt_setname(straystr, is->is_index + 1); is->is_straycount = &intrcnt[is->is_index + 1]; + mtx_unlock_spin(&intrcnt_lock); } void intrcnt_add(const char *name, u_long **countp) { - mtx_lock_spin(&intr_table_lock); + mtx_lock_spin(&intrcnt_lock); *countp = &intrcnt[intrcnt_index]; intrcnt_setname(name, intrcnt_index); intrcnt_index++; - mtx_unlock_spin(&intr_table_lock); + mtx_unlock_spin(&intrcnt_lock); } static void @@ -462,7 +472,8 @@ intr_init(void *dummy __unused) intrcnt_setname("???", 0); intrcnt_index = 1; STAILQ_INIT(&pics); - mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN); + sx_init(&intr_table_lock, "intr sources"); + mtx_init(&intrcnt_lock, "intrcnt", NULL, MTX_SPIN); } SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL) @@ -570,14 +581,14 @@ intr_shuffle_irqs(void *arg __unused) return; /* Round-robin assign a CPU to each enabled source. */ - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); assign_cpu = 1; for (i = 0; i < NUM_IO_INTS; i++) { isrc = interrupt_sources[i]; - if (isrc != NULL && isrc->is_enabled) + if (isrc != NULL && isrc->is_handlers > 0) intr_assign_next_cpu(isrc); } - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); } SYSINIT(intr_shuffle_irqs, SI_SUB_SMP, SI_ORDER_SECOND, intr_shuffle_irqs, NULL) #endif diff --git a/sys/amd64/amd64/io_apic.c b/sys/amd64/amd64/io_apic.c index 88b8d4c8fbf5..05b93ce656ba 100644 --- a/sys/amd64/amd64/io_apic.c +++ b/sys/amd64/amd64/io_apic.c @@ -114,6 +114,7 @@ static void ioapic_enable_source(struct intsrc *isrc); static void ioapic_disable_source(struct intsrc *isrc, int eoi); static void ioapic_eoi_source(struct intsrc *isrc); static void ioapic_enable_intr(struct intsrc *isrc); +static void ioapic_disable_intr(struct intsrc *isrc); static int ioapic_vector(struct intsrc *isrc); static int ioapic_source_pending(struct intsrc *isrc); static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig, @@ -125,8 +126,8 @@ static void ioapic_program_intpin(struct ioapic_intsrc *intpin); static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list); struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source, ioapic_eoi_source, ioapic_enable_intr, - ioapic_vector, ioapic_source_pending, - NULL, ioapic_resume, + ioapic_disable_intr, ioapic_vector, + ioapic_source_pending, NULL, ioapic_resume, ioapic_config_intr, ioapic_assign_cpu }; static int next_ioapic_base; @@ -359,6 +360,23 @@ ioapic_enable_intr(struct intsrc *isrc) } } +static void +ioapic_disable_intr(struct intsrc *isrc) +{ + struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; + u_int vector; + + if (intpin->io_vector != 0) { + /* Mask this interrupt pin and free its APIC vector. */ + vector = intpin->io_vector; + apic_disable_vector(vector); + intpin->io_masked = 1; + intpin->io_vector = 0; + ioapic_program_intpin(intpin); + apic_free_vector(vector, intpin->io_irq); + } +} + static int ioapic_vector(struct intsrc *isrc) { diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c index df038f8aeaa1..fa46c9597609 100644 --- a/sys/amd64/amd64/local_apic.c +++ b/sys/amd64/amd64/local_apic.c @@ -147,6 +147,8 @@ static u_int32_t lapic_timer_divisors[] = { APIC_TDCR_32, APIC_TDCR_64, APIC_TDCR_128 }; +extern inthand_t IDTVEC(rsvd); + volatile lapic_t *lapic; vm_paddr_t lapic_paddr; static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz; @@ -837,6 +839,16 @@ apic_enable_vector(u_int vector) setidt(vector, ioint_handlers[vector / 32], SDT_SYSIGT, SEL_KPL, 0); } +void +apic_disable_vector(u_int vector) +{ + + KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry")); + KASSERT(ioint_handlers[vector / 32] != NULL, + ("No ISR handler for vector %u", vector)); + setidt(vector, &IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0); +} + /* Release an APIC vector when it's no longer in use. */ void apic_free_vector(u_int vector, u_int irq) diff --git a/sys/amd64/amd64/msi.c b/sys/amd64/amd64/msi.c index 3bb184c274f5..6440852375c2 100644 --- a/sys/amd64/amd64/msi.c +++ b/sys/amd64/amd64/msi.c @@ -112,11 +112,12 @@ struct msi_intsrc { u_int msi_count:8; /* Messages in this group. (g) */ }; -static struct msi_intsrc *msi_create_source(u_int irq); +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); static int msi_vector(struct intsrc *isrc); static int msi_source_pending(struct intsrc *isrc); static int msi_config_intr(struct intsrc *isrc, enum intr_trigger trig, @@ -124,11 +125,13 @@ static int msi_config_intr(struct intsrc *isrc, enum intr_trigger trig, static void msi_assign_cpu(struct intsrc *isrc, u_int apic_id); struct pic msi_pic = { msi_enable_source, msi_disable_source, msi_eoi_source, - msi_enable_intr, msi_vector, msi_source_pending, - NULL, NULL, msi_config_intr, msi_assign_cpu }; + msi_enable_intr, msi_disable_intr, msi_vector, + msi_source_pending, NULL, NULL, msi_config_intr, + msi_assign_cpu }; static int msi_enabled; -static struct sx msi_sx; +static int msi_last_irq; +static struct mtx msi_lock; static void msi_enable_source(struct intsrc *isrc) @@ -158,6 +161,14 @@ msi_enable_intr(struct intsrc *isrc) apic_enable_vector(msi->msi_vector); } +static void +msi_disable_intr(struct intsrc *isrc) +{ + struct msi_intsrc *msi = (struct msi_intsrc *)isrc; + + apic_disable_vector(msi->msi_vector); +} + static int msi_vector(struct intsrc *isrc) { @@ -191,8 +202,7 @@ msi_assign_cpu(struct intsrc *isrc, u_int apic_id) printf("msi: Assigning %s IRQ %d to local APIC %u\n", msi->msi_msix ? "MSI-X" : "MSI", msi->msi_irq, msi->msi_cpu); - if (isrc->is_enabled) - pci_remap_msi_irq(msi->msi_dev, msi->msi_irq); + pci_remap_msi_irq(msi->msi_dev, msi->msi_irq); } void @@ -206,19 +216,29 @@ msi_init(void) msi_enabled = 1; intr_register_pic(&msi_pic); - sx_init(&msi_sx, "msi"); + mtx_init(&msi_lock, "msi", NULL, MTX_DEF); } -struct msi_intsrc * -msi_create_source(u_int irq) +void +msi_create_source(void) { struct msi_intsrc *msi; + u_int irq; + + mtx_lock(&msi_lock); + if (msi_last_irq >= NUM_MSI_INTS) { + mtx_unlock(&msi_lock); + return; + } + irq = msi_last_irq + FIRST_MSI_INT; + msi_last_irq++; + mtx_unlock(&msi_lock); - msi = malloc(sizeof(struct msi_intsrc), M_MSI, M_WAITOK | M_ZERO); + msi = malloc(sizeof(struct msi_intsrc), M_MSI, M_WAITOK | M_ZERO); msi->msi_intsrc.is_pic = &msi_pic; msi->msi_irq = irq; intr_register_source(&msi->msi_intsrc); - return (msi); + nexus_add_irq(irq); } /* @@ -228,18 +248,16 @@ msi_create_source(u_int irq) * and *newcount being the number of new IRQ values added. */ int -msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, - int *newcount) +msi_alloc(device_t dev, int count, int maxcount, int *irqs) { struct msi_intsrc *msi, *fsrc; - int cnt, i, j, vector; + int cnt, i, vector; - *newirq = 0; - *newcount = 0; if (!msi_enabled) return (ENXIO); - sx_xlock(&msi_sx); +again: + mtx_lock(&msi_lock); /* Try to find 'count' free IRQs. */ cnt = 0; @@ -263,20 +281,17 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, if (cnt < count) { /* If we would exceed the max, give up. */ if (i + (count - cnt) > FIRST_MSI_INT + NUM_MSI_INTS) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } + mtx_unlock(&msi_lock); - /* We need count - cnt more sources starting at index 'cnt'. */ - *newirq = cnt; - *newcount = count - cnt; - for (j = 0; j < *newcount; j++) { - - /* Create a new MSI source and add it to our array. */ - msi_create_source(i + j); - irqs[cnt] = i + j; + /* We need count - cnt more sources. */ + while (cnt < count) { + msi_create_source(); cnt++; } + goto again; } /* Ok, we now have the IRQs allocated. */ @@ -285,7 +300,7 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, /* Allocate 'count' IDT vectors. */ vector = apic_alloc_vectors(irqs, count, maxcount); if (vector == 0) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENOSPC); } @@ -299,12 +314,11 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, printf("msi: routing MSI IRQ %d to vector %u\n", msi->msi_irq, msi->msi_vector); msi->msi_first = fsrc; - - /* XXX: Somewhat gross. */ - msi->msi_intsrc.is_enabled = 0; + KASSERT(msi->msi_intsrc.is_handlers == 0, + ("dead MSI has handlers")); } fsrc->msi_count = count; - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (0); } @@ -315,22 +329,22 @@ msi_release(int *irqs, int count) struct msi_intsrc *msi, *first; int i; - sx_xlock(&msi_sx); + mtx_lock(&msi_lock); first = (struct msi_intsrc *)intr_lookup_source(irqs[0]); if (first == NULL) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this isn't an MSI-X message. */ if (first->msi_msix) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (EINVAL); } /* Make sure this message is allocated to a group. */ if (first->msi_first == NULL) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } @@ -339,7 +353,7 @@ msi_release(int *irqs, int count) * the entire group. */ if (first->msi_first != first || first->msi_count != count) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (EINVAL); } KASSERT(first->msi_dev != NULL, ("unowned group")); @@ -362,7 +376,7 @@ msi_release(int *irqs, int count) first->msi_vector = 0; first->msi_count = 0; - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (0); } @@ -371,27 +385,27 @@ msi_map(int irq, uint64_t *addr, uint32_t *data) { struct msi_intsrc *msi; - sx_slock(&msi_sx); + mtx_lock(&msi_lock); msi = (struct msi_intsrc *)intr_lookup_source(irq); if (msi == NULL) { - sx_sunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this message is allocated to a device. */ if (msi->msi_dev == NULL) { - sx_sunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } /* * If this message isn't an MSI-X message, make sure it's part - * of a gruop, and switch to the first message in the + * of a group, and switch to the first message in the * group. */ if (!msi->msi_msix) { if (msi->msi_first == NULL) { - sx_sunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } msi = msi->msi_first; @@ -399,21 +413,21 @@ msi_map(int irq, uint64_t *addr, uint32_t *data) *addr = INTEL_ADDR(msi); *data = INTEL_DATA(msi); - sx_sunlock(&msi_sx); + mtx_unlock(&msi_lock); return (0); } int -msix_alloc(device_t dev, int *irq, int *new) +msix_alloc(device_t dev, int *irq) { struct msi_intsrc *msi; int i, vector; - *new = 0; if (!msi_enabled) return (ENXIO); - sx_xlock(&msi_sx); +again: + mtx_lock(&msi_lock); /* Find a free IRQ. */ for (i = FIRST_MSI_INT; i < FIRST_MSI_INT + NUM_MSI_INTS; i++) { @@ -423,7 +437,7 @@ msix_alloc(device_t dev, int *irq, int *new) if (msi == NULL) break; - /* If this is a free one, start or continue a run. */ + /* Stop at the first free source. */ if (msi->msi_dev == NULL) break; } @@ -432,13 +446,14 @@ msix_alloc(device_t dev, int *irq, int *new) if (msi == NULL) { /* If we would exceed the max, give up. */ if (i + 1 > FIRST_MSI_INT + NUM_MSI_INTS) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } + mtx_unlock(&msi_lock); /* Create a new source. */ - *new = 1; - msi = msi_create_source(i); + msi_create_source(); + goto again; } /* Allocate an IDT vector. */ @@ -452,9 +467,8 @@ msix_alloc(device_t dev, int *irq, int *new) msi->msi_vector = vector; msi->msi_msix = 1; - /* XXX: Somewhat gross. */ - msi->msi_intsrc.is_enabled = 0; - sx_xunlock(&msi_sx); + KASSERT(msi->msi_intsrc.is_handlers == 0, ("dead MSI-X has handlers")); + mtx_unlock(&msi_lock); *irq = i; return (0); @@ -465,16 +479,16 @@ msix_release(int irq) { struct msi_intsrc *msi; - sx_xlock(&msi_sx); + mtx_lock(&msi_lock); msi = (struct msi_intsrc *)intr_lookup_source(irq); if (msi == NULL) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this is an MSI-X message. */ if (!msi->msi_msix) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (EINVAL); } @@ -486,6 +500,6 @@ msix_release(int irq) msi->msi_vector = 0; msi->msi_msix = 0; - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (0); } diff --git a/sys/amd64/amd64/nexus.c b/sys/amd64/amd64/nexus.c index 108abc117969..b5498b7d1e18 100644 --- a/sys/amd64/amd64/nexus.c +++ b/sys/amd64/amd64/nexus.c @@ -503,15 +503,20 @@ nexus_delete_resource(device_t dev, device_t child, int type, int rid) resource_list_delete(rl, type, rid); } +/* Called from the MSI code to add new IRQs to the IRQ rman. */ +void +nexus_add_irq(u_long irq) +{ + + if (rman_manage_region(&irq_rman, irq, irq) != 0) + panic("%s: failed", __func__); +} + static int nexus_alloc_msix(device_t pcib, device_t dev, int *irq) { - int error, new; - error = msix_alloc(dev, irq, &new); - if (new) - rman_manage_region(&irq_rman, *irq, *irq); - return (error); + return (msix_alloc(dev, irq)); } static int @@ -524,17 +529,8 @@ nexus_release_msix(device_t pcib, device_t dev, int irq) static int nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs) { - int error, i, newirq, newcount; - - /* First alloc the messages. */ - error = msi_alloc(dev, count, maxcount, irqs, &newirq, &newcount); - /* Always add any new IRQs to the rman, even on failure. */ - for (i = 0; i < newcount; i++) - rman_manage_region(&irq_rman, irqs[newirq + i], - irqs[newirq + i]); - - return (error); + return (msi_alloc(dev, count, maxcount, irqs)); } static int diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h index 9ffe17c56e52..107656b687d7 100644 --- a/sys/amd64/include/apicvar.h +++ b/sys/amd64/include/apicvar.h @@ -178,6 +178,7 @@ extern vm_paddr_t lapic_paddr; u_int apic_alloc_vector(u_int irq); u_int apic_alloc_vectors(u_int *irqs, u_int count, u_int align); +void apic_disable_vector(u_int vector); void apic_enable_vector(u_int vector); void apic_free_vector(u_int vector, u_int irq); u_int apic_idt_to_irq(u_int vector); diff --git a/sys/amd64/include/intr_machdep.h b/sys/amd64/include/intr_machdep.h index fd7fa3c49165..8b16c5e2fabc 100644 --- a/sys/amd64/include/intr_machdep.h +++ b/sys/amd64/include/intr_machdep.h @@ -86,6 +86,7 @@ struct pic { void (*pic_disable_source)(struct intsrc *, int); void (*pic_eoi_source)(struct intsrc *); void (*pic_enable_intr)(struct intsrc *); + void (*pic_disable_intr)(struct intsrc *); int (*pic_vector)(struct intsrc *); int (*pic_source_pending)(struct intsrc *); void (*pic_suspend)(struct pic *); @@ -114,7 +115,7 @@ struct intsrc { u_long *is_count; u_long *is_straycount; u_int is_index; - u_int is_enabled:1; + u_int is_handlers; }; struct trapframe; @@ -146,12 +147,12 @@ int intr_remove_handler(void *cookie); void intr_resume(void); void intr_suspend(void); void intrcnt_add(const char *name, u_long **countp); -int msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, - int *newcount); +void nexus_add_irq(u_long irq); +int msi_alloc(device_t dev, int count, int maxcount, int *irqs); void msi_init(void); int msi_map(int irq, uint64_t *addr, uint32_t *data); int msi_release(int *irqs, int count); -int msix_alloc(device_t dev, int *irq, int *new); +int msix_alloc(device_t dev, int *irq); int msix_release(int irq); #endif /* !LOCORE */ diff --git a/sys/amd64/isa/atpic.c b/sys/amd64/isa/atpic.c index 3a88eda4ef10..d9792eb8fcde 100644 --- a/sys/amd64/isa/atpic.c +++ b/sys/amd64/isa/atpic.c @@ -107,9 +107,10 @@ inthand_t #define ATPIC(io, base, eoi, imenptr) \ { { atpic_enable_source, atpic_disable_source, (eoi), \ - atpic_enable_intr, atpic_vector, atpic_source_pending, NULL, \ - atpic_resume, atpic_config_intr, atpic_assign_cpu }, (io), \ - (base), IDT_IO_INTS + (base), (imenptr) } + atpic_enable_intr, atpic_disable_intr, atpic_vector, \ + atpic_source_pending, NULL, atpic_resume, atpic_config_intr,\ + atpic_assign_cpu }, (io), (base), IDT_IO_INTS + (base), \ + (imenptr) } #define INTSRC(irq) \ { { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ), \ @@ -137,6 +138,7 @@ static void atpic_disable_source(struct intsrc *isrc, int eoi); 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); static int atpic_source_pending(struct intsrc *isrc); @@ -266,6 +268,12 @@ atpic_enable_intr(struct intsrc *isrc) { } +static void +atpic_disable_intr(struct intsrc *isrc) +{ +} + + static int atpic_vector(struct intsrc *isrc) { diff --git a/sys/i386/i386/intr_machdep.c b/sys/i386/i386/intr_machdep.c index 976007008110..0fa44ad78062 100644 --- a/sys/i386/i386/intr_machdep.c +++ b/sys/i386/i386/intr_machdep.c @@ -42,13 +42,14 @@ #include <sys/param.h> #include <sys/bus.h> #include <sys/interrupt.h> -#include <sys/lock.h> #include <sys/ktr.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/mutex.h> #include <sys/proc.h> #include <sys/syslog.h> #include <sys/systm.h> +#include <sys/sx.h> #include <machine/clock.h> #include <machine/intr_machdep.h> #include <machine/smp.h> @@ -62,7 +63,8 @@ typedef void (*mask_fn)(void *); static int intrcnt_index; static struct intsrc *interrupt_sources[NUM_IO_INTS]; -static struct mtx intr_table_lock; +static struct sx intr_table_lock; +static struct mtx intrcnt_lock; static STAILQ_HEAD(, pic) pics; #ifdef INTR_FILTER @@ -106,14 +108,14 @@ intr_register_pic(struct pic *pic) { int error; - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); if (intr_pic_registered(pic)) error = EBUSY; else { STAILQ_INSERT_TAIL(&pics, pic, pics); error = 0; } - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); return (error); } @@ -141,16 +143,16 @@ intr_register_source(struct intsrc *isrc) #endif if (error) return (error); - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); if (interrupt_sources[vector] != NULL) { - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); intr_event_destroy(isrc->is_event); return (EEXIST); } intrcnt_register(isrc); interrupt_sources[vector] = isrc; - isrc->is_enabled = 0; - mtx_unlock_spin(&intr_table_lock); + isrc->is_handlers = 0; + sx_xunlock(&intr_table_lock); return (0); } @@ -174,19 +176,18 @@ intr_add_handler(const char *name, int vector, driver_filter_t filter, error = intr_event_add_handler(isrc->is_event, name, filter, handler, arg, intr_priority(flags), flags, cookiep); if (error == 0) { + sx_xlock(&intr_table_lock); intrcnt_updatename(isrc); - mtx_lock_spin(&intr_table_lock); - if (!isrc->is_enabled) { - isrc->is_enabled = 1; + isrc->is_handlers++; + if (isrc->is_handlers == 1) { #ifdef SMP if (assign_cpu) intr_assign_next_cpu(isrc); #endif - mtx_unlock_spin(&intr_table_lock); isrc->is_pic->pic_enable_intr(isrc); - } else - mtx_unlock_spin(&intr_table_lock); - isrc->is_pic->pic_enable_source(isrc); + isrc->is_pic->pic_enable_source(isrc); + } + sx_xunlock(&intr_table_lock); } return (error); } @@ -199,8 +200,16 @@ intr_remove_handler(void *cookie) isrc = intr_handler_source(cookie); error = intr_event_remove_handler(cookie); - if (error == 0) + if (error == 0) { + sx_xlock(&intr_table_lock); + isrc->is_handlers--; + if (isrc->is_handlers == 0) { + isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI); + isrc->is_pic->pic_disable_intr(isrc); + } intrcnt_updatename(isrc); + sx_xunlock(&intr_table_lock); + } return (error); } @@ -379,12 +388,12 @@ intr_resume(void) { struct pic *pic; - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); STAILQ_FOREACH(pic, &pics, pics) { if (pic->pic_resume != NULL) pic->pic_resume(pic); } - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); } void @@ -392,12 +401,12 @@ intr_suspend(void) { struct pic *pic; - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); STAILQ_FOREACH(pic, &pics, pics) { if (pic->pic_suspend != NULL) pic->pic_suspend(pic); } - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); } static void @@ -420,8 +429,8 @@ intrcnt_register(struct intsrc *is) { char straystr[MAXCOMLEN + 1]; - /* mtx_assert(&intr_table_lock, MA_OWNED); */ KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__)); + mtx_lock_spin(&intrcnt_lock); is->is_index = intrcnt_index; intrcnt_index += 2; snprintf(straystr, MAXCOMLEN + 1, "stray irq%d", @@ -430,17 +439,18 @@ intrcnt_register(struct intsrc *is) is->is_count = &intrcnt[is->is_index]; intrcnt_setname(straystr, is->is_index + 1); is->is_straycount = &intrcnt[is->is_index + 1]; + mtx_unlock_spin(&intrcnt_lock); } void intrcnt_add(const char *name, u_long **countp) { - mtx_lock_spin(&intr_table_lock); + mtx_lock_spin(&intrcnt_lock); *countp = &intrcnt[intrcnt_index]; intrcnt_setname(name, intrcnt_index); intrcnt_index++; - mtx_unlock_spin(&intr_table_lock); + mtx_unlock_spin(&intrcnt_lock); } static void @@ -450,7 +460,8 @@ intr_init(void *dummy __unused) intrcnt_setname("???", 0); intrcnt_index = 1; STAILQ_INIT(&pics); - mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN); + sx_init(&intr_table_lock, "intr sources"); + mtx_init(&intrcnt_lock, "intrcnt", NULL, MTX_SPIN); } SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL) @@ -536,14 +547,14 @@ intr_shuffle_irqs(void *arg __unused) return; /* Round-robin assign a CPU to each enabled source. */ - mtx_lock_spin(&intr_table_lock); + sx_xlock(&intr_table_lock); assign_cpu = 1; for (i = 0; i < NUM_IO_INTS; i++) { isrc = interrupt_sources[i]; - if (isrc != NULL && isrc->is_enabled) + if (isrc != NULL && isrc->is_handlers > 0) intr_assign_next_cpu(isrc); } - mtx_unlock_spin(&intr_table_lock); + sx_xunlock(&intr_table_lock); } SYSINIT(intr_shuffle_irqs, SI_SUB_SMP, SI_ORDER_SECOND, intr_shuffle_irqs, NULL) #endif diff --git a/sys/i386/i386/io_apic.c b/sys/i386/i386/io_apic.c index bccacd8385d3..88667762f7b6 100644 --- a/sys/i386/i386/io_apic.c +++ b/sys/i386/i386/io_apic.c @@ -114,6 +114,7 @@ static void ioapic_enable_source(struct intsrc *isrc); static void ioapic_disable_source(struct intsrc *isrc, int eoi); static void ioapic_eoi_source(struct intsrc *isrc); static void ioapic_enable_intr(struct intsrc *isrc); +static void ioapic_disable_intr(struct intsrc *isrc); static int ioapic_vector(struct intsrc *isrc); static int ioapic_source_pending(struct intsrc *isrc); static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig, @@ -125,8 +126,8 @@ static void ioapic_program_intpin(struct ioapic_intsrc *intpin); static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list); struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source, ioapic_eoi_source, ioapic_enable_intr, - ioapic_vector, ioapic_source_pending, - NULL, ioapic_resume, + ioapic_disable_intr, ioapic_vector, + ioapic_source_pending, NULL, ioapic_resume, ioapic_config_intr, ioapic_assign_cpu }; static int next_ioapic_base; @@ -359,6 +360,23 @@ ioapic_enable_intr(struct intsrc *isrc) } } +static void +ioapic_disable_intr(struct intsrc *isrc) +{ + struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; + u_int vector; + + if (intpin->io_vector != 0) { + /* Mask this interrupt pin and free its APIC vector. */ + vector = intpin->io_vector; + apic_disable_vector(vector); + intpin->io_masked = 1; + intpin->io_vector = 0; + ioapic_program_intpin(intpin); + apic_free_vector(vector, intpin->io_irq); + } +} + static int ioapic_vector(struct intsrc *isrc) { diff --git a/sys/i386/i386/local_apic.c b/sys/i386/i386/local_apic.c index 1bcf142f6548..1447eb0136ad 100644 --- a/sys/i386/i386/local_apic.c +++ b/sys/i386/i386/local_apic.c @@ -147,6 +147,8 @@ static u_int32_t lapic_timer_divisors[] = { APIC_TDCR_32, APIC_TDCR_64, APIC_TDCR_128 }; +extern inthand_t IDTVEC(rsvd); + volatile lapic_t *lapic; vm_paddr_t lapic_paddr; static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz; @@ -840,6 +842,17 @@ apic_enable_vector(u_int vector) GSEL(GCODE_SEL, SEL_KPL)); } +void +apic_disable_vector(u_int vector) +{ + + KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry")); + KASSERT(ioint_handlers[vector / 32] != NULL, + ("No ISR handler for vector %u", vector)); + setidt(vector, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, + GSEL(GCODE_SEL, SEL_KPL)); +} + /* Release an APIC vector when it's no longer in use. */ void apic_free_vector(u_int vector, u_int irq) diff --git a/sys/i386/i386/msi.c b/sys/i386/i386/msi.c index 3bb184c274f5..6440852375c2 100644 --- a/sys/i386/i386/msi.c +++ b/sys/i386/i386/msi.c @@ -112,11 +112,12 @@ struct msi_intsrc { u_int msi_count:8; /* Messages in this group. (g) */ }; -static struct msi_intsrc *msi_create_source(u_int irq); +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); static int msi_vector(struct intsrc *isrc); static int msi_source_pending(struct intsrc *isrc); static int msi_config_intr(struct intsrc *isrc, enum intr_trigger trig, @@ -124,11 +125,13 @@ static int msi_config_intr(struct intsrc *isrc, enum intr_trigger trig, static void msi_assign_cpu(struct intsrc *isrc, u_int apic_id); struct pic msi_pic = { msi_enable_source, msi_disable_source, msi_eoi_source, - msi_enable_intr, msi_vector, msi_source_pending, - NULL, NULL, msi_config_intr, msi_assign_cpu }; + msi_enable_intr, msi_disable_intr, msi_vector, + msi_source_pending, NULL, NULL, msi_config_intr, + msi_assign_cpu }; static int msi_enabled; -static struct sx msi_sx; +static int msi_last_irq; +static struct mtx msi_lock; static void msi_enable_source(struct intsrc *isrc) @@ -158,6 +161,14 @@ msi_enable_intr(struct intsrc *isrc) apic_enable_vector(msi->msi_vector); } +static void +msi_disable_intr(struct intsrc *isrc) +{ + struct msi_intsrc *msi = (struct msi_intsrc *)isrc; + + apic_disable_vector(msi->msi_vector); +} + static int msi_vector(struct intsrc *isrc) { @@ -191,8 +202,7 @@ msi_assign_cpu(struct intsrc *isrc, u_int apic_id) printf("msi: Assigning %s IRQ %d to local APIC %u\n", msi->msi_msix ? "MSI-X" : "MSI", msi->msi_irq, msi->msi_cpu); - if (isrc->is_enabled) - pci_remap_msi_irq(msi->msi_dev, msi->msi_irq); + pci_remap_msi_irq(msi->msi_dev, msi->msi_irq); } void @@ -206,19 +216,29 @@ msi_init(void) msi_enabled = 1; intr_register_pic(&msi_pic); - sx_init(&msi_sx, "msi"); + mtx_init(&msi_lock, "msi", NULL, MTX_DEF); } -struct msi_intsrc * -msi_create_source(u_int irq) +void +msi_create_source(void) { struct msi_intsrc *msi; + u_int irq; + + mtx_lock(&msi_lock); + if (msi_last_irq >= NUM_MSI_INTS) { + mtx_unlock(&msi_lock); + return; + } + irq = msi_last_irq + FIRST_MSI_INT; + msi_last_irq++; + mtx_unlock(&msi_lock); - msi = malloc(sizeof(struct msi_intsrc), M_MSI, M_WAITOK | M_ZERO); + msi = malloc(sizeof(struct msi_intsrc), M_MSI, M_WAITOK | M_ZERO); msi->msi_intsrc.is_pic = &msi_pic; msi->msi_irq = irq; intr_register_source(&msi->msi_intsrc); - return (msi); + nexus_add_irq(irq); } /* @@ -228,18 +248,16 @@ msi_create_source(u_int irq) * and *newcount being the number of new IRQ values added. */ int -msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, - int *newcount) +msi_alloc(device_t dev, int count, int maxcount, int *irqs) { struct msi_intsrc *msi, *fsrc; - int cnt, i, j, vector; + int cnt, i, vector; - *newirq = 0; - *newcount = 0; if (!msi_enabled) return (ENXIO); - sx_xlock(&msi_sx); +again: + mtx_lock(&msi_lock); /* Try to find 'count' free IRQs. */ cnt = 0; @@ -263,20 +281,17 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, if (cnt < count) { /* If we would exceed the max, give up. */ if (i + (count - cnt) > FIRST_MSI_INT + NUM_MSI_INTS) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } + mtx_unlock(&msi_lock); - /* We need count - cnt more sources starting at index 'cnt'. */ - *newirq = cnt; - *newcount = count - cnt; - for (j = 0; j < *newcount; j++) { - - /* Create a new MSI source and add it to our array. */ - msi_create_source(i + j); - irqs[cnt] = i + j; + /* We need count - cnt more sources. */ + while (cnt < count) { + msi_create_source(); cnt++; } + goto again; } /* Ok, we now have the IRQs allocated. */ @@ -285,7 +300,7 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, /* Allocate 'count' IDT vectors. */ vector = apic_alloc_vectors(irqs, count, maxcount); if (vector == 0) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENOSPC); } @@ -299,12 +314,11 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, printf("msi: routing MSI IRQ %d to vector %u\n", msi->msi_irq, msi->msi_vector); msi->msi_first = fsrc; - - /* XXX: Somewhat gross. */ - msi->msi_intsrc.is_enabled = 0; + KASSERT(msi->msi_intsrc.is_handlers == 0, + ("dead MSI has handlers")); } fsrc->msi_count = count; - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (0); } @@ -315,22 +329,22 @@ msi_release(int *irqs, int count) struct msi_intsrc *msi, *first; int i; - sx_xlock(&msi_sx); + mtx_lock(&msi_lock); first = (struct msi_intsrc *)intr_lookup_source(irqs[0]); if (first == NULL) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this isn't an MSI-X message. */ if (first->msi_msix) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (EINVAL); } /* Make sure this message is allocated to a group. */ if (first->msi_first == NULL) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } @@ -339,7 +353,7 @@ msi_release(int *irqs, int count) * the entire group. */ if (first->msi_first != first || first->msi_count != count) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (EINVAL); } KASSERT(first->msi_dev != NULL, ("unowned group")); @@ -362,7 +376,7 @@ msi_release(int *irqs, int count) first->msi_vector = 0; first->msi_count = 0; - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (0); } @@ -371,27 +385,27 @@ msi_map(int irq, uint64_t *addr, uint32_t *data) { struct msi_intsrc *msi; - sx_slock(&msi_sx); + mtx_lock(&msi_lock); msi = (struct msi_intsrc *)intr_lookup_source(irq); if (msi == NULL) { - sx_sunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this message is allocated to a device. */ if (msi->msi_dev == NULL) { - sx_sunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } /* * If this message isn't an MSI-X message, make sure it's part - * of a gruop, and switch to the first message in the + * of a group, and switch to the first message in the * group. */ if (!msi->msi_msix) { if (msi->msi_first == NULL) { - sx_sunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } msi = msi->msi_first; @@ -399,21 +413,21 @@ msi_map(int irq, uint64_t *addr, uint32_t *data) *addr = INTEL_ADDR(msi); *data = INTEL_DATA(msi); - sx_sunlock(&msi_sx); + mtx_unlock(&msi_lock); return (0); } int -msix_alloc(device_t dev, int *irq, int *new) +msix_alloc(device_t dev, int *irq) { struct msi_intsrc *msi; int i, vector; - *new = 0; if (!msi_enabled) return (ENXIO); - sx_xlock(&msi_sx); +again: + mtx_lock(&msi_lock); /* Find a free IRQ. */ for (i = FIRST_MSI_INT; i < FIRST_MSI_INT + NUM_MSI_INTS; i++) { @@ -423,7 +437,7 @@ msix_alloc(device_t dev, int *irq, int *new) if (msi == NULL) break; - /* If this is a free one, start or continue a run. */ + /* Stop at the first free source. */ if (msi->msi_dev == NULL) break; } @@ -432,13 +446,14 @@ msix_alloc(device_t dev, int *irq, int *new) if (msi == NULL) { /* If we would exceed the max, give up. */ if (i + 1 > FIRST_MSI_INT + NUM_MSI_INTS) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENXIO); } + mtx_unlock(&msi_lock); /* Create a new source. */ - *new = 1; - msi = msi_create_source(i); + msi_create_source(); + goto again; } /* Allocate an IDT vector. */ @@ -452,9 +467,8 @@ msix_alloc(device_t dev, int *irq, int *new) msi->msi_vector = vector; msi->msi_msix = 1; - /* XXX: Somewhat gross. */ - msi->msi_intsrc.is_enabled = 0; - sx_xunlock(&msi_sx); + KASSERT(msi->msi_intsrc.is_handlers == 0, ("dead MSI-X has handlers")); + mtx_unlock(&msi_lock); *irq = i; return (0); @@ -465,16 +479,16 @@ msix_release(int irq) { struct msi_intsrc *msi; - sx_xlock(&msi_sx); + mtx_lock(&msi_lock); msi = (struct msi_intsrc *)intr_lookup_source(irq); if (msi == NULL) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this is an MSI-X message. */ if (!msi->msi_msix) { - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (EINVAL); } @@ -486,6 +500,6 @@ msix_release(int irq) msi->msi_vector = 0; msi->msi_msix = 0; - sx_xunlock(&msi_sx); + mtx_unlock(&msi_lock); return (0); } diff --git a/sys/i386/i386/nexus.c b/sys/i386/i386/nexus.c index 3bccb9ba078d..f5fa4e05ad04 100644 --- a/sys/i386/i386/nexus.c +++ b/sys/i386/i386/nexus.c @@ -550,16 +550,21 @@ nexus_delete_resource(device_t dev, device_t child, int type, int rid) resource_list_delete(rl, type, rid); } +/* Called from the MSI code to add new IRQs to the IRQ rman. */ +void +nexus_add_irq(u_long irq) +{ + + if (rman_manage_region(&irq_rman, irq, irq) != 0) + panic("%s: failed", __func__); +} + #ifdef DEV_APIC static int nexus_alloc_msix(device_t pcib, device_t dev, int *irq) { - int error, new; - error = msix_alloc(dev, irq, &new); - if (new) - rman_manage_region(&irq_rman, *irq, *irq); - return (error); + return (msix_alloc(dev, irq)); } static int @@ -572,17 +577,8 @@ nexus_release_msix(device_t pcib, device_t dev, int irq) static int nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs) { - int error, i, newirq, newcount; - - /* First alloc the messages. */ - error = msi_alloc(dev, count, maxcount, irqs, &newirq, &newcount); - /* Always add any new IRQs to the rman, even on failure. */ - for (i = 0; i < newcount; i++) - rman_manage_region(&irq_rman, irqs[newirq + i], - irqs[newirq + i]); - - return (error); + return (msi_alloc(dev, count, maxcount, irqs)); } static int diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h index 00339b4dff31..a21e03c08d57 100644 --- a/sys/i386/include/apicvar.h +++ b/sys/i386/include/apicvar.h @@ -177,6 +177,7 @@ extern vm_paddr_t lapic_paddr; u_int apic_alloc_vector(u_int irq); u_int apic_alloc_vectors(u_int *irqs, u_int count, u_int align); +void apic_disable_vector(u_int vector); void apic_enable_vector(u_int vector); void apic_free_vector(u_int vector, u_int irq); u_int apic_idt_to_irq(u_int vector); diff --git a/sys/i386/include/intr_machdep.h b/sys/i386/include/intr_machdep.h index f8f0c8a9ec10..4e6d07013fb4 100644 --- a/sys/i386/include/intr_machdep.h +++ b/sys/i386/include/intr_machdep.h @@ -86,6 +86,7 @@ struct pic { void (*pic_disable_source)(struct intsrc *, int); void (*pic_eoi_source)(struct intsrc *); void (*pic_enable_intr)(struct intsrc *); + void (*pic_disable_intr)(struct intsrc *); int (*pic_vector)(struct intsrc *); int (*pic_source_pending)(struct intsrc *); void (*pic_suspend)(struct pic *); @@ -114,7 +115,7 @@ struct intsrc { u_long *is_count; u_long *is_straycount; u_int is_index; - u_int is_enabled:1; + u_int is_handlers; }; struct trapframe; @@ -142,12 +143,12 @@ int intr_remove_handler(void *cookie); void intr_resume(void); void intr_suspend(void); void intrcnt_add(const char *name, u_long **countp); -int msi_alloc(device_t dev, int count, int maxcount, int *irqs, int *newirq, - int *newcount); +void nexus_add_irq(u_long irq); +int msi_alloc(device_t dev, int count, int maxcount, int *irqs); void msi_init(void); int msi_map(int irq, uint64_t *addr, uint32_t *data); int msi_release(int* irqs, int count); -int msix_alloc(device_t dev, int *irq, int *new); +int msix_alloc(device_t dev, int *irq); int msix_release(int irq); #endif /* !LOCORE */ diff --git a/sys/i386/isa/atpic.c b/sys/i386/isa/atpic.c index 9cd3b3368f33..bb05837510c4 100644 --- a/sys/i386/isa/atpic.c +++ b/sys/i386/isa/atpic.c @@ -125,9 +125,10 @@ inthand_t #define ATPIC(io, base, eoi, imenptr) \ { { atpic_enable_source, atpic_disable_source, (eoi), \ - atpic_enable_intr, atpic_vector, atpic_source_pending, NULL, \ - atpic_resume, atpic_config_intr, atpic_assign_cpu }, (io), \ - (base), IDT_IO_INTS + (base), (imenptr) } + atpic_enable_intr, atpic_disable_intr, atpic_vector, \ + atpic_source_pending, NULL, atpic_resume, atpic_config_intr,\ + atpic_assign_cpu }, (io), (base), IDT_IO_INTS + (base), \ + (imenptr) } #define INTSRC(irq) \ { { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ), \ @@ -155,6 +156,7 @@ static void atpic_disable_source(struct intsrc *isrc, int eoi); 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); static int atpic_source_pending(struct intsrc *isrc); @@ -284,6 +286,12 @@ atpic_enable_intr(struct intsrc *isrc) { } +static void +atpic_disable_intr(struct intsrc *isrc) +{ +} + + static int atpic_vector(struct intsrc *isrc) { |
