From patchwork Fri May 18 10:31:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 136286 Delivered-To: patches@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp1056715lji; Fri, 18 May 2018 03:31:58 -0700 (PDT) X-Received: by 2002:a19:7007:: with SMTP id h7-v6mr19653451lfc.123.1526639518466; Fri, 18 May 2018 03:31:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526639518; cv=none; d=google.com; s=arc-20160816; b=SV/sD0yChWPdPu4G0iWJrui8Gk3glPj4tKAVihgWBddcl2VZhPP8EOdIXqJu/Xx6UF GoZ6aNp0vXS5Pvmr7cAFur0JMsf5S7INsZ8SwHpb60zyPzYJaMCi3DrtfGVY6BN7Tolz F3pPylz4LReVS6p953LocrxyvsOyY+6P2SshP1J9U5BSf3pOv4MeL9P452WB6mcdqzU/ pV6MW731lRRzEqnV7qRZaP2gMAtOGqLumkHxtn99VtotlcDiE4Usm+54PQJ/Gwf1JLKI ZaESgRdbj/Agtekq3RXnPzXQ/SKzgtVL1eVVBrLzHHVm8g6xGtOV4+/DN6b5wXqMG6Qj hVSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=Xufj7MGpsD5staIyz3w3w6bZYYrOOfrLdPdsC/ARxQ8=; b=YdmyBYOgBOiyvk9O74Ni0j8c4t8bVtPcS7MeLmn/WCv6Pf+AXY1IenjDvg9AiC5ESa 3ULN2o/Q4VqLrA7HMAblFDu1Sd9D5j3HrJnaNK/3g9MNrs6AJDil9btu37i+yjqVLGvg h9gn4S+JlLDsyuJIbeRAoUlDRDebGTVdt9LxyrUgBfQCyVJeaTkCBOs/oNgvq6gwdriR E3qib8/hpKS+yotAfVySSCn6Ntabd2dPpA+pmSkA9Sl0hCuG4B8KMiqxn5j4qZSEQuIv g2qiKjlcYAmJuldlNCLw+pjEFJ7B+LZowSXvT4V/HCcUc1IYTc6GnLx4A083mUZnSx7J rPCA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=XfaL9NAc; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id g3-v6sor1735440lje.107.2018.05.18.03.31.58 for (Google Transport Security); Fri, 18 May 2018 03:31:58 -0700 (PDT) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=XfaL9NAc; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=Xufj7MGpsD5staIyz3w3w6bZYYrOOfrLdPdsC/ARxQ8=; b=XfaL9NAcTTyxaFgCw1yf13SBWWlnK1Cm3QMV9BnJtI4NPTzxh0RhZhh8p80eKuOmAX ivYNRwLmbV0nPeXdckjpqbbZp4x0N1kPRsnfO3ww1EPh40hR33i8JVOVtrrBDHFhwoTy wpJjVPvTEs5X71FKQa34Hq5MJ23NnoPXLvtyM= 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=Xufj7MGpsD5staIyz3w3w6bZYYrOOfrLdPdsC/ARxQ8=; b=rd4Ze/eQ/U1nBNsgQ4YGr8UtWFlDTDbgu56uLfxFUbkKJMQVVHjCys7V6v8t05X8Lg YTZwoyQBzH5TqrKVf16VZnZP37Si2tJTO3ND7OhYkhU6fSfAWDgG3Nol5nrYZiCiZvbI HPdNIBYUvjhLlz5gtlePqHX/CMUKaJNnh/4rdVqRIGh4+sABmRub4MRuk1mbrKmmd/CW SsUqVbM/w9Em7j+tAz7cUg0nwGDeJma4hBrrIhw60jN2TX7VWtwwrlgPL/jZjXtDe264 PMRu+tBbJFHKkaBVGryYWu9YihvLE6qENR/YPVsLahi9AmM07XByYwrLCJXsOjjtFPrZ YPjw== X-Gm-Message-State: ALKqPwfpTxDzJZK5aVEaJsARgzmPpF974ky1cytNQ75Kgi/lxpM84bBM nyosIgpx6b21CRXA+0f3PXqp4lQL X-Google-Smtp-Source: AB8JxZq7mpM973JWrWfZxrFD1GsHz4vCBEQ6o2rdyZ/tLmF2MV4ZidskyfEYzlHs0uv7qZ2Ai2/B8Q== X-Received: by 2002:a2e:83d7:: with SMTP id s23-v6mr5316082ljh.34.1526639518196; Fri, 18 May 2018 03:31:58 -0700 (PDT) Return-Path: Received: from localhost.localdomain (h-158-174-22-210.NA.cust.bahnhof.se. [158.174.22.210]) by smtp.gmail.com with ESMTPSA id u14-v6sm393447lfk.55.2018.05.18.03.31.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 18 May 2018 03:31:57 -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 8/9] PM / Domains: Add support for multi PM domains per device to genpd Date: Fri, 18 May 2018 12:31:29 +0200 Message-Id: <1526639490-12167-9-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526639490-12167-1-git-send-email-ulf.hansson@linaro.org> References: <1526639490-12167-1-git-send-email-ulf.hansson@linaro.org> To support devices being partitioned across multiple PM domains, let's start by extending genpd to cope with these configurations. More precisely, add a new exported function, genpd_dev_pm_attach_by_id(), similar to genpd_dev_pm_attach(), but the new function also allows the caller to provide an index to what PM domain it wants to attach. Furthermore, let genpd register a new virtual struct device via calling device_register() and attach it to the corresponding PM domain, which is looked up via calling the existing genpd OF functions. Note that the new device is needed, because only one PM domain can be attached per device. At successful attachment, genpd_dev_pm_attach_by_id() returns the new device, allowing the caller to operate on it to deal with power management. To deal with detaching of a PM domain for multiple PM domain case, we can still re-use the existing genpd_dev_pm_detach() function, although we need to extend it to cover cleanup of the earlier registered device, via calling device_unregister(). An important note, genpd_dev_pm_attach_by_id() shall only be called by the driver core / PM core, similar to how genpd_dev_pm_attach() is used. Following changes deploys this. Signed-off-by: Ulf Hansson --- drivers/base/power/domain.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_domain.h | 8 +++++ 2 files changed, 87 insertions(+) -- 2.7.4 diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index d538640..ffeb6ea 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,66 @@ 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, allocates a new device and attaches it to retrieved + * pm_domain ops. + * + * Returns the allocated device if successfully attached PM domain, NULL when + * the device don't need a PM domain or have a single PM domain, else PTR_ERR() + * in case of failures. Note that if a power-domain exists for the device, but + * cannot be found or turned on, then return PTR_ERR(-EPROBE_DEFER) 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", }, { } @@ -2456,6 +2529,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 42e0d64..82458e8 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) {