diff options
| -rw-r--r-- | arch/powerpc/include/asm/opal.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/opal-wrappers.S | 1 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/opal.c | 16 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/setup.c | 6 |
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 | ||
| 829 | int64_t opal_get_msg(uint64_t buffer, size_t size); | 830 | int64_t opal_get_msg(uint64_t buffer, size_t size); |
| 830 | int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token); | 831 | int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token); |
| 832 | int64_t opal_sync_host_reboot(void); | ||
| 831 | 833 | ||
| 832 | /* Internal functions */ | 834 | /* Internal functions */ |
| 833 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); | 835 | extern 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); | |||
| 128 | OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE); | 128 | OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE); |
| 129 | OPAL_CALL(opal_get_msg, OPAL_GET_MSG); | 129 | OPAL_CALL(opal_get_msg, OPAL_GET_MSG); |
| 130 | OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION); | 130 | OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION); |
| 131 | OPAL_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); | |||
| 482 | void opal_shutdown(void) | 483 | void 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 | } |
