diff mbox

PM / sleep: Let devices force direct_complete

Message ID 1430474611-25560-1-git-send-email-tomeu.vizoso@collabora.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Tomeu Vizoso May 1, 2015, 10:03 a.m. UTC
Introduce a new per-device flag power.force_direct_complete that will
instruct the PM core to let that device remain in runtime suspend when
the system goes into a sleep power state, regardless of the PM state of
any of its descendants.

This is needed because otherwise it would be needed to get dozens of
drivers to implement the prepare() callback and be runtime PM active
even if they don't have a 1-to-1 relationship with a piece of HW.

This only applies to devices that aren't wakeup-capable, as those would
need to setup their IRQs as wakeup-capable in their prepare() callbacks.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---

Hi,

I'm sending this as a standalone patch as suggested by Alan.

Thanks,

Tomeu

---
 Documentation/power/runtime_pm.txt | 10 ++++++++++
 drivers/base/power/main.c          | 14 ++++++++++----
 include/linux/pm.h                 |  1 +
 3 files changed, 21 insertions(+), 4 deletions(-)

Comments

Alan Stern May 1, 2015, 5:24 p.m. UTC | #1
On Fri, 1 May 2015, Tomeu Vizoso wrote:

> Introduce a new per-device flag power.force_direct_complete that will
> instruct the PM core to let that device remain in runtime suspend when
> the system goes into a sleep power state, regardless of the PM state of
> any of its descendants.
> 
> This is needed because otherwise it would be needed to get dozens of
> drivers to implement the prepare() callback and be runtime PM active
> even if they don't have a 1-to-1 relationship with a piece of HW.
> 
> This only applies to devices that aren't wakeup-capable, as those would
> need to setup their IRQs as wakeup-capable in their prepare() callbacks.
> 
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> ---
> 
> Hi,
> 
> I'm sending this as a standalone patch as suggested by Alan.
> 
> Thanks,
> 
> Tomeu
> 
> ---
>  Documentation/power/runtime_pm.txt | 10 ++++++++++
>  drivers/base/power/main.c          | 14 ++++++++++----
>  include/linux/pm.h                 |  1 +
>  3 files changed, 21 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
> index 44fe1d2..3b0c68d 100644
> --- a/Documentation/power/runtime_pm.txt
> +++ b/Documentation/power/runtime_pm.txt
> @@ -665,6 +665,16 @@ as appropriate.  This only applies to system suspend transitions that are not
>  related to hibernation (see Documentation/power/devices.txt for more
>  information).
>  
> +For devices that know that can remain runtime suspended when the system
> +transitions to a sleep state regardless of the PM state of their descendants,
> +the flag power.force_direct_complete can be set on their device structures.
> +This can be useful when a real device has several virtual devices as
> +descendants and it would be very cumbersome to make sure that they return a
> +positive value in their .prepare() callback and have runtime PM enabled. Usage
> +of power.force_direct_complete is only allowed to devices that aren't
> +wakeup-capable, as they would need to set their IRQs as wakeups in their
> +.prepare() callbacks before the system transitions to a sleep state.
> +

This seems okay to me.  It specifically states that 
force_direct_complete should be used only when it is known that the PM 
states of the descendant devices don't matter.

>  The PM core does its best to reduce the probability of race conditions between
>  the runtime PM and system suspend/resume (and hibernation) callbacks by carrying
>  out the following operations:
> diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
> index 3d874ec..7b962f5 100644
> --- a/drivers/base/power/main.c
> +++ b/drivers/base/power/main.c
> @@ -1438,7 +1438,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
>  		if (parent) {
>  			spin_lock_irq(&parent->power.lock);
>  
> -			dev->parent->power.direct_complete = false;
> +			if (!dev->parent->power.force_direct_complete)
> +				dev->parent->power.direct_complete = false;
> +
>  			if (dev->power.wakeup_path
>  			    && !dev->parent->power.ignore_children)
>  				dev->parent->power.wakeup_path = true;
> @@ -1605,9 +1607,13 @@ static int device_prepare(struct device *dev, pm_message_t state)
>  	 * will do the same thing with all of its descendants".  This only
>  	 * applies to suspend transitions, however.
>  	 */
> -	spin_lock_irq(&dev->power.lock);
> -	dev->power.direct_complete = ret > 0 && state.event == PM_EVENT_SUSPEND;
> -	spin_unlock_irq(&dev->power.lock);
> +	if (state.event == PM_EVENT_SUSPEND) {
> +		spin_lock_irq(&dev->power.lock);
> +		dev->power.direct_complete = ret > 0 ||
> +			(dev->power.force_direct_complete &&
> +			 !device_can_wakeup(dev));
> +		spin_unlock_irq(&dev->power.lock);
> +	}
>  	return 0;
>  }
>  
> diff --git a/include/linux/pm.h b/include/linux/pm.h
> index 2d29c64..2e41cfd 100644
> --- a/include/linux/pm.h
> +++ b/include/linux/pm.h
> @@ -553,6 +553,7 @@ struct dev_pm_info {
>  	bool			ignore_children:1;
>  	bool			early_init:1;	/* Owned by the PM core */
>  	bool			direct_complete:1;	/* Owned by the PM core */
> +	bool			force_direct_complete:1;
>  	spinlock_t		lock;
>  #ifdef CONFIG_PM_SLEEP
>  	struct list_head	entry;

Rafael, do you think we need a setter routine that acquires the
spinlock before turning on this bit?

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kevin Hilman May 8, 2015, 8:33 p.m. UTC | #2
Tomeu Vizoso <tomeu.vizoso@collabora.com> writes:

> Introduce a new per-device flag power.force_direct_complete that will
> instruct the PM core to let that device remain in runtime suspend when
> the system goes into a sleep power state, regardless of the PM state of
> any of its descendants.
>
> This is needed because otherwise it would be needed to get dozens of
> drivers to implement the prepare() callback and be runtime PM active
> even if they don't have a 1-to-1 relationship with a piece of HW.
>
> This only applies to devices that aren't wakeup-capable, as those would
> need to setup their IRQs as wakeup-capable in their prepare() callbacks.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> ---
>
> Hi,
>
> I'm sending this as a standalone patch as suggested by Alan.
>
> Thanks,
>
> Tomeu
>
> ---
>  Documentation/power/runtime_pm.txt | 10 ++++++++++
>  drivers/base/power/main.c          | 14 ++++++++++----
>  include/linux/pm.h                 |  1 +
>  3 files changed, 21 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
> index 44fe1d2..3b0c68d 100644
> --- a/Documentation/power/runtime_pm.txt
> +++ b/Documentation/power/runtime_pm.txt
> @@ -665,6 +665,16 @@ as appropriate.  This only applies to system suspend transitions that are not
>  related to hibernation (see Documentation/power/devices.txt for more
>  information).
>  
> +For devices that know that can remain runtime suspended when the system

s/that know that/that know they/ ?

> +transitions to a sleep state regardless of the PM state of their descendants,
> +the flag power.force_direct_complete can be set on their device structures.
> +This can be useful when a real device has several virtual devices as
> +descendants and it would be very cumbersome to make sure that they return a
> +positive value in their .prepare() callback and have runtime PM enabled. Usage
> +of power.force_direct_complete is only allowed to devices that aren't
> +wakeup-capable, as they would need to set their IRQs as wakeups in their
> +.prepare() callbacks before the system transitions to a sleep state.

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 44fe1d2..3b0c68d 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -665,6 +665,16 @@  as appropriate.  This only applies to system suspend transitions that are not
 related to hibernation (see Documentation/power/devices.txt for more
 information).
 
+For devices that know that can remain runtime suspended when the system
+transitions to a sleep state regardless of the PM state of their descendants,
+the flag power.force_direct_complete can be set on their device structures.
+This can be useful when a real device has several virtual devices as
+descendants and it would be very cumbersome to make sure that they return a
+positive value in their .prepare() callback and have runtime PM enabled. Usage
+of power.force_direct_complete is only allowed to devices that aren't
+wakeup-capable, as they would need to set their IRQs as wakeups in their
+.prepare() callbacks before the system transitions to a sleep state.
+
 The PM core does its best to reduce the probability of race conditions between
 the runtime PM and system suspend/resume (and hibernation) callbacks by carrying
 out the following operations:
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 3d874ec..7b962f5 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1438,7 +1438,9 @@  static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 		if (parent) {
 			spin_lock_irq(&parent->power.lock);
 
-			dev->parent->power.direct_complete = false;
+			if (!dev->parent->power.force_direct_complete)
+				dev->parent->power.direct_complete = false;
+
 			if (dev->power.wakeup_path
 			    && !dev->parent->power.ignore_children)
 				dev->parent->power.wakeup_path = true;
@@ -1605,9 +1607,13 @@  static int device_prepare(struct device *dev, pm_message_t state)
 	 * will do the same thing with all of its descendants".  This only
 	 * applies to suspend transitions, however.
 	 */
-	spin_lock_irq(&dev->power.lock);
-	dev->power.direct_complete = ret > 0 && state.event == PM_EVENT_SUSPEND;
-	spin_unlock_irq(&dev->power.lock);
+	if (state.event == PM_EVENT_SUSPEND) {
+		spin_lock_irq(&dev->power.lock);
+		dev->power.direct_complete = ret > 0 ||
+			(dev->power.force_direct_complete &&
+			 !device_can_wakeup(dev));
+		spin_unlock_irq(&dev->power.lock);
+	}
 	return 0;
 }
 
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 2d29c64..2e41cfd 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -553,6 +553,7 @@  struct dev_pm_info {
 	bool			ignore_children:1;
 	bool			early_init:1;	/* Owned by the PM core */
 	bool			direct_complete:1;	/* Owned by the PM core */
+	bool			force_direct_complete:1;
 	spinlock_t		lock;
 #ifdef CONFIG_PM_SLEEP
 	struct list_head	entry;