Correctly manage MMIO resource used by IOAPIC when hot-plugging IOAPICs. Signed-off-by: Jiang Liu <jiang.liu@xxxxxxxxxx> --- arch/x86/kernel/apic/io_apic.c | 46 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 45 insertions(+), 1 deletions(-) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index dfb6f45..9c2ac7b 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -4054,6 +4054,42 @@ fake_ioapic_page: res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1; } +static struct resource *ioapic_add_resource(int idx) +{ + char *name; + struct resource *res; + size_t sz = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource); + + res = kzalloc(sz, GFP_KERNEL); + if (res) { + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->name = name = (char *)(res + 1); + snprintf(name, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", idx); + ioapic_setup_resource(idx, res, true); + ioapics[idx].resource = res; + + if (insert_resource(&iomem_resource, res)) { + kfree(res); + res = NULL; + } + } + + return res; +} + +static void ioapic_remove_resource(int idx) +{ + struct resource *res = ioapics[idx].resource; + + if (res) { + if (res->parent) + release_resource(res); + if (PageSlab(virt_to_page(res))) + kfree(res); + ioapics[idx].resource = NULL; + } +} + void __init ioapic_and_gsi_init(void) { int i; @@ -4191,8 +4227,12 @@ int __mp_register_ioapic(int id, u32 address, u32 gsi_base, bool hotadd) if (gsi_cfg->gsi_end >= gsi_top) gsi_top = gsi_cfg->gsi_end + 1; } else { - int irq = reserve_ioapic_gsi_irq_base(idx, true); + int irq; + if (ioapic_add_resource(idx) == NULL) + goto failed; + + irq = reserve_ioapic_gsi_irq_base(idx, true); if (irq < 0) goto failed; @@ -4210,6 +4250,7 @@ int __mp_register_ioapic(int id, u32 address, u32 gsi_base, bool hotadd) return 0; failed: + ioapic_remove_resource(idx); clear_fixmap(FIX_IO_APIC_BASE_0 + idx); memset(&ioapics[idx], 0, sizeof(struct ioapic)); ioapics[idx].mp_config.apicid = 0xff; @@ -4234,6 +4275,9 @@ int mp_unregister_ioapic(u32 gsi_base) free_ioapic_gsi_irq_base(idx); clear_fixmap(FIX_IO_APIC_BASE_0 + idx); + + ioapic_remove_resource(idx); + memset(&ioapics[idx], 0, sizeof(struct ioapic)); ioapics[idx].mp_config.apicid = 0xff; -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html