1832a4cf1SMatan Azrad /* SPDX-License-Identifier: BSD-3-Clause 2832a4cf1SMatan Azrad * Copyright 2021 Mellanox Technologies, Ltd 3832a4cf1SMatan Azrad */ 4832a4cf1SMatan Azrad 5832a4cf1SMatan Azrad #include <rte_malloc.h> 6832a4cf1SMatan Azrad #include <rte_log.h> 7832a4cf1SMatan Azrad #include <rte_errno.h> 81f37cb2bSDavid Marchand #include <bus_pci_driver.h> 939a2c871SMatan Azrad #include <rte_spinlock.h> 10832a4cf1SMatan Azrad #include <rte_comp.h> 11832a4cf1SMatan Azrad #include <rte_compressdev.h> 12832a4cf1SMatan Azrad #include <rte_compressdev_pmd.h> 13832a4cf1SMatan Azrad 14832a4cf1SMatan Azrad #include <mlx5_glue.h> 15832a4cf1SMatan Azrad #include <mlx5_common.h> 16832a4cf1SMatan Azrad #include <mlx5_devx_cmds.h> 17832a4cf1SMatan Azrad #include <mlx5_common_os.h> 188619fcd5SMatan Azrad #include <mlx5_common_devx.h> 198619fcd5SMatan Azrad #include <mlx5_common_mr.h> 20832a4cf1SMatan Azrad #include <mlx5_prm.h> 21832a4cf1SMatan Azrad 22832a4cf1SMatan Azrad #include "mlx5_compress_utils.h" 23832a4cf1SMatan Azrad 24832a4cf1SMatan Azrad #define MLX5_COMPRESS_DRIVER_NAME mlx5_compress 25fefca160SMatan Azrad #define MLX5_COMPRESS_MAX_QPS 1024 2639a2c871SMatan Azrad #define MLX5_COMP_MAX_WIN_SIZE_CONF 6u 27d3845f49SMichael Baum #define MLX5_COMP_NUM_SUP_ALGO 4 2839a2c871SMatan Azrad 29350e25faSRaja Zidane struct mlx5_compress_devarg_params { 30350e25faSRaja Zidane uint32_t log_block_sz; 31350e25faSRaja Zidane }; 32350e25faSRaja Zidane 3339a2c871SMatan Azrad struct mlx5_compress_xform { 3439a2c871SMatan Azrad LIST_ENTRY(mlx5_compress_xform) next; 3539a2c871SMatan Azrad enum rte_comp_xform_type type; 3639a2c871SMatan Azrad enum rte_comp_checksum_type csum_type; 3739a2c871SMatan Azrad uint32_t opcode; 3839a2c871SMatan Azrad uint32_t gga_ctrl1; /* BE. */ 3939a2c871SMatan Azrad }; 40832a4cf1SMatan Azrad 41832a4cf1SMatan Azrad struct mlx5_compress_priv { 42832a4cf1SMatan Azrad TAILQ_ENTRY(mlx5_compress_priv) next; 437af08c8fSMichael Baum struct rte_compressdev *compressdev; 44ca1418ceSMichael Baum struct mlx5_common_device *cdev; /* Backend mlx5 device. */ 455dfa003dSMichael Baum struct mlx5_uar uar; 46fefca160SMatan Azrad struct rte_compressdev_config dev_config; 47d3845f49SMichael Baum struct rte_compressdev_capabilities caps[MLX5_COMP_NUM_SUP_ALGO]; 4839a2c871SMatan Azrad LIST_HEAD(xform_list, mlx5_compress_xform) xform_list; 4939a2c871SMatan Azrad rte_spinlock_t xform_sl; 50350e25faSRaja Zidane uint32_t log_block_sz; 518b3a69fbSMichael Baum uint32_t crc32_opaq_offs; 52832a4cf1SMatan Azrad }; 53832a4cf1SMatan Azrad 548619fcd5SMatan Azrad struct mlx5_compress_qp { 558619fcd5SMatan Azrad uint16_t qp_id; 568619fcd5SMatan Azrad uint16_t entries_n; 578619fcd5SMatan Azrad uint16_t pi; 588619fcd5SMatan Azrad uint16_t ci; 590165bccdSMatan Azrad struct mlx5_mr_ctrl mr_ctrl; 608619fcd5SMatan Azrad int socket_id; 618619fcd5SMatan Azrad struct mlx5_devx_cq cq; 62bab51810SRaja Zidane struct mlx5_devx_qp qp; 638619fcd5SMatan Azrad struct mlx5_pmd_mr opaque_mr; 648619fcd5SMatan Azrad struct rte_comp_op **ops; 658619fcd5SMatan Azrad struct mlx5_compress_priv *priv; 66ccfd891aSMatan Azrad struct rte_compressdev_stats stats; 678619fcd5SMatan Azrad }; 688619fcd5SMatan Azrad 69832a4cf1SMatan Azrad TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list = 70832a4cf1SMatan Azrad TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list); 71832a4cf1SMatan Azrad static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER; 72832a4cf1SMatan Azrad 73832a4cf1SMatan Azrad int mlx5_compress_logtype; 74832a4cf1SMatan Azrad 75fefca160SMatan Azrad static void 76fefca160SMatan Azrad mlx5_compress_dev_info_get(struct rte_compressdev *dev, 77fefca160SMatan Azrad struct rte_compressdev_info *info) 78fefca160SMatan Azrad { 79d3845f49SMichael Baum if (dev != NULL && info != NULL) { 80d3845f49SMichael Baum struct mlx5_compress_priv *priv = dev->data->dev_private; 81d3845f49SMichael Baum 82fefca160SMatan Azrad info->max_nb_queue_pairs = MLX5_COMPRESS_MAX_QPS; 83fefca160SMatan Azrad info->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED; 84d3845f49SMichael Baum info->capabilities = priv->caps; 85fefca160SMatan Azrad } 86fefca160SMatan Azrad } 87fefca160SMatan Azrad 88fefca160SMatan Azrad static int 89fefca160SMatan Azrad mlx5_compress_dev_configure(struct rte_compressdev *dev, 90fefca160SMatan Azrad struct rte_compressdev_config *config) 91fefca160SMatan Azrad { 92fefca160SMatan Azrad struct mlx5_compress_priv *priv; 93fefca160SMatan Azrad 94fefca160SMatan Azrad if (dev == NULL || config == NULL) 95fefca160SMatan Azrad return -EINVAL; 96fefca160SMatan Azrad priv = dev->data->dev_private; 97fefca160SMatan Azrad priv->dev_config = *config; 98fefca160SMatan Azrad return 0; 99fefca160SMatan Azrad } 100fefca160SMatan Azrad 101fefca160SMatan Azrad static int 102fefca160SMatan Azrad mlx5_compress_dev_close(struct rte_compressdev *dev) 103fefca160SMatan Azrad { 104fefca160SMatan Azrad RTE_SET_USED(dev); 105fefca160SMatan Azrad return 0; 106fefca160SMatan Azrad } 107fefca160SMatan Azrad 1088619fcd5SMatan Azrad static int 1098619fcd5SMatan Azrad mlx5_compress_qp_release(struct rte_compressdev *dev, uint16_t qp_id) 1108619fcd5SMatan Azrad { 1118619fcd5SMatan Azrad struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id]; 1128619fcd5SMatan Azrad 113bab51810SRaja Zidane if (qp->qp.qp != NULL) 114bab51810SRaja Zidane mlx5_devx_qp_destroy(&qp->qp); 1158619fcd5SMatan Azrad if (qp->cq.cq != NULL) 1168619fcd5SMatan Azrad mlx5_devx_cq_destroy(&qp->cq); 1178619fcd5SMatan Azrad if (qp->opaque_mr.obj != NULL) { 1188619fcd5SMatan Azrad void *opaq = qp->opaque_mr.addr; 1198619fcd5SMatan Azrad 1208619fcd5SMatan Azrad mlx5_common_verbs_dereg_mr(&qp->opaque_mr); 1218619fcd5SMatan Azrad rte_free(opaq); 1228619fcd5SMatan Azrad } 1230165bccdSMatan Azrad mlx5_mr_btree_free(&qp->mr_ctrl.cache_bh); 1248619fcd5SMatan Azrad rte_free(qp); 1258619fcd5SMatan Azrad dev->data->queue_pairs[qp_id] = NULL; 1268619fcd5SMatan Azrad return 0; 1278619fcd5SMatan Azrad } 1288619fcd5SMatan Azrad 1298619fcd5SMatan Azrad static void 130bab51810SRaja Zidane mlx5_compress_init_qp(struct mlx5_compress_qp *qp) 1318619fcd5SMatan Azrad { 1328619fcd5SMatan Azrad volatile struct mlx5_gga_wqe *restrict wqe = 133bab51810SRaja Zidane (volatile struct mlx5_gga_wqe *)qp->qp.wqes; 1348b3a69fbSMichael Baum volatile union mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr; 135bab51810SRaja Zidane const uint32_t sq_ds = rte_cpu_to_be_32((qp->qp.qp->id << 8) | 4u); 1368619fcd5SMatan Azrad const uint32_t flags = RTE_BE32(MLX5_COMP_ALWAYS << 1378619fcd5SMatan Azrad MLX5_COMP_MODE_OFFSET); 1388619fcd5SMatan Azrad const uint32_t opaq_lkey = rte_cpu_to_be_32(qp->opaque_mr.lkey); 1398619fcd5SMatan Azrad int i; 1408619fcd5SMatan Azrad 1418619fcd5SMatan Azrad /* All the next fields state should stay constant. */ 1428619fcd5SMatan Azrad for (i = 0; i < qp->entries_n; ++i, ++wqe) { 1438619fcd5SMatan Azrad wqe->sq_ds = sq_ds; 1448619fcd5SMatan Azrad wqe->flags = flags; 1458619fcd5SMatan Azrad wqe->opaque_lkey = opaq_lkey; 1468619fcd5SMatan Azrad wqe->opaque_vaddr = rte_cpu_to_be_64 1478619fcd5SMatan Azrad ((uint64_t)(uintptr_t)&opaq[i]); 1488619fcd5SMatan Azrad } 1498619fcd5SMatan Azrad } 1508619fcd5SMatan Azrad 1518619fcd5SMatan Azrad static int 1528619fcd5SMatan Azrad mlx5_compress_qp_setup(struct rte_compressdev *dev, uint16_t qp_id, 1538619fcd5SMatan Azrad uint32_t max_inflight_ops, int socket_id) 1548619fcd5SMatan Azrad { 1558619fcd5SMatan Azrad struct mlx5_compress_priv *priv = dev->data->dev_private; 156569412e4SMichael Baum struct mlx5_hca_attr *attr = &priv->cdev->config.hca_attr; 1578619fcd5SMatan Azrad struct mlx5_compress_qp *qp; 1588619fcd5SMatan Azrad struct mlx5_devx_cq_attr cq_attr = { 1595dfa003dSMichael Baum .uar_page_id = mlx5_os_get_devx_uar_page_id(priv->uar.obj), 1608619fcd5SMatan Azrad }; 161bab51810SRaja Zidane struct mlx5_devx_qp_attr qp_attr = { 162e35ccf24SMichael Baum .pd = priv->cdev->pdn, 1635dfa003dSMichael Baum .uar_index = mlx5_os_get_devx_uar_page_id(priv->uar.obj), 164bab51810SRaja Zidane .user_index = qp_id, 1658619fcd5SMatan Azrad }; 1668619fcd5SMatan Azrad uint32_t log_ops_n = rte_log2_u32(max_inflight_ops); 1678619fcd5SMatan Azrad uint32_t alloc_size = sizeof(*qp); 1688619fcd5SMatan Azrad void *opaq_buf; 1698619fcd5SMatan Azrad int ret; 1708619fcd5SMatan Azrad 1718619fcd5SMatan Azrad alloc_size = RTE_ALIGN(alloc_size, RTE_CACHE_LINE_SIZE); 1728619fcd5SMatan Azrad alloc_size += sizeof(struct rte_comp_op *) * (1u << log_ops_n); 1738619fcd5SMatan Azrad qp = rte_zmalloc_socket(__func__, alloc_size, RTE_CACHE_LINE_SIZE, 1748619fcd5SMatan Azrad socket_id); 1758619fcd5SMatan Azrad if (qp == NULL) { 1768619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to allocate qp memory."); 1778619fcd5SMatan Azrad rte_errno = ENOMEM; 1788619fcd5SMatan Azrad return -rte_errno; 1798619fcd5SMatan Azrad } 1808619fcd5SMatan Azrad dev->data->queue_pairs[qp_id] = qp; 18171304b5cSMichael Baum if (mlx5_mr_ctrl_init(&qp->mr_ctrl, &priv->cdev->mr_scache.dev_gen, 18212b253eeSMichael Baum priv->dev_config.socket_id)) { 18312b253eeSMichael Baum DRV_LOG(ERR, "Cannot allocate MR Btree for qp %u.", 18412b253eeSMichael Baum (uint32_t)qp_id); 18512b253eeSMichael Baum rte_errno = ENOMEM; 18612b253eeSMichael Baum goto err; 18712b253eeSMichael Baum } 188c87bc83aSMichael Baum opaq_buf = rte_calloc(__func__, (size_t)1 << log_ops_n, 1898b3a69fbSMichael Baum sizeof(union mlx5_gga_compress_opaque), 1908b3a69fbSMichael Baum sizeof(union mlx5_gga_compress_opaque)); 1918619fcd5SMatan Azrad if (opaq_buf == NULL) { 1928619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to allocate opaque memory."); 1938619fcd5SMatan Azrad rte_errno = ENOMEM; 1948619fcd5SMatan Azrad goto err; 1958619fcd5SMatan Azrad } 1968619fcd5SMatan Azrad qp->entries_n = 1 << log_ops_n; 1978619fcd5SMatan Azrad qp->socket_id = socket_id; 1988619fcd5SMatan Azrad qp->qp_id = qp_id; 1998619fcd5SMatan Azrad qp->priv = priv; 2008619fcd5SMatan Azrad qp->ops = (struct rte_comp_op **)RTE_ALIGN((uintptr_t)(qp + 1), 2018619fcd5SMatan Azrad RTE_CACHE_LINE_SIZE); 202e35ccf24SMichael Baum if (mlx5_common_verbs_reg_mr(priv->cdev->pd, opaq_buf, qp->entries_n * 2038b3a69fbSMichael Baum sizeof(union mlx5_gga_compress_opaque), 2048619fcd5SMatan Azrad &qp->opaque_mr) != 0) { 2058619fcd5SMatan Azrad rte_free(opaq_buf); 2068619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to register opaque MR."); 2078619fcd5SMatan Azrad rte_errno = ENOMEM; 2088619fcd5SMatan Azrad goto err; 2098619fcd5SMatan Azrad } 210ca1418ceSMichael Baum ret = mlx5_devx_cq_create(priv->cdev->ctx, &qp->cq, log_ops_n, &cq_attr, 2118619fcd5SMatan Azrad socket_id); 2128619fcd5SMatan Azrad if (ret != 0) { 2138619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to create CQ."); 2148619fcd5SMatan Azrad goto err; 2158619fcd5SMatan Azrad } 216bab51810SRaja Zidane qp_attr.cqn = qp->cq.cq->id; 217569412e4SMichael Baum qp_attr.ts_format = mlx5_ts_format_conv(attr->qp_ts_format); 218ba707cdbSRaja Zidane qp_attr.num_of_receive_wqes = 0; 219ba707cdbSRaja Zidane qp_attr.num_of_send_wqbbs = RTE_BIT32(log_ops_n); 220569412e4SMichael Baum qp_attr.mmo = attr->mmo_compress_qp_en || attr->mmo_dma_qp_en || 221d3845f49SMichael Baum attr->decomp_lz4_checksum_en || 222d3845f49SMichael Baum attr->decomp_lz4_no_checksum_en || 223569412e4SMichael Baum attr->decomp_deflate_v1_en || attr->decomp_deflate_v2_en; 224bba8281dSRaja Zidane ret = mlx5_devx_qp_create(priv->cdev->ctx, &qp->qp, 225bba8281dSRaja Zidane qp_attr.num_of_send_wqbbs * 226bba8281dSRaja Zidane MLX5_WQE_SIZE, &qp_attr, socket_id); 2278619fcd5SMatan Azrad if (ret != 0) { 228bab51810SRaja Zidane DRV_LOG(ERR, "Failed to create QP."); 2298619fcd5SMatan Azrad goto err; 2308619fcd5SMatan Azrad } 231bab51810SRaja Zidane mlx5_compress_init_qp(qp); 232bab51810SRaja Zidane ret = mlx5_devx_qp2rts(&qp->qp, 0); 233bab51810SRaja Zidane if (ret) 2348619fcd5SMatan Azrad goto err; 2351b9e9826SThomas Monjalon DRV_LOG(INFO, "QP %u: SQN=0x%X CQN=0x%X entries num = %u", 236bab51810SRaja Zidane (uint32_t)qp_id, qp->qp.qp->id, qp->cq.cq->id, qp->entries_n); 2378619fcd5SMatan Azrad return 0; 2388619fcd5SMatan Azrad err: 2398619fcd5SMatan Azrad mlx5_compress_qp_release(dev, qp_id); 2408619fcd5SMatan Azrad return -1; 2418619fcd5SMatan Azrad } 2428619fcd5SMatan Azrad 24339a2c871SMatan Azrad static int 24439a2c871SMatan Azrad mlx5_compress_xform_free(struct rte_compressdev *dev, void *xform) 24539a2c871SMatan Azrad { 24639a2c871SMatan Azrad struct mlx5_compress_priv *priv = dev->data->dev_private; 24739a2c871SMatan Azrad 24839a2c871SMatan Azrad rte_spinlock_lock(&priv->xform_sl); 24939a2c871SMatan Azrad LIST_REMOVE((struct mlx5_compress_xform *)xform, next); 25039a2c871SMatan Azrad rte_spinlock_unlock(&priv->xform_sl); 25139a2c871SMatan Azrad rte_free(xform); 25239a2c871SMatan Azrad return 0; 25339a2c871SMatan Azrad } 25439a2c871SMatan Azrad 25539a2c871SMatan Azrad static int 256569412e4SMichael Baum mlx5_compress_xform_validate(const struct rte_comp_xform *xform, 257569412e4SMichael Baum const struct mlx5_hca_attr *attr) 25839a2c871SMatan Azrad { 2592efd2654SRaja Zidane switch (xform->type) { 2602efd2654SRaja Zidane case RTE_COMP_COMPRESS: 2612efd2654SRaja Zidane if (xform->compress.algo == RTE_COMP_ALGO_NULL && 262569412e4SMichael Baum !attr->mmo_dma_qp_en && !attr->mmo_dma_sq_en) { 2632efd2654SRaja Zidane DRV_LOG(ERR, "Not enough capabilities to support DMA operation, maybe old FW/OFED version?"); 2642efd2654SRaja Zidane return -ENOTSUP; 265569412e4SMichael Baum } else if (!attr->mmo_compress_qp_en && 266569412e4SMichael Baum !attr->mmo_compress_sq_en) { 267d3845f49SMichael Baum DRV_LOG(ERR, "Not enough capabilities to support compress operation."); 268d3845f49SMichael Baum return -ENOTSUP; 269d3845f49SMichael Baum } 270d3845f49SMichael Baum if (xform->compress.algo == RTE_COMP_ALGO_LZ4) { 271d3845f49SMichael Baum DRV_LOG(ERR, "LZ4 compression is not supported."); 2722efd2654SRaja Zidane return -ENOTSUP; 2732efd2654SRaja Zidane } 2742efd2654SRaja Zidane if (xform->compress.level == RTE_COMP_LEVEL_NONE) { 27539a2c871SMatan Azrad DRV_LOG(ERR, "Non-compressed block is not supported."); 27639a2c871SMatan Azrad return -ENOTSUP; 27739a2c871SMatan Azrad } 2782efd2654SRaja Zidane if (xform->compress.hash_algo != RTE_COMP_HASH_ALGO_NONE) { 27939a2c871SMatan Azrad DRV_LOG(ERR, "SHA is not supported."); 28039a2c871SMatan Azrad return -ENOTSUP; 28139a2c871SMatan Azrad } 282d3845f49SMichael Baum if (xform->compress.chksum == RTE_COMP_CHECKSUM_XXHASH32) { 283d3845f49SMichael Baum DRV_LOG(ERR, "xxHash32 checksum isn't supported in compress operation."); 284d3845f49SMichael Baum return -ENOTSUP; 285d3845f49SMichael Baum } 2862efd2654SRaja Zidane break; 2872efd2654SRaja Zidane case RTE_COMP_DECOMPRESS: 288569412e4SMichael Baum switch (xform->decompress.algo) { 289569412e4SMichael Baum case RTE_COMP_ALGO_NULL: 290569412e4SMichael Baum if (!attr->mmo_dma_qp_en && !attr->mmo_dma_sq_en) { 2912efd2654SRaja Zidane DRV_LOG(ERR, "Not enough capabilities to support DMA operation, maybe old FW/OFED version?"); 2922efd2654SRaja Zidane return -ENOTSUP; 293569412e4SMichael Baum } 294569412e4SMichael Baum break; 295569412e4SMichael Baum case RTE_COMP_ALGO_DEFLATE: 296569412e4SMichael Baum if (!attr->decomp_deflate_v1_en && 297569412e4SMichael Baum !attr->decomp_deflate_v2_en && 298569412e4SMichael Baum !attr->mmo_decompress_sq_en) { 299569412e4SMichael Baum DRV_LOG(ERR, "Not enough capabilities to support decompress DEFLATE algorithm, maybe old FW/OFED version?"); 300569412e4SMichael Baum return -ENOTSUP; 301569412e4SMichael Baum } 302d3845f49SMichael Baum switch (xform->decompress.chksum) { 303d3845f49SMichael Baum case RTE_COMP_CHECKSUM_NONE: 304d3845f49SMichael Baum case RTE_COMP_CHECKSUM_CRC32: 305d3845f49SMichael Baum case RTE_COMP_CHECKSUM_ADLER32: 306d3845f49SMichael Baum case RTE_COMP_CHECKSUM_CRC32_ADLER32: 307d3845f49SMichael Baum break; 308d3845f49SMichael Baum case RTE_COMP_CHECKSUM_XXHASH32: 309d3845f49SMichael Baum default: 310d3845f49SMichael Baum DRV_LOG(ERR, "DEFLATE algorithm doesn't support %u checksum.", 311d3845f49SMichael Baum xform->decompress.chksum); 312d3845f49SMichael Baum return -ENOTSUP; 313d3845f49SMichael Baum } 314d3845f49SMichael Baum break; 315d3845f49SMichael Baum case RTE_COMP_ALGO_LZ4: 316d3845f49SMichael Baum if (!attr->decomp_lz4_no_checksum_en && 317d3845f49SMichael Baum !attr->decomp_lz4_checksum_en) { 318d3845f49SMichael Baum DRV_LOG(ERR, "Not enough capabilities to support decompress LZ4 algorithm, maybe old FW/OFED version?"); 319d3845f49SMichael Baum return -ENOTSUP; 320d3845f49SMichael Baum } 321d3845f49SMichael Baum if (xform->decompress.lz4.flags & 322d3845f49SMichael Baum RTE_COMP_LZ4_FLAG_BLOCK_CHECKSUM) { 323d3845f49SMichael Baum if (!attr->decomp_lz4_checksum_en) { 324d3845f49SMichael Baum DRV_LOG(ERR, "Not enough capabilities to support decompress LZ4 block with checksum param, maybe old FW/OFED version?"); 325d3845f49SMichael Baum return -ENOTSUP; 326d3845f49SMichael Baum } 327d3845f49SMichael Baum } else { 328d3845f49SMichael Baum if (!attr->decomp_lz4_no_checksum_en) { 329d3845f49SMichael Baum DRV_LOG(ERR, "Not enough capabilities to support decompress LZ4 block without checksum param, maybe old FW/OFED version?"); 330d3845f49SMichael Baum return -ENOTSUP; 331d3845f49SMichael Baum } 332d3845f49SMichael Baum } 333d3845f49SMichael Baum if (xform->decompress.chksum != 334d3845f49SMichael Baum RTE_COMP_CHECKSUM_XXHASH32 && 335d3845f49SMichael Baum xform->decompress.chksum != 336d3845f49SMichael Baum RTE_COMP_CHECKSUM_NONE) { 337d3845f49SMichael Baum DRV_LOG(ERR, "LZ4 algorithm supports only xxHash32 checksum."); 338d3845f49SMichael Baum return -ENOTSUP; 339d3845f49SMichael Baum } 340569412e4SMichael Baum break; 341569412e4SMichael Baum default: 342569412e4SMichael Baum DRV_LOG(ERR, "Algorithm %u is not supported.", 343569412e4SMichael Baum xform->decompress.algo); 3442efd2654SRaja Zidane return -ENOTSUP; 3452efd2654SRaja Zidane } 34612b4c485SMichael Baum if (xform->decompress.hash_algo != RTE_COMP_HASH_ALGO_NONE) { 3472efd2654SRaja Zidane DRV_LOG(ERR, "SHA is not supported."); 3482efd2654SRaja Zidane return -ENOTSUP; 3492efd2654SRaja Zidane } 3502efd2654SRaja Zidane break; 3512efd2654SRaja Zidane default: 3522efd2654SRaja Zidane DRV_LOG(ERR, "Xform type should be compress/decompress"); 3532efd2654SRaja Zidane return -ENOTSUP; 3542efd2654SRaja Zidane } 355569412e4SMichael Baum return 0; 356569412e4SMichael Baum } 3572efd2654SRaja Zidane 358569412e4SMichael Baum static int 359569412e4SMichael Baum mlx5_compress_xform_create(struct rte_compressdev *dev, 360569412e4SMichael Baum const struct rte_comp_xform *xform, 361569412e4SMichael Baum void **private_xform) 362569412e4SMichael Baum { 363569412e4SMichael Baum struct mlx5_compress_priv *priv = dev->data->dev_private; 364569412e4SMichael Baum struct mlx5_compress_xform *xfrm; 365569412e4SMichael Baum uint32_t size; 366569412e4SMichael Baum int ret; 367569412e4SMichael Baum 368569412e4SMichael Baum ret = mlx5_compress_xform_validate(xform, &priv->cdev->config.hca_attr); 369569412e4SMichael Baum if (ret < 0) 370569412e4SMichael Baum return ret; 37139a2c871SMatan Azrad xfrm = rte_zmalloc_socket(__func__, sizeof(*xfrm), 0, 37239a2c871SMatan Azrad priv->dev_config.socket_id); 37339a2c871SMatan Azrad if (xfrm == NULL) 37439a2c871SMatan Azrad return -ENOMEM; 37539a2c871SMatan Azrad xfrm->opcode = MLX5_OPCODE_MMO; 37639a2c871SMatan Azrad xfrm->type = xform->type; 37739a2c871SMatan Azrad switch (xform->type) { 37839a2c871SMatan Azrad case RTE_COMP_COMPRESS: 37939a2c871SMatan Azrad switch (xform->compress.algo) { 38039a2c871SMatan Azrad case RTE_COMP_ALGO_NULL: 38139a2c871SMatan Azrad xfrm->opcode += MLX5_OPC_MOD_MMO_DMA << 38239a2c871SMatan Azrad WQE_CSEG_OPC_MOD_OFFSET; 38339a2c871SMatan Azrad break; 38439a2c871SMatan Azrad case RTE_COMP_ALGO_DEFLATE: 38539a2c871SMatan Azrad size = 1 << xform->compress.window_size; 38639a2c871SMatan Azrad size /= MLX5_GGA_COMP_WIN_SIZE_UNITS; 38739a2c871SMatan Azrad xfrm->gga_ctrl1 += RTE_MIN(rte_log2_u32(size), 38839a2c871SMatan Azrad MLX5_COMP_MAX_WIN_SIZE_CONF) << 38939a2c871SMatan Azrad WQE_GGA_COMP_WIN_SIZE_OFFSET; 390350e25faSRaja Zidane size = priv->log_block_sz; 391b8871a7eSRaja Zidane xfrm->gga_ctrl1 += size << 39239a2c871SMatan Azrad WQE_GGA_COMP_BLOCK_SIZE_OFFSET; 39339a2c871SMatan Azrad xfrm->opcode += MLX5_OPC_MOD_MMO_COMP << 39439a2c871SMatan Azrad WQE_CSEG_OPC_MOD_OFFSET; 39539a2c871SMatan Azrad size = xform->compress.deflate.huffman == 39639a2c871SMatan Azrad RTE_COMP_HUFFMAN_DYNAMIC ? 39739a2c871SMatan Azrad MLX5_GGA_COMP_LOG_DYNAMIC_SIZE_MAX : 39839a2c871SMatan Azrad MLX5_GGA_COMP_LOG_DYNAMIC_SIZE_MIN; 39939a2c871SMatan Azrad xfrm->gga_ctrl1 += size << 40039a2c871SMatan Azrad WQE_GGA_COMP_DYNAMIC_SIZE_OFFSET; 40139a2c871SMatan Azrad break; 40239a2c871SMatan Azrad default: 40339a2c871SMatan Azrad goto err; 40439a2c871SMatan Azrad } 40539a2c871SMatan Azrad xfrm->csum_type = xform->compress.chksum; 40639a2c871SMatan Azrad break; 40739a2c871SMatan Azrad case RTE_COMP_DECOMPRESS: 40839a2c871SMatan Azrad switch (xform->decompress.algo) { 40939a2c871SMatan Azrad case RTE_COMP_ALGO_NULL: 41039a2c871SMatan Azrad xfrm->opcode += MLX5_OPC_MOD_MMO_DMA << 41139a2c871SMatan Azrad WQE_CSEG_OPC_MOD_OFFSET; 41239a2c871SMatan Azrad break; 41339a2c871SMatan Azrad case RTE_COMP_ALGO_DEFLATE: 41439a2c871SMatan Azrad xfrm->opcode += MLX5_OPC_MOD_MMO_DECOMP << 41539a2c871SMatan Azrad WQE_CSEG_OPC_MOD_OFFSET; 416d3845f49SMichael Baum xfrm->gga_ctrl1 += WQE_GGA_DECOMP_DEFLATE << 417d3845f49SMichael Baum WQE_GGA_DECOMP_TYPE_OFFSET; 418d3845f49SMichael Baum break; 419d3845f49SMichael Baum case RTE_COMP_ALGO_LZ4: 420d3845f49SMichael Baum xfrm->opcode += MLX5_OPC_MOD_MMO_DECOMP << 421d3845f49SMichael Baum WQE_CSEG_OPC_MOD_OFFSET; 422d3845f49SMichael Baum xfrm->gga_ctrl1 += WQE_GGA_DECOMP_LZ4 << 423d3845f49SMichael Baum WQE_GGA_DECOMP_TYPE_OFFSET; 424d3845f49SMichael Baum if (xform->decompress.lz4.flags & 425d3845f49SMichael Baum RTE_COMP_LZ4_FLAG_BLOCK_CHECKSUM) 426d3845f49SMichael Baum xfrm->gga_ctrl1 += 427d3845f49SMichael Baum MLX5_GGA_DECOMP_LZ4_BLOCK_WITH_CHECKSUM << 428d3845f49SMichael Baum WQE_GGA_DECOMP_PARAMS_OFFSET; 429d3845f49SMichael Baum else 430d3845f49SMichael Baum xfrm->gga_ctrl1 += 431d3845f49SMichael Baum MLX5_GGA_DECOMP_LZ4_BLOCK_WITHOUT_CHECKSUM 432d3845f49SMichael Baum << WQE_GGA_DECOMP_PARAMS_OFFSET; 433d3845f49SMichael Baum if (xform->decompress.lz4.flags & 434d3845f49SMichael Baum RTE_COMP_LZ4_FLAG_BLOCK_INDEPENDENCE) 435d3845f49SMichael Baum xfrm->gga_ctrl1 += 1u << 436d3845f49SMichael Baum WQE_GGA_DECOMP_BLOCK_INDEPENDENT_OFFSET; 43739a2c871SMatan Azrad break; 43839a2c871SMatan Azrad default: 43939a2c871SMatan Azrad goto err; 44039a2c871SMatan Azrad } 44139a2c871SMatan Azrad xfrm->csum_type = xform->decompress.chksum; 44239a2c871SMatan Azrad break; 44339a2c871SMatan Azrad default: 444d3845f49SMichael Baum DRV_LOG(ERR, "Operation %u is not supported.", xform->type); 44539a2c871SMatan Azrad goto err; 44639a2c871SMatan Azrad } 44739a2c871SMatan Azrad DRV_LOG(DEBUG, "New xform: gga ctrl1 = 0x%08X opcode = 0x%08X csum " 44839a2c871SMatan Azrad "type = %d.", xfrm->gga_ctrl1, xfrm->opcode, xfrm->csum_type); 44939a2c871SMatan Azrad xfrm->gga_ctrl1 = rte_cpu_to_be_32(xfrm->gga_ctrl1); 45039a2c871SMatan Azrad rte_spinlock_lock(&priv->xform_sl); 45139a2c871SMatan Azrad LIST_INSERT_HEAD(&priv->xform_list, xfrm, next); 45239a2c871SMatan Azrad rte_spinlock_unlock(&priv->xform_sl); 45339a2c871SMatan Azrad *private_xform = xfrm; 45439a2c871SMatan Azrad return 0; 45539a2c871SMatan Azrad err: 45639a2c871SMatan Azrad rte_free(xfrm); 45739a2c871SMatan Azrad return -ENOTSUP; 45839a2c871SMatan Azrad } 45939a2c871SMatan Azrad 460f8c97babSMatan Azrad static void 461f8c97babSMatan Azrad mlx5_compress_dev_stop(struct rte_compressdev *dev) 462f8c97babSMatan Azrad { 463f8c97babSMatan Azrad RTE_SET_USED(dev); 464f8c97babSMatan Azrad } 465f8c97babSMatan Azrad 466f8c97babSMatan Azrad static int 467f8c97babSMatan Azrad mlx5_compress_dev_start(struct rte_compressdev *dev) 468f8c97babSMatan Azrad { 469fc59a1ecSMichael Baum struct mlx5_compress_priv *priv = dev->data->dev_private; 470fc59a1ecSMichael Baum 471fc59a1ecSMichael Baum return mlx5_dev_mempool_subscribe(priv->cdev); 472f8c97babSMatan Azrad } 473f8c97babSMatan Azrad 474ccfd891aSMatan Azrad static void 475ccfd891aSMatan Azrad mlx5_compress_stats_get(struct rte_compressdev *dev, 476ccfd891aSMatan Azrad struct rte_compressdev_stats *stats) 477ccfd891aSMatan Azrad { 478ccfd891aSMatan Azrad int qp_id; 479ccfd891aSMatan Azrad 480ccfd891aSMatan Azrad for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) { 481ccfd891aSMatan Azrad struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id]; 482ccfd891aSMatan Azrad 483ccfd891aSMatan Azrad stats->enqueued_count += qp->stats.enqueued_count; 484ccfd891aSMatan Azrad stats->dequeued_count += qp->stats.dequeued_count; 485ccfd891aSMatan Azrad stats->enqueue_err_count += qp->stats.enqueue_err_count; 486ccfd891aSMatan Azrad stats->dequeue_err_count += qp->stats.dequeue_err_count; 487ccfd891aSMatan Azrad } 488ccfd891aSMatan Azrad } 489ccfd891aSMatan Azrad 490ccfd891aSMatan Azrad static void 491ccfd891aSMatan Azrad mlx5_compress_stats_reset(struct rte_compressdev *dev) 492ccfd891aSMatan Azrad { 493ccfd891aSMatan Azrad int qp_id; 494ccfd891aSMatan Azrad 495ccfd891aSMatan Azrad for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) { 496ccfd891aSMatan Azrad struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id]; 497ccfd891aSMatan Azrad 498ccfd891aSMatan Azrad memset(&qp->stats, 0, sizeof(qp->stats)); 499ccfd891aSMatan Azrad } 500ccfd891aSMatan Azrad } 501ccfd891aSMatan Azrad 502832a4cf1SMatan Azrad static struct rte_compressdev_ops mlx5_compress_ops = { 503fefca160SMatan Azrad .dev_configure = mlx5_compress_dev_configure, 504f8c97babSMatan Azrad .dev_start = mlx5_compress_dev_start, 505f8c97babSMatan Azrad .dev_stop = mlx5_compress_dev_stop, 506fefca160SMatan Azrad .dev_close = mlx5_compress_dev_close, 507fefca160SMatan Azrad .dev_infos_get = mlx5_compress_dev_info_get, 508ccfd891aSMatan Azrad .stats_get = mlx5_compress_stats_get, 509ccfd891aSMatan Azrad .stats_reset = mlx5_compress_stats_reset, 5108619fcd5SMatan Azrad .queue_pair_setup = mlx5_compress_qp_setup, 5118619fcd5SMatan Azrad .queue_pair_release = mlx5_compress_qp_release, 51239a2c871SMatan Azrad .private_xform_create = mlx5_compress_xform_create, 51339a2c871SMatan Azrad .private_xform_free = mlx5_compress_xform_free, 514832a4cf1SMatan Azrad .stream_create = NULL, 515832a4cf1SMatan Azrad .stream_free = NULL, 516832a4cf1SMatan Azrad }; 517832a4cf1SMatan Azrad 518f8c97babSMatan Azrad static __rte_always_inline uint32_t 519f8c97babSMatan Azrad mlx5_compress_dseg_set(struct mlx5_compress_qp *qp, 520f8c97babSMatan Azrad volatile struct mlx5_wqe_dseg *restrict dseg, 521f8c97babSMatan Azrad struct rte_mbuf *restrict mbuf, 522f8c97babSMatan Azrad uint32_t offset, uint32_t len) 523f8c97babSMatan Azrad { 524f8c97babSMatan Azrad uintptr_t addr = rte_pktmbuf_mtod_offset(mbuf, uintptr_t, offset); 525f8c97babSMatan Azrad 526f8c97babSMatan Azrad dseg->bcount = rte_cpu_to_be_32(len); 52720489176SMichael Baum dseg->lkey = mlx5_mr_mb2mr(&qp->mr_ctrl, mbuf); 528f8c97babSMatan Azrad dseg->pbuf = rte_cpu_to_be_64(addr); 529f8c97babSMatan Azrad return dseg->lkey; 530f8c97babSMatan Azrad } 531f8c97babSMatan Azrad 532f8c97babSMatan Azrad static uint16_t 533f8c97babSMatan Azrad mlx5_compress_enqueue_burst(void *queue_pair, struct rte_comp_op **ops, 534f8c97babSMatan Azrad uint16_t nb_ops) 535f8c97babSMatan Azrad { 536f8c97babSMatan Azrad struct mlx5_compress_qp *qp = queue_pair; 537f8c97babSMatan Azrad volatile struct mlx5_gga_wqe *wqes = (volatile struct mlx5_gga_wqe *) 538bab51810SRaja Zidane qp->qp.wqes, *wqe; 539f8c97babSMatan Azrad struct mlx5_compress_xform *xform; 540f8c97babSMatan Azrad struct rte_comp_op *op; 541f8c97babSMatan Azrad uint16_t mask = qp->entries_n - 1; 542f8c97babSMatan Azrad uint16_t remain = qp->entries_n - (qp->pi - qp->ci); 543f8c97babSMatan Azrad uint16_t idx; 544f8c97babSMatan Azrad bool invalid; 545f8c97babSMatan Azrad 546f8c97babSMatan Azrad if (remain < nb_ops) 547f8c97babSMatan Azrad nb_ops = remain; 548f8c97babSMatan Azrad else 549f8c97babSMatan Azrad remain = nb_ops; 550f8c97babSMatan Azrad if (unlikely(remain == 0)) 551f8c97babSMatan Azrad return 0; 552f8c97babSMatan Azrad do { 553f8c97babSMatan Azrad idx = qp->pi & mask; 554f8c97babSMatan Azrad wqe = &wqes[idx]; 555f8c97babSMatan Azrad rte_prefetch0(&wqes[(qp->pi + 1) & mask]); 556f8c97babSMatan Azrad op = *ops++; 557f8c97babSMatan Azrad xform = op->private_xform; 558f8c97babSMatan Azrad /* 559f8c97babSMatan Azrad * Check operation arguments and error cases: 560f8c97babSMatan Azrad * - Operation type must be state-less. 561f8c97babSMatan Azrad * - Compress operation flush flag must be FULL or FINAL. 562f8c97babSMatan Azrad * - Source and destination buffers must be mapped internally. 563f8c97babSMatan Azrad */ 564f8c97babSMatan Azrad invalid = op->op_type != RTE_COMP_OP_STATELESS || 565f8c97babSMatan Azrad (xform->type == RTE_COMP_COMPRESS && 566f8c97babSMatan Azrad op->flush_flag < RTE_COMP_FLUSH_FULL); 567f8c97babSMatan Azrad if (unlikely(invalid || 568f8c97babSMatan Azrad (mlx5_compress_dseg_set(qp, &wqe->gather, 569f8c97babSMatan Azrad op->m_src, 570f8c97babSMatan Azrad op->src.offset, 571f8c97babSMatan Azrad op->src.length) == 572f8c97babSMatan Azrad UINT32_MAX) || 573f8c97babSMatan Azrad (mlx5_compress_dseg_set(qp, &wqe->scatter, 574f8c97babSMatan Azrad op->m_dst, 575f8c97babSMatan Azrad op->dst.offset, 576f8c97babSMatan Azrad rte_pktmbuf_pkt_len(op->m_dst) - 577f8c97babSMatan Azrad op->dst.offset) == 578f8c97babSMatan Azrad UINT32_MAX))) { 579f8c97babSMatan Azrad op->status = invalid ? RTE_COMP_OP_STATUS_INVALID_ARGS : 580f8c97babSMatan Azrad RTE_COMP_OP_STATUS_ERROR; 581f8c97babSMatan Azrad nb_ops -= remain; 582f8c97babSMatan Azrad if (unlikely(nb_ops == 0)) 583f8c97babSMatan Azrad return 0; 584f8c97babSMatan Azrad break; 585f8c97babSMatan Azrad } 586f8c97babSMatan Azrad wqe->gga_ctrl1 = xform->gga_ctrl1; 587f8c97babSMatan Azrad wqe->opcode = rte_cpu_to_be_32(xform->opcode + (qp->pi << 8)); 588f8c97babSMatan Azrad qp->ops[idx] = op; 589f8c97babSMatan Azrad qp->pi++; 590f8c97babSMatan Azrad } while (--remain); 591ccfd891aSMatan Azrad qp->stats.enqueued_count += nb_ops; 5925dfa003dSMichael Baum mlx5_doorbell_ring(&qp->priv->uar.bf_db, *(volatile uint64_t *)wqe, 5935dfa003dSMichael Baum qp->pi, &qp->qp.db_rec[MLX5_SND_DBR], 5945dfa003dSMichael Baum !qp->priv->uar.dbnc); 595f8c97babSMatan Azrad return nb_ops; 596f8c97babSMatan Azrad } 597f8c97babSMatan Azrad 598f8c97babSMatan Azrad static void 599f8c97babSMatan Azrad mlx5_compress_dump_err_objs(volatile uint32_t *cqe, volatile uint32_t *wqe, 600f8c97babSMatan Azrad volatile uint32_t *opaq) 601f8c97babSMatan Azrad { 602f8c97babSMatan Azrad size_t i; 603f8c97babSMatan Azrad 604f8c97babSMatan Azrad DRV_LOG(ERR, "Error cqe:"); 605*3cddeba0SAlexander Kozyrev for (i = 0; i < sizeof(struct mlx5_error_cqe) >> 2; i += 4) 606f8c97babSMatan Azrad DRV_LOG(ERR, "%08X %08X %08X %08X", cqe[i], cqe[i + 1], 607f8c97babSMatan Azrad cqe[i + 2], cqe[i + 3]); 608f8c97babSMatan Azrad DRV_LOG(ERR, "\nError wqe:"); 609f8c97babSMatan Azrad for (i = 0; i < sizeof(struct mlx5_gga_wqe) >> 2; i += 4) 610f8c97babSMatan Azrad DRV_LOG(ERR, "%08X %08X %08X %08X", wqe[i], wqe[i + 1], 611f8c97babSMatan Azrad wqe[i + 2], wqe[i + 3]); 612f8c97babSMatan Azrad DRV_LOG(ERR, "\nError opaq:"); 6138b3a69fbSMichael Baum for (i = 0; i < sizeof(union mlx5_gga_compress_opaque) >> 2; i += 4) 614f8c97babSMatan Azrad DRV_LOG(ERR, "%08X %08X %08X %08X", opaq[i], opaq[i + 1], 615f8c97babSMatan Azrad opaq[i + 2], opaq[i + 3]); 616f8c97babSMatan Azrad } 617f8c97babSMatan Azrad 618f8c97babSMatan Azrad static void 619f8c97babSMatan Azrad mlx5_compress_cqe_err_handle(struct mlx5_compress_qp *qp, 620f8c97babSMatan Azrad struct rte_comp_op *op) 621f8c97babSMatan Azrad { 622f8c97babSMatan Azrad const uint32_t idx = qp->ci & (qp->entries_n - 1); 623*3cddeba0SAlexander Kozyrev volatile struct mlx5_error_cqe *cqe = (volatile struct mlx5_error_cqe *) 624f8c97babSMatan Azrad &qp->cq.cqes[idx]; 625f8c97babSMatan Azrad volatile struct mlx5_gga_wqe *wqes = (volatile struct mlx5_gga_wqe *) 626bab51810SRaja Zidane qp->qp.wqes; 6278b3a69fbSMichael Baum volatile union mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr; 628f8c97babSMatan Azrad 629d2781de6SRaja Zidane volatile uint32_t *synd_word = RTE_PTR_ADD(cqe, MLX5_ERROR_CQE_SYNDROME_OFFSET); 630d2781de6SRaja Zidane switch (*synd_word) { 631d2781de6SRaja Zidane case MLX5_GGA_COMP_OUT_OF_SPACE_SYNDROME_BE: 632d2781de6SRaja Zidane op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED; 633d2781de6SRaja Zidane DRV_LOG(DEBUG, "OUT OF SPACE error, output is bigger than dst buffer."); 634d2781de6SRaja Zidane break; 635d2781de6SRaja Zidane case MLX5_GGA_COMP_MISSING_BFINAL_SYNDROME_BE: 636d2781de6SRaja Zidane DRV_LOG(DEBUG, "The last compressed block missed the B-final flag; maybe the compressed data is not complete or garbaged?"); 637d2781de6SRaja Zidane /* fallthrough */ 638d2781de6SRaja Zidane default: 639f8c97babSMatan Azrad op->status = RTE_COMP_OP_STATUS_ERROR; 640d2781de6SRaja Zidane } 641f8c97babSMatan Azrad op->consumed = 0; 642f8c97babSMatan Azrad op->produced = 0; 643f8c97babSMatan Azrad op->output_chksum = 0; 6448b3a69fbSMichael Baum op->debug_status = rte_be_to_cpu_32(opaq[idx].syndrome) | 645f8c97babSMatan Azrad ((uint64_t)rte_be_to_cpu_32(cqe->syndrome) << 32); 646f8c97babSMatan Azrad mlx5_compress_dump_err_objs((volatile uint32_t *)cqe, 647f8c97babSMatan Azrad (volatile uint32_t *)&wqes[idx], 648f8c97babSMatan Azrad (volatile uint32_t *)&opaq[idx]); 649ccfd891aSMatan Azrad qp->stats.dequeue_err_count++; 650f8c97babSMatan Azrad } 651f8c97babSMatan Azrad 652f8c97babSMatan Azrad static uint16_t 653f8c97babSMatan Azrad mlx5_compress_dequeue_burst(void *queue_pair, struct rte_comp_op **ops, 654f8c97babSMatan Azrad uint16_t nb_ops) 655f8c97babSMatan Azrad { 656f8c97babSMatan Azrad struct mlx5_compress_qp *qp = queue_pair; 657f8c97babSMatan Azrad volatile struct mlx5_compress_xform *restrict xform; 658f8c97babSMatan Azrad volatile struct mlx5_cqe *restrict cqe; 6598b3a69fbSMichael Baum volatile union mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr; 660f8c97babSMatan Azrad struct rte_comp_op *restrict op; 661f8c97babSMatan Azrad const unsigned int cq_size = qp->entries_n; 662f8c97babSMatan Azrad const unsigned int mask = cq_size - 1; 663f8c97babSMatan Azrad uint32_t idx; 664f8c97babSMatan Azrad uint32_t next_idx = qp->ci & mask; 665f8c97babSMatan Azrad const uint16_t max = RTE_MIN((uint16_t)(qp->pi - qp->ci), nb_ops); 6668b3a69fbSMichael Baum uint32_t crc32_idx = qp->priv->crc32_opaq_offs; 667f8c97babSMatan Azrad uint16_t i = 0; 668f8c97babSMatan Azrad int ret; 669f8c97babSMatan Azrad 670f8c97babSMatan Azrad if (unlikely(max == 0)) 671f8c97babSMatan Azrad return 0; 672f8c97babSMatan Azrad do { 673f8c97babSMatan Azrad idx = next_idx; 674f8c97babSMatan Azrad next_idx = (qp->ci + 1) & mask; 675f8c97babSMatan Azrad rte_prefetch0(&qp->cq.cqes[next_idx]); 676f8c97babSMatan Azrad rte_prefetch0(qp->ops[next_idx]); 677f8c97babSMatan Azrad op = qp->ops[idx]; 678f8c97babSMatan Azrad cqe = &qp->cq.cqes[idx]; 679f8c97babSMatan Azrad ret = check_cqe(cqe, cq_size, qp->ci); 680f8c97babSMatan Azrad /* 681f8c97babSMatan Azrad * Be sure owner read is done before any other cookie field or 682f8c97babSMatan Azrad * opaque field. 683f8c97babSMatan Azrad */ 684f8c97babSMatan Azrad rte_io_rmb(); 685f8c97babSMatan Azrad if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) { 686f8c97babSMatan Azrad if (likely(ret == MLX5_CQE_STATUS_HW_OWN)) 687f8c97babSMatan Azrad break; 688f8c97babSMatan Azrad mlx5_compress_cqe_err_handle(qp, op); 689f8c97babSMatan Azrad } else { 690f8c97babSMatan Azrad xform = op->private_xform; 691f8c97babSMatan Azrad op->status = RTE_COMP_OP_STATUS_SUCCESS; 692f8c97babSMatan Azrad op->consumed = op->src.length; 693f8c97babSMatan Azrad op->produced = rte_be_to_cpu_32(cqe->byte_cnt); 694f8c97babSMatan Azrad MLX5_ASSERT(cqe->byte_cnt == 695c0249919SMatan Azrad opaq[idx].scattered_length); 696f8c97babSMatan Azrad switch (xform->csum_type) { 697f8c97babSMatan Azrad case RTE_COMP_CHECKSUM_CRC32: 698f8c97babSMatan Azrad op->output_chksum = (uint64_t)rte_be_to_cpu_32 6998b3a69fbSMichael Baum (opaq[idx].data[crc32_idx]); 700f8c97babSMatan Azrad break; 701f8c97babSMatan Azrad case RTE_COMP_CHECKSUM_ADLER32: 702f8c97babSMatan Azrad op->output_chksum = (uint64_t)rte_be_to_cpu_32 7038b3a69fbSMichael Baum (opaq[idx].data[crc32_idx + 1]); 704f8c97babSMatan Azrad break; 705f8c97babSMatan Azrad case RTE_COMP_CHECKSUM_CRC32_ADLER32: 706f8c97babSMatan Azrad op->output_chksum = (uint64_t)rte_be_to_cpu_32 7078b3a69fbSMichael Baum (opaq[idx].data[crc32_idx]) | 708f8c97babSMatan Azrad ((uint64_t)rte_be_to_cpu_32 7098b3a69fbSMichael Baum (opaq[idx].data[crc32_idx + 1]) << 32); 710f8c97babSMatan Azrad break; 711d3845f49SMichael Baum case RTE_COMP_CHECKSUM_XXHASH32: 712d3845f49SMichael Baum op->output_chksum = (uint64_t)rte_be_to_cpu_32 713d3845f49SMichael Baum (opaq[idx].v2.xxh32); 714d3845f49SMichael Baum break; 715f8c97babSMatan Azrad default: 716f8c97babSMatan Azrad break; 717f8c97babSMatan Azrad } 718f8c97babSMatan Azrad } 719f8c97babSMatan Azrad ops[i++] = op; 720f8c97babSMatan Azrad qp->ci++; 721f8c97babSMatan Azrad } while (i < max); 722f8c97babSMatan Azrad if (likely(i != 0)) { 723f8c97babSMatan Azrad rte_io_wmb(); 724f8c97babSMatan Azrad qp->cq.db_rec[0] = rte_cpu_to_be_32(qp->ci); 725ccfd891aSMatan Azrad qp->stats.dequeued_count += i; 726f8c97babSMatan Azrad } 727f8c97babSMatan Azrad return i; 728f8c97babSMatan Azrad } 729f8c97babSMatan Azrad 730832a4cf1SMatan Azrad static int 731350e25faSRaja Zidane mlx5_compress_args_check_handler(const char *key, const char *val, void *opaque) 732350e25faSRaja Zidane { 733350e25faSRaja Zidane struct mlx5_compress_devarg_params *devarg_prms = opaque; 734350e25faSRaja Zidane 735350e25faSRaja Zidane if (strcmp(key, "log-block-size") == 0) { 736350e25faSRaja Zidane errno = 0; 737350e25faSRaja Zidane devarg_prms->log_block_sz = (uint32_t)strtoul(val, NULL, 10); 738350e25faSRaja Zidane if (errno) { 739a729d2f0SMichael Baum DRV_LOG(WARNING, "%s: \"%s\" is an invalid integer.", 740a729d2f0SMichael Baum key, val); 741350e25faSRaja Zidane return -errno; 742350e25faSRaja Zidane } 743350e25faSRaja Zidane } 744350e25faSRaja Zidane return 0; 745350e25faSRaja Zidane } 746350e25faSRaja Zidane 747350e25faSRaja Zidane static int 748a729d2f0SMichael Baum mlx5_compress_handle_devargs(struct mlx5_kvargs_ctrl *mkvlist, 749350e25faSRaja Zidane struct mlx5_compress_devarg_params *devarg_prms, 750350e25faSRaja Zidane struct mlx5_hca_attr *att) 751350e25faSRaja Zidane { 752a729d2f0SMichael Baum const char **params = (const char *[]){ 753a729d2f0SMichael Baum "log-block-size", 754a729d2f0SMichael Baum NULL, 755a729d2f0SMichael Baum }; 756350e25faSRaja Zidane 757350e25faSRaja Zidane devarg_prms->log_block_sz = MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX; 758a729d2f0SMichael Baum if (mkvlist == NULL) 759350e25faSRaja Zidane return 0; 760a729d2f0SMichael Baum if (mlx5_kvargs_process(mkvlist, params, 761a729d2f0SMichael Baum mlx5_compress_args_check_handler, 762350e25faSRaja Zidane devarg_prms) != 0) { 763350e25faSRaja Zidane DRV_LOG(ERR, "Devargs handler function Failed."); 764350e25faSRaja Zidane rte_errno = EINVAL; 765350e25faSRaja Zidane return -1; 766350e25faSRaja Zidane } 767350e25faSRaja Zidane if (devarg_prms->log_block_sz > MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX || 768350e25faSRaja Zidane devarg_prms->log_block_sz < att->compress_min_block_size) { 769350e25faSRaja Zidane DRV_LOG(WARNING, "Log block size provided is out of range(" 770350e25faSRaja Zidane "%u); default it to %u.", 771350e25faSRaja Zidane devarg_prms->log_block_sz, 772350e25faSRaja Zidane MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX); 773350e25faSRaja Zidane devarg_prms->log_block_sz = MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX; 774350e25faSRaja Zidane } 775350e25faSRaja Zidane return 0; 776350e25faSRaja Zidane } 777350e25faSRaja Zidane 778d3845f49SMichael Baum static void 779d3845f49SMichael Baum mlx5_compress_fill_caps(struct mlx5_compress_priv *priv, 780d3845f49SMichael Baum const struct mlx5_hca_attr *attr) 781d3845f49SMichael Baum { 782d3845f49SMichael Baum struct rte_compressdev_capabilities caps[] = { 783d3845f49SMichael Baum { 784d3845f49SMichael Baum .algo = RTE_COMP_ALGO_NULL, 785d3845f49SMichael Baum .comp_feature_flags = RTE_COMP_FF_ADLER32_CHECKSUM | 786d3845f49SMichael Baum RTE_COMP_FF_CRC32_CHECKSUM | 787d3845f49SMichael Baum RTE_COMP_FF_CRC32_ADLER32_CHECKSUM | 788d3845f49SMichael Baum RTE_COMP_FF_SHAREABLE_PRIV_XFORM, 789d3845f49SMichael Baum }, 790d3845f49SMichael Baum { 791d3845f49SMichael Baum .algo = RTE_COMP_ALGO_DEFLATE, 792d3845f49SMichael Baum .comp_feature_flags = RTE_COMP_FF_ADLER32_CHECKSUM | 793d3845f49SMichael Baum RTE_COMP_FF_CRC32_CHECKSUM | 794d3845f49SMichael Baum RTE_COMP_FF_CRC32_ADLER32_CHECKSUM | 795d3845f49SMichael Baum RTE_COMP_FF_SHAREABLE_PRIV_XFORM | 796d3845f49SMichael Baum RTE_COMP_FF_HUFFMAN_FIXED | 797d3845f49SMichael Baum RTE_COMP_FF_HUFFMAN_DYNAMIC, 798d3845f49SMichael Baum .window_size = {.min = 10, .max = 15, .increment = 1}, 799d3845f49SMichael Baum }, 800d3845f49SMichael Baum { 801d3845f49SMichael Baum .algo = RTE_COMP_ALGO_LZ4, 802d3845f49SMichael Baum .comp_feature_flags = RTE_COMP_FF_XXHASH32_CHECKSUM | 803d3845f49SMichael Baum RTE_COMP_FF_SHAREABLE_PRIV_XFORM | 804d3845f49SMichael Baum RTE_COMP_FF_LZ4_BLOCK_INDEPENDENCE, 805d3845f49SMichael Baum .window_size = {.min = 1, .max = 15, .increment = 1}, 806d3845f49SMichael Baum }, 807d3845f49SMichael Baum RTE_COMP_END_OF_CAPABILITIES_LIST() 808d3845f49SMichael Baum }; 809d3845f49SMichael Baum priv->caps[0] = caps[0]; 810d3845f49SMichael Baum priv->caps[1] = caps[1]; 811d3845f49SMichael Baum if (attr->decomp_lz4_checksum_en || attr->decomp_lz4_no_checksum_en) { 812d3845f49SMichael Baum priv->caps[2] = caps[2]; 813d3845f49SMichael Baum if (attr->decomp_lz4_checksum_en) 814d3845f49SMichael Baum priv->caps[2].comp_feature_flags |= 815d3845f49SMichael Baum RTE_COMP_FF_LZ4_BLOCK_WITH_CHECKSUM; 816d3845f49SMichael Baum priv->caps[3] = caps[3]; 817d3845f49SMichael Baum } else 818d3845f49SMichael Baum priv->caps[2] = caps[3]; 819d3845f49SMichael Baum } 820d3845f49SMichael Baum 821350e25faSRaja Zidane static int 822a729d2f0SMichael Baum mlx5_compress_dev_probe(struct mlx5_common_device *cdev, 823a729d2f0SMichael Baum struct mlx5_kvargs_ctrl *mkvlist) 824832a4cf1SMatan Azrad { 8257af08c8fSMichael Baum struct rte_compressdev *compressdev; 826832a4cf1SMatan Azrad struct mlx5_compress_priv *priv; 827fe46b20cSMichael Baum struct mlx5_hca_attr *attr = &cdev->config.hca_attr; 828350e25faSRaja Zidane struct mlx5_compress_devarg_params devarg_prms = {0}; 829832a4cf1SMatan Azrad struct rte_compressdev_pmd_init_params init_params = { 830832a4cf1SMatan Azrad .name = "", 8317af08c8fSMichael Baum .socket_id = cdev->dev->numa_node, 832832a4cf1SMatan Azrad }; 833ca1418ceSMichael Baum const char *ibdev_name = mlx5_os_get_ctx_device_name(cdev->ctx); 8348b3a69fbSMichael Baum uint32_t crc32_opaq_offset; 835832a4cf1SMatan Azrad 836832a4cf1SMatan Azrad if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 837832a4cf1SMatan Azrad DRV_LOG(ERR, "Non-primary process type is not supported."); 838832a4cf1SMatan Azrad rte_errno = ENOTSUP; 839832a4cf1SMatan Azrad return -rte_errno; 840832a4cf1SMatan Azrad } 841d3845f49SMichael Baum if (!attr->decomp_lz4_checksum_en && !attr->decomp_lz4_no_checksum_en && 842d3845f49SMichael Baum !attr->decomp_deflate_v1_en && !attr->decomp_deflate_v2_en && 8438b3a69fbSMichael Baum !attr->mmo_decompress_sq_en && !attr->mmo_compress_qp_en && 8448b3a69fbSMichael Baum !attr->mmo_compress_sq_en && !attr->mmo_dma_qp_en && 8458b3a69fbSMichael Baum !attr->mmo_dma_sq_en) { 8462efd2654SRaja Zidane DRV_LOG(ERR, "Not enough capabilities to support compress operations, maybe old FW/OFED version?"); 847832a4cf1SMatan Azrad rte_errno = ENOTSUP; 848832a4cf1SMatan Azrad return -ENOTSUP; 849832a4cf1SMatan Azrad } 850a729d2f0SMichael Baum mlx5_compress_handle_devargs(mkvlist, &devarg_prms, attr); 851ca1418ceSMichael Baum compressdev = rte_compressdev_pmd_create(ibdev_name, cdev->dev, 852832a4cf1SMatan Azrad sizeof(*priv), &init_params); 8537af08c8fSMichael Baum if (compressdev == NULL) { 854ca1418ceSMichael Baum DRV_LOG(ERR, "Failed to create device \"%s\".", ibdev_name); 855832a4cf1SMatan Azrad return -ENODEV; 856832a4cf1SMatan Azrad } 857832a4cf1SMatan Azrad DRV_LOG(INFO, 858ca1418ceSMichael Baum "Compress device %s was created successfully.", ibdev_name); 8597af08c8fSMichael Baum compressdev->dev_ops = &mlx5_compress_ops; 8607af08c8fSMichael Baum compressdev->dequeue_burst = mlx5_compress_dequeue_burst; 8617af08c8fSMichael Baum compressdev->enqueue_burst = mlx5_compress_enqueue_burst; 8627af08c8fSMichael Baum compressdev->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED; 8637af08c8fSMichael Baum priv = compressdev->data->dev_private; 864350e25faSRaja Zidane priv->log_block_sz = devarg_prms.log_block_sz; 865d3845f49SMichael Baum if (attr->decomp_deflate_v2_en || attr->decomp_lz4_checksum_en || 866d3845f49SMichael Baum attr->decomp_lz4_no_checksum_en) 8678b3a69fbSMichael Baum crc32_opaq_offset = offsetof(union mlx5_gga_compress_opaque, 8688b3a69fbSMichael Baum v2.crc32); 8698b3a69fbSMichael Baum else 8708b3a69fbSMichael Baum crc32_opaq_offset = offsetof(union mlx5_gga_compress_opaque, 8718b3a69fbSMichael Baum v1.crc32); 8728b3a69fbSMichael Baum MLX5_ASSERT((crc32_opaq_offset % 4) == 0); 8738b3a69fbSMichael Baum priv->crc32_opaq_offs = crc32_opaq_offset / 4; 874ca1418ceSMichael Baum priv->cdev = cdev; 8757af08c8fSMichael Baum priv->compressdev = compressdev; 876d3845f49SMichael Baum mlx5_compress_fill_caps(priv, attr); 8775dfa003dSMichael Baum if (mlx5_devx_uar_prepare(cdev, &priv->uar) != 0) { 8787af08c8fSMichael Baum rte_compressdev_pmd_destroy(priv->compressdev); 879832a4cf1SMatan Azrad return -1; 880832a4cf1SMatan Azrad } 881832a4cf1SMatan Azrad pthread_mutex_lock(&priv_list_lock); 882832a4cf1SMatan Azrad TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next); 883832a4cf1SMatan Azrad pthread_mutex_unlock(&priv_list_lock); 884832a4cf1SMatan Azrad return 0; 885832a4cf1SMatan Azrad } 886832a4cf1SMatan Azrad 887832a4cf1SMatan Azrad static int 8887af08c8fSMichael Baum mlx5_compress_dev_remove(struct mlx5_common_device *cdev) 889832a4cf1SMatan Azrad { 890832a4cf1SMatan Azrad struct mlx5_compress_priv *priv = NULL; 891832a4cf1SMatan Azrad 892832a4cf1SMatan Azrad pthread_mutex_lock(&priv_list_lock); 893832a4cf1SMatan Azrad TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next) 8947af08c8fSMichael Baum if (priv->compressdev->device == cdev->dev) 895832a4cf1SMatan Azrad break; 896832a4cf1SMatan Azrad if (priv) 897832a4cf1SMatan Azrad TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next); 898832a4cf1SMatan Azrad pthread_mutex_unlock(&priv_list_lock); 899832a4cf1SMatan Azrad if (priv) { 9005dfa003dSMichael Baum mlx5_devx_uar_release(&priv->uar); 9017af08c8fSMichael Baum rte_compressdev_pmd_destroy(priv->compressdev); 902832a4cf1SMatan Azrad } 903832a4cf1SMatan Azrad return 0; 904832a4cf1SMatan Azrad } 905832a4cf1SMatan Azrad 906832a4cf1SMatan Azrad static const struct rte_pci_id mlx5_compress_pci_id_map[] = { 907832a4cf1SMatan Azrad { 908832a4cf1SMatan Azrad RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 9090a9fff95SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_BLUEFIELD2) 910832a4cf1SMatan Azrad }, 911832a4cf1SMatan Azrad { 912559014f2SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 9130a9fff95SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_BLUEFIELD3) 914559014f2SRaslan Darawsheh }, 915559014f2SRaslan Darawsheh { 9167bac80b0SMichael Baum RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 9177bac80b0SMichael Baum PCI_DEVICE_ID_MELLANOX_CONNECTXVF) 9187bac80b0SMichael Baum }, 9197bac80b0SMichael Baum { 920832a4cf1SMatan Azrad .vendor_id = 0 921832a4cf1SMatan Azrad } 922832a4cf1SMatan Azrad }; 923832a4cf1SMatan Azrad 92482242186SXueming Li static struct mlx5_class_driver mlx5_compress_driver = { 92582242186SXueming Li .drv_class = MLX5_CLASS_COMPRESS, 926832a4cf1SMatan Azrad .name = RTE_STR(MLX5_COMPRESS_DRIVER_NAME), 927832a4cf1SMatan Azrad .id_table = mlx5_compress_pci_id_map, 92882242186SXueming Li .probe = mlx5_compress_dev_probe, 92982242186SXueming Li .remove = mlx5_compress_dev_remove, 930832a4cf1SMatan Azrad }; 931832a4cf1SMatan Azrad 932832a4cf1SMatan Azrad RTE_INIT(rte_mlx5_compress_init) 933832a4cf1SMatan Azrad { 934832a4cf1SMatan Azrad mlx5_common_init(); 935832a4cf1SMatan Azrad if (mlx5_glue != NULL) 93682242186SXueming Li mlx5_class_driver_register(&mlx5_compress_driver); 937832a4cf1SMatan Azrad } 938832a4cf1SMatan Azrad 939eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(mlx5_compress_logtype, NOTICE) 940832a4cf1SMatan Azrad RTE_PMD_EXPORT_NAME(MLX5_COMPRESS_DRIVER_NAME, __COUNTER__); 941832a4cf1SMatan Azrad RTE_PMD_REGISTER_PCI_TABLE(MLX5_COMPRESS_DRIVER_NAME, mlx5_compress_pci_id_map); 942832a4cf1SMatan Azrad RTE_PMD_REGISTER_KMOD_DEP(MLX5_COMPRESS_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 943