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_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_device *dev) 80 { 81 sprintf(name, "mlx5_regex_%s", dev->name); 82 } 83 84 static int 85 mlx5_regex_dev_probe(struct rte_device *rte_dev) 86 { 87 struct ibv_device *ibv; 88 struct mlx5_regex_priv *priv = NULL; 89 struct ibv_context *ctx = NULL; 90 struct mlx5_hca_attr attr; 91 char name[RTE_REGEXDEV_NAME_MAX_LEN]; 92 int ret; 93 uint32_t val; 94 95 ibv = mlx5_os_get_ibv_dev(rte_dev); 96 if (ibv == NULL) 97 return -rte_errno; 98 DRV_LOG(INFO, "Probe device \"%s\".", ibv->name); 99 ctx = mlx5_glue->dv_open_device(ibv); 100 if (!ctx) { 101 DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name); 102 rte_errno = ENODEV; 103 return -rte_errno; 104 } 105 ret = mlx5_devx_cmd_query_hca_attr(ctx, &attr); 106 if (ret) { 107 DRV_LOG(ERR, "Unable to read HCA capabilities."); 108 rte_errno = ENOTSUP; 109 goto dev_error; 110 } else if (!attr.regex || attr.regexp_num_of_engines == 0) { 111 DRV_LOG(ERR, "Not enough capabilities to support RegEx, maybe " 112 "old FW/OFED version?"); 113 rte_errno = ENOTSUP; 114 goto dev_error; 115 } 116 if (mlx5_regex_engines_status(ctx, 2)) { 117 DRV_LOG(ERR, "RegEx engine error."); 118 rte_errno = ENOMEM; 119 goto dev_error; 120 } 121 priv = rte_zmalloc("mlx5 regex device private", sizeof(*priv), 122 RTE_CACHE_LINE_SIZE); 123 if (!priv) { 124 DRV_LOG(ERR, "Failed to allocate private memory."); 125 rte_errno = ENOMEM; 126 goto dev_error; 127 } 128 priv->sq_ts_format = attr.sq_ts_format; 129 priv->ctx = ctx; 130 priv->nb_engines = 2; /* attr.regexp_num_of_engines */ 131 ret = mlx5_devx_regex_register_read(priv->ctx, 0, 132 MLX5_RXP_CSR_IDENTIFIER, &val); 133 if (ret) { 134 DRV_LOG(ERR, "CSR read failed!"); 135 return -1; 136 } 137 if (val == MLX5_RXP_BF2_IDENTIFIER) 138 priv->is_bf2 = 1; 139 /* Default RXP programming mode to Shared. */ 140 priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE; 141 mlx5_regex_get_name(name, rte_dev); 142 priv->regexdev = rte_regexdev_register(name); 143 if (priv->regexdev == NULL) { 144 DRV_LOG(ERR, "Failed to register RegEx device."); 145 rte_errno = rte_errno ? rte_errno : EINVAL; 146 goto error; 147 } 148 /* 149 * This PMD always claims the write memory barrier on UAR 150 * registers writings, it is safe to allocate UAR with any 151 * memory mapping type. 152 */ 153 priv->uar = mlx5_devx_alloc_uar(ctx, -1); 154 if (!priv->uar) { 155 DRV_LOG(ERR, "can't allocate uar."); 156 rte_errno = ENOMEM; 157 goto error; 158 } 159 priv->pd = mlx5_glue->alloc_pd(ctx); 160 if (!priv->pd) { 161 DRV_LOG(ERR, "can't allocate pd."); 162 rte_errno = ENOMEM; 163 goto error; 164 } 165 priv->regexdev->dev_ops = &mlx5_regexdev_ops; 166 priv->regexdev->enqueue = mlx5_regexdev_enqueue; 167 #ifdef HAVE_MLX5_UMR_IMKEY 168 if (!attr.umr_indirect_mkey_disabled && 169 !attr.umr_modify_entity_size_disabled) 170 priv->has_umr = 1; 171 if (priv->has_umr) 172 priv->regexdev->enqueue = mlx5_regexdev_enqueue_gga; 173 #endif 174 priv->regexdev->dequeue = mlx5_regexdev_dequeue; 175 priv->regexdev->device = rte_dev; 176 priv->regexdev->data->dev_private = priv; 177 priv->regexdev->state = RTE_REGEXDEV_READY; 178 priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr; 179 priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr; 180 ret = mlx5_mr_btree_init(&priv->mr_scache.cache, 181 MLX5_MR_BTREE_CACHE_N * 2, 182 rte_socket_id()); 183 if (ret) { 184 DRV_LOG(ERR, "MR init tree failed."); 185 rte_errno = ENOMEM; 186 goto error; 187 } 188 DRV_LOG(INFO, "RegEx GGA is %s.", 189 priv->has_umr ? "supported" : "unsupported"); 190 return 0; 191 192 error: 193 if (priv->pd) 194 mlx5_glue->dealloc_pd(priv->pd); 195 if (priv->uar) 196 mlx5_glue->devx_free_uar(priv->uar); 197 if (priv->regexdev) 198 rte_regexdev_unregister(priv->regexdev); 199 dev_error: 200 if (ctx) 201 mlx5_glue->close_device(ctx); 202 if (priv) 203 rte_free(priv); 204 return -rte_errno; 205 } 206 207 static int 208 mlx5_regex_dev_remove(struct rte_device *rte_dev) 209 { 210 char name[RTE_REGEXDEV_NAME_MAX_LEN]; 211 struct rte_regexdev *dev; 212 struct mlx5_regex_priv *priv = NULL; 213 214 mlx5_regex_get_name(name, rte_dev); 215 dev = rte_regexdev_get_device_by_name(name); 216 if (!dev) 217 return 0; 218 priv = dev->data->dev_private; 219 if (priv) { 220 if (priv->pd) 221 mlx5_glue->dealloc_pd(priv->pd); 222 if (priv->uar) 223 mlx5_glue->devx_free_uar(priv->uar); 224 if (priv->regexdev) 225 rte_regexdev_unregister(priv->regexdev); 226 if (priv->ctx) 227 mlx5_glue->close_device(priv->ctx); 228 if (priv->regexdev) 229 rte_regexdev_unregister(priv->regexdev); 230 rte_free(priv); 231 } 232 return 0; 233 } 234 235 static const struct rte_pci_id mlx5_regex_pci_id_map[] = { 236 { 237 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 238 PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 239 }, 240 { 241 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 242 PCI_DEVICE_ID_MELLANOX_CONNECTX7BF) 243 }, 244 { 245 .vendor_id = 0 246 } 247 }; 248 249 static struct mlx5_class_driver mlx5_regex_driver = { 250 .drv_class = MLX5_CLASS_REGEX, 251 .name = RTE_STR(MLX5_REGEX_DRIVER_NAME), 252 .id_table = mlx5_regex_pci_id_map, 253 .probe = mlx5_regex_dev_probe, 254 .remove = mlx5_regex_dev_remove, 255 }; 256 257 RTE_INIT(rte_mlx5_regex_init) 258 { 259 mlx5_common_init(); 260 if (mlx5_glue) 261 mlx5_class_driver_register(&mlx5_regex_driver); 262 } 263 264 RTE_LOG_REGISTER_DEFAULT(mlx5_regex_logtype, NOTICE) 265 RTE_PMD_EXPORT_NAME(MLX5_REGEX_DRIVER_NAME, __COUNTER__); 266 RTE_PMD_REGISTER_PCI_TABLE(MLX5_REGEX_DRIVER_NAME, mlx5_regex_pci_id_map); 267 RTE_PMD_REGISTER_KMOD_DEP(MLX5_REGEX_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib"); 268