aboutsummaryrefslogtreecommitdiff
path: root/arch/ia64/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/process.c')
-rw-r--r--arch/ia64/kernel/process.c77
1 files changed, 44 insertions, 33 deletions
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 91293388dd2..ebb71f3d6d1 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 1998-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
+ * 04/11/17 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
*/
#define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */
#include <linux/config.h>
@@ -49,7 +50,7 @@
#include "sigframe.h"
void (*ia64_mark_idle)(int);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override);
@@ -172,7 +173,9 @@ do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall
ia64_do_signal(oldset, scr, in_syscall);
}
-static int pal_halt = 1;
+static int pal_halt = 1;
+static int can_do_pal_halt = 1;
+
static int __init nohalt_setup(char * str)
{
pal_halt = 0;
@@ -180,16 +183,20 @@ static int __init nohalt_setup(char * str)
}
__setup("nohalt", nohalt_setup);
+void
+update_pal_halt_status(int status)
+{
+ can_do_pal_halt = pal_halt && status;
+}
+
/*
* We use this if we don't have any better idle routine..
*/
void
default_idle (void)
{
- unsigned long pmu_active = ia64_getreg(_IA64_REG_PSR) & (IA64_PSR_PP | IA64_PSR_UP);
-
while (!need_resched())
- if (pal_halt && !pmu_active)
+ if (can_do_pal_halt)
safe_halt();
else
cpu_relax();
@@ -200,27 +207,20 @@ default_idle (void)
static inline void play_dead(void)
{
extern void ia64_cpu_local_tick (void);
+ unsigned int this_cpu = smp_processor_id();
+
/* Ack it */
__get_cpu_var(cpu_state) = CPU_DEAD;
- /* We shouldn't have to disable interrupts while dead, but
- * some interrupts just don't seem to go away, and this makes
- * it "work" for testing purposes. */
max_xtp();
local_irq_disable();
- /* Death loop */
- while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
- cpu_relax();
-
+ idle_task_exit();
+ ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]);
/*
- * Enable timer interrupts from now on
- * Not required if we put processor in SAL_BOOT_RENDEZ mode.
+ * The above is a point of no-return, the processor is
+ * expected to be in SAL loop now.
*/
- local_flush_tlb_all();
- cpu_set(smp_processor_id(), cpu_online_map);
- wmb();
- ia64_cpu_local_tick ();
- local_irq_enable();
+ BUG();
}
#else
static inline void play_dead(void)
@@ -229,20 +229,31 @@ static inline void play_dead(void)
}
#endif /* CONFIG_HOTPLUG_CPU */
-
void cpu_idle_wait(void)
{
- int cpu;
- cpumask_t map;
+ unsigned int cpu, this_cpu = get_cpu();
+ cpumask_t map;
+
+ set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ put_cpu();
- for_each_online_cpu(cpu)
- cpu_set(cpu, cpu_idle_map);
+ cpus_clear(map);
+ for_each_online_cpu(cpu) {
+ per_cpu(cpu_idle_state, cpu) = 1;
+ cpu_set(cpu, map);
+ }
- wmb();
- do {
- ssleep(1);
- cpus_and(map, cpu_idle_map, cpu_online_map);
- } while (!cpus_empty(map));
+ __get_cpu_var(cpu_idle_state) = 0;
+
+ wmb();
+ do {
+ ssleep(1);
+ for_each_online_cpu(cpu) {
+ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+ cpu_clear(cpu, map);
+ }
+ cpus_and(map, map, cpu_online_map);
+ } while (!cpus_empty(map));
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -250,7 +261,6 @@ void __attribute__((noreturn))
cpu_idle (void)
{
void (*mark_idle)(int) = ia64_mark_idle;
- int cpu = smp_processor_id();
/* endless idle loop with no priority at all */
while (1) {
@@ -261,12 +271,13 @@ cpu_idle (void)
while (!need_resched()) {
void (*idle)(void);
+ if (__get_cpu_var(cpu_idle_state))
+ __get_cpu_var(cpu_idle_state) = 0;
+
+ rmb();
if (mark_idle)
(*mark_idle)(1);
- if (cpu_isset(cpu, cpu_idle_map))
- cpu_clear(cpu, cpu_idle_map);
- rmb();
idle = pm_idle;
if (!idle)
idle = default_idle;