From: Soumyadeep Hore <soumyadeep.hore@intel.com>
To: jingjing.wu@intel.com
Cc: dev@dpdk.org
Subject: [PATCH 11/25] common/idpf: support added for xn transactions
Date: Tue, 28 May 2024 07:35:51 +0000 [thread overview]
Message-ID: <20240528073559.867121-2-soumyadeep.hore@intel.com> (raw)
In-Reply-To: <20240528073559.867121-1-soumyadeep.hore@intel.com>
Support added for xn transaction apis to send/receive control queue
messages.
Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com>
---
drivers/common/idpf/base/idpf_osdep.c | 71 +++++
drivers/common/idpf/base/idpf_osdep.h | 80 ++++-
drivers/common/idpf/base/idpf_xn.c | 439 ++++++++++++++++++++++++++
drivers/common/idpf/base/idpf_xn.h | 90 ++++++
drivers/common/idpf/base/meson.build | 2 +
5 files changed, 681 insertions(+), 1 deletion(-)
create mode 100644 drivers/common/idpf/base/idpf_osdep.c
create mode 100644 drivers/common/idpf/base/idpf_xn.c
create mode 100644 drivers/common/idpf/base/idpf_xn.h
diff --git a/drivers/common/idpf/base/idpf_osdep.c b/drivers/common/idpf/base/idpf_osdep.c
new file mode 100644
index 0000000000..2faf5ef6a3
--- /dev/null
+++ b/drivers/common/idpf/base/idpf_osdep.c
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2024 Intel Corporation
+ */
+
+#include "idpf_osdep.h"
+
+int idpf_compl_event_init(struct completion *completion)
+{
+ int poll_fd;
+
+ poll_fd = epoll_create(1);
+ if (poll_fd < 0) {
+ perror("epoll create failed\n");
+ return EPERM;
+ }
+ completion->poll_fd = poll_fd;
+
+ return 0;
+}
+
+int idpf_compl_event_reinit(struct completion *completion)
+{
+ struct epoll_event event;
+ int fd, ret;
+
+ fd = eventfd(0,0);
+ if (fd < 0) {
+ perror("Eventfd open failed\n");
+ return EPERM;
+ }
+ completion->event_fd = fd;
+ event.events = EPOLLIN | EPOLLERR | EPOLLHUP;
+ event.data.fd = fd;
+ ret = epoll_ctl(completion->poll_fd, EPOLL_CTL_ADD, fd, &event);
+ if (ret < 0) {
+ perror("Eventfd open failed\n");
+ close(fd);
+ return EPERM;
+ }
+ return 0;
+}
+
+int idpf_compl_event_sig(struct completion *completion, uint64_t status)
+{
+ int ret;
+
+ ret = write(completion->event_fd, &status, sizeof(status));
+
+ return (ret > 0 ? 0 : 1);
+}
+
+int idpf_compl_event_wait(struct completion *completion, int timeout)
+{
+ struct epoll_event event = { 0 };
+ uint64_t status;
+ int ret;
+
+ ret = epoll_wait(completion->poll_fd, &event, 1, timeout);
+ if (ret > 0) {
+ printf("Command Completed successfully\n");
+ ret = read(completion->event_fd, &status, sizeof(status));
+ }
+ close(completion->event_fd);
+
+ return (ret > 0 ? 0 : 1);
+}
+
+void idpf_compl_event_deinit(struct completion *completion)
+{
+ close(completion->poll_fd);
+}
diff --git a/drivers/common/idpf/base/idpf_osdep.h b/drivers/common/idpf/base/idpf_osdep.h
index 74a376cb13..bd11eab351 100644
--- a/drivers/common/idpf/base/idpf_osdep.h
+++ b/drivers/common/idpf/base/idpf_osdep.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2023 Intel Corporation
+ * Copyright(c) 2001-2024 Intel Corporation
*/
#ifndef _IDPF_OSDEP_H_
@@ -12,6 +12,11 @@
#include <inttypes.h>
#include <sys/queue.h>
#include <stdbool.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
#include <rte_common.h>
#include <rte_memcpy.h>
@@ -353,4 +358,77 @@ idpf_hweight32(u32 num)
#endif
+#ifndef IDPF_DFLT_MBX_BUF_SIZE
+#define IDPF_DFLT_MBX_BUF_SIZE 4096
+#endif
+
+#ifndef __iovec_defined
+#define __iovec_defined 1
+
+#define __need_size_t
+
+/* Structure for scatter/gather I/O. */
+struct iovec
+ {
+ void *iov_base; /* Pointer to data. */
+ size_t iov_len; /* Length of data. */
+ };
+
+#endif
+
+#define IDPF_IOVEC struct iovec
+
+#define IDPF_LIST_HEAD(name, type) SLIST_HEAD(name, type)
+#define IDPF_LIST_HEAD_INIT(head) SLIST_INIT(head)
+#define IDPF_LIST_ENTRY(type) SLIST_ENTRY(type)
+#define IDPF_LIST_ADD(head, node) SLIST_INSERT_HEAD(head, node, entry)
+#define IDPF_LIST_DEL(head) SLIST_REMOVE_HEAD(head, entry)
+#define IDPF_LIST_FOR_EACH(var, head) SLIST_FOREACH(var, head, entry)
+#define IDPF_LIST_EMPTY(head) SLIST_EMPTY(head)
+#define IDPF_LIST_FIRST(head) SLIST_FIRST(head)
+
+/* OSdep changes */
+#define IDPF_LOCK pthread_mutex_t
+#define IDPF_LOCK_INIT(mutex) pthread_mutex_init(mutex, NULL)
+#define IDPF_LOCK_DESTROY(mutex) pthread_mutex_destroy(mutex)
+#define IDPF_LOCK_ACQUIRE(mutex) pthread_mutex_lock(mutex)
+#define IDPF_LOCK_RELEASE(mutex) pthread_mutex_unlock(mutex)
+
+#ifndef FIELD_PREP
+
+#define __bf_shf(x) (__builtin_ffsll(x) - 1)
+#define FIELD_PREP(_mask, _val) \
+ ({ \
+ ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
+ })
+
+#define FIELD_GET(_mask, _reg) \
+ ({ \
+ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
+ })
+#endif /* FIELD_PREP */
+
+struct completion {
+ int event_fd;
+ int poll_fd;
+};
+
+/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */
+#define EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */
+
+int idpf_compl_event_init(struct completion *completion);
+int idpf_compl_event_reinit(struct completion *completion);
+int idpf_compl_event_sig(struct completion *completion, uint64_t status);
+int idpf_compl_event_wait(struct completion *completion, int timeout);
+void idpf_compl_event_deinit(struct completion *completion);
+
+#define IDPF_CMD_COMPLETION struct completion
+#define IDPF_CMD_COMPLETION_INIT(x) idpf_compl_event_init(x)
+#define IDPF_CMD_COMPLETION_REINIT(x) idpf_compl_event_reinit(x)
+#define IDPF_CMD_COMPLETION_DEINIT(x) idpf_compl_event_deinit(x)
+#define IDPF_CMD_COMPLETION_SIG(x, y) idpf_compl_event_sig(x, y)
+#define IDPF_CMD_COMPLETION_WAIT(x, y) idpf_compl_event_wait(x, y)
+
+#define IDPF_DEBUG_PRINT printf
+
#endif /* _IDPF_OSDEP_H_ */
diff --git a/drivers/common/idpf/base/idpf_xn.c b/drivers/common/idpf/base/idpf_xn.c
new file mode 100644
index 0000000000..5492564903
--- /dev/null
+++ b/drivers/common/idpf/base/idpf_xn.c
@@ -0,0 +1,439 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2024 Intel Corporation
+ */
+
+#include "idpf_xn.h"
+#include "virtchnl2.h"
+#include "idpf_controlq.h"
+
+/**
+ * idpf_ctlq_xn_pop_free - get a free xn entry from the free list
+ * @xnmn: pointer to transaction manager
+ *
+ * Retrieve a free xn entry from the free list
+ *
+ */
+static struct idpf_ctlq_xn *
+idpf_ctlq_xn_pop_free(struct idpf_ctlq_xn_manager *xnm)
+{
+ struct idpf_ctlq_xn *xn;
+
+ IDPF_LOCK_ACQUIRE(&xnm->xn_list_lock);
+ if (IDPF_LIST_EMPTY(&xnm->free_xns)) {
+ IDPF_LOCK_RELEASE(&xnm->xn_list_lock);
+ return NULL;
+ }
+
+ xn = IDPF_LIST_FIRST(&xnm->free_xns);
+ IDPF_LIST_DEL(&xnm->free_xns);
+ xn->cookie = xnm->cookie++;
+ IDPF_LOCK_RELEASE(&xnm->xn_list_lock);
+
+ return xn;
+}
+
+/**
+ * idpf_ctlq_xn_push_free - push a xn entry into free list
+ * @xnm: pointer to transaction manager
+ * @xn: pointer to xn entry
+ *
+ * Add the used xn entry back to the free list
+ *
+ */
+static void idpf_ctlq_xn_push_free(struct idpf_ctlq_xn_manager *xnm, struct idpf_ctlq_xn *xn)
+{
+ if (xn->state == IDPF_CTLQ_XN_SHUTDOWN)
+ return;
+
+ xn->recv_buf.iov_base = NULL;
+ xn->recv_buf.iov_len = 0;
+ xn->state = IDPF_CTLQ_XN_IDLE;
+ IDPF_LOCK_ACQUIRE(&xnm->xn_list_lock);
+ IDPF_LIST_ADD(&xnm->free_xns, xn);
+ IDPF_LOCK_RELEASE(&xnm->xn_list_lock);
+}
+
+/**
+ * idpf_ctlq_xn_deinit_dma - Free the dma memory that allocated for send messages
+ * @hw: pointer to hw structure
+ * @xnm: pointer to transaction manager
+ *
+ * Free the dma memory that allocated for send messages
+ *
+ */
+static void idpf_ctlq_xn_deinit_dma(struct idpf_hw *hw, struct idpf_ctlq_xn_manager *xnm)
+{
+ int i;
+
+ for (i = 0; i < MAX_XN_ENTRIES; i++) {
+ struct idpf_ctlq_xn *xn = &xnm->ring[i];
+
+ if (xn->dma_mem) {
+ idpf_free_dma_mem(hw, xn->dma_mem);
+ idpf_free(hw, xn->dma_mem);
+ }
+ }
+
+ return;
+}
+
+/**
+ * idpf_ctlq_xn_init_dma - pre allocate dma memory for send messages in xn
+ * @hw: pointer to hw structure
+ * @xnm: pointer to transaction manager
+ *
+ * pre allocate dma memory for send messages in xn
+ *
+ */
+static int idpf_ctlq_xn_init_dma(struct idpf_hw *hw, struct idpf_ctlq_xn_manager *xnm)
+{
+ struct idpf_dma_mem *dma_mem;
+ int i;
+
+ for (i = 0; i < MAX_XN_ENTRIES; i++) {
+ struct idpf_ctlq_xn *xn = &xnm->ring[i];
+
+ dma_mem = (struct idpf_dma_mem *)idpf_calloc(hw, 1, sizeof(*dma_mem));
+ if (!dma_mem)
+ break;
+ dma_mem->va = idpf_alloc_dma_mem(hw, dma_mem, IDPF_DFLT_MBX_BUF_SIZE);
+ if (!dma_mem->va) {
+ idpf_free(hw, dma_mem);
+ break;
+ }
+ xn->dma_mem = dma_mem;
+ }
+
+ /* error case, dma allocate failed, so free the allocated ones and fail the init */
+ if (i < MAX_XN_ENTRIES) {
+ idpf_ctlq_xn_deinit_dma(hw, xnm);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * idpf_ctlq_xn_process_recv - process a control queue receive message
+ * @params: pointer to receive param structure
+ * @ctlq_msg: pointer to control queue message
+ *
+ * Process a control queue receive message and send a complete event notification
+ *
+ */
+static int idpf_ctlq_xn_process_recv(struct idpf_ctlq_xn_recv_params *params, struct idpf_ctlq_msg *ctlq_msg)
+{
+ async_ctlq_xn_resp_cb async_resp_cb = NULL;
+ size_t payload_size, return_size;
+ struct idpf_ctlq_xn *xn;
+ IDPF_IOVEC recv_buf;
+ u16 msg_cookie;
+ void *payload;
+ u8 xn_index;
+ int status;
+ int ret;
+
+ xn_index = FIELD_GET(IDPF_CTLQ_XN_INDEX_M, ctlq_msg->ctx.sw_cookie.data);
+ msg_cookie = FIELD_GET(IDPF_CTLQ_XN_COOKIE_M, ctlq_msg->ctx.sw_cookie.data);
+ payload = ctlq_msg->ctx.indirect.payload->va;
+ payload_size = ctlq_msg->ctx.indirect.payload->size;
+ status = (ctlq_msg->cookie.mbx.chnl_retval) ? -EBADMSG : 0;
+
+ if (xn_index >= MAX_XN_ENTRIES) {
+ IDPF_DEBUG_PRINT("Out of bounds cookie received: %02x\n", xn_index);
+ return -ENXIO;
+ }
+ xn = ¶ms->xnm->ring[xn_index];
+
+ if (xn->cookie != msg_cookie) {
+ IDPF_DEBUG_PRINT("Transaction cookie does not match (%02x != %02x)\n", xn->cookie, msg_cookie);
+ return -ENXIO;
+ }
+
+ IDPF_LOCK_ACQUIRE(&xn->lock);
+ if ((xn->state != IDPF_CTLQ_XN_ASYNC) && (xn->state != IDPF_CTLQ_XN_WAITING)) {
+ IDPF_DEBUG_PRINT(" Recv error xn state %d\n", xn->state);
+ ret = -EBADMSG;
+ goto exit;
+ }
+
+ return_size = (xn->recv_buf.iov_len < payload_size) ? xn->recv_buf.iov_len : payload_size;
+ if (xn->recv_buf.iov_base && return_size)
+ idpf_memcpy(xn->recv_buf.iov_base, payload, return_size, IDPF_DMA_TO_NONDMA);
+
+ if (status)
+ IDPF_DEBUG_PRINT("Async message failure (op %d)\n", ctlq_msg->cookie.mbx.chnl_opcode);
+
+ if (xn->state == IDPF_CTLQ_XN_ASYNC) {
+ async_resp_cb = xn->async_resp_cb;
+ recv_buf = xn->recv_buf;
+ ret = 0;
+ goto exit;
+ }
+
+ xn->state = status ? IDPF_CTLQ_XN_COMPLETED_FAILED : IDPF_CTLQ_XN_COMPLETED_SUCCESS;
+ IDPF_LOCK_RELEASE(&xn->lock);
+ IDPF_CMD_COMPLETION_SIG(&xn->cmd_completion_event, 1);
+ return 0;
+
+exit:
+ idpf_ctlq_xn_push_free(params->xnm, xn);
+ IDPF_LOCK_RELEASE(&xn->lock);
+
+ /* call the callback after xn unlock */
+ if (async_resp_cb)
+ async_resp_cb(params->hw, recv_buf.iov_base, return_size, status);
+ return ret;
+}
+
+/**
+ * idpf_ctlq_xn_recv - Function to handle a receive message
+ * @params: pointer to receive param structure
+ *
+ * Process a receive message and update the receive queue buffer
+ *
+ */
+int idpf_ctlq_xn_recv(struct idpf_ctlq_xn_recv_params *params)
+{
+ struct idpf_dma_mem *dma_mem = NULL;
+ struct idpf_ctlq_msg ctlq_msg;
+ u16 num_recv = 1;
+ int ret;
+
+ if (!params || !params->hw || !params->xnm ||
+ !params->ctlq_info || !params->default_msg_handler)
+ return -EBADR;
+
+ ret = idpf_ctlq_recv(params->ctlq_info, &num_recv, &ctlq_msg);
+ if (ret)
+ return ret;
+
+ if (ctlq_msg.data_len)
+ dma_mem = ctlq_msg.ctx.indirect.payload;
+
+ ret = idpf_ctlq_xn_process_recv(params, &ctlq_msg);
+ /* Call the default handler for HMA event messages */
+ if (ret == -ENXIO)
+ ret = params->default_msg_handler(params->hw, &ctlq_msg);
+ ret = idpf_ctlq_post_rx_buffs(params->hw, params->ctlq_info, &num_recv, &dma_mem);
+
+ return ret;
+}
+
+/**
+ * idpf_ctlq_xn_process_msg - process and send a control queue message
+ * @params: pointer to send params structure
+ * @xn: pointer to xn entry
+ *
+ * Process and send a control queue message
+ *
+ */
+static int idpf_ctlq_xn_process_send(struct idpf_ctlq_xn_send_params *params, struct idpf_ctlq_xn *xn)
+{
+ u16 cookie;
+ int ret;
+
+ /* It's possible we're just sending an opcode but no buffer */
+ if (params->send_buf.iov_base && params->send_buf.iov_len) {
+ if (params->send_buf.iov_len >= IDPF_DFLT_MBX_BUF_SIZE)
+ return -EBADMSG;
+
+ idpf_memcpy(xn->dma_mem->va, params->send_buf.iov_base, params->send_buf.iov_len, IDPF_NONDMA_TO_DMA);
+ params->ctlq_msg->ctx.indirect.payload = xn->dma_mem;
+ }
+ cookie = FIELD_PREP(IDPF_CTLQ_XN_COOKIE_M, xn->cookie) | FIELD_PREP(IDPF_CTLQ_XN_INDEX_M, xn->index);
+ params->ctlq_msg->ctx.sw_cookie.data = cookie;
+ ret = idpf_ctlq_send(params->hw, params->ctlq_info, 1, params->ctlq_msg);
+
+ return ret;
+}
+
+/**
+ * idpf_ctlq_xn_send - Function to send a control queue message
+ * @params: pointer to send param structure
+ *
+ * Send a control queue (mailbox or config) message.
+ * Based on the params value, the call can be completed synchronusly or asynchronusly.
+ *
+ */
+int idpf_ctlq_xn_send(struct idpf_ctlq_xn_send_params *params)
+{
+ struct idpf_ctlq_xn *xn;
+ int ret;
+
+ if (!params || !params->hw || !params->xnm ||
+ !params->ctlq_msg || !params->ctlq_info)
+ return -EBADR;
+
+ xn = idpf_ctlq_xn_pop_free(params->xnm);
+ /* no free transactions available */
+ if (!xn)
+ return -EBUSY;
+
+ IDPF_LOCK_ACQUIRE(&xn->lock);
+ if (xn->state != IDPF_CTLQ_XN_IDLE) {
+ ret = -EBUSY;
+ goto error;
+ }
+ xn->recv_buf = params->recv_buf;
+ xn->state = params->async_resp_cb ? IDPF_CTLQ_XN_ASYNC : IDPF_CTLQ_XN_WAITING;
+ xn->send_ctlq_info = params->ctlq_info;
+ /* if callback is not provided then process it as a synchronous message */
+ if (!params->async_resp_cb)
+ IDPF_CMD_COMPLETION_REINIT(&xn->cmd_completion_event);
+ else
+ xn->async_resp_cb = params->async_resp_cb;
+ IDPF_LOCK_RELEASE(&xn->lock);
+
+ ret = idpf_ctlq_xn_process_send(params, xn);
+ if (ret)
+ goto error;
+
+ if (params->async_resp_cb)
+ return 0;
+ /* wait for the command completion */
+ IDPF_CMD_COMPLETION_WAIT(&xn->cmd_completion_event, params->timeout_ms);
+
+ IDPF_LOCK_ACQUIRE(&xn->lock);
+ switch (xn->state) {
+ case IDPF_CTLQ_XN_WAITING:
+ ret = -ETIMEDOUT;
+ break;
+ case IDPF_CTLQ_XN_COMPLETED_SUCCESS:
+ ret = 0;
+ break;
+ default:
+ ret = -EBADMSG;
+ break;
+ }
+
+error:
+ IDPF_LOCK_RELEASE(&xn->lock);
+ idpf_ctlq_xn_push_free(params->xnm, xn);
+ return ret;
+}
+
+/**
+ * idpf_ctlq_xn_send_clean - cleanup the send control queue message buffers
+ * @hw: pointer to hardware structure
+ * @ctlq_info: pointer to control queue info to be cleaned
+ *
+ * Cleanup the send buffers for the given control queue, if force is set, then
+ * clear all the outstanding send messages irrrespective their send status. Force should be
+ * used during deinit or reset.
+ *
+ */
+int idpf_ctlq_xn_send_clean(struct idpf_ctlq_xn_clean_params *params)
+{
+ int ret = 0;
+
+ if (!params || !params->hw || !params->ctlq_info ||
+ !params->num_msgs || !params->q_msg)
+ return -EBADR;
+
+ if (params->force)
+ ret = idpf_ctlq_clean_sq_force(params->ctlq_info, ¶ms->num_msgs, params->q_msg);
+ else
+ ret = idpf_ctlq_clean_sq(params->ctlq_info, ¶ms->num_msgs, params->q_msg);
+
+ return ret;
+}
+
+/**
+ * idpf_ctlq_xn_deinit - deallocate and free the transaction manager resources
+ * @xn_mngr: pointer to xn init params
+ *
+ * Deallocate and free the transaction manager structure.
+ *
+ */
+int idpf_ctlq_xn_deinit(struct idpf_ctlq_xn_init_params *params)
+{
+ enum idpf_ctlq_xn_state prev_state;
+ int i;
+
+ if (!params || !params->hw || !params->xnm)
+ return -EBADR;
+
+ for (i = 0; i < MAX_XN_ENTRIES; i++) {
+ struct idpf_ctlq_xn *xn = ¶ms->xnm->ring[i];
+
+ IDPF_LOCK_ACQUIRE(&xn->lock);
+ prev_state = xn->state;
+ xn->state = IDPF_CTLQ_XN_SHUTDOWN;
+ switch (prev_state) {
+ case IDPF_CTLQ_XN_WAITING:
+ IDPF_CMD_COMPLETION_SIG(&xn->cmd_completion_event, 1);
+ break;
+ case IDPF_CTLQ_XN_ASYNC:
+ xn->async_resp_cb(params->hw, xn->recv_buf.iov_base, 0, -EBADMSG);
+ break;
+ default:
+ break;
+ }
+ IDPF_CMD_COMPLETION_DEINIT(&xn->cmd_completion_event);
+ IDPF_LOCK_RELEASE(&xn->lock);
+ IDPF_LOCK_DESTROY(&xn->lock);
+ }
+
+ IDPF_LOCK_ACQUIRE(¶ms->xnm->xn_list_lock);
+ while (IDPF_LIST_EMPTY(¶ms->xnm->free_xns))
+ IDPF_LIST_DEL(¶ms->xnm->free_xns);
+ IDPF_LOCK_RELEASE(¶ms->xnm->xn_list_lock);
+ IDPF_LOCK_DESTROY(¶ms->xnm->xn_list_lock);
+ idpf_ctlq_xn_deinit_dma(params->hw, params->xnm);
+
+ idpf_free(params->hw, params->xnm);
+ idpf_ctlq_deinit(params->hw);
+
+ return 0;
+}
+
+/**
+ * idpf_ctlq_xn_init - initialize transaction manager
+ * @xn_mngr: pointer to xn init params
+ *
+ * Allocate and initialize transaction manager structure.
+ * Return success if no errors occur.
+ *
+ */
+int idpf_ctlq_xn_init(struct idpf_ctlq_xn_init_params *params)
+{
+ struct idpf_ctlq_xn_manager *xnm;
+ int i, ret;
+
+ if (!params || !params->hw || !params->cctlq_info ||
+ !params->num_qs)
+ return -EBADR;
+
+ ret = idpf_ctlq_init(params->hw, params->num_qs, params->cctlq_info);
+ if (ret)
+ return ret;
+
+ xnm = idpf_calloc(params->hw, 1, sizeof(struct idpf_ctlq_xn_manager));
+ if (!xnm) {
+ idpf_ctlq_deinit(params->hw);
+ return -ENOMEM;
+ }
+
+ ret = idpf_ctlq_xn_init_dma(params->hw, xnm);
+ if (ret) {
+ idpf_free(params->hw, xnm);
+ idpf_ctlq_deinit(params->hw);
+ return -ENOMEM;
+ }
+
+ IDPF_LIST_HEAD_INIT(&xnm->free_xns);
+ IDPF_LOCK_INIT(&xnm->xn_list_lock);
+
+ for (i = 0; i < MAX_XN_ENTRIES; i++) {
+ struct idpf_ctlq_xn *xn = &xnm->ring[i];
+
+ xn->state = IDPF_CTLQ_XN_IDLE;
+ xn->index = i;
+ IDPF_CMD_COMPLETION_INIT(&xn->cmd_completion_event);
+ IDPF_LIST_ADD(&xnm->free_xns, xn);
+ IDPF_LOCK_INIT(&xn->lock);
+ }
+
+ params->xnm = xnm;
+ return 0;
+}
diff --git a/drivers/common/idpf/base/idpf_xn.h b/drivers/common/idpf/base/idpf_xn.h
new file mode 100644
index 0000000000..42f2b849d1
--- /dev/null
+++ b/drivers/common/idpf/base/idpf_xn.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2024 Intel Corporation
+ */
+
+#ifndef _IDPF_XN_H_
+#define _IDPF_XN_H_
+
+#include "idpf_osdep.h"
+
+#define MAX_XN_ENTRIES 256
+#define IDPF_CTLQ_XN_INDEX_M GENMASK(7, 0)
+#define IDPF_CTLQ_XN_COOKIE_M GENMASK(15, 8)
+#define IN
+#define OUT
+
+struct idpf_ctlq_msg;
+typedef int (*async_ctlq_xn_resp_cb) (struct idpf_hw *, void *, size_t len, int status);
+typedef int (*default_ctlq_msg_handler) (struct idpf_hw *, struct idpf_ctlq_msg *ctlq_msg);
+
+enum idpf_ctlq_xn_state {
+ IDPF_CTLQ_XN_IDLE = 1,
+ IDPF_CTLQ_XN_WAITING,
+ IDPF_CTLQ_XN_COMPLETED_SUCCESS,
+ IDPF_CTLQ_XN_COMPLETED_FAILED,
+ IDPF_CTLQ_XN_SHUTDOWN,
+ IDPF_CTLQ_XN_ASYNC,
+};
+
+struct idpf_ctlq_xn {
+ IDPF_LIST_ENTRY(idpf_ctlq_xn) entry;
+ u8 cookie;
+ u8 index;
+ IDPF_IOVEC recv_buf;
+ IDPF_LOCK lock;
+ enum idpf_ctlq_xn_state state;
+ struct idpf_ctlq_info *send_ctlq_info;
+ IDPF_CMD_COMPLETION cmd_completion_event;
+ struct idpf_dma_mem *dma_mem;
+ async_ctlq_xn_resp_cb async_resp_cb;
+};
+
+/* The below structures are available for user APIs */
+struct idpf_ctlq_xn_manager {
+ u8 cookie;
+ IDPF_LOCK xn_list_lock;
+ IDPF_LIST_HEAD(head, idpf_ctlq_xn) free_xns;
+ struct idpf_ctlq_xn ring[MAX_XN_ENTRIES];
+};
+
+/* Base driver fills all these values before calling send */
+struct idpf_ctlq_xn_send_params {
+ IN struct idpf_hw *hw;
+ IN struct idpf_ctlq_xn_manager *xnm;
+ IN struct idpf_ctlq_info *ctlq_info;
+ IN struct idpf_ctlq_msg *ctlq_msg;
+ IN IDPF_IOVEC send_buf;
+ IN IDPF_IOVEC recv_buf;
+ IN u64 timeout_ms;
+ IN async_ctlq_xn_resp_cb async_resp_cb;
+};
+
+struct idpf_ctlq_xn_recv_params {
+ IN struct idpf_ctlq_xn_manager *xnm;
+ IN struct idpf_hw *hw;
+ IN struct idpf_ctlq_info *ctlq_info;
+ IN default_ctlq_msg_handler default_msg_handler;
+};
+
+struct idpf_ctlq_xn_clean_params {
+ IN bool force;
+ IN u16 num_msgs;
+ IN struct idpf_hw *hw;
+ IN struct idpf_ctlq_info *ctlq_info;
+ IN OUT struct idpf_ctlq_msg **q_msg;
+};
+
+struct idpf_ctlq_xn_init_params {
+ IN u8 num_qs;
+ IN struct idpf_ctlq_create_info *cctlq_info;
+ IN struct idpf_hw *hw;
+ OUT struct idpf_ctlq_xn_manager *xnm;
+};
+
+int idpf_ctlq_xn_init(struct idpf_ctlq_xn_init_params *params);
+int idpf_ctlq_xn_deinit(struct idpf_ctlq_xn_init_params *params);
+
+int idpf_ctlq_xn_send(struct idpf_ctlq_xn_send_params *params);
+int idpf_ctlq_xn_recv(struct idpf_ctlq_xn_recv_params *params);
+int idpf_ctlq_xn_send_clean(struct idpf_ctlq_xn_clean_params *params);
+#endif /* _ISEP_XN_H_ */
diff --git a/drivers/common/idpf/base/meson.build b/drivers/common/idpf/base/meson.build
index 96d7642209..539f9f7203 100644
--- a/drivers/common/idpf/base/meson.build
+++ b/drivers/common/idpf/base/meson.build
@@ -3,8 +3,10 @@
sources += files(
'idpf_common.c',
+ 'idpf_osdep.c',
'idpf_controlq.c',
'idpf_controlq_setup.c',
+ 'idpf_xn.c'
)
cflags += ['-Wno-unused-value']
--
2.43.0
next prev parent reply other threads:[~2024-05-28 8:17 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-28 7:35 [PATCH 10/25] common/idpf: avoid variable 0-init Soumyadeep Hore
2024-05-28 7:35 ` Soumyadeep Hore [this message]
2024-05-28 7:35 ` [PATCH 12/25] common/idpf: rename of VIRTCHNL2 CAP INLINE FLOW STEER Soumyadeep Hore
2024-05-28 7:35 ` [PATCH 13/25] common/idpf: update compiler padding Soumyadeep Hore
2024-05-28 7:35 ` [PATCH 14/25] common/idpf: avoid " Soumyadeep Hore
2024-05-28 7:35 ` [PATCH 15/25] common/idpf: add wmb before tail Soumyadeep Hore
2024-05-28 7:35 ` [PATCH 16/25] common/idpf: add a new Tx context descriptor structure Soumyadeep Hore
2024-05-28 7:35 ` [PATCH 17/25] common/idpf: removing redundant implementation Soumyadeep Hore
2024-05-28 7:35 ` [PATCH 18/25] common/idpf: removing redundant functionality of virtchnl2 Soumyadeep Hore
2024-05-28 7:35 ` [PATCH 19/25] common/idpf: updating common code of latest base driver Soumyadeep Hore
2024-05-29 13:26 ` [PATCH 10/25] common/idpf: avoid variable 0-init Bruce Richardson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240528073559.867121-2-soumyadeep.hore@intel.com \
--to=soumyadeep.hore@intel.com \
--cc=dev@dpdk.org \
--cc=jingjing.wu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).