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, 113*ca1418ceSMichael Baum mlx5_os_get_ctx_device_name 114*ca1418ceSMichael Baum (priv->cdev->ctx), 11529ca3215SMichael Baum addr, len); 11629ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 11729ca3215SMichael Baum break; 11829ca3215SMichael Baum case RTE_MEM_EVENT_ALLOC: 11929ca3215SMichael Baum default: 12029ca3215SMichael Baum break; 12129ca3215SMichael Baum } 12229ca3215SMichael Baum } 12329ca3215SMichael Baum 124cfc672a9SOri Kam static int 1257af08c8fSMichael Baum mlx5_regex_dev_probe(struct mlx5_common_device *cdev) 126cfc672a9SOri Kam { 127cfc672a9SOri Kam struct mlx5_regex_priv *priv = NULL; 128cfc672a9SOri Kam struct mlx5_hca_attr attr; 129cfc672a9SOri Kam char name[RTE_REGEXDEV_NAME_MAX_LEN]; 130cfc672a9SOri Kam int ret; 131f324162eSOri Kam uint32_t val; 132cfc672a9SOri Kam 133*ca1418ceSMichael Baum ret = mlx5_devx_cmd_query_hca_attr(cdev->ctx, &attr); 134cfc672a9SOri Kam if (ret) { 135cfc672a9SOri Kam DRV_LOG(ERR, "Unable to read HCA capabilities."); 136cfc672a9SOri Kam rte_errno = ENOTSUP; 137*ca1418ceSMichael Baum return -rte_errno; 13827003260SRaja Zidane } else if (((!attr.regex) && (!attr.mmo_regex_sq_en) && 13927003260SRaja Zidane (!attr.mmo_regex_qp_en)) || attr.regexp_num_of_engines == 0) { 140cfc672a9SOri Kam DRV_LOG(ERR, "Not enough capabilities to support RegEx, maybe " 141cfc672a9SOri Kam "old FW/OFED version?"); 142cfc672a9SOri Kam rte_errno = ENOTSUP; 143*ca1418ceSMichael Baum return -rte_errno; 144cfc672a9SOri Kam } 145*ca1418ceSMichael Baum if (mlx5_regex_engines_status(cdev->ctx, 2)) { 1469428310aSOri Kam DRV_LOG(ERR, "RegEx engine error."); 1479428310aSOri Kam rte_errno = ENOMEM; 148*ca1418ceSMichael Baum return -rte_errno; 1499428310aSOri Kam } 150cfc672a9SOri Kam priv = rte_zmalloc("mlx5 regex device private", sizeof(*priv), 151cfc672a9SOri Kam RTE_CACHE_LINE_SIZE); 152cfc672a9SOri Kam if (!priv) { 153cfc672a9SOri Kam DRV_LOG(ERR, "Failed to allocate private memory."); 154cfc672a9SOri Kam rte_errno = ENOMEM; 155*ca1418ceSMichael Baum return -rte_errno; 156cfc672a9SOri Kam } 15727003260SRaja Zidane priv->mmo_regex_qp_cap = attr.mmo_regex_qp_en; 15827003260SRaja Zidane priv->mmo_regex_sq_cap = attr.mmo_regex_sq_en; 15927003260SRaja Zidane priv->qp_ts_format = attr.qp_ts_format; 160*ca1418ceSMichael Baum priv->cdev = cdev; 161b34d8163SFrancis Kelly priv->nb_engines = 2; /* attr.regexp_num_of_engines */ 162*ca1418ceSMichael Baum ret = mlx5_devx_regex_register_read(priv->cdev->ctx, 0, 163f324162eSOri Kam MLX5_RXP_CSR_IDENTIFIER, &val); 164f324162eSOri Kam if (ret) { 165f324162eSOri Kam DRV_LOG(ERR, "CSR read failed!"); 1660972b7baSMichael Baum goto dev_error; 167f324162eSOri Kam } 168f324162eSOri Kam if (val == MLX5_RXP_BF2_IDENTIFIER) 169f324162eSOri Kam priv->is_bf2 = 1; 170b34d8163SFrancis Kelly /* Default RXP programming mode to Shared. */ 171b34d8163SFrancis Kelly priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE; 1727af08c8fSMichael Baum mlx5_regex_get_name(name, cdev->dev); 173cfc672a9SOri Kam priv->regexdev = rte_regexdev_register(name); 174cfc672a9SOri Kam if (priv->regexdev == NULL) { 175cfc672a9SOri Kam DRV_LOG(ERR, "Failed to register RegEx device."); 176cfc672a9SOri Kam rte_errno = rte_errno ? rte_errno : EINVAL; 177*ca1418ceSMichael Baum goto dev_error; 178cfc672a9SOri Kam } 179e8f05161SViacheslav Ovsiienko /* 180e8f05161SViacheslav Ovsiienko * This PMD always claims the write memory barrier on UAR 181e8f05161SViacheslav Ovsiienko * registers writings, it is safe to allocate UAR with any 182e8f05161SViacheslav Ovsiienko * memory mapping type. 183e8f05161SViacheslav Ovsiienko */ 184*ca1418ceSMichael Baum priv->uar = mlx5_devx_alloc_uar(priv->cdev->ctx, -1); 185b34d8163SFrancis Kelly if (!priv->uar) { 186b34d8163SFrancis Kelly DRV_LOG(ERR, "can't allocate uar."); 187b34d8163SFrancis Kelly rte_errno = ENOMEM; 188b34d8163SFrancis Kelly goto error; 189b34d8163SFrancis Kelly } 190*ca1418ceSMichael Baum priv->pd = mlx5_glue->alloc_pd(priv->cdev->ctx); 191b34d8163SFrancis Kelly if (!priv->pd) { 192b34d8163SFrancis Kelly DRV_LOG(ERR, "can't allocate pd."); 193b34d8163SFrancis Kelly rte_errno = ENOMEM; 194b34d8163SFrancis Kelly goto error; 195b34d8163SFrancis Kelly } 196cfc672a9SOri Kam priv->regexdev->dev_ops = &mlx5_regexdev_ops; 1974d4e245aSYuval Avnery priv->regexdev->enqueue = mlx5_regexdev_enqueue; 198330a70b7SSuanming Mou #ifdef HAVE_MLX5_UMR_IMKEY 199330a70b7SSuanming Mou if (!attr.umr_indirect_mkey_disabled && 200330a70b7SSuanming Mou !attr.umr_modify_entity_size_disabled) 201330a70b7SSuanming Mou priv->has_umr = 1; 202330a70b7SSuanming Mou if (priv->has_umr) 203330a70b7SSuanming Mou priv->regexdev->enqueue = mlx5_regexdev_enqueue_gga; 204330a70b7SSuanming Mou #endif 2050db041e7SYuval Avnery priv->regexdev->dequeue = mlx5_regexdev_dequeue; 2067af08c8fSMichael Baum priv->regexdev->device = cdev->dev; 207cfc672a9SOri Kam priv->regexdev->data->dev_private = priv; 208e3dbbf71SOri Kam priv->regexdev->state = RTE_REGEXDEV_READY; 209cda883bbSYuval Avnery priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr; 210cda883bbSYuval Avnery priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr; 211cda883bbSYuval Avnery ret = mlx5_mr_btree_init(&priv->mr_scache.cache, 212cda883bbSYuval Avnery MLX5_MR_BTREE_CACHE_N * 2, 213cda883bbSYuval Avnery rte_socket_id()); 214cda883bbSYuval Avnery if (ret) { 215cda883bbSYuval Avnery DRV_LOG(ERR, "MR init tree failed."); 216cda883bbSYuval Avnery rte_errno = ENOMEM; 217cda883bbSYuval Avnery goto error; 218cda883bbSYuval Avnery } 21929ca3215SMichael Baum /* Register callback function for global shared MR cache management. */ 22029ca3215SMichael Baum if (TAILQ_EMPTY(&mlx5_mem_event_list)) 22129ca3215SMichael Baum rte_mem_event_callback_register("MLX5_MEM_EVENT_CB", 22229ca3215SMichael Baum mlx5_regex_mr_mem_event_cb, 22329ca3215SMichael Baum NULL); 22429ca3215SMichael Baum /* Add device to memory callback list. */ 22529ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 22629ca3215SMichael Baum TAILQ_INSERT_TAIL(&mlx5_mem_event_list, priv, mem_event_cb); 22729ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 228330a70b7SSuanming Mou DRV_LOG(INFO, "RegEx GGA is %s.", 229330a70b7SSuanming Mou priv->has_umr ? "supported" : "unsupported"); 230cfc672a9SOri Kam return 0; 231cfc672a9SOri Kam 232cfc672a9SOri Kam error: 233b34d8163SFrancis Kelly if (priv->pd) 234b34d8163SFrancis Kelly mlx5_glue->dealloc_pd(priv->pd); 235b34d8163SFrancis Kelly if (priv->uar) 236b34d8163SFrancis Kelly mlx5_glue->devx_free_uar(priv->uar); 237b34d8163SFrancis Kelly if (priv->regexdev) 238b34d8163SFrancis Kelly rte_regexdev_unregister(priv->regexdev); 2391db6ebd4SParav Pandit dev_error: 240cfc672a9SOri Kam if (priv) 241cfc672a9SOri Kam rte_free(priv); 242cfc672a9SOri Kam return -rte_errno; 243cfc672a9SOri Kam } 244cfc672a9SOri Kam 245cfc672a9SOri Kam static int 2467af08c8fSMichael Baum mlx5_regex_dev_remove(struct mlx5_common_device *cdev) 247cfc672a9SOri Kam { 248cfc672a9SOri Kam char name[RTE_REGEXDEV_NAME_MAX_LEN]; 249cfc672a9SOri Kam struct rte_regexdev *dev; 250cfc672a9SOri Kam struct mlx5_regex_priv *priv = NULL; 251cfc672a9SOri Kam 2527af08c8fSMichael Baum mlx5_regex_get_name(name, cdev->dev); 253cfc672a9SOri Kam dev = rte_regexdev_get_device_by_name(name); 254cfc672a9SOri Kam if (!dev) 255cfc672a9SOri Kam return 0; 256cfc672a9SOri Kam priv = dev->data->dev_private; 257cfc672a9SOri Kam if (priv) { 25829ca3215SMichael Baum /* Remove from memory callback device list. */ 25929ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 26029ca3215SMichael Baum TAILQ_REMOVE(&mlx5_mem_event_list, priv, mem_event_cb); 26129ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 26229ca3215SMichael Baum if (TAILQ_EMPTY(&mlx5_mem_event_list)) 26329ca3215SMichael Baum rte_mem_event_callback_unregister("MLX5_MEM_EVENT_CB", 26429ca3215SMichael Baum NULL); 265a1fcde8cSMichael Baum if (priv->mr_scache.cache.table) 266a1fcde8cSMichael Baum mlx5_mr_release_cache(&priv->mr_scache); 267b34d8163SFrancis Kelly if (priv->pd) 268b34d8163SFrancis Kelly mlx5_glue->dealloc_pd(priv->pd); 269b34d8163SFrancis Kelly if (priv->uar) 270b34d8163SFrancis Kelly mlx5_glue->devx_free_uar(priv->uar); 271b34d8163SFrancis Kelly if (priv->regexdev) 272b34d8163SFrancis Kelly rte_regexdev_unregister(priv->regexdev); 273cfc672a9SOri Kam rte_free(priv); 274cfc672a9SOri Kam } 275cfc672a9SOri Kam return 0; 276cfc672a9SOri Kam } 277cfc672a9SOri Kam 278cfc672a9SOri Kam static const struct rte_pci_id mlx5_regex_pci_id_map[] = { 279cfc672a9SOri Kam { 280cfc672a9SOri Kam RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 281cfc672a9SOri Kam PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 282cfc672a9SOri Kam }, 283cfc672a9SOri Kam { 2846ca37b06SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2856ca37b06SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX7BF) 2866ca37b06SRaslan Darawsheh }, 2876ca37b06SRaslan Darawsheh { 288cfc672a9SOri Kam .vendor_id = 0 289cfc672a9SOri Kam } 290cfc672a9SOri Kam }; 291cfc672a9SOri Kam 2920564ddeaSXueming Li static struct mlx5_class_driver mlx5_regex_driver = { 2930564ddeaSXueming Li .drv_class = MLX5_CLASS_REGEX, 29450458c9dSThomas Monjalon .name = RTE_STR(MLX5_REGEX_DRIVER_NAME), 295cfc672a9SOri Kam .id_table = mlx5_regex_pci_id_map, 2960564ddeaSXueming Li .probe = mlx5_regex_dev_probe, 2970564ddeaSXueming Li .remove = mlx5_regex_dev_remove, 298cfc672a9SOri Kam }; 299cfc672a9SOri Kam 300cfc672a9SOri Kam RTE_INIT(rte_mlx5_regex_init) 301cfc672a9SOri Kam { 30282088001SParav Pandit mlx5_common_init(); 303cfc672a9SOri Kam if (mlx5_glue) 3040564ddeaSXueming Li mlx5_class_driver_register(&mlx5_regex_driver); 305cfc672a9SOri Kam } 306cfc672a9SOri Kam 307eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(mlx5_regex_logtype, NOTICE) 30850458c9dSThomas Monjalon RTE_PMD_EXPORT_NAME(MLX5_REGEX_DRIVER_NAME, __COUNTER__); 30950458c9dSThomas Monjalon RTE_PMD_REGISTER_PCI_TABLE(MLX5_REGEX_DRIVER_NAME, mlx5_regex_pci_id_map); 31050458c9dSThomas Monjalon RTE_PMD_REGISTER_KMOD_DEP(MLX5_REGEX_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 311