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 1240564ddeaSXueming Li mlx5_regex_dev_probe(struct rte_device *rte_dev) 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 1340564ddeaSXueming Li ibv = mlx5_os_get_ibv_dev(rte_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; 149cfc672a9SOri Kam } else if (!attr.regex || attr.regexp_num_of_engines == 0) { 150cfc672a9SOri Kam DRV_LOG(ERR, "Not enough capabilities to support RegEx, maybe " 151cfc672a9SOri Kam "old FW/OFED version?"); 152cfc672a9SOri Kam rte_errno = ENOTSUP; 1531db6ebd4SParav Pandit goto dev_error; 154cfc672a9SOri Kam } 1559428310aSOri Kam if (mlx5_regex_engines_status(ctx, 2)) { 1569428310aSOri Kam DRV_LOG(ERR, "RegEx engine error."); 1579428310aSOri Kam rte_errno = ENOMEM; 1581db6ebd4SParav Pandit goto dev_error; 1599428310aSOri Kam } 160cfc672a9SOri Kam priv = rte_zmalloc("mlx5 regex device private", sizeof(*priv), 161cfc672a9SOri Kam RTE_CACHE_LINE_SIZE); 162cfc672a9SOri Kam if (!priv) { 163cfc672a9SOri Kam DRV_LOG(ERR, "Failed to allocate private memory."); 164cfc672a9SOri Kam rte_errno = ENOMEM; 1653423d02bSMichael Baum goto dev_error; 166cfc672a9SOri Kam } 167dd25bd20SViacheslav Ovsiienko priv->sq_ts_format = attr.sq_ts_format; 168cfc672a9SOri Kam priv->ctx = ctx; 169b34d8163SFrancis Kelly priv->nb_engines = 2; /* attr.regexp_num_of_engines */ 170f324162eSOri Kam ret = mlx5_devx_regex_register_read(priv->ctx, 0, 171f324162eSOri Kam MLX5_RXP_CSR_IDENTIFIER, &val); 172f324162eSOri Kam if (ret) { 173f324162eSOri Kam DRV_LOG(ERR, "CSR read failed!"); 174*0972b7baSMichael Baum goto dev_error; 175f324162eSOri Kam } 176f324162eSOri Kam if (val == MLX5_RXP_BF2_IDENTIFIER) 177f324162eSOri Kam priv->is_bf2 = 1; 178b34d8163SFrancis Kelly /* Default RXP programming mode to Shared. */ 179b34d8163SFrancis Kelly priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE; 1800564ddeaSXueming Li mlx5_regex_get_name(name, rte_dev); 181cfc672a9SOri Kam priv->regexdev = rte_regexdev_register(name); 182cfc672a9SOri Kam if (priv->regexdev == NULL) { 183cfc672a9SOri Kam DRV_LOG(ERR, "Failed to register RegEx device."); 184cfc672a9SOri Kam rte_errno = rte_errno ? rte_errno : EINVAL; 185cfc672a9SOri Kam goto error; 186cfc672a9SOri Kam } 187e8f05161SViacheslav Ovsiienko /* 188e8f05161SViacheslav Ovsiienko * This PMD always claims the write memory barrier on UAR 189e8f05161SViacheslav Ovsiienko * registers writings, it is safe to allocate UAR with any 190e8f05161SViacheslav Ovsiienko * memory mapping type. 191e8f05161SViacheslav Ovsiienko */ 192e8f05161SViacheslav Ovsiienko priv->uar = mlx5_devx_alloc_uar(ctx, -1); 193b34d8163SFrancis Kelly if (!priv->uar) { 194b34d8163SFrancis Kelly DRV_LOG(ERR, "can't allocate uar."); 195b34d8163SFrancis Kelly rte_errno = ENOMEM; 196b34d8163SFrancis Kelly goto error; 197b34d8163SFrancis Kelly } 198b34d8163SFrancis Kelly priv->pd = mlx5_glue->alloc_pd(ctx); 199b34d8163SFrancis Kelly if (!priv->pd) { 200b34d8163SFrancis Kelly DRV_LOG(ERR, "can't allocate pd."); 201b34d8163SFrancis Kelly rte_errno = ENOMEM; 202b34d8163SFrancis Kelly goto error; 203b34d8163SFrancis Kelly } 204cfc672a9SOri Kam priv->regexdev->dev_ops = &mlx5_regexdev_ops; 2054d4e245aSYuval Avnery priv->regexdev->enqueue = mlx5_regexdev_enqueue; 206330a70b7SSuanming Mou #ifdef HAVE_MLX5_UMR_IMKEY 207330a70b7SSuanming Mou if (!attr.umr_indirect_mkey_disabled && 208330a70b7SSuanming Mou !attr.umr_modify_entity_size_disabled) 209330a70b7SSuanming Mou priv->has_umr = 1; 210330a70b7SSuanming Mou if (priv->has_umr) 211330a70b7SSuanming Mou priv->regexdev->enqueue = mlx5_regexdev_enqueue_gga; 212330a70b7SSuanming Mou #endif 2130db041e7SYuval Avnery priv->regexdev->dequeue = mlx5_regexdev_dequeue; 2140564ddeaSXueming Li priv->regexdev->device = rte_dev; 215cfc672a9SOri Kam priv->regexdev->data->dev_private = priv; 216e3dbbf71SOri Kam priv->regexdev->state = RTE_REGEXDEV_READY; 217cda883bbSYuval Avnery priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr; 218cda883bbSYuval Avnery priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr; 219cda883bbSYuval Avnery ret = mlx5_mr_btree_init(&priv->mr_scache.cache, 220cda883bbSYuval Avnery MLX5_MR_BTREE_CACHE_N * 2, 221cda883bbSYuval Avnery rte_socket_id()); 222cda883bbSYuval Avnery if (ret) { 223cda883bbSYuval Avnery DRV_LOG(ERR, "MR init tree failed."); 224cda883bbSYuval Avnery rte_errno = ENOMEM; 225cda883bbSYuval Avnery goto error; 226cda883bbSYuval Avnery } 22729ca3215SMichael Baum /* Register callback function for global shared MR cache management. */ 22829ca3215SMichael Baum if (TAILQ_EMPTY(&mlx5_mem_event_list)) 22929ca3215SMichael Baum rte_mem_event_callback_register("MLX5_MEM_EVENT_CB", 23029ca3215SMichael Baum mlx5_regex_mr_mem_event_cb, 23129ca3215SMichael Baum NULL); 23229ca3215SMichael Baum /* Add device to memory callback list. */ 23329ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 23429ca3215SMichael Baum TAILQ_INSERT_TAIL(&mlx5_mem_event_list, priv, mem_event_cb); 23529ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 236330a70b7SSuanming Mou DRV_LOG(INFO, "RegEx GGA is %s.", 237330a70b7SSuanming Mou priv->has_umr ? "supported" : "unsupported"); 238cfc672a9SOri Kam return 0; 239cfc672a9SOri Kam 240cfc672a9SOri Kam error: 241b34d8163SFrancis Kelly if (priv->pd) 242b34d8163SFrancis Kelly mlx5_glue->dealloc_pd(priv->pd); 243b34d8163SFrancis Kelly if (priv->uar) 244b34d8163SFrancis Kelly mlx5_glue->devx_free_uar(priv->uar); 245b34d8163SFrancis Kelly if (priv->regexdev) 246b34d8163SFrancis Kelly rte_regexdev_unregister(priv->regexdev); 2471db6ebd4SParav Pandit dev_error: 248cfc672a9SOri Kam if (ctx) 249cfc672a9SOri Kam mlx5_glue->close_device(ctx); 250cfc672a9SOri Kam if (priv) 251cfc672a9SOri Kam rte_free(priv); 252cfc672a9SOri Kam return -rte_errno; 253cfc672a9SOri Kam } 254cfc672a9SOri Kam 255cfc672a9SOri Kam static int 2560564ddeaSXueming Li mlx5_regex_dev_remove(struct rte_device *rte_dev) 257cfc672a9SOri Kam { 258cfc672a9SOri Kam char name[RTE_REGEXDEV_NAME_MAX_LEN]; 259cfc672a9SOri Kam struct rte_regexdev *dev; 260cfc672a9SOri Kam struct mlx5_regex_priv *priv = NULL; 261cfc672a9SOri Kam 2620564ddeaSXueming Li mlx5_regex_get_name(name, rte_dev); 263cfc672a9SOri Kam dev = rte_regexdev_get_device_by_name(name); 264cfc672a9SOri Kam if (!dev) 265cfc672a9SOri Kam return 0; 266cfc672a9SOri Kam priv = dev->data->dev_private; 267cfc672a9SOri Kam if (priv) { 26829ca3215SMichael Baum /* Remove from memory callback device list. */ 26929ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 27029ca3215SMichael Baum TAILQ_REMOVE(&mlx5_mem_event_list, priv, mem_event_cb); 27129ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 27229ca3215SMichael Baum if (TAILQ_EMPTY(&mlx5_mem_event_list)) 27329ca3215SMichael Baum rte_mem_event_callback_unregister("MLX5_MEM_EVENT_CB", 27429ca3215SMichael Baum NULL); 275a1fcde8cSMichael Baum if (priv->mr_scache.cache.table) 276a1fcde8cSMichael Baum mlx5_mr_release_cache(&priv->mr_scache); 277b34d8163SFrancis Kelly if (priv->pd) 278b34d8163SFrancis Kelly mlx5_glue->dealloc_pd(priv->pd); 279b34d8163SFrancis Kelly if (priv->uar) 280b34d8163SFrancis Kelly mlx5_glue->devx_free_uar(priv->uar); 281b34d8163SFrancis Kelly if (priv->regexdev) 282b34d8163SFrancis Kelly rte_regexdev_unregister(priv->regexdev); 283cfc672a9SOri Kam if (priv->ctx) 284cfc672a9SOri Kam mlx5_glue->close_device(priv->ctx); 285cfc672a9SOri Kam rte_free(priv); 286cfc672a9SOri Kam } 287cfc672a9SOri Kam return 0; 288cfc672a9SOri Kam } 289cfc672a9SOri Kam 290cfc672a9SOri Kam static const struct rte_pci_id mlx5_regex_pci_id_map[] = { 291cfc672a9SOri Kam { 292cfc672a9SOri Kam RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 293cfc672a9SOri Kam PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 294cfc672a9SOri Kam }, 295cfc672a9SOri Kam { 2966ca37b06SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2976ca37b06SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX7BF) 2986ca37b06SRaslan Darawsheh }, 2996ca37b06SRaslan Darawsheh { 300cfc672a9SOri Kam .vendor_id = 0 301cfc672a9SOri Kam } 302cfc672a9SOri Kam }; 303cfc672a9SOri Kam 3040564ddeaSXueming Li static struct mlx5_class_driver mlx5_regex_driver = { 3050564ddeaSXueming Li .drv_class = MLX5_CLASS_REGEX, 30650458c9dSThomas Monjalon .name = RTE_STR(MLX5_REGEX_DRIVER_NAME), 307cfc672a9SOri Kam .id_table = mlx5_regex_pci_id_map, 3080564ddeaSXueming Li .probe = mlx5_regex_dev_probe, 3090564ddeaSXueming Li .remove = mlx5_regex_dev_remove, 310cfc672a9SOri Kam }; 311cfc672a9SOri Kam 312cfc672a9SOri Kam RTE_INIT(rte_mlx5_regex_init) 313cfc672a9SOri Kam { 31482088001SParav Pandit mlx5_common_init(); 315cfc672a9SOri Kam if (mlx5_glue) 3160564ddeaSXueming Li mlx5_class_driver_register(&mlx5_regex_driver); 317cfc672a9SOri Kam } 318cfc672a9SOri Kam 319eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(mlx5_regex_logtype, NOTICE) 32050458c9dSThomas Monjalon RTE_PMD_EXPORT_NAME(MLX5_REGEX_DRIVER_NAME, __COUNTER__); 32150458c9dSThomas Monjalon RTE_PMD_REGISTER_PCI_TABLE(MLX5_REGEX_DRIVER_NAME, mlx5_regex_pci_id_map); 32250458c9dSThomas Monjalon RTE_PMD_REGISTER_KMOD_DEP(MLX5_REGEX_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 323