Re: [PATCH v3 3/4] thermal/drivers/cpuidle_cooling: Change the registration function

From: Daniel Lezcano
Date: Tue Apr 28 2020 - 11:30:12 EST



Hi Lukasz,

On 28/04/2020 17:20, Lukasz Luba wrote:
> Hi Daniel,
>
> I have checked the patches and run them on Juno.
> Please find my comments below.

thanks a lot for the review and the testing.



> On 4/14/20 11:08 PM, Daniel Lezcano wrote:
>> 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@xxxxxxxxxx>
>> Signed-off-by: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx>
>> ---
>> Â drivers/thermal/cpuidle_cooling.c | 58 +++++++++++++++++++++++++------
>> Â include/linux/cpu_cooling.hÂÂÂÂÂÂ |Â 7 ----
>> Â 2 files changed, 47 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/thermal/cpuidle_cooling.c
>> b/drivers/thermal/cpuidle_cooling.c
>> index 0bb843246f59..b2c81c427f05 100644
>> --- a/drivers/thermal/cpuidle_cooling.c
>> +++ b/drivers/thermal/cpuidle_cooling.c
>> @@ -10,6 +10,7 @@
>> Â #include <linux/err.h>
>> Â #include <linux/idle_inject.h>
>> Â #include <linux/idr.h>
>> +#include <linux/of_device.h>
>> Â #include <linux/slab.h>
>> Â #include <linux/thermal.h>
>> Â @@ -154,22 +155,25 @@ static struct thermal_cooling_device_ops
>> cpuidle_cooling_ops = {
>> Â };
>> Â Â /**
>> - * cpuidle_of_cooling_register - Idle cooling device initialization
>> function
>> + * __cpuidle_cooling_register: register the cooling device
>> ÂÂ * @drv: a cpuidle driver structure pointer
>> - * @np: a node pointer to a device tree cooling device node
>> + * @np: a device node structure pointer used for the thermal binding
>> ÂÂ *
>> - * This function is in charge of creating a cooling device per cpuidle
>> - * driver and register it to thermal framework.
>> + * This function is in charge of allocating the cpuidle cooling device
>> + * structure, the idle injection, initialize them and register the
>> + * cooling device to the thermal framework.
>> ÂÂ *
>> - * Return: zero on success, or negative value corresponding to the
>> - * error detected in the underlying subsystems.
>> + * Return: zero on success, a negative value returned by one of the
>> + * underlying subsystem in case of error
>> ÂÂ */
>> -int cpuidle_of_cooling_register(struct device_node *np,
>> -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct cpuidle_driver *drv)
>> +static int __cpuidle_cooling_register(struct device_node *np,
>> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct cpuidle_driver *drv)
>> Â {
>> ÂÂÂÂÂ struct idle_inject_device *ii_dev;
>> ÂÂÂÂÂ struct cpuidle_cooling_device *idle_cdev;
>> ÂÂÂÂÂ struct thermal_cooling_device *cdev;
>> +ÂÂÂ unsigned int idle_duration_us = TICK_USEC;
>> +ÂÂÂ unsigned int latency_us = UINT_MAX;
>> ÂÂÂÂÂ char dev_name[THERMAL_NAME_LENGTH];
>> ÂÂÂÂÂ int id, ret;
>> Â @@ -191,7 +195,11 @@ int cpuidle_of_cooling_register(struct
>> device_node *np,
>> ÂÂÂÂÂÂÂÂÂ goto out_id;
>> ÂÂÂÂÂ }
>> Â -ÂÂÂ idle_inject_set_duration(ii_dev, TICK_USEC, TICK_USEC);
>> +ÂÂÂ of_property_read_u32(np, "duration", &idle_duration_us);
>
> This probably is 'duration-us' according to DT bindings.
>
>> +ÂÂÂ of_property_read_u32(np, "latency", &latency_us);
>
> the same here s/latency/exit-latency-us/
>
>> +
>> +ÂÂÂ idle_inject_set_duration(ii_dev, TICK_USEC, idle_duration_us);
>> +ÂÂÂ idle_inject_set_latency(ii_dev, latency_us);
>> Â ÂÂÂÂÂ idle_cdev->ii_dev = ii_dev;
>> Â @@ -204,6 +212,9 @@ int cpuidle_of_cooling_register(struct
>> device_node *np,
>> ÂÂÂÂÂÂÂÂÂ goto out_unregister;
>> ÂÂÂÂÂ }
>> Â +ÂÂÂ pr_info("%s: Idle injection set with idle duration=%u,
>> latency=%u\n",
>> +ÂÂÂÂÂÂÂ dev_name, idle_duration_us, latency_us);
>
> 1. It is more like a 'debug' rather than 'info', I would change it.
> 2. This is going to be printed for every CPU which has the
> 'thermal-idle' feature in DT. For platforms with many CPUs, it's a lot
> of log entries
>
>> +
>> ÂÂÂÂÂ return 0;
>> Â Â out_unregister:
>> @@ -221,12 +232,37 @@ int cpuidle_of_cooling_register(struct
>> device_node *np,
>> ÂÂ * @drv: a cpuidle driver structure pointer
>> ÂÂ *
>> ÂÂ * This function is in charge of creating a cooling device per cpuidle
>> - * driver and register it to thermal framework.
>> + * driver and register it to the thermal framework.
>> ÂÂ *
>> ÂÂ * Return: zero on success, or negative value corresponding to the
>> ÂÂ * error detected in the underlying subsystems.
>> ÂÂ */
>> Â int cpuidle_cooling_register(struct cpuidle_driver *drv)
>> Â {
>> -ÂÂÂ return cpuidle_of_cooling_register(NULL, drv);
>> +ÂÂÂ struct device_node *cooling_node;
>> +ÂÂÂ struct device_node *cpu_node;
>> +ÂÂÂ int cpu, ret;
>> +
>> +ÂÂÂ for_each_cpu(cpu, drv->cpumask) {
>> +
>> +ÂÂÂÂÂÂÂ cpu_node = of_cpu_device_node_get(cpu);
>> +
>> +ÂÂÂÂÂÂÂ cooling_node = of_get_child_by_name(cpu_node, "idle-thermal");
>
> In DT binding this is 'thermal-idle'.
>
>> +
>> +ÂÂÂÂÂÂÂ of_node_put(cpu_node);
>> +
>> +ÂÂÂÂÂÂÂ if (!cooling_node)
>> +ÂÂÂÂÂÂÂÂÂÂÂ continue;
>
> This 'continue' is suspicious because it won't tell if there was no
> node "idle-thermal" but still the function will return 0. This was
> my case when I tried to enable it on Juno.
>
> Maybe a debug print that the node hasn't been found would be a
> good idea. Or somehow return different value than 0 taking into
> account that every CPU was skipped.
>
>> +
>> +ÂÂÂÂÂÂÂ ret = __cpuidle_cooling_register(cooling_node, drv);
>> +
>> +ÂÂÂÂÂÂÂ of_node_put(cooling_node);
>> +
>> +ÂÂÂÂÂÂÂ if (ret)
>> +ÂÂÂÂÂÂÂÂÂÂÂ return ret;
>> +
>> +ÂÂÂÂÂÂÂ cooling_node = NULL;
>> +ÂÂÂ }
>> +
>> +ÂÂÂ return 0;
>> Â }
>> diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h
>> index 65501d8f9778..4d7b4a303327 100644
>> --- a/include/linux/cpu_cooling.h
>> +++ b/include/linux/cpu_cooling.h
>> @@ -64,18 +64,11 @@ struct cpuidle_driver;
>> Â Â #ifdef CONFIG_CPU_IDLE_THERMAL
>> Â int cpuidle_cooling_register(struct cpuidle_driver *drv);
>> -int cpuidle_of_cooling_register(struct device_node *np,
>> -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct cpuidle_driver *drv);
>> Â #else /* CONFIG_CPU_IDLE_THERMAL */
>> Â static inline int cpuidle_cooling_register(struct cpuidle_driver *drv)
>> Â {
>> ÂÂÂÂÂ return 0;
>> Â }
>> -static inline int cpuidle_of_cooling_register(struct device_node *np,
>> -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct cpuidle_driver *drv)
>> -{
>> -ÂÂÂ return 0;
>> -}
>> Â #endif /* CONFIG_CPU_IDLE_THERMAL */
>> Â Â #endif /* __CPU_COOLING_H__ */
>>
>
> Apart from that, looks good to me.
>
> Regards,
> Lukasz


--
<http://www.linaro.org/> Linaro.org â Open source software for ARM SoCs

Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog