hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/drivers/thermal/devfreq_cooling.c
....@@ -1,17 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * devfreq_cooling: Thermal cooling device implementation for devices using
34 * devfreq
45 *
56 * Copyright (C) 2014-2015 ARM Limited
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License version 2 as
9
- * published by the Free Software Foundation.
10
- *
11
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12
- * kind, whether express or implied; without even the implied warranty
13
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
157 *
168 * TODO:
179 * - If OPPs are added or removed after devfreq cooling has
....@@ -24,11 +16,13 @@
2416 #include <linux/idr.h>
2517 #include <linux/slab.h>
2618 #include <linux/pm_opp.h>
19
+#include <linux/pm_qos.h>
2720 #include <linux/thermal.h>
2821
2922 #include <trace/events/thermal.h>
3023
31
-#define SCALE_ERROR_MITIGATION 100
24
+#define HZ_PER_KHZ 1000
25
+#define SCALE_ERROR_MITIGATION 100
3226
3327 static DEFINE_IDA(devfreq_ida);
3428
....@@ -53,6 +47,9 @@
5347 * 'utilization' (which is 'busy_time / 'total_time').
5448 * The 'res_util' range is from 100 to (power_table[state] * 100)
5549 * for the corresponding 'state'.
50
+ * @capped_state: index to cooling state with in dynamic power budget
51
+ * @req_max_freq: PM QoS request for limiting the maximum frequency
52
+ * of the devfreq device.
5653 */
5754 struct devfreq_cooling_device {
5855 int id;
....@@ -65,48 +62,8 @@
6562 struct devfreq_cooling_power *power_ops;
6663 u32 res_util;
6764 int capped_state;
65
+ struct dev_pm_qos_request req_max_freq;
6866 };
69
-
70
-/**
71
- * partition_enable_opps() - disable all opps above a given state
72
- * @dfc: Pointer to devfreq we are operating on
73
- * @cdev_state: cooling device state we're setting
74
- *
75
- * Go through the OPPs of the device, enabling all OPPs until
76
- * @cdev_state and disabling those frequencies above it.
77
- */
78
-static int partition_enable_opps(struct devfreq_cooling_device *dfc,
79
- unsigned long cdev_state)
80
-{
81
- int i;
82
- struct device *dev = dfc->devfreq->dev.parent;
83
-
84
- for (i = 0; i < dfc->freq_table_size; i++) {
85
- struct dev_pm_opp *opp;
86
- int ret = 0;
87
- unsigned int freq = dfc->freq_table[i];
88
- bool want_enable = i >= cdev_state ? true : false;
89
-
90
- opp = dev_pm_opp_find_freq_exact(dev, freq, !want_enable);
91
-
92
- if (PTR_ERR(opp) == -ERANGE)
93
- continue;
94
- else if (IS_ERR(opp))
95
- return PTR_ERR(opp);
96
-
97
- dev_pm_opp_put(opp);
98
-
99
- if (want_enable)
100
- ret = dev_pm_opp_enable(dev, freq);
101
- else
102
- ret = dev_pm_opp_disable(dev, freq);
103
-
104
- if (ret)
105
- return ret;
106
- }
107
-
108
- return 0;
109
-}
11067
11168 static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev,
11269 unsigned long *state)
....@@ -134,7 +91,7 @@
13491 struct devfreq_cooling_device *dfc = cdev->devdata;
13592 struct devfreq *df = dfc->devfreq;
13693 struct device *dev = df->dev.parent;
137
- int ret;
94
+ unsigned long freq;
13895
13996 if (state == dfc->cooling_state)
14097 return 0;
....@@ -144,9 +101,10 @@
144101 if (state >= dfc->freq_table_size)
145102 return -EINVAL;
146103
147
- ret = partition_enable_opps(dfc, state);
148
- if (ret)
149
- return ret;
104
+ freq = dfc->freq_table[state];
105
+
106
+ dev_pm_qos_update_request(&dfc->req_max_freq,
107
+ DIV_ROUND_UP(freq, HZ_PER_KHZ));
150108
151109 dfc->cooling_state = state;
152110
....@@ -271,7 +229,6 @@
271229
272230
273231 static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev,
274
- struct thermal_zone_device *tz,
275232 u32 *power)
276233 {
277234 struct devfreq_cooling_device *dfc = cdev->devdata;
....@@ -283,14 +240,6 @@
283240 u32 dyn_power = 0;
284241 u32 static_power = 0;
285242 int res;
286
-
287
- if (status->update) {
288
- if (df->profile->get_dev_status(df->dev.parent,
289
- &df->last_status)) {
290
- status->busy_time = 1;
291
- status->total_time = 1;
292
- }
293
- }
294243
295244 state = freq_get_state(dfc, freq);
296245 if (state == THERMAL_CSTATE_INVALID) {
....@@ -339,7 +288,6 @@
339288 }
340289
341290 static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,
342
- struct thermal_zone_device *tz,
343291 unsigned long state,
344292 u32 *power)
345293 {
....@@ -358,7 +306,6 @@
358306 }
359307
360308 static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
361
- struct thermal_zone_device *tz,
362309 u32 power, unsigned long *state)
363310 {
364311 struct devfreq_cooling_device *dfc = cdev->devdata;
....@@ -537,9 +484,15 @@
537484 if (err)
538485 goto free_dfc;
539486
540
- err = ida_simple_get(&devfreq_ida, 0, 0, GFP_KERNEL);
487
+ err = dev_pm_qos_add_request(df->dev.parent, &dfc->req_max_freq,
488
+ DEV_PM_QOS_MAX_FREQUENCY,
489
+ PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
541490 if (err < 0)
542491 goto free_tables;
492
+
493
+ err = ida_simple_get(&devfreq_ida, 0, 0, GFP_KERNEL);
494
+ if (err < 0)
495
+ goto remove_qos_req;
543496 dfc->id = err;
544497
545498 snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id);
....@@ -560,6 +513,10 @@
560513
561514 release_ida:
562515 ida_simple_remove(&devfreq_ida, dfc->id);
516
+
517
+remove_qos_req:
518
+ dev_pm_qos_remove_request(&dfc->req_max_freq);
519
+
563520 free_tables:
564521 kfree(dfc->power_table);
565522 kfree(dfc->freq_table);
....@@ -595,7 +552,7 @@
595552
596553 /**
597554 * devfreq_cooling_unregister() - Unregister devfreq cooling device.
598
- * @dfc: Pointer to devfreq cooling device to unregister.
555
+ * @cdev: Pointer to devfreq cooling device to unregister.
599556 */
600557 void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
601558 {
....@@ -608,6 +565,7 @@
608565
609566 thermal_cooling_device_unregister(dfc->cdev);
610567 ida_simple_remove(&devfreq_ida, dfc->id);
568
+ dev_pm_qos_remove_request(&dfc->req_max_freq);
611569 kfree(dfc->power_table);
612570 kfree(dfc->freq_table);
613571