Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp3204911imm; Tue, 29 May 2018 03:06:32 -0700 (PDT) X-Google-Smtp-Source: AB8JxZoRCSXocNz+FQ3Fo5aG8LbbEtDLkJkWNcIGUJwaikaDVx5EX9Z14ROjlgVxq//KXvK3opX9 X-Received: by 2002:a62:1549:: with SMTP id 70-v6mr16824451pfv.91.1527588392353; Tue, 29 May 2018 03:06:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527588392; cv=none; d=google.com; s=arc-20160816; b=ta3oxCszT8SE27oGkK7JjbEvmO/mb21ZB7mlBleLuqh4qjIi1ExNHBE9bzO8jbnSg1 ln09iT7RYiD/g3Y8QZUEKBbddbXRCmmmjs9z485hDaO1NIoU50OQHM0fpbN1MxgJOIXm 0uKG4rPv8aFnd1q/IBEx4qAMS3afIgxDPqJVtI5pXrmYIvhqvHLGvu801pgnYYdCyyCe vRVb4yn49FkgtK0lX3rbSHny3DvjKloO9kVR3XburRIgzWgoaUjN4hu0fT89sT0A2g// +KMDgF0NJ8ll1aeGJa5Hj52hVV3KdmLw+i9T2wwFxBkFds2x7wkD6JsVC0iZTIBz5DMf tWRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=4AKcocpDu8LzFvQQptUzJpFM524E5IXAqb+rjvCBc/c=; b=mCMZ0QIbPSUQkuLJeZkjoeXTP2e4UFDkIY3SbJg+zxv6hufeDhzY1Y1JmF717nhw6O 0xxmeLfdhwfxyq4xXIyDE0u4PCmgvey+Qd7fMLXfSnvfFZFMbwRFCsJNPzxJkqwI5u4Z 7TijlfUzdbbni655PW6z2Qzzf7anjNKg3+DaCe5xnLQtBiWUpHB9jEsh62ZqCCWUTMGM 7TIE5DR7mJbchy5RsntPMUWCWCLGNjluI/rBln4IP/EfCVbD8aVcn55OPfnSD1Wq9/5T AGZWWakX0HINY5dsIvp+OKmh+5oKlDFz+upTq1hhIyL/DjqoBeVxG39m5IJFsyR39fr7 EZKA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZZJD24OS; 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 i1-v6si7641775pgc.100.2018.05.29.03.06.18; Tue, 29 May 2018 03:06:32 -0700 (PDT) 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=ZZJD24OS; 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 S933171AbeE2KFc (ORCPT + 99 others); Tue, 29 May 2018 06:05:32 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:52558 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933165AbeE2KEm (ORCPT ); Tue, 29 May 2018 06:04:42 -0400 Received: by mail-wm0-f66.google.com with SMTP id 18-v6so33275161wml.2 for ; Tue, 29 May 2018 03:04:41 -0700 (PDT) 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; bh=4AKcocpDu8LzFvQQptUzJpFM524E5IXAqb+rjvCBc/c=; b=ZZJD24OSCW897IXk7gN0gsb538Ig7zxjlS3qOtp99xeQh2i2UskamIfmgRM7lHsKnr nK1yXnN+vDVZjpTWJIu0A4f6F9y/IaZnqPl2mFEhssWHHjOog4mQdHPkC/pTV8dnfq0P hIhci/jpMHG3M4VejT5BBJW/dpRmS1mqPOlzI= 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; bh=4AKcocpDu8LzFvQQptUzJpFM524E5IXAqb+rjvCBc/c=; b=l6bK+C2qoXA4fnTYziR7BwThsB/U7sWdVIapKnmRZcxazNILHlu0INCe/dUsk2Kyrx kHL3YewXB4buJRJl0B+VvqAbzpPx2vsuUXMDqWYYAajHC0VBbSvnzCRoFc7uxh6sZodb x1UA8hPXhiCMK+p1VAPJx08NWPrfMxOdfxCm8hpWyZI/WZvawys8rWrjEchGagLX6Wan sYZaRorRM9YexVYCSfHb1BX2Psy67t0gD7/wKYe9dlF1V34gEBKouFcSGVxgbVBxLpHK CsfQ712/Gn/Fq/H4/9Vu5YGkLkN3NN6A2NIztRoA4Q0ERzm4lQ/pJpDKZmhy+YWoMQNU EQ2g== X-Gm-Message-State: ALKqPwd8bf6F2X/Q7+ig6gxjg/cPV9Pth8wV9g1Cjd0KMrYA175vZCMN M0ZLIVqK6SVAJZhOSiUYGt1vHw== X-Received: by 2002:a2e:8948:: with SMTP id b8-v6mr10916487ljk.31.1527588281021; Tue, 29 May 2018 03:04:41 -0700 (PDT) Received: from localhost.localdomain (h-158-174-22-210.NA.cust.bahnhof.se. [158.174.22.210]) by smtp.gmail.com with ESMTPSA id e21-v6sm2561718lfg.74.2018.05.29.03.04.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 29 May 2018 03:04:40 -0700 (PDT) From: Ulf Hansson To: "Rafael J . Wysocki" , linux-pm@vger.kernel.org Cc: Ulf Hansson , Greg Kroah-Hartman , Jon Hunter , Geert Uytterhoeven , Todor Tomov , Rajendra Nayak , Viresh Kumar , Vincent Guittot , Kevin Hilman , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-tegra@vger.kernel.org Subject: [PATCH v2 8/9] PM / Domains: Add support for multi PM domains per device to genpd Date: Tue, 29 May 2018 12:04:20 +0200 Message-Id: <20180529100421.31022-9-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180529100421.31022-1-ulf.hansson@linaro.org> References: <20180529100421.31022-1-ulf.hansson@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org To support devices being partitioned across multiple PM domains, let's begin with extending genpd to cope with these kind of configurations. Therefore, add a new exported function genpd_dev_pm_attach_by_id(), which is similar to the existing genpd_dev_pm_attach(), but with the difference that it allows its callers to provide an index to the PM domain that it wants to attach. Note that, genpd_dev_pm_attach_by_id() shall only be called by the driver core / PM core, similar to how the existing dev_pm_domain_attach() makes use of genpd_dev_pm_attach(). However, this is implemented by following changes on top. Because, only one PM domain can be attached per device, genpd needs to create a virtual device that it can attach/detach instead. More precisely, let the new function genpd_dev_pm_attach_by_id() register a virtual struct device via calling device_register(). Then let it attach this device to the corresponding PM domain, rather than the one that is provided by the caller. The actual attaching is done via re-using the existing genpd OF functions. At successful attachment, genpd_dev_pm_attach_by_id() returns the created virtual device, which allows the caller to operate on it to deal with power management. Following changes on top, provides more details in this regards. To deal with detaching of a PM domain for the multiple PM domains case, let's also extend the existing genpd_dev_pm_detach() function, to cover the cleanup of the created virtual device, via make it call device_unregister() on it. In this way, there is no need to introduce a new function to deal with detach for the multiple PM domain case, but instead the existing one is re-used. Signed-off-by: Ulf Hansson --- Changes in v2: - Fixed comments from Jon. Clarified function descriptions and changelog. --- drivers/base/power/domain.c | 80 +++++++++++++++++++++++++++++++++++++ include/linux/pm_domain.h | 8 ++++ 2 files changed, 88 insertions(+) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 2af99bfcbe3c..2b496d79159d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2171,6 +2171,15 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np) } EXPORT_SYMBOL_GPL(of_genpd_remove_last); +static void genpd_release_dev(struct device *dev) +{ + kfree(dev); +} + +static struct bus_type genpd_bus_type = { + .name = "genpd", +}; + /** * genpd_dev_pm_detach - Detach a device from its PM domain. * @dev: Device to detach. @@ -2208,6 +2217,10 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) /* Check if PM domain can be powered off after removing this device. */ genpd_queue_power_off_work(pd); + + /* Unregister the device if it was created by genpd. */ + if (dev->bus == &genpd_bus_type) + device_unregister(dev); } static void genpd_dev_pm_sync(struct device *dev) @@ -2298,6 +2311,67 @@ int genpd_dev_pm_attach(struct device *dev) } EXPORT_SYMBOL_GPL(genpd_dev_pm_attach); +/** + * genpd_dev_pm_attach_by_id() - Attach a device to one of its PM domain. + * @dev: Device to attach. + * @index: The index of the PM domain. + * + * Parse device's OF node to find a PM domain specifier at the provided @index. + * If such is found, creates a virtual device and attaches it to the retrieved + * pm_domain ops. To deal with detaching of the virtual device, the ->detach() + * callback in the struct dev_pm_domain are assigned to genpd_dev_pm_detach(). + * + * Returns the created virtual device if successfully attached PM domain, NULL + * when the device don't need a PM domain, else an ERR_PTR() in case of + * failures. If a power-domain exists for the device, but cannot be found or + * turned on, then ERR_PTR(-EPROBE_DEFER) is returned to ensure that the device + * is not probed and to re-try again later. + */ +struct device *genpd_dev_pm_attach_by_id(struct device *dev, + unsigned int index) +{ + struct device *genpd_dev; + int num_domains; + int ret; + + if (!dev->of_node) + return NULL; + + /* Deal only with devices using multiple PM domains. */ + num_domains = of_count_phandle_with_args(dev->of_node, "power-domains", + "#power-domain-cells"); + if (num_domains < 2 || index >= num_domains) + return NULL; + + /* Allocate and register device on the genpd bus. */ + genpd_dev = kzalloc(sizeof(*genpd_dev), GFP_KERNEL); + if (!genpd_dev) + return ERR_PTR(-ENOMEM); + + dev_set_name(genpd_dev, "genpd:%u:%s", index, dev_name(dev)); + genpd_dev->bus = &genpd_bus_type; + genpd_dev->release = genpd_release_dev; + + ret = device_register(genpd_dev); + if (ret) { + kfree(genpd_dev); + return ERR_PTR(ret); + } + + /* Try to attach the device to the PM domain at the specified index. */ + ret = __genpd_dev_pm_attach(genpd_dev, dev->of_node, index); + if (ret < 1) { + device_unregister(genpd_dev); + return ret ? ERR_PTR(ret) : NULL; + } + + pm_runtime_set_active(genpd_dev); + pm_runtime_enable(genpd_dev); + + return genpd_dev; +} +EXPORT_SYMBOL_GPL(genpd_dev_pm_attach_by_id); + static const struct of_device_id idle_state_match[] = { { .compatible = "domain-idle-state", }, { } @@ -2457,6 +2531,12 @@ unsigned int of_genpd_opp_to_performance_state(struct device *dev, } EXPORT_SYMBOL_GPL(of_genpd_opp_to_performance_state); +static int __init genpd_bus_init(void) +{ + return bus_register(&genpd_bus_type); +} +core_initcall(genpd_bus_init); + #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */ diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 42e0d649e653..82458e8e2e01 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -237,6 +237,8 @@ unsigned int of_genpd_opp_to_performance_state(struct device *dev, struct device_node *opp_node); int genpd_dev_pm_attach(struct device *dev); +struct device *genpd_dev_pm_attach_by_id(struct device *dev, + unsigned int index); #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */ static inline int of_genpd_add_provider_simple(struct device_node *np, struct generic_pm_domain *genpd) @@ -282,6 +284,12 @@ static inline int genpd_dev_pm_attach(struct device *dev) return 0; } +static inline struct device *genpd_dev_pm_attach_by_id(struct device *dev, + unsigned int index) +{ + return NULL; +} + static inline struct generic_pm_domain *of_genpd_remove_last(struct device_node *np) { -- 2.17.0