1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2020 Mellanox Technologies, Ltd 3 */ 4 5 #include <rte_malloc.h> 6 #include <rte_log.h> 7 #include <rte_errno.h> 8 #include <rte_pci.h> 9 #include <rte_regexdev.h> 10 #include <rte_regexdev_core.h> 11 #include <rte_regexdev_driver.h> 12 #include <rte_bus_pci.h> 13 14 #include <mlx5_common.h> 15 #include <mlx5_common_mr.h> 16 #include <mlx5_glue.h> 17 #include <mlx5_devx_cmds.h> 18 #include <mlx5_prm.h> 19 20 #include "mlx5_regex.h" 21 #include "mlx5_regex_utils.h" 22 #include "mlx5_rxp_csrs.h" 23 24 #define MLX5_REGEX_DRIVER_NAME regex_mlx5 25 26 int mlx5_regex_logtype; 27 28 const struct rte_regexdev_ops mlx5_regexdev_ops = { 29 .dev_info_get = mlx5_regex_info_get, 30 .dev_configure = mlx5_regex_configure, 31 .dev_db_import = mlx5_regex_rules_db_import, 32 .dev_qp_setup = mlx5_regex_qp_setup, 33 .dev_start = mlx5_regex_start, 34 .dev_stop = mlx5_regex_stop, 35 .dev_close = mlx5_regex_close, 36 }; 37 38 int 39 mlx5_regex_start(struct rte_regexdev *dev) 40 { 41 struct mlx5_regex_priv *priv = dev->data->dev_private; 42 43 return mlx5_dev_mempool_subscribe(priv->cdev); 44 } 45 46 int 47 mlx5_regex_stop(struct rte_regexdev *dev __rte_unused) 48 { 49 struct mlx5_regex_priv *priv = dev->data->dev_private; 50 uint32_t i; 51 52 mlx5_regex_clean_ctrl(dev); 53 rte_free(priv->qps); 54 priv->qps = NULL; 55 56 for (i = 0; i < priv->nb_engines; i++) 57 /* Stop engine. */ 58 mlx5_devx_regex_database_stop(priv->cdev->ctx, i); 59 60 return 0; 61 } 62 63 int 64 mlx5_regex_close(struct rte_regexdev *dev __rte_unused) 65 { 66 return 0; 67 } 68 69 static void 70 mlx5_regex_get_name(char *name, struct rte_device *dev) 71 { 72 sprintf(name, "mlx5_regex_%s", dev->name); 73 } 74 75 static int 76 mlx5_regex_dev_probe(struct mlx5_common_device *cdev) 77 { 78 struct mlx5_regex_priv *priv = NULL; 79 struct mlx5_hca_attr *attr = &cdev->config.hca_attr; 80 char name[RTE_REGEXDEV_NAME_MAX_LEN]; 81 82 if ((!attr->regexp_params && !attr->mmo_regex_sq_en && !attr->mmo_regex_qp_en) 83 || attr->regexp_num_of_engines == 0) { 84 DRV_LOG(ERR, "Not enough capabilities to support RegEx, maybe " 85 "old FW/OFED version?"); 86 rte_errno = ENOTSUP; 87 return -rte_errno; 88 } 89 priv = rte_zmalloc("mlx5 regex device private", sizeof(*priv), 90 RTE_CACHE_LINE_SIZE); 91 if (!priv) { 92 DRV_LOG(ERR, "Failed to allocate private memory."); 93 rte_errno = ENOMEM; 94 return -rte_errno; 95 } 96 priv->mmo_regex_qp_cap = attr->mmo_regex_qp_en; 97 priv->mmo_regex_sq_cap = attr->mmo_regex_sq_en; 98 priv->cdev = cdev; 99 priv->nb_engines = 2; /* attr.regexp_num_of_engines */ 100 if (attr->regexp_version == MLX5_RXP_BF2_IDENTIFIER) 101 priv->is_bf2 = 1; 102 /* Default RXP programming mode to Shared. */ 103 priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE; 104 mlx5_regex_get_name(name, cdev->dev); 105 priv->regexdev = rte_regexdev_register(name); 106 if (priv->regexdev == NULL) { 107 DRV_LOG(ERR, "Failed to register RegEx device."); 108 rte_errno = rte_errno ? rte_errno : EINVAL; 109 goto dev_error; 110 } 111 /* 112 * This PMD always claims the write memory barrier on UAR 113 * registers writings, it is safe to allocate UAR with any 114 * memory mapping type. 115 */ 116 priv->uar = mlx5_devx_alloc_uar(priv->cdev->ctx, -1); 117 if (!priv->uar) { 118 DRV_LOG(ERR, "can't allocate uar."); 119 rte_errno = ENOMEM; 120 goto error; 121 } 122 priv->regexdev->dev_ops = &mlx5_regexdev_ops; 123 priv->regexdev->enqueue = mlx5_regexdev_enqueue; 124 #ifdef HAVE_MLX5_UMR_IMKEY 125 if (!attr->umr_indirect_mkey_disabled && 126 !attr->umr_modify_entity_size_disabled) 127 priv->has_umr = 1; 128 if (priv->has_umr) 129 priv->regexdev->enqueue = mlx5_regexdev_enqueue_gga; 130 #endif 131 priv->regexdev->dequeue = mlx5_regexdev_dequeue; 132 priv->regexdev->device = cdev->dev; 133 priv->regexdev->data->dev_private = priv; 134 priv->regexdev->state = RTE_REGEXDEV_READY; 135 DRV_LOG(INFO, "RegEx GGA is %s.", 136 priv->has_umr ? "supported" : "unsupported"); 137 return 0; 138 139 error: 140 if (priv->uar) 141 mlx5_glue->devx_free_uar(priv->uar); 142 if (priv->regexdev) 143 rte_regexdev_unregister(priv->regexdev); 144 dev_error: 145 if (priv) 146 rte_free(priv); 147 return -rte_errno; 148 } 149 150 static int 151 mlx5_regex_dev_remove(struct mlx5_common_device *cdev) 152 { 153 char name[RTE_REGEXDEV_NAME_MAX_LEN]; 154 struct rte_regexdev *dev; 155 struct mlx5_regex_priv *priv = NULL; 156 157 mlx5_regex_get_name(name, cdev->dev); 158 dev = rte_regexdev_get_device_by_name(name); 159 if (!dev) 160 return 0; 161 priv = dev->data->dev_private; 162 if (priv) { 163 if (priv->uar) 164 mlx5_glue->devx_free_uar(priv->uar); 165 if (priv->regexdev) 166 rte_regexdev_unregister(priv->regexdev); 167 rte_free(priv); 168 } 169 return 0; 170 } 171 172 static const struct rte_pci_id mlx5_regex_pci_id_map[] = { 173 { 174 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 175 PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 176 }, 177 { 178 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 179 PCI_DEVICE_ID_MELLANOX_CONNECTX7BF) 180 }, 181 { 182 .vendor_id = 0 183 } 184 }; 185 186 static struct mlx5_class_driver mlx5_regex_driver = { 187 .drv_class = MLX5_CLASS_REGEX, 188 .name = RTE_STR(MLX5_REGEX_DRIVER_NAME), 189 .id_table = mlx5_regex_pci_id_map, 190 .probe = mlx5_regex_dev_probe, 191 .remove = mlx5_regex_dev_remove, 192 }; 193 194 RTE_INIT(rte_mlx5_regex_init) 195 { 196 mlx5_common_init(); 197 if (mlx5_glue) 198 mlx5_class_driver_register(&mlx5_regex_driver); 199 } 200 201 RTE_LOG_REGISTER_DEFAULT(mlx5_regex_logtype, NOTICE) 202 RTE_PMD_EXPORT_NAME(MLX5_REGEX_DRIVER_NAME, __COUNTER__); 203 RTE_PMD_REGISTER_PCI_TABLE(MLX5_REGEX_DRIVER_NAME, mlx5_regex_pci_id_map); 204 RTE_PMD_REGISTER_KMOD_DEP(MLX5_REGEX_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 205