Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1564676 > unrolled thread

[PATCH V2 00/12] PM / OPP: Use kref and move away from RCU locking

Started byViresh Kumar <viresh.kumar@linaro.org>
First post2017-01-23 05:50 +0100
Last post2017-01-31 09:50 +0100
Articles 6 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH V2 00/12] PM / OPP: Use kref and move away from RCU locking Viresh Kumar <viresh.kumar@linaro.org> - 2017-01-23 05:50 +0100
    [PATCH V2 10/12] PM / OPP: Simplify _opp_set_availability() Viresh Kumar <viresh.kumar@linaro.org> - 2017-01-23 05:50 +0100
    [PATCH V2 02/12] PM / OPP: Add 'struct kref' to OPP table Viresh Kumar <viresh.kumar@linaro.org> - 2017-01-23 05:50 +0100
    [PATCH V2 05/12] PM / OPP: Use dev_pm_opp_get_opp_table() instead of _add_opp_table() Viresh Kumar <viresh.kumar@linaro.org> - 2017-01-23 05:50 +0100
    RE: [PATCH V2 07/12] PM / OPP: Update OPP users to put reference MyungJoo Ham <myungjoo.ham@samsung.com> - 2017-01-31 08:20 +0100
      Re: [PATCH V2 07/12] PM / OPP: Update OPP users to put reference Viresh Kumar <viresh.kumar@linaro.org> - 2017-01-31 09:50 +0100

#1564676 — [PATCH V2 00/12] PM / OPP: Use kref and move away from RCU locking

FromViresh Kumar <viresh.kumar@linaro.org>
Date2017-01-23 05:50 +0100
Subject[PATCH V2 00/12] PM / OPP: Use kref and move away from RCU locking
Message-ID<t2EJQ-1Od-5@gated-at.bofh.it>
Hi Rafael,

This series is based over the other OPP series [1] which is ready to be
merged and is fully reviewed.

In this series, 11 out of 12 patches have Reviewed-by from Stephen. Only
the 7th patch hasn't got any of those.

@Stephen: Can you see if you can do a generic review of it as well?
Thanks for continuing to review this stuff.

The RCU locking isn't well suited for the OPP core. The RCU locking fits
better for reader heavy stuff, while the OPP core have at max one or two
readers only at a time.

Over that, it was getting very confusing the way RCU locking was used
within the OPP core. The individual OPPs are mostly well handled, i.e.
for an update a new structure was created and then that replaced the
older one. But the OPP tables were updated directly all the time from
various parts of the core. Though they were mostly used from within RCU
locked region, they didn't had much to do with RCU and were governed by
the mutex instead.

And that mixed with the 'opp_table_lock' has made the core even more
confusing.

Similar concerns were shared by Stephen Boyd earlier [2].

This patchset simplifies the locking in OPP core to great extent using
Kernel reference counting mechanism along with per OPP table mutex.
And finally it gets rid of RCU locking as well.

Each and every patch of this series is individually:
- build tested
- boot tested with cpufreq-dt.ko module. Insmod and rmmod to make sure
  the OPPs and the OPP tables are getting freed.

More testing is also done by various build and boot bots for last few
days. And they reported lots of issues (both build and boot time) that
helped making this series more robust:
- Kernel CI (Linaro)
- Fengguang Wu's bot (Intel)

V1->V2:
- Minor documentation fixes pointed out by Stephen
- dev_pm_opp_put() is called only if OPP is valid (in the 7th patch)

--
viresh

[1] https://marc.info/?l=linux-kernel&m=148334828916156&w=2
[2] https://marc.info/?l=linux-kernel&m=147742717527548&w=2

Viresh Kumar (12):
  PM / OPP: Add per OPP table mutex
  PM / OPP: Add 'struct kref' to OPP table
  PM / OPP: Return opp_table from dev_pm_opp_set_*() routines
  PM / OPP: Take reference of the OPP table while adding/removing OPPs
  PM / OPP: Use dev_pm_opp_get_opp_table() instead of _add_opp_table()
  PM / OPP: Add 'struct kref' to struct dev_pm_opp
  PM / OPP: Update OPP users to put reference
  PM / OPP: Take kref from _find_opp_table()
  PM / OPP: Move away from RCU locking
  PM / OPP: Simplify _opp_set_availability()
  PM / OPP: Simplify dev_pm_opp_get_max_volt_latency()
  PM / OPP: Update Documentation to remove RCU specific bits

 Documentation/power/opp.txt          |  52 +-
 arch/arm/mach-omap2/pm.c             |   5 +-
 drivers/base/power/opp/core.c        | 888 +++++++++++------------------------
 drivers/base/power/opp/cpu.c         |  66 +--
 drivers/base/power/opp/of.c          |  94 +---
 drivers/base/power/opp/opp.h         |  31 +-
 drivers/clk/tegra/clk-dfll.c         |  17 +-
 drivers/cpufreq/exynos5440-cpufreq.c |   5 +-
 drivers/cpufreq/imx6q-cpufreq.c      |  10 +-
 drivers/cpufreq/mt8173-cpufreq.c     |   8 +-
 drivers/cpufreq/omap-cpufreq.c       |   4 +-
 drivers/cpufreq/sti-cpufreq.c        |  13 +-
 drivers/devfreq/devfreq.c            |  14 +-
 drivers/devfreq/exynos-bus.c         |  14 +-
 drivers/devfreq/governor_passive.c   |   4 +-
 drivers/devfreq/rk3399_dmc.c         |  16 +-
 drivers/devfreq/tegra-devfreq.c      |   4 +-
 drivers/thermal/cpu_cooling.c        |  11 +-
 drivers/thermal/devfreq_cooling.c    |  15 +-
 include/linux/pm_opp.h               |  48 +-
 20 files changed, 433 insertions(+), 886 deletions(-)

-- 
2.7.1.410.g6faf27b

[toc] | [next] | [standalone]


#1564677 — [PATCH V2 10/12] PM / OPP: Simplify _opp_set_availability()

FromViresh Kumar <viresh.kumar@linaro.org>
Date2017-01-23 05:50 +0100
Subject[PATCH V2 10/12] PM / OPP: Simplify _opp_set_availability()
Message-ID<t2EJR-1Od-31@gated-at.bofh.it>
In reply to#1564676
As we don't use RCU locking anymore, there is no need to replace an
earlier OPP node with a new one. Just update the existing one.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/base/power/opp/core.c | 27 +++++----------------------
 1 file changed, 5 insertions(+), 22 deletions(-)

diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index c40d9868bd97..f54ac2484723 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -1510,20 +1510,15 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
 				 bool availability_req)
 {
 	struct opp_table *opp_table;
-	struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+	struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV);
 	int r = 0;
 
-	/* keep the node allocated */
-	new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL);
-	if (!new_opp)
-		return -ENOMEM;
-
 	/* Find the opp_table */
 	opp_table = _find_opp_table(dev);
 	if (IS_ERR(opp_table)) {
 		r = PTR_ERR(opp_table);
 		dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
-		goto free_opp;
+		return r;
 	}
 
 	mutex_lock(&opp_table->lock);
@@ -1544,32 +1539,20 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
 	/* Is update really needed? */
 	if (opp->available == availability_req)
 		goto unlock;
-	/* copy the old data over */
-	*new_opp = *opp;
-
-	/* plug in new node */
-	new_opp->available = availability_req;
 
-	list_replace(&opp->node, &new_opp->node);
-	kfree(opp);
+	opp->available = availability_req;
 
 	/* Notify the change of the OPP availability */
 	if (availability_req)
 		blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ENABLE,
-					     new_opp);
+					     opp);
 	else
 		blocking_notifier_call_chain(&opp_table->head,
-					     OPP_EVENT_DISABLE, new_opp);
-
-	mutex_unlock(&opp_table->lock);
-	dev_pm_opp_put_opp_table(opp_table);
-	return 0;
+					     OPP_EVENT_DISABLE, opp);
 
 unlock:
 	mutex_unlock(&opp_table->lock);
 	dev_pm_opp_put_opp_table(opp_table);
-free_opp:
-	kfree(new_opp);
 	return r;
 }
 
-- 
2.7.1.410.g6faf27b

[toc] | [prev] | [next] | [standalone]


#1564678 — [PATCH V2 02/12] PM / OPP: Add 'struct kref' to OPP table

FromViresh Kumar <viresh.kumar@linaro.org>
Date2017-01-23 05:50 +0100
Subject[PATCH V2 02/12] PM / OPP: Add 'struct kref' to OPP table
Message-ID<t2EJR-1Od-29@gated-at.bofh.it>
In reply to#1564676
Add kref to struct opp_table for easier accounting of the OPP table.

Note that the new routine dev_pm_opp_get_opp_table() takes the reference
from under the opp_table_lock, which guarantees that the OPP table
doesn't get freed unless dev_pm_opp_put_opp_table() is called for the
OPP table.

Two separate release mechanisms are added: locked and unlocked. In
unlocked version the routines aren't required to take/drop
opp_table_lock as the callers have already done that. This is required
to avoid breaking git bisect, otherwise we may get lockdeps between
commits. Once all the users of OPP table are updated the unlocked
version shall be removed.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/base/power/opp/core.c | 51 +++++++++++++++++++++++++++++++++++++++++--
 drivers/base/power/opp/opp.h  |  3 +++
 include/linux/pm_opp.h        | 10 +++++++++
 3 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index dcebd5efb6a1..ccc0d8913fd0 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -855,6 +855,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev)
 	srcu_init_notifier_head(&opp_table->srcu_head);
 	INIT_LIST_HEAD(&opp_table->opp_list);
 	mutex_init(&opp_table->lock);
+	kref_init(&opp_table->kref);
 
 	/* Secure the device table modification */
 	list_add_rcu(&opp_table->node, &opp_tables);
@@ -894,8 +895,36 @@ static void _kfree_device_rcu(struct rcu_head *head)
 	kfree_rcu(opp_table, rcu_head);
 }
 
-static void _free_opp_table(struct opp_table *opp_table)
+void _get_opp_table_kref(struct opp_table *opp_table)
 {
+	kref_get(&opp_table->kref);
+}
+
+struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
+{
+	struct opp_table *opp_table;
+
+	/* Hold our table modification lock here */
+	mutex_lock(&opp_table_lock);
+
+	opp_table = _find_opp_table(dev);
+	if (!IS_ERR(opp_table)) {
+		_get_opp_table_kref(opp_table);
+		goto unlock;
+	}
+
+	opp_table = _allocate_opp_table(dev);
+
+unlock:
+	mutex_unlock(&opp_table_lock);
+
+	return opp_table;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table);
+
+static void _opp_table_kref_release_unlocked(struct kref *kref)
+{
+	struct opp_table *opp_table = container_of(kref, struct opp_table, kref);
 	struct opp_device *opp_dev;
 
 	/* Release clk */
@@ -916,6 +945,24 @@ static void _free_opp_table(struct opp_table *opp_table)
 		  _kfree_device_rcu);
 }
 
+static void dev_pm_opp_put_opp_table_unlocked(struct opp_table *opp_table)
+{
+	kref_put(&opp_table->kref, _opp_table_kref_release_unlocked);
+}
+
+static void _opp_table_kref_release(struct kref *kref)
+{
+	_opp_table_kref_release_unlocked(kref);
+	mutex_unlock(&opp_table_lock);
+}
+
+void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
+{
+	kref_put_mutex(&opp_table->kref, _opp_table_kref_release,
+		       &opp_table_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_opp_table);
+
 /**
  * _remove_opp_table() - Removes a OPP table
  * @opp_table: OPP table to be removed.
@@ -939,7 +986,7 @@ static void _remove_opp_table(struct opp_table *opp_table)
 	if (opp_table->set_opp)
 		return;
 
-	_free_opp_table(opp_table);
+	dev_pm_opp_put_opp_table_unlocked(opp_table);
 }
 
 void _opp_free(struct dev_pm_opp *opp)
diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h
index 105243b06373..aae4d8f480ef 100644
--- a/drivers/base/power/opp/opp.h
+++ b/drivers/base/power/opp/opp.h
@@ -131,6 +131,7 @@ enum opp_table_access {
  * @rcu_head:	RCU callback head used for deferred freeing
  * @dev_list:	list of devices that share these OPPs
  * @opp_list:	table of opps
+ * @kref:	for reference count of the table.
  * @lock:	mutex protecting the opp_list.
  * @np:		struct device_node pointer for opp's DT node.
  * @clock_latency_ns_max: Max clock latency in nanoseconds.
@@ -164,6 +165,7 @@ struct opp_table {
 	struct rcu_head rcu_head;
 	struct list_head dev_list;
 	struct list_head opp_list;
+	struct kref kref;
 	struct mutex lock;
 
 	struct device_node *np;
@@ -192,6 +194,7 @@ struct opp_table {
 };
 
 /* Routines internal to opp core */
+void _get_opp_table_kref(struct opp_table *opp_table);
 struct opp_table *_find_opp_table(struct device *dev);
 struct opp_table *_add_opp_table(struct device *dev);
 struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 66a02deeb03f..d867c6b25f9a 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -78,6 +78,9 @@ struct dev_pm_set_opp_data {
 
 #if defined(CONFIG_PM_OPP)
 
+struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
+void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
+
 unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
@@ -126,6 +129,13 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
 void dev_pm_opp_remove_table(struct device *dev);
 void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask);
 #else
+static inline struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
+static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {}
+
 static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
 {
 	return 0;
-- 
2.7.1.410.g6faf27b

[toc] | [prev] | [next] | [standalone]


#1564679 — [PATCH V2 05/12] PM / OPP: Use dev_pm_opp_get_opp_table() instead of _add_opp_table()

FromViresh Kumar <viresh.kumar@linaro.org>
Date2017-01-23 05:50 +0100
Subject[PATCH V2 05/12] PM / OPP: Use dev_pm_opp_get_opp_table() instead of _add_opp_table()
Message-ID<t2EJR-1Od-33@gated-at.bofh.it>
In reply to#1564676
Migrate all users of _add_opp_table() to use dev_pm_opp_get_opp_table()
to guarantee that the OPP table doesn't get freed while being used.

Also update _managed_opp() to get the reference to the OPP table.

Now that the OPP table wouldn't get freed while these routines are
executing after dev_pm_opp_get_opp_table() is called, there is no need
to take opp_table_lock. Drop them as well.

Now that _add_opp_table(), _remove_opp_table() and the unlocked release
routines aren't used anymore, remove them.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/base/power/opp/core.c | 63 ++++---------------------------------------
 drivers/base/power/opp/of.c   | 54 +++++++++++++++++--------------------
 drivers/base/power/opp/opp.h  |  1 -
 3 files changed, 29 insertions(+), 89 deletions(-)

diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index 1a38b5d8dc54..ab9499e3ba02 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -863,27 +863,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev)
 }
 
 /**
- * _add_opp_table() - Find OPP table or allocate a new one
- * @dev:	device for which we do this operation
- *
- * It tries to find an existing table first, if it couldn't find one, it
- * allocates a new OPP table and returns that.
- *
- * Return: valid opp_table pointer if success, else NULL.
- */
-struct opp_table *_add_opp_table(struct device *dev)
-{
-	struct opp_table *opp_table;
-
-	/* Check for existing table for 'dev' first */
-	opp_table = _find_opp_table(dev);
-	if (!IS_ERR(opp_table))
-		return opp_table;
-
-	return _allocate_opp_table(dev);
-}
-
-/**
  * _kfree_device_rcu() - Free opp_table RCU handler
  * @head:	RCU head
  */
@@ -922,7 +901,7 @@ struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table);
 
-static void _opp_table_kref_release_unlocked(struct kref *kref)
+static void _opp_table_kref_release(struct kref *kref)
 {
 	struct opp_table *opp_table = container_of(kref, struct opp_table, kref);
 	struct opp_device *opp_dev;
@@ -943,16 +922,7 @@ static void _opp_table_kref_release_unlocked(struct kref *kref)
 	list_del_rcu(&opp_table->node);
 	call_srcu(&opp_table->srcu_head.srcu, &opp_table->rcu_head,
 		  _kfree_device_rcu);
-}
 
-static void dev_pm_opp_put_opp_table_unlocked(struct opp_table *opp_table)
-{
-	kref_put(&opp_table->kref, _opp_table_kref_release_unlocked);
-}
-
-static void _opp_table_kref_release(struct kref *kref)
-{
-	_opp_table_kref_release_unlocked(kref);
 	mutex_unlock(&opp_table_lock);
 }
 
@@ -963,17 +933,6 @@ void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put_opp_table);
 
-/**
- * _remove_opp_table() - Removes a OPP table
- * @opp_table: OPP table to be removed.
- *
- * Removes/frees OPP table if it doesn't contain any OPPs.
- */
-static void _remove_opp_table(struct opp_table *opp_table)
-{
-	dev_pm_opp_put_opp_table_unlocked(opp_table);
-}
-
 void _opp_free(struct dev_pm_opp *opp)
 {
 	kfree(opp);
@@ -1218,8 +1177,6 @@ int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
 	unsigned long tol;
 	int ret;
 
-	opp_rcu_lockdep_assert();
-
 	new_opp = _opp_allocate(opp_table);
 	if (!new_opp)
 		return -ENOMEM;
@@ -1640,21 +1597,13 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 	struct opp_table *opp_table;
 	int ret;
 
-	/* Hold our table modification lock here */
-	mutex_lock(&opp_table_lock);
-
-	opp_table = _add_opp_table(dev);
-	if (!opp_table) {
-		ret = -ENOMEM;
-		goto unlock;
-	}
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	if (!opp_table)
+		return -ENOMEM;
 
 	ret = _opp_add_v1(opp_table, dev, freq, u_volt, true);
-	if (ret)
-		_remove_opp_table(opp_table);
 
-unlock:
-	mutex_unlock(&opp_table_lock);
+	dev_pm_opp_put_opp_table(opp_table);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_add);
@@ -1865,8 +1814,6 @@ void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev,
 {
 	struct dev_pm_opp *opp, *tmp;
 
-	opp_rcu_lockdep_assert();
-
 	/* Find if opp_table manages a single device */
 	if (list_is_singular(&opp_table->dev_list)) {
 		/* Free static OPPs */
diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c
index cdbf733ac9b1..6a6e6e7846b3 100644
--- a/drivers/base/power/opp/of.c
+++ b/drivers/base/power/opp/of.c
@@ -24,7 +24,9 @@
 
 static struct opp_table *_managed_opp(const struct device_node *np)
 {
-	struct opp_table *opp_table;
+	struct opp_table *opp_table, *managed_table = NULL;
+
+	mutex_lock(&opp_table_lock);
 
 	list_for_each_entry_rcu(opp_table, &opp_tables, node) {
 		if (opp_table->np == np) {
@@ -35,14 +37,18 @@ static struct opp_table *_managed_opp(const struct device_node *np)
 			 * But the OPPs will be considered as shared only if the
 			 * OPP table contains a "opp-shared" property.
 			 */
-			if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED)
-				return opp_table;
+			if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED) {
+				_get_opp_table_kref(opp_table);
+				managed_table = opp_table;
+			}
 
-			return NULL;
+			break;
 		}
 	}
 
-	return NULL;
+	mutex_unlock(&opp_table_lock);
+
+	return managed_table;
 }
 
 void _of_init_opp_table(struct opp_table *opp_table, struct device *dev)
@@ -368,21 +374,17 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
 	struct opp_table *opp_table;
 	int ret = 0, count = 0;
 
-	mutex_lock(&opp_table_lock);
-
 	opp_table = _managed_opp(opp_np);
 	if (opp_table) {
 		/* OPPs are already managed */
 		if (!_add_opp_dev(dev, opp_table))
 			ret = -ENOMEM;
-		goto unlock;
+		goto put_opp_table;
 	}
 
-	opp_table = _add_opp_table(dev);
-	if (!opp_table) {
-		ret = -ENOMEM;
-		goto unlock;
-	}
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	if (!opp_table)
+		return -ENOMEM;
 
 	/* We have opp-table node now, iterate over it and add OPPs */
 	for_each_available_child_of_node(opp_np, np) {
@@ -392,14 +394,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
 		if (ret) {
 			dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
 				ret);
-			goto free_table;
+			_dev_pm_opp_remove_table(opp_table, dev, false);
+			goto put_opp_table;
 		}
 	}
 
 	/* There should be one of more OPP defined */
 	if (WARN_ON(!count)) {
 		ret = -ENOENT;
-		goto free_table;
+		goto put_opp_table;
 	}
 
 	opp_table->np = opp_np;
@@ -408,12 +411,8 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
 	else
 		opp_table->shared_opp = OPP_TABLE_ACCESS_EXCLUSIVE;
 
-	goto unlock;
-
-free_table:
-	_dev_pm_opp_remove_table(opp_table, dev, false);
-unlock:
-	mutex_unlock(&opp_table_lock);
+put_opp_table:
+	dev_pm_opp_put_opp_table(opp_table);
 
 	return ret;
 }
@@ -442,13 +441,9 @@ static int _of_add_opp_table_v1(struct device *dev)
 		return -EINVAL;
 	}
 
-	mutex_lock(&opp_table_lock);
-
-	opp_table = _add_opp_table(dev);
-	if (!opp_table) {
-		ret = -ENOMEM;
-		goto unlock;
-	}
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	if (!opp_table)
+		return -ENOMEM;
 
 	val = prop->value;
 	while (nr) {
@@ -465,8 +460,7 @@ static int _of_add_opp_table_v1(struct device *dev)
 		nr -= 2;
 	}
 
-unlock:
-	mutex_unlock(&opp_table_lock);
+	dev_pm_opp_put_opp_table(opp_table);
 	return ret;
 }
 
diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h
index aae4d8f480ef..a01724363347 100644
--- a/drivers/base/power/opp/opp.h
+++ b/drivers/base/power/opp/opp.h
@@ -196,7 +196,6 @@ struct opp_table {
 /* Routines internal to opp core */
 void _get_opp_table_kref(struct opp_table *opp_table);
 struct opp_table *_find_opp_table(struct device *dev);
-struct opp_table *_add_opp_table(struct device *dev);
 struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
 void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev, bool remove_all);
 void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all);
-- 
2.7.1.410.g6faf27b

[toc] | [prev] | [next] | [standalone]


#1570449 — RE: [PATCH V2 07/12] PM / OPP: Update OPP users to put reference

FromMyungJoo Ham <myungjoo.ham@samsung.com>
Date2017-01-31 08:20 +0100
SubjectRE: [PATCH V2 07/12] PM / OPP: Update OPP users to put reference
Message-ID<t5ATo-6eU-5@gated-at.bofh.it>
In reply to#1564676

[Multipart message — attachments visible in raw view] — view raw

> This patch updates dev_pm_opp_find_freq_*() routines to get a reference
> to the OPPs returned by them.
> 
> Also updates the users of dev_pm_opp_find_freq_*() routines to call
> dev_pm_opp_put() after they are done using the OPPs.
> 
> As it is guaranteed the that OPPs wouldn't get freed while being used,
> the RCU read side locking present with the users isn't required anymore.
> Drop it as well.
> 
> This patch also updates all users of devfreq_recommended_opp() which was
> returning an OPP received from the OPP core.
> 
> Note that some of the OPP core routines have gained
> rcu_read_{lock|unlock}() calls, as those still use RCU specific APIs
> within them.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com> [Devfreq]

This patch gets a lot of fails during application.

For devfreq-side, I've got:
error: drivers/devfreq/devfreq.c: patch does not apply
error: patch failed: drivers/devfreq/exynos-bus.c:103
error: drivers/devfreq/exynos-bus.c: patch does not apply
error: patch failed: drivers/devfreq/governor_passive.c:59
error: drivers/devfreq/governor_passive.c: patch does not apply
error: patch failed: drivers/devfreq/rk3399_dmc.c:91
error: drivers/devfreq/rk3399_dmc.c: patch does not apply
error: patch failed: drivers/devfreq/tegra-devfreq.c:487
error: drivers/devfreq/tegra-devfreq.c: patch does not apply

With the condition that you are going to properly rebase the patch,
you may add "Reviewed-by" from me.
(the code itself looks fine.)

Cheers,
MyungJoo

> ---
>  arch/arm/mach-omap2/pm.c             |   5 +-
>  drivers/base/power/opp/core.c        | 114 +++++++++++++++++++----------------
>  drivers/base/power/opp/cpu.c         |  22 ++-----
>  drivers/clk/tegra/clk-dfll.c         |  17 ++----
>  drivers/cpufreq/exynos5440-cpufreq.c |   5 +-
>  drivers/cpufreq/imx6q-cpufreq.c      |  10 +--
>  drivers/cpufreq/mt8173-cpufreq.c     |   8 +--
>  drivers/cpufreq/omap-cpufreq.c       |   4 +-
>  drivers/devfreq/devfreq.c            |  14 ++---
>  drivers/devfreq/exynos-bus.c         |  14 ++---
>  drivers/devfreq/governor_passive.c   |   4 +-
>  drivers/devfreq/rk3399_dmc.c         |  16 ++---
>  drivers/devfreq/tegra-devfreq.c      |   4 +-
>  drivers/thermal/cpu_cooling.c        |  11 +---
>  drivers/thermal/devfreq_cooling.c    |  15 ++---
>  15 files changed, 110 insertions(+), 153 deletions(-)
> 

[toc] | [prev] | [next] | [standalone]


#1570484 — Re: [PATCH V2 07/12] PM / OPP: Update OPP users to put reference

FromViresh Kumar <viresh.kumar@linaro.org>
Date2017-01-31 09:50 +0100
SubjectRe: [PATCH V2 07/12] PM / OPP: Update OPP users to put reference
Message-ID<t5Ciu-6WK-7@gated-at.bofh.it>
In reply to#1570449
On 31-01-17, 07:17, MyungJoo Ham wrote:
> > This patch updates dev_pm_opp_find_freq_*() routines to get a reference
> > to the OPPs returned by them.
> > 
> > Also updates the users of dev_pm_opp_find_freq_*() routines to call
> > dev_pm_opp_put() after they are done using the OPPs.
> > 
> > As it is guaranteed the that OPPs wouldn't get freed while being used,
> > the RCU read side locking present with the users isn't required anymore.
> > Drop it as well.
> > 
> > This patch also updates all users of devfreq_recommended_opp() which was
> > returning an OPP received from the OPP core.
> > 
> > Note that some of the OPP core routines have gained
> > rcu_read_{lock|unlock}() calls, as those still use RCU specific APIs
> > within them.
> > 
> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> > Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com> [Devfreq]
> 
> This patch gets a lot of fails during application.
> 
> For devfreq-side, I've got:
> error: drivers/devfreq/devfreq.c: patch does not apply
> error: patch failed: drivers/devfreq/exynos-bus.c:103
> error: drivers/devfreq/exynos-bus.c: patch does not apply
> error: patch failed: drivers/devfreq/governor_passive.c:59
> error: drivers/devfreq/governor_passive.c: patch does not apply
> error: patch failed: drivers/devfreq/rk3399_dmc.c:91
> error: drivers/devfreq/rk3399_dmc.c: patch does not apply
> error: patch failed: drivers/devfreq/tegra-devfreq.c:487
> error: drivers/devfreq/tegra-devfreq.c: patch does not apply
> 
> With the condition that you are going to properly rebase the patch,
> you may add "Reviewed-by" from me.
> (the code itself looks fine.)

This is already applied by Rafael and was based over his tree only.

-- 
viresh

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web