powerpc/rtas: add rtas_ibm_suspend_me()
authorNathan Lynch <nathanl@linux.ibm.com>
Mon, 7 Dec 2020 21:51:36 +0000 (15:51 -0600)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 8 Dec 2020 10:40:55 +0000 (21:40 +1100)
Now that the name is available, provide a simple wrapper for
ibm,suspend-me which returns both a Linux errno and optionally the
actual RTAS status to the caller.

Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20201207215200.1785968-5-nathanl@linux.ibm.com
arch/powerpc/include/asm/rtas.h
arch/powerpc/kernel/rtas.c

index 8436ed0..b43165f 100644 (file)
@@ -258,6 +258,7 @@ extern void rtas_progress(char *s, unsigned short hex);
 extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
 extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
 int rtas_ibm_suspend_me_unsafe(u64 handle);
+int rtas_ibm_suspend_me(int *fw_status);
 
 struct rtc_time;
 extern time64_t rtas_get_boot_time(void);
index 0a8e5dc..8a618a3 100644 (file)
@@ -684,6 +684,63 @@ int rtas_set_indicator_fast(int indicator, int index, int new_value)
        return rc;
 }
 
+/**
+ * rtas_ibm_suspend_me() - Call ibm,suspend-me to suspend the LPAR.
+ *
+ * @fw_status: RTAS call status will be placed here if not NULL.
+ *
+ * rtas_ibm_suspend_me() should be called only on a CPU which has
+ * received H_CONTINUE from the H_JOIN hcall. All other active CPUs
+ * should be waiting to return from H_JOIN.
+ *
+ * rtas_ibm_suspend_me() may suspend execution of the OS
+ * indefinitely. Callers should take appropriate measures upon return, such as
+ * resetting watchdog facilities.
+ *
+ * Callers may choose to retry this call if @fw_status is
+ * %RTAS_THREADS_ACTIVE.
+ *
+ * Return:
+ * 0          - The partition has resumed from suspend, possibly after
+ *              migration to a different host.
+ * -ECANCELED - The operation was aborted.
+ * -EAGAIN    - There were other CPUs not in H_JOIN at the time of the call.
+ * -EBUSY     - Some other condition prevented the suspend from succeeding.
+ * -EIO       - Hardware/platform error.
+ */
+int rtas_ibm_suspend_me(int *fw_status)
+{
+       int fwrc;
+       int ret;
+
+       fwrc = rtas_call(rtas_token("ibm,suspend-me"), 0, 1, NULL);
+
+       switch (fwrc) {
+       case 0:
+               ret = 0;
+               break;
+       case RTAS_SUSPEND_ABORTED:
+               ret = -ECANCELED;
+               break;
+       case RTAS_THREADS_ACTIVE:
+               ret = -EAGAIN;
+               break;
+       case RTAS_NOT_SUSPENDABLE:
+       case RTAS_OUTSTANDING_COPROC:
+               ret = -EBUSY;
+               break;
+       case -1:
+       default:
+               ret = -EIO;
+               break;
+       }
+
+       if (fw_status)
+               *fw_status = fwrc;
+
+       return ret;
+}
+
 void __noreturn rtas_restart(char *cmd)
 {
        if (rtas_flash_term_hook)