cpuidle, tegra: Push RCU-idle into driver
Doing RCU-idle outside the driver, only to then temporarily enable it again, at least twice, before going idle is suboptimal. Notably once implicitly through the cpu_pm_*() calls and once explicitly doing RCU_NONIDLE(). Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Tested-by: Tony Lindgren <tony@atomide.com> Tested-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Frederic Weisbecker <frederic@kernel.org> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Link: https://lore.kernel.org/r/20230112195539.699546331@infradead.org
This commit is contained in:
parent
8e9ab9e8da
commit
5fca0d9f5d
@ -180,9 +180,11 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
|
||||
}
|
||||
|
||||
local_fiq_disable();
|
||||
RCU_NONIDLE(tegra_pm_set_cpu_in_lp2());
|
||||
tegra_pm_set_cpu_in_lp2();
|
||||
cpu_pm_enter();
|
||||
|
||||
ct_idle_enter();
|
||||
|
||||
switch (index) {
|
||||
case TEGRA_C7:
|
||||
err = tegra_cpuidle_c7_enter();
|
||||
@ -197,8 +199,10 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
|
||||
break;
|
||||
}
|
||||
|
||||
ct_idle_exit();
|
||||
|
||||
cpu_pm_exit();
|
||||
RCU_NONIDLE(tegra_pm_clear_cpu_in_lp2());
|
||||
tegra_pm_clear_cpu_in_lp2();
|
||||
local_fiq_enable();
|
||||
|
||||
return err ?: index;
|
||||
@ -226,6 +230,7 @@ static int tegra_cpuidle_enter(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv,
|
||||
int index)
|
||||
{
|
||||
bool do_rcu = drv->states[index].flags & CPUIDLE_FLAG_RCU_IDLE;
|
||||
unsigned int cpu = cpu_logical_map(dev->cpu);
|
||||
int ret;
|
||||
|
||||
@ -233,9 +238,13 @@ static int tegra_cpuidle_enter(struct cpuidle_device *dev,
|
||||
if (dev->states_usage[index].disable)
|
||||
return -1;
|
||||
|
||||
if (index == TEGRA_C1)
|
||||
if (index == TEGRA_C1) {
|
||||
if (do_rcu)
|
||||
ct_idle_enter();
|
||||
ret = arm_cpuidle_simple_enter(dev, drv, index);
|
||||
else
|
||||
if (do_rcu)
|
||||
ct_idle_exit();
|
||||
} else
|
||||
ret = tegra_cpuidle_state_enter(dev, index, cpu);
|
||||
|
||||
if (ret < 0) {
|
||||
@ -285,7 +294,8 @@ static struct cpuidle_driver tegra_idle_driver = {
|
||||
.exit_latency = 2000,
|
||||
.target_residency = 2200,
|
||||
.power_usage = 100,
|
||||
.flags = CPUIDLE_FLAG_TIMER_STOP,
|
||||
.flags = CPUIDLE_FLAG_TIMER_STOP |
|
||||
CPUIDLE_FLAG_RCU_IDLE,
|
||||
.name = "C7",
|
||||
.desc = "CPU core powered off",
|
||||
},
|
||||
@ -295,6 +305,7 @@ static struct cpuidle_driver tegra_idle_driver = {
|
||||
.target_residency = 10000,
|
||||
.power_usage = 0,
|
||||
.flags = CPUIDLE_FLAG_TIMER_STOP |
|
||||
CPUIDLE_FLAG_RCU_IDLE |
|
||||
CPUIDLE_FLAG_COUPLED,
|
||||
.name = "CC6",
|
||||
.desc = "CPU cluster powered off",
|
||||
|
Loading…
x
Reference in New Issue
Block a user