All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yinghai Lu <yinghai@kernel.org>
To: Thomas Gleixner <tglx@linutronix.de>, Ingo Molnar <mingo@elte.hu>,
	"H. Peter Anvin" <hpa@zytor.com>, Tony Luck <tony.luck@intel.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	"Rafael J. Wysocki" <rjw@sisk.pl>
Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, Yinghai Lu <yinghai@kernel.org>
Subject: [PATCH v5 30/33] PCI, x86, ACPI: Enable ioapic hotplug support with acpi host bridge.
Date: Thu,  2 Jan 2014 16:06:02 -0800	[thread overview]
Message-ID: <1388707565-16535-31-git-send-email-yinghai@kernel.org> (raw)
In-Reply-To: <1388707565-16535-1-git-send-email-yinghai@kernel.org>

We need to have ioapic setup before normal pci drivers.
otherwise other pci driver can not setup irq.

So we should not treat them as normal pci devices.
Also we will need to support ioapic hotplug without pci device around.

We need to call ioapic add/remove during host-bridge add/remove.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c  |   4 ++
 drivers/pci/ioapic.c     | 147 ++++++++++++++++++++++++++++++-----------------
 include/linux/pci-acpi.h |   8 +++
 3 files changed, 106 insertions(+), 53 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 20360e4..e666be3 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -599,6 +599,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
 		pci_assign_unassigned_root_bus_resources(root->bus);
 	}
 
+	acpi_pci_ioapic_add(root);
+
 	pci_bus_add_devices(root->bus);
 	return 1;
 
@@ -613,6 +615,8 @@ static void acpi_pci_root_remove(struct acpi_device *device)
 
 	pci_stop_root_bus(root->bus);
 
+	acpi_pci_ioapic_remove(root);
+
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
index 2c2930e..60351b2 100644
--- a/drivers/pci/ioapic.c
+++ b/drivers/pci/ioapic.c
@@ -22,101 +22,142 @@
 #include <linux/slab.h>
 #include <acpi/acpi_bus.h>
 
-struct ioapic {
-	acpi_handle	handle;
+struct acpi_pci_ioapic {
+	acpi_handle	root_handle;
 	u32		gsi_base;
+	struct pci_dev *pdev;
+	struct list_head list;
 };
 
-static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+static LIST_HEAD(ioapic_list);
+static DEFINE_MUTEX(ioapic_list_lock);
+
+static void handle_ioapic_add(acpi_handle handle, struct pci_dev **pdev,
+				 u32 *pgsi_base)
 {
-	acpi_handle handle;
 	acpi_status status;
 	unsigned long long gsb;
-	struct ioapic *ioapic;
+	struct pci_dev *dev;
+	u32 gsi_base;
 	int ret;
 	char *type;
-	struct resource *res;
+	struct resource r;
+	struct resource *res = &r;
+	char objname[64];
+	struct acpi_buffer buffer = {sizeof(objname), objname};
 
-	handle = ACPI_HANDLE(&dev->dev);
-	if (!handle)
-		return -EINVAL;
+	*pdev = NULL;
+	*pgsi_base = 0;
 
 	status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
-	if (ACPI_FAILURE(status))
-		return -EINVAL;
-
-	/*
-	 * The previous code in acpiphp evaluated _MAT if _GSB failed, but
-	 * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
-	 */
+	if (ACPI_FAILURE(status) || !gsb)
+		return;
 
-	ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
-	if (!ioapic)
-		return -ENOMEM;
+	dev = acpi_get_pci_dev(handle);
+	if (!dev)
+		return;
 
-	ioapic->handle = handle;
-	ioapic->gsi_base = (u32) gsb;
+	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
-	if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
-		type = "IOAPIC";
-	else
-		type = "IOxAPIC";
+	gsi_base = gsb;
+	type = "IOxAPIC";
 
 	ret = pci_enable_device(dev);
 	if (ret < 0)
-		goto exit_free;
+		goto exit_put;
 
 	pci_set_master(dev);
 
+	if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
+		type = "IOAPIC";
+
 	if (pci_request_region(dev, 0, type))
 		goto exit_disable;
 
 	res = &dev->resource[0];
-	if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
+
+	if (acpi_register_ioapic(handle, res->start, gsi_base))
 		goto exit_release;
 
-	pci_set_drvdata(dev, ioapic);
-	dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
-	return 0;
+	pr_info("%s %s %s at %pR, GSI %u\n",
+		dev_name(&dev->dev), objname, type,
+		res, gsi_base);
+
+	*pdev = dev;
+	*pgsi_base = gsi_base;
+	return;
 
 exit_release:
 	pci_release_region(dev, 0);
 exit_disable:
 	pci_disable_device(dev);
-exit_free:
-	kfree(ioapic);
-	return -ENODEV;
+exit_put:
+	pci_dev_put(dev);
 }
 
-static void ioapic_remove(struct pci_dev *dev)
+static void handle_ioapic_remove(acpi_handle handle, struct pci_dev *dev,
+				  u32 gsi_base)
 {
-	struct ioapic *ioapic = pci_get_drvdata(dev);
+	acpi_unregister_ioapic(handle, gsi_base);
 
-	acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
 	pci_release_region(dev, 0);
 	pci_disable_device(dev);
-	kfree(ioapic);
+	pci_dev_put(dev);
 }
 
+static acpi_status register_ioapic(acpi_handle handle, u32 lvl,
+					void *context, void **rv)
+{
+	acpi_handle root_handle = context;
+	struct pci_dev *pdev;
+	u32 gsi_base;
+	struct acpi_pci_ioapic *ioapic;
 
-static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = {
-	{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
-	{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, ioapic_devices);
+	handle_ioapic_add(handle, &pdev, &gsi_base);
+	if (!gsi_base)
+		return AE_OK;
 
-static struct pci_driver ioapic_driver = {
-	.name		= "ioapic",
-	.id_table	= ioapic_devices,
-	.probe		= ioapic_probe,
-	.remove		= ioapic_remove,
-};
+	ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
+	if (!ioapic) {
+		pr_err("%s: cannot allocate memory\n", __func__);
+		handle_ioapic_remove(root_handle, pdev, gsi_base);
+		return AE_OK;
+	}
+	ioapic->root_handle = root_handle;
+	ioapic->pdev = pdev;
+	ioapic->gsi_base = gsi_base;
+
+	mutex_lock(&ioapic_list_lock);
+	list_add(&ioapic->list, &ioapic_list);
+	mutex_unlock(&ioapic_list_lock);
+
+	return AE_OK;
+}
 
-static int __init ioapic_init(void)
+void acpi_pci_ioapic_add(struct acpi_pci_root *root)
 {
-	return pci_register_driver(&ioapic_driver);
+	acpi_status status;
+
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle,
+				     (u32)1, register_ioapic, NULL,
+				     root->device->handle,
+				     NULL);
+	if (ACPI_FAILURE(status))
+		pr_err("%s: register_ioapic failure - %d", __func__, status);
 }
-module_init(ioapic_init);
 
-MODULE_LICENSE("GPL");
+void acpi_pci_ioapic_remove(struct acpi_pci_root *root)
+{
+	struct acpi_pci_ioapic *ioapic, *tmp;
+
+	mutex_lock(&ioapic_list_lock);
+	list_for_each_entry_safe(ioapic, tmp, &ioapic_list, list) {
+		if (root->device->handle != ioapic->root_handle)
+			continue;
+		list_del(&ioapic->list);
+		handle_ioapic_remove(ioapic->root_handle, ioapic->pdev,
+					ioapic->gsi_base);
+		kfree(ioapic);
+	}
+	mutex_unlock(&ioapic_list_lock);
+}
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 5a462c4..d2a976a 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -67,6 +67,14 @@ static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
 static inline void acpiphp_check_host_bridge(acpi_handle handle) { }
 #endif
 
+#ifdef CONFIG_PCI_IOAPIC
+void acpi_pci_ioapic_add(struct acpi_pci_root *root);
+void acpi_pci_ioapic_remove(struct acpi_pci_root *root);
+#else
+static inline void acpi_pci_ioapic_add(struct acpi_pci_root *root) { }
+static inline void acpi_pci_ioapic_remove(struct acpi_pci_root *root) { }
+#endif
+
 #else	/* CONFIG_ACPI */
 static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
-- 
1.8.4

  parent reply	other threads:[~2014-01-03  0:06 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-03  0:05 [PATCH v5 00/33] x86, irq: Support ioapic controller hotplug Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 01/33] genirq: Split __irq_reserve_irqs from irq_alloc_descs Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 02/33] genirq: Add irq_alloc_reserved_desc() Yinghai Lu
2014-01-23  0:03   ` Thomas Gleixner
2014-02-18  0:59     ` Yinghai Lu
2014-02-22 10:08       ` Thomas Gleixner
2014-02-22 17:28         ` Yinghai Lu
2014-02-22 22:05           ` Yinghai Lu
2014-02-22 23:38             ` Thomas Gleixner
2014-02-25  1:31               ` Yinghai Lu
2014-02-21  6:45   ` Jiang Liu
2014-01-03  0:05 ` [PATCH v5 03/33] genirq: Do not free unallocated irq descriptors Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 04/33] x86, irq: Change irq_remap_modify_chip_defaults() to static Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 05/33] x86, irq: Modify irq chip once for irq remapping Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 06/33] x86, irq: Show MSI-X clearly in debug message Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 07/33] x86, irq: Show MSI-X in /proc/interrupt Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 08/33] x86, irq: Make dmar_msi/hpet_msi irq_chip name consistent Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 09/33] ia64, irq: Add dummy create_irq_nr() Yinghai Lu
2014-01-03  0:05   ` Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 10/33] iommu, irq: Allocate irq_desc for dmar_msi with local node Yinghai Lu
2014-02-21  7:43   ` Jiang Liu
2014-02-21 23:18     ` Yinghai Lu
2014-02-22  3:14       ` Jiang Liu
2014-02-22  7:44         ` Yinghai Lu
2014-02-22 15:33           ` Jiang Liu
2014-02-22 17:30             ` Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 11/33] x86, irq: Kill create_irq() Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 12/33] x86, irq: Convert irq_2_pin list to generic list Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 13/33] x86, irq: Add alloc_reserved_irq_and_cfg_at() Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 14/33] x86, irq: Move down arch_early_irq_init() Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 15/33] x86, irq: Split out alloc_ioapic_save_registers() Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 16/33] xen, irq: Call irq_alloc_reserved_desc_at() at first Yinghai Lu
2014-01-03  0:05   ` Yinghai Lu
2014-01-03 17:50   ` [Xen-devel] " Stefano Stabellini
2014-01-03 17:50     ` Stefano Stabellini
2014-01-06 20:00     ` Yinghai Lu
2014-01-07 13:30       ` Stefano Stabellini
2014-01-03  0:05 ` [PATCH v5 17/33] x86, irq: Reserve irq range and alloc_reserved for booting path Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 18/33] x86, irq: Add ioapic_gsi_to_irq Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 19/33] x86, irq: Add for_each_ioapic helper Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 20/33] x86, irq: More strict checking about registering ioapic Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 21/33] x86, irq: Make mp_register_ioapic handle hot-added ioapic Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 22/33] x86, irq: Add mp_unregister_ioapic to handle hot-remove ioapic Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 23/33] x86, ioapic: Find usable ioapic id for 64bit Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 24/33] x86: Move declaration for mp_register_ioapic() Yinghai Lu
2014-01-03 21:24   ` Bjorn Helgaas
2014-01-06 22:30     ` Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 25/33] PCI, x86: Make ioapic hotplug support built-in Yinghai Lu
2014-01-03 22:47   ` Bjorn Helgaas
2014-01-06 22:47     ` Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 26/33] ACPI: Make map_mat_entry handle x2apic entry Yinghai Lu
2014-01-03  0:05 ` [PATCH v5 27/33] ACPI: Move acpi_get_cpuid() to separated file Yinghai Lu
2014-01-03  0:06 ` [PATCH v5 28/33] ACPI, ioapic: Add acpi_get_ioapic_id() Yinghai Lu
2014-01-03  0:06 ` [PATCH v5 29/33] PCI, x86, ACPI: Link acpi ioapic register to ioapic Yinghai Lu
2014-01-03  0:06 ` Yinghai Lu [this message]
2014-01-03 22:39   ` [PATCH v5 30/33] PCI, x86, ACPI: Enable ioapic hotplug support with acpi host bridge Bjorn Helgaas
2014-01-03  0:06 ` [PATCH v5 31/33] ACPI, x86/PCI: Move resource_to_addr() to acpi generic Yinghai Lu
2014-01-03  0:06 ` [PATCH v5 32/33] PCI, x86, ACPI: get ioapic address from acpi device Yinghai Lu
2014-01-03  0:06 ` [PATCH v5 33/33] x86, ioapic: Hotadd of IOAPICs described in static MADT Yinghai Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1388707565-16535-31-git-send-email-yinghai@kernel.org \
    --to=yinghai@kernel.org \
    --cc=bhelgaas@google.com \
    --cc=hpa@zytor.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=rjw@sisk.pl \
    --cc=tglx@linutronix.de \
    --cc=tony.luck@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.