From: Lina Iyer <ilina@codeaurora.org>
To: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Ulf Hansson <ulf.hansson@linaro.org>,
"Rafael J. Wysocki" <rjw@rjwysocki.net>,
Linux PM <linux-pm@vger.kernel.org>,
linux-arm-msm <linux-arm-msm@vger.kernel.org>
Subject: Re: [PATCH v4 2/2] PM / Domains: use device's next wakeup to determine domain idle state
Date: Thu, 5 Nov 2020 12:29:07 -0700 [thread overview]
Message-ID: <20201105192907.GB2526@codeaurora.org> (raw)
In-Reply-To: <CAJZ5v0gTA=_QOFJLMCxH+CqfDFKUJU5ZbpN2+DHLTP1gKg3HQg@mail.gmail.com>
Thanks for your time Rafael.
On Thu, Nov 05 2020 at 11:56 -0700, Rafael J. Wysocki wrote:
>On Tue, Oct 20, 2020 at 8:05 PM Lina Iyer <ilina@codeaurora.org> wrote:
>>
>> Currently, a PM domain's idle state is determined based on whether the
>> QoS requirements are met. This may not save power, if the idle state
>> residency requirements are not met.
>>
>> CPU PM domains use the next timer wakeup for the CPUs in the domain to
>> determine the sleep duration of the domain. This is compared with the
>> idle state residencies to determine the optimal idle state. For other PM
>> domains, determining the sleep length is not that straight forward. But
>> if the device's next_event is available, we can use that to determine
>> the sleep duration of the PM domain.
>>
>> Let's update the domain governor logic to check for idle state residency
>> based on the next wakeup of devices as well as QoS constraints.
>>
>> Signed-off-by: Lina Iyer <ilina@codeaurora.org>
>
>A few nits follow.
>
>> ---
>> Changes in v4:
>> - Update to use next_wakeup from struct generic_pm_domain_data.
>> Changes in v3:
>> - None
>> Changes in v2:
>> - Fix state_idx type to hold negative value.
>> - Update commit text.
>> ---
>> drivers/base/power/domain_governor.c | 84 ++++++++++++++++++++++++++--
>> include/linux/pm_domain.h | 1 +
>> 2 files changed, 80 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
>> index 490ed7deb99a..092927b60dc0 100644
>> --- a/drivers/base/power/domain_governor.c
>> +++ b/drivers/base/power/domain_governor.c
>> @@ -117,6 +117,49 @@ static bool default_suspend_ok(struct device *dev)
>> return td->cached_suspend_ok;
>> }
>>
>> +static void update_domain_next_wakeup(struct generic_pm_domain *genpd, ktime_t now)
>> +{
>> + ktime_t domain_wakeup = KTIME_MAX;
>> + ktime_t next_wakeup;
>> + struct pm_domain_data *pdd;
>> + struct gpd_link *link;
>> +
>> + /* Find the earliest wakeup for all devices in the domain */
>> + list_for_each_entry(pdd, &genpd->dev_list, list_node) {
>> + next_wakeup = to_gpd_data(pdd)->next_wakeup;
>> + if (next_wakeup != KTIME_MAX && !ktime_before(next_wakeup, now))
>> + if (ktime_before(next_wakeup, domain_wakeup))
>> + domain_wakeup = next_wakeup;
>> + }
>> +
>> + /* Then find the earliest wakeup of from all the child domains */
>> + list_for_each_entry(link, &genpd->parent_links, parent_node) {
>> + next_wakeup = link->child->next_wakeup;
>> + if (next_wakeup != KTIME_MAX && !ktime_before(next_wakeup, now))
>> + if (ktime_before(next_wakeup, domain_wakeup))
>> + domain_wakeup = next_wakeup;
>> + }
>
>This is assuming that the lists will remain stable during the walks
>above, but is that guaranteed?
>
I would expect so. We are looking up the child domains, which should be
powered down and therefore their domain::next_wakeup should be locked in
(because we update next_wakeup only in this governor).
>> +
>> + genpd->next_wakeup = domain_wakeup;
>> +}
>> +
>> +static bool next_wakeup_allows_state(struct generic_pm_domain *genpd,
>> + unsigned int state, ktime_t now)
>> +{
>> + s64 idle_time_ns, min_sleep_ns;
>> + ktime_t domain_wakeup = genpd->next_wakeup;
>
>I'd move the second line to the top (it looks odd now IMO).
>
I agree and prefer that as well but I missed this.
Will update in the next spin.
>> +
>> + min_sleep_ns = genpd->states[state].power_off_latency_ns +
>> + genpd->states[state].power_on_latency_ns +
>> + genpd->states[state].residency_ns;
>> +
>> + idle_time_ns = ktime_to_ns(ktime_sub(domain_wakeup, now));
>> + if (idle_time_ns < min_sleep_ns)
>> + return false;
>> +
>> + return true;
>
>Why not
>
>+ return idle_time_ns >= min_sleep_ns;
>
OK.
>> +}
>> +
>> static bool __default_power_down_ok(struct dev_pm_domain *pd,
>> unsigned int state)
>> {
>> @@ -210,6 +253,33 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
>> {
>> struct generic_pm_domain *genpd = pd_to_genpd(pd);
>> struct gpd_link *link;
>> + int state_idx;
>
>Why not initialize it right away?
>
OK.
Thanks,
Lina
>> + ktime_t now = ktime_get();
>> +
>> + /*
>> + * Find the next wakeup from devices that can determine their own wakeup
>> + * to find when the domain would wakeup and do it for every device down
>> + * the hierarchy. It is not worth while to sleep if the state's residency
>> + * cannot be met.
>> + */
>> + update_domain_next_wakeup(genpd, now);
>> + state_idx = genpd->state_count - 1;
>> + if (genpd->next_wakeup != KTIME_MAX) {
>> + /* Let's find out the deepest domain idle state, the devices prefer */
>> + while (state_idx >= 0) {
>> + if (next_wakeup_allows_state(genpd, state_idx, now)) {
>> + genpd->max_off_time_changed = true;
>> + break;
>> + }
>> + state_idx--;
>> + }
>> +
>> + if (state_idx < 0) {
>> + state_idx = 0;
>> + genpd->cached_power_down_ok = false;
>> + goto done;
>> + }
>> + }
>>
>> if (!genpd->max_off_time_changed) {
>> genpd->state_idx = genpd->cached_power_down_state_idx;
>> @@ -228,17 +298,21 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
>> genpd->max_off_time_ns = -1;
>> genpd->max_off_time_changed = false;
>> genpd->cached_power_down_ok = true;
>> - genpd->state_idx = genpd->state_count - 1;
>>
>> - /* Find a state to power down to, starting from the deepest. */
>> - while (!__default_power_down_ok(pd, genpd->state_idx)) {
>> - if (genpd->state_idx == 0) {
>> + /*
>> + * Find a state to power down to, starting from the state
>> + * determined by the next wakeup.
>> + */
>> + while (!__default_power_down_ok(pd, state_idx)) {
>> + if (state_idx == 0) {
>> genpd->cached_power_down_ok = false;
>> break;
>> }
>> - genpd->state_idx--;
>> + state_idx--;
>> }
>>
>> +done:
>> + genpd->state_idx = state_idx;
>> genpd->cached_power_down_state_idx = genpd->state_idx;
>> return genpd->cached_power_down_ok;
>> }
>> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
>> index e00c77b1efd8..205b750a2e56 100644
>> --- a/include/linux/pm_domain.h
>> +++ b/include/linux/pm_domain.h
>> @@ -130,6 +130,7 @@ struct generic_pm_domain {
>> unsigned int state);
>> struct gpd_dev_ops dev_ops;
>> s64 max_off_time_ns; /* Maximum allowed "suspended" time. */
>> + ktime_t next_wakeup; /* Maintained by the domain governor */
>> bool max_off_time_changed;
>> bool cached_power_down_ok;
>> bool cached_power_down_state_idx;
>> --
prev parent reply other threads:[~2020-11-05 19:29 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-20 18:04 [PATCH v4 0/2] Better domain idle from device wakeup patterns Lina Iyer
2020-10-20 18:04 ` [PATCH v4 1/2] PM / domains: inform PM domain of a device's next wakeup Lina Iyer
2020-11-06 10:39 ` Ulf Hansson
2020-10-20 18:04 ` [PATCH v4 2/2] PM / Domains: use device's next wakeup to determine domain idle state Lina Iyer
2020-11-05 18:56 ` Rafael J. Wysocki
2020-11-05 19:29 ` Lina Iyer [this message]
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=20201105192907.GB2526@codeaurora.org \
--to=ilina@codeaurora.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=rjw@rjwysocki.net \
--cc=ulf.hansson@linaro.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).