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 ®); 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