1cf9b3c36SYuval Avnery /* SPDX-License-Identifier: BSD-3-Clause 2cf9b3c36SYuval Avnery * Copyright 2020 Mellanox Technologies, Ltd 3cf9b3c36SYuval Avnery */ 4cf9b3c36SYuval Avnery 5cfc672a9SOri Kam #include <rte_malloc.h> 6cfc672a9SOri Kam #include <rte_log.h> 7cfc672a9SOri Kam #include <rte_errno.h> 8cfc672a9SOri Kam #include <rte_pci.h> 9cfc672a9SOri Kam #include <rte_regexdev.h> 10cfc672a9SOri Kam #include <rte_regexdev_core.h> 11cfc672a9SOri Kam #include <rte_regexdev_driver.h> 120564ddeaSXueming Li #include <rte_bus_pci.h> 13cfc672a9SOri Kam 14c31f3f7fSShiri Kuzin #include <mlx5_common.h> 1529ca3215SMichael Baum #include <mlx5_common_mr.h> 16cfc672a9SOri Kam #include <mlx5_glue.h> 17cfc672a9SOri Kam #include <mlx5_devx_cmds.h> 18cfc672a9SOri Kam #include <mlx5_prm.h> 19cfc672a9SOri Kam 20cf9b3c36SYuval Avnery #include "mlx5_regex.h" 21215b1223SYuval Avnery #include "mlx5_regex_utils.h" 229428310aSOri Kam #include "mlx5_rxp_csrs.h" 23215b1223SYuval Avnery 2450458c9dSThomas Monjalon #define MLX5_REGEX_DRIVER_NAME regex_mlx5 2550458c9dSThomas Monjalon 26215b1223SYuval Avnery int mlx5_regex_logtype; 27215b1223SYuval Avnery 2829ca3215SMichael Baum TAILQ_HEAD(regex_mem_event, mlx5_regex_priv) mlx5_mem_event_list = 2929ca3215SMichael Baum TAILQ_HEAD_INITIALIZER(mlx5_mem_event_list); 3029ca3215SMichael Baum static pthread_mutex_t mem_event_list_lock = PTHREAD_MUTEX_INITIALIZER; 3129ca3215SMichael Baum 32c126512bSOri Kam const struct rte_regexdev_ops mlx5_regexdev_ops = { 33c126512bSOri Kam .dev_info_get = mlx5_regex_info_get, 34e3dbbf71SOri Kam .dev_configure = mlx5_regex_configure, 35b34d8163SFrancis Kelly .dev_db_import = mlx5_regex_rules_db_import, 36fbc8c700SOri Kam .dev_qp_setup = mlx5_regex_qp_setup, 37aea75c5aSOri Kam .dev_start = mlx5_regex_start, 38aea75c5aSOri Kam .dev_stop = mlx5_regex_stop, 39aea75c5aSOri Kam .dev_close = mlx5_regex_close, 40c126512bSOri Kam }; 41cfc672a9SOri Kam 42aea75c5aSOri Kam int 43aea75c5aSOri Kam mlx5_regex_start(struct rte_regexdev *dev __rte_unused) 44aea75c5aSOri Kam { 45aea75c5aSOri Kam return 0; 46aea75c5aSOri Kam } 47aea75c5aSOri Kam 48aea75c5aSOri Kam int 49aea75c5aSOri Kam mlx5_regex_stop(struct rte_regexdev *dev __rte_unused) 50aea75c5aSOri Kam { 51aea75c5aSOri Kam return 0; 52aea75c5aSOri Kam } 53aea75c5aSOri Kam 54aea75c5aSOri Kam int 55aea75c5aSOri Kam mlx5_regex_close(struct rte_regexdev *dev __rte_unused) 56aea75c5aSOri Kam { 57aea75c5aSOri Kam return 0; 58aea75c5aSOri Kam } 59aea75c5aSOri Kam 609428310aSOri Kam static int 619428310aSOri Kam mlx5_regex_engines_status(struct ibv_context *ctx, int num_engines) 629428310aSOri Kam { 639428310aSOri Kam uint32_t fpga_ident = 0; 649428310aSOri Kam int err; 659428310aSOri Kam int i; 669428310aSOri Kam 679428310aSOri Kam for (i = 0; i < num_engines; i++) { 689428310aSOri Kam err = mlx5_devx_regex_register_read(ctx, i, 699428310aSOri Kam MLX5_RXP_CSR_IDENTIFIER, 709428310aSOri Kam &fpga_ident); 719428310aSOri Kam fpga_ident = (fpga_ident & (0x0000FFFF)); 729428310aSOri Kam if (err || fpga_ident != MLX5_RXP_IDENTIFIER) { 739428310aSOri Kam DRV_LOG(ERR, "Failed setup RXP %d err %d database " 749428310aSOri Kam "memory 0x%x", i, err, fpga_ident); 759428310aSOri Kam if (!err) 769428310aSOri Kam err = EINVAL; 779428310aSOri Kam return err; 789428310aSOri Kam } 799428310aSOri Kam } 809428310aSOri Kam return 0; 819428310aSOri Kam } 82cfc672a9SOri Kam 83cfc672a9SOri Kam static void 840564ddeaSXueming Li mlx5_regex_get_name(char *name, struct rte_device *dev) 85cfc672a9SOri Kam { 860564ddeaSXueming Li sprintf(name, "mlx5_regex_%s", dev->name); 87cfc672a9SOri Kam } 88cfc672a9SOri Kam 8929ca3215SMichael Baum /** 9029ca3215SMichael Baum * Callback for memory event. 9129ca3215SMichael Baum * 9229ca3215SMichael Baum * @param event_type 9329ca3215SMichael Baum * Memory event type. 9429ca3215SMichael Baum * @param addr 9529ca3215SMichael Baum * Address of memory. 9629ca3215SMichael Baum * @param len 9729ca3215SMichael Baum * Size of memory. 9829ca3215SMichael Baum */ 9929ca3215SMichael Baum static void 10029ca3215SMichael Baum mlx5_regex_mr_mem_event_cb(enum rte_mem_event event_type, const void *addr, 10129ca3215SMichael Baum size_t len, void *arg __rte_unused) 10229ca3215SMichael Baum { 10329ca3215SMichael Baum struct mlx5_regex_priv *priv; 10429ca3215SMichael Baum 10529ca3215SMichael Baum /* Must be called from the primary process. */ 10629ca3215SMichael Baum MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 10729ca3215SMichael Baum switch (event_type) { 10829ca3215SMichael Baum case RTE_MEM_EVENT_FREE: 10929ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 11029ca3215SMichael Baum /* Iterate all the existing mlx5 devices. */ 11129ca3215SMichael Baum TAILQ_FOREACH(priv, &mlx5_mem_event_list, mem_event_cb) 11229ca3215SMichael Baum mlx5_free_mr_by_addr(&priv->mr_scache, 11329ca3215SMichael Baum priv->ctx->device->name, 11429ca3215SMichael Baum addr, len); 11529ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 11629ca3215SMichael Baum break; 11729ca3215SMichael Baum case RTE_MEM_EVENT_ALLOC: 11829ca3215SMichael Baum default: 11929ca3215SMichael Baum break; 12029ca3215SMichael Baum } 12129ca3215SMichael Baum } 12229ca3215SMichael Baum 123cfc672a9SOri Kam static int 124*7af08c8fSMichael Baum mlx5_regex_dev_probe(struct mlx5_common_device *cdev) 125cfc672a9SOri Kam { 126cfc672a9SOri Kam struct ibv_device *ibv; 127cfc672a9SOri Kam struct mlx5_regex_priv *priv = NULL; 128cfc672a9SOri Kam struct ibv_context *ctx = NULL; 129cfc672a9SOri Kam struct mlx5_hca_attr attr; 130cfc672a9SOri Kam char name[RTE_REGEXDEV_NAME_MAX_LEN]; 131cfc672a9SOri Kam int ret; 132f324162eSOri Kam uint32_t val; 133cfc672a9SOri Kam 134*7af08c8fSMichael Baum ibv = mlx5_os_get_ibv_dev(cdev->dev); 1350564ddeaSXueming Li if (ibv == NULL) 136cfc672a9SOri Kam return -rte_errno; 1370564ddeaSXueming Li DRV_LOG(INFO, "Probe device \"%s\".", ibv->name); 138cfc672a9SOri Kam ctx = mlx5_glue->dv_open_device(ibv); 139cfc672a9SOri Kam if (!ctx) { 140cfc672a9SOri Kam DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name); 141cfc672a9SOri Kam rte_errno = ENODEV; 142cfc672a9SOri Kam return -rte_errno; 143cfc672a9SOri Kam } 144cfc672a9SOri Kam ret = mlx5_devx_cmd_query_hca_attr(ctx, &attr); 145cfc672a9SOri Kam if (ret) { 146cfc672a9SOri Kam DRV_LOG(ERR, "Unable to read HCA capabilities."); 147cfc672a9SOri Kam rte_errno = ENOTSUP; 1481db6ebd4SParav Pandit goto dev_error; 14927003260SRaja Zidane } else if (((!attr.regex) && (!attr.mmo_regex_sq_en) && 15027003260SRaja Zidane (!attr.mmo_regex_qp_en)) || attr.regexp_num_of_engines == 0) { 151cfc672a9SOri Kam DRV_LOG(ERR, "Not enough capabilities to support RegEx, maybe " 152cfc672a9SOri Kam "old FW/OFED version?"); 153cfc672a9SOri Kam rte_errno = ENOTSUP; 1541db6ebd4SParav Pandit goto dev_error; 155cfc672a9SOri Kam } 1569428310aSOri Kam if (mlx5_regex_engines_status(ctx, 2)) { 1579428310aSOri Kam DRV_LOG(ERR, "RegEx engine error."); 1589428310aSOri Kam rte_errno = ENOMEM; 1591db6ebd4SParav Pandit goto dev_error; 1609428310aSOri Kam } 161cfc672a9SOri Kam priv = rte_zmalloc("mlx5 regex device private", sizeof(*priv), 162cfc672a9SOri Kam RTE_CACHE_LINE_SIZE); 163cfc672a9SOri Kam if (!priv) { 164cfc672a9SOri Kam DRV_LOG(ERR, "Failed to allocate private memory."); 165cfc672a9SOri Kam rte_errno = ENOMEM; 1663423d02bSMichael Baum goto dev_error; 167cfc672a9SOri Kam } 16827003260SRaja Zidane priv->mmo_regex_qp_cap = attr.mmo_regex_qp_en; 16927003260SRaja Zidane priv->mmo_regex_sq_cap = attr.mmo_regex_sq_en; 17027003260SRaja Zidane priv->qp_ts_format = attr.qp_ts_format; 171cfc672a9SOri Kam priv->ctx = ctx; 172b34d8163SFrancis Kelly priv->nb_engines = 2; /* attr.regexp_num_of_engines */ 173f324162eSOri Kam ret = mlx5_devx_regex_register_read(priv->ctx, 0, 174f324162eSOri Kam MLX5_RXP_CSR_IDENTIFIER, &val); 175f324162eSOri Kam if (ret) { 176f324162eSOri Kam DRV_LOG(ERR, "CSR read failed!"); 1770972b7baSMichael Baum goto dev_error; 178f324162eSOri Kam } 179f324162eSOri Kam if (val == MLX5_RXP_BF2_IDENTIFIER) 180f324162eSOri Kam priv->is_bf2 = 1; 181b34d8163SFrancis Kelly /* Default RXP programming mode to Shared. */ 182b34d8163SFrancis Kelly priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE; 183*7af08c8fSMichael Baum mlx5_regex_get_name(name, cdev->dev); 184cfc672a9SOri Kam priv->regexdev = rte_regexdev_register(name); 185cfc672a9SOri Kam if (priv->regexdev == NULL) { 186cfc672a9SOri Kam DRV_LOG(ERR, "Failed to register RegEx device."); 187cfc672a9SOri Kam rte_errno = rte_errno ? rte_errno : EINVAL; 188cfc672a9SOri Kam goto error; 189cfc672a9SOri Kam } 190e8f05161SViacheslav Ovsiienko /* 191e8f05161SViacheslav Ovsiienko * This PMD always claims the write memory barrier on UAR 192e8f05161SViacheslav Ovsiienko * registers writings, it is safe to allocate UAR with any 193e8f05161SViacheslav Ovsiienko * memory mapping type. 194e8f05161SViacheslav Ovsiienko */ 195e8f05161SViacheslav Ovsiienko priv->uar = mlx5_devx_alloc_uar(ctx, -1); 196b34d8163SFrancis Kelly if (!priv->uar) { 197b34d8163SFrancis Kelly DRV_LOG(ERR, "can't allocate uar."); 198b34d8163SFrancis Kelly rte_errno = ENOMEM; 199b34d8163SFrancis Kelly goto error; 200b34d8163SFrancis Kelly } 201b34d8163SFrancis Kelly priv->pd = mlx5_glue->alloc_pd(ctx); 202b34d8163SFrancis Kelly if (!priv->pd) { 203b34d8163SFrancis Kelly DRV_LOG(ERR, "can't allocate pd."); 204b34d8163SFrancis Kelly rte_errno = ENOMEM; 205b34d8163SFrancis Kelly goto error; 206b34d8163SFrancis Kelly } 207cfc672a9SOri Kam priv->regexdev->dev_ops = &mlx5_regexdev_ops; 2084d4e245aSYuval Avnery priv->regexdev->enqueue = mlx5_regexdev_enqueue; 209330a70b7SSuanming Mou #ifdef HAVE_MLX5_UMR_IMKEY 210330a70b7SSuanming Mou if (!attr.umr_indirect_mkey_disabled && 211330a70b7SSuanming Mou !attr.umr_modify_entity_size_disabled) 212330a70b7SSuanming Mou priv->has_umr = 1; 213330a70b7SSuanming Mou if (priv->has_umr) 214330a70b7SSuanming Mou priv->regexdev->enqueue = mlx5_regexdev_enqueue_gga; 215330a70b7SSuanming Mou #endif 2160db041e7SYuval Avnery priv->regexdev->dequeue = mlx5_regexdev_dequeue; 217*7af08c8fSMichael Baum priv->regexdev->device = cdev->dev; 218cfc672a9SOri Kam priv->regexdev->data->dev_private = priv; 219e3dbbf71SOri Kam priv->regexdev->state = RTE_REGEXDEV_READY; 220cda883bbSYuval Avnery priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr; 221cda883bbSYuval Avnery priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr; 222cda883bbSYuval Avnery ret = mlx5_mr_btree_init(&priv->mr_scache.cache, 223cda883bbSYuval Avnery MLX5_MR_BTREE_CACHE_N * 2, 224cda883bbSYuval Avnery rte_socket_id()); 225cda883bbSYuval Avnery if (ret) { 226cda883bbSYuval Avnery DRV_LOG(ERR, "MR init tree failed."); 227cda883bbSYuval Avnery rte_errno = ENOMEM; 228cda883bbSYuval Avnery goto error; 229cda883bbSYuval Avnery } 23029ca3215SMichael Baum /* Register callback function for global shared MR cache management. */ 23129ca3215SMichael Baum if (TAILQ_EMPTY(&mlx5_mem_event_list)) 23229ca3215SMichael Baum rte_mem_event_callback_register("MLX5_MEM_EVENT_CB", 23329ca3215SMichael Baum mlx5_regex_mr_mem_event_cb, 23429ca3215SMichael Baum NULL); 23529ca3215SMichael Baum /* Add device to memory callback list. */ 23629ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 23729ca3215SMichael Baum TAILQ_INSERT_TAIL(&mlx5_mem_event_list, priv, mem_event_cb); 23829ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 239330a70b7SSuanming Mou DRV_LOG(INFO, "RegEx GGA is %s.", 240330a70b7SSuanming Mou priv->has_umr ? "supported" : "unsupported"); 241cfc672a9SOri Kam return 0; 242cfc672a9SOri Kam 243cfc672a9SOri Kam error: 244b34d8163SFrancis Kelly if (priv->pd) 245b34d8163SFrancis Kelly mlx5_glue->dealloc_pd(priv->pd); 246b34d8163SFrancis Kelly if (priv->uar) 247b34d8163SFrancis Kelly mlx5_glue->devx_free_uar(priv->uar); 248b34d8163SFrancis Kelly if (priv->regexdev) 249b34d8163SFrancis Kelly rte_regexdev_unregister(priv->regexdev); 2501db6ebd4SParav Pandit dev_error: 251cfc672a9SOri Kam if (ctx) 252cfc672a9SOri Kam mlx5_glue->close_device(ctx); 253cfc672a9SOri Kam if (priv) 254cfc672a9SOri Kam rte_free(priv); 255cfc672a9SOri Kam return -rte_errno; 256cfc672a9SOri Kam } 257cfc672a9SOri Kam 258cfc672a9SOri Kam static int 259*7af08c8fSMichael Baum mlx5_regex_dev_remove(struct mlx5_common_device *cdev) 260cfc672a9SOri Kam { 261cfc672a9SOri Kam char name[RTE_REGEXDEV_NAME_MAX_LEN]; 262cfc672a9SOri Kam struct rte_regexdev *dev; 263cfc672a9SOri Kam struct mlx5_regex_priv *priv = NULL; 264cfc672a9SOri Kam 265*7af08c8fSMichael Baum mlx5_regex_get_name(name, cdev->dev); 266cfc672a9SOri Kam dev = rte_regexdev_get_device_by_name(name); 267cfc672a9SOri Kam if (!dev) 268cfc672a9SOri Kam return 0; 269cfc672a9SOri Kam priv = dev->data->dev_private; 270cfc672a9SOri Kam if (priv) { 27129ca3215SMichael Baum /* Remove from memory callback device list. */ 27229ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 27329ca3215SMichael Baum TAILQ_REMOVE(&mlx5_mem_event_list, priv, mem_event_cb); 27429ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 27529ca3215SMichael Baum if (TAILQ_EMPTY(&mlx5_mem_event_list)) 27629ca3215SMichael Baum rte_mem_event_callback_unregister("MLX5_MEM_EVENT_CB", 27729ca3215SMichael Baum NULL); 278a1fcde8cSMichael Baum if (priv->mr_scache.cache.table) 279a1fcde8cSMichael Baum mlx5_mr_release_cache(&priv->mr_scache); 280b34d8163SFrancis Kelly if (priv->pd) 281b34d8163SFrancis Kelly mlx5_glue->dealloc_pd(priv->pd); 282b34d8163SFrancis Kelly if (priv->uar) 283b34d8163SFrancis Kelly mlx5_glue->devx_free_uar(priv->uar); 284b34d8163SFrancis Kelly if (priv->regexdev) 285b34d8163SFrancis Kelly rte_regexdev_unregister(priv->regexdev); 286cfc672a9SOri Kam if (priv->ctx) 287cfc672a9SOri Kam mlx5_glue->close_device(priv->ctx); 288cfc672a9SOri Kam rte_free(priv); 289cfc672a9SOri Kam } 290cfc672a9SOri Kam return 0; 291cfc672a9SOri Kam } 292cfc672a9SOri Kam 293cfc672a9SOri Kam static const struct rte_pci_id mlx5_regex_pci_id_map[] = { 294cfc672a9SOri Kam { 295cfc672a9SOri Kam RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 296cfc672a9SOri Kam PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 297cfc672a9SOri Kam }, 298cfc672a9SOri Kam { 2996ca37b06SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 3006ca37b06SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX7BF) 3016ca37b06SRaslan Darawsheh }, 3026ca37b06SRaslan Darawsheh { 303cfc672a9SOri Kam .vendor_id = 0 304cfc672a9SOri Kam } 305cfc672a9SOri Kam }; 306cfc672a9SOri Kam 3070564ddeaSXueming Li static struct mlx5_class_driver mlx5_regex_driver = { 3080564ddeaSXueming Li .drv_class = MLX5_CLASS_REGEX, 30950458c9dSThomas Monjalon .name = RTE_STR(MLX5_REGEX_DRIVER_NAME), 310cfc672a9SOri Kam .id_table = mlx5_regex_pci_id_map, 3110564ddeaSXueming Li .probe = mlx5_regex_dev_probe, 3120564ddeaSXueming Li .remove = mlx5_regex_dev_remove, 313cfc672a9SOri Kam }; 314cfc672a9SOri Kam 315cfc672a9SOri Kam RTE_INIT(rte_mlx5_regex_init) 316cfc672a9SOri Kam { 31782088001SParav Pandit mlx5_common_init(); 318cfc672a9SOri Kam if (mlx5_glue) 3190564ddeaSXueming Li mlx5_class_driver_register(&mlx5_regex_driver); 320cfc672a9SOri Kam } 321cfc672a9SOri Kam 322eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(mlx5_regex_logtype, NOTICE) 32350458c9dSThomas Monjalon RTE_PMD_EXPORT_NAME(MLX5_REGEX_DRIVER_NAME, __COUNTER__); 32450458c9dSThomas Monjalon RTE_PMD_REGISTER_PCI_TABLE(MLX5_REGEX_DRIVER_NAME, mlx5_regex_pci_id_map); 32550458c9dSThomas Monjalon RTE_PMD_REGISTER_KMOD_DEP(MLX5_REGEX_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 326