aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2013-04-11 15:38:50 -0400
committerThomas Gleixner <tglx@linutronix.de>2013-04-13 15:36:27 -0400
commit87fa05aeb3a5e8e21b1a5510eef6983650eff092 (patch)
tree8d1cdcf61ffee47cf1ed7898ae6219f05096529c /arch/sparc
parent781b0e870c72be8a24c074073547e74e7b9bffd6 (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>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kconfig1
-rw-r--r--arch/sparc/kernel/hvtramp.S3
-rw-r--r--arch/sparc/kernel/process_32.c21
-rw-r--r--arch/sparc/kernel/process_64.c49
-rw-r--r--arch/sparc/kernel/smp_32.c2
-rw-r--r--arch/sparc/kernel/smp_64.c2
-rw-r--r--arch/sparc/kernel/trampoline_64.S3
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 *);
64struct task_struct *last_task_used_math = NULL; 64struct task_struct *last_task_used_math = NULL;
65struct thread_info *current_set[NR_CPUS]; 65struct thread_info *current_set[NR_CPUS];
66 66
67/* 67/* Idle loop support. */
68 * the idle loop on a Sparc... ;) 68void arch_cpu_idle(void)
69 */
70void 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
55static void sparc64_yield(int cpu) 55/* Idle loop support on sparc64. */
56void 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. */
92void 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)) { 88void 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
119static void show_regwindow32(struct pt_regs *regs) 96static 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
132void cpu_panic(void) 134void 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
4141: b,a,pt %xcc, 1b 4131: b,a,pt %xcc, 1b