Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2ae5da7 authored by Rui Wang's avatar Rui Wang Committed by Thomas Gleixner
Browse files

x86/ioapic: Split IOAPIC hot-removal into two steps



The hot removal of IOAPIC is handling PCI and ACPI removal in one go. That
only works when the PCI drivers released the interrupt resources, but
breaks when a IOAPIC interrupt is still associated to a PCI device.

The new pcibios_release_device() callback allows to solve that problem by
splitting the removal into two steps:

1) PCI removal:

   Release all PCI resources including eventually not yet released IOAPIC
   interrupts via the new pcibios_release_device() callback.

2) ACPI removal:

   After release of all PCI resources the ACPI resources can be released
   without issue.

[ tglx: Rewrote changelog ]

Signed-off-by: default avatarRui Wang <rui.y.wang@intel.com>
Cc: tony.luck@intel.com
Cc: linux-pci@vger.kernel.org
Cc: rjw@rjwysocki.net
Cc: linux-acpi@vger.kernel.org
Cc: fengguang.wu@intel.com
Cc: helgaas@kernel.org
Cc: kbuild-all@01.org
Cc: bhelgaas@google.com
Link: http://lkml.kernel.org/r/1488288869-31290-3-git-send-email-rui.y.wang@intel.com


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 153654db
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -41,8 +41,10 @@ void acpi_gpe_apply_masked_gpes(void);
void acpi_container_init(void);
void acpi_memory_hotplug_init(void);
#ifdef	CONFIG_ACPI_HOTPLUG_IOAPIC
void pci_ioapic_remove(struct acpi_pci_root *root);
int acpi_ioapic_remove(struct acpi_pci_root *root);
#else
static inline void pci_ioapic_remove(struct acpi_pci_root *root) { return; }
static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; }
#endif
#ifdef CONFIG_ACPI_DOCK
+16 −6
Original line number Diff line number Diff line
@@ -206,24 +206,34 @@ int acpi_ioapic_add(acpi_handle root_handle)
	return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV;
}

int acpi_ioapic_remove(struct acpi_pci_root *root)
void pci_ioapic_remove(struct acpi_pci_root *root)
{
	int retval = 0;
	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;

		if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base))
			retval = -EBUSY;

		if (ioapic->pdev) {
			pci_release_region(ioapic->pdev, 0);
			pci_disable_device(ioapic->pdev);
			pci_dev_put(ioapic->pdev);
		}
	}
	mutex_unlock(&ioapic_list_lock);
}

int acpi_ioapic_remove(struct acpi_pci_root *root)
{
	int retval = 0;
	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;
		if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base))
			retval = -EBUSY;
		if (ioapic->res.flags && ioapic->res.parent)
			release_resource(&ioapic->res);
		list_del(&ioapic->list);
+2 −2
Original line number Diff line number Diff line
@@ -648,12 +648,12 @@ static void acpi_pci_root_remove(struct acpi_device *device)

	pci_stop_root_bus(root->bus);

	WARN_ON(acpi_ioapic_remove(root));

	pci_ioapic_remove(root);
	device_set_run_wake(root->bus->bridge, false);
	pci_acpi_remove_bus_pm_notifier(device);

	pci_remove_root_bus(root->bus);
	WARN_ON(acpi_ioapic_remove(root));

	dmar_device_remove(device->handle);