aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/pseries/hotplug-cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/hotplug-cpu.c')
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c71
1 files changed, 39 insertions, 32 deletions
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index fd50ccd4bac..20d62975856 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -19,26 +19,23 @@
*/
#include <linux/kernel.h>
+#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/sched.h> /* for idle_task_exit */
#include <linux/cpu.h>
-#include <asm/system.h>
+#include <linux/of.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/firmware.h>
#include <asm/machdep.h>
#include <asm/vdso_datapage.h>
-#include <asm/pSeries_reconfig.h>
-#include "xics.h"
-#include "plpar_wrappers.h"
+#include <asm/xics.h>
+#include <asm/plpar_wrappers.h>
+
#include "offline_states.h"
/* This version can't take the spinlock, because it never returns */
-static struct rtas_args rtas_stop_self_args = {
- .token = RTAS_UNKNOWN_SERVICE,
- .nargs = 0,
- .nret = 1,
- .rets = &rtas_stop_self_args.args[0],
-};
+static int rtas_stop_self_token = RTAS_UNKNOWN_SERVICE;
static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) =
CPU_STATE_OFFLINE;
@@ -91,15 +88,21 @@ void set_default_offline_state(int cpu)
static void rtas_stop_self(void)
{
- struct rtas_args *args = &rtas_stop_self_args;
+ static struct rtas_args args = {
+ .nargs = 0,
+ .nret = 1,
+ .rets = &args.args[0],
+ };
+
+ args.token = cpu_to_be32(rtas_stop_self_token);
local_irq_disable();
- BUG_ON(args->token == RTAS_UNKNOWN_SERVICE);
+ BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
printk("cpu %u (hwid %u) Ready to die...\n",
smp_processor_id(), hard_smp_processor_id());
- enter_rtas(__pa(args));
+ enter_rtas(__pa(&args));
panic("Alas, I survived.\n");
}
@@ -122,20 +125,28 @@ static void pseries_mach_cpu_die(void)
cede_latency_hint = 2;
get_lppaca()->idle = 1;
- if (!get_lppaca()->shared_proc)
+ if (!lppaca_shared_proc(get_lppaca()))
get_lppaca()->donate_dedicated_cpu = 1;
while (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
+ while (!prep_irq_for_idle()) {
+ local_irq_enable();
+ local_irq_disable();
+ }
+
extended_cede_processor(cede_latency_hint);
}
- if (!get_lppaca()->shared_proc)
+ local_irq_disable();
+
+ if (!lppaca_shared_proc(get_lppaca()))
get_lppaca()->donate_dedicated_cpu = 0;
get_lppaca()->idle = 0;
if (get_preferred_offline_state(cpu) == CPU_STATE_ONLINE) {
- unregister_slb_shadow(hwcpu, __pa(get_slb_shadow()));
+ unregister_slb_shadow(hwcpu);
+ hard_irq_disable();
/*
* Call to start_secondary_resume() will not return.
* Kernel stack will be reset and start_secondary()
@@ -149,7 +160,7 @@ static void pseries_mach_cpu_die(void)
WARN_ON(get_preferred_offline_state(cpu) != CPU_STATE_OFFLINE);
set_cpu_current_state(cpu, CPU_STATE_OFFLINE);
- unregister_slb_shadow(hwcpu, __pa(get_slb_shadow()));
+ unregister_slb_shadow(hwcpu);
rtas_stop_self();
/* Should never get here... */
@@ -216,7 +227,7 @@ static void pseries_cpu_die(unsigned int cpu)
cpu, pcpu, cpu_status);
}
- /* Isolation and deallocation are definatly done by
+ /* Isolation and deallocation are definitely done by
* drslot_chrp_cpu. If they were not they would be
* done here. Change isolate state to Isolate and
* change allocation-state to Unusable.
@@ -280,7 +291,7 @@ static int pseries_add_processor(struct device_node *np)
}
for_each_cpu(cpu, tmp) {
- BUG_ON(cpumask_test_cpu(cpu, cpu_present_mask));
+ BUG_ON(cpu_present(cpu));
set_cpu_present(cpu, true);
set_hard_smp_processor_id(cpu, *intserv++);
}
@@ -329,21 +340,17 @@ static void pseries_remove_processor(struct device_node *np)
static int pseries_smp_notifier(struct notifier_block *nb,
unsigned long action, void *node)
{
- int err = NOTIFY_OK;
+ int err = 0;
switch (action) {
- case PSERIES_RECONFIG_ADD:
- if (pseries_add_processor(node))
- err = NOTIFY_BAD;
+ case OF_RECONFIG_ATTACH_NODE:
+ err = pseries_add_processor(node);
break;
- case PSERIES_RECONFIG_REMOVE:
+ case OF_RECONFIG_DETACH_NODE:
pseries_remove_processor(node);
break;
- default:
- err = NOTIFY_DONE;
- break;
}
- return err;
+ return notifier_from_errno(err);
}
static struct notifier_block pseries_smp_nb = {
@@ -386,10 +393,10 @@ static int __init pseries_cpu_hotplug_init(void)
}
}
- rtas_stop_self_args.token = rtas_token("stop-self");
+ rtas_stop_self_token = rtas_token("stop-self");
qcss_tok = rtas_token("query-cpu-stopped-state");
- if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE ||
+ if (rtas_stop_self_token == RTAS_UNKNOWN_SERVICE ||
qcss_tok == RTAS_UNKNOWN_SERVICE) {
printk(KERN_INFO "CPU Hotplug not supported by firmware "
"- disabling.\n");
@@ -402,7 +409,7 @@ static int __init pseries_cpu_hotplug_init(void)
/* Processors can be added/removed only on LPAR */
if (firmware_has_feature(FW_FEATURE_LPAR)) {
- pSeries_reconfig_notifier_register(&pseries_smp_nb);
+ of_reconfig_notifier_register(&pseries_smp_nb);
cpu_maps_update_begin();
if (cede_offline_enabled && parse_cede_parameters() == 0) {
default_offline_state = CPU_STATE_INACTIVE;
@@ -414,4 +421,4 @@ static int __init pseries_cpu_hotplug_init(void)
return 0;
}
-arch_initcall(pseries_cpu_hotplug_init);
+machine_arch_initcall(pseries, pseries_cpu_hotplug_init);