linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table
@ 2020-11-06  6:24 Viresh Kumar
  2020-11-06  6:24 ` [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table() Viresh Kumar
       [not found] ` <CGME20201109124218eucas1p1b8948a9bf2cf107b17b500b1603905e8@eucas1p1.samsung.com>
  0 siblings, 2 replies; 12+ messages in thread
From: Viresh Kumar @ 2020-11-06  6:24 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar
  Cc: linux-pm, Vincent Guittot, Stephen Boyd, Nishanth Menon, digetx,
	Stephan Gerhold, linux-kernel

Initially, the helper dev_pm_opp_get_opp_table() was supposed to be used
only for the OPP core's internal use (it tries to find an existing OPP
table and if it doesn't find one, then it allocates the OPP table).

Sometime back, the cpufreq-dt driver started using it to make sure all
the relevant resources required by the OPP core are available earlier
during initialization process to properly propagate -EPROBE_DEFER.

It worked but it also abused the API to create an OPP table, which
should be created with the help of other helpers provided by the OPP
core.

The OPP core will be updated in a later commit to limit the scope of
dev_pm_opp_get_opp_table() to only finding an existing OPP table and not
create one. This commit updates the cpufreq-dt driver before that
happens.

Now the cpufreq-dt driver creates the OPP and cpufreq tables for all the
CPUs from driver's init callback itself.

Cc: Stephan Gerhold <stephan@gerhold.net>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq-dt.c | 158 +++++++++++++++--------------------
 1 file changed, 68 insertions(+), 90 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index e363ae04aac6..66b3db5efb53 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -30,7 +30,7 @@ struct private_data {
 	cpumask_var_t cpus;
 	struct device *cpu_dev;
 	struct opp_table *opp_table;
-	struct opp_table *reg_opp_table;
+	struct cpufreq_frequency_table *freq_table;
 	bool have_static_opps;
 };
 
@@ -102,7 +102,6 @@ static const char *find_supply_name(struct device *dev)
 
 static int cpufreq_init(struct cpufreq_policy *policy)
 {
-	struct cpufreq_frequency_table *freq_table;
 	struct private_data *priv;
 	struct device *cpu_dev;
 	struct clk *cpu_clk;
@@ -114,9 +113,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		pr_err("failed to find data for cpu%d\n", policy->cpu);
 		return -ENODEV;
 	}
-
 	cpu_dev = priv->cpu_dev;
-	cpumask_copy(policy->cpus, priv->cpus);
 
 	cpu_clk = clk_get(cpu_dev, NULL);
 	if (IS_ERR(cpu_clk)) {
@@ -125,67 +122,32 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		return ret;
 	}
 
-	/*
-	 * Initialize OPP tables for all policy->cpus. They will be shared by
-	 * all CPUs which have marked their CPUs shared with OPP bindings.
-	 *
-	 * For platforms not using operating-points-v2 bindings, we do this
-	 * before updating policy->cpus. Otherwise, we will end up creating
-	 * duplicate OPPs for policy->cpus.
-	 *
-	 * OPPs might be populated at runtime, don't check for error here
-	 */
-	if (!dev_pm_opp_of_cpumask_add_table(policy->cpus))
-		priv->have_static_opps = true;
-
-	/*
-	 * But we need OPP table to function so if it is not there let's
-	 * give platform code chance to provide it for us.
-	 */
-	ret = dev_pm_opp_get_opp_count(cpu_dev);
-	if (ret <= 0) {
-		dev_err(cpu_dev, "OPP table can't be empty\n");
-		ret = -ENODEV;
-		goto out_free_opp;
-	}
-
-	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
-	if (ret) {
-		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
-		goto out_free_opp;
-	}
+	transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
+	if (!transition_latency)
+		transition_latency = CPUFREQ_ETERNAL;
 
+	cpumask_copy(policy->cpus, priv->cpus);
 	policy->driver_data = priv;
 	policy->clk = cpu_clk;
-	policy->freq_table = freq_table;
-
+	policy->freq_table = priv->freq_table;
 	policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
+	policy->cpuinfo.transition_latency = transition_latency;
+	policy->dvfs_possible_from_any_cpu = true;
 
 	/* Support turbo/boost mode */
 	if (policy_has_boost_freq(policy)) {
 		/* This gets disabled by core on driver unregister */
 		ret = cpufreq_enable_boost_support();
 		if (ret)
-			goto out_free_cpufreq_table;
+			goto out_clk_put;
 		cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
 	}
 
-	transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
-	if (!transition_latency)
-		transition_latency = CPUFREQ_ETERNAL;
-
-	policy->cpuinfo.transition_latency = transition_latency;
-	policy->dvfs_possible_from_any_cpu = true;
-
 	dev_pm_opp_of_register_em(cpu_dev, policy->cpus);
 
 	return 0;
 
-out_free_cpufreq_table:
-	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
-out_free_opp:
-	if (priv->have_static_opps)
-		dev_pm_opp_of_cpumask_remove_table(policy->cpus);
+out_clk_put:
 	clk_put(cpu_clk);
 
 	return ret;
@@ -208,11 +170,6 @@ static int cpufreq_offline(struct cpufreq_policy *policy)
 
 static int cpufreq_exit(struct cpufreq_policy *policy)
 {
-	struct private_data *priv = policy->driver_data;
-
-	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
-	if (priv->have_static_opps)
-		dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
 	clk_put(policy->clk);
 	return 0;
 }
@@ -236,6 +193,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
 {
 	struct private_data *priv;
 	struct device *cpu_dev;
+	bool fallback = false;
 	const char *reg_name;
 	int ret;
 
@@ -254,69 +212,87 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
 	if (!alloc_cpumask_var(&priv->cpus, GFP_KERNEL))
 		return -ENOMEM;
 
+	cpumask_set_cpu(cpu, priv->cpus);
 	priv->cpu_dev = cpu_dev;
 
-	/* Try to get OPP table early to ensure resources are available */
-	priv->opp_table = dev_pm_opp_get_opp_table(cpu_dev);
-	if (IS_ERR(priv->opp_table)) {
-		ret = PTR_ERR(priv->opp_table);
-		if (ret != -EPROBE_DEFER)
-			dev_err(cpu_dev, "failed to get OPP table: %d\n", ret);
-		goto free_cpumask;
-	}
-
 	/*
 	 * OPP layer will be taking care of regulators now, but it needs to know
 	 * the name of the regulator first.
 	 */
 	reg_name = find_supply_name(cpu_dev);
 	if (reg_name) {
-		priv->reg_opp_table = dev_pm_opp_set_regulators(cpu_dev,
-								&reg_name, 1);
-		if (IS_ERR(priv->reg_opp_table)) {
-			ret = PTR_ERR(priv->reg_opp_table);
+		priv->opp_table = dev_pm_opp_set_regulators(cpu_dev, &reg_name,
+							    1);
+		if (IS_ERR(priv->opp_table)) {
+			ret = PTR_ERR(priv->opp_table);
 			if (ret != -EPROBE_DEFER)
 				dev_err(cpu_dev, "failed to set regulators: %d\n",
 					ret);
-			goto put_table;
+			goto out;
 		}
 	}
 
-	/* Find OPP sharing information so we can fill pri->cpus here */
 	/* Get OPP-sharing information from "operating-points-v2" bindings */
 	ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->cpus);
 	if (ret) {
 		if (ret != -ENOENT)
-			goto put_reg;
+			goto out;
 
 		/*
 		 * operating-points-v2 not supported, fallback to all CPUs share
 		 * OPP for backward compatibility if the platform hasn't set
 		 * sharing CPUs.
 		 */
-		if (dev_pm_opp_get_sharing_cpus(cpu_dev, priv->cpus)) {
-			cpumask_setall(priv->cpus);
-
-			/*
-			 * OPP tables are initialized only for cpu, do it for
-			 * others as well.
-			 */
-			ret = dev_pm_opp_set_sharing_cpus(cpu_dev, priv->cpus);
-			if (ret)
-				dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
-					__func__, ret);
-		}
+		if (dev_pm_opp_get_sharing_cpus(cpu_dev, priv->cpus))
+			fallback = true;
+	}
+
+	/*
+	 * Initialize OPP tables for all priv->cpus. They will be shared by
+	 * all CPUs which have marked their CPUs shared with OPP bindings.
+	 *
+	 * For platforms not using operating-points-v2 bindings, we do this
+	 * before updating priv->cpus. Otherwise, we will end up creating
+	 * duplicate OPPs for the CPUs.
+	 *
+	 * OPPs might be populated at runtime, don't check for error here.
+	 */
+	if (!dev_pm_opp_of_cpumask_add_table(priv->cpus))
+		priv->have_static_opps = true;
+
+	/*
+	 * The OPP table must be initialized, statically or dynamically, by this
+	 * point.
+	 */
+	ret = dev_pm_opp_get_opp_count(cpu_dev);
+	if (ret <= 0) {
+		dev_err(cpu_dev, "OPP table can't be empty\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (fallback) {
+		cpumask_setall(priv->cpus);
+		ret = dev_pm_opp_set_sharing_cpus(cpu_dev, priv->cpus);
+		if (ret)
+			dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
+				__func__, ret);
+	}
+
+	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &priv->freq_table);
+	if (ret) {
+		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
+		goto out;
 	}
 
 	list_add(&priv->node, &priv_list);
 	return 0;
 
-put_reg:
-	if (priv->reg_opp_table)
-		dev_pm_opp_put_regulators(priv->reg_opp_table);
-put_table:
-	dev_pm_opp_put_opp_table(priv->opp_table);
-free_cpumask:
+out:
+	if (priv->have_static_opps)
+		dev_pm_opp_of_cpumask_remove_table(priv->cpus);
+	if (priv->opp_table)
+		dev_pm_opp_put_regulators(priv->opp_table);
 	free_cpumask_var(priv->cpus);
 	return ret;
 }
@@ -326,9 +302,11 @@ static void dt_cpufreq_release(void)
 	struct private_data *priv, *tmp;
 
 	list_for_each_entry_safe(priv, tmp, &priv_list, node) {
-		if (priv->reg_opp_table)
-			dev_pm_opp_put_regulators(priv->reg_opp_table);
-		dev_pm_opp_put_opp_table(priv->opp_table);
+		dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &priv->freq_table);
+		if (priv->have_static_opps)
+			dev_pm_opp_of_cpumask_remove_table(priv->cpus);
+		if (priv->opp_table)
+			dev_pm_opp_put_regulators(priv->opp_table);
 		free_cpumask_var(priv->cpus);
 		list_del(&priv->node);
 	}
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table()
  2020-11-06  6:24 [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table Viresh Kumar
@ 2020-11-06  6:24 ` Viresh Kumar
  2020-11-06 10:25   ` Ulf Hansson
  2020-11-06 13:18   ` Dmitry Osipenko
       [not found] ` <CGME20201109124218eucas1p1b8948a9bf2cf107b17b500b1603905e8@eucas1p1.samsung.com>
  1 sibling, 2 replies; 12+ messages in thread
From: Viresh Kumar @ 2020-11-06  6:24 UTC (permalink / raw)
  To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Len Brown,
	Pavel Machek, Greg Kroah-Hartman, Viresh Kumar, Nishanth Menon,
	Stephen Boyd
  Cc: Viresh Kumar, linux-pm, Vincent Guittot, digetx, linux-kernel

It has been found that some users (like cpufreq-dt and others on LKML)
have abused the helper dev_pm_opp_get_opp_table() to create the OPP
table instead of just finding it, which is the wrong thing to do. This
routine was meant for OPP core's internal working and exposed the whole
functionality by mistake.

Change the scope of dev_pm_opp_get_opp_table() to only finding the
table. The internal helpers _opp_get_opp_table*() are thus renamed to
_add_opp_table*(), dev_pm_opp_get_opp_table_indexed() is removed (as we
don't need the index field for finding the OPP table) and so the only
user, genpd, is updated.

Note that the prototype of _add_opp_table() was already left in opp.h by
mistake when it was removed earlier and so we weren't required to add it
now.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/domain.c |  2 +-
 drivers/opp/core.c          | 27 +++++++++++++--------------
 drivers/opp/of.c            |  4 ++--
 drivers/opp/opp.h           |  1 +
 include/linux/pm_opp.h      |  1 -
 5 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 743268996336..92b750b865d5 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2249,7 +2249,7 @@ int of_genpd_add_provider_onecell(struct device_node *np,
 			 * Save table for faster processing while setting
 			 * performance state.
 			 */
-			genpd->opp_table = dev_pm_opp_get_opp_table_indexed(&genpd->dev, i);
+			genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev);
 			WARN_ON(IS_ERR(genpd->opp_table));
 		}
 
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 9915e8487f0b..b24f685823ae 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1138,7 +1138,7 @@ void _get_opp_table_kref(struct opp_table *opp_table)
  * uses the opp_tables_busy flag to indicate if another creator is in the middle
  * of adding an OPP table and others should wait for it to finish.
  */
-static struct opp_table *_opp_get_opp_table(struct device *dev, int index)
+struct opp_table *_add_opp_table_indexed(struct device *dev, int index)
 {
 	struct opp_table *opp_table;
 
@@ -1188,17 +1188,16 @@ static struct opp_table *_opp_get_opp_table(struct device *dev, int index)
 	return opp_table;
 }
 
-struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
+struct opp_table *_add_opp_table(struct device *dev)
 {
-	return _opp_get_opp_table(dev, 0);
+	return _add_opp_table_indexed(dev, 0);
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table);
 
-struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev,
-						   int index)
+struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
 {
-	return _opp_get_opp_table(dev, index);
+	return _find_opp_table(dev);
 }
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table);
 
 static void _opp_table_kref_release(struct kref *kref)
 {
@@ -1627,7 +1626,7 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
 {
 	struct opp_table *opp_table;
 
-	opp_table = dev_pm_opp_get_opp_table(dev);
+	opp_table = _add_opp_table(dev);
 	if (IS_ERR(opp_table))
 		return opp_table;
 
@@ -1686,7 +1685,7 @@ struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
 {
 	struct opp_table *opp_table;
 
-	opp_table = dev_pm_opp_get_opp_table(dev);
+	opp_table = _add_opp_table(dev);
 	if (IS_ERR(opp_table))
 		return opp_table;
 
@@ -1779,7 +1778,7 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
 	struct regulator *reg;
 	int ret, i;
 
-	opp_table = dev_pm_opp_get_opp_table(dev);
+	opp_table = _add_opp_table(dev);
 	if (IS_ERR(opp_table))
 		return opp_table;
 
@@ -1887,7 +1886,7 @@ struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name)
 	struct opp_table *opp_table;
 	int ret;
 
-	opp_table = dev_pm_opp_get_opp_table(dev);
+	opp_table = _add_opp_table(dev);
 	if (IS_ERR(opp_table))
 		return opp_table;
 
@@ -1955,7 +1954,7 @@ struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
 	if (!set_opp)
 		return ERR_PTR(-EINVAL);
 
-	opp_table = dev_pm_opp_get_opp_table(dev);
+	opp_table = _add_opp_table(dev);
 	if (IS_ERR(opp_table))
 		return opp_table;
 
@@ -2039,7 +2038,7 @@ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev,
 	int index = 0, ret = -EINVAL;
 	const char **name = names;
 
-	opp_table = dev_pm_opp_get_opp_table(dev);
+	opp_table = _add_opp_table(dev);
 	if (IS_ERR(opp_table))
 		return opp_table;
 
@@ -2204,7 +2203,7 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 	struct opp_table *opp_table;
 	int ret;
 
-	opp_table = dev_pm_opp_get_opp_table(dev);
+	opp_table = _add_opp_table(dev);
 	if (IS_ERR(opp_table))
 		return PTR_ERR(opp_table);
 
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 9faeb83e4b32..c718092757d9 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -974,7 +974,7 @@ int dev_pm_opp_of_add_table(struct device *dev)
 	struct opp_table *opp_table;
 	int ret;
 
-	opp_table = dev_pm_opp_get_opp_table_indexed(dev, 0);
+	opp_table = _add_opp_table_indexed(dev, 0);
 	if (IS_ERR(opp_table))
 		return PTR_ERR(opp_table);
 
@@ -1029,7 +1029,7 @@ int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
 			index = 0;
 	}
 
-	opp_table = dev_pm_opp_get_opp_table_indexed(dev, index);
+	opp_table = _add_opp_table_indexed(dev, index);
 	if (IS_ERR(opp_table))
 		return PTR_ERR(opp_table);
 
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index ebd930e0b3ca..4ced7ffa8158 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -224,6 +224,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *o
 int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
 void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
 struct opp_table *_add_opp_table(struct device *dev);
+struct opp_table *_add_opp_table_indexed(struct device *dev, int index);
 void _put_opp_list_kref(struct opp_table *opp_table);
 
 #ifdef CONFIG_OF
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index dbb484524f82..1435c054016a 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -90,7 +90,6 @@ struct dev_pm_set_opp_data {
 #if defined(CONFIG_PM_OPP)
 
 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
-struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, int index);
 void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
 
 unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table()
  2020-11-06  6:24 ` [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table() Viresh Kumar
@ 2020-11-06 10:25   ` Ulf Hansson
  2020-11-06 13:18   ` Dmitry Osipenko
  1 sibling, 0 replies; 12+ messages in thread
From: Ulf Hansson @ 2020-11-06 10:25 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, Kevin Hilman, Len Brown, Pavel Machek,
	Greg Kroah-Hartman, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Linux PM, Vincent Guittot, Dmitry Osipenko,
	Linux Kernel Mailing List

On Fri, 6 Nov 2020 at 07:25, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> It has been found that some users (like cpufreq-dt and others on LKML)
> have abused the helper dev_pm_opp_get_opp_table() to create the OPP
> table instead of just finding it, which is the wrong thing to do. This
> routine was meant for OPP core's internal working and exposed the whole
> functionality by mistake.
>
> Change the scope of dev_pm_opp_get_opp_table() to only finding the
> table. The internal helpers _opp_get_opp_table*() are thus renamed to
> _add_opp_table*(), dev_pm_opp_get_opp_table_indexed() is removed (as we
> don't need the index field for finding the OPP table) and so the only
> user, genpd, is updated.
>
> Note that the prototype of _add_opp_table() was already left in opp.h by
> mistake when it was removed earlier and so we weren't required to add it
> now.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

Acked-by: Ulf Hansson <ulf.hansson@linaro.org>

Kind regards
Uffe

> ---
>  drivers/base/power/domain.c |  2 +-
>  drivers/opp/core.c          | 27 +++++++++++++--------------
>  drivers/opp/of.c            |  4 ++--
>  drivers/opp/opp.h           |  1 +
>  include/linux/pm_opp.h      |  1 -
>  5 files changed, 17 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> index 743268996336..92b750b865d5 100644
> --- a/drivers/base/power/domain.c
> +++ b/drivers/base/power/domain.c
> @@ -2249,7 +2249,7 @@ int of_genpd_add_provider_onecell(struct device_node *np,
>                          * Save table for faster processing while setting
>                          * performance state.
>                          */
> -                       genpd->opp_table = dev_pm_opp_get_opp_table_indexed(&genpd->dev, i);
> +                       genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev);
>                         WARN_ON(IS_ERR(genpd->opp_table));
>                 }
>
> diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> index 9915e8487f0b..b24f685823ae 100644
> --- a/drivers/opp/core.c
> +++ b/drivers/opp/core.c
> @@ -1138,7 +1138,7 @@ void _get_opp_table_kref(struct opp_table *opp_table)
>   * uses the opp_tables_busy flag to indicate if another creator is in the middle
>   * of adding an OPP table and others should wait for it to finish.
>   */
> -static struct opp_table *_opp_get_opp_table(struct device *dev, int index)
> +struct opp_table *_add_opp_table_indexed(struct device *dev, int index)
>  {
>         struct opp_table *opp_table;
>
> @@ -1188,17 +1188,16 @@ static struct opp_table *_opp_get_opp_table(struct device *dev, int index)
>         return opp_table;
>  }
>
> -struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
> +struct opp_table *_add_opp_table(struct device *dev)
>  {
> -       return _opp_get_opp_table(dev, 0);
> +       return _add_opp_table_indexed(dev, 0);
>  }
> -EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table);
>
> -struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev,
> -                                                  int index)
> +struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
>  {
> -       return _opp_get_opp_table(dev, index);
> +       return _find_opp_table(dev);
>  }
> +EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table);
>
>  static void _opp_table_kref_release(struct kref *kref)
>  {
> @@ -1627,7 +1626,7 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
>  {
>         struct opp_table *opp_table;
>
> -       opp_table = dev_pm_opp_get_opp_table(dev);
> +       opp_table = _add_opp_table(dev);
>         if (IS_ERR(opp_table))
>                 return opp_table;
>
> @@ -1686,7 +1685,7 @@ struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
>  {
>         struct opp_table *opp_table;
>
> -       opp_table = dev_pm_opp_get_opp_table(dev);
> +       opp_table = _add_opp_table(dev);
>         if (IS_ERR(opp_table))
>                 return opp_table;
>
> @@ -1779,7 +1778,7 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
>         struct regulator *reg;
>         int ret, i;
>
> -       opp_table = dev_pm_opp_get_opp_table(dev);
> +       opp_table = _add_opp_table(dev);
>         if (IS_ERR(opp_table))
>                 return opp_table;
>
> @@ -1887,7 +1886,7 @@ struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name)
>         struct opp_table *opp_table;
>         int ret;
>
> -       opp_table = dev_pm_opp_get_opp_table(dev);
> +       opp_table = _add_opp_table(dev);
>         if (IS_ERR(opp_table))
>                 return opp_table;
>
> @@ -1955,7 +1954,7 @@ struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
>         if (!set_opp)
>                 return ERR_PTR(-EINVAL);
>
> -       opp_table = dev_pm_opp_get_opp_table(dev);
> +       opp_table = _add_opp_table(dev);
>         if (IS_ERR(opp_table))
>                 return opp_table;
>
> @@ -2039,7 +2038,7 @@ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev,
>         int index = 0, ret = -EINVAL;
>         const char **name = names;
>
> -       opp_table = dev_pm_opp_get_opp_table(dev);
> +       opp_table = _add_opp_table(dev);
>         if (IS_ERR(opp_table))
>                 return opp_table;
>
> @@ -2204,7 +2203,7 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
>         struct opp_table *opp_table;
>         int ret;
>
> -       opp_table = dev_pm_opp_get_opp_table(dev);
> +       opp_table = _add_opp_table(dev);
>         if (IS_ERR(opp_table))
>                 return PTR_ERR(opp_table);
>
> diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> index 9faeb83e4b32..c718092757d9 100644
> --- a/drivers/opp/of.c
> +++ b/drivers/opp/of.c
> @@ -974,7 +974,7 @@ int dev_pm_opp_of_add_table(struct device *dev)
>         struct opp_table *opp_table;
>         int ret;
>
> -       opp_table = dev_pm_opp_get_opp_table_indexed(dev, 0);
> +       opp_table = _add_opp_table_indexed(dev, 0);
>         if (IS_ERR(opp_table))
>                 return PTR_ERR(opp_table);
>
> @@ -1029,7 +1029,7 @@ int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
>                         index = 0;
>         }
>
> -       opp_table = dev_pm_opp_get_opp_table_indexed(dev, index);
> +       opp_table = _add_opp_table_indexed(dev, index);
>         if (IS_ERR(opp_table))
>                 return PTR_ERR(opp_table);
>
> diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
> index ebd930e0b3ca..4ced7ffa8158 100644
> --- a/drivers/opp/opp.h
> +++ b/drivers/opp/opp.h
> @@ -224,6 +224,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *o
>  int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
>  void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
>  struct opp_table *_add_opp_table(struct device *dev);
> +struct opp_table *_add_opp_table_indexed(struct device *dev, int index);
>  void _put_opp_list_kref(struct opp_table *opp_table);
>
>  #ifdef CONFIG_OF
> diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
> index dbb484524f82..1435c054016a 100644
> --- a/include/linux/pm_opp.h
> +++ b/include/linux/pm_opp.h
> @@ -90,7 +90,6 @@ struct dev_pm_set_opp_data {
>  #if defined(CONFIG_PM_OPP)
>
>  struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
> -struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, int index);
>  void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
>
>  unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
> --
> 2.25.0.rc1.19.g042ed3e048af
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table()
  2020-11-06  6:24 ` [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table() Viresh Kumar
  2020-11-06 10:25   ` Ulf Hansson
@ 2020-11-06 13:18   ` Dmitry Osipenko
  2020-11-09  4:34     ` Viresh Kumar
  1 sibling, 1 reply; 12+ messages in thread
From: Dmitry Osipenko @ 2020-11-06 13:18 UTC (permalink / raw)
  To: Viresh Kumar, Rafael J. Wysocki, Kevin Hilman, Ulf Hansson,
	Len Brown, Pavel Machek, Greg Kroah-Hartman, Viresh Kumar,
	Nishanth Menon, Stephen Boyd
  Cc: linux-pm, Vincent Guittot, linux-kernel

06.11.2020 09:24, Viresh Kumar пишет:
> It has been found that some users (like cpufreq-dt and others on LKML)
> have abused the helper dev_pm_opp_get_opp_table() to create the OPP
> table instead of just finding it, which is the wrong thing to do. This
> routine was meant for OPP core's internal working and exposed the whole
> functionality by mistake.
> 
> Change the scope of dev_pm_opp_get_opp_table() to only finding the
> table. The internal helpers _opp_get_opp_table*() are thus renamed to
> _add_opp_table*(), dev_pm_opp_get_opp_table_indexed() is removed (as we
> don't need the index field for finding the OPP table) and so the only
> user, genpd, is updated.
> 
> Note that the prototype of _add_opp_table() was already left in opp.h by
> mistake when it was removed earlier and so we weren't required to add it
> now.

Hello Viresh,

It looks like this is not an entirely correct change because previously
it was possible to get an empty opp_table in order to use it for the
dev_pm_opp_set_rate(), which would fall back to clk_set_rate if table is
empty.

Now it's not possible to get an empty table and
dev_pm_opp_of_add_table() would error out if OPPs are missing in a
device-tree. Hence it's not possible to implement a fall back without
abusing opp_set_regulators() or opp_set_supported_hw() for getting the
empty table. Or am I missing something?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table()
  2020-11-06 13:18   ` Dmitry Osipenko
@ 2020-11-09  4:34     ` Viresh Kumar
  2020-11-09  4:41       ` Dmitry Osipenko
  0 siblings, 1 reply; 12+ messages in thread
From: Viresh Kumar @ 2020-11-09  4:34 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Len Brown,
	Pavel Machek, Greg Kroah-Hartman, Viresh Kumar, Nishanth Menon,
	Stephen Boyd, linux-pm, Vincent Guittot, linux-kernel

On 06-11-20, 16:18, Dmitry Osipenko wrote:
> 06.11.2020 09:24, Viresh Kumar пишет:
> > It has been found that some users (like cpufreq-dt and others on LKML)
> > have abused the helper dev_pm_opp_get_opp_table() to create the OPP
> > table instead of just finding it, which is the wrong thing to do. This
> > routine was meant for OPP core's internal working and exposed the whole
> > functionality by mistake.
> > 
> > Change the scope of dev_pm_opp_get_opp_table() to only finding the
> > table. The internal helpers _opp_get_opp_table*() are thus renamed to
> > _add_opp_table*(), dev_pm_opp_get_opp_table_indexed() is removed (as we
> > don't need the index field for finding the OPP table) and so the only
> > user, genpd, is updated.
> > 
> > Note that the prototype of _add_opp_table() was already left in opp.h by
> > mistake when it was removed earlier and so we weren't required to add it
> > now.
> 
> Hello Viresh,
> 
> It looks like this is not an entirely correct change because previously
> it was possible to get an empty opp_table in order to use it for the
> dev_pm_opp_set_rate(), which would fall back to clk_set_rate if table is
> empty.
> 
> Now it's not possible to get an empty table and
> dev_pm_opp_of_add_table() would error out if OPPs are missing in a
> device-tree. Hence it's not possible to implement a fall back without
> abusing opp_set_regulators() or opp_set_supported_hw() for getting the
> empty table. Or am I missing something?

For that case you were always required to call
dev_pm_opp_set_clkname(), otherwise how would the OPP core know which
clock to set ? And the same shall work now as well.

-- 
viresh

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table()
  2020-11-09  4:34     ` Viresh Kumar
@ 2020-11-09  4:41       ` Dmitry Osipenko
  2020-11-09  4:57         ` Viresh Kumar
  0 siblings, 1 reply; 12+ messages in thread
From: Dmitry Osipenko @ 2020-11-09  4:41 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Len Brown,
	Pavel Machek, Greg Kroah-Hartman, Viresh Kumar, Nishanth Menon,
	Stephen Boyd, linux-pm, Vincent Guittot, linux-kernel

09.11.2020 07:34, Viresh Kumar пишет:
> On 06-11-20, 16:18, Dmitry Osipenko wrote:
>> 06.11.2020 09:24, Viresh Kumar пишет:
>>> It has been found that some users (like cpufreq-dt and others on LKML)
>>> have abused the helper dev_pm_opp_get_opp_table() to create the OPP
>>> table instead of just finding it, which is the wrong thing to do. This
>>> routine was meant for OPP core's internal working and exposed the whole
>>> functionality by mistake.
>>>
>>> Change the scope of dev_pm_opp_get_opp_table() to only finding the
>>> table. The internal helpers _opp_get_opp_table*() are thus renamed to
>>> _add_opp_table*(), dev_pm_opp_get_opp_table_indexed() is removed (as we
>>> don't need the index field for finding the OPP table) and so the only
>>> user, genpd, is updated.
>>>
>>> Note that the prototype of _add_opp_table() was already left in opp.h by
>>> mistake when it was removed earlier and so we weren't required to add it
>>> now.
>>
>> Hello Viresh,
>>
>> It looks like this is not an entirely correct change because previously
>> it was possible to get an empty opp_table in order to use it for the
>> dev_pm_opp_set_rate(), which would fall back to clk_set_rate if table is
>> empty.
>>
>> Now it's not possible to get an empty table and
>> dev_pm_opp_of_add_table() would error out if OPPs are missing in a
>> device-tree. Hence it's not possible to implement a fall back without
>> abusing opp_set_regulators() or opp_set_supported_hw() for getting the
>> empty table. Or am I missing something?
> 
> For that case you were always required to call
> dev_pm_opp_set_clkname(), otherwise how would the OPP core know which
> clock to set ? And the same shall work now as well.

Why _allocate_opp_table() grabs the first default clk of a device and
assigns it to the created table?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table()
  2020-11-09  4:41       ` Dmitry Osipenko
@ 2020-11-09  4:57         ` Viresh Kumar
  2020-11-09  5:29           ` Dmitry Osipenko
  0 siblings, 1 reply; 12+ messages in thread
From: Viresh Kumar @ 2020-11-09  4:57 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Len Brown,
	Pavel Machek, Greg Kroah-Hartman, Viresh Kumar, Nishanth Menon,
	Stephen Boyd, linux-pm, Vincent Guittot, linux-kernel

On 09-11-20, 07:41, Dmitry Osipenko wrote:
> 09.11.2020 07:34, Viresh Kumar пишет:
> > On 06-11-20, 16:18, Dmitry Osipenko wrote:
> >> 06.11.2020 09:24, Viresh Kumar пишет:
> >>> It has been found that some users (like cpufreq-dt and others on LKML)
> >>> have abused the helper dev_pm_opp_get_opp_table() to create the OPP
> >>> table instead of just finding it, which is the wrong thing to do. This
> >>> routine was meant for OPP core's internal working and exposed the whole
> >>> functionality by mistake.
> >>>
> >>> Change the scope of dev_pm_opp_get_opp_table() to only finding the
> >>> table. The internal helpers _opp_get_opp_table*() are thus renamed to
> >>> _add_opp_table*(), dev_pm_opp_get_opp_table_indexed() is removed (as we
> >>> don't need the index field for finding the OPP table) and so the only
> >>> user, genpd, is updated.
> >>>
> >>> Note that the prototype of _add_opp_table() was already left in opp.h by
> >>> mistake when it was removed earlier and so we weren't required to add it
> >>> now.
> >>
> >> Hello Viresh,
> >>
> >> It looks like this is not an entirely correct change because previously
> >> it was possible to get an empty opp_table in order to use it for the
> >> dev_pm_opp_set_rate(), which would fall back to clk_set_rate if table is
> >> empty.
> >>
> >> Now it's not possible to get an empty table and
> >> dev_pm_opp_of_add_table() would error out if OPPs are missing in a
> >> device-tree. Hence it's not possible to implement a fall back without
> >> abusing opp_set_regulators() or opp_set_supported_hw() for getting the
> >> empty table. Or am I missing something?
> > 
> > For that case you were always required to call
> > dev_pm_opp_set_clkname(), otherwise how would the OPP core know which
> > clock to set ? And the same shall work now as well.
> 
> Why _allocate_opp_table() grabs the first default clk of a device and
> assigns it to the created table?

Right, it was there so everybody isn't required to call
dev_pm_opp_set_clkname() if they don't need to pass a connection id
while getting the clock. But for the case of supporting empty OPP
tables for cases where we just want dev_pm_opp_set_rate() to act as
clk_set_rate() (in order for the drivers to avoid supporting two
different ways of doing so), we do need that call to be made.

We need to add the OPP table explicitly and what happened with
dev_pm_opp_get_opp_table() was accidental and not what I wanted.

drivers/mmc/host/sdhci-msm.c has an example of how this is done.

-- 
viresh

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table()
  2020-11-09  4:57         ` Viresh Kumar
@ 2020-11-09  5:29           ` Dmitry Osipenko
  0 siblings, 0 replies; 12+ messages in thread
From: Dmitry Osipenko @ 2020-11-09  5:29 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Len Brown,
	Pavel Machek, Greg Kroah-Hartman, Viresh Kumar, Nishanth Menon,
	Stephen Boyd, linux-pm, Vincent Guittot, linux-kernel

09.11.2020 07:57, Viresh Kumar пишет:
> On 09-11-20, 07:41, Dmitry Osipenko wrote:
>> 09.11.2020 07:34, Viresh Kumar пишет:
>>> On 06-11-20, 16:18, Dmitry Osipenko wrote:
>>>> 06.11.2020 09:24, Viresh Kumar пишет:
>>>>> It has been found that some users (like cpufreq-dt and others on LKML)
>>>>> have abused the helper dev_pm_opp_get_opp_table() to create the OPP
>>>>> table instead of just finding it, which is the wrong thing to do. This
>>>>> routine was meant for OPP core's internal working and exposed the whole
>>>>> functionality by mistake.
>>>>>
>>>>> Change the scope of dev_pm_opp_get_opp_table() to only finding the
>>>>> table. The internal helpers _opp_get_opp_table*() are thus renamed to
>>>>> _add_opp_table*(), dev_pm_opp_get_opp_table_indexed() is removed (as we
>>>>> don't need the index field for finding the OPP table) and so the only
>>>>> user, genpd, is updated.
>>>>>
>>>>> Note that the prototype of _add_opp_table() was already left in opp.h by
>>>>> mistake when it was removed earlier and so we weren't required to add it
>>>>> now.
>>>>
>>>> Hello Viresh,
>>>>
>>>> It looks like this is not an entirely correct change because previously
>>>> it was possible to get an empty opp_table in order to use it for the
>>>> dev_pm_opp_set_rate(), which would fall back to clk_set_rate if table is
>>>> empty.
>>>>
>>>> Now it's not possible to get an empty table and
>>>> dev_pm_opp_of_add_table() would error out if OPPs are missing in a
>>>> device-tree. Hence it's not possible to implement a fall back without
>>>> abusing opp_set_regulators() or opp_set_supported_hw() for getting the
>>>> empty table. Or am I missing something?
>>>
>>> For that case you were always required to call
>>> dev_pm_opp_set_clkname(), otherwise how would the OPP core know which
>>> clock to set ? And the same shall work now as well.
>>
>> Why _allocate_opp_table() grabs the first default clk of a device and
>> assigns it to the created table?
> 
> Right, it was there so everybody isn't required to call
> dev_pm_opp_set_clkname() if they don't need to pass a connection id
> while getting the clock. But for the case of supporting empty OPP
> tables for cases where we just want dev_pm_opp_set_rate() to act as
> clk_set_rate() (in order for the drivers to avoid supporting two
> different ways of doing so), we do need that call to be made.
> 
> We need to add the OPP table explicitly and what happened with
> dev_pm_opp_get_opp_table() was accidental and not what I wanted.
> 
> drivers/mmc/host/sdhci-msm.c has an example of how this is done.
> 

Alright, thank you for the clarification.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table
       [not found] ` <CGME20201109124218eucas1p1b8948a9bf2cf107b17b500b1603905e8@eucas1p1.samsung.com>
@ 2020-11-09 12:42   ` Marek Szyprowski
  2020-11-10  6:00     ` Viresh Kumar
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Szyprowski @ 2020-11-09 12:42 UTC (permalink / raw)
  To: Viresh Kumar, Rafael J. Wysocki
  Cc: linux-pm, Vincent Guittot, Stephen Boyd, Nishanth Menon, digetx,
	Stephan Gerhold, linux-kernel, Bartlomiej Zolnierkiewicz

Hi Viresh,

On 06.11.2020 07:24, Viresh Kumar wrote:
> Initially, the helper dev_pm_opp_get_opp_table() was supposed to be used
> only for the OPP core's internal use (it tries to find an existing OPP
> table and if it doesn't find one, then it allocates the OPP table).
>
> Sometime back, the cpufreq-dt driver started using it to make sure all
> the relevant resources required by the OPP core are available earlier
> during initialization process to properly propagate -EPROBE_DEFER.
>
> It worked but it also abused the API to create an OPP table, which
> should be created with the help of other helpers provided by the OPP
> core.
>
> The OPP core will be updated in a later commit to limit the scope of
> dev_pm_opp_get_opp_table() to only finding an existing OPP table and not
> create one. This commit updates the cpufreq-dt driver before that
> happens.
>
> Now the cpufreq-dt driver creates the OPP and cpufreq tables for all the
> CPUs from driver's init callback itself.
>
> Cc: Stephan Gerhold <stephan@gerhold.net>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

This patch landed in linux next-20201109 as commit e8f7703f8fe5 
("cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP 
table"). Sadly it causes regression on some Samsung Exynos based boards:

8<--- cut here ---
Unable to handle kernel paging request at virtual address ffffff37
pgd = (ptrval)
[ffffff37] *pgd=4ffff841, *pte=00000000, *ppte=00000000
Internal error: Oops: 27 [#1] PREEMPT SMP ARM
Modules linked in:
usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.10.0-rc1-00007-ge8f7703f8fe5 
#1908
Hardware name: Samsung Exynos (Flattened Device Tree)
PC is at dev_pm_opp_put_regulators+0x8/0xf0
LR is at dt_cpufreq_probe+0x19c/0x3fc
pc : [<c0847694>]    lr : [<c08538b8>]    psr: a0000013
...
Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
Stack: (0xc1d29da8 to 0xc1d2a000)
...
[<c0847694>] (dev_pm_opp_put_regulators) from [<c08538b8>] 
(dt_cpufreq_probe+0x19c/0x3fc)
[<c08538b8>] (dt_cpufreq_probe) from [<c068eecc>] 
(platform_drv_probe+0x6c/0xa4)
[<c068eecc>] (platform_drv_probe) from [<c068c490>] 
(really_probe+0x200/0x4fc)
[<c068c490>] (really_probe) from [<c068c954>] 
(driver_probe_device+0x78/0x1fc)
[<c068c954>] (driver_probe_device) from [<c068cd3c>] 
(device_driver_attach+0x58/0x60)
[<c068cd3c>] (device_driver_attach) from [<c068ce20>] 
(__driver_attach+0xdc/0x174)
[<c068ce20>] (__driver_attach) from [<c068a218>] 
(bus_for_each_dev+0x68/0xb4)
[<c068a218>] (bus_for_each_dev) from [<c068b54c>] 
(bus_add_driver+0x158/0x214)
[<c068b54c>] (bus_add_driver) from [<c068dc80>] (driver_register+0x78/0x110)
[<c068dc80>] (driver_register) from [<c0102484>] 
(do_one_initcall+0x8c/0x42c)
[<c0102484>] (do_one_initcall) from [<c11011c0>] 
(kernel_init_freeable+0x190/0x1dc)
[<c11011c0>] (kernel_init_freeable) from [<c0b208f8>] 
(kernel_init+0x8/0x118)
[<c0b208f8>] (kernel_init) from [<c0100114>] (ret_from_fork+0x14/0x20)
Exception stack(0xc1d29fb0 to 0xc1d29ff8)
...
---[ end trace 5879c43bc748d0d3 ]---
Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
CPU0: stopping

Reverting this patch and d44aca126b03 ("cpufreq: dt: 
dev_pm_opp_put_regulators() accepts NULL argument"), which depends on 
it, fixes the panic on current linux-next.

> ---
>   drivers/cpufreq/cpufreq-dt.c | 158 +++++++++++++++--------------------
>   1 file changed, 68 insertions(+), 90 deletions(-)
>
> ...

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table
  2020-11-09 12:42   ` [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table Marek Szyprowski
@ 2020-11-10  6:00     ` Viresh Kumar
  2020-11-10  6:57       ` Marek Szyprowski
  0 siblings, 1 reply; 12+ messages in thread
From: Viresh Kumar @ 2020-11-10  6:00 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Rafael J. Wysocki, linux-pm, Vincent Guittot, Stephen Boyd,
	Nishanth Menon, digetx, Stephan Gerhold, linux-kernel,
	Bartlomiej Zolnierkiewicz

On 09-11-20, 13:42, Marek Szyprowski wrote:
> This patch landed in linux next-20201109 as commit e8f7703f8fe5 
> ("cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP 
> table"). Sadly it causes regression on some Samsung Exynos based boards:
> 
> 8<--- cut here ---
> Unable to handle kernel paging request at virtual address ffffff37
> pgd = (ptrval)
> [ffffff37] *pgd=4ffff841, *pte=00000000, *ppte=00000000
> Internal error: Oops: 27 [#1] PREEMPT SMP ARM
> Modules linked in:
> usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.10.0-rc1-00007-ge8f7703f8fe5 
> #1908
> Hardware name: Samsung Exynos (Flattened Device Tree)
> PC is at dev_pm_opp_put_regulators+0x8/0xf0
> LR is at dt_cpufreq_probe+0x19c/0x3fc

Does this fix it for you ?

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 66b3db5efb53..5aa3d4e3140d 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -228,7 +228,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
                        if (ret != -EPROBE_DEFER)
                                dev_err(cpu_dev, "failed to set regulators: %d\n",
                                        ret);
-                       goto out;
+                       goto free_cpumask;
                }
        }
 
@@ -293,6 +293,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
                dev_pm_opp_of_cpumask_remove_table(priv->cpus);
        if (priv->opp_table)
                dev_pm_opp_put_regulators(priv->opp_table);
+free_cpumask:
        free_cpumask_var(priv->cpus);
        return ret;
 }


-- 
viresh

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table
  2020-11-10  6:00     ` Viresh Kumar
@ 2020-11-10  6:57       ` Marek Szyprowski
  2020-11-10  6:59         ` Viresh Kumar
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Szyprowski @ 2020-11-10  6:57 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, linux-pm, Vincent Guittot, Stephen Boyd,
	Nishanth Menon, digetx, Stephan Gerhold, linux-kernel,
	Bartlomiej Zolnierkiewicz

Hi Viresh,

On 10.11.2020 07:00, Viresh Kumar wrote:
> On 09-11-20, 13:42, Marek Szyprowski wrote:
>> This patch landed in linux next-20201109 as commit e8f7703f8fe5
>> ("cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP
>> table"). Sadly it causes regression on some Samsung Exynos based boards:
>>
>> 8<--- cut here ---
>> Unable to handle kernel paging request at virtual address ffffff37
>> pgd = (ptrval)
>> [ffffff37] *pgd=4ffff841, *pte=00000000, *ppte=00000000
>> Internal error: Oops: 27 [#1] PREEMPT SMP ARM
>> Modules linked in:
>> usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
>> CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.10.0-rc1-00007-ge8f7703f8fe5
>> #1908
>> Hardware name: Samsung Exynos (Flattened Device Tree)
>> PC is at dev_pm_opp_put_regulators+0x8/0xf0
>> LR is at dt_cpufreq_probe+0x19c/0x3fc
> Does this fix it for you ?

Yes, thanks!

Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>

Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>

> diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
> index 66b3db5efb53..5aa3d4e3140d 100644
> --- a/drivers/cpufreq/cpufreq-dt.c
> +++ b/drivers/cpufreq/cpufreq-dt.c
> @@ -228,7 +228,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
>                          if (ret != -EPROBE_DEFER)
>                                  dev_err(cpu_dev, "failed to set regulators: %d\n",
>                                          ret);
> -                       goto out;
> +                       goto free_cpumask;
>                  }
>          }
>   
> @@ -293,6 +293,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
>                  dev_pm_opp_of_cpumask_remove_table(priv->cpus);
>          if (priv->opp_table)
>                  dev_pm_opp_put_regulators(priv->opp_table);
> +free_cpumask:
>          free_cpumask_var(priv->cpus);
>          return ret;
>   }
>
>
Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table
  2020-11-10  6:57       ` Marek Szyprowski
@ 2020-11-10  6:59         ` Viresh Kumar
  0 siblings, 0 replies; 12+ messages in thread
From: Viresh Kumar @ 2020-11-10  6:59 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Rafael J. Wysocki, linux-pm, Vincent Guittot, Stephen Boyd,
	Nishanth Menon, digetx, Stephan Gerhold, linux-kernel,
	Bartlomiej Zolnierkiewicz

On 10-11-20, 07:57, Marek Szyprowski wrote:
> Hi Viresh,
> 
> On 10.11.2020 07:00, Viresh Kumar wrote:
> > On 09-11-20, 13:42, Marek Szyprowski wrote:
> >> This patch landed in linux next-20201109 as commit e8f7703f8fe5
> >> ("cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP
> >> table"). Sadly it causes regression on some Samsung Exynos based boards:
> >>
> >> 8<--- cut here ---
> >> Unable to handle kernel paging request at virtual address ffffff37
> >> pgd = (ptrval)
> >> [ffffff37] *pgd=4ffff841, *pte=00000000, *ppte=00000000
> >> Internal error: Oops: 27 [#1] PREEMPT SMP ARM
> >> Modules linked in:
> >> usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> >> CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.10.0-rc1-00007-ge8f7703f8fe5
> >> #1908
> >> Hardware name: Samsung Exynos (Flattened Device Tree)
> >> PC is at dev_pm_opp_put_regulators+0x8/0xf0
> >> LR is at dt_cpufreq_probe+0x19c/0x3fc
> > Does this fix it for you ?
> 
> Yes, thanks!
> 
> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>

Thanks. I have fixed the original patch itself and pushed for linux-next.

-- 
viresh

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-11-10  6:59 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-06  6:24 [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table Viresh Kumar
2020-11-06  6:24 ` [PATCH 2/2] opp: Don't create an OPP table from dev_pm_opp_get_opp_table() Viresh Kumar
2020-11-06 10:25   ` Ulf Hansson
2020-11-06 13:18   ` Dmitry Osipenko
2020-11-09  4:34     ` Viresh Kumar
2020-11-09  4:41       ` Dmitry Osipenko
2020-11-09  4:57         ` Viresh Kumar
2020-11-09  5:29           ` Dmitry Osipenko
     [not found] ` <CGME20201109124218eucas1p1b8948a9bf2cf107b17b500b1603905e8@eucas1p1.samsung.com>
2020-11-09 12:42   ` [PATCH 1/2] cpufreq: dt: Don't (ab)use dev_pm_opp_get_opp_table() to create OPP table Marek Szyprowski
2020-11-10  6:00     ` Viresh Kumar
2020-11-10  6:57       ` Marek Szyprowski
2020-11-10  6:59         ` Viresh Kumar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).