powerpc/pseries: Fix kexec regression caused by CPPR tracking
authorMark Nelson <markn@au1.ibm.com>
Sun, 7 Feb 2010 16:45:12 +0000 (16:45 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 8 Feb 2010 04:29:19 +0000 (15:29 +1100)
The code to track the CPPR values added by commit
49bd3647134ea47420067aea8d1401e722bf2aac ("powerpc/pseries: Track previous
CPPR values to correctly EOI interrupts") broke kexec on pseries because
the kexec code in xics.c calls xics_set_cpu_priority() before the IPI has
been EOI'ed. This wasn't a problem previously but it now triggers a BUG_ON
in xics_set_cpu_priority() because os_cppr->index isn't 0.

Fix this problem by setting the index on the CPPR stack to 0 before calling
xics_set_cpu_priority() in xics_teardown_cpu().

Also make it clear that we only want to set the priority when there's just
one CPPR value in the stack, and enforce it by updating the value of
os_cppr->stack[0] rather than os_cppr->stack[os_cppr->index].

While we're at it change the BUG_ON to a WARN_ON.

Reported-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Mark Nelson <markn@au1.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/platforms/pseries/xics.c

index 1ee66db..f5f7919 100644 (file)
@@ -784,9 +784,13 @@ static void xics_set_cpu_priority(unsigned char cppr)
 {
        struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
 
-       BUG_ON(os_cppr->index != 0);
+       /*
+        * we only really want to set the priority when there's
+        * just one cppr value on the stack
+        */
+       WARN_ON(os_cppr->index != 0);
 
-       os_cppr->stack[os_cppr->index] = cppr;
+       os_cppr->stack[0] = cppr;
 
        if (firmware_has_feature(FW_FEATURE_LPAR))
                lpar_cppr_info(cppr);
@@ -821,8 +825,14 @@ void xics_setup_cpu(void)
 
 void xics_teardown_cpu(void)
 {
+       struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
        int cpu = smp_processor_id();
 
+       /*
+        * we have to reset the cppr index to 0 because we're
+        * not going to return from the IPI
+        */
+       os_cppr->index = 0;
        xics_set_cpu_priority(0);
 
        /* Clear any pending IPI request */