aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>2014-01-15 01:02:04 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-01-15 01:21:18 -0500
commitf7d98d18a01ece2863984d4fb5ae949b18b02715 (patch)
tree062fe89b801c7c017da5fc6403cab2f473492cb4
parentcb5b242c8c14a4b1dcd358400da28208fde78947 (diff)
powerpc/powernv: Call OPAL sync before kexec'ing
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>
-rw-r--r--arch/powerpc/include/asm/opal.h2
-rw-r--r--arch/powerpc/platforms/powernv/opal-wrappers.S1
-rw-r--r--arch/powerpc/platforms/powernv/opal.c16
-rw-r--r--arch/powerpc/platforms/powernv/setup.c6
4 files changed, 23 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 9a87b4401a41..40157e2ca691 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -156,6 +156,7 @@ extern int opal_enter_rtas(struct rtas_args *args,
156#define OPAL_FLASH_UPDATE 78 156#define OPAL_FLASH_UPDATE 78
157#define OPAL_GET_MSG 85 157#define OPAL_GET_MSG 85
158#define OPAL_CHECK_ASYNC_COMPLETION 86 158#define OPAL_CHECK_ASYNC_COMPLETION 86
159#define OPAL_SYNC_HOST_REBOOT 87
159 160
160#ifndef __ASSEMBLY__ 161#ifndef __ASSEMBLY__
161 162
@@ -828,6 +829,7 @@ int64_t opal_update_flash(uint64_t blk_list);
828 829
829int64_t opal_get_msg(uint64_t buffer, size_t size); 830int64_t opal_get_msg(uint64_t buffer, size_t size);
830int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token); 831int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
832int64_t opal_sync_host_reboot(void);
831 833
832/* Internal functions */ 834/* Internal functions */
833extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); 835extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index 719aa5c325c6..3e8829c40fbb 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -128,3 +128,4 @@ OPAL_CALL(opal_manage_flash, OPAL_FLASH_MANAGE);
128OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE); 128OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE);
129OPAL_CALL(opal_get_msg, OPAL_GET_MSG); 129OPAL_CALL(opal_get_msg, OPAL_GET_MSG);
130OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION); 130OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION);
131OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 7a184a0ff183..65499adaecff 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -20,6 +20,7 @@
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/kobject.h> 22#include <linux/kobject.h>
23#include <linux/delay.h>
23#include <asm/opal.h> 24#include <asm/opal.h>
24#include <asm/firmware.h> 25#include <asm/firmware.h>
25#include <asm/mce.h> 26#include <asm/mce.h>
@@ -482,10 +483,25 @@ subsys_initcall(opal_init);
482void opal_shutdown(void) 483void opal_shutdown(void)
483{ 484{
484 unsigned int i; 485 unsigned int i;
486 long rc = OPAL_BUSY;
485 487
488 /* First free interrupts, which will also mask them */
486 for (i = 0; i < opal_irq_count; i++) { 489 for (i = 0; i < opal_irq_count; i++) {
487 if (opal_irqs[i]) 490 if (opal_irqs[i])
488 free_irq(opal_irqs[i], NULL); 491 free_irq(opal_irqs[i], NULL);
489 opal_irqs[i] = 0; 492 opal_irqs[i] = 0;
490 } 493 }
494
495 /*
496 * Then sync with OPAL which ensure anything that can
497 * potentially write to our memory has completed such
498 * as an ongoing dump retrieval
499 */
500 while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
501 rc = opal_sync_host_reboot();
502 if (rc == OPAL_BUSY)
503 opal_poll_events(NULL);
504 else
505 mdelay(10);
506 }
491} 507}
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 19884b2a51b4..a932feb2901c 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -145,8 +145,10 @@ static void pnv_shutdown(void)
145 /* Let the PCI code clear up IODA tables */ 145 /* Let the PCI code clear up IODA tables */
146 pnv_pci_shutdown(); 146 pnv_pci_shutdown();
147 147
148 /* And unregister all OPAL interrupts so they don't fire 148 /*
149 * up while we kexec 149 * Stop OPAL activity: Unregister all OPAL interrupts so they
150 * don't fire up while we kexec and make sure all potentially
151 * DMA'ing ops are complete (such as dump retrieval).
150 */ 152 */
151 opal_shutdown(); 153 opal_shutdown();
152} 154}