/** * @remote: PF/VF identifier of the origin (or target) of the relay * request message.
*/
u32 remote;
/** @rid: identifier of the VF/PF relay message. */
u32 rid;
/** * @request: points to the inner VF/PF request message, copied to the * #response_buf starting at #offset.
*/
u32 *request;
/** @request_len: length of the inner VF/PF request message. */
u32 request_len;
/** * @response: points to the placeholder buffer where inner VF/PF * response will be located, for outgoing transaction * this could be caller's buffer (if provided) otherwise * it points to the #response_buf starting at #offset.
*/
u32 *response;
/** * @response_len: length of the inner VF/PF response message (only * if #status is 0), initially set to the size of the * placeholder buffer where response message will be * copied.
*/
u32 response_len;
/** * @offset: offset to the start of the inner VF/PF relay message inside * buffers; this offset is equal the length of the outer GuC * relay header message.
*/
u32 offset;
/** * @request_buf: buffer with VF/PF request message including outer * transport message.
*/
u32 request_buf[GUC_CTB_MAX_DWORDS];
/** * @response_buf: buffer with VF/PF response message including outer * transport message.
*/
u32 response_buf[GUC_CTB_MAX_DWORDS];
/** * @reply: status of the reply, 0 means that data pointed by the * #response is valid.
*/ int reply;
/** @done: completion of the outgoing transaction. */ struct completion done;
/** @link: transaction list link */ struct list_head link;
};
if (unlikely(!relay_is_ready(relay))) return ERR_PTR(-ENODEV);
/* * For incoming requests we can't use GFP_KERNEL as those are delivered * with CTB lock held which is marked as used in the reclaim path. * Btw, that's one of the reason why we use mempool here!
*/
txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_NOWAIT); if (!txn) return ERR_PTR(-ENOMEM);
/** * xe_guc_relay_init - Initialize a &xe_guc_relay * @relay: the &xe_guc_relay to initialize * * Initialize remaining members of &xe_guc_relay that may depend * on the SR-IOV mode. * * Return: 0 on success or a negative error code on failure.
*/ int xe_guc_relay_init(struct xe_guc_relay *relay)
{ constint XE_RELAY_MEMPOOL_MIN_NUM = 1; struct xe_device *xe = relay_to_xe(relay); int err;
static u32 sanitize_relay_error(u32 error)
{ /* XXX TBD if generic error codes will be allowed */ if (!IS_ENABLED(CONFIG_DRM_XE_DEBUG))
error = GUC_RELAY_ERROR_UNDISCLOSED; return error;
}
static u32 sanitize_relay_error_hint(u32 hint)
{ /* XXX TBD if generic error codes will be allowed */ if (!IS_ENABLED(CONFIG_DRM_XE_DEBUG))
hint = 0; return hint;
}
/* list ordering does not need to match RID ordering */
spin_lock(&relay->lock);
list_add_tail(&txn->link, &relay->pending_relays);
spin_unlock(&relay->lock);
resend:
ret = relay_send_transaction(relay, txn); if (unlikely(ret < 0)) goto unlink;
wait:
n = wait_for_completion_timeout(&txn->done, timeout); if (unlikely(n == 0 && txn->reply)) {
ret = -ETIME; goto unlink;
}
relay_debug(relay, "%u.%u reply %d after %u msec\n",
txn->remote, txn->rid, txn->reply, jiffies_to_msecs(timeout - n)); if (unlikely(txn->reply)) {
reinit_completion(&txn->done); if (txn->reply == -EAGAIN) goto resend; if (txn->reply == -EBUSY) {
relay_testonly_nop(relay); goto wait;
} if (txn->reply > 0)
ret = from_relay_error(txn->reply); else
ret = txn->reply; goto unlink;
}
#ifdef CONFIG_PCI_IOV /** * xe_guc_relay_send_to_vf - Send a message to the VF. * @relay: the &xe_guc_relay which will send the message * @target: target VF number * @msg: request message to be sent * @len: length of the request message (in dwords, can't be 0) * @buf: placeholder for the response message * @buf_size: size of the response message placeholder (in dwords) * * This function can only be used by the driver running in the SR-IOV PF mode. * * Return: Non-negative response length (in dwords) or * a negative error code on failure.
*/ int xe_guc_relay_send_to_vf(struct xe_guc_relay *relay, u32 target, const u32 *msg, u32 len, u32 *buf, u32 buf_size)
{
relay_assert(relay, IS_SRIOV_PF(relay_to_xe(relay)));
/** * xe_guc_relay_send_to_pf - Send a message to the PF. * @relay: the &xe_guc_relay which will send the message * @msg: request message to be sent * @len: length of the message (in dwords, can't be 0) * @buf: placeholder for the response message * @buf_size: size of the response message placeholder (in dwords) * * This function can only be used by driver running in SR-IOV VF mode. * * Return: Non-negative response length (in dwords) or * a negative error code on failure.
*/ int xe_guc_relay_send_to_pf(struct xe_guc_relay *relay, const u32 *msg, u32 len, u32 *buf, u32 buf_size)
{
relay_assert(relay, IS_SRIOV_VF(relay_to_xe(relay)));
if (unlikely(len < GUC_HXG_MSG_MIN_LEN)) return -EPROTO;
if (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, msg[0]) != GUC_HXG_ORIGIN_HOST) return -EPROTO;
type = FIELD_GET(GUC_HXG_MSG_0_TYPE, msg[0]);
relay_debug(relay, "received %s.%u from %u = %*ph\n",
guc_hxg_type_to_string(type), rid, origin, 4 * len, msg);
switch (type) { case GUC_HXG_TYPE_REQUEST: case GUC_HXG_TYPE_FAST_REQUEST: case GUC_HXG_TYPE_EVENT:
err = relay_queue_action_msg(relay, origin, rid, msg, len); break; case GUC_HXG_TYPE_RESPONSE_SUCCESS:
err = relay_handle_reply(relay, origin, rid, 0, msg, len); break; case GUC_HXG_TYPE_NO_RESPONSE_BUSY:
err = relay_handle_reply(relay, origin, rid, -EBUSY, NULL, 0); break; case GUC_HXG_TYPE_NO_RESPONSE_RETRY:
err = relay_handle_reply(relay, origin, rid, -EAGAIN, NULL, 0); break; case GUC_HXG_TYPE_RESPONSE_FAILURE:
err = relay_handle_failure(relay, origin, rid, msg, len); break; default:
err = -EBADRQC;
}
if (unlikely(err))
relay_notice(relay, "Failed to process %s.%u from %u (%pe) %*ph\n",
guc_hxg_type_to_string(type), rid, origin,
ERR_PTR(err), 4 * len, msg);
return err;
}
/** * xe_guc_relay_process_guc2vf - Handle relay notification message from the GuC. * @relay: the &xe_guc_relay which will handle the message * @msg: message to be handled * @len: length of the message (in dwords) * * This function will handle relay messages received from the GuC. * * This function is can only be used if driver is running in SR-IOV mode. * * Return: 0 on success or a negative error code on failure.
*/ int xe_guc_relay_process_guc2vf(struct xe_guc_relay *relay, const u32 *msg, u32 len)
{
u32 rid;
#ifdef CONFIG_PCI_IOV /** * xe_guc_relay_process_guc2pf - Handle relay notification message from the GuC. * @relay: the &xe_guc_relay which will handle the message * @msg: message to be handled * @len: length of the message (in dwords) * * This function will handle relay messages received from the GuC. * * This function can only be used if driver is running in SR-IOV PF mode. * * Return: 0 on success or a negative error code on failure.
*/ int xe_guc_relay_process_guc2pf(struct xe_guc_relay *relay, const u32 *msg, u32 len)
{
u32 origin, rid; int err;
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.