regex/mlx5: support configuration

This commit implements the configure function.
This function is responsible to configure the RegEx engine.

Signed-off-by: Ori Kam <orika@mellanox.com>
This commit is contained in:
Ori Kam 2020-07-20 06:26:10 +00:00 committed by Thomas Monjalon
parent 9428310ae1
commit e3dbbf718e
3 changed files with 248 additions and 0 deletions

View File

@ -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:

View File

@ -7,16 +7,31 @@
#include <rte_regexdev.h>
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,

View File

@ -4,11 +4,18 @@
#include <rte_log.h>
#include <rte_errno.h>
#include <rte_malloc.h>
#include <rte_regexdev.h>
#include <rte_regexdev_core.h>
#include <rte_regexdev_driver.h>
#include <mlx5_glue.h>
#include <mlx5_devx_cmds.h>
#include <mlx5_prm.h>
#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,
&reg);
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;
}