diff mbox series

PM: EM: Fix potential division-by-zero error in em_compute_costs()

Message ID tencent_8478BF8F2549630842D323E7394CB6F49D08@qq.com
State New
Headers show
Series PM: EM: Fix potential division-by-zero error in em_compute_costs() | expand

Commit Message

Yaxiong Tian April 10, 2025, 5:33 a.m. UTC
From: Yaxiong Tian <tianyaxiong@kylinos.cn>

When the device is of a non-CPU type, table[i].performance won't be
initialized in the previous em_init_performance(), resulting in division
 by zero when calculating costs in em_compute_costs().

Considering that the performance field in struct em_perf_state is defined
as "CPU performance (capacity) at a given frequency", the original
calculation method should be maintained when the device is of a non-CPU
type.

Fixes: <1b600da51073> ("PM: EM: Optimize em_cpu_energy() and remove division")

Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
---
 kernel/power/energy_model.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index d9b7e2b38c7a..bbd95573d91e 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -231,9 +231,11 @@  static int em_compute_costs(struct device *dev, struct em_perf_state *table,
 			    unsigned long flags)
 {
 	unsigned long prev_cost = ULONG_MAX;
+	u64 fmax;
 	int i, ret;
 
 	/* Compute the cost of each performance state. */
+	fmax = (u64) table[nr_states - 1].frequency;
 	for (i = nr_states - 1; i >= 0; i--) {
 		unsigned long power_res, cost;
 
@@ -245,9 +247,15 @@  static int em_compute_costs(struct device *dev, struct em_perf_state *table,
 				return -EINVAL;
 			}
 		} else {
-			/* increase resolution of 'cost' precision */
-			power_res = table[i].power * 10;
-			cost = power_res / table[i].performance;
+			if (_is_cpu_device(dev)) {
+				/* increase resolution of 'cost' precision */
+				power_res = table[i].power * 10;
+				cost = power_res / table[i].performance;
+			} else {
+				power_res = table[i].power;
+				cost = div64_u64(fmax * power_res, table[i].frequency);
+
+			}
 		}
 
 		table[i].cost = cost;