[V2,3/4] mmc: slot-gpio: Add a function to enable/disable card detect IRQ wakeup
diff mbox

Message ID 1518612992-4951-4-git-send-email-adrian.hunter@intel.com
State New
Headers show

Commit Message

Adrian Hunter Feb. 14, 2018, 12:56 p.m. UTC
Commit 03dbaa04a2e5 ("mmc: slot-gpio: Add support to enable irq wake on
cd_irq") enabled wakeup irrespective of the host controller's PM flags.
However, users also want to control it from sysfs power/wakeup attribute.
That means the driver needs to check the PM flags before enabling it in the
suspend callback. Add helper function mmc_gpio_set_cd_wake() to make it
easy for drivers to do that.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/mmc/core/core.c       |  3 +--
 drivers/mmc/core/slot-gpio.c  | 23 +++++++++++++++++++++++
 include/linux/mmc/slot-gpio.h |  1 +
 3 files changed, 25 insertions(+), 2 deletions(-)

Comments

Ulf Hansson Feb. 27, 2018, 8:45 a.m. UTC | #1
On 14 February 2018 at 13:56, Adrian Hunter <adrian.hunter@intel.com> wrote:
> Commit 03dbaa04a2e5 ("mmc: slot-gpio: Add support to enable irq wake on
> cd_irq") enabled wakeup irrespective of the host controller's PM flags.
> However, users also want to control it from sysfs power/wakeup attribute.
> That means the driver needs to check the PM flags before enabling it in the
> suspend callback. Add helper function mmc_gpio_set_cd_wake() to make it
> easy for drivers to do that.

Depending on if device_may_wakeup() returns true to allow GPIO card
detect IRQ to be configured as a wakeup IRQ is problematic.

The reason is related to PM domains (genpd) when it checks the
dev->power.wakeup_path in system suspend. In case device_may_wakeup()
returns true, it may lead to the PM domain is kept powered during
system suspend, while in fact this may not be needed for the GPIO IRQ
to be configured as wakeup (because the SoC have external HW logic to
deal with wakeup IRQs).

So I can't apply this, until we have a solution of how to deal with
the above situation and I have been working on that. According to the
latest discussions [1], between me and Rafael, it seems like the
solution must also take runtime PM wakeups into account.

Or perhaps you have some other ideas of how we can move forward?

>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
>  drivers/mmc/core/core.c       |  3 +--
>  drivers/mmc/core/slot-gpio.c  | 23 +++++++++++++++++++++++
>  include/linux/mmc/slot-gpio.h |  1 +
>  3 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index c0ba6d8823b7..7bed23c877de 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -2655,8 +2655,7 @@ void mmc_start_host(struct mmc_host *host)
>  void mmc_stop_host(struct mmc_host *host)
>  {
>         if (host->slot.cd_irq >= 0) {
> -               if (host->slot.cd_wake_enabled)
> -                       disable_irq_wake(host->slot.cd_irq);
> +               mmc_gpio_set_cd_wake(host, false);
>                 disable_irq(host->slot.cd_irq);
>         }
>
> diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
> index 3698b0576009..817d668aae34 100644
> --- a/drivers/mmc/core/slot-gpio.c
> +++ b/drivers/mmc/core/slot-gpio.c
> @@ -154,6 +154,29 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host)
>  }
>  EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
>
> +int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on)
> +{
> +       int ret = 0;
> +
> +       if (!(host->caps & MMC_CAP_CD_WAKE) ||
> +           host->slot.cd_irq < 0 ||
> +           on == host->slot.cd_wake_enabled)
> +               return 0;
> +
> +       if (on) {
> +               if (device_may_wakeup(mmc_dev(host))) {
> +                       ret = enable_irq_wake(host->slot.cd_irq);
> +                       host->slot.cd_wake_enabled = !ret;
> +               }
> +       } else {
> +               disable_irq_wake(host->slot.cd_irq);
> +               host->slot.cd_wake_enabled = false;
> +       }
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL(mmc_gpio_set_cd_wake);
> +
>  /* Register an alternate interrupt service routine for
>   * the card-detect GPIO.
>   */
> diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
> index 91f1ba0663c8..06607c59c4d0 100644
> --- a/include/linux/mmc/slot-gpio.h
> +++ b/include/linux/mmc/slot-gpio.h
> @@ -31,6 +31,7 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
>                          unsigned int debounce, bool *gpio_invert);
>  void mmc_gpio_set_cd_isr(struct mmc_host *host,
>                          irqreturn_t (*isr)(int irq, void *dev_id));
> +int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on);
>  void mmc_gpiod_request_cd_irq(struct mmc_host *host);
>  bool mmc_can_gpio_cd(struct mmc_host *host);
>  bool mmc_can_gpio_ro(struct mmc_host *host);
> --
> 1.9.1
>

Kind regards
Uffe

[1]
https://marc.info/?l=linux-pm&m=151689653022118&w=2
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Adrian Hunter Feb. 27, 2018, 10:06 a.m. UTC | #2
On 27/02/18 10:45, Ulf Hansson wrote:
> On 14 February 2018 at 13:56, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> Commit 03dbaa04a2e5 ("mmc: slot-gpio: Add support to enable irq wake on
>> cd_irq") enabled wakeup irrespective of the host controller's PM flags.
>> However, users also want to control it from sysfs power/wakeup attribute.
>> That means the driver needs to check the PM flags before enabling it in the
>> suspend callback. Add helper function mmc_gpio_set_cd_wake() to make it
>> easy for drivers to do that.
> 
> Depending on if device_may_wakeup() returns true to allow GPIO card
> detect IRQ to be configured as a wakeup IRQ is problematic.
> 
> The reason is related to PM domains (genpd) when it checks the
> dev->power.wakeup_path in system suspend. In case device_may_wakeup()
> returns true, it may lead to the PM domain is kept powered during
> system suspend, while in fact this may not be needed for the GPIO IRQ
> to be configured as wakeup (because the SoC have external HW logic to
> deal with wakeup IRQs).
> 
> So I can't apply this, until we have a solution of how to deal with
> the above situation and I have been working on that. According to the
> latest discussions [1], between me and Rafael, it seems like the
> solution must also take runtime PM wakeups into account.
> 
> Or perhaps you have some other ideas of how we can move forward?

What about removing device_may_wakeup() from mmc_gpio_set_cd_wake()
and leaving it to the driver (sdhci-pci) to decide whether to call
device_may_wakeup()?

> 
>>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>> ---
>>  drivers/mmc/core/core.c       |  3 +--
>>  drivers/mmc/core/slot-gpio.c  | 23 +++++++++++++++++++++++
>>  include/linux/mmc/slot-gpio.h |  1 +
>>  3 files changed, 25 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>> index c0ba6d8823b7..7bed23c877de 100644
>> --- a/drivers/mmc/core/core.c
>> +++ b/drivers/mmc/core/core.c
>> @@ -2655,8 +2655,7 @@ void mmc_start_host(struct mmc_host *host)
>>  void mmc_stop_host(struct mmc_host *host)
>>  {
>>         if (host->slot.cd_irq >= 0) {
>> -               if (host->slot.cd_wake_enabled)
>> -                       disable_irq_wake(host->slot.cd_irq);
>> +               mmc_gpio_set_cd_wake(host, false);
>>                 disable_irq(host->slot.cd_irq);
>>         }
>>
>> diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
>> index 3698b0576009..817d668aae34 100644
>> --- a/drivers/mmc/core/slot-gpio.c
>> +++ b/drivers/mmc/core/slot-gpio.c
>> @@ -154,6 +154,29 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host)
>>  }
>>  EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
>>
>> +int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on)
>> +{
>> +       int ret = 0;
>> +
>> +       if (!(host->caps & MMC_CAP_CD_WAKE) ||
>> +           host->slot.cd_irq < 0 ||
>> +           on == host->slot.cd_wake_enabled)
>> +               return 0;
>> +
>> +       if (on) {
>> +               if (device_may_wakeup(mmc_dev(host))) {
>> +                       ret = enable_irq_wake(host->slot.cd_irq);
>> +                       host->slot.cd_wake_enabled = !ret;
>> +               }
>> +       } else {
>> +               disable_irq_wake(host->slot.cd_irq);
>> +               host->slot.cd_wake_enabled = false;
>> +       }
>> +
>> +       return ret;
>> +}
>> +EXPORT_SYMBOL(mmc_gpio_set_cd_wake);
>> +
>>  /* Register an alternate interrupt service routine for
>>   * the card-detect GPIO.
>>   */
>> diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
>> index 91f1ba0663c8..06607c59c4d0 100644
>> --- a/include/linux/mmc/slot-gpio.h
>> +++ b/include/linux/mmc/slot-gpio.h
>> @@ -31,6 +31,7 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
>>                          unsigned int debounce, bool *gpio_invert);
>>  void mmc_gpio_set_cd_isr(struct mmc_host *host,
>>                          irqreturn_t (*isr)(int irq, void *dev_id));
>> +int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on);
>>  void mmc_gpiod_request_cd_irq(struct mmc_host *host);
>>  bool mmc_can_gpio_cd(struct mmc_host *host);
>>  bool mmc_can_gpio_ro(struct mmc_host *host);
>> --
>> 1.9.1
>>
> 
> Kind regards
> Uffe
> 
> [1]
> https://marc.info/?l=linux-pm&m=151689653022118&w=2
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ulf Hansson Feb. 27, 2018, 10:15 a.m. UTC | #3
On 27 February 2018 at 11:06, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 27/02/18 10:45, Ulf Hansson wrote:
>> On 14 February 2018 at 13:56, Adrian Hunter <adrian.hunter@intel.com> wrote:
>>> Commit 03dbaa04a2e5 ("mmc: slot-gpio: Add support to enable irq wake on
>>> cd_irq") enabled wakeup irrespective of the host controller's PM flags.
>>> However, users also want to control it from sysfs power/wakeup attribute.
>>> That means the driver needs to check the PM flags before enabling it in the
>>> suspend callback. Add helper function mmc_gpio_set_cd_wake() to make it
>>> easy for drivers to do that.
>>
>> Depending on if device_may_wakeup() returns true to allow GPIO card
>> detect IRQ to be configured as a wakeup IRQ is problematic.
>>
>> The reason is related to PM domains (genpd) when it checks the
>> dev->power.wakeup_path in system suspend. In case device_may_wakeup()
>> returns true, it may lead to the PM domain is kept powered during
>> system suspend, while in fact this may not be needed for the GPIO IRQ
>> to be configured as wakeup (because the SoC have external HW logic to
>> deal with wakeup IRQs).
>>
>> So I can't apply this, until we have a solution of how to deal with
>> the above situation and I have been working on that. According to the
>> latest discussions [1], between me and Rafael, it seems like the
>> solution must also take runtime PM wakeups into account.
>>
>> Or perhaps you have some other ideas of how we can move forward?
>
> What about removing device_may_wakeup() from mmc_gpio_set_cd_wake()
> and leaving it to the driver (sdhci-pci) to decide whether to call
> device_may_wakeup()?

Yes, that's would be fine for now.

[...]

Kind regards
Uffe
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c0ba6d8823b7..7bed23c877de 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2655,8 +2655,7 @@  void mmc_start_host(struct mmc_host *host)
 void mmc_stop_host(struct mmc_host *host)
 {
 	if (host->slot.cd_irq >= 0) {
-		if (host->slot.cd_wake_enabled)
-			disable_irq_wake(host->slot.cd_irq);
+		mmc_gpio_set_cd_wake(host, false);
 		disable_irq(host->slot.cd_irq);
 	}
 
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
index 3698b0576009..817d668aae34 100644
--- a/drivers/mmc/core/slot-gpio.c
+++ b/drivers/mmc/core/slot-gpio.c
@@ -154,6 +154,29 @@  void mmc_gpiod_request_cd_irq(struct mmc_host *host)
 }
 EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
 
+int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on)
+{
+	int ret = 0;
+
+	if (!(host->caps & MMC_CAP_CD_WAKE) ||
+	    host->slot.cd_irq < 0 ||
+	    on == host->slot.cd_wake_enabled)
+		return 0;
+
+	if (on) {
+		if (device_may_wakeup(mmc_dev(host))) {
+			ret = enable_irq_wake(host->slot.cd_irq);
+			host->slot.cd_wake_enabled = !ret;
+		}
+	} else {
+		disable_irq_wake(host->slot.cd_irq);
+		host->slot.cd_wake_enabled = false;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(mmc_gpio_set_cd_wake);
+
 /* Register an alternate interrupt service routine for
  * the card-detect GPIO.
  */
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
index 91f1ba0663c8..06607c59c4d0 100644
--- a/include/linux/mmc/slot-gpio.h
+++ b/include/linux/mmc/slot-gpio.h
@@ -31,6 +31,7 @@  int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
 			 unsigned int debounce, bool *gpio_invert);
 void mmc_gpio_set_cd_isr(struct mmc_host *host,
 			 irqreturn_t (*isr)(int irq, void *dev_id));
+int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on);
 void mmc_gpiod_request_cd_irq(struct mmc_host *host);
 bool mmc_can_gpio_cd(struct mmc_host *host);
 bool mmc_can_gpio_ro(struct mmc_host *host);