Commit d9213319 authored by Nathan Lynch's avatar Nathan Lynch Committed by Michael Ellerman

powerpc/pseries/mobility: extract VASI session polling logic

The behavior of rtas_ibm_suspend_me_unsafe() is to return -EAGAIN to
the caller until the specified VASI suspend session state makes the
transition from H_VASI_ENABLED to H_VASI_SUSPENDING. In the interest
of separating concerns to prepare for a new implementation of the
join/suspend sequence, extract VASI session polling logic into a
couple of local functions. Waiting for the session state to reach
H_VASI_SUSPENDING before calling rtas_ibm_suspend_me_unsafe() ensures
that we will never get an EAGAIN result necessitating a retry. No
user-visible change in behavior is intended.
Signed-off-by: default avatarNathan Lynch <nathanl@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20201207215200.1785968-12-nathanl@linux.ibm.com
parent c3ae9781
...@@ -345,6 +345,66 @@ void post_mobility_fixup(void) ...@@ -345,6 +345,66 @@ void post_mobility_fixup(void)
return; return;
} }
static int poll_vasi_state(u64 handle, unsigned long *res)
{
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
long hvrc;
int ret;
hvrc = plpar_hcall(H_VASI_STATE, retbuf, handle);
switch (hvrc) {
case H_SUCCESS:
ret = 0;
*res = retbuf[0];
break;
case H_PARAMETER:
ret = -EINVAL;
break;
case H_FUNCTION:
ret = -EOPNOTSUPP;
break;
case H_HARDWARE:
default:
pr_err("unexpected H_VASI_STATE result %ld\n", hvrc);
ret = -EIO;
break;
}
return ret;
}
static int wait_for_vasi_session_suspending(u64 handle)
{
unsigned long state;
int ret;
/*
* Wait for transition from H_VASI_ENABLED to
* H_VASI_SUSPENDING. Treat anything else as an error.
*/
while (true) {
ret = poll_vasi_state(handle, &state);
if (ret != 0 || state == H_VASI_SUSPENDING) {
break;
} else if (state == H_VASI_ENABLED) {
ssleep(1);
} else {
pr_err("unexpected H_VASI_STATE result %lu\n", state);
ret = -EIO;
break;
}
}
/*
* Proceed even if H_VASI_STATE is unavailable. If H_JOIN or
* ibm,suspend-me are also unimplemented, we'll recover then.
*/
if (ret == -EOPNOTSUPP)
ret = 0;
return ret;
}
static ssize_t migration_store(struct class *class, static ssize_t migration_store(struct class *class,
struct class_attribute *attr, const char *buf, struct class_attribute *attr, const char *buf,
size_t count) size_t count)
...@@ -356,12 +416,11 @@ static ssize_t migration_store(struct class *class, ...@@ -356,12 +416,11 @@ static ssize_t migration_store(struct class *class,
if (rc) if (rc)
return rc; return rc;
do { rc = wait_for_vasi_session_suspending(streamid);
rc = rtas_ibm_suspend_me_unsafe(streamid); if (rc)
if (rc == -EAGAIN) return rc;
ssleep(1);
} while (rc == -EAGAIN);
rc = rtas_ibm_suspend_me_unsafe(streamid);
if (rc) if (rc)
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment