powerpc/rtas: add rtas_ibm_suspend_me()

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
This commit is contained in:
Nathan Lynch 2020-12-07 15:51:36 -06:00 committed by Michael Ellerman
parent 7049b288ea
commit 701ba68342
2 changed files with 58 additions and 0 deletions

View 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);

View 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)