diff mbox

[RFC,3/4] mmc: sdhci-acpi: Set MMC_CAP2_NO_SDIO_RESET if child has wake from S4 (hibernate)

Message ID 1492769288-7474-4-git-send-email-adrian.hunter@intel.com (mailing list archive)
State RFC, archived
Headers show

Commit Message

Adrian Hunter April 21, 2017, 10:08 a.m. UTC
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@intel.com>
---
 drivers/mmc/host/sdhci-acpi.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

Comments

Rafael J. Wysocki April 24, 2017, 9:52 p.m. UTC | #1
On Fri, Apr 21, 2017 at 12:08 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> 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@intel.com>
> ---
>  drivers/mmc/host/sdhci-acpi.c | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
> index c6a9a1bfaa22..e053a45db6b1 100644
> --- a/drivers/mmc/host/sdhci-acpi.c
> +++ b/drivers/mmc/host/sdhci-acpi.c
> @@ -374,6 +374,14 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid,
>         return NULL;
>  }
>
> +static bool sdhci_acpi_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));

First off, there is acpi_has_method().

Second, checking child->wakeup.sleep_state is a better indicator of S4
wakeup support.

> +}
> +
>  static int sdhci_acpi_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;

Thanks,
Rafael
Adrian Hunter April 25, 2017, 7:28 a.m. UTC | #2
On 25/04/17 00:52, Rafael J. Wysocki wrote:
> On Fri, Apr 21, 2017 at 12:08 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> 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@intel.com>
>> ---
>>  drivers/mmc/host/sdhci-acpi.c | 17 ++++++++++++++++-
>>  1 file changed, 16 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
>> index c6a9a1bfaa22..e053a45db6b1 100644
>> --- a/drivers/mmc/host/sdhci-acpi.c
>> +++ b/drivers/mmc/host/sdhci-acpi.c
>> @@ -374,6 +374,14 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid,
>>         return NULL;
>>  }
>>
>> +static bool sdhci_acpi_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));
> 
> First off, there is acpi_has_method().
> 
> Second, checking child->wakeup.sleep_state is a better indicator of S4
> wakeup support.

So, like this?

	child->wakeup.sleep_state >= ACPI_STATE_S4

That comes just from _PRW right?

> 
>> +}
>> +
>>  static int sdhci_acpi_probe(struct platform_device *pdev)
>>  {
>>         struct device *dev = &pdev->dev;
> 
> Thanks,
> Rafael
>
Rafael J. Wysocki April 25, 2017, 11:05 a.m. UTC | #3
On Tue, Apr 25, 2017 at 9:28 AM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 25/04/17 00:52, Rafael J. Wysocki wrote:
>> On Fri, Apr 21, 2017 at 12:08 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>> 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@intel.com>
>>> ---
>>>  drivers/mmc/host/sdhci-acpi.c | 17 ++++++++++++++++-
>>>  1 file changed, 16 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
>>> index c6a9a1bfaa22..e053a45db6b1 100644
>>> --- a/drivers/mmc/host/sdhci-acpi.c
>>> +++ b/drivers/mmc/host/sdhci-acpi.c
>>> @@ -374,6 +374,14 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid,
>>>         return NULL;
>>>  }
>>>
>>> +static bool sdhci_acpi_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));
>>
>> First off, there is acpi_has_method().
>>
>> Second, checking child->wakeup.sleep_state is a better indicator of S4
>> wakeup support.
>
> So, like this?
>
>         child->wakeup.sleep_state >= ACPI_STATE_S4
>
> That comes just from _PRW right?

It may be fixed up if the power resources in there don't match what
_PRW itself returns, but generally yes.

In any case _S4W is optional even for devices that can wake up from S4 IIRC.

Thanks,
Rafael
diff mbox

Patch

diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index c6a9a1bfaa22..e053a45db6b1 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -374,6 +374,14 @@  static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid,
 	return NULL;
 }
 
+static bool sdhci_acpi_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 int sdhci_acpi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -382,6 +390,7 @@  static int sdhci_acpi_probe(struct platform_device *pdev)
 	struct sdhci_acpi_host *c;
 	struct sdhci_host *host;
 	struct resource *iomem;
+	bool child_has_s4w = false;
 	resource_size_t len;
 	const char *hid;
 	const char *uid;
@@ -393,8 +402,11 @@  static int sdhci_acpi_probe(struct platform_device *pdev)
 	/* Power on the SDHCI controller and its children */
 	acpi_device_fix_up_power(device);
 	list_for_each_entry(child, &device->children, node)
-		if (child->status.present && child->status.enabled)
+		if (child->status.present && child->status.enabled) {
 			acpi_device_fix_up_power(child);
+			if (sdhci_acpi_child_has_s4w(child))
+				child_has_s4w = true;
+		}
 
 	if (acpi_bus_get_status(device) || !device->status.present)
 		return -ENODEV;
@@ -439,6 +451,9 @@  static int sdhci_acpi_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
+	if (child_has_s4w)
+		host->mmc->caps2 |= MMC_CAP2_NO_SDIO_RESET;
+
 	if (c->slot) {
 		if (c->slot->probe_slot) {
 			err = c->slot->probe_slot(pdev, hid, uid);