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