diff options
| author | Sam Ravnborg <sam@ravnborg.org> | 2013-04-11 15:38:50 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2013-04-13 15:36:27 -0400 |
| commit | 87fa05aeb3a5e8e21b1a5510eef6983650eff092 (patch) | |
| tree | 8d1cdcf61ffee47cf1ed7898ae6219f05096529c | |
| parent | 781b0e870c72be8a24c074073547e74e7b9bffd6 (diff) | |
sparc: Use generic idle loop
Add generic cpu_idle support
sparc32:
- replace call to cpu_idle() with cpu_startup_entry()
- add arch_cpu_idle()
sparc64:
- smp_callin() now include cpu_startup_entry() call so we can
skip calling cpu_idle from assembler
- add arch_cpu_idle() and arch_cpu_idle_dead()
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Reviewed-by: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Cc: torvalds@linux-foundation.org
Cc: rusty@rustcorp.com.au
Cc: paulmck@linux.vnet.ibm.com
Cc: peterz@infradead.org
Cc: magnus.damm@gmail.com
Acked-by: David Miller <davem@davemloft.net>
Link: http://lkml.kernel.org/r/20130411193850.GA2330@merkur.ravnborg.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
| -rw-r--r-- | arch/sparc/Kconfig | 1 | ||||
| -rw-r--r-- | arch/sparc/kernel/hvtramp.S | 3 | ||||
| -rw-r--r-- | arch/sparc/kernel/process_32.c | 21 | ||||
| -rw-r--r-- | arch/sparc/kernel/process_64.c | 49 | ||||
| -rw-r--r-- | arch/sparc/kernel/smp_32.c | 2 | ||||
| -rw-r--r-- | arch/sparc/kernel/smp_64.c | 2 | ||||
| -rw-r--r-- | arch/sparc/kernel/trampoline_64.S | 3 |
7 files changed, 24 insertions, 57 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 3d361f236308..ee5eacc5a649 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
| @@ -37,6 +37,7 @@ config SPARC | |||
| 37 | select GENERIC_SMP_IDLE_THREAD | 37 | select GENERIC_SMP_IDLE_THREAD |
| 38 | select GENERIC_CMOS_UPDATE | 38 | select GENERIC_CMOS_UPDATE |
| 39 | select GENERIC_CLOCKEVENTS | 39 | select GENERIC_CLOCKEVENTS |
| 40 | select GENERIC_IDLE_LOOP | ||
| 40 | select GENERIC_STRNCPY_FROM_USER | 41 | select GENERIC_STRNCPY_FROM_USER |
| 41 | select GENERIC_STRNLEN_USER | 42 | select GENERIC_STRNLEN_USER |
| 42 | select MODULES_USE_ELF_RELA | 43 | select MODULES_USE_ELF_RELA |
diff --git a/arch/sparc/kernel/hvtramp.S b/arch/sparc/kernel/hvtramp.S index 9365432904d6..605c960b2fa6 100644 --- a/arch/sparc/kernel/hvtramp.S +++ b/arch/sparc/kernel/hvtramp.S | |||
| @@ -128,8 +128,7 @@ hv_cpu_startup: | |||
| 128 | 128 | ||
| 129 | call smp_callin | 129 | call smp_callin |
| 130 | nop | 130 | nop |
| 131 | call cpu_idle | 131 | |
| 132 | mov 0, %o0 | ||
| 133 | call cpu_panic | 132 | call cpu_panic |
| 134 | nop | 133 | nop |
| 135 | 134 | ||
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 62eede13831a..c85241006e32 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c | |||
| @@ -64,23 +64,12 @@ extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *); | |||
| 64 | struct task_struct *last_task_used_math = NULL; | 64 | struct task_struct *last_task_used_math = NULL; |
| 65 | struct thread_info *current_set[NR_CPUS]; | 65 | struct thread_info *current_set[NR_CPUS]; |
| 66 | 66 | ||
| 67 | /* | 67 | /* Idle loop support. */ |
| 68 | * the idle loop on a Sparc... ;) | 68 | void arch_cpu_idle(void) |
| 69 | */ | ||
| 70 | void cpu_idle(void) | ||
| 71 | { | 69 | { |
| 72 | set_thread_flag(TIF_POLLING_NRFLAG); | 70 | if (sparc_idle) |
| 73 | 71 | (*sparc_idle)(); | |
| 74 | /* endless idle loop with no priority at all */ | 72 | local_irq_enable(); |
| 75 | for (;;) { | ||
| 76 | while (!need_resched()) { | ||
| 77 | if (sparc_idle) | ||
| 78 | (*sparc_idle)(); | ||
| 79 | else | ||
| 80 | cpu_relax(); | ||
| 81 | } | ||
| 82 | schedule_preempt_disabled(); | ||
| 83 | } | ||
| 84 | } | 73 | } |
| 85 | 74 | ||
| 86 | /* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */ | 75 | /* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */ |
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index cdb80b2adbe0..9fbf0d14a361 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c | |||
| @@ -52,20 +52,17 @@ | |||
| 52 | 52 | ||
| 53 | #include "kstack.h" | 53 | #include "kstack.h" |
| 54 | 54 | ||
| 55 | static void sparc64_yield(int cpu) | 55 | /* Idle loop support on sparc64. */ |
| 56 | void arch_cpu_idle(void) | ||
| 56 | { | 57 | { |
| 57 | if (tlb_type != hypervisor) { | 58 | if (tlb_type != hypervisor) { |
| 58 | touch_nmi_watchdog(); | 59 | touch_nmi_watchdog(); |
| 59 | return; | 60 | } else { |
| 60 | } | ||
| 61 | |||
| 62 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
| 63 | smp_mb__after_clear_bit(); | ||
| 64 | |||
| 65 | while (!need_resched() && !cpu_is_offline(cpu)) { | ||
| 66 | unsigned long pstate; | 61 | unsigned long pstate; |
| 67 | 62 | ||
| 68 | /* Disable interrupts. */ | 63 | /* The sun4v sleeping code requires that we have PSTATE.IE cleared over |
| 64 | * the cpu sleep hypervisor call. | ||
| 65 | */ | ||
| 69 | __asm__ __volatile__( | 66 | __asm__ __volatile__( |
| 70 | "rdpr %%pstate, %0\n\t" | 67 | "rdpr %%pstate, %0\n\t" |
| 71 | "andn %0, %1, %0\n\t" | 68 | "andn %0, %1, %0\n\t" |
| @@ -73,7 +70,7 @@ static void sparc64_yield(int cpu) | |||
| 73 | : "=&r" (pstate) | 70 | : "=&r" (pstate) |
| 74 | : "i" (PSTATE_IE)); | 71 | : "i" (PSTATE_IE)); |
| 75 | 72 | ||
| 76 | if (!need_resched() && !cpu_is_offline(cpu)) | 73 | if (!need_resched() && !cpu_is_offline(smp_processor_id())) |
| 77 | sun4v_cpu_yield(); | 74 | sun4v_cpu_yield(); |
| 78 | 75 | ||
| 79 | /* Re-enable interrupts. */ | 76 | /* Re-enable interrupts. */ |
| @@ -84,36 +81,16 @@ static void sparc64_yield(int cpu) | |||
| 84 | : "=&r" (pstate) | 81 | : "=&r" (pstate) |
| 85 | : "i" (PSTATE_IE)); | 82 | : "i" (PSTATE_IE)); |
| 86 | } | 83 | } |
| 87 | 84 | local_irq_enable(); | |
| 88 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
| 89 | } | 85 | } |
| 90 | 86 | ||
| 91 | /* The idle loop on sparc64. */ | ||
| 92 | void cpu_idle(void) | ||
| 93 | { | ||
| 94 | int cpu = smp_processor_id(); | ||
| 95 | |||
| 96 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
| 97 | |||
| 98 | while(1) { | ||
| 99 | tick_nohz_idle_enter(); | ||
| 100 | rcu_idle_enter(); | ||
| 101 | |||
| 102 | while (!need_resched() && !cpu_is_offline(cpu)) | ||
| 103 | sparc64_yield(cpu); | ||
| 104 | |||
| 105 | rcu_idle_exit(); | ||
| 106 | tick_nohz_idle_exit(); | ||
| 107 | |||
| 108 | #ifdef CONFIG_HOTPLUG_CPU | 87 | #ifdef CONFIG_HOTPLUG_CPU |
| 109 | if (cpu_is_offline(cpu)) { | 88 | void arch_cpu_idle_dead() |
| 110 | sched_preempt_enable_no_resched(); | 89 | { |
| 111 | cpu_play_dead(); | 90 | sched_preempt_enable_no_resched(); |
| 112 | } | 91 | cpu_play_dead(); |
| 113 | #endif | ||
| 114 | schedule_preempt_disabled(); | ||
| 115 | } | ||
| 116 | } | 92 | } |
| 93 | #endif | ||
| 117 | 94 | ||
| 118 | #ifdef CONFIG_COMPAT | 95 | #ifdef CONFIG_COMPAT |
| 119 | static void show_regwindow32(struct pt_regs *regs) | 96 | static void show_regwindow32(struct pt_regs *regs) |
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 9e7e6d718367..e3f2b81c23f1 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c | |||
| @@ -369,7 +369,7 @@ void __cpuinit sparc_start_secondary(void *arg) | |||
| 369 | local_irq_enable(); | 369 | local_irq_enable(); |
| 370 | 370 | ||
| 371 | wmb(); | 371 | wmb(); |
| 372 | cpu_idle(); | 372 | cpu_startup_entry(CPUHP_ONLINE); |
| 373 | 373 | ||
| 374 | /* We should never reach here! */ | 374 | /* We should never reach here! */ |
| 375 | BUG(); | 375 | BUG(); |
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 537eb66abd06..c025ffce7a40 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c | |||
| @@ -127,6 +127,8 @@ void __cpuinit smp_callin(void) | |||
| 127 | 127 | ||
| 128 | /* idle thread is expected to have preempt disabled */ | 128 | /* idle thread is expected to have preempt disabled */ |
| 129 | preempt_disable(); | 129 | preempt_disable(); |
| 130 | |||
| 131 | cpu_startup_entry(CPUHP_ONLINE); | ||
| 130 | } | 132 | } |
| 131 | 133 | ||
| 132 | void cpu_panic(void) | 134 | void cpu_panic(void) |
diff --git a/arch/sparc/kernel/trampoline_64.S b/arch/sparc/kernel/trampoline_64.S index da1b781b5e65..2e973a26fbda 100644 --- a/arch/sparc/kernel/trampoline_64.S +++ b/arch/sparc/kernel/trampoline_64.S | |||
| @@ -407,8 +407,7 @@ after_lock_tlb: | |||
| 407 | 407 | ||
| 408 | call smp_callin | 408 | call smp_callin |
| 409 | nop | 409 | nop |
| 410 | call cpu_idle | 410 | |
| 411 | mov 0, %o0 | ||
| 412 | call cpu_panic | 411 | call cpu_panic |
| 413 | nop | 412 | nop |
| 414 | 1: b,a,pt %xcc, 1b | 413 | 1: b,a,pt %xcc, 1b |
