summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeepak Katragadda <dkatraga@codeaurora.org>2016-02-03 14:36:42 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:19:48 -0700
commitff072849f7ca602ac6afda540db3b9cf3e9b2a35 (patch)
tree5251aa95254fbe7ffb098a7aadc27333d70db716
parent1c3a19b61d41585564161494c6466f7f4932f726 (diff)
clk: msm: clock: Refactor the aggr_sibling_rates logic
Return early if the branch clock does not need the rate aggregation support. Only take the common branch_clk_lock when needed; doing so unnecessarily will lead to lock contention in some cases. CRs-Fixed: 972426 Change-Id: I00476d1c193df025a1da19aa0d0ddf0f0462b4d0 Signed-off-by: Deepak Katragadda <dkatraga@codeaurora.org>
-rw-r--r--drivers/clk/msm/clock-local2.c71
1 files changed, 36 insertions, 35 deletions
diff --git a/drivers/clk/msm/clock-local2.c b/drivers/clk/msm/clock-local2.c
index 5e60f0ff06e2..934219df53ef 100644
--- a/drivers/clk/msm/clock-local2.c
+++ b/drivers/clk/msm/clock-local2.c
@@ -647,15 +647,16 @@ static int branch_clk_prepare(struct clk *c)
unsigned long curr_rate;
int ret = 0;
+ if (!branch->aggr_sibling_rates)
+ return ret;
+
mutex_lock(&branch_clk_lock);
branch->is_prepared = false;
- if (branch->aggr_sibling_rates) {
- curr_rate = branch_clk_aggregate_rate(c->parent);
- if (c->rate > curr_rate) {
- ret = clk_set_rate(c->parent, c->rate);
- if (ret)
- goto exit;
- }
+ curr_rate = branch_clk_aggregate_rate(c->parent);
+ if (c->rate > curr_rate) {
+ ret = clk_set_rate(c->parent, c->rate);
+ if (ret)
+ goto exit;
}
branch->is_prepared = true;
exit:
@@ -699,14 +700,15 @@ static void branch_clk_unprepare(struct clk *c)
struct branch_clk *branch = to_branch_clk(c);
unsigned long curr_rate, new_rate;
+ if (!branch->aggr_sibling_rates)
+ return;
+
mutex_lock(&branch_clk_lock);
branch->is_prepared = false;
- if (branch->aggr_sibling_rates) {
- new_rate = branch_clk_aggregate_rate(c->parent);
- curr_rate = max(new_rate, c->rate);
- if (new_rate < curr_rate)
- clk_set_rate(c->parent, new_rate);
- }
+ new_rate = branch_clk_aggregate_rate(c->parent);
+ curr_rate = max(new_rate, c->rate);
+ if (new_rate < curr_rate)
+ clk_set_rate(c->parent, new_rate);
mutex_unlock(&branch_clk_lock);
}
@@ -764,31 +766,30 @@ static int branch_clk_set_rate(struct clk *c, unsigned long rate)
if (branch->has_sibling)
return -EPERM;
+ if (!branch->aggr_sibling_rates)
+ return clk_set_rate(c->parent, rate);
+
mutex_lock(&branch_clk_lock);
- if (branch->aggr_sibling_rates) {
- if (!branch->is_prepared) {
- c->rate = rate;
- goto exit;
- }
- /*
- * Get the aggregate rate without this clock's vote and update
- * if the new rate is different than the current rate.
- */
- list_for_each_entry(clkp, &parent->children, siblings) {
- clkh = to_branch_clk(clkp);
- if (clkh->is_prepared && clkh != branch)
- other_rate = max(clkp->rate, other_rate);
- }
- curr_rate = max(other_rate, c->rate);
- new_rate = max(other_rate, rate);
- if (new_rate != curr_rate) {
- ret = clk_set_rate(parent, new_rate);
- if (!ret)
- c->rate = rate;
- }
+ if (!branch->is_prepared) {
+ c->rate = rate;
goto exit;
}
- ret = clk_set_rate(c->parent, rate);
+ /*
+ * Get the aggregate rate without this clock's vote and update
+ * if the new rate is different than the current rate.
+ */
+ list_for_each_entry(clkp, &parent->children, siblings) {
+ clkh = to_branch_clk(clkp);
+ if (clkh->is_prepared && clkh != branch)
+ other_rate = max(clkp->rate, other_rate);
+ }
+ curr_rate = max(other_rate, c->rate);
+ new_rate = max(other_rate, rate);
+ if (new_rate != curr_rate) {
+ ret = clk_set_rate(parent, new_rate);
+ if (!ret)
+ c->rate = rate;
+ }
exit:
mutex_unlock(&branch_clk_lock);
return ret;