From patchwork Wed Dec 12 10:57:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 153574 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp1679634ljp; Wed, 12 Dec 2018 02:58:11 -0800 (PST) X-Google-Smtp-Source: AFSGD/UPeNu8+anRCBG5JyXVtfz3tT533d/mLhkWtfaeEdIrF1F8fvaiH06i1l9z8FfpEXL8VOzf X-Received: by 2002:a17:902:22f:: with SMTP id 44mr19293330plc.137.1544612291459; Wed, 12 Dec 2018 02:58:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544612291; cv=none; d=google.com; s=arc-20160816; b=of2ky1Q/1YJtKIES4Dc3nK2WT0rc2Tq6+dDiPDHJlj1G1sabjE/QHbD7o4uMKrZYYl 1PO7o5BSTyhE09Q2k4mcnTcZD6w7eCa5tH3VyEYMQe5zUbTlU8109KZYJQpp5zcYvIIQ J24lFsPOteU5GLKGkLocPT7W64jyBhb/PNiKqC1JLUi3Kf9vkF5QONA7oeVnGQ8y/eOF asmI7dxARBdT3g2KxBTH7OM+FkmcvzrleG68esDcB8LINiV53/HFqizn/8AXsDb3l/HI VaL3LpeO74qfvuCne8xhsc9FT4epLEVjYtcpCrTAB40GOh8oby3mypSslERKuA4LREL0 Xx7A== 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=o6OdClubF4RfL9e05GmhHLx7Ei4hstJaBiTl97uuPI8=; b=jS6gTUiZihEdMyt7tZTe7+YMCryzNhXOvzIh4nwgfA5Us1HnU9hm0xzOuj9WLpEPy+ /URYSB7FNx1psNhATvfBvucKZLbvZVRhXiL7K/LjUfA2M8B0g/5+M+0/mDpb7lKA0YJO ex2oFvdu5u2f2OtKjiyX43ggXwLunWVJqtdtkLtBx6qMpoO8ePz37g5QNbGo2ssE6DIZ S6HHACP9JV7MBPnqrfDXvKdX9fNfNU+ZHC26CDz9SPJH9GftiWBzcBYgenyvgmBEfkgN 6A/TCRdCEFl4ZbGieidbxZqPkJVgI9rP/4Ix4p0AaO5moNNDdIcYhM0i243kg2baa3FJ Iulg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=h+iqgxNa; 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 n67si15450072pfk.34.2018.12.12.02.58.11; Wed, 12 Dec 2018 02:58:11 -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=h+iqgxNa; 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 S1727347AbeLLK6J (ORCPT + 31 others); Wed, 12 Dec 2018 05:58:09 -0500 Received: from mail-pl1-f194.google.com ([209.85.214.194]:34136 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727302AbeLLK6G (ORCPT ); Wed, 12 Dec 2018 05:58:06 -0500 Received: by mail-pl1-f194.google.com with SMTP id w4so8456103plz.1 for ; Wed, 12 Dec 2018 02:58:06 -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=o6OdClubF4RfL9e05GmhHLx7Ei4hstJaBiTl97uuPI8=; b=h+iqgxNa/x6wXA7miuOUX5zrFMVjNFZHOu6qUD0o9RpqbtK3QJ9oiEDppegHtytORq +BGsVThazgEY3qtWaySy/zDbYm19yrGzsdaGz9FLAVUr7yr4kDHkxsnrbkFw37ugvk2i /uLGZPIpanZscY37gu7l2Hcdh8uxyXQ9tOSc4= 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=o6OdClubF4RfL9e05GmhHLx7Ei4hstJaBiTl97uuPI8=; b=DArA1Dkm1DHya4qdfmOrcixbFKS/13UVHWsarZUIW2Cawhx8EcKhABDe8N+fJDE2zR bMqssk1DeOP/27Cf2kzZOnGJtQznaU1qxoywGMxdUY8Vz0b9OFTDK6RFgm/Jv9bVksji rs36iWKmKf+7B++8FHcdHU5ADn4FLyhHr3DxEocXsmUIjLyPYXOAWjwr9Uy5QohYjXba P5Kfq+vLekVvc0HqJbY7nDDSENQW0Z8VNQHEbr9NbMUeRLRUjro7M/89aNGbVakMIWW/ v0ALi+xQxXQJxsEY6p6pUmrAn5ePM6VR77B5pmsnQk+cDOx3h8tJ8kMgowzGoAC/Rqrf eFFQ== X-Gm-Message-State: AA+aEWZCpRK+O8GKLipl/EOEMYT9Zs86yzw1a/f4PYaEdGuDqalukinZ wSpVBUC8XC33r/+5C6IMNO1EqA== X-Received: by 2002:a17:902:2aaa:: with SMTP id j39mr19893330plb.335.1544612286046; Wed, 12 Dec 2018 02:58:06 -0800 (PST) Received: from localhost ([122.172.23.29]) by smtp.gmail.com with ESMTPSA id 69sm31751751pgg.86.2018.12.12.02.58.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 12 Dec 2018 02:58:05 -0800 (PST) From: Viresh Kumar To: ulf.hansson@linaro.org, Rafael Wysocki , Kevin Hilman , Pavel Machek , Len Brown 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 V3 6/6] PM / Domains: Propagate performance state updates Date: Wed, 12 Dec 2018 16:27:29 +0530 Message-Id: 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 This commit updates genpd core to start propagating performance state updates to master domains that have their set_performance_state() callback set. 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. Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/base/power/domain.c | 105 ++++++++++++++++++++++++++++++------ include/linux/pm_domain.h | 4 ++ 2 files changed, 94 insertions(+), 15 deletions(-) -- 2.19.1.568.g152ad8e3369a diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 32ecbefbd191..5e0479b2e976 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -239,24 +239,90 @@ static void genpd_update_accounting(struct generic_pm_domain *genpd) static inline void genpd_update_accounting(struct generic_pm_domain *genpd) {} #endif +static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, + unsigned int state, int depth); + static int _genpd_set_performance_state(struct generic_pm_domain *genpd, - unsigned int state) + unsigned int state, int depth) { + struct generic_pm_domain *master; + struct gpd_link *link; + unsigned int master_state; int ret; + /* Propagate to masters of genpd */ + list_for_each_entry(link, &genpd->slave_links, slave_node) { + master = link->master; + + if (!master->set_performance_state) + continue; + + if (unlikely(!state)) { + master_state = 0; + } else { + /* Find master's performance state */ + master_state = dev_pm_opp_xlate_performance_state(genpd->opp_table, + master->opp_table, state); + if (unlikely(!master_state)) { + ret = -EINVAL; + goto err; + } + } + + genpd_lock_nested(master, depth + 1); + + link->prev_performance_state = link->performance_state; + link->performance_state = master_state; + ret = _genpd_reeval_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; + + if (_genpd_reeval_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; } static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, - unsigned int state) + unsigned int state, int depth) { 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) @@ -274,21 +340,30 @@ static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, state = pd_data->performance_state; } - if (state == genpd->performance_state) - return 0; - /* - * 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; + } + + if (state == genpd->performance_state) + return 0; update_state: - return _genpd_set_performance_state(genpd, state); + return _genpd_set_performance_state(genpd, state, depth); } /** @@ -332,7 +407,7 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) prev = gpd_data->performance_state; gpd_data->performance_state = state; - ret = _genpd_reeval_performance_state(genpd, state); + ret = _genpd_reeval_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 {