Skip to contentSkip to conversation

FAILED: patch "[PATCH] PM / OPP: Update voltage in case freq == old_freq" failed to apply to 4.9-stable tree

PATCH [email protected] 1 participant 1 message Jul 1, 2018

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

Quoted 1 line

From c5c2a97b3ac7d1ec19e7cff9e38caca6afefc3de Mon Sep 17 00:00:00 2001

From: Waldemar Rymarkiewicz <[email protected]>
Date: Thu, 14 Jun 2018 15:56:08 +0200
Subject: [PATCH] PM / OPP: Update voltage in case freq == old_freq

This commit fixes a rare but possible case when the clk rate is updated without update of the regulator voltage.

At boot up, CPUfreq checks if the system is running at the right freq. This is a sanity check in case a bootloader set clk rate that is outside of freq table present with cpufreq core. In such cases system can be unstable so better to change it to a freq that is preset in freq-table.

The CPUfreq takes next freq that is >= policy->cur and this is our target_freq that needs to be set now.

dev_pm_opp_set_rate(dev, target_freq) checks the target_freq and the old_freq (a current rate). If these are equal it returns early. If not, it searches for OPP (old_opp) that fits best to old_freq (not listed in the table) and updates old_freq (!).

Here, we can end up with old_freq = old_opp.rate = target_freq, which is not handled in _generic_set_opp_regulator(). It's supposed to update voltage only when freq > old_freq || freq > old_freq.

if (freq > old_freq) {
		ret = _set_opp_voltage(dev, reg, new_supply);
[...]
if (freq < old_freq) {
		ret = _set_opp_voltage(dev, reg, new_supply);
		if (ret)

It results in, no voltage update while clk rate is updated.

Example:

freq-table = {
	1000MHz   1.15V
	 666MHZ   1.10V
	 333MHz   1.05V
}
boot-up-freq        = 800MHz   # not listed in freq-table
freq = target_freq  = 1GHz
old_freq            = 800Mhz

old_opp = _find_freq_ceil(opp_table, &old_freq); #(old_freq is modified!)
old_freq = 1GHz

Fixes 6a0712f6f199 ("PM / OPP: Add dev_pm_opp_set_rate()")
Cc 4.6+ <[email protected]> # v4.6+
drivers/opp/core.c +1 -1
index ab2f3fead6b1..31ff03dbeb83 100644
@@ -598,7 +598,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table,
 	}
 
 	/* Scaling up? Scale voltage before frequency */
-	if (freq > old_freq) {
+	if (freq >= old_freq) {
 		ret = _set_opp_voltage(dev, reg, new_supply);
 		if (ret)
 			goto restore_voltage;