aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/pseries/setup.c26
-rw-r--r--arch/ppc64/kernel/machine_kexec.c12
-rw-r--r--include/asm-powerpc/machdep.h4
3 files changed, 33 insertions, 9 deletions
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 31990829310..b9d9732b2e0 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -200,14 +200,12 @@ static void __init pSeries_setup_arch(void)
if (ppc64_interrupt_controller == IC_OPEN_PIC) {
ppc_md.init_IRQ = pSeries_init_mpic;
ppc_md.get_irq = mpic_get_irq;
- ppc_md.cpu_irq_down = mpic_teardown_this_cpu;
/* Allocate the mpic now, so that find_and_init_phbs() can
* fill the ISUs */
pSeries_setup_mpic();
} else {
ppc_md.init_IRQ = xics_init_IRQ;
ppc_md.get_irq = xics_get_irq;
- ppc_md.cpu_irq_down = xics_teardown_cpu;
}
#ifdef CONFIG_SMP
@@ -595,6 +593,27 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
return PCI_PROBE_NORMAL;
}
+#ifdef CONFIG_KEXEC
+static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
+{
+ /* Don't risk a hypervisor call if we're crashing */
+ if (!crash_shutdown) {
+ unsigned long vpa = __pa(&get_paca()->lppaca);
+
+ if (unregister_vpa(hard_smp_processor_id(), vpa)) {
+ printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
+ "failed\n", smp_processor_id(),
+ hard_smp_processor_id());
+ }
+ }
+
+ if (ppc64_interrupt_controller == IC_OPEN_PIC)
+ mpic_teardown_this_cpu(secondary);
+ else
+ xics_teardown_cpu(secondary);
+}
+#endif
+
struct machdep_calls __initdata pSeries_md = {
.probe = pSeries_probe,
.setup_arch = pSeries_setup_arch,
@@ -617,4 +636,7 @@ struct machdep_calls __initdata pSeries_md = {
.check_legacy_ioport = pSeries_check_legacy_ioport,
.system_reset_exception = pSeries_system_reset_exception,
.machine_check_exception = pSeries_machine_check_exception,
+#ifdef CONFIG_KEXEC
+ .kexec_cpu_down = pseries_kexec_cpu_down,
+#endif
};
diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c
index 07ea03598c0..203f1d5e6f1 100644
--- a/arch/ppc64/kernel/machine_kexec.c
+++ b/arch/ppc64/kernel/machine_kexec.c
@@ -185,8 +185,8 @@ void kexec_copy_flush(struct kimage *image)
*/
void kexec_smp_down(void *arg)
{
- if (ppc_md.cpu_irq_down)
- ppc_md.cpu_irq_down(1);
+ if (ppc_md.kexec_cpu_down)
+ ppc_md.kexec_cpu_down(0, 1);
local_irq_disable();
kexec_smp_wait();
@@ -233,8 +233,8 @@ static void kexec_prepare_cpus(void)
}
/* after we tell the others to go down */
- if (ppc_md.cpu_irq_down)
- ppc_md.cpu_irq_down(0);
+ if (ppc_md.kexec_cpu_down)
+ ppc_md.kexec_cpu_down(0, 0);
put_cpu();
@@ -255,8 +255,8 @@ static void kexec_prepare_cpus(void)
* UP to an SMP kernel.
*/
smp_release_cpus();
- if (ppc_md.cpu_irq_down)
- ppc_md.cpu_irq_down(0);
+ if (ppc_md.kexec_cpu_down)
+ ppc_md.kexec_cpu_down(0, 0);
local_irq_disable();
}
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 5670f0cd614..c011abb8b60 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -93,7 +93,9 @@ struct machdep_calls {
void (*init_IRQ)(void);
int (*get_irq)(struct pt_regs *);
- void (*cpu_irq_down)(int secondary);
+#ifdef CONFIG_KEXEC
+ void (*kexec_cpu_down)(int crash_shutdown, int secondary);
+#endif
/* PCI stuff */
/* Called after scanning the bus, before allocating resources */