All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitry Osipenko <digetx@gmail.com>
To: Thierry Reding <thierry.reding@gmail.com>,
	Jonathan Hunter <jonathanh@nvidia.com>,
	Mark Brown <broonie@kernel.org>,
	Liam Girdwood <lgirdwood@gmail.com>,
	Ulf Hansson <ulf.hansson@linaro.org>,
	Peter Geis <pgwipeout@gmail.com>,
	Nicolas Chauvet <kwizart@gmail.com>,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>,
	Kevin Hilman <khilman@kernel.org>,
	Peter De Schrijver <pdeschrijver@nvidia.com>,
	Viresh Kumar <vireshk@kernel.org>,
	Stephen Boyd <sboyd@kernel.org>, Nishanth Menon <nm@ti.com>,
	Yangtao Li <tiny.windzz@gmail.com>,
	Matt Merhar <mattmerhar@protonmail.com>
Cc: linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
	linux-pm@vger.kernel.org
Subject: [PATCH v3 10/12] opp: Support set_opp() customization without requiring to use regulators
Date: Mon, 18 Jan 2021 03:55:22 +0300	[thread overview]
Message-ID: <20210118005524.27787-11-digetx@gmail.com> (raw)
In-Reply-To: <20210118005524.27787-1-digetx@gmail.com>

Support set_opp() customization without requiring to use regulators. This
is needed by drivers which want to use dev_pm_opp_set_rate() for changing
rates of a multiple clocks and don't need to touch regulator.

One example is NVIDIA Tegra30/114 SoCs which have two sibling 3D hardware
units which should be use to the same clock rate, meanwhile voltage
scaling is done using a power domain. In this case OPP table doesn't have
a regulator, causing a NULL dereference in _set_opp_custom().

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Tested-by: Matt Merhar <mattmerhar@protonmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/opp/core.c     | 46 +++++++++++++++++++++++++++++++++++-------
 include/linux/pm_opp.h |  3 +++
 2 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 49419ab9fbb4..7726c4c40b53 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -829,16 +829,21 @@ static int _set_opp_custom(const struct opp_table *opp_table,
 			   struct dev_pm_opp_supply *new_supply)
 {
 	struct dev_pm_set_opp_data *data;
-	int size;
+	int size, count;
+
+	if (opp_table->regulators)
+		count = opp_table->regulator_count;
+	else
+		count = 0;
 
 	data = opp_table->set_opp_data;
 	data->regulators = opp_table->regulators;
-	data->regulator_count = opp_table->regulator_count;
+	data->regulator_count = count;
 	data->clk = opp_table->clk;
 	data->dev = dev;
 
 	data->old_opp.rate = old_freq;
-	size = sizeof(*old_supply) * opp_table->regulator_count;
+	size = sizeof(*old_supply) * count;
 	if (!old_supply)
 		memset(data->old_opp.supplies, 0, size);
 	else
@@ -1860,8 +1865,14 @@ static int _allocate_set_opp_data(struct opp_table *opp_table)
 	struct dev_pm_set_opp_data *data;
 	int len, count = opp_table->regulator_count;
 
-	if (WARN_ON(!opp_table->regulators))
-		return -EINVAL;
+	/* just bump the refcount if already allocated */
+	if (opp_table->set_opp_data) {
+		kref_get(&opp_table->set_opp_data->kref);
+		return 0;
+	}
+
+	/* allocate maximum number of regulators, for simplicity */
+	count = max(count, 1);
 
 	/* space for set_opp_data */
 	len = sizeof(*data);
@@ -1873,6 +1884,7 @@ static int _allocate_set_opp_data(struct opp_table *opp_table)
 	if (!data)
 		return -ENOMEM;
 
+	kref_init(&data->kref);
 	data->old_opp.supplies = (void *)(data + 1);
 	data->new_opp.supplies = data->old_opp.supplies + count;
 
@@ -1881,10 +1893,17 @@ static int _allocate_set_opp_data(struct opp_table *opp_table)
 	return 0;
 }
 
+static void _release_set_opp_data(struct kref *kref)
+{
+	kfree(container_of(kref, struct dev_pm_set_opp_data, kref));
+}
+
 static void _free_set_opp_data(struct opp_table *opp_table)
 {
-	kfree(opp_table->set_opp_data);
-	opp_table->set_opp_data = NULL;
+	struct dev_pm_set_opp_data *data = opp_table->set_opp_data;
+
+	if (kref_put(&data->kref, _release_set_opp_data))
+		opp_table->set_opp_data = NULL;
 }
 
 /**
@@ -2182,6 +2201,7 @@ struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
 			int (*set_opp)(struct dev_pm_set_opp_data *data))
 {
 	struct opp_table *opp_table;
+	int ret;
 
 	if (!set_opp)
 		return ERR_PTR(-EINVAL);
@@ -2196,11 +2216,21 @@ struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
 		return ERR_PTR(-EBUSY);
 	}
 
+	/* Allocate block to pass to set_opp() routines */
+	ret = _allocate_set_opp_data(opp_table);
+	if (ret)
+		goto err;
+
 	/* Another CPU that shares the OPP table has set the helper ? */
 	if (!opp_table->set_opp)
 		opp_table->set_opp = set_opp;
 
 	return opp_table;
+
+err:
+	dev_pm_opp_put_opp_table(opp_table);
+
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_register_set_opp_helper);
 
@@ -2219,6 +2249,8 @@ void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table)
 	/* Make sure there are no concurrent readers while updating opp_table */
 	WARN_ON(!list_empty(&opp_table->opp_list));
 
+	_free_set_opp_data(opp_table);
+
 	opp_table->set_opp = NULL;
 	dev_pm_opp_put_opp_table(opp_table);
 }
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index eefd0b15890c..c98fd2add563 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -13,6 +13,7 @@
 
 #include <linux/energy_model.h>
 #include <linux/err.h>
+#include <linux/kref.h>
 #include <linux/notifier.h>
 
 struct clk;
@@ -74,6 +75,7 @@ struct dev_pm_opp_info {
  * @regulator_count: Number of regulators
  * @clk:	Pointer to clk
  * @dev:	Pointer to the struct device
+ * @kref:	Reference counter
  *
  * This structure contains all information required for setting an OPP.
  */
@@ -85,6 +87,7 @@ struct dev_pm_set_opp_data {
 	unsigned int regulator_count;
 	struct clk *clk;
 	struct device *dev;
+	struct kref kref;
 };
 
 #if defined(CONFIG_PM_OPP)
-- 
2.29.2


  parent reply	other threads:[~2021-01-18  1:04 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-18  0:55 [PATCH v3 00/12] OPP API fixes and improvements Dmitry Osipenko
2021-01-18  0:55 ` [PATCH v3 01/12] opp: Fix adding OPP entries in a wrong order if rate is unavailable Dmitry Osipenko
2021-01-18  7:44   ` Viresh Kumar
2021-01-18 18:46     ` Dmitry Osipenko
2021-01-18  0:55 ` [PATCH v3 02/12] opp: Filter out OPPs based on availability of a required-OPP Dmitry Osipenko
2021-01-18  8:11   ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 03/12] opp: Correct debug message in _opp_add_static_v2() Dmitry Osipenko
2021-01-18  8:14   ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 04/12] opp: Add dev_pm_opp_sync_regulators() Dmitry Osipenko
2021-01-18  4:19   ` kernel test robot
2021-01-18  8:20   ` Viresh Kumar
2021-01-18 18:35     ` Dmitry Osipenko
2021-01-19  4:58       ` Viresh Kumar
2021-01-19 22:42         ` Dmitry Osipenko
2021-01-18 11:00   ` Viresh Kumar
2021-01-18 11:06     ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 05/12] opp: Add dev_pm_opp_set_voltage() Dmitry Osipenko
2021-01-18  9:52   ` Viresh Kumar
2021-01-18 19:14     ` Dmitry Osipenko
2021-01-20 21:57       ` Dmitry Osipenko
2021-01-21 11:20         ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 06/12] opp: Add dev_pm_opp_find_level_ceil() Dmitry Osipenko
2021-01-18  9:58   ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 07/12] opp: Add dev_pm_opp_get_required_pstate() Dmitry Osipenko
2021-01-18 10:50   ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 08/12] opp: Add devm_pm_opp_register_set_opp_helper Dmitry Osipenko
2021-01-18 11:07   ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 09/12] opp: Add devm_pm_opp_attach_genpd Dmitry Osipenko
2021-01-18 11:14   ` Viresh Kumar
2021-01-18  0:55 ` Dmitry Osipenko [this message]
2021-01-18 11:44   ` [PATCH v3 10/12] opp: Support set_opp() customization without requiring to use regulators Viresh Kumar
2021-01-18 18:48     ` Dmitry Osipenko
2021-01-19  6:35       ` [PATCH] opp: Prepare for ->set_opp() helper to work without regulators Viresh Kumar
2021-01-19 17:16         ` Dmitry Osipenko
2021-01-20  7:39           ` Viresh Kumar
2021-01-20 14:50             ` Dmitry Osipenko
2021-01-21 11:25               ` Viresh Kumar
2021-01-19 17:18         ` Dmitry Osipenko
2021-01-20  8:08         ` Viresh Kumar
2021-01-21 11:28           ` Viresh Kumar
2021-01-19  6:36       ` [PATCH v3 10/12] opp: Support set_opp() customization without requiring to use regulators Viresh Kumar
2021-01-21 11:30       ` [PATCH V2] opp: Prepare for ->set_opp() helper to work without regulators Viresh Kumar
2021-01-21 21:02         ` Dmitry Osipenko
2021-01-22  3:05           ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 11/12] opp: Handle missing OPP table in dev_pm_opp_xlate_performance_state() Dmitry Osipenko
2021-01-18 11:18   ` Viresh Kumar
2021-01-18  0:55 ` [PATCH v3 12/12] opp: Print OPP level in debug message of _opp_add_static_v2() Dmitry Osipenko
2021-01-18 11:18   ` Viresh Kumar
2021-01-18 11:46 ` [PATCH v3 00/12] OPP API fixes and improvements Viresh Kumar
2021-01-19 17:35   ` Dmitry Osipenko
2021-01-20 15:41     ` Dmitry Osipenko
2021-01-21  7:51       ` Viresh Kumar
2021-01-21 20:30         ` Dmitry Osipenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210118005524.27787-11-digetx@gmail.com \
    --to=digetx@gmail.com \
    --cc=broonie@kernel.org \
    --cc=jonathanh@nvidia.com \
    --cc=khilman@kernel.org \
    --cc=kwizart@gmail.com \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=mattmerhar@protonmail.com \
    --cc=nm@ti.com \
    --cc=pdeschrijver@nvidia.com \
    --cc=pgwipeout@gmail.com \
    --cc=rjw@rjwysocki.net \
    --cc=sboyd@kernel.org \
    --cc=thierry.reding@gmail.com \
    --cc=tiny.windzz@gmail.com \
    --cc=ulf.hansson@linaro.org \
    --cc=vireshk@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.