Current PSCI code handles idle state entry through the psci_cpu_suspend_enter() API, that takes an idle state index as a parameter and convert the index into a previously initialized power_state parameter before calling the PSCI.CPU_SUSPEND() with it. This is unwieldly, since it forces the PSCI firmware layer to keep track of power_state parameter for every idle state so that the index->power_state conversion can be made in the PSCI firmware layer instead of the CPUidle driver implementations. Move the power_state handling out of drivers/firmware/psci into the respective ACPI/DT PSCI CPUidle backends and convert the psci_cpu_suspend_enter() API to get the power_state parameter as input, which makes it closer to its firmware interface PSCI.CPU_SUSPEND() API. A notable side effect is that the PSCI ACPI/DT CPUidle backends now can directly handle (and if needed update) power_state parameters before handing them over to the PSCI firmware interface to trigger PSCI.CPU_SUSPEND() calls.
Showing the changes to include/linux (2 of 5 files). Show all
Unified · Split
| @@ -256,7 +256,10 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) · 255 unmodified lines | ||
| 256 | 256 | {return 0;} |
| 257 | 257 | #endif |
| 258 | 258 | |
| 259 | −#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, is_retention) \ | |
| 259 | +#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, \ | |
| 260 | + idx, \ | |
| 261 | + state, \ | |
| 262 | + is_retention) \ | |
| 260 | 263 | ({ \ |
| 261 | 264 | int __ret = 0; \ |
| 262 | 265 | \ |
| @@ -268,7 +271,7 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) · 5 unmodified lines | ||
| 268 | 271 | if (!is_retention) \ |
| 269 | 272 | __ret = cpu_pm_enter(); \ |
| 270 | 273 | if (!__ret) { \ |
| 271 | − __ret = low_level_idle_enter(idx); \ | |
| 274 | + __ret = low_level_idle_enter(state); \ | |
| 272 | 275 | if (!is_retention) \ |
| 273 | 276 | cpu_pm_exit(); \ |
| 274 | 277 | } \ |
| @@ -277,9 +280,15 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) · 2 unmodified lines | ||
| 277 | 280 | }) |
| 278 | 281 | |
| 279 | 282 | #define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \ |
| 280 | − __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 0) | |
| 283 | + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 0) | |
| 281 | 284 | |
| 282 | 285 | #define CPU_PM_CPU_IDLE_ENTER_RETENTION(low_level_idle_enter, idx) \ |
| 283 | − __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 1) | |
| 286 | + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 1) | |
| 287 | + | |
| 288 | +#define CPU_PM_CPU_IDLE_ENTER_PARAM(low_level_idle_enter, idx, state) \ | |
| 289 | + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 0) | |
| 290 | + | |
| 291 | +#define CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(low_level_idle_enter, idx, state) \ | |
| 292 | + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 1) | |
| 284 | 293 | |
| 285 | 294 | #endif /* _LINUX_CPUIDLE_H */ |
| @@ -15,8 +15,8 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | bool psci_tos_resident_on(int cpu); |
| 17 | 17 | |
| 18 | −int psci_cpu_init_idle(unsigned int cpu); | |
| 19 | −int psci_cpu_suspend_enter(unsigned long index); | |
| 18 | +int psci_cpu_suspend_enter(u32 state); | |
| 19 | +bool psci_power_state_is_valid(u32 state); | |
| 20 | 20 | |
| 21 | 21 | enum psci_conduit { |
| 22 | 22 | PSCI_CONDUIT_NONE, |