Skip to contentSkip to conversation

enhance IOAPIC core to support hotplug

RFC PATCH In review Jiang Liu 2 participants 6 messages May 27, 2014 – May 28, 2014

Subsystems (3)
lore
Share & tools
lore

Jiang Liu

author
#0 lore raw

cover enhance IOAPIC core to support hotplug

This patch set enhances IOAPIC core to support IOAPIC hotplug on x86 platforms. It's based on another patch set "use irqdomain to dynamically allocate IRQ for IOAPIC" at https://lkml.org/lkml/2014/5/27/86

You may pull from
https://github.com/jiangliu/linux.git ioapic/hotplug

Once passed review, we will use Yinghai's patches to glue IOAPIC driver and ACPI PCI root driver to handle hotplug events.

Jiang Liu (4):
x86, irq: refine mp_register_ioapic() to prepare for IOAPIC hotplug x86, irq, ACPI: introduce a rwsem to protect IOAPIC operations from
hotplug
x86, irq, ACPI: implement interface to support ACPI based IOAPIC
hot-addition
x86, irq, ACPI: implement interface to support ACPI based IOAPIC
hot-removal

 arch/x86/include/asm/io_apic.h |    5 +-
 arch/x86/kernel/acpi/boot.c    |   44 +++++++--
 arch/x86/kernel/apic/io_apic.c |  207 ++++++++++++++++++++++++++++++----------
 3 files changed, 196 insertions(+), 60 deletions(-)
Signature · 1 line
1.7.10.4
author
#1 lore raw

RFC PATCH 1/4 x86, irq: refine mp_register_ioapic() to prepare for IOAPIC hotplug

---
 arch/x86/include/asm/io_apic.h |    4 +-
 arch/x86/kernel/apic/io_apic.c |  143 ++++++++++++++++++++++++++--------------
 2 files changed, 94 insertions(+), 53 deletions(-)
arch/x86/include/asm/io_apic.h +2 -2
index 6b40122bec0c..64379c285435 100644
@@ -181,8 +181,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-				      ioapic_create_domain_fn cb, void *arg);
+extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			      ioapic_create_domain_fn cb, void *arg);
 extern struct irq_domain *mp_irqdomain_create(int ioapic,
 		struct device_node *np, const struct irq_domain_ops *ops);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
arch/x86/kernel/apic/io_apic.c +92 -51

241 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#2 lore raw

Re: [RFC Patch V1 1/4] x86, irq: refine mp_register_ioapic() to prepare for IOAPIC hotplug

Quoted 2 lines · Jiang Liu
arch/x86/kernel/apic/io_apic.c +1 -1
-static void ioapic_create_irqdomains(void)
+static int ioapic_create_irqdomain(int idx)

...

arch/x86/kernel/apic/io_apic.c io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) · line 3435

Quoted 2 lines
arch/x86/kernel/apic/io_apic.c +1 -1
-static int __init io_apic_get_redir_entries(int ioapic)
+static int io_apic_get_redir_entries(int ioapic)

Can you please split the functional changes from the trivial __init removal ones?

Thanks,

tglx

author
#3 lore raw

RFC PATCH 2/4 x86, irq, ACPI: introduce a rwsem to protect IOAPIC operations from hotplug

In reply to Jiang Liu

We are going to support ACPI based IOAPIC hotplug, so introduce a rwsem to protect IOAPIC data structures from IOAPIC hotplug. We choose to serialize in ACPI instead of in the IOAPIC core because:
1) currently we are only plan to support ACPI based IOAPIC hotplug
2) it's much more clean and easy
3) It does't affect IOAPIC discovered by devicetree, SFI and mppparse.

---
 arch/x86/kernel/acpi/boot.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
arch/x86/kernel/acpi/boot.c +12 -1
index c8e8fe67bbc8..a1b388e88bcb 100644
@@ -75,6 +75,8 @@ int acpi_fix_pin2_polarity __initdata;
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
 
+static DECLARE_RWSEM(acpi_ioapic_rwsem);
+
 #ifndef __HAVE_ARCH_CMPXCHG
 #warning ACPI uses CMPXCHG, i486 and later hardware
 #endif
@@ -495,8 +497,11 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 {
-	int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+	int irq;
 
+	down_read(&acpi_ioapic_rwsem);
+	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+	up_read(&acpi_ioapic_rwsem);
 	if (irq >= 0) {
 		*irqp = irq;
 		return 0;
@@ -537,7 +542,9 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
 	int irq = gsi;
 
 #ifdef CONFIG_X86_IO_APIC
+	down_read(&acpi_ioapic_rwsem);
 	irq = mp_register_gsi(dev, gsi, trigger, polarity);
+	up_read(&acpi_ioapic_rwsem);
 #endif
 
 	return irq;
@@ -546,7 +553,9 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
 static void acpi_unregister_gsi_ioapic(u32 gsi)
 {
 #ifdef CONFIG_X86_IO_APIC
+	down_read(&acpi_ioapic_rwsem);
 	mp_unregister_gsi(gsi);
+	up_read(&acpi_ioapic_rwsem);
 #endif
 }
 
@@ -1198,7 +1207,9 @@ static void __init acpi_process_madt(void)
 			/*
 			 * Parse MADT IO-APIC entries
 			 */
+			down_write(&acpi_ioapic_rwsem);
 			error = acpi_parse_madt_ioapic_entries();
+			up_write(&acpi_ioapic_rwsem);
 			if (!error) {
 				acpi_set_irq_model_ioapic();
 
Signature · 1 line
1.7.10.4
author
#4 lore raw

RFC PATCH 3/4 x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-addition

In reply to Jiang Liu

Implement acpi_register_ioapic() and enhance mp_register_ioapic() to support ACPI based IOAPIC hot-addition.

---
 arch/x86/kernel/acpi/boot.c    |   18 ++++++++++++++++--
 arch/x86/kernel/apic/io_apic.c |   24 +++++++++++++++++++++---
 2 files changed, 37 insertions(+), 5 deletions(-)
arch/x86/kernel/acpi/boot.c +16 -2
index a1b388e88bcb..d807e16f8fec 100644
@@ -655,8 +655,22 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
+	int ret = -ENOSYS;
+#ifdef CONFIG_X86_IO_APIC
+	unsigned long long uid;
+	acpi_status status;
+
+	status = acpi_evaluate_integer(handle, METHOD_NAME__UID, NULL, &uid);
+	if (ACPI_FAILURE(status))
+		uid = 0;
+
+	down_write(&acpi_ioapic_rwsem);
+	ret  = mp_register_ioapic((int)uid, phys_addr, gsi_base,
+				  acpi_create_irqdomain, NULL);
+	up_write(&acpi_ioapic_rwsem);
+#endif
+
+	return ret;
 }
 
 EXPORT_SYMBOL(acpi_register_ioapic);
arch/x86/kernel/apic/io_apic.c +21 -3
index f70fa239f34b..4bddff760ff4 100644
@@ -3802,7 +3802,13 @@ static int bad_ioapic_register(int idx)
 
 static int find_free_ioapic_entry(void)
 {
-	return nr_ioapics;
+	int idx;
+
+	for (idx = 0; idx < MAX_IO_APICS; idx++)
+		if (ioapics[idx].nr_registers == 0)
+			return idx;
+
+	return MAX_IO_APICS;
 }
 
 int mp_register_ioapic(int id, u32 address, u32 gsi_base,
@@ -3818,8 +3824,15 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	}
 	for_each_ioapic(ioapic)
 		if (ioapics[ioapic].mp_config.apicaddr == address) {
-			pr_warn("address 0x%x conflicts with IOAPIC%d\n",
-				address, ioapic);
+			/*
+			 * IOAPIC unit may also be visible in PCI scope.
+			 * When ioapic PCI driver's probe() is called,
+			 * the IOAPIC unit may have already been initialized
+			 * at boot time.
+			 */
+			if (!ioapic_initialized)
+				pr_warn("address 0x%x conflicts with IOAPIC%d\n",
+					address, ioapic);
 			return -EEXIST;
 		}
 
@@ -3875,6 +3888,11 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	if (nr_ioapics <= idx)
 		nr_ioapics = idx + 1;
 
+	if (ioapic_initialized && ioapic_create_irqdomain(idx)) {
+		clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
+		return -ENOMEM;
+	}
+
 	/* Set nr_registers to mark entry present */
 	ioapics[idx].nr_registers = entries;
 
Signature · 1 line
1.7.10.4
author
#5 lore raw

RFC PATCH 4/4 x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-removal

In reply to Jiang Liu

Implement acpi_unregister_ioapic() to support ACPI based IOAPIC hot-removal. An IOAPIC could only be removed when all its pins are unused.

---
 arch/x86/include/asm/io_apic.h |    1 +
 arch/x86/kernel/acpi/boot.c    |   13 ++++++++----
 arch/x86/kernel/apic/io_apic.c |   46 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 4 deletions(-)
arch/x86/include/asm/io_apic.h +1 -0
index 64379c285435..256ec8d9050c 100644
@@ -183,6 +183,7 @@ extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      ioapic_create_domain_fn cb, void *arg);
+extern int mp_unregister_ioapic(u32 gsi_base);
 extern struct irq_domain *mp_irqdomain_create(int ioapic,
 		struct device_node *np, const struct irq_domain_ops *ops);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
arch/x86/kernel/acpi/boot.c +9 -4
index d807e16f8fec..c17cc0510040 100644
@@ -672,15 +672,20 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 
 	return ret;
 }
-
 EXPORT_SYMBOL(acpi_register_ioapic);
 
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
-}
+	int ret = -ENOSYS;
+
+#ifdef CONFIG_X86_IO_APIC
+	down_write(&acpi_ioapic_rwsem);
+	ret  = mp_unregister_ioapic(gsi_base);
+	up_write(&acpi_ioapic_rwsem);
+#endif
 
+	return ret;
+}
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
arch/x86/kernel/apic/io_apic.c +46 -0

58 lines not on this page · raw message

Signature · 1 line
1.7.10.4