1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 Mellanox Technologies, Ltd
7 #include <rte_malloc.h>
8 #include <rte_regexdev.h>
9 #include <rte_regexdev_core.h>
10 #include <rte_regexdev_driver.h>
12 #include <mlx5_glue.h>
13 #include <mlx5_devx_cmds.h>
16 #include "mlx5_regex.h"
17 #include "mlx5_regex_utils.h"
18 #include "mlx5_rxp_csrs.h"
20 #define MLX5_REGEX_MAX_MATCHES 255
21 #define MLX5_REGEX_MAX_PAYLOAD_SIZE UINT16_MAX
22 #define MLX5_REGEX_MAX_RULES_PER_GROUP UINT16_MAX
23 #define MLX5_REGEX_MAX_GROUPS UINT16_MAX
26 mlx5_regex_info_get(struct rte_regexdev *dev __rte_unused,
27 struct rte_regexdev_info *info)
29 info->max_matches = MLX5_REGEX_MAX_MATCHES;
30 info->max_payload_size = MLX5_REGEX_MAX_PAYLOAD_SIZE;
31 info->max_rules_per_group = MLX5_REGEX_MAX_RULES_PER_GROUP;
32 info->max_groups = MLX5_REGEX_MAX_GROUPS;
33 info->regexdev_capa = RTE_REGEXDEV_SUPP_PCRE_GREEDY_F;
39 rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value,
40 uint32_t address, uint32_t expected_value,
41 uint32_t expected_mask, uint32_t timeout_ms, uint8_t id)
47 for (i = 0; i < timeout_ms; i++) {
48 if (mlx5_devx_regex_register_read(ctx, id, address, value))
51 if ((*value & expected_mask) == expected_value) {
61 rxp_start_engine(struct ibv_context *ctx, uint8_t id)
66 ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl);
69 ctrl |= MLX5_RXP_CSR_CTRL_GO;
70 ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl);
75 rxp_stop_engine(struct ibv_context *ctx, uint8_t id)
80 ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl);
83 ctrl &= ~MLX5_RXP_CSR_CTRL_GO;
84 ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl);
89 rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits)
93 uint32_t expected_value;
94 uint32_t expected_mask;
97 /* Read the rtru ctrl CSR. */
98 ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
102 /* Clear any previous init modes. */
103 ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_MASK);
104 if (ctrl_value & MLX5_RXP_RTRU_CSR_CTRL_INIT) {
105 ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT);
106 mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
109 /* Set the init_mode bits in the rtru ctrl CSR. */
110 ctrl_value |= init_bits;
111 mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
113 /* Need to sleep for a short period after pulsing the rtru init bit. */
115 /* Poll the rtru status CSR until all the init done bits are set. */
116 DRV_LOG(DEBUG, "waiting for RXP rule memory to complete init");
117 /* Set the init bit in the rtru ctrl CSR. */
118 ctrl_value |= MLX5_RXP_RTRU_CSR_CTRL_INIT;
119 mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
121 /* Clear the init bit in the rtru ctrl CSR */
122 ctrl_value &= ~MLX5_RXP_RTRU_CSR_CTRL_INIT;
123 mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
125 /* Check that the following bits are set in the RTRU_CSR. */
126 if (init_bits == MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2) {
127 /* Must be incremental mode */
128 expected_value = MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE |
129 MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
131 expected_value = MLX5_RXP_RTRU_CSR_STATUS_IM_INIT_DONE |
132 MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE |
133 MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
135 expected_mask = expected_value;
136 ret = rxp_poll_csr_for_value(ctx, &poll_value,
137 MLX5_RXP_RTRU_CSR_STATUS,
138 expected_value, expected_mask,
139 MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, id);
142 DRV_LOG(DEBUG, "rule memory initialise: 0x%08X", poll_value);
143 /* Clear the init bit in the rtru ctrl CSR */
144 ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT);
145 mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
151 rxp_init(struct mlx5_regex_priv *priv, uint8_t id)
155 struct ibv_context *ctx = priv->ctx;
158 ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl);
161 if (ctrl & MLX5_RXP_CSR_CTRL_INIT) {
162 ctrl &= ~MLX5_RXP_CSR_CTRL_INIT;
163 ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL,
168 ctrl |= MLX5_RXP_CSR_CTRL_INIT;
169 ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl);
172 ctrl &= ~MLX5_RXP_CSR_CTRL_INIT;
173 ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl);
176 ret = rxp_poll_csr_for_value(ctx, &ctrl, MLX5_RXP_CSR_STATUS,
177 MLX5_RXP_CSR_STATUS_INIT_DONE,
178 MLX5_RXP_CSR_STATUS_INIT_DONE,
179 MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, id);
182 ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl);
185 ctrl &= ~MLX5_RXP_CSR_CTRL_INIT;
186 ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL,
190 rxp_init_rtru(ctx, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2);
191 ret = rxp_init_rtru(ctx, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2);
194 ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CAPABILITY_5,
198 DRV_LOG(DEBUG, "max matches: %d, DDOS threshold: %d", reg >> 16,
200 ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_MAX_MATCH,
201 priv->nb_max_matches);
202 ret |= mlx5_devx_regex_register_write(ctx, id,
203 MLX5_RXP_CSR_MAX_LATENCY, 0);
204 ret |= mlx5_devx_regex_register_write(ctx, id,
205 MLX5_RXP_CSR_MAX_PRI_THREAD, 0);
210 mlx5_regex_configure(struct rte_regexdev *dev,
211 const struct rte_regexdev_config *cfg)
213 struct mlx5_regex_priv *priv = dev->data->dev_private;
217 priv->nb_queues = cfg->nb_queue_pairs;
218 priv->qps = rte_zmalloc(NULL, sizeof(struct mlx5_regex_qp) *
220 if (!priv->nb_queues) {
221 DRV_LOG(ERR, "can't allocate qps memory");
225 priv->nb_max_matches = cfg->nb_max_matches;
226 for (id = 0; id < 2; id++) {
227 ret = rxp_stop_engine(priv->ctx, id);
229 DRV_LOG(ERR, "can't stop engine.");
233 ret = rxp_init(priv, id);
235 DRV_LOG(ERR, "can't init engine.");
239 ret = mlx5_devx_regex_register_write(priv->ctx, id,
240 MLX5_RXP_CSR_MAX_MATCH,
241 priv->nb_max_matches);
243 DRV_LOG(ERR, "can't update number of matches.");
245 goto configure_error;
247 ret = rxp_start_engine(priv->ctx, id);
249 DRV_LOG(ERR, "can't start engine.");
251 goto configure_error;