aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-05-19 20:14:13 -0400
committerBjorn Helgaas <bhelgaas@google.com>2015-05-22 18:38:50 -0400
commitd41be3466f4243f1b198b76fe3bcd91d88194f12 (patch)
tree189aafeadad5e3e1d8417bfec726ee090d9cb53b
parent2af31f415fa177dd11bc76f2a292b09330803c89 (diff)
ACPI / hotplug / PCI: Check ignore_hotplug for all downstream devices
If the ignore_hotplug flag is set for a PCI device without an ACPI companion and a bus check notification is received for an ancestor bridge that is not the device's parent, ACPIPHP will ignore that flag. Namely, in that case acpiphp_check_bridge() is called for the target bridge and if all of the devices immediately below the bridge are still present, trim_stale_devices() will be called for each of them. That function recursively walks the hierarchy downwards and removes device objects corresponding to devices that don't appear to be present any more. Unfortunately, it only checks ignore_hotplug for devices having ACPI companions, so it will remove the others (if they don't respond) regardless of the ignore_hotplug value. Fix the problem by making trim_stale_devices() take ignore_hotplug into consideration regardless of whether or not an ACPI companion is present for the device it has been called for. [bhelgaas: This may fix bug 61891, depending on whether the bridge above a device is removed along with the device] Link: https://bugzilla.kernel.org/show_bug.cgi?id=61891 Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index bcb90e4888dd..ff538568a617 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -632,15 +632,14 @@ static void trim_stale_devices(struct pci_dev *dev)
632{ 632{
633 struct acpi_device *adev = ACPI_COMPANION(&dev->dev); 633 struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
634 struct pci_bus *bus = dev->subordinate; 634 struct pci_bus *bus = dev->subordinate;
635 bool alive = false; 635 bool alive = dev->ignore_hotplug;
636 636
637 if (adev) { 637 if (adev) {
638 acpi_status status; 638 acpi_status status;
639 unsigned long long sta; 639 unsigned long long sta;
640 640
641 status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); 641 status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
642 alive = (ACPI_SUCCESS(status) && device_status_valid(sta)) 642 alive = alive || (ACPI_SUCCESS(status) && device_status_valid(sta));
643 || dev->ignore_hotplug;
644 } 643 }
645 if (!alive) 644 if (!alive)
646 alive = pci_device_is_present(dev); 645 alive = pci_device_is_present(dev);