diff --git a/sys/powerpc/powernv/opal.h b/sys/powerpc/powernv/opal.h index 5933a599c96..4ddd56a85e1 100644 --- a/sys/powerpc/powernv/opal.h +++ b/sys/powerpc/powernv/opal.h @@ -201,7 +201,7 @@ struct opal_ipmi_msg { int opal_init_async_tokens(int); int opal_alloc_async_token(void); void opal_free_async_token(int); -int opal_wait_completion(void *, uint64_t, uint64_t); +int opal_wait_completion(void *, uint64_t, int); typedef void (*opal_msg_handler_fn)(void *, struct opal_msg *); EVENTHANDLER_DECLARE(OPAL_ASYNC_COMP, opal_msg_handler_fn); diff --git a/sys/powerpc/powernv/opal_async.c b/sys/powerpc/powernv/opal_async.c index f64ba7dccf3..1af518f8399 100644 --- a/sys/powerpc/powernv/opal_async.c +++ b/sys/powerpc/powernv/opal_async.c @@ -50,8 +50,8 @@ static vmem_t *async_token_pool; static void opal_handle_async_completion(void *, struct opal_msg *); struct async_completion { - uint64_t rval; - bool completed; + volatile uint64_t completed; + struct opal_msg msg; }; struct async_completion *completions; @@ -98,16 +98,21 @@ opal_free_async_token(int token) * of the operation, error if it returns early. */ int -opal_wait_completion(void *buf, uint64_t size, uint64_t token) +opal_wait_completion(void *buf, uint64_t size, int token) { int err; do { err = opal_call(OPAL_CHECK_ASYNC_COMPLETION, vtophys(buf), size, token); - if (err == OPAL_BUSY) - if (completions[token].completed) - return (completions[token].rval); + if (err == OPAL_BUSY) { + if (completions[token].completed) { + atomic_thread_fence_acq(); + memcpy(buf, &completions[token].msg, size); + return (OPAL_SUCCESS); + } + } + DELAY(100); } while (err == OPAL_BUSY); return (err); @@ -118,7 +123,7 @@ static void opal_handle_async_completion(void *arg, struct opal_msg *msg) int token; token = msg->params[0]; - completions[token].rval = msg->params[1]; - isync(); + memcpy(&completions[token].msg, msg, sizeof(*msg)); + atomic_thread_fence_rel(); completions[token].completed = true; }