From patchwork Fri Apr 24 17:35:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Axel Haslam X-Patchwork-Id: 6272631 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 3A0959F313 for ; Fri, 24 Apr 2015 17:35:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7E3CB20381 for ; Fri, 24 Apr 2015 17:35:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6C8F520386 for ; Fri, 24 Apr 2015 17:35:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966637AbbDXRfp (ORCPT ); Fri, 24 Apr 2015 13:35:45 -0400 Received: from mail-wi0-f170.google.com ([209.85.212.170]:36500 "EHLO mail-wi0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S966362AbbDXRfo (ORCPT ); Fri, 24 Apr 2015 13:35:44 -0400 Received: by wizk4 with SMTP id k4so30404912wiz.1 for ; Fri, 24 Apr 2015 10:35:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=cdEugQZ5PKyXWn01n6C2MksvLApf5GM+fewK4nkSXGs=; b=MJyJyzZJzOSyKPsaz4lvWW2YTGYByTbU4vXS+ibn6jK0gPU/vpkmZ7f4zXnfiDsDSd EL8DrOjiOCNtm6UkKNIiPR2bWF8zj5vSnyhh1yUcKEVXvnqtAuQWEry+w/ddEXf4xUEF RoIBzFNODaJkOx+5yPuZii9ygPMmzaiNK+jM8uiuAVIvj21zX5qEMJkdbienDb4HNjx6 HYbak9Yb2d6SoxY/UiFsdexq0CNp6LJ+i2mF8GWuZKIE2OljVCuD22hm7flpQRirp/vP 3tAXCG4DMveeOcyhlN27ZnN44Bkcf3BaHE6e4MlJYttv52pfEgruX7ravkGsa4gWmS5B P80g== X-Gm-Message-State: ALoCoQm+VwfE4Igm9Ao0xDQqCDC0r5dqdBlss02KpfShDw1/WbQJ/+YiQbKh3PNQrtry1/RLmoVy X-Received: by 10.180.37.207 with SMTP id a15mr5807087wik.2.1429896943548; Fri, 24 Apr 2015 10:35:43 -0700 (PDT) Received: from axelh-ThinkPad-T440s.home (LPoitiers-656-1-62-228.w90-63.abo.wanadoo.fr. [90.63.143.228]) by mx.google.com with ESMTPSA id n3sm177488wix.1.2015.04.24.10.35.41 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 24 Apr 2015 10:35:42 -0700 (PDT) From: ahaslam@baylibre.com To: ulf.hansson@linaro.org, khilman@linaro.org, k.kozlowski.k@gmail.com, geert@linux-m68k.org, rjw@rjwysocki.net Cc: bcousson@baylibre.com, linux-pm@vger.kernel.org, Axel Haslam Subject: [RFC v5 2/8] PM / Domains: select deepest state Date: Fri, 24 Apr 2015 19:35:18 +0200 Message-Id: <1429896924-21540-3-git-send-email-ahaslam@baylibre.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1429896924-21540-1-git-send-email-ahaslam@baylibre.com> References: <1429896924-21540-1-git-send-email-ahaslam@baylibre.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Axel Haslam now that the structures of genpd can support multiple state definitions, add the logic in the governor to select the deepest possible state when powering down. For this, create the new function power_down_ok_for_state which will test if a particular state will not violate the devices and sub-domains constraints. default_power_down_ok is modified to try each state starting from the deepest until a valid state is found or there are no more states to test. the resulting state will be valid until there are latency or constraint changes, thus, we can avoid looping every power_down, and use the cached results instead. Signed-off-by: Axel Haslam --- drivers/base/power/domain_governor.c | 77 ++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 9d74885..061c711 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c @@ -97,7 +97,7 @@ static bool default_stop_ok(struct device *dev) * * This routine must be executed under the PM domain's lock. */ -static bool default_power_down_ok(struct dev_pm_domain *pd) +static bool power_down_ok_for_state(struct dev_pm_domain *pd, int state) { struct generic_pm_domain *genpd = pd_to_genpd(pd); struct gpd_link *link; @@ -105,31 +105,12 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) s64 min_off_time_ns; s64 off_on_time_ns; - if (genpd->max_off_time_changed) { - struct gpd_link *link; - - /* - * We have to invalidate the cached results for the masters, so - * use the observation that default_power_down_ok() is not - * going to be called for any master until this instance - * returns. - */ - list_for_each_entry(link, &genpd->slave_links, slave_node) - link->master->max_off_time_changed = true; - - genpd->max_off_time_changed = false; - genpd->cached_power_down_ok = false; - genpd->max_off_time_ns = -1; - } else { - return genpd->cached_power_down_ok; - } - if (genpd->state_count == 0) off_on_time_ns = genpd->power_off_latency_ns + genpd->power_on_latency_ns; else - off_on_time_ns = genpd->states[0].power_off_latency_ns + - genpd->states[0].power_on_latency_ns; + off_on_time_ns = genpd->states[state].power_off_latency_ns + + genpd->states[state].power_on_latency_ns; /* * It doesn't make sense to remove power from the domain if saving * the state of all devices in it and the power off/power on operations @@ -205,8 +186,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) min_off_time_ns = constraint_ns; } - genpd->cached_power_down_ok = true; - /* * If the computed minimum device off time is negative, there are no * latency constraints, so the domain can spend arbitrary time in the @@ -225,10 +204,58 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) min_off_time_ns - genpd->power_on_latency_ns; else genpd->max_off_time_ns = min_off_time_ns - - genpd->states[0].power_on_latency_ns; + genpd->states[state].power_on_latency_ns; return true; } +static bool default_power_down_ok(struct dev_pm_domain *pd) +{ + struct generic_pm_domain *genpd = pd_to_genpd(pd); + int last_state_idx = genpd->state_count - 1; + struct gpd_link *link; + bool retval = false; + int i; + + /* + * if there was no change on max_off_time, we can return the + * cached value and we dont need to find a new target_state + */ + if (!genpd->max_off_time_changed) + return genpd->cached_power_down_ok; + + /* + * We have to invalidate the cached results for the masters, so + * use the observation that default_power_down_ok() is not + * going to be called for any master until this instance + * returns. + */ + list_for_each_entry(link, &genpd->slave_links, slave_node) + link->master->max_off_time_changed = true; + + genpd->max_off_time_ns = -1; + genpd->max_off_time_changed = false; + + /* find a state to power down to, starting from the deepest */ + if (genpd->state_count == 0) { + /* + * there are no states. power_down_ok_for_state will use + * the stateless values, and ignore the state argument. + */ + retval = power_down_ok_for_state(pd, 0); + } else { + for (i = 0; i < genpd->state_count; i++) { + if (power_down_ok_for_state(pd, last_state_idx - i)) { + genpd->state_idx = last_state_idx - i; + retval = true; + break; + } + } + } + + genpd->cached_power_down_ok = retval; + return retval; +} + static bool always_on_power_down_ok(struct dev_pm_domain *domain) { return false;