Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Rafael J. Wysocki and committed by
Bjorn Helgaas
d41be346 2af31f41

+2 -3
+2 -3
drivers/pci/hotplug/acpiphp_glue.c
··· 632 632 { 633 633 struct acpi_device *adev = ACPI_COMPANION(&dev->dev); 634 634 struct pci_bus *bus = dev->subordinate; 635 - bool alive = false; 635 + bool alive = dev->ignore_hotplug; 636 636 637 637 if (adev) { 638 638 acpi_status status; 639 639 unsigned long long sta; 640 640 641 641 status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); 642 - alive = (ACPI_SUCCESS(status) && device_status_valid(sta)) 643 - || dev->ignore_hotplug; 642 + alive = alive || (ACPI_SUCCESS(status) && device_status_valid(sta)); 644 643 } 645 644 if (!alive) 646 645 alive = pci_device_is_present(dev);