/* * Note: If the returned token is used in an opal call and opal returns * OPAL_ASYNC_COMPLETION you MUST call one of opal_async_wait_response() or * opal_async_wait_response_interruptible() at least once before calling another * opal_async_* function
*/ int opal_async_get_token_interruptible(void)
{ int token;
/* Wait until a token is available */ if (down_interruptible(&opal_async_sem)) return -ERESTARTSYS;
token = __opal_async_get_token(); if (token < 0)
up(&opal_async_sem);
staticint __opal_async_release_token(int token)
{ unsignedlong flags; int rc;
if (token < 0 || token >= opal_max_async_tokens) {
pr_err("%s: Passed token is out of range, token %d\n",
__func__, token); return -EINVAL;
}
spin_lock_irqsave(&opal_async_comp_lock, flags); switch (opal_async_tokens[token].state) { case ASYNC_TOKEN_COMPLETED: case ASYNC_TOKEN_ALLOCATED:
opal_async_tokens[token].state = ASYNC_TOKEN_UNALLOCATED;
rc = 0; break; /* * DISPATCHED and ABANDONED tokens must wait for OPAL to respond. * Mark a DISPATCHED token as ABANDONED so that the response handling * code knows no one cares and that it can free it then.
*/ case ASYNC_TOKEN_DISPATCHED:
opal_async_tokens[token].state = ASYNC_TOKEN_ABANDONED;
fallthrough; default:
rc = 1;
}
spin_unlock_irqrestore(&opal_async_comp_lock, flags);
return rc;
}
int opal_async_release_token(int token)
{ int ret;
ret = __opal_async_release_token(token); if (!ret)
up(&opal_async_sem);
/* * There is no need to mark the token as dispatched, wait_event() * will block until the token completes. * * Wakeup the poller before we wait for events to speed things * up on platforms or simulators where the interrupts aren't * functional.
*/
opal_wake_poller();
wait_event(opal_async_wait, opal_async_tokens[token].state
== ASYNC_TOKEN_COMPLETED);
memcpy(msg, &opal_async_tokens[token].response, sizeof(*msg));
/* * The first time this gets called we mark the token as DISPATCHED * so that if wait_event_interruptible() returns not zero and the * caller frees the token, we know not to actually free the token * until the response comes. * * Only change if the token is ALLOCATED - it may have been * completed even before the caller gets around to calling this * the first time. * * There is also a dirty great comment at the token allocation * function that if the opal call returns OPAL_ASYNC_COMPLETION to * the caller then the caller *must* call this or the not * interruptible version before doing anything else with the * token.
*/ if (opal_async_tokens[token].state == ASYNC_TOKEN_ALLOCATED) {
spin_lock_irqsave(&opal_async_comp_lock, flags); if (opal_async_tokens[token].state == ASYNC_TOKEN_ALLOCATED)
opal_async_tokens[token].state = ASYNC_TOKEN_DISPATCHED;
spin_unlock_irqrestore(&opal_async_comp_lock, flags);
}
/* * Wakeup the poller before we wait for events to speed things * up on platforms or simulators where the interrupts aren't * functional.
*/
opal_wake_poller();
ret = wait_event_interruptible(opal_async_wait,
opal_async_tokens[token].state ==
ASYNC_TOKEN_COMPLETED); if (!ret)
memcpy(msg, &opal_async_tokens[token].response, sizeof(*msg));
if (state == ASYNC_TOKEN_ABANDONED) { /* Free the token, no one else will */
opal_async_release_token(token); return 0;
}
memcpy(&opal_async_tokens[token].response, comp_msg, sizeof(*comp_msg));
wake_up(&opal_async_wait);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.