Skip to content

Commit

Permalink
x86/ioapic: Split IOAPIC hot-removal into two steps
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ruiwang1 authored and KAGA-KOKO committed Mar 1, 2017
1 parent 153654d commit f2ae5da
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 8 deletions.
2 changes: 2 additions & 0 deletions drivers/acpi/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 16 additions & 6 deletions drivers/acpi/ioapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions drivers/acpi/pci_root.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit f2ae5da

Please sign in to comment.