aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power
diff options
context:
space:
mode:
authorBen Dooks <ben.dooks@codethink.co.uk>2014-01-14 07:23:40 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-14 19:50:50 -0500
commit8a6720ec2020f01756154d9c272f88a6af76fb81 (patch)
tree45064596fd904fe22ce57946c3cb2a15a75fd54a /drivers/base/power
parent7e22e91102c6b9df7c4ae2168910e19d2bb14cd6 (diff)
PM / clock_ops: fix up clk prepare/unprepare count
The drivers/base/power/clock_ops.c file is causing warnings from the clock driver (as shown below) due to failing to do a clk_prepare() call before enabling a clock. It also fails to check the balance of prepare/unprepare as __pm_clk_remove() do clk_disable_unprepare() call. This bug has probably been in since commit b2476490e ("clk: introduce the common clock framework") as the warning was part of the original commit. It is strange that it has not been noticed (although this has also been coupled with a failure for certain SH builds to not build the necessary glue to use this method of controlling the clocks). In summary, this is probably needed in several stable branches but need advice on which ones. On the Renesas Lager board, this causes numerous warnings of the following and even worse the clock system will not enable clocks, causing drivers that are in development to fail to work: WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:883 __clk_enable+0x2c/0xa0() Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> Reviewed-by: Ian Molton <ian.molton@codethink.co.uk> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/base/power')
-rw-r--r--drivers/base/power/clock_ops.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 9d8fde709390..b9dd8fac87d7 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -43,6 +43,7 @@ static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
43 if (IS_ERR(ce->clk)) { 43 if (IS_ERR(ce->clk)) {
44 ce->status = PCE_STATUS_ERROR; 44 ce->status = PCE_STATUS_ERROR;
45 } else { 45 } else {
46 clk_prepare(ce->clk);
46 ce->status = PCE_STATUS_ACQUIRED; 47 ce->status = PCE_STATUS_ACQUIRED;
47 dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id); 48 dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id);
48 } 49 }
@@ -99,10 +100,12 @@ static void __pm_clk_remove(struct pm_clock_entry *ce)
99 100
100 if (ce->status < PCE_STATUS_ERROR) { 101 if (ce->status < PCE_STATUS_ERROR) {
101 if (ce->status == PCE_STATUS_ENABLED) 102 if (ce->status == PCE_STATUS_ENABLED)
102 clk_disable_unprepare(ce->clk); 103 clk_disable(ce->clk);
103 104
104 if (ce->status >= PCE_STATUS_ACQUIRED) 105 if (ce->status >= PCE_STATUS_ACQUIRED) {
106 clk_unprepare(ce->clk);
105 clk_put(ce->clk); 107 clk_put(ce->clk);
108 }
106 } 109 }
107 110
108 kfree(ce->con_id); 111 kfree(ce->con_id);