diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2009-09-08 20:55:21 -0400 |
|---|---|---|
| committer | Dan Williams <dan.j.williams@intel.com> | 2009-09-08 20:55:21 -0400 |
| commit | bbb20089a3275a19e475dbc21320c3742e3ca423 (patch) | |
| tree | 216fdc1cbef450ca688135c5b8969169482d9a48 /arch/arm/kernel/process.c | |
| parent | 3e48e656903e9fd8bc805c6a2c4264d7808d315b (diff) | |
| parent | 657a77fa7284d8ae28dfa48f1dc5d919bf5b2843 (diff) | |
Merge branch 'dmaengine' into async-tx-next
Conflicts:
crypto/async_tx/async_xor.c
drivers/dma/ioat/dma_v2.h
drivers/dma/ioat/pci.c
drivers/md/raid5.c
Diffstat (limited to 'arch/arm/kernel/process.c')
| -rw-r--r-- | arch/arm/kernel/process.c | 79 |
1 files changed, 51 insertions, 28 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index c3265a2e7cd4..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(); |
| @@ -352,6 +358,23 @@ asm( ".section .text\n" | |||
| 352 | " .size kernel_thread_helper, . - kernel_thread_helper\n" | 358 | " .size kernel_thread_helper, . - kernel_thread_helper\n" |
| 353 | " .previous"); | 359 | " .previous"); |
| 354 | 360 | ||
| 361 | #ifdef CONFIG_ARM_UNWIND | ||
| 362 | extern void kernel_thread_exit(long code); | ||
| 363 | asm( ".section .text\n" | ||
| 364 | " .align\n" | ||
| 365 | " .type kernel_thread_exit, #function\n" | ||
| 366 | "kernel_thread_exit:\n" | ||
| 367 | " .fnstart\n" | ||
| 368 | " .cantunwind\n" | ||
| 369 | " bl do_exit\n" | ||
| 370 | " nop\n" | ||
| 371 | " .fnend\n" | ||
| 372 | " .size kernel_thread_exit, . - kernel_thread_exit\n" | ||
| 373 | " .previous"); | ||
| 374 | #else | ||
| 375 | #define kernel_thread_exit do_exit | ||
| 376 | #endif | ||
| 377 | |||
| 355 | /* | 378 | /* |
| 356 | * Create a kernel thread. | 379 | * Create a kernel thread. |
| 357 | */ | 380 | */ |
| @@ -363,9 +386,9 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |||
| 363 | 386 | ||
| 364 | regs.ARM_r1 = (unsigned long)arg; | 387 | regs.ARM_r1 = (unsigned long)arg; |
| 365 | regs.ARM_r2 = (unsigned long)fn; | 388 | regs.ARM_r2 = (unsigned long)fn; |
| 366 | regs.ARM_r3 = (unsigned long)do_exit; | 389 | regs.ARM_r3 = (unsigned long)kernel_thread_exit; |
| 367 | regs.ARM_pc = (unsigned long)kernel_thread_helper; | 390 | regs.ARM_pc = (unsigned long)kernel_thread_helper; |
| 368 | regs.ARM_cpsr = SVC_MODE; | 391 | regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE; |
| 369 | 392 | ||
| 370 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | 393 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); |
| 371 | } | 394 | } |
