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> 882242186SXueming Li #include <rte_bus_pci.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 2739a2c871SMatan Azrad 2839a2c871SMatan Azrad struct mlx5_compress_xform { 2939a2c871SMatan Azrad LIST_ENTRY(mlx5_compress_xform) next; 3039a2c871SMatan Azrad enum rte_comp_xform_type type; 3139a2c871SMatan Azrad enum rte_comp_checksum_type csum_type; 3239a2c871SMatan Azrad uint32_t opcode; 3339a2c871SMatan Azrad uint32_t gga_ctrl1; /* BE. */ 3439a2c871SMatan Azrad }; 35832a4cf1SMatan Azrad 36832a4cf1SMatan Azrad struct mlx5_compress_priv { 37832a4cf1SMatan Azrad TAILQ_ENTRY(mlx5_compress_priv) next; 38832a4cf1SMatan Azrad struct ibv_context *ctx; /* Device context. */ 39832a4cf1SMatan Azrad struct rte_compressdev *cdev; 40832a4cf1SMatan Azrad void *uar; 41832a4cf1SMatan Azrad uint32_t pdn; /* Protection Domain number. */ 42832a4cf1SMatan Azrad uint8_t min_block_size; 4310787aa2SViacheslav Ovsiienko uint8_t sq_ts_format; /* Whether SQ supports timestamp formats. */ 44832a4cf1SMatan Azrad /* Minimum huffman block size supported by the device. */ 45832a4cf1SMatan Azrad struct ibv_pd *pd; 46fefca160SMatan Azrad struct rte_compressdev_config dev_config; 4739a2c871SMatan Azrad LIST_HEAD(xform_list, mlx5_compress_xform) xform_list; 4839a2c871SMatan Azrad rte_spinlock_t xform_sl; 490165bccdSMatan Azrad struct mlx5_mr_share_cache mr_scache; /* Global shared MR cache. */ 5037862dafSMatan Azrad volatile uint64_t *uar_addr; 5137862dafSMatan Azrad #ifndef RTE_ARCH_64 5237862dafSMatan Azrad rte_spinlock_t uar32_sl; 5337862dafSMatan Azrad #endif /* RTE_ARCH_64 */ 54832a4cf1SMatan Azrad }; 55832a4cf1SMatan Azrad 568619fcd5SMatan Azrad struct mlx5_compress_qp { 578619fcd5SMatan Azrad uint16_t qp_id; 588619fcd5SMatan Azrad uint16_t entries_n; 598619fcd5SMatan Azrad uint16_t pi; 608619fcd5SMatan Azrad uint16_t ci; 610165bccdSMatan Azrad struct mlx5_mr_ctrl mr_ctrl; 628619fcd5SMatan Azrad int socket_id; 638619fcd5SMatan Azrad struct mlx5_devx_cq cq; 648619fcd5SMatan Azrad struct mlx5_devx_sq sq; 658619fcd5SMatan Azrad struct mlx5_pmd_mr opaque_mr; 668619fcd5SMatan Azrad struct rte_comp_op **ops; 678619fcd5SMatan Azrad struct mlx5_compress_priv *priv; 68ccfd891aSMatan Azrad struct rte_compressdev_stats stats; 698619fcd5SMatan Azrad }; 708619fcd5SMatan Azrad 71832a4cf1SMatan Azrad TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list = 72832a4cf1SMatan Azrad TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list); 73832a4cf1SMatan Azrad static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER; 74832a4cf1SMatan Azrad 75832a4cf1SMatan Azrad int mlx5_compress_logtype; 76832a4cf1SMatan Azrad 77384bac8dSMatan Azrad static const struct rte_compressdev_capabilities mlx5_caps[] = { 78384bac8dSMatan Azrad { 79384bac8dSMatan Azrad .algo = RTE_COMP_ALGO_NULL, 80384bac8dSMatan Azrad .comp_feature_flags = RTE_COMP_FF_ADLER32_CHECKSUM | 81384bac8dSMatan Azrad RTE_COMP_FF_CRC32_CHECKSUM | 82384bac8dSMatan Azrad RTE_COMP_FF_CRC32_ADLER32_CHECKSUM | 83384bac8dSMatan Azrad RTE_COMP_FF_SHAREABLE_PRIV_XFORM, 84384bac8dSMatan Azrad }, 85384bac8dSMatan Azrad { 86384bac8dSMatan Azrad .algo = RTE_COMP_ALGO_DEFLATE, 87384bac8dSMatan Azrad .comp_feature_flags = RTE_COMP_FF_ADLER32_CHECKSUM | 88384bac8dSMatan Azrad RTE_COMP_FF_CRC32_CHECKSUM | 89384bac8dSMatan Azrad RTE_COMP_FF_CRC32_ADLER32_CHECKSUM | 90384bac8dSMatan Azrad RTE_COMP_FF_SHAREABLE_PRIV_XFORM | 91384bac8dSMatan Azrad RTE_COMP_FF_HUFFMAN_FIXED | 92384bac8dSMatan Azrad RTE_COMP_FF_HUFFMAN_DYNAMIC, 93384bac8dSMatan Azrad .window_size = {.min = 10, .max = 15, .increment = 1}, 94384bac8dSMatan Azrad }, 95384bac8dSMatan Azrad { 96384bac8dSMatan Azrad .algo = RTE_COMP_ALGO_LIST_END, 97384bac8dSMatan Azrad } 98384bac8dSMatan Azrad }; 99fefca160SMatan Azrad 100fefca160SMatan Azrad static void 101fefca160SMatan Azrad mlx5_compress_dev_info_get(struct rte_compressdev *dev, 102fefca160SMatan Azrad struct rte_compressdev_info *info) 103fefca160SMatan Azrad { 104fefca160SMatan Azrad RTE_SET_USED(dev); 105fefca160SMatan Azrad if (info != NULL) { 106fefca160SMatan Azrad info->max_nb_queue_pairs = MLX5_COMPRESS_MAX_QPS; 107fefca160SMatan Azrad info->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED; 108fefca160SMatan Azrad info->capabilities = mlx5_caps; 109fefca160SMatan Azrad } 110fefca160SMatan Azrad } 111fefca160SMatan Azrad 112fefca160SMatan Azrad static int 113fefca160SMatan Azrad mlx5_compress_dev_configure(struct rte_compressdev *dev, 114fefca160SMatan Azrad struct rte_compressdev_config *config) 115fefca160SMatan Azrad { 116fefca160SMatan Azrad struct mlx5_compress_priv *priv; 117fefca160SMatan Azrad 118fefca160SMatan Azrad if (dev == NULL || config == NULL) 119fefca160SMatan Azrad return -EINVAL; 120fefca160SMatan Azrad priv = dev->data->dev_private; 121fefca160SMatan Azrad priv->dev_config = *config; 122fefca160SMatan Azrad return 0; 123fefca160SMatan Azrad } 124fefca160SMatan Azrad 125fefca160SMatan Azrad static int 126fefca160SMatan Azrad mlx5_compress_dev_close(struct rte_compressdev *dev) 127fefca160SMatan Azrad { 128fefca160SMatan Azrad RTE_SET_USED(dev); 129fefca160SMatan Azrad return 0; 130fefca160SMatan Azrad } 131fefca160SMatan Azrad 1328619fcd5SMatan Azrad static int 1338619fcd5SMatan Azrad mlx5_compress_qp_release(struct rte_compressdev *dev, uint16_t qp_id) 1348619fcd5SMatan Azrad { 1358619fcd5SMatan Azrad struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id]; 1368619fcd5SMatan Azrad 1378619fcd5SMatan Azrad if (qp->sq.sq != NULL) 1388619fcd5SMatan Azrad mlx5_devx_sq_destroy(&qp->sq); 1398619fcd5SMatan Azrad if (qp->cq.cq != NULL) 1408619fcd5SMatan Azrad mlx5_devx_cq_destroy(&qp->cq); 1418619fcd5SMatan Azrad if (qp->opaque_mr.obj != NULL) { 1428619fcd5SMatan Azrad void *opaq = qp->opaque_mr.addr; 1438619fcd5SMatan Azrad 1448619fcd5SMatan Azrad mlx5_common_verbs_dereg_mr(&qp->opaque_mr); 1458619fcd5SMatan Azrad if (opaq != NULL) 1468619fcd5SMatan Azrad rte_free(opaq); 1478619fcd5SMatan Azrad } 1480165bccdSMatan Azrad mlx5_mr_btree_free(&qp->mr_ctrl.cache_bh); 1498619fcd5SMatan Azrad rte_free(qp); 1508619fcd5SMatan Azrad dev->data->queue_pairs[qp_id] = NULL; 1518619fcd5SMatan Azrad return 0; 1528619fcd5SMatan Azrad } 1538619fcd5SMatan Azrad 1548619fcd5SMatan Azrad static void 1558619fcd5SMatan Azrad mlx5_compress_init_sq(struct mlx5_compress_qp *qp) 1568619fcd5SMatan Azrad { 1578619fcd5SMatan Azrad volatile struct mlx5_gga_wqe *restrict wqe = 1588619fcd5SMatan Azrad (volatile struct mlx5_gga_wqe *)qp->sq.wqes; 1598619fcd5SMatan Azrad volatile struct mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr; 1608619fcd5SMatan Azrad const uint32_t sq_ds = rte_cpu_to_be_32((qp->sq.sq->id << 8) | 4u); 1618619fcd5SMatan Azrad const uint32_t flags = RTE_BE32(MLX5_COMP_ALWAYS << 1628619fcd5SMatan Azrad MLX5_COMP_MODE_OFFSET); 1638619fcd5SMatan Azrad const uint32_t opaq_lkey = rte_cpu_to_be_32(qp->opaque_mr.lkey); 1648619fcd5SMatan Azrad int i; 1658619fcd5SMatan Azrad 1668619fcd5SMatan Azrad /* All the next fields state should stay constant. */ 1678619fcd5SMatan Azrad for (i = 0; i < qp->entries_n; ++i, ++wqe) { 1688619fcd5SMatan Azrad wqe->sq_ds = sq_ds; 1698619fcd5SMatan Azrad wqe->flags = flags; 1708619fcd5SMatan Azrad wqe->opaque_lkey = opaq_lkey; 1718619fcd5SMatan Azrad wqe->opaque_vaddr = rte_cpu_to_be_64 1728619fcd5SMatan Azrad ((uint64_t)(uintptr_t)&opaq[i]); 1738619fcd5SMatan Azrad } 1748619fcd5SMatan Azrad } 1758619fcd5SMatan Azrad 1768619fcd5SMatan Azrad static int 1778619fcd5SMatan Azrad mlx5_compress_qp_setup(struct rte_compressdev *dev, uint16_t qp_id, 1788619fcd5SMatan Azrad uint32_t max_inflight_ops, int socket_id) 1798619fcd5SMatan Azrad { 1808619fcd5SMatan Azrad struct mlx5_compress_priv *priv = dev->data->dev_private; 1818619fcd5SMatan Azrad struct mlx5_compress_qp *qp; 1828619fcd5SMatan Azrad struct mlx5_devx_cq_attr cq_attr = { 1838619fcd5SMatan Azrad .uar_page_id = mlx5_os_get_devx_uar_page_id(priv->uar), 1848619fcd5SMatan Azrad }; 1858619fcd5SMatan Azrad struct mlx5_devx_create_sq_attr sq_attr = { 1868619fcd5SMatan Azrad .user_index = qp_id, 1878619fcd5SMatan Azrad .wq_attr = (struct mlx5_devx_wq_attr){ 1888619fcd5SMatan Azrad .pd = priv->pdn, 1898619fcd5SMatan Azrad .uar_page = mlx5_os_get_devx_uar_page_id(priv->uar), 1908619fcd5SMatan Azrad }, 1918619fcd5SMatan Azrad }; 1928619fcd5SMatan Azrad struct mlx5_devx_modify_sq_attr modify_attr = { 1938619fcd5SMatan Azrad .state = MLX5_SQC_STATE_RDY, 1948619fcd5SMatan Azrad }; 1958619fcd5SMatan Azrad uint32_t log_ops_n = rte_log2_u32(max_inflight_ops); 1968619fcd5SMatan Azrad uint32_t alloc_size = sizeof(*qp); 1978619fcd5SMatan Azrad void *opaq_buf; 1988619fcd5SMatan Azrad int ret; 1998619fcd5SMatan Azrad 2008619fcd5SMatan Azrad alloc_size = RTE_ALIGN(alloc_size, RTE_CACHE_LINE_SIZE); 2018619fcd5SMatan Azrad alloc_size += sizeof(struct rte_comp_op *) * (1u << log_ops_n); 2028619fcd5SMatan Azrad qp = rte_zmalloc_socket(__func__, alloc_size, RTE_CACHE_LINE_SIZE, 2038619fcd5SMatan Azrad socket_id); 2048619fcd5SMatan Azrad if (qp == NULL) { 2058619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to allocate qp memory."); 2068619fcd5SMatan Azrad rte_errno = ENOMEM; 2078619fcd5SMatan Azrad return -rte_errno; 2088619fcd5SMatan Azrad } 2098619fcd5SMatan Azrad dev->data->queue_pairs[qp_id] = qp; 210*12b253eeSMichael Baum if (mlx5_mr_btree_init(&qp->mr_ctrl.cache_bh, MLX5_MR_BTREE_CACHE_N, 211*12b253eeSMichael Baum priv->dev_config.socket_id)) { 212*12b253eeSMichael Baum DRV_LOG(ERR, "Cannot allocate MR Btree for qp %u.", 213*12b253eeSMichael Baum (uint32_t)qp_id); 214*12b253eeSMichael Baum rte_errno = ENOMEM; 215*12b253eeSMichael Baum goto err; 216*12b253eeSMichael Baum } 217c87bc83aSMichael Baum opaq_buf = rte_calloc(__func__, (size_t)1 << log_ops_n, 2188619fcd5SMatan Azrad sizeof(struct mlx5_gga_compress_opaque), 2198619fcd5SMatan Azrad sizeof(struct mlx5_gga_compress_opaque)); 2208619fcd5SMatan Azrad if (opaq_buf == NULL) { 2218619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to allocate opaque memory."); 2228619fcd5SMatan Azrad rte_errno = ENOMEM; 2238619fcd5SMatan Azrad goto err; 2248619fcd5SMatan Azrad } 2258619fcd5SMatan Azrad qp->entries_n = 1 << log_ops_n; 2268619fcd5SMatan Azrad qp->socket_id = socket_id; 2278619fcd5SMatan Azrad qp->qp_id = qp_id; 2288619fcd5SMatan Azrad qp->priv = priv; 2298619fcd5SMatan Azrad qp->ops = (struct rte_comp_op **)RTE_ALIGN((uintptr_t)(qp + 1), 2308619fcd5SMatan Azrad RTE_CACHE_LINE_SIZE); 2318619fcd5SMatan Azrad if (mlx5_common_verbs_reg_mr(priv->pd, opaq_buf, qp->entries_n * 2328619fcd5SMatan Azrad sizeof(struct mlx5_gga_compress_opaque), 2338619fcd5SMatan Azrad &qp->opaque_mr) != 0) { 2348619fcd5SMatan Azrad rte_free(opaq_buf); 2358619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to register opaque MR."); 2368619fcd5SMatan Azrad rte_errno = ENOMEM; 2378619fcd5SMatan Azrad goto err; 2388619fcd5SMatan Azrad } 2398619fcd5SMatan Azrad ret = mlx5_devx_cq_create(priv->ctx, &qp->cq, log_ops_n, &cq_attr, 2408619fcd5SMatan Azrad socket_id); 2418619fcd5SMatan Azrad if (ret != 0) { 2428619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to create CQ."); 2438619fcd5SMatan Azrad goto err; 2448619fcd5SMatan Azrad } 2458619fcd5SMatan Azrad sq_attr.cqn = qp->cq.cq->id; 24610787aa2SViacheslav Ovsiienko sq_attr.ts_format = mlx5_ts_format_conv(priv->sq_ts_format); 2478619fcd5SMatan Azrad ret = mlx5_devx_sq_create(priv->ctx, &qp->sq, log_ops_n, &sq_attr, 2488619fcd5SMatan Azrad socket_id); 2498619fcd5SMatan Azrad if (ret != 0) { 2508619fcd5SMatan Azrad DRV_LOG(ERR, "Failed to create SQ."); 2518619fcd5SMatan Azrad goto err; 2528619fcd5SMatan Azrad } 2538619fcd5SMatan Azrad mlx5_compress_init_sq(qp); 2548619fcd5SMatan Azrad ret = mlx5_devx_cmd_modify_sq(qp->sq.sq, &modify_attr); 2558619fcd5SMatan Azrad if (ret != 0) { 2568619fcd5SMatan Azrad DRV_LOG(ERR, "Can't change SQ state to ready."); 2578619fcd5SMatan Azrad goto err; 2588619fcd5SMatan Azrad } 2598c090106SMichael Baum /* Save pointer of global generation number to check memory event. */ 2608c090106SMichael Baum qp->mr_ctrl.dev_gen_ptr = &priv->mr_scache.dev_gen; 2611b9e9826SThomas Monjalon DRV_LOG(INFO, "QP %u: SQN=0x%X CQN=0x%X entries num = %u", 2628619fcd5SMatan Azrad (uint32_t)qp_id, qp->sq.sq->id, qp->cq.cq->id, qp->entries_n); 2638619fcd5SMatan Azrad return 0; 2648619fcd5SMatan Azrad err: 2658619fcd5SMatan Azrad mlx5_compress_qp_release(dev, qp_id); 2668619fcd5SMatan Azrad return -1; 2678619fcd5SMatan Azrad } 2688619fcd5SMatan Azrad 26939a2c871SMatan Azrad static int 27039a2c871SMatan Azrad mlx5_compress_xform_free(struct rte_compressdev *dev, void *xform) 27139a2c871SMatan Azrad { 27239a2c871SMatan Azrad struct mlx5_compress_priv *priv = dev->data->dev_private; 27339a2c871SMatan Azrad 27439a2c871SMatan Azrad rte_spinlock_lock(&priv->xform_sl); 27539a2c871SMatan Azrad LIST_REMOVE((struct mlx5_compress_xform *)xform, next); 27639a2c871SMatan Azrad rte_spinlock_unlock(&priv->xform_sl); 27739a2c871SMatan Azrad rte_free(xform); 27839a2c871SMatan Azrad return 0; 27939a2c871SMatan Azrad } 28039a2c871SMatan Azrad 28139a2c871SMatan Azrad static int 28239a2c871SMatan Azrad mlx5_compress_xform_create(struct rte_compressdev *dev, 28339a2c871SMatan Azrad const struct rte_comp_xform *xform, 28439a2c871SMatan Azrad void **private_xform) 28539a2c871SMatan Azrad { 28639a2c871SMatan Azrad struct mlx5_compress_priv *priv = dev->data->dev_private; 28739a2c871SMatan Azrad struct mlx5_compress_xform *xfrm; 28839a2c871SMatan Azrad uint32_t size; 28939a2c871SMatan Azrad 29039a2c871SMatan Azrad if (xform->type == RTE_COMP_COMPRESS && xform->compress.level == 29139a2c871SMatan Azrad RTE_COMP_LEVEL_NONE) { 29239a2c871SMatan Azrad DRV_LOG(ERR, "Non-compressed block is not supported."); 29339a2c871SMatan Azrad return -ENOTSUP; 29439a2c871SMatan Azrad } 29539a2c871SMatan Azrad if ((xform->type == RTE_COMP_COMPRESS && xform->compress.hash_algo != 29639a2c871SMatan Azrad RTE_COMP_HASH_ALGO_NONE) || (xform->type == RTE_COMP_DECOMPRESS && 29739a2c871SMatan Azrad xform->decompress.hash_algo != RTE_COMP_HASH_ALGO_NONE)) { 29839a2c871SMatan Azrad DRV_LOG(ERR, "SHA is not supported."); 29939a2c871SMatan Azrad return -ENOTSUP; 30039a2c871SMatan Azrad } 30139a2c871SMatan Azrad xfrm = rte_zmalloc_socket(__func__, sizeof(*xfrm), 0, 30239a2c871SMatan Azrad priv->dev_config.socket_id); 30339a2c871SMatan Azrad if (xfrm == NULL) 30439a2c871SMatan Azrad return -ENOMEM; 30539a2c871SMatan Azrad xfrm->opcode = MLX5_OPCODE_MMO; 30639a2c871SMatan Azrad xfrm->type = xform->type; 30739a2c871SMatan Azrad switch (xform->type) { 30839a2c871SMatan Azrad case RTE_COMP_COMPRESS: 30939a2c871SMatan Azrad switch (xform->compress.algo) { 31039a2c871SMatan Azrad case RTE_COMP_ALGO_NULL: 31139a2c871SMatan Azrad xfrm->opcode += MLX5_OPC_MOD_MMO_DMA << 31239a2c871SMatan Azrad WQE_CSEG_OPC_MOD_OFFSET; 31339a2c871SMatan Azrad break; 31439a2c871SMatan Azrad case RTE_COMP_ALGO_DEFLATE: 31539a2c871SMatan Azrad size = 1 << xform->compress.window_size; 31639a2c871SMatan Azrad size /= MLX5_GGA_COMP_WIN_SIZE_UNITS; 31739a2c871SMatan Azrad xfrm->gga_ctrl1 += RTE_MIN(rte_log2_u32(size), 31839a2c871SMatan Azrad MLX5_COMP_MAX_WIN_SIZE_CONF) << 31939a2c871SMatan Azrad WQE_GGA_COMP_WIN_SIZE_OFFSET; 320237aad88SRaja Zidane switch (xform->compress.level) { 321237aad88SRaja Zidane case RTE_COMP_LEVEL_PMD_DEFAULT: 32239a2c871SMatan Azrad size = MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX; 323237aad88SRaja Zidane break; 324237aad88SRaja Zidane case RTE_COMP_LEVEL_MAX: 325237aad88SRaja Zidane size = priv->min_block_size; 326237aad88SRaja Zidane break; 327237aad88SRaja Zidane default: 328237aad88SRaja Zidane size = RTE_MAX(MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX 329237aad88SRaja Zidane + 1 - xform->compress.level, 330237aad88SRaja Zidane priv->min_block_size); 331237aad88SRaja Zidane } 33239a2c871SMatan Azrad xfrm->gga_ctrl1 += RTE_MIN(size, 33339a2c871SMatan Azrad MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX) << 33439a2c871SMatan Azrad WQE_GGA_COMP_BLOCK_SIZE_OFFSET; 33539a2c871SMatan Azrad xfrm->opcode += MLX5_OPC_MOD_MMO_COMP << 33639a2c871SMatan Azrad WQE_CSEG_OPC_MOD_OFFSET; 33739a2c871SMatan Azrad size = xform->compress.deflate.huffman == 33839a2c871SMatan Azrad RTE_COMP_HUFFMAN_DYNAMIC ? 33939a2c871SMatan Azrad MLX5_GGA_COMP_LOG_DYNAMIC_SIZE_MAX : 34039a2c871SMatan Azrad MLX5_GGA_COMP_LOG_DYNAMIC_SIZE_MIN; 34139a2c871SMatan Azrad xfrm->gga_ctrl1 += size << 34239a2c871SMatan Azrad WQE_GGA_COMP_DYNAMIC_SIZE_OFFSET; 34339a2c871SMatan Azrad break; 34439a2c871SMatan Azrad default: 34539a2c871SMatan Azrad goto err; 34639a2c871SMatan Azrad } 34739a2c871SMatan Azrad xfrm->csum_type = xform->compress.chksum; 34839a2c871SMatan Azrad break; 34939a2c871SMatan Azrad case RTE_COMP_DECOMPRESS: 35039a2c871SMatan Azrad switch (xform->decompress.algo) { 35139a2c871SMatan Azrad case RTE_COMP_ALGO_NULL: 35239a2c871SMatan Azrad xfrm->opcode += MLX5_OPC_MOD_MMO_DMA << 35339a2c871SMatan Azrad WQE_CSEG_OPC_MOD_OFFSET; 35439a2c871SMatan Azrad break; 35539a2c871SMatan Azrad case RTE_COMP_ALGO_DEFLATE: 35639a2c871SMatan Azrad xfrm->opcode += MLX5_OPC_MOD_MMO_DECOMP << 35739a2c871SMatan Azrad WQE_CSEG_OPC_MOD_OFFSET; 35839a2c871SMatan Azrad break; 35939a2c871SMatan Azrad default: 36039a2c871SMatan Azrad goto err; 36139a2c871SMatan Azrad } 36239a2c871SMatan Azrad xfrm->csum_type = xform->decompress.chksum; 36339a2c871SMatan Azrad break; 36439a2c871SMatan Azrad default: 36539a2c871SMatan Azrad DRV_LOG(ERR, "Algorithm %u is not supported.", xform->type); 36639a2c871SMatan Azrad goto err; 36739a2c871SMatan Azrad } 36839a2c871SMatan Azrad DRV_LOG(DEBUG, "New xform: gga ctrl1 = 0x%08X opcode = 0x%08X csum " 36939a2c871SMatan Azrad "type = %d.", xfrm->gga_ctrl1, xfrm->opcode, xfrm->csum_type); 37039a2c871SMatan Azrad xfrm->gga_ctrl1 = rte_cpu_to_be_32(xfrm->gga_ctrl1); 37139a2c871SMatan Azrad rte_spinlock_lock(&priv->xform_sl); 37239a2c871SMatan Azrad LIST_INSERT_HEAD(&priv->xform_list, xfrm, next); 37339a2c871SMatan Azrad rte_spinlock_unlock(&priv->xform_sl); 37439a2c871SMatan Azrad *private_xform = xfrm; 37539a2c871SMatan Azrad return 0; 37639a2c871SMatan Azrad err: 37739a2c871SMatan Azrad rte_free(xfrm); 37839a2c871SMatan Azrad return -ENOTSUP; 37939a2c871SMatan Azrad } 38039a2c871SMatan Azrad 381f8c97babSMatan Azrad static void 382f8c97babSMatan Azrad mlx5_compress_dev_stop(struct rte_compressdev *dev) 383f8c97babSMatan Azrad { 384f8c97babSMatan Azrad RTE_SET_USED(dev); 385f8c97babSMatan Azrad } 386f8c97babSMatan Azrad 387f8c97babSMatan Azrad static int 388f8c97babSMatan Azrad mlx5_compress_dev_start(struct rte_compressdev *dev) 389f8c97babSMatan Azrad { 390f8c97babSMatan Azrad RTE_SET_USED(dev); 391f8c97babSMatan Azrad return 0; 392f8c97babSMatan Azrad } 393f8c97babSMatan Azrad 394ccfd891aSMatan Azrad static void 395ccfd891aSMatan Azrad mlx5_compress_stats_get(struct rte_compressdev *dev, 396ccfd891aSMatan Azrad struct rte_compressdev_stats *stats) 397ccfd891aSMatan Azrad { 398ccfd891aSMatan Azrad int qp_id; 399ccfd891aSMatan Azrad 400ccfd891aSMatan Azrad for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) { 401ccfd891aSMatan Azrad struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id]; 402ccfd891aSMatan Azrad 403ccfd891aSMatan Azrad stats->enqueued_count += qp->stats.enqueued_count; 404ccfd891aSMatan Azrad stats->dequeued_count += qp->stats.dequeued_count; 405ccfd891aSMatan Azrad stats->enqueue_err_count += qp->stats.enqueue_err_count; 406ccfd891aSMatan Azrad stats->dequeue_err_count += qp->stats.dequeue_err_count; 407ccfd891aSMatan Azrad } 408ccfd891aSMatan Azrad } 409ccfd891aSMatan Azrad 410ccfd891aSMatan Azrad static void 411ccfd891aSMatan Azrad mlx5_compress_stats_reset(struct rte_compressdev *dev) 412ccfd891aSMatan Azrad { 413ccfd891aSMatan Azrad int qp_id; 414ccfd891aSMatan Azrad 415ccfd891aSMatan Azrad for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) { 416ccfd891aSMatan Azrad struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id]; 417ccfd891aSMatan Azrad 418ccfd891aSMatan Azrad memset(&qp->stats, 0, sizeof(qp->stats)); 419ccfd891aSMatan Azrad } 420ccfd891aSMatan Azrad } 421ccfd891aSMatan Azrad 422832a4cf1SMatan Azrad static struct rte_compressdev_ops mlx5_compress_ops = { 423fefca160SMatan Azrad .dev_configure = mlx5_compress_dev_configure, 424f8c97babSMatan Azrad .dev_start = mlx5_compress_dev_start, 425f8c97babSMatan Azrad .dev_stop = mlx5_compress_dev_stop, 426fefca160SMatan Azrad .dev_close = mlx5_compress_dev_close, 427fefca160SMatan Azrad .dev_infos_get = mlx5_compress_dev_info_get, 428ccfd891aSMatan Azrad .stats_get = mlx5_compress_stats_get, 429ccfd891aSMatan Azrad .stats_reset = mlx5_compress_stats_reset, 4308619fcd5SMatan Azrad .queue_pair_setup = mlx5_compress_qp_setup, 4318619fcd5SMatan Azrad .queue_pair_release = mlx5_compress_qp_release, 43239a2c871SMatan Azrad .private_xform_create = mlx5_compress_xform_create, 43339a2c871SMatan Azrad .private_xform_free = mlx5_compress_xform_free, 434832a4cf1SMatan Azrad .stream_create = NULL, 435832a4cf1SMatan Azrad .stream_free = NULL, 436832a4cf1SMatan Azrad }; 437832a4cf1SMatan Azrad 4388c090106SMichael Baum /** 4398c090106SMichael Baum * Query LKey from a packet buffer for QP. If not found, add the mempool. 4408c090106SMichael Baum * 4418c090106SMichael Baum * @param priv 4428c090106SMichael Baum * Pointer to the priv object. 4438c090106SMichael Baum * @param addr 4448c090106SMichael Baum * Search key. 4458c090106SMichael Baum * @param mr_ctrl 4468c090106SMichael Baum * Pointer to per-queue MR control structure. 4478c090106SMichael Baum * @param ol_flags 4488c090106SMichael Baum * Mbuf offload features. 4498c090106SMichael Baum * 4508c090106SMichael Baum * @return 4518c090106SMichael Baum * Searched LKey on success, UINT32_MAX on no match. 4528c090106SMichael Baum */ 4538c090106SMichael Baum static __rte_always_inline uint32_t 4548c090106SMichael Baum mlx5_compress_addr2mr(struct mlx5_compress_priv *priv, uintptr_t addr, 4558c090106SMichael Baum struct mlx5_mr_ctrl *mr_ctrl, uint64_t ol_flags) 4568c090106SMichael Baum { 4578c090106SMichael Baum uint32_t lkey; 4588c090106SMichael Baum 4598c090106SMichael Baum /* Check generation bit to see if there's any change on existing MRs. */ 4608c090106SMichael Baum if (unlikely(*mr_ctrl->dev_gen_ptr != mr_ctrl->cur_gen)) 4618c090106SMichael Baum mlx5_mr_flush_local_cache(mr_ctrl); 4628c090106SMichael Baum /* Linear search on MR cache array. */ 4638c090106SMichael Baum lkey = mlx5_mr_lookup_lkey(mr_ctrl->cache, &mr_ctrl->mru, 4648c090106SMichael Baum MLX5_MR_CACHE_N, addr); 4658c090106SMichael Baum if (likely(lkey != UINT32_MAX)) 4668c090106SMichael Baum return lkey; 4678c090106SMichael Baum /* Take slower bottom-half on miss. */ 4688c090106SMichael Baum return mlx5_mr_addr2mr_bh(priv->pd, 0, &priv->mr_scache, mr_ctrl, addr, 4698c090106SMichael Baum !!(ol_flags & EXT_ATTACHED_MBUF)); 4708c090106SMichael Baum } 4718c090106SMichael Baum 472f8c97babSMatan Azrad static __rte_always_inline uint32_t 473f8c97babSMatan Azrad mlx5_compress_dseg_set(struct mlx5_compress_qp *qp, 474f8c97babSMatan Azrad volatile struct mlx5_wqe_dseg *restrict dseg, 475f8c97babSMatan Azrad struct rte_mbuf *restrict mbuf, 476f8c97babSMatan Azrad uint32_t offset, uint32_t len) 477f8c97babSMatan Azrad { 478f8c97babSMatan Azrad uintptr_t addr = rte_pktmbuf_mtod_offset(mbuf, uintptr_t, offset); 479f8c97babSMatan Azrad 480f8c97babSMatan Azrad dseg->bcount = rte_cpu_to_be_32(len); 4818c090106SMichael Baum dseg->lkey = mlx5_compress_addr2mr(qp->priv, addr, &qp->mr_ctrl, 4828c090106SMichael Baum mbuf->ol_flags); 483f8c97babSMatan Azrad dseg->pbuf = rte_cpu_to_be_64(addr); 484f8c97babSMatan Azrad return dseg->lkey; 485f8c97babSMatan Azrad } 486f8c97babSMatan Azrad 48737862dafSMatan Azrad /* 48837862dafSMatan Azrad * Provide safe 64bit store operation to mlx5 UAR region for both 32bit and 48937862dafSMatan Azrad * 64bit architectures. 49037862dafSMatan Azrad */ 49137862dafSMatan Azrad static __rte_always_inline void 49237862dafSMatan Azrad mlx5_compress_uar_write(uint64_t val, struct mlx5_compress_priv *priv) 49337862dafSMatan Azrad { 49437862dafSMatan Azrad #ifdef RTE_ARCH_64 49537862dafSMatan Azrad *priv->uar_addr = val; 49637862dafSMatan Azrad #else /* !RTE_ARCH_64 */ 49737862dafSMatan Azrad rte_spinlock_lock(&priv->uar32_sl); 49837862dafSMatan Azrad *(volatile uint32_t *)priv->uar_addr = val; 49937862dafSMatan Azrad rte_io_wmb(); 50037862dafSMatan Azrad *((volatile uint32_t *)priv->uar_addr + 1) = val >> 32; 50137862dafSMatan Azrad rte_spinlock_unlock(&priv->uar32_sl); 50237862dafSMatan Azrad #endif 50337862dafSMatan Azrad } 50437862dafSMatan Azrad 505f8c97babSMatan Azrad static uint16_t 506f8c97babSMatan Azrad mlx5_compress_enqueue_burst(void *queue_pair, struct rte_comp_op **ops, 507f8c97babSMatan Azrad uint16_t nb_ops) 508f8c97babSMatan Azrad { 509f8c97babSMatan Azrad struct mlx5_compress_qp *qp = queue_pair; 510f8c97babSMatan Azrad volatile struct mlx5_gga_wqe *wqes = (volatile struct mlx5_gga_wqe *) 511f8c97babSMatan Azrad qp->sq.wqes, *wqe; 512f8c97babSMatan Azrad struct mlx5_compress_xform *xform; 513f8c97babSMatan Azrad struct rte_comp_op *op; 514f8c97babSMatan Azrad uint16_t mask = qp->entries_n - 1; 515f8c97babSMatan Azrad uint16_t remain = qp->entries_n - (qp->pi - qp->ci); 516f8c97babSMatan Azrad uint16_t idx; 517f8c97babSMatan Azrad bool invalid; 518f8c97babSMatan Azrad 519f8c97babSMatan Azrad if (remain < nb_ops) 520f8c97babSMatan Azrad nb_ops = remain; 521f8c97babSMatan Azrad else 522f8c97babSMatan Azrad remain = nb_ops; 523f8c97babSMatan Azrad if (unlikely(remain == 0)) 524f8c97babSMatan Azrad return 0; 525f8c97babSMatan Azrad do { 526f8c97babSMatan Azrad idx = qp->pi & mask; 527f8c97babSMatan Azrad wqe = &wqes[idx]; 528f8c97babSMatan Azrad rte_prefetch0(&wqes[(qp->pi + 1) & mask]); 529f8c97babSMatan Azrad op = *ops++; 530f8c97babSMatan Azrad xform = op->private_xform; 531f8c97babSMatan Azrad /* 532f8c97babSMatan Azrad * Check operation arguments and error cases: 533f8c97babSMatan Azrad * - Operation type must be state-less. 534f8c97babSMatan Azrad * - Compress operation flush flag must be FULL or FINAL. 535f8c97babSMatan Azrad * - Source and destination buffers must be mapped internally. 536f8c97babSMatan Azrad */ 537f8c97babSMatan Azrad invalid = op->op_type != RTE_COMP_OP_STATELESS || 538f8c97babSMatan Azrad (xform->type == RTE_COMP_COMPRESS && 539f8c97babSMatan Azrad op->flush_flag < RTE_COMP_FLUSH_FULL); 540f8c97babSMatan Azrad if (unlikely(invalid || 541f8c97babSMatan Azrad (mlx5_compress_dseg_set(qp, &wqe->gather, 542f8c97babSMatan Azrad op->m_src, 543f8c97babSMatan Azrad op->src.offset, 544f8c97babSMatan Azrad op->src.length) == 545f8c97babSMatan Azrad UINT32_MAX) || 546f8c97babSMatan Azrad (mlx5_compress_dseg_set(qp, &wqe->scatter, 547f8c97babSMatan Azrad op->m_dst, 548f8c97babSMatan Azrad op->dst.offset, 549f8c97babSMatan Azrad rte_pktmbuf_pkt_len(op->m_dst) - 550f8c97babSMatan Azrad op->dst.offset) == 551f8c97babSMatan Azrad UINT32_MAX))) { 552f8c97babSMatan Azrad op->status = invalid ? RTE_COMP_OP_STATUS_INVALID_ARGS : 553f8c97babSMatan Azrad RTE_COMP_OP_STATUS_ERROR; 554f8c97babSMatan Azrad nb_ops -= remain; 555f8c97babSMatan Azrad if (unlikely(nb_ops == 0)) 556f8c97babSMatan Azrad return 0; 557f8c97babSMatan Azrad break; 558f8c97babSMatan Azrad } 559f8c97babSMatan Azrad wqe->gga_ctrl1 = xform->gga_ctrl1; 560f8c97babSMatan Azrad wqe->opcode = rte_cpu_to_be_32(xform->opcode + (qp->pi << 8)); 561f8c97babSMatan Azrad qp->ops[idx] = op; 562f8c97babSMatan Azrad qp->pi++; 563f8c97babSMatan Azrad } while (--remain); 564ccfd891aSMatan Azrad qp->stats.enqueued_count += nb_ops; 565f8c97babSMatan Azrad rte_io_wmb(); 566f8c97babSMatan Azrad qp->sq.db_rec[MLX5_SND_DBR] = rte_cpu_to_be_32(qp->pi); 567f8c97babSMatan Azrad rte_wmb(); 56837862dafSMatan Azrad mlx5_compress_uar_write(*(volatile uint64_t *)wqe, qp->priv); 569f8c97babSMatan Azrad rte_wmb(); 570f8c97babSMatan Azrad return nb_ops; 571f8c97babSMatan Azrad } 572f8c97babSMatan Azrad 573f8c97babSMatan Azrad static void 574f8c97babSMatan Azrad mlx5_compress_dump_err_objs(volatile uint32_t *cqe, volatile uint32_t *wqe, 575f8c97babSMatan Azrad volatile uint32_t *opaq) 576f8c97babSMatan Azrad { 577f8c97babSMatan Azrad size_t i; 578f8c97babSMatan Azrad 579f8c97babSMatan Azrad DRV_LOG(ERR, "Error cqe:"); 580f8c97babSMatan Azrad for (i = 0; i < sizeof(struct mlx5_err_cqe) >> 2; i += 4) 581f8c97babSMatan Azrad DRV_LOG(ERR, "%08X %08X %08X %08X", cqe[i], cqe[i + 1], 582f8c97babSMatan Azrad cqe[i + 2], cqe[i + 3]); 583f8c97babSMatan Azrad DRV_LOG(ERR, "\nError wqe:"); 584f8c97babSMatan Azrad for (i = 0; i < sizeof(struct mlx5_gga_wqe) >> 2; i += 4) 585f8c97babSMatan Azrad DRV_LOG(ERR, "%08X %08X %08X %08X", wqe[i], wqe[i + 1], 586f8c97babSMatan Azrad wqe[i + 2], wqe[i + 3]); 587f8c97babSMatan Azrad DRV_LOG(ERR, "\nError opaq:"); 588f8c97babSMatan Azrad for (i = 0; i < sizeof(struct mlx5_gga_compress_opaque) >> 2; i += 4) 589f8c97babSMatan Azrad DRV_LOG(ERR, "%08X %08X %08X %08X", opaq[i], opaq[i + 1], 590f8c97babSMatan Azrad opaq[i + 2], opaq[i + 3]); 591f8c97babSMatan Azrad } 592f8c97babSMatan Azrad 593f8c97babSMatan Azrad static void 594f8c97babSMatan Azrad mlx5_compress_cqe_err_handle(struct mlx5_compress_qp *qp, 595f8c97babSMatan Azrad struct rte_comp_op *op) 596f8c97babSMatan Azrad { 597f8c97babSMatan Azrad const uint32_t idx = qp->ci & (qp->entries_n - 1); 598f8c97babSMatan Azrad volatile struct mlx5_err_cqe *cqe = (volatile struct mlx5_err_cqe *) 599f8c97babSMatan Azrad &qp->cq.cqes[idx]; 600f8c97babSMatan Azrad volatile struct mlx5_gga_wqe *wqes = (volatile struct mlx5_gga_wqe *) 601f8c97babSMatan Azrad qp->sq.wqes; 602f8c97babSMatan Azrad volatile struct mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr; 603f8c97babSMatan Azrad 604f8c97babSMatan Azrad op->status = RTE_COMP_OP_STATUS_ERROR; 605f8c97babSMatan Azrad op->consumed = 0; 606f8c97babSMatan Azrad op->produced = 0; 607f8c97babSMatan Azrad op->output_chksum = 0; 608f8c97babSMatan Azrad op->debug_status = rte_be_to_cpu_32(opaq[idx].syndrom) | 609f8c97babSMatan Azrad ((uint64_t)rte_be_to_cpu_32(cqe->syndrome) << 32); 610f8c97babSMatan Azrad mlx5_compress_dump_err_objs((volatile uint32_t *)cqe, 611f8c97babSMatan Azrad (volatile uint32_t *)&wqes[idx], 612f8c97babSMatan Azrad (volatile uint32_t *)&opaq[idx]); 613ccfd891aSMatan Azrad qp->stats.dequeue_err_count++; 614f8c97babSMatan Azrad } 615f8c97babSMatan Azrad 616f8c97babSMatan Azrad static uint16_t 617f8c97babSMatan Azrad mlx5_compress_dequeue_burst(void *queue_pair, struct rte_comp_op **ops, 618f8c97babSMatan Azrad uint16_t nb_ops) 619f8c97babSMatan Azrad { 620f8c97babSMatan Azrad struct mlx5_compress_qp *qp = queue_pair; 621f8c97babSMatan Azrad volatile struct mlx5_compress_xform *restrict xform; 622f8c97babSMatan Azrad volatile struct mlx5_cqe *restrict cqe; 623f8c97babSMatan Azrad volatile struct mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr; 624f8c97babSMatan Azrad struct rte_comp_op *restrict op; 625f8c97babSMatan Azrad const unsigned int cq_size = qp->entries_n; 626f8c97babSMatan Azrad const unsigned int mask = cq_size - 1; 627f8c97babSMatan Azrad uint32_t idx; 628f8c97babSMatan Azrad uint32_t next_idx = qp->ci & mask; 629f8c97babSMatan Azrad const uint16_t max = RTE_MIN((uint16_t)(qp->pi - qp->ci), nb_ops); 630f8c97babSMatan Azrad uint16_t i = 0; 631f8c97babSMatan Azrad int ret; 632f8c97babSMatan Azrad 633f8c97babSMatan Azrad if (unlikely(max == 0)) 634f8c97babSMatan Azrad return 0; 635f8c97babSMatan Azrad do { 636f8c97babSMatan Azrad idx = next_idx; 637f8c97babSMatan Azrad next_idx = (qp->ci + 1) & mask; 638f8c97babSMatan Azrad rte_prefetch0(&qp->cq.cqes[next_idx]); 639f8c97babSMatan Azrad rte_prefetch0(qp->ops[next_idx]); 640f8c97babSMatan Azrad op = qp->ops[idx]; 641f8c97babSMatan Azrad cqe = &qp->cq.cqes[idx]; 642f8c97babSMatan Azrad ret = check_cqe(cqe, cq_size, qp->ci); 643f8c97babSMatan Azrad /* 644f8c97babSMatan Azrad * Be sure owner read is done before any other cookie field or 645f8c97babSMatan Azrad * opaque field. 646f8c97babSMatan Azrad */ 647f8c97babSMatan Azrad rte_io_rmb(); 648f8c97babSMatan Azrad if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) { 649f8c97babSMatan Azrad if (likely(ret == MLX5_CQE_STATUS_HW_OWN)) 650f8c97babSMatan Azrad break; 651f8c97babSMatan Azrad mlx5_compress_cqe_err_handle(qp, op); 652f8c97babSMatan Azrad } else { 653f8c97babSMatan Azrad xform = op->private_xform; 654f8c97babSMatan Azrad op->status = RTE_COMP_OP_STATUS_SUCCESS; 655f8c97babSMatan Azrad op->consumed = op->src.length; 656f8c97babSMatan Azrad op->produced = rte_be_to_cpu_32(cqe->byte_cnt); 657f8c97babSMatan Azrad MLX5_ASSERT(cqe->byte_cnt == 658c0249919SMatan Azrad opaq[idx].scattered_length); 659f8c97babSMatan Azrad switch (xform->csum_type) { 660f8c97babSMatan Azrad case RTE_COMP_CHECKSUM_CRC32: 661f8c97babSMatan Azrad op->output_chksum = (uint64_t)rte_be_to_cpu_32 662f8c97babSMatan Azrad (opaq[idx].crc32); 663f8c97babSMatan Azrad break; 664f8c97babSMatan Azrad case RTE_COMP_CHECKSUM_ADLER32: 665f8c97babSMatan Azrad op->output_chksum = (uint64_t)rte_be_to_cpu_32 666f8c97babSMatan Azrad (opaq[idx].adler32) << 32; 667f8c97babSMatan Azrad break; 668f8c97babSMatan Azrad case RTE_COMP_CHECKSUM_CRC32_ADLER32: 669f8c97babSMatan Azrad op->output_chksum = (uint64_t)rte_be_to_cpu_32 670f8c97babSMatan Azrad (opaq[idx].crc32) | 671f8c97babSMatan Azrad ((uint64_t)rte_be_to_cpu_32 672f8c97babSMatan Azrad (opaq[idx].adler32) << 32); 673f8c97babSMatan Azrad break; 674f8c97babSMatan Azrad default: 675f8c97babSMatan Azrad break; 676f8c97babSMatan Azrad } 677f8c97babSMatan Azrad } 678f8c97babSMatan Azrad ops[i++] = op; 679f8c97babSMatan Azrad qp->ci++; 680f8c97babSMatan Azrad } while (i < max); 681f8c97babSMatan Azrad if (likely(i != 0)) { 682f8c97babSMatan Azrad rte_io_wmb(); 683f8c97babSMatan Azrad qp->cq.db_rec[0] = rte_cpu_to_be_32(qp->ci); 684ccfd891aSMatan Azrad qp->stats.dequeued_count += i; 685f8c97babSMatan Azrad } 686f8c97babSMatan Azrad return i; 687f8c97babSMatan Azrad } 688f8c97babSMatan Azrad 689832a4cf1SMatan Azrad static void 690832a4cf1SMatan Azrad mlx5_compress_hw_global_release(struct mlx5_compress_priv *priv) 691832a4cf1SMatan Azrad { 692832a4cf1SMatan Azrad if (priv->pd != NULL) { 693832a4cf1SMatan Azrad claim_zero(mlx5_glue->dealloc_pd(priv->pd)); 694832a4cf1SMatan Azrad priv->pd = NULL; 695832a4cf1SMatan Azrad } 696832a4cf1SMatan Azrad if (priv->uar != NULL) { 697832a4cf1SMatan Azrad mlx5_glue->devx_free_uar(priv->uar); 698832a4cf1SMatan Azrad priv->uar = NULL; 699832a4cf1SMatan Azrad } 700832a4cf1SMatan Azrad } 701832a4cf1SMatan Azrad 702832a4cf1SMatan Azrad static int 703832a4cf1SMatan Azrad mlx5_compress_pd_create(struct mlx5_compress_priv *priv) 704832a4cf1SMatan Azrad { 705832a4cf1SMatan Azrad #ifdef HAVE_IBV_FLOW_DV_SUPPORT 706832a4cf1SMatan Azrad struct mlx5dv_obj obj; 707832a4cf1SMatan Azrad struct mlx5dv_pd pd_info; 708832a4cf1SMatan Azrad int ret; 709832a4cf1SMatan Azrad 710832a4cf1SMatan Azrad priv->pd = mlx5_glue->alloc_pd(priv->ctx); 711832a4cf1SMatan Azrad if (priv->pd == NULL) { 712832a4cf1SMatan Azrad DRV_LOG(ERR, "Failed to allocate PD."); 713832a4cf1SMatan Azrad return errno ? -errno : -ENOMEM; 714832a4cf1SMatan Azrad } 715832a4cf1SMatan Azrad obj.pd.in = priv->pd; 716832a4cf1SMatan Azrad obj.pd.out = &pd_info; 717832a4cf1SMatan Azrad ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD); 718832a4cf1SMatan Azrad if (ret != 0) { 719832a4cf1SMatan Azrad DRV_LOG(ERR, "Fail to get PD object info."); 720832a4cf1SMatan Azrad mlx5_glue->dealloc_pd(priv->pd); 721832a4cf1SMatan Azrad priv->pd = NULL; 722832a4cf1SMatan Azrad return -errno; 723832a4cf1SMatan Azrad } 724832a4cf1SMatan Azrad priv->pdn = pd_info.pdn; 725832a4cf1SMatan Azrad return 0; 726832a4cf1SMatan Azrad #else 727832a4cf1SMatan Azrad (void)priv; 728832a4cf1SMatan Azrad DRV_LOG(ERR, "Cannot get pdn - no DV support."); 729832a4cf1SMatan Azrad return -ENOTSUP; 730832a4cf1SMatan Azrad #endif /* HAVE_IBV_FLOW_DV_SUPPORT */ 731832a4cf1SMatan Azrad } 732832a4cf1SMatan Azrad 733832a4cf1SMatan Azrad static int 734832a4cf1SMatan Azrad mlx5_compress_hw_global_prepare(struct mlx5_compress_priv *priv) 735832a4cf1SMatan Azrad { 736832a4cf1SMatan Azrad if (mlx5_compress_pd_create(priv) != 0) 737832a4cf1SMatan Azrad return -1; 738832a4cf1SMatan Azrad priv->uar = mlx5_devx_alloc_uar(priv->ctx, -1); 739832a4cf1SMatan Azrad if (priv->uar == NULL || mlx5_os_get_devx_uar_reg_addr(priv->uar) == 740832a4cf1SMatan Azrad NULL) { 741832a4cf1SMatan Azrad rte_errno = errno; 742832a4cf1SMatan Azrad claim_zero(mlx5_glue->dealloc_pd(priv->pd)); 743832a4cf1SMatan Azrad DRV_LOG(ERR, "Failed to allocate UAR."); 744832a4cf1SMatan Azrad return -1; 745832a4cf1SMatan Azrad } 74637862dafSMatan Azrad priv->uar_addr = mlx5_os_get_devx_uar_reg_addr(priv->uar); 747c0249919SMatan Azrad MLX5_ASSERT(priv->uar_addr); 74837862dafSMatan Azrad #ifndef RTE_ARCH_64 74937862dafSMatan Azrad rte_spinlock_init(&priv->uar32_sl); 75037862dafSMatan Azrad #endif /* RTE_ARCH_64 */ 751832a4cf1SMatan Azrad return 0; 752832a4cf1SMatan Azrad } 753832a4cf1SMatan Azrad 754832a4cf1SMatan Azrad /** 7558c090106SMichael Baum * Callback for memory event. 7568c090106SMichael Baum * 7578c090106SMichael Baum * @param event_type 7588c090106SMichael Baum * Memory event type. 7598c090106SMichael Baum * @param addr 7608c090106SMichael Baum * Address of memory. 7618c090106SMichael Baum * @param len 7628c090106SMichael Baum * Size of memory. 7638c090106SMichael Baum */ 7648c090106SMichael Baum static void 7658c090106SMichael Baum mlx5_compress_mr_mem_event_cb(enum rte_mem_event event_type, const void *addr, 7668c090106SMichael Baum size_t len, void *arg __rte_unused) 7678c090106SMichael Baum { 7688c090106SMichael Baum struct mlx5_compress_priv *priv; 7698c090106SMichael Baum 7708c090106SMichael Baum /* Must be called from the primary process. */ 7718c090106SMichael Baum MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 7728c090106SMichael Baum switch (event_type) { 7738c090106SMichael Baum case RTE_MEM_EVENT_FREE: 7748c090106SMichael Baum pthread_mutex_lock(&priv_list_lock); 7758c090106SMichael Baum /* Iterate all the existing mlx5 devices. */ 7768c090106SMichael Baum TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next) 7778c090106SMichael Baum mlx5_free_mr_by_addr(&priv->mr_scache, 7788c090106SMichael Baum priv->ctx->device->name, 7798c090106SMichael Baum addr, len); 7808c090106SMichael Baum pthread_mutex_unlock(&priv_list_lock); 7818c090106SMichael Baum break; 7828c090106SMichael Baum case RTE_MEM_EVENT_ALLOC: 7838c090106SMichael Baum default: 7848c090106SMichael Baum break; 7858c090106SMichael Baum } 7868c090106SMichael Baum } 7878c090106SMichael Baum 788832a4cf1SMatan Azrad static int 78982242186SXueming Li mlx5_compress_dev_probe(struct rte_device *dev) 790832a4cf1SMatan Azrad { 791832a4cf1SMatan Azrad struct ibv_device *ibv; 792832a4cf1SMatan Azrad struct rte_compressdev *cdev; 793832a4cf1SMatan Azrad struct ibv_context *ctx; 794832a4cf1SMatan Azrad struct mlx5_compress_priv *priv; 795832a4cf1SMatan Azrad struct mlx5_hca_attr att = { 0 }; 796832a4cf1SMatan Azrad struct rte_compressdev_pmd_init_params init_params = { 797832a4cf1SMatan Azrad .name = "", 79882242186SXueming Li .socket_id = dev->numa_node, 799832a4cf1SMatan Azrad }; 800832a4cf1SMatan Azrad 801832a4cf1SMatan Azrad if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 802832a4cf1SMatan Azrad DRV_LOG(ERR, "Non-primary process type is not supported."); 803832a4cf1SMatan Azrad rte_errno = ENOTSUP; 804832a4cf1SMatan Azrad return -rte_errno; 805832a4cf1SMatan Azrad } 80682242186SXueming Li ibv = mlx5_os_get_ibv_dev(dev); 80782242186SXueming Li if (ibv == NULL) 808832a4cf1SMatan Azrad return -rte_errno; 809832a4cf1SMatan Azrad ctx = mlx5_glue->dv_open_device(ibv); 810832a4cf1SMatan Azrad if (ctx == NULL) { 811832a4cf1SMatan Azrad DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name); 812832a4cf1SMatan Azrad rte_errno = ENODEV; 813832a4cf1SMatan Azrad return -rte_errno; 814832a4cf1SMatan Azrad } 815832a4cf1SMatan Azrad if (mlx5_devx_cmd_query_hca_attr(ctx, &att) != 0 || 816832a4cf1SMatan Azrad att.mmo_compress_en == 0 || att.mmo_decompress_en == 0 || 817832a4cf1SMatan Azrad att.mmo_dma_en == 0) { 818832a4cf1SMatan Azrad DRV_LOG(ERR, "Not enough capabilities to support compress " 819832a4cf1SMatan Azrad "operations, maybe old FW/OFED version?"); 820832a4cf1SMatan Azrad claim_zero(mlx5_glue->close_device(ctx)); 821832a4cf1SMatan Azrad rte_errno = ENOTSUP; 822832a4cf1SMatan Azrad return -ENOTSUP; 823832a4cf1SMatan Azrad } 82482242186SXueming Li cdev = rte_compressdev_pmd_create(ibv->name, dev, 825832a4cf1SMatan Azrad sizeof(*priv), &init_params); 826832a4cf1SMatan Azrad if (cdev == NULL) { 827832a4cf1SMatan Azrad DRV_LOG(ERR, "Failed to create device \"%s\".", ibv->name); 828832a4cf1SMatan Azrad claim_zero(mlx5_glue->close_device(ctx)); 829832a4cf1SMatan Azrad return -ENODEV; 830832a4cf1SMatan Azrad } 831832a4cf1SMatan Azrad DRV_LOG(INFO, 832832a4cf1SMatan Azrad "Compress device %s was created successfully.", ibv->name); 833832a4cf1SMatan Azrad cdev->dev_ops = &mlx5_compress_ops; 834f8c97babSMatan Azrad cdev->dequeue_burst = mlx5_compress_dequeue_burst; 835f8c97babSMatan Azrad cdev->enqueue_burst = mlx5_compress_enqueue_burst; 836832a4cf1SMatan Azrad cdev->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED; 837832a4cf1SMatan Azrad priv = cdev->data->dev_private; 838832a4cf1SMatan Azrad priv->ctx = ctx; 839832a4cf1SMatan Azrad priv->cdev = cdev; 840832a4cf1SMatan Azrad priv->min_block_size = att.compress_min_block_size; 84110787aa2SViacheslav Ovsiienko priv->sq_ts_format = att.sq_ts_format; 842832a4cf1SMatan Azrad if (mlx5_compress_hw_global_prepare(priv) != 0) { 843832a4cf1SMatan Azrad rte_compressdev_pmd_destroy(priv->cdev); 844832a4cf1SMatan Azrad claim_zero(mlx5_glue->close_device(priv->ctx)); 845832a4cf1SMatan Azrad return -1; 846832a4cf1SMatan Azrad } 8470165bccdSMatan Azrad if (mlx5_mr_btree_init(&priv->mr_scache.cache, 8480165bccdSMatan Azrad MLX5_MR_BTREE_CACHE_N * 2, rte_socket_id()) != 0) { 8490165bccdSMatan Azrad DRV_LOG(ERR, "Failed to allocate shared cache MR memory."); 8500165bccdSMatan Azrad mlx5_compress_hw_global_release(priv); 8510165bccdSMatan Azrad rte_compressdev_pmd_destroy(priv->cdev); 8520165bccdSMatan Azrad claim_zero(mlx5_glue->close_device(priv->ctx)); 8530165bccdSMatan Azrad rte_errno = ENOMEM; 8540165bccdSMatan Azrad return -rte_errno; 8550165bccdSMatan Azrad } 8560165bccdSMatan Azrad priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr; 8570165bccdSMatan Azrad priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr; 8588c090106SMichael Baum /* Register callback function for global shared MR cache management. */ 8598c090106SMichael Baum if (TAILQ_EMPTY(&mlx5_compress_priv_list)) 8608c090106SMichael Baum rte_mem_event_callback_register("MLX5_MEM_EVENT_CB", 8618c090106SMichael Baum mlx5_compress_mr_mem_event_cb, 8628c090106SMichael Baum NULL); 863832a4cf1SMatan Azrad pthread_mutex_lock(&priv_list_lock); 864832a4cf1SMatan Azrad TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next); 865832a4cf1SMatan Azrad pthread_mutex_unlock(&priv_list_lock); 866832a4cf1SMatan Azrad return 0; 867832a4cf1SMatan Azrad } 868832a4cf1SMatan Azrad 869832a4cf1SMatan Azrad static int 87082242186SXueming Li mlx5_compress_dev_remove(struct rte_device *dev) 871832a4cf1SMatan Azrad { 872832a4cf1SMatan Azrad struct mlx5_compress_priv *priv = NULL; 873832a4cf1SMatan Azrad 874832a4cf1SMatan Azrad pthread_mutex_lock(&priv_list_lock); 875832a4cf1SMatan Azrad TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next) 87682242186SXueming Li if (priv->cdev->device == dev) 877832a4cf1SMatan Azrad break; 878832a4cf1SMatan Azrad if (priv) 879832a4cf1SMatan Azrad TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next); 880832a4cf1SMatan Azrad pthread_mutex_unlock(&priv_list_lock); 881832a4cf1SMatan Azrad if (priv) { 8828c090106SMichael Baum if (TAILQ_EMPTY(&mlx5_compress_priv_list)) 8838c090106SMichael Baum rte_mem_event_callback_unregister("MLX5_MEM_EVENT_CB", 8848c090106SMichael Baum NULL); 8850165bccdSMatan Azrad mlx5_mr_release_cache(&priv->mr_scache); 886832a4cf1SMatan Azrad mlx5_compress_hw_global_release(priv); 887832a4cf1SMatan Azrad rte_compressdev_pmd_destroy(priv->cdev); 888832a4cf1SMatan Azrad claim_zero(mlx5_glue->close_device(priv->ctx)); 889832a4cf1SMatan Azrad } 890832a4cf1SMatan Azrad return 0; 891832a4cf1SMatan Azrad } 892832a4cf1SMatan Azrad 893832a4cf1SMatan Azrad static const struct rte_pci_id mlx5_compress_pci_id_map[] = { 894832a4cf1SMatan Azrad { 895832a4cf1SMatan Azrad RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 896832a4cf1SMatan Azrad PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 897832a4cf1SMatan Azrad }, 898832a4cf1SMatan Azrad { 899832a4cf1SMatan Azrad .vendor_id = 0 900832a4cf1SMatan Azrad } 901832a4cf1SMatan Azrad }; 902832a4cf1SMatan Azrad 90382242186SXueming Li static struct mlx5_class_driver mlx5_compress_driver = { 90482242186SXueming Li .drv_class = MLX5_CLASS_COMPRESS, 905832a4cf1SMatan Azrad .name = RTE_STR(MLX5_COMPRESS_DRIVER_NAME), 906832a4cf1SMatan Azrad .id_table = mlx5_compress_pci_id_map, 90782242186SXueming Li .probe = mlx5_compress_dev_probe, 90882242186SXueming Li .remove = mlx5_compress_dev_remove, 909832a4cf1SMatan Azrad }; 910832a4cf1SMatan Azrad 911832a4cf1SMatan Azrad RTE_INIT(rte_mlx5_compress_init) 912832a4cf1SMatan Azrad { 913832a4cf1SMatan Azrad mlx5_common_init(); 914832a4cf1SMatan Azrad if (mlx5_glue != NULL) 91582242186SXueming Li mlx5_class_driver_register(&mlx5_compress_driver); 916832a4cf1SMatan Azrad } 917832a4cf1SMatan Azrad 918eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(mlx5_compress_logtype, NOTICE) 919832a4cf1SMatan Azrad RTE_PMD_EXPORT_NAME(MLX5_COMPRESS_DRIVER_NAME, __COUNTER__); 920832a4cf1SMatan Azrad RTE_PMD_REGISTER_PCI_TABLE(MLX5_COMPRESS_DRIVER_NAME, mlx5_compress_pci_id_map); 921832a4cf1SMatan Azrad RTE_PMD_REGISTER_KMOD_DEP(MLX5_COMPRESS_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 922