From: "Li, Aubrey" <aubrey.li@linux.intel.com>
To: "Rafael J. Wysocki" <rjw@rjwysocki.net>,
Linux PM list <linux-pm@vger.kernel.org>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Daniel Lezcano <daniel.lezcano@linaro.org>,
Zhang Rui <rui.zhang@intel.com>, Aubrey Li <aubrey.li@intel.com>
Subject: Re: [PATCH] PM / suspend: Always use deepest C-state in the "freeze" sleep state
Date: Mon, 05 May 2014 20:46:20 +0800 [thread overview]
Message-ID: <5367881C.6000104@linux.intel.com> (raw)
In-Reply-To: <2548502.zJ1no3NhRc@vostro.rjw.lan>
On 2014/5/5 6:51, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> If freeze_enter() is called, we want to bypass the current cpuidle
> governor and always use the deepest available (that is, not disabled)
> C-state, because we want to save as much energy as reasonably possible
> then and runtime latency constraints don't matter at that point, since
> the system is in a sleep state anyway.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>
> This is on top of https://patchwork.kernel.org/patch/4071541/ .
>
> ---
> drivers/cpuidle/cpuidle.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
> include/linux/cpuidle.h | 2 ++
> kernel/power/suspend.c | 2 ++
> 3 files changed, 48 insertions(+), 1 deletion(-)
>
> Index: linux-pm/drivers/cpuidle/cpuidle.c
> ===================================================================
> --- linux-pm.orig/drivers/cpuidle/cpuidle.c
> +++ linux-pm/drivers/cpuidle/cpuidle.c
> @@ -32,6 +32,7 @@ LIST_HEAD(cpuidle_detected_devices);
> static int enabled_devices;
> static int off __read_mostly;
> static int initialized __read_mostly;
> +static bool use_deepest_state __read_mostly;
>
> int cpuidle_disabled(void)
> {
> @@ -65,6 +66,45 @@ int cpuidle_play_dead(void)
> }
>
> /**
> + * cpuidle_use_deepest_state - Enable/disable the "deepest idle" mode.
> + * @enable: Whether enable or disable the feature.
> + *
> + * If the "deepest idle" mode is enabled, cpuidle will ignore the governor and
> + * always use the state with the greatest exit latency (out of the states that
> + * are not disabled).
> + *
> + * This function can only be called after cpuidle_pause() to avoid races.
> + */
> +void cpuidle_use_deepest_state(bool enable)
> +{
> + use_deepest_state = enable;
> +}
> +
> +/**
> + * cpuidle_find_deepest_state - Find the state of the greatest exit latency.
> + * @drv: cpuidle driver for a given CPU.
> + * @dev: cpuidle device for a given CPU.
> + */
> +static int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
> + struct cpuidle_device *dev)
> +{
> + unsigned int latency_req = 0;
> + int i, ret = CPUIDLE_DRIVER_STATE_START - 1;
> +
> + for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
> + struct cpuidle_state *s = &drv->states[i];
> + struct cpuidle_state_usage *su = &dev->states_usage[i];
> +
> + if (s->disabled || su->disable || s->exit_latency <= latency_req)
> + continue;
> +
> + latency_req = s->exit_latency;
> + ret = i;
> + }
> + return ret;
> +}
> +
> +/**
> * cpuidle_enter_state - enter the state and update stats
> * @dev: cpuidle device for this cpu
> * @drv: cpuidle driver for this cpu
> @@ -124,6 +164,9 @@ int cpuidle_select(struct cpuidle_driver
> if (!drv || !dev || !dev->enabled)
> return -EBUSY;
>
> + if (unlikely(use_deepest_state))
> + return cpuidle_find_deepest_state(drv, dev);
> +
> return cpuidle_curr_governor->select(drv, dev);
> }
>
> @@ -155,7 +198,7 @@ int cpuidle_enter(struct cpuidle_driver
> */
> void cpuidle_reflect(struct cpuidle_device *dev, int index)
> {
> - if (cpuidle_curr_governor->reflect)
> + if (cpuidle_curr_governor->reflect && !unlikely(use_deepest_state))
> cpuidle_curr_governor->reflect(dev, index);
> }
>
> Index: linux-pm/include/linux/cpuidle.h
> ===================================================================
> --- linux-pm.orig/include/linux/cpuidle.h
> +++ linux-pm/include/linux/cpuidle.h
> @@ -143,6 +143,7 @@ extern void cpuidle_resume(void);
> extern int cpuidle_enable_device(struct cpuidle_device *dev);
> extern void cpuidle_disable_device(struct cpuidle_device *dev);
> extern int cpuidle_play_dead(void);
> +extern void cpuidle_use_deepest_state(bool enable);
>
> extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
> #else
> @@ -175,6 +176,7 @@ static inline int cpuidle_enable_device(
> {return -ENODEV; }
> static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
> static inline int cpuidle_play_dead(void) {return -ENODEV; }
> +static inline void cpuidle_use_deepest_state(bool enable) {}
> static inline struct cpuidle_driver *cpuidle_get_cpu_driver(
> struct cpuidle_device *dev) {return NULL; }
> #endif
> Index: linux-pm/kernel/power/suspend.c
> ===================================================================
> --- linux-pm.orig/kernel/power/suspend.c
> +++ linux-pm/kernel/power/suspend.c
> @@ -54,9 +54,11 @@ static void freeze_begin(void)
>
> static void freeze_enter(void)
> {
> + cpuidle_use_deepest_state(true);
> cpuidle_resume();
> wait_event(suspend_freeze_wait_head, suspend_freeze_wake);
> cpuidle_pause();
> + cpuidle_use_deepest_state(false);
> }
>
> void freeze_wake(void)
>
Tested-by: Aubrey Li <aubrey.li@linux.intel.com>
I tested freeze mode on ASUS-T100, it works as expected. Thanks Rafael!
-Aubrey
next prev parent reply other threads:[~2014-05-05 12:46 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-04 22:51 [PATCH] PM / suspend: Always use deepest C-state in the "freeze" sleep state Rafael J. Wysocki
2014-05-05 12:46 ` Li, Aubrey [this message]
2014-05-09 7:38 ` Pavel Machek
2014-05-09 11:26 ` Rafael J. Wysocki
2014-05-09 14:13 ` Pavel Machek
2014-05-09 21:25 ` Rafael J. Wysocki
2014-05-12 14:08 ` Daniel Lezcano
2014-05-12 14:19 ` Li, Aubrey
2014-05-12 14:52 ` Daniel Lezcano
2014-05-12 23:53 ` Rafael J. Wysocki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5367881C.6000104@linux.intel.com \
--to=aubrey.li@linux.intel.com \
--cc=aubrey.li@intel.com \
--cc=daniel.lezcano@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=rjw@rjwysocki.net \
--cc=rui.zhang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.