Index: sys/x86/x86/msi.c =================================================================== --- sys/x86/x86/msi.c +++ sys/x86/x86/msi.c @@ -246,7 +246,7 @@ struct msi_intsrc *sib, *msi = (struct msi_intsrc *)isrc; int old_vector; u_int old_id; - int i, vector; + int error, i, vector; /* * Only allow CPUs to be assigned to the first message for an @@ -286,28 +286,41 @@ return (ENOSPC); } - msi->msi_cpu = apic_id; - msi->msi_vector = vector; if (msi->msi_intsrc.is_handlers > 0) - apic_enable_vector(msi->msi_cpu, msi->msi_vector); + apic_enable_vector(apic_id, vector); if (bootverbose) printf("msi: Assigning %s IRQ %d to local APIC %u vector %u\n", msi->msi_msix ? "MSI-X" : "MSI", msi->msi_irq, msi->msi_cpu, msi->msi_vector); for (i = 1; i < msi->msi_count; i++) { sib = (struct msi_intsrc *)intr_lookup_source(msi->msi_irqs[i]); - sib->msi_cpu = apic_id; - sib->msi_vector = vector + i; if (sib->msi_intsrc.is_handlers > 0) - apic_enable_vector(sib->msi_cpu, sib->msi_vector); + apic_enable_vector(apic_id, vector + i); if (bootverbose) printf( "msi: Assigning MSI IRQ %d to local APIC %u vector %u\n", sib->msi_irq, sib->msi_cpu, sib->msi_vector); } - BUS_REMAP_INTR(device_get_parent(msi->msi_dev), msi->msi_dev, + error = BUS_REMAP_INTR(device_get_parent(msi->msi_dev), msi->msi_dev, msi->msi_irq); + if (error != 0) { + printf("%s: error %d from BUS_REMAP_INTR for irq %u\n", + __func__, error, msi->msi_irq); + if (msi->msi_intsrc.is_handlers > 0) + apic_disable_vector(apic_id, vector); + for (i = 1; i < msi->msi_count; i++) { + sib = (struct msi_intsrc *)intr_lookup_source( + msi->msi_irqs[i]); + if (sib->msi_intsrc.is_handlers > 0) + apic_disable_vector(apic_id, vector + i); + } + for (i = 0; i < msi->msi_count; i++) + apic_free_vector(apic_id, vector + i, msi->msi_irqs[i]); + return (error); + } + msi->msi_cpu = apic_id; + msi->msi_vector = vector; /* * Free the old vector after the new one is established. This is done * to prevent races where we could miss an interrupt. @@ -317,6 +330,8 @@ apic_free_vector(old_id, old_vector, msi->msi_irq); for (i = 1; i < msi->msi_count; i++) { sib = (struct msi_intsrc *)intr_lookup_source(msi->msi_irqs[i]); + sib->msi_cpu = apic_id; + sib->msi_vector = vector + i; if (sib->msi_intsrc.is_handlers > 0) apic_disable_vector(old_id, old_vector + i); apic_free_vector(old_id, old_vector + i, msi->msi_irqs[i]);