@@ -7,6 +7,7 @@
#include <rte_errno.h>
#include <rte_log.h>
#include <rte_pci.h>
+#include <rte_memory.h>
#include <mlx5_glue.h>
#include <mlx5_common.h>
@@ -184,6 +185,125 @@ mlx5_crypto_sym_session_clear(struct rte_cryptodev *dev,
DRV_LOG(DEBUG, "Session %p was cleared.", sess_private_data);
}
+static int
+mlx5_crypto_queue_pair_release(struct rte_cryptodev *dev, uint16_t qp_id)
+{
+ struct mlx5_crypto_qp *qp = dev->data->queue_pairs[qp_id];
+
+ if (qp->qp_obj != NULL)
+ claim_zero(mlx5_devx_cmd_destroy(qp->qp_obj));
+ if (qp->umem_obj != NULL)
+ claim_zero(mlx5_glue->devx_umem_dereg(qp->umem_obj));
+ if (qp->umem_buf != NULL)
+ rte_free(qp->umem_buf);
+ mlx5_devx_cq_destroy(&qp->cq_obj);
+ rte_free(qp);
+ dev->data->queue_pairs[qp_id] = NULL;
+ return 0;
+}
+
+static int
+mlx5_crypto_qp2rts(struct mlx5_crypto_qp *qp)
+{
+ /*
+ * In Order to configure self loopback, when calling these functions the
+ * remote QP id that is used is the id of the same QP.
+ */
+ if (mlx5_devx_cmd_modify_qp_state(qp->qp_obj, MLX5_CMD_OP_RST2INIT_QP,
+ qp->qp_obj->id)) {
+ DRV_LOG(ERR, "Failed to modify QP to INIT state(%u).",
+ rte_errno);
+ return -1;
+ }
+ if (mlx5_devx_cmd_modify_qp_state(qp->qp_obj, MLX5_CMD_OP_INIT2RTR_QP,
+ qp->qp_obj->id)) {
+ DRV_LOG(ERR, "Failed to modify QP to RTR state(%u).",
+ rte_errno);
+ return -1;
+ }
+ if (mlx5_devx_cmd_modify_qp_state(qp->qp_obj, MLX5_CMD_OP_RTR2RTS_QP,
+ qp->qp_obj->id)) {
+ DRV_LOG(ERR, "Failed to modify QP to RTS state(%u).",
+ rte_errno);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+mlx5_crypto_queue_pair_setup(struct rte_cryptodev *dev, uint16_t qp_id,
+ const struct rte_cryptodev_qp_conf *qp_conf,
+ int socket_id)
+{
+ struct mlx5_crypto_priv *priv = dev->data->dev_private;
+ struct mlx5_devx_qp_attr attr = {0};
+ struct mlx5_crypto_qp *qp;
+ uint16_t log_nb_desc = rte_log2_u32(qp_conf->nb_descriptors);
+ uint32_t umem_size = RTE_BIT32(log_nb_desc) *
+ MLX5_CRYPTO_WQE_SET_SIZE +
+ sizeof(*qp->db_rec) * 2;
+ uint32_t alloc_size = sizeof(*qp);
+ struct mlx5_devx_cq_attr cq_attr = {
+ .uar_page_id = mlx5_os_get_devx_uar_page_id(priv->uar),
+ };
+
+ alloc_size = RTE_ALIGN(alloc_size, RTE_CACHE_LINE_SIZE);
+ alloc_size += sizeof(struct rte_crypto_op *) * RTE_BIT32(log_nb_desc);
+ qp = rte_zmalloc_socket(__func__, alloc_size, RTE_CACHE_LINE_SIZE,
+ socket_id);
+ if (qp == NULL) {
+ DRV_LOG(ERR, "Failed to allocate QP memory.");
+ rte_errno = ENOMEM;
+ return -rte_errno;
+ }
+ if (mlx5_devx_cq_create(priv->ctx, &qp->cq_obj, log_nb_desc,
+ &cq_attr, socket_id) != 0) {
+ DRV_LOG(ERR, "Failed to create CQ.");
+ goto error;
+ }
+ qp->umem_buf = rte_zmalloc_socket(__func__, umem_size, 4096, socket_id);
+ if (qp->umem_buf == NULL) {
+ DRV_LOG(ERR, "Failed to allocate QP umem.");
+ rte_errno = ENOMEM;
+ goto error;
+ }
+ qp->umem_obj = mlx5_glue->devx_umem_reg(priv->ctx,
+ (void *)(uintptr_t)qp->umem_buf,
+ umem_size,
+ IBV_ACCESS_LOCAL_WRITE);
+ if (qp->umem_obj == NULL) {
+ DRV_LOG(ERR, "Failed to register QP umem.");
+ goto error;
+ }
+ attr.pd = priv->pdn;
+ attr.uar_index = mlx5_os_get_devx_uar_page_id(priv->uar);
+ attr.cqn = qp->cq_obj.cq->id;
+ attr.log_page_size = rte_log2_u32(sysconf(_SC_PAGESIZE));
+ attr.rq_size = 0;
+ attr.sq_size = RTE_BIT32(log_nb_desc);
+ attr.dbr_umem_valid = 1;
+ attr.wq_umem_id = qp->umem_obj->umem_id;
+ attr.wq_umem_offset = 0;
+ attr.dbr_umem_id = qp->umem_obj->umem_id;
+ attr.dbr_address = RTE_BIT64(log_nb_desc) *
+ MLX5_CRYPTO_WQE_SET_SIZE;
+ qp->qp_obj = mlx5_devx_cmd_create_qp(priv->ctx, &attr);
+ if (qp->qp_obj == NULL) {
+ DRV_LOG(ERR, "Failed to create QP(%u).", rte_errno);
+ goto error;
+ }
+ qp->db_rec = RTE_PTR_ADD(qp->umem_buf, (uintptr_t)attr.dbr_address);
+ if (mlx5_crypto_qp2rts(qp))
+ goto error;
+ qp->ops = (struct rte_crypto_op **)RTE_ALIGN((uintptr_t)(qp + 1),
+ RTE_CACHE_LINE_SIZE);
+ dev->data->queue_pairs[qp_id] = qp;
+ return 0;
+error:
+ mlx5_crypto_queue_pair_release(dev, qp_id);
+ return -1;
+}
+
static struct rte_cryptodev_ops mlx5_crypto_ops = {
.dev_configure = mlx5_crypto_dev_configure,
.dev_start = NULL,
@@ -192,8 +312,8 @@ static struct rte_cryptodev_ops mlx5_crypto_ops = {
.dev_infos_get = mlx5_crypto_dev_infos_get,
.stats_get = NULL,
.stats_reset = NULL,
- .queue_pair_setup = NULL,
- .queue_pair_release = NULL,
+ .queue_pair_setup = mlx5_crypto_queue_pair_setup,
+ .queue_pair_release = mlx5_crypto_queue_pair_release,
.sym_session_get_size = mlx5_crypto_sym_session_get_size,
.sym_session_configure = mlx5_crypto_sym_session_configure,
.sym_session_clear = mlx5_crypto_sym_session_clear,
@@ -11,9 +11,11 @@
#include <rte_cryptodev_pmd.h>
#include <mlx5_common_utils.h>
+#include <mlx5_common_devx.h>
#define MLX5_CRYPTO_DEK_HTABLE_SZ (1 << 11)
#define MLX5_CRYPTO_KEY_LENGTH 80
+#define MLX5_CRYPTO_WQE_SET_SIZE 1024
struct mlx5_crypto_priv {
TAILQ_ENTRY(mlx5_crypto_priv) next;
@@ -27,6 +29,15 @@ struct mlx5_crypto_priv {
struct rte_cryptodev_config dev_config;
};
+struct mlx5_crypto_qp {
+ struct mlx5_devx_cq cq_obj;
+ struct mlx5_devx_obj *qp_obj;
+ struct mlx5dv_devx_umem *umem_obj;
+ void *umem_buf;
+ volatile uint32_t *db_rec;
+ struct rte_crypto_op **ops;
+};
+
struct mlx5_crypto_dek {
struct mlx5_hlist_entry entry; /* Pointer to DEK hash list entry. */
struct mlx5_devx_obj *obj; /* Pointer to DEK DevX object. */