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 | {return 0;} | 256 | {return 0;} |
| 257 | #endif | 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 | int __ret = 0; \ | 264 | int __ret = 0; \ |
| 262 | \ | 265 | \ |
| @@ -268,7 +271,7 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) · 5 unmodified lines | |||
| 268 | if (!is_retention) \ | 271 | if (!is_retention) \ |
| 269 | __ret = cpu_pm_enter(); \ | 272 | __ret = cpu_pm_enter(); \ |
| 270 | if (!__ret) { \ | 273 | if (!__ret) { \ |
| 271 | __ret = low_level_idle_enter(idx); \ | 274 | __ret = low_level_idle_enter(state); \ |
| 272 | if (!is_retention) \ | 275 | if (!is_retention) \ |
| 273 | cpu_pm_exit(); \ | 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 | #define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \ | 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 | #define CPU_PM_CPU_IDLE_ENTER_RETENTION(low_level_idle_enter, idx) \ | 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 | #endif /* _LINUX_CPUIDLE_H */ | 294 | #endif /* _LINUX_CPUIDLE_H */ |
| @@ -15,8 +15,8 @@ · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | bool psci_tos_resident_on(int cpu); | 16 | bool psci_tos_resident_on(int cpu); |
| 17 | 17 | ||
| 18 | int psci_cpu_init_idle(unsigned int cpu); | 18 | int psci_cpu_suspend_enter(u32 state); |
| 19 | int psci_cpu_suspend_enter(unsigned long index); | 19 | bool psci_power_state_is_valid(u32 state); |
| 20 | 20 | ||
| 21 | enum psci_conduit { | 21 | enum psci_conduit { |
| 22 | PSCI_CONDUIT_NONE, | 22 | PSCI_CONDUIT_NONE, |