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

PM / devfreq: Register devfreq as a cooling device on demand

Currently the default behavior is to manually having the devfreq
backend to register themselves as a devfreq cooling device.

Instead of adding the code in the drivers for the thermal cooling
device registering, let's provide a flag in the devfreq's profile to
tell the common devfreq code to register the newly created devfreq as
a cooling device.

Suggested-by: Chanwoo Choi <cwchoi00@gmail.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Steven Price <steven.price@arm.com>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>

authored by

Daniel Lezcano and committed by
Chanwoo Choi
1224451b fe07bfda

+18
+9
drivers/devfreq/devfreq.c
··· 11 11 #include <linux/kmod.h> 12 12 #include <linux/sched.h> 13 13 #include <linux/debugfs.h> 14 + #include <linux/devfreq_cooling.h> 14 15 #include <linux/errno.h> 15 16 #include <linux/err.h> 16 17 #include <linux/init.h> ··· 936 935 937 936 mutex_unlock(&devfreq_list_lock); 938 937 938 + if (devfreq->profile->is_cooling_device) { 939 + devfreq->cdev = devfreq_cooling_em_register(devfreq, NULL); 940 + if (IS_ERR(devfreq->cdev)) 941 + devfreq->cdev = NULL; 942 + } 943 + 939 944 return devfreq; 940 945 941 946 err_init: ··· 966 959 { 967 960 if (!devfreq) 968 961 return -EINVAL; 962 + 963 + devfreq_cooling_unregister(devfreq->cdev); 969 964 970 965 if (devfreq->governor) { 971 966 devfreq->governor->event_handler(devfreq,
+9
include/linux/devfreq.h
··· 38 38 39 39 struct devfreq; 40 40 struct devfreq_governor; 41 + struct thermal_cooling_device; 41 42 42 43 /** 43 44 * struct devfreq_dev_status - Data given from devfreq user device to ··· 99 98 * @freq_table: Optional list of frequencies to support statistics 100 99 * and freq_table must be generated in ascending order. 101 100 * @max_state: The size of freq_table. 101 + * 102 + * @is_cooling_device: A self-explanatory boolean giving the device a 103 + * cooling effect property. 102 104 */ 103 105 struct devfreq_dev_profile { 104 106 unsigned long initial_freq; 105 107 unsigned int polling_ms; 106 108 enum devfreq_timer timer; 109 + bool is_cooling_device; 107 110 108 111 int (*target)(struct device *dev, unsigned long *freq, u32 flags); 109 112 int (*get_dev_status)(struct device *dev, ··· 161 156 * @suspend_count: suspend requests counter for a device. 162 157 * @stats: Statistics of devfreq device behavior 163 158 * @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier 159 + * @cdev: Cooling device pointer if the devfreq has cooling property 164 160 * @nb_min: Notifier block for DEV_PM_QOS_MIN_FREQUENCY 165 161 * @nb_max: Notifier block for DEV_PM_QOS_MAX_FREQUENCY 166 162 * ··· 203 197 struct devfreq_stats stats; 204 198 205 199 struct srcu_notifier_head transition_notifier_list; 200 + 201 + /* Pointer to the cooling device if used for thermal mitigation */ 202 + struct thermal_cooling_device *cdev; 206 203 207 204 struct notifier_block nb_min; 208 205 struct notifier_block nb_max;