Received: by 2002:a25:c593:0:0:0:0:0 with SMTP id v141csp2348422ybe; Thu, 12 Sep 2019 08:11:51 -0700 (PDT) X-Google-Smtp-Source: APXvYqyhsjHVhwf+E7D97TV7049t9kbcxuq5VDiUAzQlsodZ5hoPT0EgxPM/F7kaaEo2rkDoP8vS X-Received: by 2002:a17:906:43cf:: with SMTP id j15mr35654950ejn.7.1568301110979; Thu, 12 Sep 2019 08:11:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1568301110; cv=none; d=google.com; s=arc-20160816; b=cay+bRTWUn03tJJ1D8kGBTbvK/B18lBlvWxKPrXpQc+miIGA0TuyeNN4h7L5c8DcHn 6993vDjJXX84jn8UVFWC2fAhrqc7EEKVpzE7LIDu9IwxLIU6Lx+ebzCDK19f817+Nj8P /a1RdP+pFZ3ZIoVXFhZpfYQrvHCC6spDgUol+jB6tL4BO8/mhjoUNvax2UKlS/2FJuFo T7JkrYVafndjVjJdvlp6kA3TRGggy6lAOypyl6eoN81wqwqFIxAXac+tTz9TjrMzZxQl Ak3RzmA2v7T73ph8YRlmaS2lOJfO2nJYyN5j4XQtWjq4iq0ra1dMX6RnEFqcJZp0s3V3 hNkw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=xFNNCOgYKpq2tfIBsvM5Q2EFA3f47YwR/HKpQvuH55A=; b=Dt5tfLyJ5QFEYikzapIR7+hwWaRI4yYZaTytWQdbgqaDxHaegPwd8QweP3H73BFpmT s9fgKfjP+97Qmbid0DLpVtTy50EQ9NmICx78ul2CF+2d87VAp8V6NGhWNHt7CqzXDEXi s2AHrJzoAG15MjjbFAjXNsY9zUUfp1+VIfmI+ssQtzDAOD8wgsA/Gc48h9O6nLggGSe7 I9KXySCFasfFHIrbN21d3FT0VJEWMAWXD61HVVLtLsQpiG9BISs7NoFBLe3BBmDUwIhc wA2GBuW4PwggBfu/w9cuKG8YidRvB8Frt9yIU3K5GDTNPDjO9QMQNACneczLv6iLPg84 U6Lw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=AZEvGYnH; 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 d6si13006686edv.22.2019.09.12.08.11.25; Thu, 12 Sep 2019 08:11:50 -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=AZEvGYnH; 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 S1732966AbfILPEk (ORCPT + 99 others); Thu, 12 Sep 2019 11:04:40 -0400 Received: from mail-vk1-f196.google.com ([209.85.221.196]:33159 "EHLO mail-vk1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732592AbfILPEk (ORCPT ); Thu, 12 Sep 2019 11:04:40 -0400 Received: by mail-vk1-f196.google.com with SMTP id q186so5224574vkb.0 for ; Thu, 12 Sep 2019 08:04:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=xFNNCOgYKpq2tfIBsvM5Q2EFA3f47YwR/HKpQvuH55A=; b=AZEvGYnHobz+aCT+xnfAm+qo5L3S6S0AsimwkFQLGvUSD1g9sEjVwzSPupFnLuhUGb BkJp+eA6AN7OZp6PYY//MtWmqLqL6DjY5KT59ehRnTV2w9kilGBb7+zg/Lm/9PMIMAwU yaaC8yubvTQWQ6q22ByA5EqaO/cu2bJABaQNJwntZBiI1668H2QIAG4W1vWCf5PQ+bDq sINOBDMlzXWVnhASAglbBurBC1bHAK3wSNkv5g0+e/5v1+GpIoJZnk06vF4hCc0oDjQv D1HUQ8r+Gz0ca+OaEINpNDWtZQXKgcLdrHScU/jJAu6Cw7ZBMW6ODoMZtB8VK4iX2sol 2Y1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=xFNNCOgYKpq2tfIBsvM5Q2EFA3f47YwR/HKpQvuH55A=; b=JWKk0SDU061CtRJgW61lHip8fI37petWsTprQqQhuOz4x8HoctKDE1AV3jjV0J1l1u 7/m+uzLT9XC5NDMiPfb+1Z6cMWX8q5VSowrMhjJEP0aGZ4+rfwSLOK6ps+qBpTbf8tnS Kx90zwOkrU31qI0slGw0ytBpPJ9vRcxhhFLks2FZaF2Om37YzjmkwGaIJRu3sQZw++m7 aD/BKDBN+ZD4hSy4nyGIZ9meQqi/p4UQ3wGgYrQGTQ0F+47+Uz8VrPI2iB6ex3qGyHxe Yn2TQrOVFUQvuKIMOL9veIdGbS+JxhknICsMbURhr1MjzG8oU42dftNewgJ2S+dtK6l7 6JHg== X-Gm-Message-State: APjAAAXAzjnGDiZ4wd6iLvV8YHDWuU+NbneYV8pIoxhkOcW+TXXiE42m vrBgQHPgttjHmsOC8xFvnnlc+CXKeM3yH88sN4dA3A== X-Received: by 2002:a1f:8c50:: with SMTP id o77mr7663416vkd.52.1568300678305; Thu, 12 Sep 2019 08:04:38 -0700 (PDT) MIME-Version: 1.0 References: <1568135676-9328-1-git-send-email-thara.gopinath@linaro.org> <1568135676-9328-5-git-send-email-thara.gopinath@linaro.org> In-Reply-To: <1568135676-9328-5-git-send-email-thara.gopinath@linaro.org> From: Ulf Hansson Date: Thu, 12 Sep 2019 17:04:01 +0200 Message-ID: Subject: Re: [PATCH 4/5] thermal: Add generic power domain warming device driver. To: Thara Gopinath Cc: Eduardo Valentin , Zhang Rui , Daniel Lezcano , Bjorn Andersson , Rob Herring , agross@kernel.org, amit.kucheria@verdurent.com, Mark Rutland , "Rafael J. Wysocki" , Linux PM , DTML , linux-arm-msm , Linux Kernel Mailing List Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, 10 Sep 2019 at 19:14, Thara Gopinath wrote: > > Resources modeled as power domains in linux kenrel > can be used to warm the SoC(eg. mx power domain on sdm845). > To support this feature, introduce a generic power domain > warming device driver that can be plugged into the thermal framework > (The thermal framework itself requires further modifiction to > support a warming device in place of a cooling device. > Those extensions are not introduced in this patch series). > > Signed-off-by: Thara Gopinath > --- > v1->v2: > - Make power domain based warming device driver a generic > driver in the thermal framework. v1 implemented this as a > Qualcomm specific driver. > - Rename certain variables as per review suggestions on the > mailing list. > > drivers/thermal/Kconfig | 11 +++ > drivers/thermal/Makefile | 2 + > drivers/thermal/pwr_domain_warming.c | 174 +++++++++++++++++++++++++++++++++++ > 3 files changed, 187 insertions(+) > create mode 100644 drivers/thermal/pwr_domain_warming.c > > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig > index 9966364..eeb6018 100644 > --- a/drivers/thermal/Kconfig > +++ b/drivers/thermal/Kconfig > @@ -187,6 +187,17 @@ config DEVFREQ_THERMAL > > If you want this support, you should say Y here. > > +config PWR_DOMAIN_WARMING_THERMAL > + bool "Power Domain based warming device" > + depends on PM_GENERIC_DOMAINS > + depends on PM_GENERIC_DOMAINS_OF PM_GENERIC_DOMAINS_OF can't be set unless PM_GENERIC_DOMAINS is set too. So I assume it's sufficient to depend on PM_GENERIC_DOMAINS_OF? > + help > + This implements the generic power domain based warming > + mechanism through increasing the performance state of > + a power domain. > + > + If you want this support, you should say Y here. > + > config THERMAL_EMULATION > bool "Thermal emulation mode support" > help > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile > index 74a37c7..382c64a 100644 > --- a/drivers/thermal/Makefile > +++ b/drivers/thermal/Makefile > @@ -27,6 +27,8 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o > # devfreq cooling > thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o > > +thermal_sys-$(CONFIG_PWR_DOMAIN_WARMING_THERMAL) += pwr_domain_warming.o > + > # platform thermal drivers > obj-y += broadcom/ > obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o > diff --git a/drivers/thermal/pwr_domain_warming.c b/drivers/thermal/pwr_domain_warming.c > new file mode 100644 > index 0000000..3dd792b > --- /dev/null > +++ b/drivers/thermal/pwr_domain_warming.c > @@ -0,0 +1,174 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2019, Linaro Ltd > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +struct pd_warming_device { > + struct thermal_cooling_device *cdev; > + struct device *dev; > + int max_state; > + int cur_state; > + bool runtime_resumed; > +}; > + > +static const struct of_device_id pd_wdev_match_table[] = { > + { .compatible = "thermal-power-domain-wdev", .data = NULL }, > + { } > +}; > +MODULE_DEVICE_TABLE(of, pd_wdev_match_table); > + > +static int pd_wdev_get_max_state(struct thermal_cooling_device *cdev, > + unsigned long *state) > +{ > + struct pd_warming_device *pd_wdev = cdev->devdata; > + > + *state = pd_wdev->max_state; > + return 0; > +} > + > +static int pd_wdev_get_cur_state(struct thermal_cooling_device *cdev, > + unsigned long *state) > +{ > + struct pd_warming_device *pd_wdev = cdev->devdata; > + > + *state = dev_pm_genpd_get_performance_state(pd_wdev->dev); > + > + return 0; > +} > + > +static int pd_wdev_set_cur_state(struct thermal_cooling_device *cdev, > + unsigned long state) > +{ > + struct pd_warming_device *pd_wdev = cdev->devdata; > + struct device *dev = pd_wdev->dev; > + int ret; > + > + ret = dev_pm_genpd_set_performance_state(dev, state); > + > + if (ret) > + return ret; > + > + if (state && !pd_wdev->runtime_resumed) { > + ret = pm_runtime_get_sync(dev); > + pd_wdev->runtime_resumed = true; > + } else if (!state && pd_wdev->runtime_resumed) { > + ret = pm_runtime_put(dev); > + pd_wdev->runtime_resumed = false; > + } > + > + return ret; > +} > + > +static struct thermal_cooling_device_ops pd_warming_device_ops = { > + .get_max_state = pd_wdev_get_max_state, > + .get_cur_state = pd_wdev_get_cur_state, > + .set_cur_state = pd_wdev_set_cur_state, > +}; > + > +static int pd_wdev_create(struct device *dev, const char *name) > +{ > + struct pd_warming_device *pd_wdev; > + int state_count; > + > + pd_wdev = devm_kzalloc(dev, sizeof(*pd_wdev), GFP_KERNEL); > + if (!pd_wdev) > + return -ENOMEM; > + > + state_count = dev_pm_genpd_performance_state_count(dev); > + if (state_count < 0) > + return state_count; > + > + pd_wdev->dev = dev; > + pd_wdev->max_state = state_count - 1; > + pd_wdev->runtime_resumed = false; > + > + pm_runtime_enable(dev); > + > + pd_wdev->cdev = thermal_of_cooling_device_register > + (dev->of_node, name, > + pd_wdev, > + &pd_warming_device_ops); > + if (IS_ERR(pd_wdev->cdev)) { > + dev_err(dev, "unable to register %s cooling device\n", name); > + pm_runtime_disable(dev); > + > + return PTR_ERR(pd_wdev->cdev); > + } > + > + return 0; > +} > + > +static int pd_wdev_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev, *pd_dev; > + const char *pd_name; > + int id, count, ret = 0; > + > + count = of_count_phandle_with_args(dev->of_node, "power-domains", > + "#power-domain-cells"); Perhaps this should be converted to genpd OF helper function instead, that allows the caller to know how many power-domains there are specified for a device node. > + > + if (count > 1) { > + for (id = 0; id < count; id++) { > + ret = of_property_read_string_index > + (dev->of_node, "power-domain-names", > + id, &pd_name); > + if (ret) { > + dev_err(dev, "Error reading the power domain name %d\n", ret); > + continue; > + } It looks a bit awkward that you want to re-use the power-domain-names as the name for the cooling (warming) device. This isn't really what we use the "*-names" bindings for in general, I think. Anyway, if you want a name corresponding to the actual attached PM domain, perhaps re-using "->name" from the struct generic_pm_domain is better. We can add a genpd helper for that, no problem. Of course it also means that you must call dev_pm_domain_attach_by_id() first, to attach the device and then get the name of the genpd, but that should be fine. > + > + pd_dev = dev_pm_domain_attach_by_id(dev, id); > + if (IS_ERR(pd_dev)) { > + dev_err(dev, "Error attaching power domain %s %ld\n", pd_name, PTR_ERR(pd_dev)); > + continue; > + } > + > + ret = pd_wdev_create(pd_dev, pd_name); > + if (ret) { > + dev_err(dev, "Error building cooling device %s %d\n", pd_name, ret); > + dev_pm_domain_detach(pd_dev, false); > + continue; > + } I am wondering about the use case of having multiple PM domains attached to the cooling (warming) device. Is that really needed? Perhaps you can elaborate on that a bit? > + } > + } else if (count == 1) { > + ret = of_property_read_string_index(dev->of_node, > + "power-domain-names", > + 0, &pd_name); > + if (ret) { > + dev_err(dev, "Error reading the power domain name %d\n", ret); > + goto exit; > + } According to my comment above, perhaps we simply don't have to use the "power-domain-names" binding at all. Also, I don't think this is really safe, as there is no guarantee that there is PM domain attached to the device, just because you found the DT property "power-domain-names". Probably better to check pm_domain pointer for the device. > + > + ret = pd_wdev_create(dev, pd_name); > + if (ret) { > + dev_err(dev, "Error building cooling device %s %d\n", pd_name, ret); > + goto exit; > + } > + } else { > + ret = -EINVAL; > + } > + > +exit: > + return ret; > +} > + > +static struct platform_driver pd_wdev_driver = { > + .driver = { > + .name = "qcom-rpmhpd-cdev", Probably rename to a more generic name (leftover from earlier version I assume). > + .of_match_table = pd_wdev_match_table, > + }, > + .probe = pd_wdev_probe, > +}; > +module_platform_driver(pd_wdev_driver); > + > +MODULE_DESCRIPTION("Qualcomm RPMHPD cooling device driver"); Ditto. > +MODULE_LICENSE("GPL v2"); > -- > 2.1.4 > Kind regards Uffe