mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 05:34:13 +08:00
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: Rui 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: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
153654dbe5
commit
f2ae5da726
@ -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
|
||||
|
@ -206,6 +206,23 @@ int acpi_ioapic_add(acpi_handle root_handle)
|
||||
return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
void 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;
|
||||
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;
|
||||
@ -215,15 +232,8 @@ int acpi_ioapic_remove(struct acpi_pci_root *root)
|
||||
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);
|
||||
}
|
||||
if (ioapic->res.flags && ioapic->res.parent)
|
||||
release_resource(&ioapic->res);
|
||||
list_del(&ioapic->list);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user