diff --git a/drivers/regex/mlx5/mlx5_regex.c b/drivers/regex/mlx5/mlx5_regex.c index 89d4fc84e1..118e386456 100644 --- a/drivers/regex/mlx5/mlx5_regex.c +++ b/drivers/regex/mlx5/mlx5_regex.c @@ -23,6 +23,7 @@ int mlx5_regex_logtype; const struct rte_regexdev_ops mlx5_regexdev_ops = { .dev_info_get = mlx5_regex_info_get, + .dev_configure = mlx5_regex_configure, }; static struct ibv_device * @@ -143,6 +144,7 @@ mlx5_regex_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, priv->regexdev->dev_ops = &mlx5_regexdev_ops; priv->regexdev->device = (struct rte_device *)pci_dev; priv->regexdev->data->dev_private = priv; + priv->regexdev->state = RTE_REGEXDEV_READY; return 0; error: diff --git a/drivers/regex/mlx5/mlx5_regex.h b/drivers/regex/mlx5/mlx5_regex.h index 082d1348cf..f17b4f81bd 100644 --- a/drivers/regex/mlx5/mlx5_regex.h +++ b/drivers/regex/mlx5/mlx5_regex.h @@ -7,16 +7,31 @@ #include +struct mlx5_regex_sq { + uint32_t nb_desc; /* Number of desc for this object. */ +}; + +struct mlx5_regex_qp { + uint32_t flags; /* QP user flags. */ + uint32_t nb_desc; /* Total number of desc for this qp. */ + struct mlx5_regex_sq *sqs; /* Pointer to sq array. */ +}; + struct mlx5_regex_priv { TAILQ_ENTRY(mlx5_regex_priv) next; struct ibv_context *ctx; /* Device context. */ struct rte_pci_device *pci_dev; struct rte_regexdev *regexdev; /* Pointer to the RegEx dev. */ + uint16_t nb_queues; /* Number of queues. */ + struct mlx5_regex_qp *qps; /* Pointer to the qp array. */ + uint16_t nb_max_matches; /* Max number of matches. */ }; /* mlx5_rxp.c */ int mlx5_regex_info_get(struct rte_regexdev *dev, struct rte_regexdev_info *info); +int mlx5_regex_configure(struct rte_regexdev *dev, + const struct rte_regexdev_config *cfg); /* mlx5_regex_devx.c */ int mlx5_devx_regex_register_write(struct ibv_context *ctx, int engine_id, diff --git a/drivers/regex/mlx5/mlx5_rxp.c b/drivers/regex/mlx5/mlx5_rxp.c index 9a9645f30d..bc940e62a3 100644 --- a/drivers/regex/mlx5/mlx5_rxp.c +++ b/drivers/regex/mlx5/mlx5_rxp.c @@ -4,11 +4,18 @@ #include #include +#include #include #include #include +#include +#include +#include + #include "mlx5_regex.h" +#include "mlx5_regex_utils.h" +#include "mlx5_rxp_csrs.h" #define MLX5_REGEX_MAX_MATCHES 255 #define MLX5_REGEX_MAX_PAYLOAD_SIZE UINT16_MAX @@ -27,3 +34,227 @@ mlx5_regex_info_get(struct rte_regexdev *dev __rte_unused, info->rule_flags = 0; return 0; } + +static int +rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value, + uint32_t address, uint32_t expected_value, + uint32_t expected_mask, uint32_t timeout_ms, uint8_t id) +{ + unsigned int i; + int ret; + + ret = -EBUSY; + for (i = 0; i < timeout_ms; i++) { + if (mlx5_devx_regex_register_read(ctx, id, address, value)) + return -1; + + if ((*value & expected_mask) == expected_value) { + ret = 0; + break; + } + rte_delay_us(1000); + } + return ret; +} + +static int +rxp_start_engine(struct ibv_context *ctx, uint8_t id) +{ + uint32_t ctrl; + int ret; + + ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl); + if (ret) + return ret; + ctrl |= MLX5_RXP_CSR_CTRL_GO; + ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl); + return ret; +} + +static int +rxp_stop_engine(struct ibv_context *ctx, uint8_t id) +{ + uint32_t ctrl; + int ret; + + ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl); + if (ret) + return ret; + ctrl &= ~MLX5_RXP_CSR_CTRL_GO; + ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl); + return ret; +} + +static int +rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits) +{ + uint32_t ctrl_value; + uint32_t poll_value; + uint32_t expected_value; + uint32_t expected_mask; + int ret = 0; + + /* Read the rtru ctrl CSR. */ + ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, + &ctrl_value); + if (ret) + return -1; + /* Clear any previous init modes. */ + ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_MASK); + if (ctrl_value & MLX5_RXP_RTRU_CSR_CTRL_INIT) { + ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT); + mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, + ctrl_value); + } + /* Set the init_mode bits in the rtru ctrl CSR. */ + ctrl_value |= init_bits; + mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, + ctrl_value); + /* Need to sleep for a short period after pulsing the rtru init bit. */ + rte_delay_us(20000); + /* Poll the rtru status CSR until all the init done bits are set. */ + DRV_LOG(DEBUG, "waiting for RXP rule memory to complete init"); + /* Set the init bit in the rtru ctrl CSR. */ + ctrl_value |= MLX5_RXP_RTRU_CSR_CTRL_INIT; + mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, + ctrl_value); + /* Clear the init bit in the rtru ctrl CSR */ + ctrl_value &= ~MLX5_RXP_RTRU_CSR_CTRL_INIT; + mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, + ctrl_value); + /* Check that the following bits are set in the RTRU_CSR. */ + if (init_bits == MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2) { + /* Must be incremental mode */ + expected_value = MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE | + MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE; + } else { + expected_value = MLX5_RXP_RTRU_CSR_STATUS_IM_INIT_DONE | + MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE | + MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE; + } + expected_mask = expected_value; + ret = rxp_poll_csr_for_value(ctx, &poll_value, + MLX5_RXP_RTRU_CSR_STATUS, + expected_value, expected_mask, + MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, id); + if (ret) + return ret; + DRV_LOG(DEBUG, "rule memory initialise: 0x%08X", poll_value); + /* Clear the init bit in the rtru ctrl CSR */ + ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT); + mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, + ctrl_value); + return 0; +} + +static int +rxp_init(struct mlx5_regex_priv *priv, uint8_t id) +{ + uint32_t ctrl; + uint32_t reg; + struct ibv_context *ctx = priv->ctx; + int ret; + + ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl); + if (ret) + return ret; + if (ctrl & MLX5_RXP_CSR_CTRL_INIT) { + ctrl &= ~MLX5_RXP_CSR_CTRL_INIT; + ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, + ctrl); + if (ret) + return ret; + } + ctrl |= MLX5_RXP_CSR_CTRL_INIT; + ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl); + if (ret) + return ret; + ctrl &= ~MLX5_RXP_CSR_CTRL_INIT; + ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl); + rte_delay_us(20000); + + ret = rxp_poll_csr_for_value(ctx, &ctrl, MLX5_RXP_CSR_STATUS, + MLX5_RXP_CSR_STATUS_INIT_DONE, + MLX5_RXP_CSR_STATUS_INIT_DONE, + MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, id); + if (ret) + return ret; + ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl); + if (ret) + return ret; + ctrl &= ~MLX5_RXP_CSR_CTRL_INIT; + ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, + ctrl); + if (ret) + return ret; + rxp_init_rtru(ctx, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2); + ret = rxp_init_rtru(ctx, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2); + if (ret) + return ret; + ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CAPABILITY_5, + ®); + if (ret) + return ret; + DRV_LOG(DEBUG, "max matches: %d, DDOS threshold: %d", reg >> 16, + reg & 0xffff); + ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_MAX_MATCH, + priv->nb_max_matches); + ret |= mlx5_devx_regex_register_write(ctx, id, + MLX5_RXP_CSR_MAX_LATENCY, 0); + ret |= mlx5_devx_regex_register_write(ctx, id, + MLX5_RXP_CSR_MAX_PRI_THREAD, 0); + return ret; +} + +int +mlx5_regex_configure(struct rte_regexdev *dev, + const struct rte_regexdev_config *cfg) +{ + struct mlx5_regex_priv *priv = dev->data->dev_private; + int ret; + uint8_t id; + + priv->nb_queues = cfg->nb_queue_pairs; + priv->qps = rte_zmalloc(NULL, sizeof(struct mlx5_regex_qp) * + priv->nb_queues, 0); + if (!priv->nb_queues) { + DRV_LOG(ERR, "can't allocate qps memory"); + rte_errno = ENOMEM; + return -rte_errno; + } + priv->nb_max_matches = cfg->nb_max_matches; + for (id = 0; id < 2; id++) { + ret = rxp_stop_engine(priv->ctx, id); + if (ret) { + DRV_LOG(ERR, "can't stop engine."); + rte_errno = ENODEV; + return -rte_errno; + } + ret = rxp_init(priv, id); + if (ret) { + DRV_LOG(ERR, "can't init engine."); + rte_errno = ENODEV; + return -rte_errno; + } + ret = mlx5_devx_regex_register_write(priv->ctx, id, + MLX5_RXP_CSR_MAX_MATCH, + priv->nb_max_matches); + if (ret) { + DRV_LOG(ERR, "can't update number of matches."); + rte_errno = ENODEV; + goto configure_error; + } + ret = rxp_start_engine(priv->ctx, id); + if (ret) { + DRV_LOG(ERR, "can't start engine."); + rte_errno = ENODEV; + goto configure_error; + } + + } + return 0; +configure_error: + if (priv->qps) + rte_free(priv->qps); + return -rte_errno; +}