[v3,3/4] PM / wakeup: Add device_set_wakeup_path() helper to control wakeup path

Message ID 1514909333-4450-4-git-send-email-ulf.hansson@linaro.org
State Accepted
Commit cf04ce7841fabc7af0d6ee273711ec29658bee7b
Headers show
Series
  • PM / core: Extend behaviour for wakeup paths
Related show

Commit Message

Ulf Hansson Jan. 2, 2018, 4:08 p.m.
During system suspend, a driver may find that the wakeup setting is enabled
for its device and therefore configures it to deliver system wakeup
signals.

Additionally, sometimes the driver and its device, relies on some further
consumed resource, like an irqchip or a phy for example, to stay powered
on, as to be able to deliver system wakeup signals.

In general the driver deals with this, via raising an "enable count" of the
consumed resource or via a subsystem specific API, like irq_set_irq_wake()
or enable|disable_irq_wake() for an irqchip. However, this may not be
sufficient in cases when the resource's device may be attached to a PM
domain (genpd for example) or is attached to a non-trivial middle layer
(PCI for example).

To address cases like these, the existing ->dev.power.wakeup_path status
flag is there to help. As a matter of fact, genpd already monitors the flag
during system suspend and acts accordingly.

However, so far it has not been clear, if anybody else but the PM core is
allowed to set the ->dev.power.wakeup_path status flag, which is required
to make this work. For this reason, let's introduce a new helper function,
device_set_wakeup_path().

Typically a driver that manages a resource needed in the wakeup path,
should call device_set_wakeup_path() from its ->suspend() or
->suspend_late() callback.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

---
 include/linux/pm_wakeup.h | 7 +++++++
 1 file changed, 7 insertions(+)

-- 
2.7.4

Comments

Rafael J. Wysocki Jan. 7, 2018, 11:34 p.m. | #1
On Tuesday, January 2, 2018 5:08:52 PM CET Ulf Hansson wrote:
> During system suspend, a driver may find that the wakeup setting is enabled

> for its device and therefore configures it to deliver system wakeup

> signals.

> 

> Additionally, sometimes the driver and its device, relies on some further

> consumed resource, like an irqchip or a phy for example, to stay powered

> on, as to be able to deliver system wakeup signals.

> 

> In general the driver deals with this, via raising an "enable count" of the

> consumed resource or via a subsystem specific API, like irq_set_irq_wake()

> or enable|disable_irq_wake() for an irqchip. However, this may not be

> sufficient in cases when the resource's device may be attached to a PM

> domain (genpd for example) or is attached to a non-trivial middle layer

> (PCI for example).

> 

> To address cases like these, the existing ->dev.power.wakeup_path status

> flag is there to help. As a matter of fact, genpd already monitors the flag

> during system suspend and acts accordingly.

> 

> However, so far it has not been clear, if anybody else but the PM core is

> allowed to set the ->dev.power.wakeup_path status flag, which is required

> to make this work. For this reason, let's introduce a new helper function,

> device_set_wakeup_path().

> 

> Typically a driver that manages a resource needed in the wakeup path,

> should call device_set_wakeup_path() from its ->suspend() or

> ->suspend_late() callback.

> 

> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

> ---

>  include/linux/pm_wakeup.h | 7 +++++++

>  1 file changed, 7 insertions(+)

> 

> diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h

> index 4c2cba7..4238dde 100644

> --- a/include/linux/pm_wakeup.h

> +++ b/include/linux/pm_wakeup.h

> @@ -88,6 +88,11 @@ static inline bool device_may_wakeup(struct device *dev)

>  	return dev->power.can_wakeup && !!dev->power.wakeup;

>  }

>  

> +static inline void device_set_wakeup_path(struct device *dev)

> +{

> +	dev->power.wakeup_path = true;

> +}

> +

>  /* drivers/base/power/wakeup.c */

>  extern void wakeup_source_prepare(struct wakeup_source *ws, const char *name);

>  extern struct wakeup_source *wakeup_source_create(const char *name);

> @@ -174,6 +179,8 @@ static inline bool device_may_wakeup(struct device *dev)

>  	return dev->power.can_wakeup && dev->power.should_wakeup;

>  }

>  

> +static inline void device_set_wakeup_path(struct device *dev) {}

> +

>  static inline void __pm_stay_awake(struct wakeup_source *ws) {}

>  

>  static inline void pm_stay_awake(struct device *dev) {}

> 


Applied, thanks!

Patch

diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
index 4c2cba7..4238dde 100644
--- a/include/linux/pm_wakeup.h
+++ b/include/linux/pm_wakeup.h
@@ -88,6 +88,11 @@  static inline bool device_may_wakeup(struct device *dev)
 	return dev->power.can_wakeup && !!dev->power.wakeup;
 }
 
+static inline void device_set_wakeup_path(struct device *dev)
+{
+	dev->power.wakeup_path = true;
+}
+
 /* drivers/base/power/wakeup.c */
 extern void wakeup_source_prepare(struct wakeup_source *ws, const char *name);
 extern struct wakeup_source *wakeup_source_create(const char *name);
@@ -174,6 +179,8 @@  static inline bool device_may_wakeup(struct device *dev)
 	return dev->power.can_wakeup && dev->power.should_wakeup;
 }
 
+static inline void device_set_wakeup_path(struct device *dev) {}
+
 static inline void __pm_stay_awake(struct wakeup_source *ws) {}
 
 static inline void pm_stay_awake(struct device *dev) {}