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 13 #include <mlx5_common_pci.h> 14 #include <mlx5_common.h> 15 #include <mlx5_glue.h> 16 #include <mlx5_devx_cmds.h> 17 #include <mlx5_prm.h> 18 19 #include "mlx5_regex.h" 20 #include "mlx5_regex_utils.h" 21 #include "mlx5_rxp_csrs.h" 22 23 #define MLX5_REGEX_DRIVER_NAME regex_mlx5 24 25 int mlx5_regex_logtype; 26 27 const struct rte_regexdev_ops mlx5_regexdev_ops = { 28 .dev_info_get = mlx5_regex_info_get, 29 .dev_configure = mlx5_regex_configure, 30 .dev_db_import = mlx5_regex_rules_db_import, 31 .dev_qp_setup = mlx5_regex_qp_setup, 32 .dev_start = mlx5_regex_start, 33 .dev_stop = mlx5_regex_stop, 34 .dev_close = mlx5_regex_close, 35 }; 36 37 int 38 mlx5_regex_start(struct rte_regexdev *dev __rte_unused) 39 { 40 return 0; 41 } 42 43 int 44 mlx5_regex_stop(struct rte_regexdev *dev __rte_unused) 45 { 46 return 0; 47 } 48 49 int 50 mlx5_regex_close(struct rte_regexdev *dev __rte_unused) 51 { 52 return 0; 53 } 54 55 static int 56 mlx5_regex_engines_status(struct ibv_context *ctx, int num_engines) 57 { 58 uint32_t fpga_ident = 0; 59 int err; 60 int i; 61 62 for (i = 0; i < num_engines; i++) { 63 err = mlx5_devx_regex_register_read(ctx, i, 64 MLX5_RXP_CSR_IDENTIFIER, 65 &fpga_ident); 66 fpga_ident = (fpga_ident & (0x0000FFFF)); 67 if (err || fpga_ident != MLX5_RXP_IDENTIFIER) { 68 DRV_LOG(ERR, "Failed setup RXP %d err %d database " 69 "memory 0x%x", i, err, fpga_ident); 70 if (!err) 71 err = EINVAL; 72 return err; 73 } 74 } 75 return 0; 76 } 77 78 static void 79 mlx5_regex_get_name(char *name, struct rte_pci_device *pci_dev __rte_unused) 80 { 81 sprintf(name, "mlx5_regex_%02x:%02x.%02x", pci_dev->addr.bus, 82 pci_dev->addr.devid, pci_dev->addr.function); 83 } 84 85 static int 86 mlx5_regex_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 87 struct rte_pci_device *pci_dev) 88 { 89 struct ibv_device *ibv; 90 struct mlx5_regex_priv *priv = NULL; 91 struct ibv_context *ctx = NULL; 92 struct mlx5_hca_attr attr; 93 char name[RTE_REGEXDEV_NAME_MAX_LEN]; 94 int ret; 95 uint32_t val; 96 97 ibv = mlx5_os_get_ibv_device(&pci_dev->addr); 98 if (!ibv) { 99 DRV_LOG(ERR, "No matching IB device for PCI slot " 100 PCI_PRI_FMT ".", pci_dev->addr.domain, 101 pci_dev->addr.bus, pci_dev->addr.devid, 102 pci_dev->addr.function); 103 return -rte_errno; 104 } 105 DRV_LOG(INFO, "PCI information matches for device \"%s\".", 106 ibv->name); 107 ctx = mlx5_glue->dv_open_device(ibv); 108 if (!ctx) { 109 DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name); 110 rte_errno = ENODEV; 111 return -rte_errno; 112 } 113 ret = mlx5_devx_cmd_query_hca_attr(ctx, &attr); 114 if (ret) { 115 DRV_LOG(ERR, "Unable to read HCA capabilities."); 116 rte_errno = ENOTSUP; 117 goto dev_error; 118 } else if (!attr.regex || attr.regexp_num_of_engines == 0) { 119 DRV_LOG(ERR, "Not enough capabilities to support RegEx, maybe " 120 "old FW/OFED version?"); 121 rte_errno = ENOTSUP; 122 goto dev_error; 123 } 124 if (mlx5_regex_engines_status(ctx, 2)) { 125 DRV_LOG(ERR, "RegEx engine error."); 126 rte_errno = ENOMEM; 127 goto dev_error; 128 } 129 priv = rte_zmalloc("mlx5 regex device private", sizeof(*priv), 130 RTE_CACHE_LINE_SIZE); 131 if (!priv) { 132 DRV_LOG(ERR, "Failed to allocate private memory."); 133 rte_errno = ENOMEM; 134 goto dev_error; 135 } 136 priv->sq_ts_format = attr.sq_ts_format; 137 priv->ctx = ctx; 138 priv->nb_engines = 2; /* attr.regexp_num_of_engines */ 139 ret = mlx5_devx_regex_register_read(priv->ctx, 0, 140 MLX5_RXP_CSR_IDENTIFIER, &val); 141 if (ret) { 142 DRV_LOG(ERR, "CSR read failed!"); 143 return -1; 144 } 145 if (val == MLX5_RXP_BF2_IDENTIFIER) 146 priv->is_bf2 = 1; 147 /* Default RXP programming mode to Shared. */ 148 priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE; 149 mlx5_regex_get_name(name, pci_dev); 150 priv->regexdev = rte_regexdev_register(name); 151 if (priv->regexdev == NULL) { 152 DRV_LOG(ERR, "Failed to register RegEx device."); 153 rte_errno = rte_errno ? rte_errno : EINVAL; 154 goto error; 155 } 156 /* 157 * This PMD always claims the write memory barrier on UAR 158 * registers writings, it is safe to allocate UAR with any 159 * memory mapping type. 160 */ 161 priv->uar = mlx5_devx_alloc_uar(ctx, -1); 162 if (!priv->uar) { 163 DRV_LOG(ERR, "can't allocate uar."); 164 rte_errno = ENOMEM; 165 goto error; 166 } 167 priv->pd = mlx5_glue->alloc_pd(ctx); 168 if (!priv->pd) { 169 DRV_LOG(ERR, "can't allocate pd."); 170 rte_errno = ENOMEM; 171 goto error; 172 } 173 priv->regexdev->dev_ops = &mlx5_regexdev_ops; 174 priv->regexdev->enqueue = mlx5_regexdev_enqueue; 175 #ifdef HAVE_MLX5_UMR_IMKEY 176 if (!attr.umr_indirect_mkey_disabled && 177 !attr.umr_modify_entity_size_disabled) 178 priv->has_umr = 1; 179 if (priv->has_umr) 180 priv->regexdev->enqueue = mlx5_regexdev_enqueue_gga; 181 #endif 182 priv->regexdev->dequeue = mlx5_regexdev_dequeue; 183 priv->regexdev->device = (struct rte_device *)pci_dev; 184 priv->regexdev->data->dev_private = priv; 185 priv->regexdev->state = RTE_REGEXDEV_READY; 186 priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr; 187 priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr; 188 ret = mlx5_mr_btree_init(&priv->mr_scache.cache, 189 MLX5_MR_BTREE_CACHE_N * 2, 190 rte_socket_id()); 191 if (ret) { 192 DRV_LOG(ERR, "MR init tree failed."); 193 rte_errno = ENOMEM; 194 goto error; 195 } 196 DRV_LOG(INFO, "RegEx GGA is %s.", 197 priv->has_umr ? "supported" : "unsupported"); 198 return 0; 199 200 error: 201 if (priv->pd) 202 mlx5_glue->dealloc_pd(priv->pd); 203 if (priv->uar) 204 mlx5_glue->devx_free_uar(priv->uar); 205 if (priv->regexdev) 206 rte_regexdev_unregister(priv->regexdev); 207 dev_error: 208 if (ctx) 209 mlx5_glue->close_device(ctx); 210 if (priv) 211 rte_free(priv); 212 return -rte_errno; 213 } 214 215 static int 216 mlx5_regex_pci_remove(struct rte_pci_device *pci_dev) 217 { 218 char name[RTE_REGEXDEV_NAME_MAX_LEN]; 219 struct rte_regexdev *dev; 220 struct mlx5_regex_priv *priv = NULL; 221 222 mlx5_regex_get_name(name, pci_dev); 223 dev = rte_regexdev_get_device_by_name(name); 224 if (!dev) 225 return 0; 226 priv = dev->data->dev_private; 227 if (priv) { 228 if (priv->pd) 229 mlx5_glue->dealloc_pd(priv->pd); 230 if (priv->uar) 231 mlx5_glue->devx_free_uar(priv->uar); 232 if (priv->regexdev) 233 rte_regexdev_unregister(priv->regexdev); 234 if (priv->ctx) 235 mlx5_glue->close_device(priv->ctx); 236 if (priv->regexdev) 237 rte_regexdev_unregister(priv->regexdev); 238 rte_free(priv); 239 } 240 return 0; 241 } 242 243 static const struct rte_pci_id mlx5_regex_pci_id_map[] = { 244 { 245 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 246 PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 247 }, 248 { 249 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 250 PCI_DEVICE_ID_MELLANOX_CONNECTX7BF) 251 }, 252 { 253 .vendor_id = 0 254 } 255 }; 256 257 static struct mlx5_pci_driver mlx5_regex_driver = { 258 .driver_class = MLX5_CLASS_REGEX, 259 .pci_driver = { 260 .driver = { 261 .name = RTE_STR(MLX5_REGEX_DRIVER_NAME), 262 }, 263 .id_table = mlx5_regex_pci_id_map, 264 .probe = mlx5_regex_pci_probe, 265 .remove = mlx5_regex_pci_remove, 266 .drv_flags = 0, 267 }, 268 }; 269 270 RTE_INIT(rte_mlx5_regex_init) 271 { 272 mlx5_common_init(); 273 if (mlx5_glue) 274 mlx5_pci_driver_register(&mlx5_regex_driver); 275 } 276 277 RTE_LOG_REGISTER_DEFAULT(mlx5_regex_logtype, NOTICE) 278 RTE_PMD_EXPORT_NAME(MLX5_REGEX_DRIVER_NAME, __COUNTER__); 279 RTE_PMD_REGISTER_PCI_TABLE(MLX5_REGEX_DRIVER_NAME, mlx5_regex_pci_id_map); 280 RTE_PMD_REGISTER_KMOD_DEP(MLX5_REGEX_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 281