From patchwork Tue Jan 3 11:06:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 89633 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp7951486qgi; Tue, 3 Jan 2017 03:07:15 -0800 (PST) X-Received: by 10.84.216.70 with SMTP id f6mr117733443plj.10.1483441635396; Tue, 03 Jan 2017 03:07:15 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i8si25735369plk.60.2017.01.03.03.07.15; Tue, 03 Jan 2017 03:07:15 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934544AbdACLHL (ORCPT + 13 others); Tue, 3 Jan 2017 06:07:11 -0500 Received: from mail-pg0-f48.google.com ([74.125.83.48]:32968 "EHLO mail-pg0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934849AbdACLG4 (ORCPT ); Tue, 3 Jan 2017 06:06:56 -0500 Received: by mail-pg0-f48.google.com with SMTP id g1so174778470pgn.0 for ; Tue, 03 Jan 2017 03:06:51 -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 :in-reply-to:references; bh=FhxefQxMVQtPbqCWkp78tnGgLxZvol1p0N20HhSqW8s=; b=I4pXPIivJkKu5hxUhNc6kRZdP6GeLoFt0kGop1VZwJKKmJKkOhfPF0pjwfpQB4cpIL f2H961iJNqyd1tWZoqo6MjOIVT7ZlcC/XK6whLdtOG7bdR1rfGMlRUvDE294aZOW1xql wjIgQj3gGzcyX8S+25ndWfqkgiLysVXmtkfoM= 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:in-reply-to:references; bh=FhxefQxMVQtPbqCWkp78tnGgLxZvol1p0N20HhSqW8s=; b=qStrY0HhQ/Ys2e21y2dyKEN0a1wg5qOb6XZLns/OHQiLdhChNN2xzF0e+HKzkFKJLJ XOheWiWZxKuAwXVX34ZUwGUv+ff7M2I/JZh37s3VinUvpZF280OgaSw3QOlfNIYXOBcs 0wN3xLVqdOHV4T+YZCZnvcApIyg5p/Y/pHqlXYcVqCGkcyh6yNNCxnG2bIVqdS0SZCGi /Ow6VwVT0MRh6TtGmPQMQwcuc4cIkvvdfZGbYYlh3XFhPGOFGMklhh7v1rVcttArmSFm 39sH6WiCmYqsdV8dbYkGvCTUGvYkCsRuVdN7lwhwfE1DtOiObLdMnrHjK4CY/2YX5t6C RJ1A== X-Gm-Message-State: AIkVDXIAaJlUPOkLa22v9xjtwMMudwqGd2LH11HPkL8n0JZGsWHy/FHTiB480MBRgZ8SjWoC X-Received: by 10.99.146.13 with SMTP id o13mr116233337pgd.3.1483441606028; Tue, 03 Jan 2017 03:06:46 -0800 (PST) Received: from localhost ([122.171.77.55]) by smtp.gmail.com with ESMTPSA id r2sm139052219pfi.67.2017.01.03.03.06.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Jan 2017 03:06:45 -0800 (PST) From: Viresh Kumar To: Rafael Wysocki , khilman@baylibre.com, ulf.hansson@linaro.org, Kevin Hilman , Len Brown , Pavel Machek Cc: linaro-kernel@lists.linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Stephen Boyd , Nishanth Menon , Vincent Guittot , robh+dt@kernel.org, mark.rutland@arm.com, lina.iyer@linaro.org, rnayak@codeaurora.org, Viresh Kumar Subject: [PATCH 4/6] PM / domain: Register for PM QOS performance notifier Date: Tue, 3 Jan 2017 16:36:10 +0530 Message-Id: <9e3e66a8f7392c7baa57a16325724f4a20584e3e.1483439894.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.7.1.410.g6faf27b In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Some platforms have the capability to configure the performance state of their Power Domains. The performance levels are represented by positive integer values, a lower value represents lower performance state. This patch registers the power domain framework for PM QOS performance notifier in order to manage performance state of power domains. This also allows the power domain drivers to implement a ->set_performance_state() callback, which will be called by the power domain core from the notifier routine. Signed-off-by: Viresh Kumar --- drivers/base/power/domain.c | 75 +++++++++++++++++++++++++++++++++++++++++++-- include/linux/pm_domain.h | 5 +++ 2 files changed, 78 insertions(+), 2 deletions(-) -- 2.7.1.410.g6faf27b -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 12f16d9b6b55..f460be4ca5f7 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -367,6 +367,61 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, return NOTIFY_DONE; } +static void update_domain_performance_state(struct generic_pm_domain *genpd) +{ + struct generic_pm_domain_data *pd_data; + struct pm_domain_data *pdd; + unsigned int state = 0; + + if (!genpd->set_performance_state) + return; + + list_for_each_entry(pdd, &genpd->dev_list, list_node) { + pd_data = to_gpd_data(pdd); + + if (pd_data->performance_state > state) + state = pd_data->performance_state; + } + + if (genpd->performance_state == state) + return; + + genpd->performance_state = state; + genpd->set_performance_state(genpd, state); +} + +static int genpd_dev_pm_qos_perf_notifier(struct notifier_block *nb, + unsigned long val, void *ptr) +{ + struct generic_pm_domain_data *gpd_data; + struct generic_pm_domain *genpd = ERR_PTR(-ENODATA); + struct pm_domain_data *pdd; + struct device *dev; + + gpd_data = container_of(nb, struct generic_pm_domain_data, perf_nb); + dev = gpd_data->base.dev; + + spin_lock_irq(&dev->power.lock); + + pdd = dev->power.subsys_data ? + dev->power.subsys_data->domain_data : NULL; + + if (pdd && pdd->dev) + genpd = dev_to_genpd(dev); + + spin_unlock_irq(&dev->power.lock); + + if (IS_ERR(genpd)) + return NOTIFY_DONE; + + genpd_lock(genpd); + gpd_data->performance_state = val; + update_domain_performance_state(genpd); + genpd_unlock(genpd); + + return NOTIFY_DONE; +} + /** * genpd_poweroff - Remove power from a given PM domain. * @genpd: PM domain to power down. @@ -1127,6 +1182,10 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev, gpd_data->td.constraint_changed = true; gpd_data->td.effective_constraint_ns = -1; gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier; + gpd_data->performance_state = 0; + + if (genpd->set_performance_state) + gpd_data->perf_nb.notifier_call = genpd_dev_pm_qos_perf_notifier; spin_lock_irq(&dev->power.lock); @@ -1200,12 +1259,17 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, out: genpd_unlock(genpd); - if (ret) + if (ret) { genpd_free_dev_data(dev, gpd_data); - else + } else { dev_pm_qos_add_notifier(dev, &gpd_data->nb, DEV_PM_QOS_RESUME_LATENCY); + if (genpd->set_performance_state) + dev_pm_qos_add_notifier(dev, &gpd_data->perf_nb, + DEV_PM_QOS_PERFORMANCE); + } + return ret; } @@ -1239,6 +1303,9 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, pdd = dev->power.subsys_data->domain_data; gpd_data = to_gpd_data(pdd); + if (genpd->set_performance_state) + dev_pm_qos_remove_notifier(dev, &gpd_data->perf_nb, + DEV_PM_QOS_PERFORMANCE); dev_pm_qos_remove_notifier(dev, &gpd_data->nb, DEV_PM_QOS_RESUME_LATENCY); @@ -1267,6 +1334,10 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, genpd_unlock(genpd); dev_pm_qos_add_notifier(dev, &gpd_data->nb, DEV_PM_QOS_RESUME_LATENCY); + if (genpd->set_performance_state) + dev_pm_qos_add_notifier(dev, &gpd_data->perf_nb, + DEV_PM_QOS_PERFORMANCE); + return ret; } diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 81ece61075df..d994ad5ba1c0 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -62,8 +62,11 @@ struct generic_pm_domain { unsigned int device_count; /* Number of devices */ unsigned int suspended_count; /* System suspend device counter */ unsigned int prepared_count; /* Suspend counter of prepared devices */ + unsigned int performance_state; /* Max requested performance state */ int (*power_off)(struct generic_pm_domain *domain); int (*power_on)(struct generic_pm_domain *domain); + int (*set_performance_state)(struct generic_pm_domain *domain, + unsigned int state); struct gpd_dev_ops dev_ops; s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ bool max_off_time_changed; @@ -117,6 +120,8 @@ struct generic_pm_domain_data { struct pm_domain_data base; struct gpd_timing_data td; struct notifier_block nb; + struct notifier_block perf_nb; + unsigned int performance_state; }; #ifdef CONFIG_PM_GENERIC_DOMAINS