Michal Suchanek c48668
From 701ba68342412ae9be99a7c7f3badebf95271403 Mon Sep 17 00:00:00 2001
Michal Suchanek c48668
From: Nathan Lynch <nathanl@linux.ibm.com>
Michal Suchanek c48668
Date: Mon, 7 Dec 2020 15:51:36 -0600
Michal Suchanek c48668
Subject: [PATCH] powerpc/rtas: add rtas_ibm_suspend_me()
Michal Suchanek c48668
Michal Suchanek c48668
References: bsc#1181674 ltc#189159
Michal Suchanek c48668
Patch-mainline: v5.11-rc1
Michal Suchanek c48668
Git-commit: 701ba68342412ae9be99a7c7f3badebf95271403
Michal Suchanek c48668
Michal Suchanek c48668
Now that the name is available, provide a simple wrapper for
Michal Suchanek c48668
ibm,suspend-me which returns both a Linux errno and optionally the
Michal Suchanek c48668
actual RTAS status to the caller.
Michal Suchanek c48668
Michal Suchanek c48668
Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
Michal Suchanek c48668
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Michal Suchanek c48668
Link: https://lore.kernel.org/r/20201207215200.1785968-5-nathanl@linux.ibm.com
Michal Suchanek c48668
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek c48668
---
Michal Suchanek c48668
 arch/powerpc/include/asm/rtas.h |  1 +
Michal Suchanek c48668
 arch/powerpc/kernel/rtas.c      | 57 +++++++++++++++++++++++++++++++++
Michal Suchanek c48668
 2 files changed, 58 insertions(+)
Michal Suchanek c48668
Michal Suchanek c48668
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
Michal Suchanek c48668
--- a/arch/powerpc/include/asm/rtas.h
Michal Suchanek c48668
+++ b/arch/powerpc/include/asm/rtas.h
Michal Suchanek c48668
@@ -258,6 +258,7 @@ extern void rtas_progress(char *s, unsigned short hex);
Michal Suchanek c48668
 extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
Michal Suchanek c48668
 extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
Michal Suchanek c48668
 int rtas_ibm_suspend_me_unsafe(u64 handle);
Michal Suchanek c48668
+int rtas_ibm_suspend_me(int *fw_status);
Michal Suchanek c48668
 
Michal Suchanek c48668
 struct rtc_time;
Michal Suchanek c48668
 extern unsigned long rtas_get_boot_time(void);
Michal Suchanek c48668
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
Michal Suchanek c48668
index 0a8e5dc2c108..8a618a3c4beb 100644
Michal Suchanek c48668
--- a/arch/powerpc/kernel/rtas.c
Michal Suchanek c48668
+++ b/arch/powerpc/kernel/rtas.c
Michal Suchanek c48668
@@ -684,6 +684,63 @@ int rtas_set_indicator_fast(int indicator, int index, int new_value)
Michal Suchanek c48668
 	return rc;
Michal Suchanek c48668
 }
Michal Suchanek c48668
 
Michal Suchanek c48668
+/**
Michal Suchanek c48668
+ * rtas_ibm_suspend_me() - Call ibm,suspend-me to suspend the LPAR.
Michal Suchanek c48668
+ *
Michal Suchanek c48668
+ * @fw_status: RTAS call status will be placed here if not NULL.
Michal Suchanek c48668
+ *
Michal Suchanek c48668
+ * rtas_ibm_suspend_me() should be called only on a CPU which has
Michal Suchanek c48668
+ * received H_CONTINUE from the H_JOIN hcall. All other active CPUs
Michal Suchanek c48668
+ * should be waiting to return from H_JOIN.
Michal Suchanek c48668
+ *
Michal Suchanek c48668
+ * rtas_ibm_suspend_me() may suspend execution of the OS
Michal Suchanek c48668
+ * indefinitely. Callers should take appropriate measures upon return, such as
Michal Suchanek c48668
+ * resetting watchdog facilities.
Michal Suchanek c48668
+ *
Michal Suchanek c48668
+ * Callers may choose to retry this call if @fw_status is
Michal Suchanek c48668
+ * %RTAS_THREADS_ACTIVE.
Michal Suchanek c48668
+ *
Michal Suchanek c48668
+ * Return:
Michal Suchanek c48668
+ * 0          - The partition has resumed from suspend, possibly after
Michal Suchanek c48668
+ *              migration to a different host.
Michal Suchanek c48668
+ * -ECANCELED - The operation was aborted.
Michal Suchanek c48668
+ * -EAGAIN    - There were other CPUs not in H_JOIN at the time of the call.
Michal Suchanek c48668
+ * -EBUSY     - Some other condition prevented the suspend from succeeding.
Michal Suchanek c48668
+ * -EIO       - Hardware/platform error.
Michal Suchanek c48668
+ */
Michal Suchanek c48668
+int rtas_ibm_suspend_me(int *fw_status)
Michal Suchanek c48668
+{
Michal Suchanek c48668
+	int fwrc;
Michal Suchanek c48668
+	int ret;
Michal Suchanek c48668
+
Michal Suchanek c48668
+	fwrc = rtas_call(rtas_token("ibm,suspend-me"), 0, 1, NULL);
Michal Suchanek c48668
+
Michal Suchanek c48668
+	switch (fwrc) {
Michal Suchanek c48668
+	case 0:
Michal Suchanek c48668
+		ret = 0;
Michal Suchanek c48668
+		break;
Michal Suchanek c48668
+	case RTAS_SUSPEND_ABORTED:
Michal Suchanek c48668
+		ret = -ECANCELED;
Michal Suchanek c48668
+		break;
Michal Suchanek c48668
+	case RTAS_THREADS_ACTIVE:
Michal Suchanek c48668
+		ret = -EAGAIN;
Michal Suchanek c48668
+		break;
Michal Suchanek c48668
+	case RTAS_NOT_SUSPENDABLE:
Michal Suchanek c48668
+	case RTAS_OUTSTANDING_COPROC:
Michal Suchanek c48668
+		ret = -EBUSY;
Michal Suchanek c48668
+		break;
Michal Suchanek c48668
+	case -1:
Michal Suchanek c48668
+	default:
Michal Suchanek c48668
+		ret = -EIO;
Michal Suchanek c48668
+		break;
Michal Suchanek c48668
+	}
Michal Suchanek c48668
+
Michal Suchanek c48668
+	if (fw_status)
Michal Suchanek c48668
+		*fw_status = fwrc;
Michal Suchanek c48668
+
Michal Suchanek c48668
+	return ret;
Michal Suchanek c48668
+}
Michal Suchanek c48668
+
Michal Suchanek c48668
 void __noreturn rtas_restart(char *cmd)
Michal Suchanek c48668
 {
Michal Suchanek c48668
 	if (rtas_flash_term_hook)
Michal Suchanek c48668
-- 
Michal Suchanek c48668
2.26.2
Michal Suchanek c48668