aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/acpi/boot.c31
-rw-r--r--arch/x86/kernel/apic/io_apic.c22
2 files changed, 50 insertions, 3 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 2d76f022adc2..0b993511e0c5 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -780,8 +780,35 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
780 780
781int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base) 781int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
782{ 782{
783 /* TBD */ 783 int ret = -ENOSYS;
784 return -EINVAL; 784#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
785 int ioapic_id;
786 u64 addr;
787 struct ioapic_domain_cfg cfg = {
788 .type = IOAPIC_DOMAIN_DYNAMIC,
789 .ops = &acpi_irqdomain_ops,
790 };
791
792 ioapic_id = acpi_get_ioapic_id(handle, gsi_base, &addr);
793 if (ioapic_id < 0) {
794 unsigned long long uid;
795 acpi_status status;
796
797 status = acpi_evaluate_integer(handle, METHOD_NAME__UID,
798 NULL, &uid);
799 if (ACPI_FAILURE(status)) {
800 acpi_handle_warn(handle, "failed to get IOAPIC ID.\n");
801 return -EINVAL;
802 }
803 ioapic_id = (int)uid;
804 }
805
806 mutex_lock(&acpi_ioapic_lock);
807 ret = mp_register_ioapic(ioapic_id, phys_addr, gsi_base, &cfg);
808 mutex_unlock(&acpi_ioapic_lock);
809#endif
810
811 return ret;
785} 812}
786 813
787EXPORT_SYMBOL(acpi_register_ioapic); 814EXPORT_SYMBOL(acpi_register_ioapic);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 4333a751937d..826f44f0a2bf 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3861,7 +3861,13 @@ static int bad_ioapic_register(int idx)
3861 3861
3862static int find_free_ioapic_entry(void) 3862static int find_free_ioapic_entry(void)
3863{ 3863{
3864 return nr_ioapics; 3864 int idx;
3865
3866 for (idx = 0; idx < MAX_IO_APICS; idx++)
3867 if (ioapics[idx].nr_registers == 0)
3868 return idx;
3869
3870 return MAX_IO_APICS;
3865} 3871}
3866 3872
3867/** 3873/**
@@ -3874,6 +3880,7 @@ static int find_free_ioapic_entry(void)
3874int mp_register_ioapic(int id, u32 address, u32 gsi_base, 3880int mp_register_ioapic(int id, u32 address, u32 gsi_base,
3875 struct ioapic_domain_cfg *cfg) 3881 struct ioapic_domain_cfg *cfg)
3876{ 3882{
3883 bool hotplug = !!ioapic_initialized;
3877 struct mp_ioapic_gsi *gsi_cfg; 3884 struct mp_ioapic_gsi *gsi_cfg;
3878 int idx, ioapic, entries; 3885 int idx, ioapic, entries;
3879 u32 gsi_end; 3886 u32 gsi_end;
@@ -3935,6 +3942,19 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
3935 ioapics[idx].irqdomain = NULL; 3942 ioapics[idx].irqdomain = NULL;
3936 ioapics[idx].irqdomain_cfg = *cfg; 3943 ioapics[idx].irqdomain_cfg = *cfg;
3937 3944
3945 /*
3946 * If mp_register_ioapic() is called during early boot stage when
3947 * walking ACPI/SFI/DT tables, it's too early to create irqdomain,
3948 * we are still using bootmem allocator. So delay it to setup_IO_APIC().
3949 */
3950 if (hotplug) {
3951 if (mp_irqdomain_create(idx)) {
3952 clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
3953 return -ENOMEM;
3954 }
3955 alloc_ioapic_saved_registers(idx);
3956 }
3957
3938 if (gsi_cfg->gsi_end >= gsi_top) 3958 if (gsi_cfg->gsi_end >= gsi_top)
3939 gsi_top = gsi_cfg->gsi_end + 1; 3959 gsi_top = gsi_cfg->gsi_end + 1;
3940 if (nr_ioapics <= idx) 3960 if (nr_ioapics <= idx)