33
33
34
34
#include "powernv.h"
35
35
36
- static void __devinit pnv_smp_setup_cpu (int cpu )
36
+ #ifdef DEBUG
37
+ #include <asm/udbg.h>
38
+ #define DBG (fmt ...) udbg_printf(fmt)
39
+ #else
40
+ #define DBG (fmt ...)
41
+ #endif
42
+
43
+ static void __cpuinit pnv_smp_setup_cpu (int cpu )
37
44
{
38
45
if (cpu != boot_cpuid )
39
46
xics_setup_cpu ();
@@ -55,13 +62,78 @@ static int pnv_smp_cpu_bootable(unsigned int nr)
55
62
return 1 ;
56
63
}
57
64
65
+ #ifdef CONFIG_HOTPLUG_CPU
66
+
67
+ static int pnv_smp_cpu_disable (void )
68
+ {
69
+ int cpu = smp_processor_id ();
70
+
71
+ /* This is identical to pSeries... might consolidate by
72
+ * moving migrate_irqs_away to a ppc_md with default to
73
+ * the generic fixup_irqs. --BenH.
74
+ */
75
+ set_cpu_online (cpu , false);
76
+ vdso_data -> processorCount -- ;
77
+ if (cpu == boot_cpuid )
78
+ boot_cpuid = cpumask_any (cpu_online_mask );
79
+ xics_migrate_irqs_away ();
80
+ return 0 ;
81
+ }
82
+
83
+ static void pnv_smp_cpu_kill_self (void )
84
+ {
85
+ unsigned int cpu ;
86
+
87
+ /* If powersave_nap is enabled, use NAP mode, else just
88
+ * spin aimlessly
89
+ */
90
+ if (!powersave_nap ) {
91
+ generic_mach_cpu_die ();
92
+ return ;
93
+ }
94
+
95
+ /* Standard hot unplug procedure */
96
+ local_irq_disable ();
97
+ idle_task_exit ();
98
+ current -> active_mm = NULL ; /* for sanity */
99
+ cpu = smp_processor_id ();
100
+ DBG ("CPU%d offline\n" , cpu );
101
+ generic_set_cpu_dead (cpu );
102
+ smp_wmb ();
103
+
104
+ /* We don't want to take decrementer interrupts while we are offline,
105
+ * so clear LPCR:PECE1. We keep PECE2 enabled.
106
+ */
107
+ mtspr (SPRN_LPCR , mfspr (SPRN_LPCR ) & ~(u64 )LPCR_PECE1 );
108
+ while (!generic_check_cpu_restart (cpu )) {
109
+ power7_idle ();
110
+ if (!generic_check_cpu_restart (cpu )) {
111
+ DBG ("CPU%d Unexpected exit while offline !\n" , cpu );
112
+ /* We may be getting an IPI, so we re-enable
113
+ * interrupts to process it, it will be ignored
114
+ * since we aren't online (hopefully)
115
+ */
116
+ local_irq_enable ();
117
+ local_irq_disable ();
118
+ }
119
+ }
120
+ mtspr (SPRN_LPCR , mfspr (SPRN_LPCR ) | LPCR_PECE1 );
121
+ DBG ("CPU%d coming online...\n" , cpu );
122
+ }
123
+
124
+ #endif /* CONFIG_HOTPLUG_CPU */
125
+
58
126
static struct smp_ops_t pnv_smp_ops = {
59
127
.message_pass = smp_muxed_ipi_message_pass ,
60
128
.cause_ipi = NULL , /* Filled at runtime by xics_smp_probe() */
61
129
.probe = xics_smp_probe ,
62
130
.kick_cpu = smp_generic_kick_cpu ,
63
131
.setup_cpu = pnv_smp_setup_cpu ,
64
132
.cpu_bootable = pnv_smp_cpu_bootable ,
133
+ #ifdef CONFIG_HOTPLUG_CPU
134
+ .cpu_disable = pnv_smp_cpu_disable ,
135
+ .cpu_die = generic_cpu_die ,
136
+ #endif /* CONFIG_HOTPLUG_CPU */
65
137
};
66
138
67
139
/* This is called very early during platform setup_arch */
@@ -80,4 +152,8 @@ void __init pnv_smp_init(void)
80
152
smp_ops -> take_timebase = rtas_take_timebase ;
81
153
}
82
154
#endif /* CONFIG_PPC_RTAS */
155
+
156
+ #ifdef CONFIG_HOTPLUG_CPU
157
+ ppc_md .cpu_die = pnv_smp_cpu_kill_self ;
158
+ #endif
83
159
}
0 commit comments