powerpc/powernv: Call OPAL sync before kexec'ing
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>
Wed, 15 Jan 2014 06:02:04 +0000 (17:02 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 15 Jan 2014 06:21:18 +0000 (17:21 +1100)
Its possible that OPAL may be writing to host memory during
kexec (like dump retrieve scenario). In this situation we might
end up corrupting host memory.

This patch makes OPAL sync call to make sure OPAL stops
writing to host memory before kexec'ing.

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/opal.h
arch/powerpc/platforms/powernv/opal-wrappers.S
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/setup.c

index 9a87b4401a416dc39e89bb530e11d5cd272905c5..40157e2ca6914467cddae0225070d8582ad0861c 100644 (file)
@@ -156,6 +156,7 @@ extern int opal_enter_rtas(struct rtas_args *args,
 #define OPAL_FLASH_UPDATE                      78
 #define OPAL_GET_MSG                           85
 #define OPAL_CHECK_ASYNC_COMPLETION            86
+#define OPAL_SYNC_HOST_REBOOT                  87
 
 #ifndef __ASSEMBLY__
 
@@ -828,6 +829,7 @@ int64_t opal_update_flash(uint64_t blk_list);
 
 int64_t opal_get_msg(uint64_t buffer, size_t size);
 int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
+int64_t opal_sync_host_reboot(void);
 
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
index 719aa5c325c65121c9a826a3cefc3e59ec014f47..3e8829c40fbbfc436adb206fb297b82ea7385e89 100644 (file)
@@ -128,3 +128,4 @@ OPAL_CALL(opal_manage_flash,                        OPAL_FLASH_MANAGE);
 OPAL_CALL(opal_update_flash,                   OPAL_FLASH_UPDATE);
 OPAL_CALL(opal_get_msg,                                OPAL_GET_MSG);
 OPAL_CALL(opal_check_completion,               OPAL_CHECK_ASYNC_COMPLETION);
+OPAL_CALL(opal_sync_host_reboot,               OPAL_SYNC_HOST_REBOOT);
index 7a184a0ff18371c717ed705d2a2f021b65eec8f3..65499adaecff2a1e2367612ece5e051028e38634 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/kobject.h>
+#include <linux/delay.h>
 #include <asm/opal.h>
 #include <asm/firmware.h>
 #include <asm/mce.h>
@@ -482,10 +483,25 @@ subsys_initcall(opal_init);
 void opal_shutdown(void)
 {
        unsigned int i;
+       long rc = OPAL_BUSY;
 
+       /* First free interrupts, which will also mask them */
        for (i = 0; i < opal_irq_count; i++) {
                if (opal_irqs[i])
                        free_irq(opal_irqs[i], NULL);
                opal_irqs[i] = 0;
        }
+
+       /*
+        * Then sync with OPAL which ensure anything that can
+        * potentially write to our memory has completed such
+        * as an ongoing dump retrieval
+        */
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_sync_host_reboot();
+               if (rc == OPAL_BUSY)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
 }
index 19884b2a51b4743f78a9389f22e8588e228616d7..a932feb2901c74df383aa7114b256ed57007b677 100644 (file)
@@ -145,8 +145,10 @@ static void pnv_shutdown(void)
        /* Let the PCI code clear up IODA tables */
        pnv_pci_shutdown();
 
-       /* And unregister all OPAL interrupts so they don't fire
-        * up while we kexec
+       /*
+        * Stop OPAL activity: Unregister all OPAL interrupts so they
+        * don't fire up while we kexec and make sure all potentially
+        * DMA'ing ops are complete (such as dump retrieval).
         */
        opal_shutdown();
 }
This page took 0.026934 seconds and 5 git commands to generate.