powerpc/pseries: Fix kexec on recent firmware versions
authorAnton Blanchard <anton@samba.org>
Mon, 25 Jul 2011 01:46:32 +0000 (01:46 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 5 Aug 2011 04:47:57 +0000 (14:47 +1000)
Recent versions of firmware will fail to unmap the virtual processor
area if we have a dispatch trace log registered. This causes kexec
to fail.

If a trace log is registered this patch unregisters it before the
SLB shadow and virtual processor areas, fixing the problem.

The address argument is ignored by firmware on unregister so we
may as well remove it.

Signed-off-by: Anton Blanchard <anton@samba.org>
Cc: <stable@kernel.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/platforms/pseries/dtl.c
arch/powerpc/platforms/pseries/kexec.c
arch/powerpc/platforms/pseries/plpar_wrappers.h

index e9190073bb9791cb3a3486d05c336b430ef36e63..0e8656370063fe6bf005e59032a67c414efe729f 100644 (file)
@@ -181,7 +181,7 @@ static void dtl_stop(struct dtl *dtl)
 
        lppaca_of(dtl->cpu).dtl_enable_mask = 0x0;
 
-       unregister_dtl(hwcpu, __pa(dtl->buf));
+       unregister_dtl(hwcpu);
 }
 
 static u64 dtl_current_index(struct dtl *dtl)
index 54cf3a4aa16b31d58214655c1b69d209a7a335ac..1118cb79f9e3f7af435bc73762b510cb37242934 100644 (file)
@@ -26,6 +26,17 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
        /* Don't risk a hypervisor call if we're crashing */
        if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
                unsigned long addr;
+               int ret;
+
+               if (get_lppaca()->dtl_enable_mask) {
+                       ret = unregister_dtl(hard_smp_processor_id());
+                       if (ret) {
+                               pr_err("WARNING: DTL deregistration for cpu "
+                                      "%d (hw %d) failed with %d\n",
+                                      smp_processor_id(),
+                                      hard_smp_processor_id(), ret);
+                       }
+               }
 
                addr = __pa(get_slb_shadow());
                if (unregister_slb_shadow(hard_smp_processor_id(), addr))
index 4bf21207d7d3b17e95e3a2e1cda7387fd531dd0f..a6921aec2d6f2ea113cd79514e04a142beeb43d4 100644 (file)
@@ -73,9 +73,9 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
        return vpa_call(0x3, cpu, vpa);
 }
 
-static inline long unregister_dtl(unsigned long cpu, unsigned long vpa)
+static inline long unregister_dtl(unsigned long cpu)
 {
-       return vpa_call(0x6, cpu, vpa);
+       return vpa_call(0x6, cpu, 0);
 }
 
 static inline long register_dtl(unsigned long cpu, unsigned long vpa)