From patchwork Fri Dec 14 10:15:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 153809 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp1881907ljp; Fri, 14 Dec 2018 02:16:03 -0800 (PST) X-Google-Smtp-Source: AFSGD/V3B2ESIAJHoCjEqpF5fpH4EQP7e721rFy1iXnoZWtHPWvF953i6ThF9J2uRZQcV5AmsdEg X-Received: by 2002:a63:7d06:: with SMTP id y6mr2137136pgc.171.1544782563722; Fri, 14 Dec 2018 02:16:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544782563; cv=none; d=google.com; s=arc-20160816; b=CJEN5OTpIKQicoqobyPF6sGfym1/2Y+EzUK9C7G0RUNdo6BW0mtOaDhvrmxp7JrM3i gLc8fiMk3pb7tO/RTyyH8RRgyS07ff2qkT1Tx97xFHOmfXYLbyuKOy5J+OrtJ7kd12vZ I3Rgg657US7dJzLHFZLn/f/Lqq34ovDvazFcd0zpIG58bwYp9Glh5d417lIixiUABjGM n46CNmuGfhTlo0jgMZk6ST6ZSMpGKqLtVvQaCykRs3WLo3fZko84epPgz2kZzPWb3UUL gbSjdVgcuIvdIetTFSwIN1J8jGlP9uFeWv16cnaHyrsyEujyGOsQQ0fUAM0fXwNJbeYc wb1g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=GuwS/J0VRMUUsTtu4AOCAiCLWgTA0AmO9JSD70SaiQk=; b=CAceHI37aWSuwsp1Hhh/67cMlWibYiFZyP9PbWBkFveWN6ad90LAR6gP4hhVMbXrvp kz/2rTNsoOY3rAfS6xl+58s+/XYf1W0oL3W8SmgXvsUD3VgckEu1PYck4nJYUrrKvcCL dqZz9+6NtcaZYa4rK0WPU8k2ki6we3OUjeHDvIwY7Pwd0hw1o8F2EiRVFH5e/rFozMbI IV+BeywPGKCIu8R+dPNRQt51G2CcQXPCDeRyPC2WbZe3Po6t5AnBJq9szP2mt/ffy66k AtcjVAyzcq1Xxc1X8ROZCrc86AJ2cPm2SzLXG4YJ7B7w7BynGfSlZY1pNdWpkaHmRvmo Mb2w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VU1LNQg1; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r77si3710707pfa.186.2018.12.14.02.16.03; Fri, 14 Dec 2018 02:16:03 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VU1LNQg1; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729657AbeLNKQC (ORCPT + 31 others); Fri, 14 Dec 2018 05:16:02 -0500 Received: from mail-pg1-f194.google.com ([209.85.215.194]:32856 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729624AbeLNKP7 (ORCPT ); Fri, 14 Dec 2018 05:15:59 -0500 Received: by mail-pg1-f194.google.com with SMTP id z11so2516759pgu.0 for ; Fri, 14 Dec 2018 02:15:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GuwS/J0VRMUUsTtu4AOCAiCLWgTA0AmO9JSD70SaiQk=; b=VU1LNQg12XoWRQsPmxfL2kqW9a5aUSOuaM2mQcAPorUuaHGO6YvNZVCmjqU9i/eIIt fs03GzcarocK5NeZkre3RGce7WeMcgRK0kk7eibnfwWd94CwOM0f1wrqf7d+AERTsp20 9EoLFoKTwcEyNhvJThmwovtYTS3qutHGRdjTM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GuwS/J0VRMUUsTtu4AOCAiCLWgTA0AmO9JSD70SaiQk=; b=EJ0BKhvesBgFFbLZ4hmMe9ksnf6wTnhe7+EYpr96v8zWDTauu/udctmBta8/T+E/2K F3cq3uVm8Fv6yF+atgAbb4c3D1sOg64Ja8q9HqFbgt30/eRavLRbjK7V9KlNPIRHArvM 9mwovIA4F54xqZMueAiaOsp4hOeaIpVr4QC44oytEcWylZLm3RHwU37vt1VkYRwzF6Pt 5D8mzA7wK4QKMVk17wFW3rrgkeHR+kFACuvxYuxhVCXcw7rZLljt/7VSmSW36EXtwxe8 EI7+gTq4oxzEtd/LgvSf7C7qFB6zVQopq1VCu2WkpsIZ+KgIm77YdBebO7rk75A9BiTg 1PMQ== X-Gm-Message-State: AA+aEWYKeKK2cXw9fnV4MII7Mkk4dz9V1HsRkSYV86IMJFyB5zvxgrIC Prnbp3j2b/VrfrGUOeX9fd/ik3Grb+A= X-Received: by 2002:a65:4142:: with SMTP id x2mr2117023pgp.356.1544782559125; Fri, 14 Dec 2018 02:15:59 -0800 (PST) Received: from localhost ([122.172.23.29]) by smtp.gmail.com with ESMTPSA id b4sm4870265pgq.65.2018.12.14.02.15.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Dec 2018 02:15:58 -0800 (PST) From: Viresh Kumar To: ulf.hansson@linaro.org, Rafael Wysocki , Kevin Hilman , Len Brown , Pavel Machek Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Stephen Boyd , Nishanth Menon , rnayak@codeaurora.org, niklas.cassel@linaro.org, linux-kernel@vger.kernel.org Subject: [PATCH V4 7/7] PM / Domains: Propagate performance state updates Date: Fri, 14 Dec 2018 15:45:33 +0530 Message-Id: <0c7ef1300e212f0ae06ccf10398f8c9453c064a5.1544782279.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.19.1.568.g152ad8e3369a In-Reply-To: References: MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently a genpd only handles the performance state requirements from the devices under its control. This commit extends that to also handle the performance state requirement(s) put on the master genpd by its sub-domains. There is a separate value required for each master that the genpd has and so a new field is added to the struct gpd_link (link->performance_state), which represents the link between a genpd and its master. The struct gpd_link also got another field prev_performance_state, which is used by genpd core as a temporary variable during transitions. On a call to dev_pm_genpd_set_performance_state(), the genpd core first updates the performance state of the masters of the device's genpd and then updates the performance state of the genpd. The masters do the same and propagate performance state updates to their masters before updating their own. The performance state transition from genpd to its master is done with the help of dev_pm_opp_xlate_performance_state(), which looks at the OPP tables of both the domains to translate the state. Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/base/power/domain.c | 93 ++++++++++++++++++++++++++++++++----- include/linux/pm_domain.h | 4 ++ 2 files changed, 86 insertions(+), 11 deletions(-) -- 2.19.1.568.g152ad8e3369a Reviewed-by: Ulf Hansson diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 808ba41b6580..611c0ccbad5f 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -244,6 +244,7 @@ static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, { struct generic_pm_domain_data *pd_data; struct pm_domain_data *pdd; + struct gpd_link *link; /* New requested state is same as Max requested state */ if (state == genpd->performance_state) @@ -262,31 +263,101 @@ static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, } /* - * We aren't propagating performance state changes of a subdomain to its - * masters as we don't have hardware that needs it. Over that, the - * performance states of subdomain and its masters may not have - * one-to-one mapping and would require additional information. We can - * get back to this once we have hardware that needs it. For that - * reason, we don't have to consider performance state of the subdomains - * of genpd here. + * Traverse all sub-domains within the domain. This can be + * done without any additional locking as the link->performance_state + * field is protected by the master genpd->lock, which is already taken. + * + * Also note that link->performance_state (subdomain's performance state + * requirement to master domain) is different from + * link->slave->performance_state (current performance state requirement + * of the devices/sub-domains of the subdomain) and so can have a + * different value. + * + * Note that we also take vote from powered-off sub-domains into account + * as the same is done for devices right now. */ + list_for_each_entry(link, &genpd->master_links, master_node) { + if (link->performance_state > state) + state = link->performance_state; + } + return state; } static int _genpd_set_performance_state(struct generic_pm_domain *genpd, - unsigned int state) + unsigned int state, int depth) { - int ret; + struct generic_pm_domain *master; + struct gpd_link *link; + int master_state, ret; if (state == genpd->performance_state) return 0; + /* Propagate to masters of genpd */ + list_for_each_entry(link, &genpd->slave_links, slave_node) { + master = link->master; + + if (!master->set_performance_state) + continue; + + /* Find master's performance state */ + ret = dev_pm_opp_xlate_performance_state(genpd->opp_table, + master->opp_table, + state); + if (unlikely(ret < 0)) + goto err; + + master_state = ret; + + genpd_lock_nested(master, depth + 1); + + link->prev_performance_state = link->performance_state; + link->performance_state = master_state; + master_state = _genpd_reeval_performance_state(master, + master_state); + ret = _genpd_set_performance_state(master, master_state, depth + 1); + if (ret) + link->performance_state = link->prev_performance_state; + + genpd_unlock(master); + + if (ret) + goto err; + } + ret = genpd->set_performance_state(genpd, state); if (ret) - return ret; + goto err; genpd->performance_state = state; return 0; + +err: + /* Encountered an error, lets rollback */ + list_for_each_entry_continue_reverse(link, &genpd->slave_links, + slave_node) { + master = link->master; + + if (!master->set_performance_state) + continue; + + genpd_lock_nested(master, depth + 1); + + master_state = link->prev_performance_state; + link->performance_state = master_state; + + master_state = _genpd_reeval_performance_state(master, + master_state); + if (_genpd_set_performance_state(master, master_state, depth + 1)) { + pr_err("%s: Failed to roll back to %d performance state\n", + master->name, master_state); + } + + genpd_unlock(master); + } + + return ret; } /** @@ -331,7 +402,7 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) gpd_data->performance_state = state; state = _genpd_reeval_performance_state(genpd, state); - ret = _genpd_set_performance_state(genpd, state); + ret = _genpd_set_performance_state(genpd, state, 0); if (ret) gpd_data->performance_state = prev; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 9ad101362aef..dd364abb649a 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -136,6 +136,10 @@ struct gpd_link { struct list_head master_node; struct generic_pm_domain *slave; struct list_head slave_node; + + /* Sub-domain's per-master domain performance state */ + unsigned int performance_state; + unsigned int prev_performance_state; }; struct gpd_timing_data {