On Monday 21 Sep 2020 at 13:20:04 (+0100), Lukasz Luba wrote:
Devfreq cooling needs to now the correct status of the device in order
to operate. Do not rely on Devfreq last_status which might be a stale data
and get more up-to-date values of the load.
Devfreq framework can change the device status in the background. To
mitigate this situation make a copy of the status structure and use it
for internal calculations.
In addition this patch adds normalization function, which also makes sure
that whatever data comes from the device, it is in a sane range.
Signed-off-by: Lukasz Luba <lukasz.luba@xxxxxxx>
---
drivers/thermal/devfreq_cooling.c | 52 +++++++++++++++++++++++++------
1 file changed, 43 insertions(+), 9 deletions(-)
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c
index 7063ccb7b86d..cf045bd4d16b 100644
--- a/drivers/thermal/devfreq_cooling.c
+++ b/drivers/thermal/devfreq_cooling.c
@@ -227,6 +227,24 @@ static inline unsigned long get_total_power(struct devfreq_cooling_device *dfc,
voltage);
}
+static void _normalize_load(struct devfreq_dev_status *status)
Is there a reason for the leading "_" ?
AFAIK, "__name()" is meant to suggest a "worker" function for another
"name()" function, but that would not apply here.
+{
+ /* Make some space if needed */
+ if (status->busy_time > 0xffff) {
+ status->busy_time >>= 10;
+ status->total_time >>= 10;
+ }
How about removing the above code and adding here:
status->busy_time = status->busy_time ? : 1;
+
+ if (status->busy_time > status->total_time)
This check would then cover the possibility that total_time is 0.
+ status->busy_time = status->total_time;
But a reversal is needed here:
status->total_time = status->busy_time;
+
+ status->busy_time *= 100;
+ status->busy_time /= status->total_time ? : 1;
+
+ /* Avoid division by 0 */
+ status->busy_time = status->busy_time ? : 1;
+ status->total_time = 100;
Then all of this code can be replaced by:
status->busy_time = (unsigned long)div64_u64((u64)status->busy_time << 10,
status->total_time);
status->total_time = 1 << 10;
This way you gain some resolution to busy_time and the divisions in the
callers would just become shifts by 10.
Hope it helps,
Ionela.