diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-01-17 20:52:42 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-01-17 20:52:42 -0500 |
commit | f06970f4b03dffeb9831a8ad605db3c85a55aca1 (patch) | |
tree | a4477a4878350d63e3399e7f0d57d64e26065f09 | |
parent | 343a8d17fa8d6dd97f408e8fedbcef12073f3774 (diff) | |
parent | ac89c400ebb146604e718b3fa168c15592e73a8c (diff) |
Merge branch 'pm-cpufreq-thermal' into pm-cpufreq
* pm-cpufreq-thermal:
cpu_cooling: Remove static-power related documentation
cpu_cooling: Drop static-power related stuff
cpu_cooling: Keep only one of_cpufreq*cooling_register() helper
cpu_cooling: Remove unused cpufreq_power_cooling_register()
cpu_cooling: Make of_cpufreq_power_cooling_register() parse DT
-rw-r--r-- | Documentation/thermal/cpu-cooling-api.txt | 115 | ||||
-rw-r--r-- | drivers/cpufreq/arm_big_little.c | 23 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq-dt.c | 27 | ||||
-rw-r--r-- | drivers/cpufreq/mediatek-cpufreq.c | 22 | ||||
-rw-r--r-- | drivers/cpufreq/qoriq-cpufreq.c | 14 | ||||
-rw-r--r-- | drivers/thermal/cpu_cooling.c | 201 | ||||
-rw-r--r-- | include/linux/cpu_cooling.h | 75 | ||||
-rw-r--r-- | include/trace/events/thermal.h | 10 |
8 files changed, 66 insertions, 421 deletions
diff --git a/Documentation/thermal/cpu-cooling-api.txt b/Documentation/thermal/cpu-cooling-api.txt index 71653584cd03..7df567eaea1a 100644 --- a/Documentation/thermal/cpu-cooling-api.txt +++ b/Documentation/thermal/cpu-cooling-api.txt | |||
@@ -26,39 +26,16 @@ the user. The registration APIs returns the cooling device pointer. | |||
26 | clip_cpus: cpumask of cpus where the frequency constraints will happen. | 26 | clip_cpus: cpumask of cpus where the frequency constraints will happen. |
27 | 27 | ||
28 | 1.1.2 struct thermal_cooling_device *of_cpufreq_cooling_register( | 28 | 1.1.2 struct thermal_cooling_device *of_cpufreq_cooling_register( |
29 | struct device_node *np, const struct cpumask *clip_cpus) | 29 | struct cpufreq_policy *policy) |
30 | 30 | ||
31 | This interface function registers the cpufreq cooling device with | 31 | This interface function registers the cpufreq cooling device with |
32 | the name "thermal-cpufreq-%x" linking it with a device tree node, in | 32 | the name "thermal-cpufreq-%x" linking it with a device tree node, in |
33 | order to bind it via the thermal DT code. This api can support multiple | 33 | order to bind it via the thermal DT code. This api can support multiple |
34 | instances of cpufreq cooling devices. | 34 | instances of cpufreq cooling devices. |
35 | 35 | ||
36 | np: pointer to the cooling device device tree node | 36 | policy: CPUFreq policy. |
37 | clip_cpus: cpumask of cpus where the frequency constraints will happen. | ||
38 | 37 | ||
39 | 1.1.3 struct thermal_cooling_device *cpufreq_power_cooling_register( | 38 | 1.1.3 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) |
40 | const struct cpumask *clip_cpus, u32 capacitance, | ||
41 | get_static_t plat_static_func) | ||
42 | |||
43 | Similar to cpufreq_cooling_register, this function registers a cpufreq | ||
44 | cooling device. Using this function, the cooling device will | ||
45 | implement the power extensions by using a simple cpu power model. The | ||
46 | cpus must have registered their OPPs using the OPP library. | ||
47 | |||
48 | The additional parameters are needed for the power model (See 2. Power | ||
49 | models). "capacitance" is the dynamic power coefficient (See 2.1 | ||
50 | Dynamic power). "plat_static_func" is a function to calculate the | ||
51 | static power consumed by these cpus (See 2.2 Static power). | ||
52 | |||
53 | 1.1.4 struct thermal_cooling_device *of_cpufreq_power_cooling_register( | ||
54 | struct device_node *np, const struct cpumask *clip_cpus, u32 capacitance, | ||
55 | get_static_t plat_static_func) | ||
56 | |||
57 | Similar to cpufreq_power_cooling_register, this function register a | ||
58 | cpufreq cooling device with power extensions using the device tree | ||
59 | information supplied by the np parameter. | ||
60 | |||
61 | 1.1.5 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) | ||
62 | 39 | ||
63 | This interface function unregisters the "thermal-cpufreq-%x" cooling device. | 40 | This interface function unregisters the "thermal-cpufreq-%x" cooling device. |
64 | 41 | ||
@@ -67,20 +44,14 @@ information supplied by the np parameter. | |||
67 | 2. Power models | 44 | 2. Power models |
68 | 45 | ||
69 | The power API registration functions provide a simple power model for | 46 | The power API registration functions provide a simple power model for |
70 | CPUs. The current power is calculated as dynamic + (optionally) | 47 | CPUs. The current power is calculated as dynamic power (static power isn't |
71 | static power. This power model requires that the operating-points of | 48 | supported currently). This power model requires that the operating-points of |
72 | the CPUs are registered using the kernel's opp library and the | 49 | the CPUs are registered using the kernel's opp library and the |
73 | `cpufreq_frequency_table` is assigned to the `struct device` of the | 50 | `cpufreq_frequency_table` is assigned to the `struct device` of the |
74 | cpu. If you are using CONFIG_CPUFREQ_DT then the | 51 | cpu. If you are using CONFIG_CPUFREQ_DT then the |
75 | `cpufreq_frequency_table` should already be assigned to the cpu | 52 | `cpufreq_frequency_table` should already be assigned to the cpu |
76 | device. | 53 | device. |
77 | 54 | ||
78 | The `plat_static_func` parameter of `cpufreq_power_cooling_register()` | ||
79 | and `of_cpufreq_power_cooling_register()` is optional. If you don't | ||
80 | provide it, only dynamic power will be considered. | ||
81 | |||
82 | 2.1 Dynamic power | ||
83 | |||
84 | The dynamic power consumption of a processor depends on many factors. | 55 | The dynamic power consumption of a processor depends on many factors. |
85 | For a given processor implementation the primary factors are: | 56 | For a given processor implementation the primary factors are: |
86 | 57 | ||
@@ -119,79 +90,3 @@ mW/MHz/uVolt^2. Typical values for mobile CPUs might lie in range | |||
119 | from 100 to 500. For reference, the approximate values for the SoC in | 90 | from 100 to 500. For reference, the approximate values for the SoC in |
120 | ARM's Juno Development Platform are 530 for the Cortex-A57 cluster and | 91 | ARM's Juno Development Platform are 530 for the Cortex-A57 cluster and |
121 | 140 for the Cortex-A53 cluster. | 92 | 140 for the Cortex-A53 cluster. |
122 | |||
123 | |||
124 | 2.2 Static power | ||
125 | |||
126 | Static leakage power consumption depends on a number of factors. For a | ||
127 | given circuit implementation the primary factors are: | ||
128 | |||
129 | - Time the circuit spends in each 'power state' | ||
130 | - Temperature | ||
131 | - Operating voltage | ||
132 | - Process grade | ||
133 | |||
134 | The time the circuit spends in each 'power state' for a given | ||
135 | evaluation period at first order means OFF or ON. However, | ||
136 | 'retention' states can also be supported that reduce power during | ||
137 | inactive periods without loss of context. | ||
138 | |||
139 | Note: The visibility of state entries to the OS can vary, according to | ||
140 | platform specifics, and this can then impact the accuracy of a model | ||
141 | based on OS state information alone. It might be possible in some | ||
142 | cases to extract more accurate information from system resources. | ||
143 | |||
144 | The temperature, operating voltage and process 'grade' (slow to fast) | ||
145 | of the circuit are all significant factors in static leakage power | ||
146 | consumption. All of these have complex relationships to static power. | ||
147 | |||
148 | Circuit implementation specific factors include the chosen silicon | ||
149 | process as well as the type, number and size of transistors in both | ||
150 | the logic gates and any RAM elements included. | ||
151 | |||
152 | The static power consumption modelling must take into account the | ||
153 | power managed regions that are implemented. Taking the example of an | ||
154 | ARM processor cluster, the modelling would take into account whether | ||
155 | each CPU can be powered OFF separately or if only a single power | ||
156 | region is implemented for the complete cluster. | ||
157 | |||
158 | In one view, there are others, a static power consumption model can | ||
159 | then start from a set of reference values for each power managed | ||
160 | region (e.g. CPU, Cluster/L2) in each state (e.g. ON, OFF) at an | ||
161 | arbitrary process grade, voltage and temperature point. These values | ||
162 | are then scaled for all of the following: the time in each state, the | ||
163 | process grade, the current temperature and the operating voltage. | ||
164 | However, since both implementation specific and complex relationships | ||
165 | dominate the estimate, the appropriate interface to the model from the | ||
166 | cpu cooling device is to provide a function callback that calculates | ||
167 | the static power in this platform. When registering the cpu cooling | ||
168 | device pass a function pointer that follows the `get_static_t` | ||
169 | prototype: | ||
170 | |||
171 | int plat_get_static(cpumask_t *cpumask, int interval, | ||
172 | unsigned long voltage, u32 &power); | ||
173 | |||
174 | `cpumask` is the cpumask of the cpus involved in the calculation. | ||
175 | `voltage` is the voltage at which they are operating. The function | ||
176 | should calculate the average static power for the last `interval` | ||
177 | milliseconds. It returns 0 on success, -E* on error. If it | ||
178 | succeeds, it should store the static power in `power`. Reading the | ||
179 | temperature of the cpus described by `cpumask` is left for | ||
180 | plat_get_static() to do as the platform knows best which thermal | ||
181 | sensor is closest to the cpu. | ||
182 | |||
183 | If `plat_static_func` is NULL, static power is considered to be | ||
184 | negligible for this platform and only dynamic power is considered. | ||
185 | |||
186 | The platform specific callback can then use any combination of tables | ||
187 | and/or equations to permute the estimated value. Process grade | ||
188 | information is not passed to the model since access to such data, from | ||
189 | on-chip measurement capability or manufacture time data, is platform | ||
190 | specific. | ||
191 | |||
192 | Note: the significance of static power for CPUs in comparison to | ||
193 | dynamic power is highly dependent on implementation. Given the | ||
194 | potential complexity in implementation, the importance and accuracy of | ||
195 | its inclusion when using cpu cooling devices should be assessed on a | ||
196 | case by case basis. | ||
197 | |||
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 65ec5f01aa8d..c56b57dcfda5 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c | |||
@@ -526,34 +526,13 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) | |||
526 | 526 | ||
527 | static void bL_cpufreq_ready(struct cpufreq_policy *policy) | 527 | static void bL_cpufreq_ready(struct cpufreq_policy *policy) |
528 | { | 528 | { |
529 | struct device *cpu_dev = get_cpu_device(policy->cpu); | ||
530 | int cur_cluster = cpu_to_cluster(policy->cpu); | 529 | int cur_cluster = cpu_to_cluster(policy->cpu); |
531 | struct device_node *np; | ||
532 | 530 | ||
533 | /* Do not register a cpu_cooling device if we are in IKS mode */ | 531 | /* Do not register a cpu_cooling device if we are in IKS mode */ |
534 | if (cur_cluster >= MAX_CLUSTERS) | 532 | if (cur_cluster >= MAX_CLUSTERS) |
535 | return; | 533 | return; |
536 | 534 | ||
537 | np = of_node_get(cpu_dev->of_node); | 535 | cdev[cur_cluster] = of_cpufreq_cooling_register(policy); |
538 | if (WARN_ON(!np)) | ||
539 | return; | ||
540 | |||
541 | if (of_find_property(np, "#cooling-cells", NULL)) { | ||
542 | u32 power_coefficient = 0; | ||
543 | |||
544 | of_property_read_u32(np, "dynamic-power-coefficient", | ||
545 | &power_coefficient); | ||
546 | |||
547 | cdev[cur_cluster] = of_cpufreq_power_cooling_register(np, | ||
548 | policy, power_coefficient, NULL); | ||
549 | if (IS_ERR(cdev[cur_cluster])) { | ||
550 | dev_err(cpu_dev, | ||
551 | "running cpufreq without cooling device: %ld\n", | ||
552 | PTR_ERR(cdev[cur_cluster])); | ||
553 | cdev[cur_cluster] = NULL; | ||
554 | } | ||
555 | } | ||
556 | of_node_put(np); | ||
557 | } | 536 | } |
558 | 537 | ||
559 | static struct cpufreq_driver bL_cpufreq_driver = { | 538 | static struct cpufreq_driver bL_cpufreq_driver = { |
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 545946ad0752..de3d104c25d7 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c | |||
@@ -319,33 +319,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy) | |||
319 | static void cpufreq_ready(struct cpufreq_policy *policy) | 319 | static void cpufreq_ready(struct cpufreq_policy *policy) |
320 | { | 320 | { |
321 | struct private_data *priv = policy->driver_data; | 321 | struct private_data *priv = policy->driver_data; |
322 | struct device_node *np = of_node_get(priv->cpu_dev->of_node); | ||
323 | 322 | ||
324 | if (WARN_ON(!np)) | 323 | priv->cdev = of_cpufreq_cooling_register(policy); |
325 | return; | ||
326 | |||
327 | /* | ||
328 | * For now, just loading the cooling device; | ||
329 | * thermal DT code takes care of matching them. | ||
330 | */ | ||
331 | if (of_find_property(np, "#cooling-cells", NULL)) { | ||
332 | u32 power_coefficient = 0; | ||
333 | |||
334 | of_property_read_u32(np, "dynamic-power-coefficient", | ||
335 | &power_coefficient); | ||
336 | |||
337 | priv->cdev = of_cpufreq_power_cooling_register(np, | ||
338 | policy, power_coefficient, NULL); | ||
339 | if (IS_ERR(priv->cdev)) { | ||
340 | dev_err(priv->cpu_dev, | ||
341 | "running cpufreq without cooling device: %ld\n", | ||
342 | PTR_ERR(priv->cdev)); | ||
343 | |||
344 | priv->cdev = NULL; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | of_node_put(np); | ||
349 | } | 324 | } |
350 | 325 | ||
351 | static struct cpufreq_driver dt_cpufreq_driver = { | 326 | static struct cpufreq_driver dt_cpufreq_driver = { |
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index b783919f063d..8c04dddd3c28 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c | |||
@@ -310,28 +310,8 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, | |||
310 | static void mtk_cpufreq_ready(struct cpufreq_policy *policy) | 310 | static void mtk_cpufreq_ready(struct cpufreq_policy *policy) |
311 | { | 311 | { |
312 | struct mtk_cpu_dvfs_info *info = policy->driver_data; | 312 | struct mtk_cpu_dvfs_info *info = policy->driver_data; |
313 | struct device_node *np = of_node_get(info->cpu_dev->of_node); | ||
314 | u32 capacitance = 0; | ||
315 | 313 | ||
316 | if (WARN_ON(!np)) | 314 | info->cdev = of_cpufreq_cooling_register(policy); |
317 | return; | ||
318 | |||
319 | if (of_find_property(np, "#cooling-cells", NULL)) { | ||
320 | of_property_read_u32(np, DYNAMIC_POWER, &capacitance); | ||
321 | |||
322 | info->cdev = of_cpufreq_power_cooling_register(np, | ||
323 | policy, capacitance, NULL); | ||
324 | |||
325 | if (IS_ERR(info->cdev)) { | ||
326 | dev_err(info->cpu_dev, | ||
327 | "running cpufreq without cooling device: %ld\n", | ||
328 | PTR_ERR(info->cdev)); | ||
329 | |||
330 | info->cdev = NULL; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | of_node_put(np); | ||
335 | } | 315 | } |
336 | 316 | ||
337 | static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) | 317 | static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) |
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 4ada55b8856e..0562761a3dec 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c | |||
@@ -275,20 +275,8 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy, | |||
275 | static void qoriq_cpufreq_ready(struct cpufreq_policy *policy) | 275 | static void qoriq_cpufreq_ready(struct cpufreq_policy *policy) |
276 | { | 276 | { |
277 | struct cpu_data *cpud = policy->driver_data; | 277 | struct cpu_data *cpud = policy->driver_data; |
278 | struct device_node *np = of_get_cpu_node(policy->cpu, NULL); | ||
279 | 278 | ||
280 | if (of_find_property(np, "#cooling-cells", NULL)) { | 279 | cpud->cdev = of_cpufreq_cooling_register(policy); |
281 | cpud->cdev = of_cpufreq_cooling_register(np, policy); | ||
282 | |||
283 | if (IS_ERR(cpud->cdev) && PTR_ERR(cpud->cdev) != -ENOSYS) { | ||
284 | pr_err("cpu%d is not running as cooling device: %ld\n", | ||
285 | policy->cpu, PTR_ERR(cpud->cdev)); | ||
286 | |||
287 | cpud->cdev = NULL; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | of_node_put(np); | ||
292 | } | 280 | } |
293 | 281 | ||
294 | static struct cpufreq_driver qoriq_cpufreq_driver = { | 282 | static struct cpufreq_driver qoriq_cpufreq_driver = { |
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index dc63aba092e4..dfd23245f778 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c | |||
@@ -88,7 +88,6 @@ struct time_in_idle { | |||
88 | * @policy: cpufreq policy. | 88 | * @policy: cpufreq policy. |
89 | * @node: list_head to link all cpufreq_cooling_device together. | 89 | * @node: list_head to link all cpufreq_cooling_device together. |
90 | * @idle_time: idle time stats | 90 | * @idle_time: idle time stats |
91 | * @plat_get_static_power: callback to calculate the static power | ||
92 | * | 91 | * |
93 | * This structure is required for keeping information of each registered | 92 | * This structure is required for keeping information of each registered |
94 | * cpufreq_cooling_device. | 93 | * cpufreq_cooling_device. |
@@ -104,7 +103,6 @@ struct cpufreq_cooling_device { | |||
104 | struct cpufreq_policy *policy; | 103 | struct cpufreq_policy *policy; |
105 | struct list_head node; | 104 | struct list_head node; |
106 | struct time_in_idle *idle_time; | 105 | struct time_in_idle *idle_time; |
107 | get_static_t plat_get_static_power; | ||
108 | }; | 106 | }; |
109 | 107 | ||
110 | static DEFINE_IDA(cpufreq_ida); | 108 | static DEFINE_IDA(cpufreq_ida); |
@@ -319,60 +317,6 @@ static u32 get_load(struct cpufreq_cooling_device *cpufreq_cdev, int cpu, | |||
319 | } | 317 | } |
320 | 318 | ||
321 | /** | 319 | /** |
322 | * get_static_power() - calculate the static power consumed by the cpus | ||
323 | * @cpufreq_cdev: struct &cpufreq_cooling_device for this cpu cdev | ||
324 | * @tz: thermal zone device in which we're operating | ||
325 | * @freq: frequency in KHz | ||
326 | * @power: pointer in which to store the calculated static power | ||
327 | * | ||
328 | * Calculate the static power consumed by the cpus described by | ||
329 | * @cpu_actor running at frequency @freq. This function relies on a | ||
330 | * platform specific function that should have been provided when the | ||
331 | * actor was registered. If it wasn't, the static power is assumed to | ||
332 | * be negligible. The calculated static power is stored in @power. | ||
333 | * | ||
334 | * Return: 0 on success, -E* on failure. | ||
335 | */ | ||
336 | static int get_static_power(struct cpufreq_cooling_device *cpufreq_cdev, | ||
337 | struct thermal_zone_device *tz, unsigned long freq, | ||
338 | u32 *power) | ||
339 | { | ||
340 | struct dev_pm_opp *opp; | ||
341 | unsigned long voltage; | ||
342 | struct cpufreq_policy *policy = cpufreq_cdev->policy; | ||
343 | struct cpumask *cpumask = policy->related_cpus; | ||
344 | unsigned long freq_hz = freq * 1000; | ||
345 | struct device *dev; | ||
346 | |||
347 | if (!cpufreq_cdev->plat_get_static_power) { | ||
348 | *power = 0; | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | dev = get_cpu_device(policy->cpu); | ||
353 | WARN_ON(!dev); | ||
354 | |||
355 | opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true); | ||
356 | if (IS_ERR(opp)) { | ||
357 | dev_warn_ratelimited(dev, "Failed to find OPP for frequency %lu: %ld\n", | ||
358 | freq_hz, PTR_ERR(opp)); | ||
359 | return -EINVAL; | ||
360 | } | ||
361 | |||
362 | voltage = dev_pm_opp_get_voltage(opp); | ||
363 | dev_pm_opp_put(opp); | ||
364 | |||
365 | if (voltage == 0) { | ||
366 | dev_err_ratelimited(dev, "Failed to get voltage for frequency %lu\n", | ||
367 | freq_hz); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | |||
371 | return cpufreq_cdev->plat_get_static_power(cpumask, tz->passive_delay, | ||
372 | voltage, power); | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * get_dynamic_power() - calculate the dynamic power | 320 | * get_dynamic_power() - calculate the dynamic power |
377 | * @cpufreq_cdev: &cpufreq_cooling_device for this cdev | 321 | * @cpufreq_cdev: &cpufreq_cooling_device for this cdev |
378 | * @freq: current frequency | 322 | * @freq: current frequency |
@@ -491,8 +435,8 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, | |||
491 | u32 *power) | 435 | u32 *power) |
492 | { | 436 | { |
493 | unsigned long freq; | 437 | unsigned long freq; |
494 | int i = 0, cpu, ret; | 438 | int i = 0, cpu; |
495 | u32 static_power, dynamic_power, total_load = 0; | 439 | u32 total_load = 0; |
496 | struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; | 440 | struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; |
497 | struct cpufreq_policy *policy = cpufreq_cdev->policy; | 441 | struct cpufreq_policy *policy = cpufreq_cdev->policy; |
498 | u32 *load_cpu = NULL; | 442 | u32 *load_cpu = NULL; |
@@ -522,22 +466,15 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, | |||
522 | 466 | ||
523 | cpufreq_cdev->last_load = total_load; | 467 | cpufreq_cdev->last_load = total_load; |
524 | 468 | ||
525 | dynamic_power = get_dynamic_power(cpufreq_cdev, freq); | 469 | *power = get_dynamic_power(cpufreq_cdev, freq); |
526 | ret = get_static_power(cpufreq_cdev, tz, freq, &static_power); | ||
527 | if (ret) { | ||
528 | kfree(load_cpu); | ||
529 | return ret; | ||
530 | } | ||
531 | 470 | ||
532 | if (load_cpu) { | 471 | if (load_cpu) { |
533 | trace_thermal_power_cpu_get_power(policy->related_cpus, freq, | 472 | trace_thermal_power_cpu_get_power(policy->related_cpus, freq, |
534 | load_cpu, i, dynamic_power, | 473 | load_cpu, i, *power); |
535 | static_power); | ||
536 | 474 | ||
537 | kfree(load_cpu); | 475 | kfree(load_cpu); |
538 | } | 476 | } |
539 | 477 | ||
540 | *power = static_power + dynamic_power; | ||
541 | return 0; | 478 | return 0; |
542 | } | 479 | } |
543 | 480 | ||
@@ -561,8 +498,6 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, | |||
561 | unsigned long state, u32 *power) | 498 | unsigned long state, u32 *power) |
562 | { | 499 | { |
563 | unsigned int freq, num_cpus; | 500 | unsigned int freq, num_cpus; |
564 | u32 static_power, dynamic_power; | ||
565 | int ret; | ||
566 | struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; | 501 | struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; |
567 | 502 | ||
568 | /* Request state should be less than max_level */ | 503 | /* Request state should be less than max_level */ |
@@ -572,13 +507,9 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, | |||
572 | num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus); | 507 | num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus); |
573 | 508 | ||
574 | freq = cpufreq_cdev->freq_table[state].frequency; | 509 | freq = cpufreq_cdev->freq_table[state].frequency; |
575 | dynamic_power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus; | 510 | *power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus; |
576 | ret = get_static_power(cpufreq_cdev, tz, freq, &static_power); | ||
577 | if (ret) | ||
578 | return ret; | ||
579 | 511 | ||
580 | *power = static_power + dynamic_power; | 512 | return 0; |
581 | return ret; | ||
582 | } | 513 | } |
583 | 514 | ||
584 | /** | 515 | /** |
@@ -606,21 +537,14 @@ static int cpufreq_power2state(struct thermal_cooling_device *cdev, | |||
606 | unsigned long *state) | 537 | unsigned long *state) |
607 | { | 538 | { |
608 | unsigned int cur_freq, target_freq; | 539 | unsigned int cur_freq, target_freq; |
609 | int ret; | 540 | u32 last_load, normalised_power; |
610 | s32 dyn_power; | ||
611 | u32 last_load, normalised_power, static_power; | ||
612 | struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; | 541 | struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; |
613 | struct cpufreq_policy *policy = cpufreq_cdev->policy; | 542 | struct cpufreq_policy *policy = cpufreq_cdev->policy; |
614 | 543 | ||
615 | cur_freq = cpufreq_quick_get(policy->cpu); | 544 | cur_freq = cpufreq_quick_get(policy->cpu); |
616 | ret = get_static_power(cpufreq_cdev, tz, cur_freq, &static_power); | 545 | power = power > 0 ? power : 0; |
617 | if (ret) | ||
618 | return ret; | ||
619 | |||
620 | dyn_power = power - static_power; | ||
621 | dyn_power = dyn_power > 0 ? dyn_power : 0; | ||
622 | last_load = cpufreq_cdev->last_load ?: 1; | 546 | last_load = cpufreq_cdev->last_load ?: 1; |
623 | normalised_power = (dyn_power * 100) / last_load; | 547 | normalised_power = (power * 100) / last_load; |
624 | target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power); | 548 | target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power); |
625 | 549 | ||
626 | *state = get_level(cpufreq_cdev, target_freq); | 550 | *state = get_level(cpufreq_cdev, target_freq); |
@@ -671,8 +595,6 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table, | |||
671 | * @policy: cpufreq policy | 595 | * @policy: cpufreq policy |
672 | * Normally this should be same as cpufreq policy->related_cpus. | 596 | * Normally this should be same as cpufreq policy->related_cpus. |
673 | * @capacitance: dynamic power coefficient for these cpus | 597 | * @capacitance: dynamic power coefficient for these cpus |
674 | * @plat_static_func: function to calculate the static power consumed by these | ||
675 | * cpus (optional) | ||
676 | * | 598 | * |
677 | * This interface function registers the cpufreq cooling device with the name | 599 | * This interface function registers the cpufreq cooling device with the name |
678 | * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq | 600 | * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq |
@@ -684,8 +606,7 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table, | |||
684 | */ | 606 | */ |
685 | static struct thermal_cooling_device * | 607 | static struct thermal_cooling_device * |
686 | __cpufreq_cooling_register(struct device_node *np, | 608 | __cpufreq_cooling_register(struct device_node *np, |
687 | struct cpufreq_policy *policy, u32 capacitance, | 609 | struct cpufreq_policy *policy, u32 capacitance) |
688 | get_static_t plat_static_func) | ||
689 | { | 610 | { |
690 | struct thermal_cooling_device *cdev; | 611 | struct thermal_cooling_device *cdev; |
691 | struct cpufreq_cooling_device *cpufreq_cdev; | 612 | struct cpufreq_cooling_device *cpufreq_cdev; |
@@ -755,8 +676,6 @@ __cpufreq_cooling_register(struct device_node *np, | |||
755 | } | 676 | } |
756 | 677 | ||
757 | if (capacitance) { | 678 | if (capacitance) { |
758 | cpufreq_cdev->plat_get_static_power = plat_static_func; | ||
759 | |||
760 | ret = update_freq_table(cpufreq_cdev, capacitance); | 679 | ret = update_freq_table(cpufreq_cdev, capacitance); |
761 | if (ret) { | 680 | if (ret) { |
762 | cdev = ERR_PTR(ret); | 681 | cdev = ERR_PTR(ret); |
@@ -813,13 +732,12 @@ free_cdev: | |||
813 | struct thermal_cooling_device * | 732 | struct thermal_cooling_device * |
814 | cpufreq_cooling_register(struct cpufreq_policy *policy) | 733 | cpufreq_cooling_register(struct cpufreq_policy *policy) |
815 | { | 734 | { |
816 | return __cpufreq_cooling_register(NULL, policy, 0, NULL); | 735 | return __cpufreq_cooling_register(NULL, policy, 0); |
817 | } | 736 | } |
818 | EXPORT_SYMBOL_GPL(cpufreq_cooling_register); | 737 | EXPORT_SYMBOL_GPL(cpufreq_cooling_register); |
819 | 738 | ||
820 | /** | 739 | /** |
821 | * of_cpufreq_cooling_register - function to create cpufreq cooling device. | 740 | * of_cpufreq_cooling_register - function to create cpufreq cooling device. |
822 | * @np: a valid struct device_node to the cooling device device tree node | ||
823 | * @policy: cpufreq policy | 741 | * @policy: cpufreq policy |
824 | * | 742 | * |
825 | * This interface function registers the cpufreq cooling device with the name | 743 | * This interface function registers the cpufreq cooling device with the name |
@@ -827,86 +745,45 @@ EXPORT_SYMBOL_GPL(cpufreq_cooling_register); | |||
827 | * cooling devices. Using this API, the cpufreq cooling device will be | 745 | * cooling devices. Using this API, the cpufreq cooling device will be |
828 | * linked to the device tree node provided. | 746 | * linked to the device tree node provided. |
829 | * | 747 | * |
830 | * Return: a valid struct thermal_cooling_device pointer on success, | ||
831 | * on failure, it returns a corresponding ERR_PTR(). | ||
832 | */ | ||
833 | struct thermal_cooling_device * | ||
834 | of_cpufreq_cooling_register(struct device_node *np, | ||
835 | struct cpufreq_policy *policy) | ||
836 | { | ||
837 | if (!np) | ||
838 | return ERR_PTR(-EINVAL); | ||
839 | |||
840 | return __cpufreq_cooling_register(np, policy, 0, NULL); | ||
841 | } | ||
842 | EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register); | ||
843 | |||
844 | /** | ||
845 | * cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions | ||
846 | * @policy: cpufreq policy | ||
847 | * @capacitance: dynamic power coefficient for these cpus | ||
848 | * @plat_static_func: function to calculate the static power consumed by these | ||
849 | * cpus (optional) | ||
850 | * | ||
851 | * This interface function registers the cpufreq cooling device with | ||
852 | * the name "thermal-cpufreq-%x". This api can support multiple | ||
853 | * instances of cpufreq cooling devices. Using this function, the | ||
854 | * cooling device will implement the power extensions by using a | ||
855 | * simple cpu power model. The cpus must have registered their OPPs | ||
856 | * using the OPP library. | ||
857 | * | ||
858 | * An optional @plat_static_func may be provided to calculate the | ||
859 | * static power consumed by these cpus. If the platform's static | ||
860 | * power consumption is unknown or negligible, make it NULL. | ||
861 | * | ||
862 | * Return: a valid struct thermal_cooling_device pointer on success, | ||
863 | * on failure, it returns a corresponding ERR_PTR(). | ||
864 | */ | ||
865 | struct thermal_cooling_device * | ||
866 | cpufreq_power_cooling_register(struct cpufreq_policy *policy, u32 capacitance, | ||
867 | get_static_t plat_static_func) | ||
868 | { | ||
869 | return __cpufreq_cooling_register(NULL, policy, capacitance, | ||
870 | plat_static_func); | ||
871 | } | ||
872 | EXPORT_SYMBOL(cpufreq_power_cooling_register); | ||
873 | |||
874 | /** | ||
875 | * of_cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions | ||
876 | * @np: a valid struct device_node to the cooling device device tree node | ||
877 | * @policy: cpufreq policy | ||
878 | * @capacitance: dynamic power coefficient for these cpus | ||
879 | * @plat_static_func: function to calculate the static power consumed by these | ||
880 | * cpus (optional) | ||
881 | * | ||
882 | * This interface function registers the cpufreq cooling device with | ||
883 | * the name "thermal-cpufreq-%x". This api can support multiple | ||
884 | * instances of cpufreq cooling devices. Using this API, the cpufreq | ||
885 | * cooling device will be linked to the device tree node provided. | ||
886 | * Using this function, the cooling device will implement the power | 748 | * Using this function, the cooling device will implement the power |
887 | * extensions by using a simple cpu power model. The cpus must have | 749 | * extensions by using a simple cpu power model. The cpus must have |
888 | * registered their OPPs using the OPP library. | 750 | * registered their OPPs using the OPP library. |
889 | * | 751 | * |
890 | * An optional @plat_static_func may be provided to calculate the | 752 | * It also takes into account, if property present in policy CPU node, the |
891 | * static power consumed by these cpus. If the platform's static | 753 | * static power consumed by the cpu. |
892 | * power consumption is unknown or negligible, make it NULL. | ||
893 | * | 754 | * |
894 | * Return: a valid struct thermal_cooling_device pointer on success, | 755 | * Return: a valid struct thermal_cooling_device pointer on success, |
895 | * on failure, it returns a corresponding ERR_PTR(). | 756 | * and NULL on failure. |
896 | */ | 757 | */ |
897 | struct thermal_cooling_device * | 758 | struct thermal_cooling_device * |
898 | of_cpufreq_power_cooling_register(struct device_node *np, | 759 | of_cpufreq_cooling_register(struct cpufreq_policy *policy) |
899 | struct cpufreq_policy *policy, | ||
900 | u32 capacitance, | ||
901 | get_static_t plat_static_func) | ||
902 | { | 760 | { |
903 | if (!np) | 761 | struct device_node *np = of_get_cpu_node(policy->cpu, NULL); |
904 | return ERR_PTR(-EINVAL); | 762 | struct thermal_cooling_device *cdev = NULL; |
763 | u32 capacitance = 0; | ||
764 | |||
765 | if (!np) { | ||
766 | pr_err("cpu_cooling: OF node not available for cpu%d\n", | ||
767 | policy->cpu); | ||
768 | return NULL; | ||
769 | } | ||
770 | |||
771 | if (of_find_property(np, "#cooling-cells", NULL)) { | ||
772 | of_property_read_u32(np, "dynamic-power-coefficient", | ||
773 | &capacitance); | ||
905 | 774 | ||
906 | return __cpufreq_cooling_register(np, policy, capacitance, | 775 | cdev = __cpufreq_cooling_register(np, policy, capacitance); |
907 | plat_static_func); | 776 | if (IS_ERR(cdev)) { |
777 | pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n", | ||
778 | policy->cpu, PTR_ERR(cdev)); | ||
779 | cdev = NULL; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | of_node_put(np); | ||
784 | return cdev; | ||
908 | } | 785 | } |
909 | EXPORT_SYMBOL(of_cpufreq_power_cooling_register); | 786 | EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register); |
910 | 787 | ||
911 | /** | 788 | /** |
912 | * cpufreq_cooling_unregister - function to remove cpufreq cooling device. | 789 | * cpufreq_cooling_unregister - function to remove cpufreq cooling device. |
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h index d4292ebc5c8b..de0dafb9399d 100644 --- a/include/linux/cpu_cooling.h +++ b/include/linux/cpu_cooling.h | |||
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | struct cpufreq_policy; | 31 | struct cpufreq_policy; |
32 | 32 | ||
33 | typedef int (*get_static_t)(cpumask_t *cpumask, int interval, | ||
34 | unsigned long voltage, u32 *power); | ||
35 | |||
36 | #ifdef CONFIG_CPU_THERMAL | 33 | #ifdef CONFIG_CPU_THERMAL |
37 | /** | 34 | /** |
38 | * cpufreq_cooling_register - function to create cpufreq cooling device. | 35 | * cpufreq_cooling_register - function to create cpufreq cooling device. |
@@ -41,43 +38,6 @@ typedef int (*get_static_t)(cpumask_t *cpumask, int interval, | |||
41 | struct thermal_cooling_device * | 38 | struct thermal_cooling_device * |
42 | cpufreq_cooling_register(struct cpufreq_policy *policy); | 39 | cpufreq_cooling_register(struct cpufreq_policy *policy); |
43 | 40 | ||
44 | struct thermal_cooling_device * | ||
45 | cpufreq_power_cooling_register(struct cpufreq_policy *policy, | ||
46 | u32 capacitance, get_static_t plat_static_func); | ||
47 | |||
48 | /** | ||
49 | * of_cpufreq_cooling_register - create cpufreq cooling device based on DT. | ||
50 | * @np: a valid struct device_node to the cooling device device tree node. | ||
51 | * @policy: cpufreq policy. | ||
52 | */ | ||
53 | #ifdef CONFIG_THERMAL_OF | ||
54 | struct thermal_cooling_device * | ||
55 | of_cpufreq_cooling_register(struct device_node *np, | ||
56 | struct cpufreq_policy *policy); | ||
57 | |||
58 | struct thermal_cooling_device * | ||
59 | of_cpufreq_power_cooling_register(struct device_node *np, | ||
60 | struct cpufreq_policy *policy, | ||
61 | u32 capacitance, | ||
62 | get_static_t plat_static_func); | ||
63 | #else | ||
64 | static inline struct thermal_cooling_device * | ||
65 | of_cpufreq_cooling_register(struct device_node *np, | ||
66 | struct cpufreq_policy *policy) | ||
67 | { | ||
68 | return ERR_PTR(-ENOSYS); | ||
69 | } | ||
70 | |||
71 | static inline struct thermal_cooling_device * | ||
72 | of_cpufreq_power_cooling_register(struct device_node *np, | ||
73 | struct cpufreq_policy *policy, | ||
74 | u32 capacitance, | ||
75 | get_static_t plat_static_func) | ||
76 | { | ||
77 | return NULL; | ||
78 | } | ||
79 | #endif | ||
80 | |||
81 | /** | 41 | /** |
82 | * cpufreq_cooling_unregister - function to remove cpufreq cooling device. | 42 | * cpufreq_cooling_unregister - function to remove cpufreq cooling device. |
83 | * @cdev: thermal cooling device pointer. | 43 | * @cdev: thermal cooling device pointer. |
@@ -90,34 +50,27 @@ cpufreq_cooling_register(struct cpufreq_policy *policy) | |||
90 | { | 50 | { |
91 | return ERR_PTR(-ENOSYS); | 51 | return ERR_PTR(-ENOSYS); |
92 | } | 52 | } |
93 | static inline struct thermal_cooling_device * | ||
94 | cpufreq_power_cooling_register(struct cpufreq_policy *policy, | ||
95 | u32 capacitance, get_static_t plat_static_func) | ||
96 | { | ||
97 | return NULL; | ||
98 | } | ||
99 | 53 | ||
100 | static inline struct thermal_cooling_device * | 54 | static inline |
101 | of_cpufreq_cooling_register(struct device_node *np, | 55 | void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) |
102 | struct cpufreq_policy *policy) | ||
103 | { | 56 | { |
104 | return ERR_PTR(-ENOSYS); | 57 | return; |
105 | } | 58 | } |
59 | #endif /* CONFIG_CPU_THERMAL */ | ||
106 | 60 | ||
61 | #if defined(CONFIG_THERMAL_OF) && defined(CONFIG_CPU_THERMAL) | ||
62 | /** | ||
63 | * of_cpufreq_cooling_register - create cpufreq cooling device based on DT. | ||
64 | * @policy: cpufreq policy. | ||
65 | */ | ||
66 | struct thermal_cooling_device * | ||
67 | of_cpufreq_cooling_register(struct cpufreq_policy *policy); | ||
68 | #else | ||
107 | static inline struct thermal_cooling_device * | 69 | static inline struct thermal_cooling_device * |
108 | of_cpufreq_power_cooling_register(struct device_node *np, | 70 | of_cpufreq_cooling_register(struct cpufreq_policy *policy) |
109 | struct cpufreq_policy *policy, | ||
110 | u32 capacitance, | ||
111 | get_static_t plat_static_func) | ||
112 | { | 71 | { |
113 | return NULL; | 72 | return NULL; |
114 | } | 73 | } |
115 | 74 | #endif /* defined(CONFIG_THERMAL_OF) && defined(CONFIG_CPU_THERMAL) */ | |
116 | static inline | ||
117 | void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) | ||
118 | { | ||
119 | return; | ||
120 | } | ||
121 | #endif /* CONFIG_CPU_THERMAL */ | ||
122 | 75 | ||
123 | #endif /* __CPU_COOLING_H__ */ | 76 | #endif /* __CPU_COOLING_H__ */ |
diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h index 78946640fe03..135e5421f003 100644 --- a/include/trace/events/thermal.h +++ b/include/trace/events/thermal.h | |||
@@ -94,9 +94,9 @@ TRACE_EVENT(thermal_zone_trip, | |||
94 | #ifdef CONFIG_CPU_THERMAL | 94 | #ifdef CONFIG_CPU_THERMAL |
95 | TRACE_EVENT(thermal_power_cpu_get_power, | 95 | TRACE_EVENT(thermal_power_cpu_get_power, |
96 | TP_PROTO(const struct cpumask *cpus, unsigned long freq, u32 *load, | 96 | TP_PROTO(const struct cpumask *cpus, unsigned long freq, u32 *load, |
97 | size_t load_len, u32 dynamic_power, u32 static_power), | 97 | size_t load_len, u32 dynamic_power), |
98 | 98 | ||
99 | TP_ARGS(cpus, freq, load, load_len, dynamic_power, static_power), | 99 | TP_ARGS(cpus, freq, load, load_len, dynamic_power), |
100 | 100 | ||
101 | TP_STRUCT__entry( | 101 | TP_STRUCT__entry( |
102 | __bitmask(cpumask, num_possible_cpus()) | 102 | __bitmask(cpumask, num_possible_cpus()) |
@@ -104,7 +104,6 @@ TRACE_EVENT(thermal_power_cpu_get_power, | |||
104 | __dynamic_array(u32, load, load_len) | 104 | __dynamic_array(u32, load, load_len) |
105 | __field(size_t, load_len ) | 105 | __field(size_t, load_len ) |
106 | __field(u32, dynamic_power ) | 106 | __field(u32, dynamic_power ) |
107 | __field(u32, static_power ) | ||
108 | ), | 107 | ), |
109 | 108 | ||
110 | TP_fast_assign( | 109 | TP_fast_assign( |
@@ -115,13 +114,12 @@ TRACE_EVENT(thermal_power_cpu_get_power, | |||
115 | load_len * sizeof(*load)); | 114 | load_len * sizeof(*load)); |
116 | __entry->load_len = load_len; | 115 | __entry->load_len = load_len; |
117 | __entry->dynamic_power = dynamic_power; | 116 | __entry->dynamic_power = dynamic_power; |
118 | __entry->static_power = static_power; | ||
119 | ), | 117 | ), |
120 | 118 | ||
121 | TP_printk("cpus=%s freq=%lu load={%s} dynamic_power=%d static_power=%d", | 119 | TP_printk("cpus=%s freq=%lu load={%s} dynamic_power=%d", |
122 | __get_bitmask(cpumask), __entry->freq, | 120 | __get_bitmask(cpumask), __entry->freq, |
123 | __print_array(__get_dynamic_array(load), __entry->load_len, 4), | 121 | __print_array(__get_dynamic_array(load), __entry->load_len, 4), |
124 | __entry->dynamic_power, __entry->static_power) | 122 | __entry->dynamic_power) |
125 | ); | 123 | ); |
126 | 124 | ||
127 | TRACE_EVENT(thermal_power_cpu_limit, | 125 | TRACE_EVENT(thermal_power_cpu_limit, |