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

Commit 03bc10ab authored by Boris Brezillon's avatar Boris Brezillon Committed by Michael Turquette
Browse files

clk: check ->determine/round_rate() return value in clk_calc_new_rates



->determine_rate() and ->round_rate() can return the closest rate to the
requested one or an error code.
clk_calc_new_rates is assuming these functions can't return a negative
value, which leads to a undefined behavior when the clk implementation
returns such an error code.
Fix this by returning NULL in case ->determine_rate() or ->round_rate()
returned an error code.

Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: default avatarMichael Turquette <mturquette@linaro.org>
parent 45912431
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -1618,6 +1618,7 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
	unsigned long min_rate;
	unsigned long max_rate;
	int p_index = 0;
	long ret;

	/* sanity */
	if (IS_ERR_OR_NULL(clk))
@@ -1633,15 +1634,23 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
	/* find the closest rate and parent clk/rate */
	if (clk->ops->determine_rate) {
		parent_hw = parent ? parent->hw : NULL;
		new_rate = clk->ops->determine_rate(clk->hw, rate,
		ret = clk->ops->determine_rate(clk->hw, rate,
					       min_rate,
					       max_rate,
					       &best_parent_rate,
					       &parent_hw);
		if (ret < 0)
			return NULL;

		new_rate = ret;
		parent = parent_hw ? parent_hw->core : NULL;
	} else if (clk->ops->round_rate) {
		new_rate = clk->ops->round_rate(clk->hw, rate,
		ret = clk->ops->round_rate(clk->hw, rate,
					   &best_parent_rate);
		if (ret < 0)
			return NULL;

		new_rate = ret;
		if (new_rate < min_rate || new_rate > max_rate)
			return NULL;
	} else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {