diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2025-11-07 20:07:28 +0100 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2025-11-12 21:00:00 +0100 |
| commit | 76934e495cdc31942b53b513cee4290750578a9a (patch) | |
| tree | 6ecc37127840a6f349b698aeb4aec275cf70c987 | |
| parent | 07d815701274d156ad8c7c088a52e01642156fb8 (diff) | |
cpuidle: Add sanity check for exit latency and target residency
Make __cpuidle_driver_init() fail if the exit latency of one of the
driver's idle states is less than its target residency which would
break cpuidle assumptions.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Reviewed-by: Christian Loehle <christian.loehle@arm.com>
[ rjw: Changelog fix ]
Link: https://patch.msgid.link/12779486.O9o76ZdvQC@rafael.j.wysocki
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
| -rw-r--r-- | drivers/cpuidle/driver.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 9bbfa594c442..1c295a93d582 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -152,7 +152,7 @@ static void cpuidle_setup_broadcast_timer(void *arg) * __cpuidle_driver_init - initialize the driver's internal data * @drv: a valid pointer to a struct cpuidle_driver */ -static void __cpuidle_driver_init(struct cpuidle_driver *drv) +static int __cpuidle_driver_init(struct cpuidle_driver *drv) { int i; @@ -193,7 +193,17 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) s->exit_latency_ns = 0; else s->exit_latency = div_u64(s->exit_latency_ns, NSEC_PER_USEC); + + /* + * Ensure that the exit latency of a CPU idle state does not + * exceed its target residency which is assumed in cpuidle in + * multiple places. + */ + if (s->exit_latency_ns > s->target_residency_ns) + return -EINVAL; } + + return 0; } /** @@ -223,7 +233,9 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) if (cpuidle_disabled()) return -ENODEV; - __cpuidle_driver_init(drv); + ret = __cpuidle_driver_init(drv); + if (ret) + return ret; ret = __cpuidle_set_driver(drv); if (ret) |
