xref: /dpdk/drivers/regex/mlx5/mlx5_rxp.c (revision e3dbbf718ebc7cccc7b0a5f524f2250f69caff31)
1c126512bSOri Kam /* SPDX-License-Identifier: BSD-3-Clause
2c126512bSOri Kam  * Copyright 2020 Mellanox Technologies, Ltd
3c126512bSOri Kam  */
4c126512bSOri Kam 
5c126512bSOri Kam #include <rte_log.h>
6c126512bSOri Kam #include <rte_errno.h>
7*e3dbbf71SOri Kam #include <rte_malloc.h>
8c126512bSOri Kam #include <rte_regexdev.h>
9c126512bSOri Kam #include <rte_regexdev_core.h>
10c126512bSOri Kam #include <rte_regexdev_driver.h>
11c126512bSOri Kam 
12*e3dbbf71SOri Kam #include <mlx5_glue.h>
13*e3dbbf71SOri Kam #include <mlx5_devx_cmds.h>
14*e3dbbf71SOri Kam #include <mlx5_prm.h>
15*e3dbbf71SOri Kam 
16c126512bSOri Kam #include "mlx5_regex.h"
17*e3dbbf71SOri Kam #include "mlx5_regex_utils.h"
18*e3dbbf71SOri Kam #include "mlx5_rxp_csrs.h"
19c126512bSOri Kam 
20c126512bSOri Kam #define MLX5_REGEX_MAX_MATCHES 255
21c126512bSOri Kam #define MLX5_REGEX_MAX_PAYLOAD_SIZE UINT16_MAX
22c126512bSOri Kam #define MLX5_REGEX_MAX_RULES_PER_GROUP UINT16_MAX
23c126512bSOri Kam #define MLX5_REGEX_MAX_GROUPS UINT16_MAX
24c126512bSOri Kam 
25c126512bSOri Kam int
26c126512bSOri Kam mlx5_regex_info_get(struct rte_regexdev *dev __rte_unused,
27c126512bSOri Kam 		    struct rte_regexdev_info *info)
28c126512bSOri Kam {
29c126512bSOri Kam 	info->max_matches = MLX5_REGEX_MAX_MATCHES;
30c126512bSOri Kam 	info->max_payload_size = MLX5_REGEX_MAX_PAYLOAD_SIZE;
31c126512bSOri Kam 	info->max_rules_per_group = MLX5_REGEX_MAX_RULES_PER_GROUP;
32c126512bSOri Kam 	info->max_groups = MLX5_REGEX_MAX_GROUPS;
33c126512bSOri Kam 	info->regexdev_capa = RTE_REGEXDEV_SUPP_PCRE_GREEDY_F;
34c126512bSOri Kam 	info->rule_flags = 0;
35c126512bSOri Kam 	return 0;
36c126512bSOri Kam }
37*e3dbbf71SOri Kam 
38*e3dbbf71SOri Kam static int
39*e3dbbf71SOri Kam rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value,
40*e3dbbf71SOri Kam 		       uint32_t address, uint32_t expected_value,
41*e3dbbf71SOri Kam 		       uint32_t expected_mask, uint32_t timeout_ms, uint8_t id)
42*e3dbbf71SOri Kam {
43*e3dbbf71SOri Kam 	unsigned int i;
44*e3dbbf71SOri Kam 	int ret;
45*e3dbbf71SOri Kam 
46*e3dbbf71SOri Kam 	ret = -EBUSY;
47*e3dbbf71SOri Kam 	for (i = 0; i < timeout_ms; i++) {
48*e3dbbf71SOri Kam 		if (mlx5_devx_regex_register_read(ctx, id, address, value))
49*e3dbbf71SOri Kam 			return -1;
50*e3dbbf71SOri Kam 
51*e3dbbf71SOri Kam 		if ((*value & expected_mask) == expected_value) {
52*e3dbbf71SOri Kam 			ret = 0;
53*e3dbbf71SOri Kam 			break;
54*e3dbbf71SOri Kam 		}
55*e3dbbf71SOri Kam 		rte_delay_us(1000);
56*e3dbbf71SOri Kam 	}
57*e3dbbf71SOri Kam 	return ret;
58*e3dbbf71SOri Kam }
59*e3dbbf71SOri Kam 
60*e3dbbf71SOri Kam static int
61*e3dbbf71SOri Kam rxp_start_engine(struct ibv_context *ctx, uint8_t id)
62*e3dbbf71SOri Kam {
63*e3dbbf71SOri Kam 	uint32_t ctrl;
64*e3dbbf71SOri Kam 	int ret;
65*e3dbbf71SOri Kam 
66*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl);
67*e3dbbf71SOri Kam 	if (ret)
68*e3dbbf71SOri Kam 		return ret;
69*e3dbbf71SOri Kam 	ctrl |= MLX5_RXP_CSR_CTRL_GO;
70*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl);
71*e3dbbf71SOri Kam 	return ret;
72*e3dbbf71SOri Kam }
73*e3dbbf71SOri Kam 
74*e3dbbf71SOri Kam static int
75*e3dbbf71SOri Kam rxp_stop_engine(struct ibv_context *ctx, uint8_t id)
76*e3dbbf71SOri Kam {
77*e3dbbf71SOri Kam 	uint32_t ctrl;
78*e3dbbf71SOri Kam 	int ret;
79*e3dbbf71SOri Kam 
80*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl);
81*e3dbbf71SOri Kam 	if (ret)
82*e3dbbf71SOri Kam 		return ret;
83*e3dbbf71SOri Kam 	ctrl &= ~MLX5_RXP_CSR_CTRL_GO;
84*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl);
85*e3dbbf71SOri Kam 	return ret;
86*e3dbbf71SOri Kam }
87*e3dbbf71SOri Kam 
88*e3dbbf71SOri Kam static int
89*e3dbbf71SOri Kam rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits)
90*e3dbbf71SOri Kam {
91*e3dbbf71SOri Kam 	uint32_t ctrl_value;
92*e3dbbf71SOri Kam 	uint32_t poll_value;
93*e3dbbf71SOri Kam 	uint32_t expected_value;
94*e3dbbf71SOri Kam 	uint32_t expected_mask;
95*e3dbbf71SOri Kam 	int ret = 0;
96*e3dbbf71SOri Kam 
97*e3dbbf71SOri Kam 	/* Read the rtru ctrl CSR. */
98*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
99*e3dbbf71SOri Kam 					    &ctrl_value);
100*e3dbbf71SOri Kam 	if (ret)
101*e3dbbf71SOri Kam 		return -1;
102*e3dbbf71SOri Kam 	/* Clear any previous init modes. */
103*e3dbbf71SOri Kam 	ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_MASK);
104*e3dbbf71SOri Kam 	if (ctrl_value & MLX5_RXP_RTRU_CSR_CTRL_INIT) {
105*e3dbbf71SOri Kam 		ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT);
106*e3dbbf71SOri Kam 		mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
107*e3dbbf71SOri Kam 					       ctrl_value);
108*e3dbbf71SOri Kam 	}
109*e3dbbf71SOri Kam 	/* Set the init_mode bits in the rtru ctrl CSR. */
110*e3dbbf71SOri Kam 	ctrl_value |= init_bits;
111*e3dbbf71SOri Kam 	mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
112*e3dbbf71SOri Kam 				       ctrl_value);
113*e3dbbf71SOri Kam 	/* Need to sleep for a short period after pulsing the rtru init bit. */
114*e3dbbf71SOri Kam 	rte_delay_us(20000);
115*e3dbbf71SOri Kam 	/* Poll the rtru status CSR until all the init done bits are set. */
116*e3dbbf71SOri Kam 	DRV_LOG(DEBUG, "waiting for RXP rule memory to complete init");
117*e3dbbf71SOri Kam 	/* Set the init bit in the rtru ctrl CSR. */
118*e3dbbf71SOri Kam 	ctrl_value |= MLX5_RXP_RTRU_CSR_CTRL_INIT;
119*e3dbbf71SOri Kam 	mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
120*e3dbbf71SOri Kam 				       ctrl_value);
121*e3dbbf71SOri Kam 	/* Clear the init bit in the rtru ctrl CSR */
122*e3dbbf71SOri Kam 	ctrl_value &= ~MLX5_RXP_RTRU_CSR_CTRL_INIT;
123*e3dbbf71SOri Kam 	mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
124*e3dbbf71SOri Kam 				       ctrl_value);
125*e3dbbf71SOri Kam 	/* Check that the following bits are set in the RTRU_CSR. */
126*e3dbbf71SOri Kam 	if (init_bits == MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2) {
127*e3dbbf71SOri Kam 		/* Must be incremental mode */
128*e3dbbf71SOri Kam 		expected_value = MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE |
129*e3dbbf71SOri Kam 			MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
130*e3dbbf71SOri Kam 	} else {
131*e3dbbf71SOri Kam 		expected_value = MLX5_RXP_RTRU_CSR_STATUS_IM_INIT_DONE |
132*e3dbbf71SOri Kam 			MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE |
133*e3dbbf71SOri Kam 			MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
134*e3dbbf71SOri Kam 	}
135*e3dbbf71SOri Kam 	expected_mask = expected_value;
136*e3dbbf71SOri Kam 	ret = rxp_poll_csr_for_value(ctx, &poll_value,
137*e3dbbf71SOri Kam 				     MLX5_RXP_RTRU_CSR_STATUS,
138*e3dbbf71SOri Kam 				     expected_value, expected_mask,
139*e3dbbf71SOri Kam 				     MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, id);
140*e3dbbf71SOri Kam 	if (ret)
141*e3dbbf71SOri Kam 		return ret;
142*e3dbbf71SOri Kam 	DRV_LOG(DEBUG, "rule memory initialise: 0x%08X", poll_value);
143*e3dbbf71SOri Kam 	/* Clear the init bit in the rtru ctrl CSR */
144*e3dbbf71SOri Kam 	ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT);
145*e3dbbf71SOri Kam 	mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
146*e3dbbf71SOri Kam 				       ctrl_value);
147*e3dbbf71SOri Kam 	return 0;
148*e3dbbf71SOri Kam }
149*e3dbbf71SOri Kam 
150*e3dbbf71SOri Kam static int
151*e3dbbf71SOri Kam rxp_init(struct mlx5_regex_priv *priv, uint8_t id)
152*e3dbbf71SOri Kam {
153*e3dbbf71SOri Kam 	uint32_t ctrl;
154*e3dbbf71SOri Kam 	uint32_t reg;
155*e3dbbf71SOri Kam 	struct ibv_context *ctx = priv->ctx;
156*e3dbbf71SOri Kam 	int ret;
157*e3dbbf71SOri Kam 
158*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl);
159*e3dbbf71SOri Kam 	if (ret)
160*e3dbbf71SOri Kam 		return ret;
161*e3dbbf71SOri Kam 	if (ctrl & MLX5_RXP_CSR_CTRL_INIT) {
162*e3dbbf71SOri Kam 		ctrl &= ~MLX5_RXP_CSR_CTRL_INIT;
163*e3dbbf71SOri Kam 		ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL,
164*e3dbbf71SOri Kam 						     ctrl);
165*e3dbbf71SOri Kam 		if (ret)
166*e3dbbf71SOri Kam 			return ret;
167*e3dbbf71SOri Kam 	}
168*e3dbbf71SOri Kam 	ctrl |= MLX5_RXP_CSR_CTRL_INIT;
169*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl);
170*e3dbbf71SOri Kam 	if (ret)
171*e3dbbf71SOri Kam 		return ret;
172*e3dbbf71SOri Kam 	ctrl &= ~MLX5_RXP_CSR_CTRL_INIT;
173*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl);
174*e3dbbf71SOri Kam 	rte_delay_us(20000);
175*e3dbbf71SOri Kam 
176*e3dbbf71SOri Kam 	ret = rxp_poll_csr_for_value(ctx, &ctrl, MLX5_RXP_CSR_STATUS,
177*e3dbbf71SOri Kam 				     MLX5_RXP_CSR_STATUS_INIT_DONE,
178*e3dbbf71SOri Kam 				     MLX5_RXP_CSR_STATUS_INIT_DONE,
179*e3dbbf71SOri Kam 				     MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, id);
180*e3dbbf71SOri Kam 	if (ret)
181*e3dbbf71SOri Kam 		return ret;
182*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl);
183*e3dbbf71SOri Kam 	if (ret)
184*e3dbbf71SOri Kam 		return ret;
185*e3dbbf71SOri Kam 	ctrl &= ~MLX5_RXP_CSR_CTRL_INIT;
186*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL,
187*e3dbbf71SOri Kam 					     ctrl);
188*e3dbbf71SOri Kam 	if (ret)
189*e3dbbf71SOri Kam 		return ret;
190*e3dbbf71SOri Kam 	rxp_init_rtru(ctx, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2);
191*e3dbbf71SOri Kam 	ret = rxp_init_rtru(ctx, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2);
192*e3dbbf71SOri Kam 	if (ret)
193*e3dbbf71SOri Kam 		return ret;
194*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CAPABILITY_5,
195*e3dbbf71SOri Kam 					    &reg);
196*e3dbbf71SOri Kam 	if (ret)
197*e3dbbf71SOri Kam 		return ret;
198*e3dbbf71SOri Kam 	DRV_LOG(DEBUG, "max matches: %d, DDOS threshold: %d", reg >> 16,
199*e3dbbf71SOri Kam 		reg & 0xffff);
200*e3dbbf71SOri Kam 	ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_MAX_MATCH,
201*e3dbbf71SOri Kam 					     priv->nb_max_matches);
202*e3dbbf71SOri Kam 	ret |= mlx5_devx_regex_register_write(ctx, id,
203*e3dbbf71SOri Kam 					      MLX5_RXP_CSR_MAX_LATENCY, 0);
204*e3dbbf71SOri Kam 	ret |= mlx5_devx_regex_register_write(ctx, id,
205*e3dbbf71SOri Kam 					      MLX5_RXP_CSR_MAX_PRI_THREAD, 0);
206*e3dbbf71SOri Kam 	return ret;
207*e3dbbf71SOri Kam }
208*e3dbbf71SOri Kam 
209*e3dbbf71SOri Kam int
210*e3dbbf71SOri Kam mlx5_regex_configure(struct rte_regexdev *dev,
211*e3dbbf71SOri Kam 		     const struct rte_regexdev_config *cfg)
212*e3dbbf71SOri Kam {
213*e3dbbf71SOri Kam 	struct mlx5_regex_priv *priv = dev->data->dev_private;
214*e3dbbf71SOri Kam 	int ret;
215*e3dbbf71SOri Kam 	uint8_t id;
216*e3dbbf71SOri Kam 
217*e3dbbf71SOri Kam 	priv->nb_queues = cfg->nb_queue_pairs;
218*e3dbbf71SOri Kam 	priv->qps = rte_zmalloc(NULL, sizeof(struct mlx5_regex_qp) *
219*e3dbbf71SOri Kam 				priv->nb_queues, 0);
220*e3dbbf71SOri Kam 	if (!priv->nb_queues) {
221*e3dbbf71SOri Kam 		DRV_LOG(ERR, "can't allocate qps memory");
222*e3dbbf71SOri Kam 		rte_errno = ENOMEM;
223*e3dbbf71SOri Kam 		return -rte_errno;
224*e3dbbf71SOri Kam 	}
225*e3dbbf71SOri Kam 	priv->nb_max_matches = cfg->nb_max_matches;
226*e3dbbf71SOri Kam 	for (id = 0; id < 2; id++) {
227*e3dbbf71SOri Kam 		ret = rxp_stop_engine(priv->ctx, id);
228*e3dbbf71SOri Kam 		if (ret) {
229*e3dbbf71SOri Kam 			DRV_LOG(ERR, "can't stop engine.");
230*e3dbbf71SOri Kam 			rte_errno = ENODEV;
231*e3dbbf71SOri Kam 			return -rte_errno;
232*e3dbbf71SOri Kam 		}
233*e3dbbf71SOri Kam 		ret = rxp_init(priv, id);
234*e3dbbf71SOri Kam 		if (ret) {
235*e3dbbf71SOri Kam 			DRV_LOG(ERR, "can't init engine.");
236*e3dbbf71SOri Kam 			rte_errno = ENODEV;
237*e3dbbf71SOri Kam 			return -rte_errno;
238*e3dbbf71SOri Kam 		}
239*e3dbbf71SOri Kam 		ret = mlx5_devx_regex_register_write(priv->ctx, id,
240*e3dbbf71SOri Kam 						     MLX5_RXP_CSR_MAX_MATCH,
241*e3dbbf71SOri Kam 						     priv->nb_max_matches);
242*e3dbbf71SOri Kam 		if (ret) {
243*e3dbbf71SOri Kam 			DRV_LOG(ERR, "can't update number of matches.");
244*e3dbbf71SOri Kam 			rte_errno = ENODEV;
245*e3dbbf71SOri Kam 			goto configure_error;
246*e3dbbf71SOri Kam 		}
247*e3dbbf71SOri Kam 		ret = rxp_start_engine(priv->ctx, id);
248*e3dbbf71SOri Kam 		if (ret) {
249*e3dbbf71SOri Kam 			DRV_LOG(ERR, "can't start engine.");
250*e3dbbf71SOri Kam 			rte_errno = ENODEV;
251*e3dbbf71SOri Kam 			goto configure_error;
252*e3dbbf71SOri Kam 		}
253*e3dbbf71SOri Kam 
254*e3dbbf71SOri Kam 	}
255*e3dbbf71SOri Kam 	return 0;
256*e3dbbf71SOri Kam configure_error:
257*e3dbbf71SOri Kam 	if (priv->qps)
258*e3dbbf71SOri Kam 		rte_free(priv->qps);
259*e3dbbf71SOri Kam 	return -rte_errno;
260*e3dbbf71SOri Kam }
261