Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / arch / sparc64 / kernel / process.c
index 8e3c6e4..ca7cdfd 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/kallsyms.h>
 #include <linux/mm.h>
+#include <linux/fs.h>
 #include <linux/smp.h>
 #include <linux/stddef.h>
 #include <linux/ptrace.h>
@@ -29,6 +30,7 @@
 #include <linux/compat.h>
 #include <linux/tick.h>
 #include <linux/init.h>
+#include <linux/cpu.h>
 
 #include <asm/oplib.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/unistd.h>
 #include <asm/hypervisor.h>
+#include <asm/sstate.h>
 
 /* #define VERBOSE_SHOWREGS */
 
-static void sparc64_yield(void)
+static void sparc64_yield(int cpu)
 {
        if (tlb_type != hypervisor)
                return;
@@ -56,7 +59,7 @@ static void sparc64_yield(void)
        clear_thread_flag(TIF_POLLING_NRFLAG);
        smp_mb__after_clear_bit();
 
-       while (!need_resched()) {
+       while (!need_resched() && !cpu_is_offline(cpu)) {
                unsigned long pstate;
 
                /* Disable interrupts. */
@@ -67,7 +70,7 @@ static void sparc64_yield(void)
                        : "=&r" (pstate)
                        : "i" (PSTATE_IE));
 
-               if (!need_resched())
+               if (!need_resched() && !cpu_is_offline(cpu))
                        sun4v_cpu_yield();
 
                /* Re-enable interrupts. */
@@ -85,15 +88,25 @@ static void sparc64_yield(void)
 /* The idle loop on sparc64. */
 void cpu_idle(void)
 {
+       int cpu = smp_processor_id();
+
        set_thread_flag(TIF_POLLING_NRFLAG);
 
        while(1) {
                tick_nohz_stop_sched_tick();
-               while (!need_resched())
-                       sparc64_yield();
+
+               while (!need_resched() && !cpu_is_offline(cpu))
+                       sparc64_yield(cpu);
+
                tick_nohz_restart_sched_tick();
 
                preempt_enable_no_resched();
+
+#ifdef CONFIG_HOTPLUG_CPU
+               if (cpu_is_offline(cpu))
+                       cpu_play_dead();
+#endif
+
                schedule();
                preempt_disable();
        }
@@ -106,7 +119,8 @@ extern void (*prom_keyboard)(void);
 
 void machine_halt(void)
 {
-       if (!serial_console && prom_palette)
+       sstate_halt();
+       if (prom_palette)
                prom_palette (1);
        if (prom_keyboard)
                prom_keyboard();
@@ -116,7 +130,8 @@ void machine_halt(void)
 
 void machine_alt_power_off(void)
 {
-       if (!serial_console && prom_palette)
+       sstate_poweroff();
+       if (prom_palette)
                prom_palette(1);
        if (prom_keyboard)
                prom_keyboard();
@@ -128,9 +143,10 @@ void machine_restart(char * cmd)
 {
        char *p;
        
+       sstate_reboot();
        p = strchr (reboot_command, '\n');
        if (p) *p = 0;
-       if (!serial_console && prom_palette)
+       if (prom_palette)
                prom_palette (1);
        if (prom_keyboard)
                prom_keyboard();
@@ -677,7 +693,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
  * NOTE! Only a kernel-only process(ie the swapper or direct descendants
  * who haven't done an "execve()") should use this: it will work within
  * a system call from a "real" process, but the process memory space will
- * not be free'd until both the parent and the child have exited.
+ * not be freed until both the parent and the child have exited.
  */
 pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {