Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81286aed authored by Taniya Das's avatar Taniya Das Committed by David Dai
Browse files

clk: Check for failure at clk_change_rate



The clk_set_rate() call can fail. Check for failure and
abort the clock rate change in case the clk_set_rate()
fails.

Change-Id: I3a3a03f8c0c261b1f89c33e1247e3dbf889a8d26
Signed-off-by: default avatarTaniya Das <tdas@codeaurora.org>
Signed-off-by: default avatarDeepak Katragadda <dkatraga@codeaurora.org>
Signed-off-by: default avatarDavid Dai <daidavid1@codeaurora.org>
parent c5866d83
Loading
Loading
Loading
Loading
+28 −10
Original line number Diff line number Diff line
@@ -1777,7 +1777,7 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
 * walk down a subtree and set the new rates notifying the rate
 * change on the way
 */
static void clk_change_rate(struct clk_core *core)
static int clk_change_rate(struct clk_core *core)
{
	struct clk_core *child;
	struct hlist_node *tmp;
@@ -1786,6 +1786,7 @@ static void clk_change_rate(struct clk_core *core)
	bool skip_set_rate = false;
	struct clk_core *old_parent;
	struct clk_core *parent = NULL;
	int rc = 0;

	old_rate = core->rate;

@@ -1797,8 +1798,9 @@ static void clk_change_rate(struct clk_core *core)
		best_parent_rate = core->parent->rate;
	}

	if (clk_pm_runtime_get(core))
		return;
	rc = clk_pm_runtime_get(core);
	if (rc)
		return rc;

	if (core->flags & CLK_SET_RATE_UNGATE) {
		unsigned long flags;
@@ -1831,8 +1833,14 @@ static void clk_change_rate(struct clk_core *core)

	trace_clk_set_rate(core, core->new_rate);

	if (!skip_set_rate && core->ops->set_rate)
		core->ops->set_rate(core->hw, core->new_rate, best_parent_rate);
	if (!skip_set_rate && core->ops->set_rate) {
		rc = core->ops->set_rate(core->hw, core->new_rate,
						best_parent_rate);
		if (rc) {
			trace_clk_set_rate_complete(core, core->new_rate);
			goto out;
		}
	}

	trace_clk_set_rate_complete(core, core->new_rate);

@@ -1864,14 +1872,18 @@ static void clk_change_rate(struct clk_core *core)
		/* Skip children who will be reparented to another clock */
		if (child->new_parent && child->new_parent != core)
			continue;
		clk_change_rate(child);
		rc = clk_change_rate(child);
		if (rc)
			goto out;
	}

	/* handle the new child who might not be in core->children yet */
	if (core->new_child)
		clk_change_rate(core->new_child);
		rc = clk_change_rate(core->new_child);

out:
	clk_pm_runtime_put(core);
	return rc;
}

static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
@@ -1933,15 +1945,21 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
	/* notify that we are about to change rates */
	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
	if (fail_clk) {
		pr_debug("%s: failed to set %s rate\n", __func__,
				fail_clk->name);
		pr_debug("%s: failed to set %s clock to run at %lu\n", __func__,
				fail_clk->name, req_rate);
		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
		ret = -EBUSY;
		goto err;
	}

	/* change the rates */
	clk_change_rate(top);
	ret = clk_change_rate(top);
	if (ret) {
		pr_err("%s: failed to set %s clock to run at %lu\n", __func__,
				top->name, req_rate);
		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
		return ret;
	}

	core->req_rate = req_rate;
err: