Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'opp/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm into pm-opp

Pull operating performance points (OPP) framework updates for v5.1
from Viresh Kumar:

"This pull request contains following changes:

- Introduced new OPP helper for power-estimation and used it in
several cpufreq drivers (Quentin Perret, Matthias Kaehlcke, Dietmar
Eggemann, and Yangtao Li).

- OPP Debugfs cleanup (Greg KH).

- OPP core cleanup (Viresh Kumar)."

* 'opp/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
cpufreq: OMAP: Register an Energy Model
cpufreq: imx6q: Register an Energy Model
opp: no need to check return value of debugfs_create functions
cpufreq: mediatek: Register an Energy Model
cpufreq: scmi: Register an Energy Model
cpufreq: arm_big_little: Register an Energy Model
cpufreq: scpi: Register an Energy Model
cpufreq: dt: Register an Energy Model
PM / OPP: Introduce a power estimation helper
PM / OPP: Remove unused parameter of _generic_set_opp_clk_only()

+197 -108
+2
drivers/cpufreq/arm_big_little.c
··· 487 487 policy->cpuinfo.transition_latency = 488 488 arm_bL_ops->get_transition_latency(cpu_dev); 489 489 490 + dev_pm_opp_of_register_em(policy->cpus); 491 + 490 492 if (is_bL_switching_enabled()) 491 493 per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu); 492 494
+2
drivers/cpufreq/cpufreq-dt.c
··· 280 280 policy->cpuinfo.transition_latency = transition_latency; 281 281 policy->dvfs_possible_from_any_cpu = true; 282 282 283 + dev_pm_opp_of_register_em(policy->cpus); 284 + 283 285 return 0; 284 286 285 287 out_free_cpufreq_table:
+1
drivers/cpufreq/imx6q-cpufreq.c
··· 210 210 policy->clk = clks[ARM].clk; 211 211 ret = cpufreq_generic_init(policy, freq_table, transition_latency); 212 212 policy->suspend_freq = max_freq; 213 + dev_pm_opp_of_register_em(policy->cpus); 213 214 214 215 return ret; 215 216 }
+2
drivers/cpufreq/mediatek-cpufreq.c
··· 465 465 policy->driver_data = info; 466 466 policy->clk = info->cpu_clk; 467 467 468 + dev_pm_opp_of_register_em(policy->cpus); 469 + 468 470 return 0; 469 471 } 470 472
+3 -1
drivers/cpufreq/omap-cpufreq.c
··· 133 133 134 134 /* FIXME: what's the actual transition time? */ 135 135 result = cpufreq_generic_init(policy, freq_table, 300 * 1000); 136 - if (!result) 136 + if (!result) { 137 + dev_pm_opp_of_register_em(policy->cpus); 137 138 return 0; 139 + } 138 140 139 141 freq_table_free(); 140 142 fail:
+36 -3
drivers/cpufreq/scmi-cpufreq.c
··· 12 12 #include <linux/cpufreq.h> 13 13 #include <linux/cpumask.h> 14 14 #include <linux/cpu_cooling.h> 15 + #include <linux/energy_model.h> 15 16 #include <linux/export.h> 16 17 #include <linux/module.h> 17 18 #include <linux/pm_opp.h> ··· 104 103 return 0; 105 104 } 106 105 106 + static int __maybe_unused 107 + scmi_get_cpu_power(unsigned long *power, unsigned long *KHz, int cpu) 108 + { 109 + struct device *cpu_dev = get_cpu_device(cpu); 110 + unsigned long Hz; 111 + int ret, domain; 112 + 113 + if (!cpu_dev) { 114 + pr_err("failed to get cpu%d device\n", cpu); 115 + return -ENODEV; 116 + } 117 + 118 + domain = handle->perf_ops->device_domain_id(cpu_dev); 119 + if (domain < 0) 120 + return domain; 121 + 122 + /* Get the power cost of the performance domain. */ 123 + Hz = *KHz * 1000; 124 + ret = handle->perf_ops->est_power_get(handle, domain, &Hz, power); 125 + if (ret) 126 + return ret; 127 + 128 + /* The EM framework specifies the frequency in KHz. */ 129 + *KHz = Hz / 1000; 130 + 131 + return 0; 132 + } 133 + 107 134 static int scmi_cpufreq_init(struct cpufreq_policy *policy) 108 135 { 109 - int ret; 136 + int ret, nr_opp; 110 137 unsigned int latency; 111 138 struct device *cpu_dev; 112 139 struct scmi_data *priv; 113 140 struct cpufreq_frequency_table *freq_table; 141 + struct em_data_callback em_cb = EM_DATA_CB(scmi_get_cpu_power); 114 142 115 143 cpu_dev = get_cpu_device(policy->cpu); 116 144 if (!cpu_dev) { ··· 166 136 return ret; 167 137 } 168 138 169 - ret = dev_pm_opp_get_opp_count(cpu_dev); 170 - if (ret <= 0) { 139 + nr_opp = dev_pm_opp_get_opp_count(cpu_dev); 140 + if (nr_opp <= 0) { 171 141 dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n"); 172 142 ret = -EPROBE_DEFER; 173 143 goto out_free_opp; ··· 201 171 policy->cpuinfo.transition_latency = latency; 202 172 203 173 policy->fast_switch_possible = true; 174 + 175 + em_register_perf_domain(policy->cpus, nr_opp, &em_cb); 176 + 204 177 return 0; 205 178 206 179 out_free_priv:
+3
drivers/cpufreq/scpi-cpufreq.c
··· 170 170 policy->cpuinfo.transition_latency = latency; 171 171 172 172 policy->fast_switch_possible = false; 173 + 174 + dev_pm_opp_of_register_em(policy->cpus); 175 + 173 176 return 0; 174 177 175 178 out_free_cpufreq_table:
+7 -15
drivers/opp/core.c
··· 533 533 return ret; 534 534 } 535 535 536 - static inline int 537 - _generic_set_opp_clk_only(struct device *dev, struct clk *clk, 538 - unsigned long old_freq, unsigned long freq) 536 + static inline int _generic_set_opp_clk_only(struct device *dev, struct clk *clk, 537 + unsigned long freq) 539 538 { 540 539 int ret; 541 540 ··· 571 572 } 572 573 573 574 /* Change frequency */ 574 - ret = _generic_set_opp_clk_only(dev, opp_table->clk, old_freq, freq); 575 + ret = _generic_set_opp_clk_only(dev, opp_table->clk, freq); 575 576 if (ret) 576 577 goto restore_voltage; 577 578 ··· 585 586 return 0; 586 587 587 588 restore_freq: 588 - if (_generic_set_opp_clk_only(dev, opp_table->clk, freq, old_freq)) 589 + if (_generic_set_opp_clk_only(dev, opp_table->clk, old_freq)) 589 590 dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n", 590 591 __func__, old_freq); 591 592 restore_voltage: ··· 758 759 opp->supplies); 759 760 } else { 760 761 /* Only frequency scaling */ 761 - ret = _generic_set_opp_clk_only(dev, clk, old_freq, freq); 762 + ret = _generic_set_opp_clk_only(dev, clk, freq); 762 763 } 763 764 764 765 /* Scaling down? Configure required OPPs after frequency */ ··· 792 793 struct opp_table *opp_table) 793 794 { 794 795 struct opp_device *opp_dev; 795 - int ret; 796 796 797 797 opp_dev = kzalloc(sizeof(*opp_dev), GFP_KERNEL); 798 798 if (!opp_dev) ··· 803 805 list_add(&opp_dev->node, &opp_table->dev_list); 804 806 805 807 /* Create debugfs entries for the opp_table */ 806 - ret = opp_debug_register(opp_dev, opp_table); 807 - if (ret) 808 - dev_err(dev, "%s: Failed to register opp debugfs (%d)\n", 809 - __func__, ret); 808 + opp_debug_register(opp_dev, opp_table); 810 809 811 810 return opp_dev; 812 811 } ··· 1224 1229 new_opp->opp_table = opp_table; 1225 1230 kref_init(&new_opp->kref); 1226 1231 1227 - ret = opp_debug_create_one(new_opp, opp_table); 1228 - if (ret) 1229 - dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n", 1230 - __func__, ret); 1232 + opp_debug_create_one(new_opp, opp_table); 1231 1233 1232 1234 if (!_opp_supported_by_regulators(new_opp, opp_table)) { 1233 1235 new_opp->available = false;
+29 -81
drivers/opp/debugfs.c
··· 35 35 debugfs_remove_recursive(opp->dentry); 36 36 } 37 37 38 - static bool opp_debug_create_supplies(struct dev_pm_opp *opp, 38 + static void opp_debug_create_supplies(struct dev_pm_opp *opp, 39 39 struct opp_table *opp_table, 40 40 struct dentry *pdentry) 41 41 { ··· 50 50 /* Create per-opp directory */ 51 51 d = debugfs_create_dir(name, pdentry); 52 52 53 - if (!d) 54 - return false; 53 + debugfs_create_ulong("u_volt_target", S_IRUGO, d, 54 + &opp->supplies[i].u_volt); 55 55 56 - if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, 57 - &opp->supplies[i].u_volt)) 58 - return false; 56 + debugfs_create_ulong("u_volt_min", S_IRUGO, d, 57 + &opp->supplies[i].u_volt_min); 59 58 60 - if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, 61 - &opp->supplies[i].u_volt_min)) 62 - return false; 59 + debugfs_create_ulong("u_volt_max", S_IRUGO, d, 60 + &opp->supplies[i].u_volt_max); 63 61 64 - if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, 65 - &opp->supplies[i].u_volt_max)) 66 - return false; 67 - 68 - if (!debugfs_create_ulong("u_amp", S_IRUGO, d, 69 - &opp->supplies[i].u_amp)) 70 - return false; 62 + debugfs_create_ulong("u_amp", S_IRUGO, d, 63 + &opp->supplies[i].u_amp); 71 64 } 72 - 73 - return true; 74 65 } 75 66 76 - int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) 67 + void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) 77 68 { 78 69 struct dentry *pdentry = opp_table->dentry; 79 70 struct dentry *d; ··· 86 95 87 96 /* Create per-opp directory */ 88 97 d = debugfs_create_dir(name, pdentry); 89 - if (!d) 90 - return -ENOMEM; 91 98 92 - if (!debugfs_create_bool("available", S_IRUGO, d, &opp->available)) 93 - return -ENOMEM; 99 + debugfs_create_bool("available", S_IRUGO, d, &opp->available); 100 + debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic); 101 + debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo); 102 + debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend); 103 + debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate); 104 + debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate); 105 + debugfs_create_ulong("clock_latency_ns", S_IRUGO, d, 106 + &opp->clock_latency_ns); 94 107 95 - if (!debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic)) 96 - return -ENOMEM; 97 - 98 - if (!debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo)) 99 - return -ENOMEM; 100 - 101 - if (!debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend)) 102 - return -ENOMEM; 103 - 104 - if (!debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate)) 105 - return -ENOMEM; 106 - 107 - if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate)) 108 - return -ENOMEM; 109 - 110 - if (!opp_debug_create_supplies(opp, opp_table, d)) 111 - return -ENOMEM; 112 - 113 - if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d, 114 - &opp->clock_latency_ns)) 115 - return -ENOMEM; 108 + opp_debug_create_supplies(opp, opp_table, d); 116 109 117 110 opp->dentry = d; 118 - return 0; 119 111 } 120 112 121 - static int opp_list_debug_create_dir(struct opp_device *opp_dev, 122 - struct opp_table *opp_table) 113 + static void opp_list_debug_create_dir(struct opp_device *opp_dev, 114 + struct opp_table *opp_table) 123 115 { 124 116 const struct device *dev = opp_dev->dev; 125 117 struct dentry *d; ··· 111 137 112 138 /* Create device specific directory */ 113 139 d = debugfs_create_dir(opp_table->dentry_name, rootdir); 114 - if (!d) { 115 - dev_err(dev, "%s: Failed to create debugfs dir\n", __func__); 116 - return -ENOMEM; 117 - } 118 140 119 141 opp_dev->dentry = d; 120 142 opp_table->dentry = d; 121 - 122 - return 0; 123 143 } 124 144 125 - static int opp_list_debug_create_link(struct opp_device *opp_dev, 126 - struct opp_table *opp_table) 145 + static void opp_list_debug_create_link(struct opp_device *opp_dev, 146 + struct opp_table *opp_table) 127 147 { 128 - const struct device *dev = opp_dev->dev; 129 148 char name[NAME_MAX]; 130 - struct dentry *d; 131 149 132 150 opp_set_dev_name(opp_dev->dev, name); 133 151 134 152 /* Create device specific directory link */ 135 - d = debugfs_create_symlink(name, rootdir, opp_table->dentry_name); 136 - if (!d) { 137 - dev_err(dev, "%s: Failed to create link\n", __func__); 138 - return -ENOMEM; 139 - } 140 - 141 - opp_dev->dentry = d; 142 - 143 - return 0; 153 + opp_dev->dentry = debugfs_create_symlink(name, rootdir, 154 + opp_table->dentry_name); 144 155 } 145 156 146 157 /** ··· 136 177 * Dynamically adds device specific directory in debugfs 'opp' directory. If the 137 178 * device-opp is shared with other devices, then links will be created for all 138 179 * devices except the first. 139 - * 140 - * Return: 0 on success, otherwise negative error. 141 180 */ 142 - int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table) 181 + void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table) 143 182 { 144 - if (!rootdir) { 145 - pr_debug("%s: Uninitialized rootdir\n", __func__); 146 - return -EINVAL; 147 - } 148 - 149 183 if (opp_table->dentry) 150 - return opp_list_debug_create_link(opp_dev, opp_table); 151 - 152 - return opp_list_debug_create_dir(opp_dev, opp_table); 184 + opp_list_debug_create_link(opp_dev, opp_table); 185 + else 186 + opp_list_debug_create_dir(opp_dev, opp_table); 153 187 } 154 188 155 189 static void opp_migrate_dentry(struct opp_device *opp_dev, ··· 204 252 { 205 253 /* Create /sys/kernel/debug/opp directory */ 206 254 rootdir = debugfs_create_dir("opp", NULL); 207 - if (!rootdir) { 208 - pr_err("%s: Failed to create root directory\n", __func__); 209 - return -ENOMEM; 210 - } 211 255 212 256 return 0; 213 257 }
+99
drivers/opp/of.c
··· 20 20 #include <linux/pm_domain.h> 21 21 #include <linux/slab.h> 22 22 #include <linux/export.h> 23 + #include <linux/energy_model.h> 23 24 24 25 #include "opp.h" 25 26 ··· 1048 1047 return of_node_get(opp->np); 1049 1048 } 1050 1049 EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node); 1050 + 1051 + /* 1052 + * Callback function provided to the Energy Model framework upon registration. 1053 + * This computes the power estimated by @CPU at @kHz if it is the frequency 1054 + * of an existing OPP, or at the frequency of the first OPP above @kHz otherwise 1055 + * (see dev_pm_opp_find_freq_ceil()). This function updates @kHz to the ceiled 1056 + * frequency and @mW to the associated power. The power is estimated as 1057 + * P = C * V^2 * f with C being the CPU's capacitance and V and f respectively 1058 + * the voltage and frequency of the OPP. 1059 + * 1060 + * Returns -ENODEV if the CPU device cannot be found, -EINVAL if the power 1061 + * calculation failed because of missing parameters, 0 otherwise. 1062 + */ 1063 + static int __maybe_unused _get_cpu_power(unsigned long *mW, unsigned long *kHz, 1064 + int cpu) 1065 + { 1066 + struct device *cpu_dev; 1067 + struct dev_pm_opp *opp; 1068 + struct device_node *np; 1069 + unsigned long mV, Hz; 1070 + u32 cap; 1071 + u64 tmp; 1072 + int ret; 1073 + 1074 + cpu_dev = get_cpu_device(cpu); 1075 + if (!cpu_dev) 1076 + return -ENODEV; 1077 + 1078 + np = of_node_get(cpu_dev->of_node); 1079 + if (!np) 1080 + return -EINVAL; 1081 + 1082 + ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap); 1083 + of_node_put(np); 1084 + if (ret) 1085 + return -EINVAL; 1086 + 1087 + Hz = *kHz * 1000; 1088 + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &Hz); 1089 + if (IS_ERR(opp)) 1090 + return -EINVAL; 1091 + 1092 + mV = dev_pm_opp_get_voltage(opp) / 1000; 1093 + dev_pm_opp_put(opp); 1094 + if (!mV) 1095 + return -EINVAL; 1096 + 1097 + tmp = (u64)cap * mV * mV * (Hz / 1000000); 1098 + do_div(tmp, 1000000000); 1099 + 1100 + *mW = (unsigned long)tmp; 1101 + *kHz = Hz / 1000; 1102 + 1103 + return 0; 1104 + } 1105 + 1106 + /** 1107 + * dev_pm_opp_of_register_em() - Attempt to register an Energy Model 1108 + * @cpus : CPUs for which an Energy Model has to be registered 1109 + * 1110 + * This checks whether the "dynamic-power-coefficient" devicetree property has 1111 + * been specified, and tries to register an Energy Model with it if it has. 1112 + */ 1113 + void dev_pm_opp_of_register_em(struct cpumask *cpus) 1114 + { 1115 + struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power); 1116 + int ret, nr_opp, cpu = cpumask_first(cpus); 1117 + struct device *cpu_dev; 1118 + struct device_node *np; 1119 + u32 cap; 1120 + 1121 + cpu_dev = get_cpu_device(cpu); 1122 + if (!cpu_dev) 1123 + return; 1124 + 1125 + nr_opp = dev_pm_opp_get_opp_count(cpu_dev); 1126 + if (nr_opp <= 0) 1127 + return; 1128 + 1129 + np = of_node_get(cpu_dev->of_node); 1130 + if (!np) 1131 + return; 1132 + 1133 + /* 1134 + * Register an EM only if the 'dynamic-power-coefficient' property is 1135 + * set in devicetree. It is assumed the voltage values are known if that 1136 + * property is set since it is useless otherwise. If voltages are not 1137 + * known, just let the EM registration fail with an error to alert the 1138 + * user about the inconsistent configuration. 1139 + */ 1140 + ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap); 1141 + of_node_put(np); 1142 + if (ret || !cap) 1143 + return; 1144 + 1145 + em_register_perf_domain(cpus, nr_opp, &em_cb); 1146 + } 1147 + EXPORT_SYMBOL_GPL(dev_pm_opp_of_register_em);
+7 -8
drivers/opp/opp.h
··· 236 236 237 237 #ifdef CONFIG_DEBUG_FS 238 238 void opp_debug_remove_one(struct dev_pm_opp *opp); 239 - int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table); 240 - int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table); 239 + void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table); 240 + void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table); 241 241 void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table); 242 242 #else 243 243 static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {} 244 244 245 - static inline int opp_debug_create_one(struct dev_pm_opp *opp, 246 - struct opp_table *opp_table) 247 - { return 0; } 248 - static inline int opp_debug_register(struct opp_device *opp_dev, 249 - struct opp_table *opp_table) 250 - { return 0; } 245 + static inline void opp_debug_create_one(struct dev_pm_opp *opp, 246 + struct opp_table *opp_table) { } 247 + 248 + static inline void opp_debug_register(struct opp_device *opp_dev, 249 + struct opp_table *opp_table) { } 251 250 252 251 static inline void opp_debug_unregister(struct opp_device *opp_dev, 253 252 struct opp_table *opp_table)
+6
include/linux/pm_opp.h
··· 327 327 struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev); 328 328 struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp); 329 329 int of_get_required_opp_performance_state(struct device_node *np, int index); 330 + void dev_pm_opp_of_register_em(struct cpumask *cpus); 330 331 #else 331 332 static inline int dev_pm_opp_of_add_table(struct device *dev) 332 333 { ··· 366 365 { 367 366 return NULL; 368 367 } 368 + 369 + static inline void dev_pm_opp_of_register_em(struct cpumask *cpus) 370 + { 371 + } 372 + 369 373 static inline int of_get_required_opp_performance_state(struct device_node *np, int index) 370 374 { 371 375 return -ENOTSUPP;