Thread (28 messages) 28 messages, 5 authors, 2014-02-18

Re: 3.12: ethernet controller missing after resuming from suspend to RAM

From: Mika Westerberg <mika.westerberg@linux.intel.com>
Date: 2014-02-11 10:35:37
Also in: lkml
Subsystem: acpi, pci subsystem, the rest · Maintainers: "Rafael J. Wysocki", Bjorn Helgaas, Linus Torvalds

Possibly related (same subject, not in this thread)

On Mon, Feb 10, 2014 at 11:39:29PM +0100, Rafael J. Wysocki wrote:
quoted
_STA() returns 0x0A instead of 0x0F. Could there be something missing in
the ACPI hotplug code that overlooks this and removes the device on resume?
That is possible.  Actually even quite likely, but let's wait for the response
from Peter.
Here's a hack that should take the 0xa return value into consideration. It
turned out that this case is even mentioned in the ACPI spec.
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index e2a783fdb98f..014381b42d86 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -730,6 +730,17 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
 	return (unsigned int)sta;
 }
 
+static inline bool device_sta_valid(unsigned long long sta)
+{
+	/*
+	 * ACPI spec says that _STA may return bit 0 clear with bit 8 set
+	 * if the device is valid but does not require device driver to be
+	 * loaded (chapter 6.3.7).
+	 */
+	unsigned mask = ACPI_STA_DEVICE_ENABLED | ACPI_STA_DEVICE_FUNCTIONING;
+	return (sta & mask) == mask;
+}
+
 /**
  * trim_stale_devices - remove PCI devices that are not responding.
  * @dev: PCI device to start walking the hierarchy from.
@@ -745,7 +756,7 @@ static void trim_stale_devices(struct pci_dev *dev)
 		unsigned long long sta;
 
 		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-		alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
+		alive = (ACPI_SUCCESS(status) && device_sta_valid(sta))
 			|| acpiphp_no_hotplug(handle);
 	}
 	if (!alive) {
@@ -792,7 +803,7 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
 		mutex_lock(&slot->crit_sect);
 		if (slot_no_hotplug(slot)) {
 			; /* do nothing */
-		} else if (get_slot_status(slot) == ACPI_STA_ALL) {
+		} else if (device_sta_valid(get_slot_status(slot))) {
 			/* remove stale devices if any */
 			list_for_each_entry_safe_reverse(dev, tmp,
 							 &bus->devices, bus_list)

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help