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

thermal/drivers/cpuidle_cooling: Change the registration function

Today, there is no user for the cpuidle cooling device. The targetted
platform is ARM and ARM64.

The cpuidle and the cpufreq cooling device are based on the device tree.

As the cpuidle cooling device can have its own configuration depending
on the platform and the available idle states. The DT node description
will give the optional properties to set the cooling device up.

Do no longer rely on the CPU node which is prone to error and will
lead to a confusion in the DT because the cpufreq cooling device is
also using it. Let initialize the cpuidle cooling device with the DT
binding.

This was tested on:
- hikey960
- hikey6220
- rock960
- db845c

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Amit Kucheria <amit.kucheria@linaro.org>
Tested-by: Amit Kucheria <amit.kucheria@linaro.org>
Link: https://lore.kernel.org/r/20200429103644.5492-3-daniel.lezcano@linaro.org

+53 -22
+51 -12
drivers/thermal/cpuidle_cooling.c
··· 5 5 * Author: Daniel Lezcano <daniel.lezcano@linaro.org> 6 6 * 7 7 */ 8 + #define pr_fmt(fmt) "cpuidle cooling: " fmt 9 + 8 10 #include <linux/cpu_cooling.h> 9 11 #include <linux/cpuidle.h> 10 12 #include <linux/err.h> 11 13 #include <linux/idle_inject.h> 12 14 #include <linux/idr.h> 15 + #include <linux/of_device.h> 13 16 #include <linux/slab.h> 14 17 #include <linux/thermal.h> 15 18 ··· 157 154 }; 158 155 159 156 /** 160 - * cpuidle_of_cooling_register - Idle cooling device initialization function 157 + * __cpuidle_cooling_register: register the cooling device 161 158 * @drv: a cpuidle driver structure pointer 162 - * @np: a node pointer to a device tree cooling device node 159 + * @np: a device node structure pointer used for the thermal binding 163 160 * 164 - * This function is in charge of creating a cooling device per cpuidle 165 - * driver and register it to thermal framework. 161 + * This function is in charge of allocating the cpuidle cooling device 162 + * structure, the idle injection, initialize them and register the 163 + * cooling device to the thermal framework. 166 164 * 167 - * Return: zero on success, or negative value corresponding to the 168 - * error detected in the underlying subsystems. 165 + * Return: zero on success, a negative value returned by one of the 166 + * underlying subsystem in case of error 169 167 */ 170 - int cpuidle_of_cooling_register(struct device_node *np, 171 - struct cpuidle_driver *drv) 168 + static int __cpuidle_cooling_register(struct device_node *np, 169 + struct cpuidle_driver *drv) 172 170 { 173 171 struct idle_inject_device *ii_dev; 174 172 struct cpuidle_cooling_device *idle_cdev; 175 173 struct thermal_cooling_device *cdev; 174 + unsigned int idle_duration_us = TICK_USEC; 175 + unsigned int latency_us = UINT_MAX; 176 176 char dev_name[THERMAL_NAME_LENGTH]; 177 177 int id, ret; 178 178 ··· 197 191 goto out_id; 198 192 } 199 193 200 - idle_inject_set_duration(ii_dev, TICK_USEC, TICK_USEC); 194 + of_property_read_u32(np, "duration-us", &idle_duration_us); 195 + of_property_read_u32(np, "exit-latency-us", &latency_us); 196 + 197 + idle_inject_set_duration(ii_dev, TICK_USEC, idle_duration_us); 198 + idle_inject_set_latency(ii_dev, latency_us); 201 199 202 200 idle_cdev->ii_dev = ii_dev; 203 201 ··· 213 203 ret = PTR_ERR(cdev); 214 204 goto out_unregister; 215 205 } 206 + 207 + pr_debug("%s: Idle injection set with idle duration=%u, latency=%u\n", 208 + dev_name, idle_duration_us, latency_us); 216 209 217 210 return 0; 218 211 ··· 234 221 * @drv: a cpuidle driver structure pointer 235 222 * 236 223 * This function is in charge of creating a cooling device per cpuidle 237 - * driver and register it to thermal framework. 224 + * driver and register it to the thermal framework. 238 225 * 239 226 * Return: zero on success, or negative value corresponding to the 240 227 * error detected in the underlying subsystems. 241 228 */ 242 - int cpuidle_cooling_register(struct cpuidle_driver *drv) 229 + void cpuidle_cooling_register(struct cpuidle_driver *drv) 243 230 { 244 - return cpuidle_of_cooling_register(NULL, drv); 231 + struct device_node *cooling_node; 232 + struct device_node *cpu_node; 233 + int cpu, ret; 234 + 235 + for_each_cpu(cpu, drv->cpumask) { 236 + 237 + cpu_node = of_cpu_device_node_get(cpu); 238 + 239 + cooling_node = of_get_child_by_name(cpu_node, "thermal-idle"); 240 + 241 + of_node_put(cpu_node); 242 + 243 + if (!cooling_node) { 244 + pr_debug("'thermal-idle' node not found for cpu%d\n", cpu); 245 + continue; 246 + } 247 + 248 + ret = __cpuidle_cooling_register(cooling_node, drv); 249 + 250 + of_node_put(cooling_node); 251 + 252 + if (ret) { 253 + pr_err("Failed to register the cpuidle cooling device" \ 254 + "for cpu%d: %d\n", cpu, ret); 255 + break; 256 + } 257 + } 245 258 }
+2 -10
include/linux/cpu_cooling.h
··· 63 63 struct cpuidle_driver; 64 64 65 65 #ifdef CONFIG_CPU_IDLE_THERMAL 66 - int cpuidle_cooling_register(struct cpuidle_driver *drv); 67 - int cpuidle_of_cooling_register(struct device_node *np, 68 - struct cpuidle_driver *drv); 66 + void cpuidle_cooling_register(struct cpuidle_driver *drv); 69 67 #else /* CONFIG_CPU_IDLE_THERMAL */ 70 - static inline int cpuidle_cooling_register(struct cpuidle_driver *drv) 68 + static inline void cpuidle_cooling_register(struct cpuidle_driver *drv) 71 69 { 72 - return 0; 73 - } 74 - static inline int cpuidle_of_cooling_register(struct device_node *np, 75 - struct cpuidle_driver *drv) 76 - { 77 - return 0; 78 70 } 79 71 #endif /* CONFIG_CPU_IDLE_THERMAL */ 80 72