SDIO reset interferes with a SDIO function driver's restore from hibernation. Set MMC_CAP2_NO_SDIO_RESET if a child node has _S4W method which indicates a capability to wake from S4 (hibernate). Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> --- drivers/mmc/host/sdhci-pci-core.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 57d6f50b73dc..cc9fc7d54570 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -597,11 +597,42 @@ static int ni_set_max_freq(struct sdhci_pci_slot *slot) return 0; } + +static bool __sdhci_pci_child_has_s4w(struct acpi_device *child) +{ + acpi_handle handle = child->handle; + unsigned long long ret; + + return ACPI_SUCCESS(acpi_evaluate_integer(handle, "_S4W", NULL, &ret)); +} + +static bool sdhci_pci_child_has_s4w(struct sdhci_pci_slot *slot) +{ + struct acpi_device *adev = ACPI_COMPANION(&slot->chip->pdev->dev); + struct acpi_device *child; + bool child_has_s4w = false; + + if (!adev) + return false; + + list_for_each_entry(child, &adev->children, node) + if (child->status.present && child->status.enabled) { + if (__sdhci_pci_child_has_s4w(child)) + child_has_s4w = true; + } + + return child_has_s4w; +} #else static inline int ni_set_max_freq(struct sdhci_pci_slot *slot) { return 0; } + +static bool sdhci_pci_child_has_s4w(struct sdhci_pci_slot *slot) +{ + return false; +} #endif static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot) @@ -1960,6 +1991,9 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( host->ioaddr = pcim_iomap_table(pdev)[bar]; + if (sdhci_pci_child_has_s4w(slot)) + host->mmc->caps2 |= MMC_CAP2_NO_SDIO_RESET; + if (chip->fixes && chip->fixes->probe_slot) { ret = chip->fixes->probe_slot(slot); if (ret) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html