diff options
Diffstat (limited to 'arch/sparc64/kernel/process.c')
| -rw-r--r-- | arch/sparc64/kernel/process.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index f5f97e2c669c..93557507ec9f 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/compat.h> | 29 | #include <linux/compat.h> |
| 30 | #include <linux/tick.h> | 30 | #include <linux/tick.h> |
| 31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
| 32 | #include <linux/cpu.h> | ||
| 32 | 33 | ||
| 33 | #include <asm/oplib.h> | 34 | #include <asm/oplib.h> |
| 34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
| @@ -49,7 +50,7 @@ | |||
| 49 | 50 | ||
| 50 | /* #define VERBOSE_SHOWREGS */ | 51 | /* #define VERBOSE_SHOWREGS */ |
| 51 | 52 | ||
| 52 | static void sparc64_yield(void) | 53 | static void sparc64_yield(int cpu) |
| 53 | { | 54 | { |
| 54 | if (tlb_type != hypervisor) | 55 | if (tlb_type != hypervisor) |
| 55 | return; | 56 | return; |
| @@ -57,7 +58,7 @@ static void sparc64_yield(void) | |||
| 57 | clear_thread_flag(TIF_POLLING_NRFLAG); | 58 | clear_thread_flag(TIF_POLLING_NRFLAG); |
| 58 | smp_mb__after_clear_bit(); | 59 | smp_mb__after_clear_bit(); |
| 59 | 60 | ||
| 60 | while (!need_resched()) { | 61 | while (!need_resched() && !cpu_is_offline(cpu)) { |
| 61 | unsigned long pstate; | 62 | unsigned long pstate; |
| 62 | 63 | ||
| 63 | /* Disable interrupts. */ | 64 | /* Disable interrupts. */ |
| @@ -68,7 +69,7 @@ static void sparc64_yield(void) | |||
| 68 | : "=&r" (pstate) | 69 | : "=&r" (pstate) |
| 69 | : "i" (PSTATE_IE)); | 70 | : "i" (PSTATE_IE)); |
| 70 | 71 | ||
| 71 | if (!need_resched()) | 72 | if (!need_resched() && !cpu_is_offline(cpu)) |
| 72 | sun4v_cpu_yield(); | 73 | sun4v_cpu_yield(); |
| 73 | 74 | ||
| 74 | /* Re-enable interrupts. */ | 75 | /* Re-enable interrupts. */ |
| @@ -86,15 +87,25 @@ static void sparc64_yield(void) | |||
| 86 | /* The idle loop on sparc64. */ | 87 | /* The idle loop on sparc64. */ |
| 87 | void cpu_idle(void) | 88 | void cpu_idle(void) |
| 88 | { | 89 | { |
| 90 | int cpu = smp_processor_id(); | ||
| 91 | |||
| 89 | set_thread_flag(TIF_POLLING_NRFLAG); | 92 | set_thread_flag(TIF_POLLING_NRFLAG); |
| 90 | 93 | ||
| 91 | while(1) { | 94 | while(1) { |
| 92 | tick_nohz_stop_sched_tick(); | 95 | tick_nohz_stop_sched_tick(); |
| 93 | while (!need_resched()) | 96 | |
| 94 | sparc64_yield(); | 97 | while (!need_resched() && !cpu_is_offline(cpu)) |
| 98 | sparc64_yield(cpu); | ||
| 99 | |||
| 95 | tick_nohz_restart_sched_tick(); | 100 | tick_nohz_restart_sched_tick(); |
| 96 | 101 | ||
| 97 | preempt_enable_no_resched(); | 102 | preempt_enable_no_resched(); |
| 103 | |||
| 104 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 105 | if (cpu_is_offline(cpu)) | ||
| 106 | cpu_play_dead(); | ||
| 107 | #endif | ||
| 108 | |||
| 98 | schedule(); | 109 | schedule(); |
| 99 | preempt_disable(); | 110 | preempt_disable(); |
| 100 | } | 111 | } |
