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, 113ca1418ceSMichael Baum mlx5_os_get_ctx_device_name 114ca1418ceSMichael 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; 128*fe46b20cSMichael Baum struct mlx5_hca_attr *attr = &cdev->config.hca_attr; 129cfc672a9SOri Kam char name[RTE_REGEXDEV_NAME_MAX_LEN]; 130cfc672a9SOri Kam int ret; 131f324162eSOri Kam uint32_t val; 132cfc672a9SOri Kam 133*fe46b20cSMichael Baum if ((!attr->regex && !attr->mmo_regex_sq_en && !attr->mmo_regex_qp_en) 134*fe46b20cSMichael Baum || attr->regexp_num_of_engines == 0) { 135cfc672a9SOri Kam DRV_LOG(ERR, "Not enough capabilities to support RegEx, maybe " 136cfc672a9SOri Kam "old FW/OFED version?"); 137cfc672a9SOri Kam rte_errno = ENOTSUP; 138ca1418ceSMichael Baum return -rte_errno; 139cfc672a9SOri Kam } 140ca1418ceSMichael Baum if (mlx5_regex_engines_status(cdev->ctx, 2)) { 1419428310aSOri Kam DRV_LOG(ERR, "RegEx engine error."); 1429428310aSOri Kam rte_errno = ENOMEM; 143ca1418ceSMichael Baum return -rte_errno; 1449428310aSOri Kam } 145cfc672a9SOri Kam priv = rte_zmalloc("mlx5 regex device private", sizeof(*priv), 146cfc672a9SOri Kam RTE_CACHE_LINE_SIZE); 147cfc672a9SOri Kam if (!priv) { 148cfc672a9SOri Kam DRV_LOG(ERR, "Failed to allocate private memory."); 149cfc672a9SOri Kam rte_errno = ENOMEM; 150ca1418ceSMichael Baum return -rte_errno; 151cfc672a9SOri Kam } 152*fe46b20cSMichael Baum priv->mmo_regex_qp_cap = attr->mmo_regex_qp_en; 153*fe46b20cSMichael Baum priv->mmo_regex_sq_cap = attr->mmo_regex_sq_en; 154ca1418ceSMichael Baum priv->cdev = cdev; 155b34d8163SFrancis Kelly priv->nb_engines = 2; /* attr.regexp_num_of_engines */ 156ca1418ceSMichael Baum ret = mlx5_devx_regex_register_read(priv->cdev->ctx, 0, 157f324162eSOri Kam MLX5_RXP_CSR_IDENTIFIER, &val); 158f324162eSOri Kam if (ret) { 159f324162eSOri Kam DRV_LOG(ERR, "CSR read failed!"); 1600972b7baSMichael Baum goto dev_error; 161f324162eSOri Kam } 162f324162eSOri Kam if (val == MLX5_RXP_BF2_IDENTIFIER) 163f324162eSOri Kam priv->is_bf2 = 1; 164b34d8163SFrancis Kelly /* Default RXP programming mode to Shared. */ 165b34d8163SFrancis Kelly priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE; 1667af08c8fSMichael Baum mlx5_regex_get_name(name, cdev->dev); 167cfc672a9SOri Kam priv->regexdev = rte_regexdev_register(name); 168cfc672a9SOri Kam if (priv->regexdev == NULL) { 169cfc672a9SOri Kam DRV_LOG(ERR, "Failed to register RegEx device."); 170cfc672a9SOri Kam rte_errno = rte_errno ? rte_errno : EINVAL; 171ca1418ceSMichael Baum goto dev_error; 172cfc672a9SOri Kam } 173e8f05161SViacheslav Ovsiienko /* 174e8f05161SViacheslav Ovsiienko * This PMD always claims the write memory barrier on UAR 175e8f05161SViacheslav Ovsiienko * registers writings, it is safe to allocate UAR with any 176e8f05161SViacheslav Ovsiienko * memory mapping type. 177e8f05161SViacheslav Ovsiienko */ 178ca1418ceSMichael Baum priv->uar = mlx5_devx_alloc_uar(priv->cdev->ctx, -1); 179b34d8163SFrancis Kelly if (!priv->uar) { 180b34d8163SFrancis Kelly DRV_LOG(ERR, "can't allocate uar."); 181b34d8163SFrancis Kelly rte_errno = ENOMEM; 182b34d8163SFrancis Kelly goto error; 183b34d8163SFrancis Kelly } 184cfc672a9SOri Kam priv->regexdev->dev_ops = &mlx5_regexdev_ops; 1854d4e245aSYuval Avnery priv->regexdev->enqueue = mlx5_regexdev_enqueue; 186330a70b7SSuanming Mou #ifdef HAVE_MLX5_UMR_IMKEY 187*fe46b20cSMichael Baum if (!attr->umr_indirect_mkey_disabled && 188*fe46b20cSMichael Baum !attr->umr_modify_entity_size_disabled) 189330a70b7SSuanming Mou priv->has_umr = 1; 190330a70b7SSuanming Mou if (priv->has_umr) 191330a70b7SSuanming Mou priv->regexdev->enqueue = mlx5_regexdev_enqueue_gga; 192330a70b7SSuanming Mou #endif 1930db041e7SYuval Avnery priv->regexdev->dequeue = mlx5_regexdev_dequeue; 1947af08c8fSMichael Baum priv->regexdev->device = cdev->dev; 195cfc672a9SOri Kam priv->regexdev->data->dev_private = priv; 196e3dbbf71SOri Kam priv->regexdev->state = RTE_REGEXDEV_READY; 197cda883bbSYuval Avnery priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr; 198cda883bbSYuval Avnery priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr; 199cda883bbSYuval Avnery ret = mlx5_mr_btree_init(&priv->mr_scache.cache, 200cda883bbSYuval Avnery MLX5_MR_BTREE_CACHE_N * 2, 201cda883bbSYuval Avnery rte_socket_id()); 202cda883bbSYuval Avnery if (ret) { 203cda883bbSYuval Avnery DRV_LOG(ERR, "MR init tree failed."); 204cda883bbSYuval Avnery rte_errno = ENOMEM; 205cda883bbSYuval Avnery goto error; 206cda883bbSYuval Avnery } 20729ca3215SMichael Baum /* Register callback function for global shared MR cache management. */ 20829ca3215SMichael Baum if (TAILQ_EMPTY(&mlx5_mem_event_list)) 20929ca3215SMichael Baum rte_mem_event_callback_register("MLX5_MEM_EVENT_CB", 21029ca3215SMichael Baum mlx5_regex_mr_mem_event_cb, 21129ca3215SMichael Baum NULL); 21229ca3215SMichael Baum /* Add device to memory callback list. */ 21329ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 21429ca3215SMichael Baum TAILQ_INSERT_TAIL(&mlx5_mem_event_list, priv, mem_event_cb); 21529ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 216330a70b7SSuanming Mou DRV_LOG(INFO, "RegEx GGA is %s.", 217330a70b7SSuanming Mou priv->has_umr ? "supported" : "unsupported"); 218cfc672a9SOri Kam return 0; 219cfc672a9SOri Kam 220cfc672a9SOri Kam error: 221b34d8163SFrancis Kelly if (priv->uar) 222b34d8163SFrancis Kelly mlx5_glue->devx_free_uar(priv->uar); 223b34d8163SFrancis Kelly if (priv->regexdev) 224b34d8163SFrancis Kelly rte_regexdev_unregister(priv->regexdev); 2251db6ebd4SParav Pandit dev_error: 226cfc672a9SOri Kam if (priv) 227cfc672a9SOri Kam rte_free(priv); 228cfc672a9SOri Kam return -rte_errno; 229cfc672a9SOri Kam } 230cfc672a9SOri Kam 231cfc672a9SOri Kam static int 2327af08c8fSMichael Baum mlx5_regex_dev_remove(struct mlx5_common_device *cdev) 233cfc672a9SOri Kam { 234cfc672a9SOri Kam char name[RTE_REGEXDEV_NAME_MAX_LEN]; 235cfc672a9SOri Kam struct rte_regexdev *dev; 236cfc672a9SOri Kam struct mlx5_regex_priv *priv = NULL; 237cfc672a9SOri Kam 2387af08c8fSMichael Baum mlx5_regex_get_name(name, cdev->dev); 239cfc672a9SOri Kam dev = rte_regexdev_get_device_by_name(name); 240cfc672a9SOri Kam if (!dev) 241cfc672a9SOri Kam return 0; 242cfc672a9SOri Kam priv = dev->data->dev_private; 243cfc672a9SOri Kam if (priv) { 24429ca3215SMichael Baum /* Remove from memory callback device list. */ 24529ca3215SMichael Baum pthread_mutex_lock(&mem_event_list_lock); 24629ca3215SMichael Baum TAILQ_REMOVE(&mlx5_mem_event_list, priv, mem_event_cb); 24729ca3215SMichael Baum pthread_mutex_unlock(&mem_event_list_lock); 24829ca3215SMichael Baum if (TAILQ_EMPTY(&mlx5_mem_event_list)) 24929ca3215SMichael Baum rte_mem_event_callback_unregister("MLX5_MEM_EVENT_CB", 25029ca3215SMichael Baum NULL); 251a1fcde8cSMichael Baum if (priv->mr_scache.cache.table) 252a1fcde8cSMichael Baum mlx5_mr_release_cache(&priv->mr_scache); 253b34d8163SFrancis Kelly if (priv->uar) 254b34d8163SFrancis Kelly mlx5_glue->devx_free_uar(priv->uar); 255b34d8163SFrancis Kelly if (priv->regexdev) 256b34d8163SFrancis Kelly rte_regexdev_unregister(priv->regexdev); 257cfc672a9SOri Kam rte_free(priv); 258cfc672a9SOri Kam } 259cfc672a9SOri Kam return 0; 260cfc672a9SOri Kam } 261cfc672a9SOri Kam 262cfc672a9SOri Kam static const struct rte_pci_id mlx5_regex_pci_id_map[] = { 263cfc672a9SOri Kam { 264cfc672a9SOri Kam RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 265cfc672a9SOri Kam PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 266cfc672a9SOri Kam }, 267cfc672a9SOri Kam { 2686ca37b06SRaslan Darawsheh RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2696ca37b06SRaslan Darawsheh PCI_DEVICE_ID_MELLANOX_CONNECTX7BF) 2706ca37b06SRaslan Darawsheh }, 2716ca37b06SRaslan Darawsheh { 272cfc672a9SOri Kam .vendor_id = 0 273cfc672a9SOri Kam } 274cfc672a9SOri Kam }; 275cfc672a9SOri Kam 2760564ddeaSXueming Li static struct mlx5_class_driver mlx5_regex_driver = { 2770564ddeaSXueming Li .drv_class = MLX5_CLASS_REGEX, 27850458c9dSThomas Monjalon .name = RTE_STR(MLX5_REGEX_DRIVER_NAME), 279cfc672a9SOri Kam .id_table = mlx5_regex_pci_id_map, 2800564ddeaSXueming Li .probe = mlx5_regex_dev_probe, 2810564ddeaSXueming Li .remove = mlx5_regex_dev_remove, 282cfc672a9SOri Kam }; 283cfc672a9SOri Kam 284cfc672a9SOri Kam RTE_INIT(rte_mlx5_regex_init) 285cfc672a9SOri Kam { 28682088001SParav Pandit mlx5_common_init(); 287cfc672a9SOri Kam if (mlx5_glue) 2880564ddeaSXueming Li mlx5_class_driver_register(&mlx5_regex_driver); 289cfc672a9SOri Kam } 290cfc672a9SOri Kam 291eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(mlx5_regex_logtype, NOTICE) 29250458c9dSThomas Monjalon RTE_PMD_EXPORT_NAME(MLX5_REGEX_DRIVER_NAME, __COUNTER__); 29350458c9dSThomas Monjalon RTE_PMD_REGISTER_PCI_TABLE(MLX5_REGEX_DRIVER_NAME, mlx5_regex_pci_id_map); 29450458c9dSThomas Monjalon RTE_PMD_REGISTER_KMOD_DEP(MLX5_REGEX_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 295