diff options
| author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-06-22 17:34:55 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-06-22 17:34:55 -0400 |
| commit | 9ccdac3662dbf3c75e8f8851a214bdf7d365a4bd (patch) | |
| tree | 0a6c340482add9fd5ac629d2441b0d0027c82760 | |
| parent | 915166d96f5cab90b6f39f37da1139e5eab516b2 (diff) | |
[ARM] idle: clean up pm_idle calling, obey hlt_counter
pm_idle is used by infrastructure (eg, cpuidle) which expects architectures
to call it in a certain way. Arrange for ARM to follow x86's lead on this
and call pm_idle() with interrupts already disabled. However, we expect
pm_idle() to enable interrupts before it returns.
Also, OMAP wants to be able to disable hlt-ing, so allow hlt_counter to
prevent all calls to pm_idle.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | arch/arm/kernel/process.c | 58 |
1 files changed, 32 insertions, 26 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 56820cce91a4..39196dff478c 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
| @@ -114,9 +114,6 @@ void arm_machine_restart(char mode, const char *cmd) | |||
| 114 | /* | 114 | /* |
| 115 | * Function pointers to optional machine specific functions | 115 | * Function pointers to optional machine specific functions |
| 116 | */ | 116 | */ |
| 117 | void (*pm_idle)(void); | ||
| 118 | EXPORT_SYMBOL(pm_idle); | ||
| 119 | |||
| 120 | void (*pm_power_off)(void); | 117 | void (*pm_power_off)(void); |
| 121 | EXPORT_SYMBOL(pm_power_off); | 118 | EXPORT_SYMBOL(pm_power_off); |
| 122 | 119 | ||
| @@ -130,20 +127,19 @@ EXPORT_SYMBOL_GPL(arm_pm_restart); | |||
| 130 | */ | 127 | */ |
| 131 | static void default_idle(void) | 128 | static void default_idle(void) |
| 132 | { | 129 | { |
| 133 | if (hlt_counter) | 130 | if (!need_resched()) |
| 134 | cpu_relax(); | 131 | arch_idle(); |
| 135 | else { | 132 | local_irq_enable(); |
| 136 | local_irq_disable(); | ||
| 137 | if (!need_resched()) | ||
| 138 | arch_idle(); | ||
| 139 | local_irq_enable(); | ||
| 140 | } | ||
| 141 | } | 133 | } |
| 142 | 134 | ||
| 135 | void (*pm_idle)(void) = default_idle; | ||
| 136 | EXPORT_SYMBOL(pm_idle); | ||
| 137 | |||
| 143 | /* | 138 | /* |
| 144 | * The idle thread. We try to conserve power, while trying to keep | 139 | * The idle thread, has rather strange semantics for calling pm_idle, |
| 145 | * overall latency low. The architecture specific idle is passed | 140 | * but this is what x86 does and we need to do the same, so that |
| 146 | * a value to indicate the level of "idleness" of the system. | 141 | * things like cpuidle get called in the same way. The only difference |
| 142 | * is that we always respect 'hlt_counter' to prevent low power idle. | ||
| 147 | */ | 143 | */ |
| 148 | void cpu_idle(void) | 144 | void cpu_idle(void) |
| 149 | { | 145 | { |
| @@ -151,21 +147,31 @@ void cpu_idle(void) | |||
| 151 | 147 | ||
| 152 | /* endless idle loop with no priority at all */ | 148 | /* endless idle loop with no priority at all */ |
| 153 | while (1) { | 149 | while (1) { |
| 154 | void (*idle)(void) = pm_idle; | 150 | tick_nohz_stop_sched_tick(1); |
| 155 | 151 | leds_event(led_idle_start); | |
| 152 | while (!need_resched()) { | ||
| 156 | #ifdef CONFIG_HOTPLUG_CPU | 153 | #ifdef CONFIG_HOTPLUG_CPU |
| 157 | if (cpu_is_offline(smp_processor_id())) { | 154 | if (cpu_is_offline(smp_processor_id())) |
| 158 | leds_event(led_idle_start); | 155 | cpu_die(); |
| 159 | cpu_die(); | ||
| 160 | } | ||
| 161 | #endif | 156 | #endif |
| 162 | 157 | ||
| 163 | if (!idle) | 158 | local_irq_disable(); |
| 164 | idle = default_idle; | 159 | if (hlt_counter) { |
| 165 | leds_event(led_idle_start); | 160 | local_irq_enable(); |
| 166 | tick_nohz_stop_sched_tick(1); | 161 | cpu_relax(); |
| 167 | while (!need_resched()) | 162 | } else { |
| 168 | idle(); | 163 | stop_critical_timings(); |
| 164 | pm_idle(); | ||
| 165 | start_critical_timings(); | ||
| 166 | /* | ||
| 167 | * This will eventually be removed - pm_idle | ||
| 168 | * functions should always return with IRQs | ||
| 169 | * enabled. | ||
| 170 | */ | ||
| 171 | WARN_ON(irqs_disabled()); | ||
| 172 | local_irq_enable(); | ||
| 173 | } | ||
| 174 | } | ||
| 169 | leds_event(led_idle_end); | 175 | leds_event(led_idle_end); |
| 170 | tick_nohz_restart_sched_tick(); | 176 | tick_nohz_restart_sched_tick(); |
| 171 | preempt_enable_no_resched(); | 177 | preempt_enable_no_resched(); |
