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> 7e3dbbf71SOri 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> 11*f324162eSOri Kam #include <sys/mman.h> 12c126512bSOri Kam 13e3dbbf71SOri Kam #include <mlx5_glue.h> 14e3dbbf71SOri Kam #include <mlx5_devx_cmds.h> 15e3dbbf71SOri Kam #include <mlx5_prm.h> 16b34d8163SFrancis Kelly #include <mlx5_common_os.h> 17e3dbbf71SOri Kam 18c126512bSOri Kam #include "mlx5_regex.h" 19e3dbbf71SOri Kam #include "mlx5_regex_utils.h" 20e3dbbf71SOri Kam #include "mlx5_rxp_csrs.h" 21b34d8163SFrancis Kelly #include "mlx5_rxp.h" 22c126512bSOri Kam 23b34d8163SFrancis Kelly #define MLX5_REGEX_MAX_MATCHES MLX5_RXP_MAX_MATCHES 24b34d8163SFrancis Kelly #define MLX5_REGEX_MAX_PAYLOAD_SIZE MLX5_RXP_MAX_JOB_LENGTH 25b34d8163SFrancis Kelly #define MLX5_REGEX_MAX_RULES_PER_GROUP UINT32_MAX 26b34d8163SFrancis Kelly #define MLX5_REGEX_MAX_GROUPS MLX5_RXP_MAX_SUBSETS 27b34d8163SFrancis Kelly 28*f324162eSOri Kam #define MLX5_REGEX_RXP_ROF2_LINE_LEN 34 29*f324162eSOri Kam 30b34d8163SFrancis Kelly /* Private Declarations */ 31b34d8163SFrancis Kelly static int 32b34d8163SFrancis Kelly rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value, 33b34d8163SFrancis Kelly uint32_t address, uint32_t expected_value, 34b34d8163SFrancis Kelly uint32_t expected_mask, uint32_t timeout_ms, uint8_t id); 35b34d8163SFrancis Kelly static int 36b34d8163SFrancis Kelly mlnx_set_database(struct mlx5_regex_priv *priv, uint8_t id, uint8_t db_to_use); 37b34d8163SFrancis Kelly static int 38b34d8163SFrancis Kelly mlnx_resume_database(struct mlx5_regex_priv *priv, uint8_t id); 39b34d8163SFrancis Kelly static int 40b34d8163SFrancis Kelly mlnx_update_database(struct mlx5_regex_priv *priv, uint8_t id); 41b34d8163SFrancis Kelly static int 42*f324162eSOri Kam program_rxp_rules(struct mlx5_regex_priv *priv, const char *buf, uint32_t len, 43b34d8163SFrancis Kelly uint8_t id); 44b34d8163SFrancis Kelly static int 45*f324162eSOri Kam rxp_init_eng(struct mlx5_regex_priv *priv, uint8_t id); 46b34d8163SFrancis Kelly static int 47b34d8163SFrancis Kelly rxp_db_setup(struct mlx5_regex_priv *priv); 48b34d8163SFrancis Kelly static void 49b34d8163SFrancis Kelly rxp_dump_csrs(struct ibv_context *ctx, uint8_t id); 50b34d8163SFrancis Kelly static int 51b34d8163SFrancis Kelly rxp_start_engine(struct ibv_context *ctx, uint8_t id); 52b34d8163SFrancis Kelly static int 53b34d8163SFrancis Kelly rxp_stop_engine(struct ibv_context *ctx, uint8_t id); 54b34d8163SFrancis Kelly 55b34d8163SFrancis Kelly static void __rte_unused 56b34d8163SFrancis Kelly rxp_dump_csrs(struct ibv_context *ctx __rte_unused, uint8_t id __rte_unused) 57b34d8163SFrancis Kelly { 58b34d8163SFrancis Kelly uint32_t reg, i; 59b34d8163SFrancis Kelly 60b34d8163SFrancis Kelly /* Main CSRs*/ 61b34d8163SFrancis Kelly for (i = 0; i < MLX5_RXP_CSR_NUM_ENTRIES; i++) { 62b34d8163SFrancis Kelly if (mlx5_devx_regex_register_read(ctx, id, 63b34d8163SFrancis Kelly (MLX5_RXP_CSR_WIDTH * i) + 64b34d8163SFrancis Kelly MLX5_RXP_CSR_BASE_ADDRESS, 65b34d8163SFrancis Kelly ®)) { 66b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to read Main CSRs Engine %d!", id); 67b34d8163SFrancis Kelly return; 68b34d8163SFrancis Kelly } 69b34d8163SFrancis Kelly DRV_LOG(DEBUG, "RXP Main CSRs (Eng%d) register (%d): %08x", 70b34d8163SFrancis Kelly id, i, reg); 71b34d8163SFrancis Kelly } 72b34d8163SFrancis Kelly /* RTRU CSRs*/ 73b34d8163SFrancis Kelly for (i = 0; i < MLX5_RXP_CSR_NUM_ENTRIES; i++) { 74b34d8163SFrancis Kelly if (mlx5_devx_regex_register_read(ctx, id, 75b34d8163SFrancis Kelly (MLX5_RXP_CSR_WIDTH * i) + 76b34d8163SFrancis Kelly MLX5_RXP_RTRU_CSR_BASE_ADDRESS, 77b34d8163SFrancis Kelly ®)) { 78b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to read RTRU CSRs Engine %d!", id); 79b34d8163SFrancis Kelly return; 80b34d8163SFrancis Kelly } 81b34d8163SFrancis Kelly DRV_LOG(DEBUG, "RXP RTRU CSRs (Eng%d) register (%d): %08x", 82b34d8163SFrancis Kelly id, i, reg); 83b34d8163SFrancis Kelly } 84b34d8163SFrancis Kelly /* STAT CSRs */ 85b34d8163SFrancis Kelly for (i = 0; i < MLX5_RXP_CSR_NUM_ENTRIES; i++) { 86b34d8163SFrancis Kelly if (mlx5_devx_regex_register_read(ctx, id, 87b34d8163SFrancis Kelly (MLX5_RXP_CSR_WIDTH * i) + 88b34d8163SFrancis Kelly MLX5_RXP_STATS_CSR_BASE_ADDRESS, 89b34d8163SFrancis Kelly ®)) { 90b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to read STAT CSRs Engine %d!", id); 91b34d8163SFrancis Kelly return; 92b34d8163SFrancis Kelly } 93b34d8163SFrancis Kelly DRV_LOG(DEBUG, "RXP STAT CSRs (Eng%d) register (%d): %08x", 94b34d8163SFrancis Kelly id, i, reg); 95b34d8163SFrancis Kelly } 96b34d8163SFrancis Kelly } 97c126512bSOri Kam 98c126512bSOri Kam int 99c126512bSOri Kam mlx5_regex_info_get(struct rte_regexdev *dev __rte_unused, 100c126512bSOri Kam struct rte_regexdev_info *info) 101c126512bSOri Kam { 102c126512bSOri Kam info->max_matches = MLX5_REGEX_MAX_MATCHES; 103c126512bSOri Kam info->max_payload_size = MLX5_REGEX_MAX_PAYLOAD_SIZE; 104c126512bSOri Kam info->max_rules_per_group = MLX5_REGEX_MAX_RULES_PER_GROUP; 105c126512bSOri Kam info->max_groups = MLX5_REGEX_MAX_GROUPS; 106b34d8163SFrancis Kelly info->max_queue_pairs = 1; 107c8452005SOphir Munk info->regexdev_capa = RTE_REGEXDEV_SUPP_PCRE_GREEDY_F | 108c8452005SOphir Munk RTE_REGEXDEV_CAPA_QUEUE_PAIR_OOS_F; 109c126512bSOri Kam info->rule_flags = 0; 110fbc8c700SOri Kam info->max_queue_pairs = 10; 111c126512bSOri Kam return 0; 112c126512bSOri Kam } 113e3dbbf71SOri Kam 114e3dbbf71SOri Kam static int 115e3dbbf71SOri Kam rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value, 116e3dbbf71SOri Kam uint32_t address, uint32_t expected_value, 117e3dbbf71SOri Kam uint32_t expected_mask, uint32_t timeout_ms, uint8_t id) 118e3dbbf71SOri Kam { 119e3dbbf71SOri Kam unsigned int i; 12097de3671SMichael Baum int ret; 121e3dbbf71SOri Kam 122e3dbbf71SOri Kam ret = -EBUSY; 123e3dbbf71SOri Kam for (i = 0; i < timeout_ms; i++) { 124e3dbbf71SOri Kam if (mlx5_devx_regex_register_read(ctx, id, address, value)) 125e3dbbf71SOri Kam return -1; 126e3dbbf71SOri Kam if ((*value & expected_mask) == expected_value) { 127e3dbbf71SOri Kam ret = 0; 128e3dbbf71SOri Kam break; 129e3dbbf71SOri Kam } 130e3dbbf71SOri Kam rte_delay_us(1000); 131e3dbbf71SOri Kam } 132e3dbbf71SOri Kam return ret; 133e3dbbf71SOri Kam } 134e3dbbf71SOri Kam 135e3dbbf71SOri Kam static int 136e3dbbf71SOri Kam rxp_start_engine(struct ibv_context *ctx, uint8_t id) 137e3dbbf71SOri Kam { 138e3dbbf71SOri Kam uint32_t ctrl; 139e3dbbf71SOri Kam int ret; 140e3dbbf71SOri Kam 141e3dbbf71SOri Kam ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl); 142e3dbbf71SOri Kam if (ret) 143e3dbbf71SOri Kam return ret; 144e3dbbf71SOri Kam ctrl |= MLX5_RXP_CSR_CTRL_GO; 145b34d8163SFrancis Kelly ctrl |= MLX5_RXP_CSR_CTRL_DISABLE_L2C; 146e3dbbf71SOri Kam ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl); 147e3dbbf71SOri Kam return ret; 148e3dbbf71SOri Kam } 149e3dbbf71SOri Kam 150e3dbbf71SOri Kam static int 151e3dbbf71SOri Kam rxp_stop_engine(struct ibv_context *ctx, uint8_t id) 152e3dbbf71SOri Kam { 153e3dbbf71SOri Kam uint32_t ctrl; 154e3dbbf71SOri Kam int ret; 155e3dbbf71SOri Kam 156e3dbbf71SOri Kam ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl); 157e3dbbf71SOri Kam if (ret) 158e3dbbf71SOri Kam return ret; 159e3dbbf71SOri Kam ctrl &= ~MLX5_RXP_CSR_CTRL_GO; 160e3dbbf71SOri Kam ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl); 161e3dbbf71SOri Kam return ret; 162e3dbbf71SOri Kam } 163e3dbbf71SOri Kam 164e3dbbf71SOri Kam static int 165*f324162eSOri Kam rxp_init_rtru(struct mlx5_regex_priv *priv, uint8_t id, uint32_t init_bits) 166e3dbbf71SOri Kam { 167e3dbbf71SOri Kam uint32_t ctrl_value; 168e3dbbf71SOri Kam uint32_t poll_value; 169e3dbbf71SOri Kam uint32_t expected_value; 170e3dbbf71SOri Kam uint32_t expected_mask; 171*f324162eSOri Kam struct ibv_context *ctx = priv->ctx; 172*f324162eSOri Kam int ret = 0; 173e3dbbf71SOri Kam 174e3dbbf71SOri Kam /* Read the rtru ctrl CSR. */ 175e3dbbf71SOri Kam ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, 176e3dbbf71SOri Kam &ctrl_value); 177e3dbbf71SOri Kam if (ret) 178e3dbbf71SOri Kam return -1; 179e3dbbf71SOri Kam /* Clear any previous init modes. */ 180e3dbbf71SOri Kam ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_MASK); 181e3dbbf71SOri Kam if (ctrl_value & MLX5_RXP_RTRU_CSR_CTRL_INIT) { 182e3dbbf71SOri Kam ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT); 183e3dbbf71SOri Kam mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, 184e3dbbf71SOri Kam ctrl_value); 185e3dbbf71SOri Kam } 186e3dbbf71SOri Kam /* Set the init_mode bits in the rtru ctrl CSR. */ 187e3dbbf71SOri Kam ctrl_value |= init_bits; 188e3dbbf71SOri Kam mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, 189e3dbbf71SOri Kam ctrl_value); 190e3dbbf71SOri Kam /* Need to sleep for a short period after pulsing the rtru init bit. */ 191e3dbbf71SOri Kam rte_delay_us(20000); 192e3dbbf71SOri Kam /* Poll the rtru status CSR until all the init done bits are set. */ 193e3dbbf71SOri Kam DRV_LOG(DEBUG, "waiting for RXP rule memory to complete init"); 194e3dbbf71SOri Kam /* Set the init bit in the rtru ctrl CSR. */ 195e3dbbf71SOri Kam ctrl_value |= MLX5_RXP_RTRU_CSR_CTRL_INIT; 196e3dbbf71SOri Kam mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, 197e3dbbf71SOri Kam ctrl_value); 198e3dbbf71SOri Kam /* Clear the init bit in the rtru ctrl CSR */ 199e3dbbf71SOri Kam ctrl_value &= ~MLX5_RXP_RTRU_CSR_CTRL_INIT; 200e3dbbf71SOri Kam mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, 201e3dbbf71SOri Kam ctrl_value); 202e3dbbf71SOri Kam /* Check that the following bits are set in the RTRU_CSR. */ 203e3dbbf71SOri Kam if (init_bits == MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2) { 204e3dbbf71SOri Kam /* Must be incremental mode */ 205*f324162eSOri Kam expected_value = MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE; 206e3dbbf71SOri Kam } else { 207e3dbbf71SOri Kam expected_value = MLX5_RXP_RTRU_CSR_STATUS_IM_INIT_DONE | 208*f324162eSOri Kam MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE; 209e3dbbf71SOri Kam } 210*f324162eSOri Kam if (priv->is_bf2) 211*f324162eSOri Kam expected_value |= MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE; 212*f324162eSOri Kam 213*f324162eSOri Kam 214e3dbbf71SOri Kam expected_mask = expected_value; 215e3dbbf71SOri Kam ret = rxp_poll_csr_for_value(ctx, &poll_value, 216e3dbbf71SOri Kam MLX5_RXP_RTRU_CSR_STATUS, 217e3dbbf71SOri Kam expected_value, expected_mask, 218e3dbbf71SOri Kam MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, id); 219e3dbbf71SOri Kam if (ret) 220e3dbbf71SOri Kam return ret; 221e3dbbf71SOri Kam DRV_LOG(DEBUG, "rule memory initialise: 0x%08X", poll_value); 222e3dbbf71SOri Kam /* Clear the init bit in the rtru ctrl CSR */ 223e3dbbf71SOri Kam ctrl_value &= ~(MLX5_RXP_RTRU_CSR_CTRL_INIT); 224e3dbbf71SOri Kam mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL, 225e3dbbf71SOri Kam ctrl_value); 226e3dbbf71SOri Kam return 0; 227e3dbbf71SOri Kam } 228e3dbbf71SOri Kam 229e3dbbf71SOri Kam static int 230*f324162eSOri Kam rxp_parse_line(char *line, uint32_t *type, uint32_t *address, uint64_t *value) 231*f324162eSOri Kam { 232*f324162eSOri Kam char *cur_pos; 233*f324162eSOri Kam 234*f324162eSOri Kam if (*line == '\0' || *line == '#') 235*f324162eSOri Kam return 1; 236*f324162eSOri Kam *type = strtoul(line, &cur_pos, 10); 237*f324162eSOri Kam if (*cur_pos != ',' && *cur_pos != '\0') 238*f324162eSOri Kam return -1; 239*f324162eSOri Kam *address = strtoul(cur_pos+1, &cur_pos, 16); 240*f324162eSOri Kam if (*cur_pos != ',' && *cur_pos != '\0') 241*f324162eSOri Kam return -1; 242*f324162eSOri Kam *value = strtoul(cur_pos+1, &cur_pos, 16); 243*f324162eSOri Kam if (*cur_pos != ',' && *cur_pos != '\0') 244*f324162eSOri Kam return -1; 245*f324162eSOri Kam return 0; 246*f324162eSOri Kam } 247*f324162eSOri Kam 248*f324162eSOri Kam static uint32_t 249*f324162eSOri Kam rxp_get_reg_address(uint32_t address) 250*f324162eSOri Kam { 251*f324162eSOri Kam uint32_t block; 252*f324162eSOri Kam uint32_t reg; 253*f324162eSOri Kam 254*f324162eSOri Kam block = (address >> 16) & 0xFFFF; 255*f324162eSOri Kam if (block == 0) 256*f324162eSOri Kam reg = MLX5_RXP_CSR_BASE_ADDRESS; 257*f324162eSOri Kam else if (block == 1) 258*f324162eSOri Kam reg = MLX5_RXP_RTRU_CSR_BASE_ADDRESS; 259*f324162eSOri Kam else { 260*f324162eSOri Kam DRV_LOG(ERR, "Invalid ROF register 0x%08X!", address); 261*f324162eSOri Kam return UINT32_MAX; 262*f324162eSOri Kam } 263*f324162eSOri Kam reg += (address & 0xFFFF) * MLX5_RXP_CSR_WIDTH; 264*f324162eSOri Kam return reg; 265*f324162eSOri Kam } 266*f324162eSOri Kam 267*f324162eSOri Kam #define MLX5_RXP_NUM_LINES_PER_BLOCK 8 268*f324162eSOri Kam 269*f324162eSOri Kam static int 270*f324162eSOri Kam rxp_program_rof(struct mlx5_regex_priv *priv, const char *buf, uint32_t len, 271*f324162eSOri Kam uint8_t id) 272b34d8163SFrancis Kelly { 273b34d8163SFrancis Kelly static const char del[] = "\n\r"; 274b34d8163SFrancis Kelly char *line; 275b34d8163SFrancis Kelly char *tmp; 276*f324162eSOri Kam uint32_t type = 0; 277*f324162eSOri Kam uint32_t address; 278*f324162eSOri Kam uint64_t val; 279*f324162eSOri Kam uint32_t reg_val; 280*f324162eSOri Kam int ret; 281*f324162eSOri Kam int skip = -1; 282*f324162eSOri Kam int last = 0; 283*f324162eSOri Kam uint32_t temp; 284*f324162eSOri Kam uint32_t tmp_addr; 285*f324162eSOri Kam uint32_t rof_rule_addr; 286*f324162eSOri Kam uint64_t tmp_write_swap[4]; 287*f324162eSOri Kam struct mlx5_rxp_rof_entry rules[8]; 288*f324162eSOri Kam int i; 289*f324162eSOri Kam int db_free; 290*f324162eSOri Kam int j; 291b34d8163SFrancis Kelly 292b34d8163SFrancis Kelly tmp = rte_malloc("", len, 0); 293b34d8163SFrancis Kelly if (!tmp) 294b34d8163SFrancis Kelly return -ENOMEM; 295b34d8163SFrancis Kelly memcpy(tmp, buf, len); 296*f324162eSOri Kam db_free = mlnx_update_database(priv, id); 297*f324162eSOri Kam if (db_free < 0) { 298*f324162eSOri Kam DRV_LOG(ERR, "Failed to setup db memory!"); 299b34d8163SFrancis Kelly rte_free(tmp); 300*f324162eSOri Kam return db_free; 301b34d8163SFrancis Kelly } 302*f324162eSOri Kam for (line = strtok(tmp, del), j = 0; line; line = strtok(NULL, del), 303*f324162eSOri Kam j++, last = type) { 304*f324162eSOri Kam ret = rxp_parse_line(line, &type, &address, &val); 305*f324162eSOri Kam if (ret != 0) { 306*f324162eSOri Kam if (ret < 0) 307*f324162eSOri Kam goto parse_error; 308b34d8163SFrancis Kelly continue; 309b34d8163SFrancis Kelly } 310*f324162eSOri Kam switch (type) { 311*f324162eSOri Kam case MLX5_RXP_ROF_ENTRY_EQ: 312*f324162eSOri Kam if (skip == 0 && address == 0) 313*f324162eSOri Kam skip = 1; 314*f324162eSOri Kam tmp_addr = rxp_get_reg_address(address); 315*f324162eSOri Kam if (tmp_addr == UINT32_MAX) 316b34d8163SFrancis Kelly goto parse_error; 317*f324162eSOri Kam ret = mlx5_devx_regex_register_read(priv->ctx, id, 318*f324162eSOri Kam tmp_addr, ®_val); 319*f324162eSOri Kam if (ret) 320b34d8163SFrancis Kelly goto parse_error; 321*f324162eSOri Kam if (skip == -1 && address == 0) { 322*f324162eSOri Kam if (val == reg_val) { 323*f324162eSOri Kam skip = 0; 324*f324162eSOri Kam continue; 325b34d8163SFrancis Kelly } 326*f324162eSOri Kam } else if (skip == 0) { 327*f324162eSOri Kam if (val != reg_val) { 328*f324162eSOri Kam DRV_LOG(ERR, 329*f324162eSOri Kam "got %08X expected == %" PRIx64, 330*f324162eSOri Kam reg_val, val); 331*f324162eSOri Kam goto parse_error; 332*f324162eSOri Kam } 333*f324162eSOri Kam } 334*f324162eSOri Kam break; 335*f324162eSOri Kam case MLX5_RXP_ROF_ENTRY_GTE: 336*f324162eSOri Kam if (skip == 0 && address == 0) 337*f324162eSOri Kam skip = 1; 338*f324162eSOri Kam tmp_addr = rxp_get_reg_address(address); 339*f324162eSOri Kam if (tmp_addr == UINT32_MAX) 340*f324162eSOri Kam goto parse_error; 341*f324162eSOri Kam ret = mlx5_devx_regex_register_read(priv->ctx, id, 342*f324162eSOri Kam tmp_addr, ®_val); 343*f324162eSOri Kam if (ret) 344*f324162eSOri Kam goto parse_error; 345*f324162eSOri Kam if (skip == -1 && address == 0) { 346*f324162eSOri Kam if (reg_val >= val) { 347*f324162eSOri Kam skip = 0; 348*f324162eSOri Kam continue; 349*f324162eSOri Kam } 350*f324162eSOri Kam } else if (skip == 0) { 351*f324162eSOri Kam if (reg_val < val) { 352*f324162eSOri Kam DRV_LOG(ERR, 353*f324162eSOri Kam "got %08X expected >= %" PRIx64, 354*f324162eSOri Kam reg_val, val); 355*f324162eSOri Kam goto parse_error; 356*f324162eSOri Kam } 357*f324162eSOri Kam } 358*f324162eSOri Kam break; 359*f324162eSOri Kam case MLX5_RXP_ROF_ENTRY_LTE: 360*f324162eSOri Kam tmp_addr = rxp_get_reg_address(address); 361*f324162eSOri Kam if (tmp_addr == UINT32_MAX) 362*f324162eSOri Kam goto parse_error; 363*f324162eSOri Kam ret = mlx5_devx_regex_register_read(priv->ctx, id, 364*f324162eSOri Kam tmp_addr, ®_val); 365*f324162eSOri Kam if (ret) 366*f324162eSOri Kam goto parse_error; 367*f324162eSOri Kam if (skip == 0 && address == 0 && 368*f324162eSOri Kam last != MLX5_RXP_ROF_ENTRY_GTE) { 369*f324162eSOri Kam skip = 1; 370*f324162eSOri Kam } else if (skip == 0 && address == 0 && 371*f324162eSOri Kam last == MLX5_RXP_ROF_ENTRY_GTE) { 372*f324162eSOri Kam if (reg_val > val) 373*f324162eSOri Kam skip = -1; 374*f324162eSOri Kam continue; 375*f324162eSOri Kam } 376*f324162eSOri Kam if (skip == -1 && address == 0) { 377*f324162eSOri Kam if (reg_val <= val) { 378*f324162eSOri Kam skip = 0; 379*f324162eSOri Kam continue; 380*f324162eSOri Kam } 381*f324162eSOri Kam } else if (skip == 0) { 382*f324162eSOri Kam if (reg_val > val) { 383*f324162eSOri Kam DRV_LOG(ERR, 384*f324162eSOri Kam "got %08X expected <= %" PRIx64, 385*f324162eSOri Kam reg_val, val); 386*f324162eSOri Kam goto parse_error; 387*f324162eSOri Kam } 388*f324162eSOri Kam } 389*f324162eSOri Kam break; 390*f324162eSOri Kam case MLX5_RXP_ROF_ENTRY_CHECKSUM: 391*f324162eSOri Kam break; 392*f324162eSOri Kam case MLX5_RXP_ROF_ENTRY_CHECKSUM_EX_EM: 393*f324162eSOri Kam if (skip) 394*f324162eSOri Kam continue; 395*f324162eSOri Kam tmp_addr = rxp_get_reg_address(address); 396*f324162eSOri Kam if (tmp_addr == UINT32_MAX) 397*f324162eSOri Kam goto parse_error; 398*f324162eSOri Kam 399*f324162eSOri Kam ret = mlx5_devx_regex_register_read(priv->ctx, id, 400*f324162eSOri Kam tmp_addr, ®_val); 401*f324162eSOri Kam if (ret) { 402*f324162eSOri Kam DRV_LOG(ERR, "RXP CSR read failed!"); 403*f324162eSOri Kam return ret; 404*f324162eSOri Kam } 405*f324162eSOri Kam if (reg_val != val) { 406*f324162eSOri Kam DRV_LOG(ERR, "got %08X expected <= %" PRIx64, 407*f324162eSOri Kam reg_val, val); 408*f324162eSOri Kam goto parse_error; 409*f324162eSOri Kam } 410*f324162eSOri Kam break; 411*f324162eSOri Kam case MLX5_RXP_ROF_ENTRY_IM: 412*f324162eSOri Kam if (skip) 413*f324162eSOri Kam continue; 414*f324162eSOri Kam /* 415*f324162eSOri Kam * NOTE: All rules written to RXP must be carried out in 416*f324162eSOri Kam * triplets of: 2xData + 1xAddr. 417*f324162eSOri Kam * No optimisation is currently allowed in this 418*f324162eSOri Kam * sequence to perform less writes. 419*f324162eSOri Kam */ 420*f324162eSOri Kam temp = val; 421*f324162eSOri Kam ret |= mlx5_devx_regex_register_write 422*f324162eSOri Kam (priv->ctx, id, 423*f324162eSOri Kam MLX5_RXP_RTRU_CSR_DATA_0, temp); 424*f324162eSOri Kam temp = (uint32_t)(val >> 32); 425*f324162eSOri Kam ret |= mlx5_devx_regex_register_write 426*f324162eSOri Kam (priv->ctx, id, 427*f324162eSOri Kam MLX5_RXP_RTRU_CSR_DATA_0 + 428*f324162eSOri Kam MLX5_RXP_CSR_WIDTH, temp); 429*f324162eSOri Kam temp = address; 430*f324162eSOri Kam ret |= mlx5_devx_regex_register_write 431*f324162eSOri Kam (priv->ctx, id, MLX5_RXP_RTRU_CSR_ADDR, 432*f324162eSOri Kam temp); 433*f324162eSOri Kam if (ret) { 434*f324162eSOri Kam DRV_LOG(ERR, 435*f324162eSOri Kam "Failed to copy instructions to RXP."); 436*f324162eSOri Kam goto parse_error; 437*f324162eSOri Kam } 438*f324162eSOri Kam break; 439*f324162eSOri Kam case MLX5_RXP_ROF_ENTRY_EM: 440*f324162eSOri Kam if (skip) 441*f324162eSOri Kam continue; 442*f324162eSOri Kam for (i = 0; i < MLX5_RXP_NUM_LINES_PER_BLOCK; i++) { 443*f324162eSOri Kam ret = rxp_parse_line(line, &type, 444*f324162eSOri Kam &rules[i].addr, 445*f324162eSOri Kam &rules[i].value); 446*f324162eSOri Kam if (ret != 0) 447*f324162eSOri Kam goto parse_error; 448*f324162eSOri Kam if (i < (MLX5_RXP_NUM_LINES_PER_BLOCK - 1)) { 449*f324162eSOri Kam line = strtok(NULL, del); 450*f324162eSOri Kam if (!line) 451*f324162eSOri Kam goto parse_error; 452*f324162eSOri Kam } 453*f324162eSOri Kam } 454*f324162eSOri Kam if ((uint8_t *)((uint8_t *) 455*f324162eSOri Kam priv->db[id].ptr + 456*f324162eSOri Kam ((rules[7].addr << 457*f324162eSOri Kam MLX5_RXP_INST_OFFSET))) >= 458*f324162eSOri Kam ((uint8_t *)((uint8_t *) 459*f324162eSOri Kam priv->db[id].ptr + MLX5_MAX_DB_SIZE))) { 460*f324162eSOri Kam DRV_LOG(ERR, "DB exceeded memory!"); 461*f324162eSOri Kam goto parse_error; 462*f324162eSOri Kam } 463*f324162eSOri Kam /* 464*f324162eSOri Kam * Rule address Offset to align with RXP 465*f324162eSOri Kam * external instruction offset. 466*f324162eSOri Kam */ 467*f324162eSOri Kam rof_rule_addr = (rules[0].addr << MLX5_RXP_INST_OFFSET); 468*f324162eSOri Kam /* 32 byte instruction swap (sw work around)! */ 469*f324162eSOri Kam tmp_write_swap[0] = le64toh(rules[4].value); 470*f324162eSOri Kam tmp_write_swap[1] = le64toh(rules[5].value); 471*f324162eSOri Kam tmp_write_swap[2] = le64toh(rules[6].value); 472*f324162eSOri Kam tmp_write_swap[3] = le64toh(rules[7].value); 473*f324162eSOri Kam /* Write only 4 of the 8 instructions. */ 474*f324162eSOri Kam memcpy((uint8_t *)((uint8_t *) 475*f324162eSOri Kam priv->db[id].ptr + rof_rule_addr), 476*f324162eSOri Kam &tmp_write_swap, (sizeof(uint64_t) * 4)); 477*f324162eSOri Kam /* Write 1st 4 rules of block after last 4. */ 478*f324162eSOri Kam rof_rule_addr = (rules[4].addr << MLX5_RXP_INST_OFFSET); 479*f324162eSOri Kam tmp_write_swap[0] = le64toh(rules[0].value); 480*f324162eSOri Kam tmp_write_swap[1] = le64toh(rules[1].value); 481*f324162eSOri Kam tmp_write_swap[2] = le64toh(rules[2].value); 482*f324162eSOri Kam tmp_write_swap[3] = le64toh(rules[3].value); 483*f324162eSOri Kam memcpy((uint8_t *)((uint8_t *) 484*f324162eSOri Kam priv->db[id].ptr + rof_rule_addr), 485*f324162eSOri Kam &tmp_write_swap, (sizeof(uint64_t) * 4)); 486*f324162eSOri Kam break; 487*f324162eSOri Kam default: 488*f324162eSOri Kam break; 489*f324162eSOri Kam } 490*f324162eSOri Kam 491*f324162eSOri Kam } 492*f324162eSOri Kam ret = mlnx_set_database(priv, id, db_free); 493*f324162eSOri Kam if (ret < 0) { 494*f324162eSOri Kam DRV_LOG(ERR, "Failed to register db memory!"); 495*f324162eSOri Kam goto parse_error; 496*f324162eSOri Kam } 497b34d8163SFrancis Kelly rte_free(tmp); 498b34d8163SFrancis Kelly return 0; 499b34d8163SFrancis Kelly parse_error: 500b34d8163SFrancis Kelly rte_free(tmp); 501*f324162eSOri Kam return ret; 502b34d8163SFrancis Kelly } 503b34d8163SFrancis Kelly 504b34d8163SFrancis Kelly static int 505b34d8163SFrancis Kelly mlnx_set_database(struct mlx5_regex_priv *priv, uint8_t id, uint8_t db_to_use) 506b34d8163SFrancis Kelly { 507b34d8163SFrancis Kelly int ret; 508b34d8163SFrancis Kelly uint32_t umem_id; 509b34d8163SFrancis Kelly 510b34d8163SFrancis Kelly ret = mlx5_devx_regex_database_stop(priv->ctx, id); 511b34d8163SFrancis Kelly if (ret < 0) { 512b34d8163SFrancis Kelly DRV_LOG(ERR, "stop engine failed!"); 513b34d8163SFrancis Kelly return ret; 514b34d8163SFrancis Kelly } 515b34d8163SFrancis Kelly umem_id = mlx5_os_get_umem_id(priv->db[db_to_use].umem.umem); 516b34d8163SFrancis Kelly ret = mlx5_devx_regex_database_program(priv->ctx, id, umem_id, 0); 517b34d8163SFrancis Kelly if (ret < 0) { 518b34d8163SFrancis Kelly DRV_LOG(ERR, "program db failed!"); 519b34d8163SFrancis Kelly return ret; 520b34d8163SFrancis Kelly } 521b34d8163SFrancis Kelly return 0; 522b34d8163SFrancis Kelly } 523b34d8163SFrancis Kelly 524b34d8163SFrancis Kelly static int 525b34d8163SFrancis Kelly mlnx_resume_database(struct mlx5_regex_priv *priv, uint8_t id) 526b34d8163SFrancis Kelly { 527b34d8163SFrancis Kelly mlx5_devx_regex_database_resume(priv->ctx, id); 528b34d8163SFrancis Kelly return 0; 529b34d8163SFrancis Kelly } 530b34d8163SFrancis Kelly 531b34d8163SFrancis Kelly /* 532b34d8163SFrancis Kelly * Assign db memory for RXP programming. 533b34d8163SFrancis Kelly */ 534b34d8163SFrancis Kelly static int 535b34d8163SFrancis Kelly mlnx_update_database(struct mlx5_regex_priv *priv, uint8_t id) 536b34d8163SFrancis Kelly { 537b34d8163SFrancis Kelly unsigned int i; 538b34d8163SFrancis Kelly uint8_t db_free = MLX5_RXP_DB_NOT_ASSIGNED; 539b34d8163SFrancis Kelly uint8_t eng_assigned = MLX5_RXP_DB_NOT_ASSIGNED; 540b34d8163SFrancis Kelly 541b34d8163SFrancis Kelly /* Check which database rxp_eng is currently located if any? */ 542b34d8163SFrancis Kelly for (i = 0; i < (priv->nb_engines + MLX5_RXP_EM_COUNT); 543b34d8163SFrancis Kelly i++) { 544b34d8163SFrancis Kelly if (priv->db[i].db_assigned_to_eng_num == id) { 545b34d8163SFrancis Kelly eng_assigned = i; 546b34d8163SFrancis Kelly break; 547b34d8163SFrancis Kelly } 548b34d8163SFrancis Kelly } 549b34d8163SFrancis Kelly /* 550b34d8163SFrancis Kelly * If private mode then, we can keep the same db ptr as RXP will be 551b34d8163SFrancis Kelly * programming EM itself if necessary, however need to see if 552b34d8163SFrancis Kelly * programmed yet. 553b34d8163SFrancis Kelly */ 554b34d8163SFrancis Kelly if ((priv->prog_mode == MLX5_RXP_PRIVATE_PROG_MODE) && 555b34d8163SFrancis Kelly (eng_assigned != MLX5_RXP_DB_NOT_ASSIGNED)) 556b34d8163SFrancis Kelly return eng_assigned; 557b34d8163SFrancis Kelly /* Check for inactive db memory to use. */ 558b34d8163SFrancis Kelly for (i = 0; i < (priv->nb_engines + MLX5_RXP_EM_COUNT); 559b34d8163SFrancis Kelly i++) { 560b34d8163SFrancis Kelly if (priv->db[i].active == true) 561b34d8163SFrancis Kelly continue; /* Already in use, so skip db. */ 562b34d8163SFrancis Kelly /* Set this db to active now as free to use. */ 563b34d8163SFrancis Kelly priv->db[i].active = true; 564b34d8163SFrancis Kelly /* Now unassign last db index in use by RXP Eng. */ 565b34d8163SFrancis Kelly if (eng_assigned != MLX5_RXP_DB_NOT_ASSIGNED) { 566b34d8163SFrancis Kelly priv->db[eng_assigned].active = false; 567b34d8163SFrancis Kelly priv->db[eng_assigned].db_assigned_to_eng_num = 568b34d8163SFrancis Kelly MLX5_RXP_DB_NOT_ASSIGNED; 569b34d8163SFrancis Kelly 570b34d8163SFrancis Kelly /* Set all DB memory to 0's before setting up DB. */ 571b34d8163SFrancis Kelly memset(priv->db[i].ptr, 0x00, MLX5_MAX_DB_SIZE); 572b34d8163SFrancis Kelly } 573b34d8163SFrancis Kelly /* Now reassign new db index with RXP Engine. */ 574b34d8163SFrancis Kelly priv->db[i].db_assigned_to_eng_num = id; 575b34d8163SFrancis Kelly db_free = i; 576b34d8163SFrancis Kelly break; 577b34d8163SFrancis Kelly } 578b34d8163SFrancis Kelly if (db_free == MLX5_RXP_DB_NOT_ASSIGNED) 579b34d8163SFrancis Kelly return -1; 580b34d8163SFrancis Kelly return db_free; 581b34d8163SFrancis Kelly } 582b34d8163SFrancis Kelly 583b34d8163SFrancis Kelly /* 584b34d8163SFrancis Kelly * Program RXP instruction db to RXP engine/s. 585b34d8163SFrancis Kelly */ 586b34d8163SFrancis Kelly static int 587*f324162eSOri Kam program_rxp_rules(struct mlx5_regex_priv *priv, const char *buf, uint32_t len, 588*f324162eSOri Kam uint8_t id) 589b34d8163SFrancis Kelly { 590*f324162eSOri Kam int ret; 591*f324162eSOri Kam uint32_t val; 592b34d8163SFrancis Kelly 593*f324162eSOri Kam ret = rxp_init_eng(priv, id); 594*f324162eSOri Kam if (ret < 0) 595*f324162eSOri Kam return ret; 596*f324162eSOri Kam /* Confirm the RXP is initialised. */ 597*f324162eSOri Kam if (mlx5_devx_regex_register_read(priv->ctx, id, 598*f324162eSOri Kam MLX5_RXP_CSR_STATUS, &val)) { 599*f324162eSOri Kam DRV_LOG(ERR, "Failed to read from RXP!"); 600*f324162eSOri Kam return -ENODEV; 601b34d8163SFrancis Kelly } 602*f324162eSOri Kam if (!(val & MLX5_RXP_CSR_STATUS_INIT_DONE)) { 603*f324162eSOri Kam DRV_LOG(ERR, "RXP not initialised..."); 604*f324162eSOri Kam return -EBUSY; 605*f324162eSOri Kam } 606*f324162eSOri Kam ret = mlx5_devx_regex_register_read(priv->ctx, id, 607*f324162eSOri Kam MLX5_RXP_RTRU_CSR_CTRL, &val); 608*f324162eSOri Kam if (ret) { 609*f324162eSOri Kam DRV_LOG(ERR, "CSR read failed!"); 610*f324162eSOri Kam return -1; 611*f324162eSOri Kam } 612*f324162eSOri Kam val |= MLX5_RXP_RTRU_CSR_CTRL_GO; 613*f324162eSOri Kam ret = mlx5_devx_regex_register_write(priv->ctx, id, 614*f324162eSOri Kam MLX5_RXP_RTRU_CSR_CTRL, val); 615*f324162eSOri Kam if (ret) { 616*f324162eSOri Kam DRV_LOG(ERR, "Can't program rof file!"); 617*f324162eSOri Kam return -1; 618*f324162eSOri Kam } 619*f324162eSOri Kam ret = rxp_program_rof(priv, buf, len, id); 620*f324162eSOri Kam if (ret) { 621*f324162eSOri Kam DRV_LOG(ERR, "Can't program rof file!"); 622*f324162eSOri Kam return -1; 623*f324162eSOri Kam } 624*f324162eSOri Kam if (priv->is_bf2) { 625*f324162eSOri Kam ret = rxp_poll_csr_for_value 626*f324162eSOri Kam (priv->ctx, &val, MLX5_RXP_RTRU_CSR_STATUS, 627*f324162eSOri Kam MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE, 628*f324162eSOri Kam MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE, 629*f324162eSOri Kam MLX5_RXP_POLL_CSR_FOR_VALUE_TIMEOUT, id); 630b34d8163SFrancis Kelly if (ret < 0) { 631*f324162eSOri Kam DRV_LOG(ERR, "Rules update timeout: 0x%08X", val); 632b34d8163SFrancis Kelly return ret; 633b34d8163SFrancis Kelly } 634*f324162eSOri Kam DRV_LOG(DEBUG, "Rules update took %d cycles", ret); 635b34d8163SFrancis Kelly } 636*f324162eSOri Kam if (mlx5_devx_regex_register_read(priv->ctx, id, MLX5_RXP_RTRU_CSR_CTRL, 637*f324162eSOri Kam &val)) { 638*f324162eSOri Kam DRV_LOG(ERR, "CSR read failed!"); 639*f324162eSOri Kam return -1; 640*f324162eSOri Kam } 641*f324162eSOri Kam val &= ~(MLX5_RXP_RTRU_CSR_CTRL_GO); 642*f324162eSOri Kam if (mlx5_devx_regex_register_write(priv->ctx, id, 643*f324162eSOri Kam MLX5_RXP_RTRU_CSR_CTRL, val)) { 644*f324162eSOri Kam DRV_LOG(ERR, "CSR write failed!"); 645*f324162eSOri Kam return -1; 646*f324162eSOri Kam } 647*f324162eSOri Kam ret = mlx5_devx_regex_register_read(priv->ctx, id, MLX5_RXP_CSR_CTRL, 648*f324162eSOri Kam &val); 649*f324162eSOri Kam if (ret) 650b34d8163SFrancis Kelly return ret; 651*f324162eSOri Kam val &= ~MLX5_RXP_CSR_CTRL_INIT; 652*f324162eSOri Kam ret = mlx5_devx_regex_register_write(priv->ctx, id, MLX5_RXP_CSR_CTRL, 653*f324162eSOri Kam val); 654*f324162eSOri Kam if (ret) 655b34d8163SFrancis Kelly return ret; 656*f324162eSOri Kam rxp_init_rtru(priv, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2); 657*f324162eSOri Kam if (priv->is_bf2) { 658*f324162eSOri Kam ret = rxp_poll_csr_for_value(priv->ctx, &val, 659*f324162eSOri Kam MLX5_RXP_CSR_STATUS, 660*f324162eSOri Kam MLX5_RXP_CSR_STATUS_INIT_DONE, 661*f324162eSOri Kam MLX5_RXP_CSR_STATUS_INIT_DONE, 662*f324162eSOri Kam MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, 663*f324162eSOri Kam id); 664*f324162eSOri Kam if (ret) { 665*f324162eSOri Kam DRV_LOG(ERR, "Device init failed!"); 666b34d8163SFrancis Kelly return ret; 667b34d8163SFrancis Kelly } 668b34d8163SFrancis Kelly } 669b34d8163SFrancis Kelly ret = mlnx_resume_database(priv, id); 670b34d8163SFrancis Kelly if (ret < 0) { 671b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to resume engine!"); 672b34d8163SFrancis Kelly return ret; 673b34d8163SFrancis Kelly } 674*f324162eSOri Kam 675*f324162eSOri Kam return ret; 676*f324162eSOri Kam 677b34d8163SFrancis Kelly } 678b34d8163SFrancis Kelly 679b34d8163SFrancis Kelly static int 680b34d8163SFrancis Kelly rxp_init_eng(struct mlx5_regex_priv *priv, uint8_t id) 681e3dbbf71SOri Kam { 682e3dbbf71SOri Kam uint32_t ctrl; 683e3dbbf71SOri Kam uint32_t reg; 684e3dbbf71SOri Kam struct ibv_context *ctx = priv->ctx; 685e3dbbf71SOri Kam int ret; 686e3dbbf71SOri Kam 687e3dbbf71SOri Kam ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl); 688e3dbbf71SOri Kam if (ret) 689e3dbbf71SOri Kam return ret; 690e3dbbf71SOri Kam if (ctrl & MLX5_RXP_CSR_CTRL_INIT) { 691e3dbbf71SOri Kam ctrl &= ~MLX5_RXP_CSR_CTRL_INIT; 692e3dbbf71SOri Kam ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, 693e3dbbf71SOri Kam ctrl); 694e3dbbf71SOri Kam if (ret) 695e3dbbf71SOri Kam return ret; 696e3dbbf71SOri Kam } 697e3dbbf71SOri Kam ctrl |= MLX5_RXP_CSR_CTRL_INIT; 698e3dbbf71SOri Kam ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl); 699e3dbbf71SOri Kam if (ret) 700e3dbbf71SOri Kam return ret; 701e3dbbf71SOri Kam ctrl &= ~MLX5_RXP_CSR_CTRL_INIT; 702e3dbbf71SOri Kam ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, ctrl); 703acb93dbcSMichael Baum if (ret) 704acb93dbcSMichael Baum return ret; 705e3dbbf71SOri Kam rte_delay_us(20000); 706e3dbbf71SOri Kam ret = rxp_poll_csr_for_value(ctx, &ctrl, MLX5_RXP_CSR_STATUS, 707e3dbbf71SOri Kam MLX5_RXP_CSR_STATUS_INIT_DONE, 708e3dbbf71SOri Kam MLX5_RXP_CSR_STATUS_INIT_DONE, 709e3dbbf71SOri Kam MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT, id); 710e3dbbf71SOri Kam if (ret) 711e3dbbf71SOri Kam return ret; 712e3dbbf71SOri Kam ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CTRL, &ctrl); 713e3dbbf71SOri Kam if (ret) 714e3dbbf71SOri Kam return ret; 715e3dbbf71SOri Kam ctrl &= ~MLX5_RXP_CSR_CTRL_INIT; 716e3dbbf71SOri Kam ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_CTRL, 717e3dbbf71SOri Kam ctrl); 718e3dbbf71SOri Kam if (ret) 719e3dbbf71SOri Kam return ret; 720*f324162eSOri Kam ret = rxp_init_rtru(priv, id, 721*f324162eSOri Kam MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2); 722e3dbbf71SOri Kam if (ret) 723e3dbbf71SOri Kam return ret; 724e3dbbf71SOri Kam ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CAPABILITY_5, 725e3dbbf71SOri Kam ®); 726e3dbbf71SOri Kam if (ret) 727e3dbbf71SOri Kam return ret; 728e3dbbf71SOri Kam DRV_LOG(DEBUG, "max matches: %d, DDOS threshold: %d", reg >> 16, 729e3dbbf71SOri Kam reg & 0xffff); 730b34d8163SFrancis Kelly if ((reg >> 16) >= priv->nb_max_matches) 731b34d8163SFrancis Kelly ret = mlx5_devx_regex_register_write(ctx, id, 732b34d8163SFrancis Kelly MLX5_RXP_CSR_MAX_MATCH, 733e3dbbf71SOri Kam priv->nb_max_matches); 734b34d8163SFrancis Kelly else 735b34d8163SFrancis Kelly ret = mlx5_devx_regex_register_write(ctx, id, 736b34d8163SFrancis Kelly MLX5_RXP_CSR_MAX_MATCH, 737b34d8163SFrancis Kelly (reg >> 16)); 738b34d8163SFrancis Kelly ret |= mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_CSR_MAX_PREFIX, 739b34d8163SFrancis Kelly (reg & 0xFFFF)); 740e3dbbf71SOri Kam ret |= mlx5_devx_regex_register_write(ctx, id, 741e3dbbf71SOri Kam MLX5_RXP_CSR_MAX_LATENCY, 0); 742e3dbbf71SOri Kam ret |= mlx5_devx_regex_register_write(ctx, id, 743e3dbbf71SOri Kam MLX5_RXP_CSR_MAX_PRI_THREAD, 0); 744e3dbbf71SOri Kam return ret; 745e3dbbf71SOri Kam } 746e3dbbf71SOri Kam 747b34d8163SFrancis Kelly static int 748b34d8163SFrancis Kelly rxp_db_setup(struct mlx5_regex_priv *priv) 749b34d8163SFrancis Kelly { 750b34d8163SFrancis Kelly int ret; 751b34d8163SFrancis Kelly uint8_t i; 752b34d8163SFrancis Kelly 753b34d8163SFrancis Kelly /* Setup database memories for both RXP engines + reprogram memory. */ 754b34d8163SFrancis Kelly for (i = 0; i < (priv->nb_engines + MLX5_RXP_EM_COUNT); i++) { 7557e8b42e8SOri Kam priv->db[i].ptr = rte_malloc("", MLX5_MAX_DB_SIZE, 1 << 21); 756b34d8163SFrancis Kelly if (!priv->db[i].ptr) { 757b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to alloc db memory!"); 758b34d8163SFrancis Kelly ret = ENODEV; 759b34d8163SFrancis Kelly goto tidyup_error; 760b34d8163SFrancis Kelly } 761b34d8163SFrancis Kelly /* Register the memory. */ 762b34d8163SFrancis Kelly priv->db[i].umem.umem = mlx5_glue->devx_umem_reg(priv->ctx, 763b34d8163SFrancis Kelly priv->db[i].ptr, 764b34d8163SFrancis Kelly MLX5_MAX_DB_SIZE, 7); 765b34d8163SFrancis Kelly if (!priv->db[i].umem.umem) { 766b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to register memory!"); 767b34d8163SFrancis Kelly ret = ENODEV; 768b34d8163SFrancis Kelly goto tidyup_error; 769b34d8163SFrancis Kelly } 770b34d8163SFrancis Kelly /* Ensure set all DB memory to 0's before setting up DB. */ 771b34d8163SFrancis Kelly memset(priv->db[i].ptr, 0x00, MLX5_MAX_DB_SIZE); 772b34d8163SFrancis Kelly /* No data currently in database. */ 773b34d8163SFrancis Kelly priv->db[i].len = 0; 774b34d8163SFrancis Kelly priv->db[i].active = false; 775b34d8163SFrancis Kelly priv->db[i].db_assigned_to_eng_num = MLX5_RXP_DB_NOT_ASSIGNED; 776b34d8163SFrancis Kelly } 777b34d8163SFrancis Kelly return 0; 778b34d8163SFrancis Kelly tidyup_error: 779b34d8163SFrancis Kelly for (i = 0; i < (priv->nb_engines + MLX5_RXP_EM_COUNT); i++) { 780b34d8163SFrancis Kelly if (priv->db[i].ptr) 781b34d8163SFrancis Kelly rte_free(priv->db[i].ptr); 782b34d8163SFrancis Kelly if (priv->db[i].umem.umem) 783b34d8163SFrancis Kelly mlx5_glue->devx_umem_dereg(priv->db[i].umem.umem); 784b34d8163SFrancis Kelly } 785b34d8163SFrancis Kelly return -ret; 786b34d8163SFrancis Kelly } 787b34d8163SFrancis Kelly 788b34d8163SFrancis Kelly int 789b34d8163SFrancis Kelly mlx5_regex_rules_db_import(struct rte_regexdev *dev, 790b34d8163SFrancis Kelly const char *rule_db, uint32_t rule_db_len) 791b34d8163SFrancis Kelly { 792b34d8163SFrancis Kelly struct mlx5_regex_priv *priv = dev->data->dev_private; 793b34d8163SFrancis Kelly struct mlx5_rxp_ctl_rules_pgm *rules = NULL; 794a07079b1SMichael Baum uint32_t id; 795b34d8163SFrancis Kelly int ret; 796*f324162eSOri Kam uint32_t ver; 797b34d8163SFrancis Kelly 798b34d8163SFrancis Kelly if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED) { 799b34d8163SFrancis Kelly DRV_LOG(ERR, "RXP programming mode not set!"); 800b34d8163SFrancis Kelly return -1; 801b34d8163SFrancis Kelly } 802b34d8163SFrancis Kelly if (rule_db == NULL) { 803b34d8163SFrancis Kelly DRV_LOG(ERR, "Database empty!"); 804b34d8163SFrancis Kelly return -ENODEV; 805b34d8163SFrancis Kelly } 806b34d8163SFrancis Kelly if (rule_db_len == 0) 807b34d8163SFrancis Kelly return -EINVAL; 808*f324162eSOri Kam if (mlx5_devx_regex_register_read(priv->ctx, 0, 809*f324162eSOri Kam MLX5_RXP_CSR_BASE_ADDRESS, &ver)) { 810*f324162eSOri Kam DRV_LOG(ERR, "Failed to read Main CSRs Engine 0!"); 811*f324162eSOri Kam return -1; 812b34d8163SFrancis Kelly } 813b34d8163SFrancis Kelly /* Need to ensure RXP not busy before stop! */ 814b34d8163SFrancis Kelly for (id = 0; id < priv->nb_engines; id++) { 815b34d8163SFrancis Kelly ret = rxp_stop_engine(priv->ctx, id); 816b34d8163SFrancis Kelly if (ret) { 817b34d8163SFrancis Kelly DRV_LOG(ERR, "Can't stop engine."); 818b34d8163SFrancis Kelly ret = -ENODEV; 819b34d8163SFrancis Kelly goto tidyup_error; 820b34d8163SFrancis Kelly } 821*f324162eSOri Kam ret = program_rxp_rules(priv, rule_db, rule_db_len, id); 822b34d8163SFrancis Kelly if (ret < 0) { 823b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to program rxp rules."); 824b34d8163SFrancis Kelly ret = -ENODEV; 825b34d8163SFrancis Kelly goto tidyup_error; 826b34d8163SFrancis Kelly } 827b34d8163SFrancis Kelly ret = rxp_start_engine(priv->ctx, id); 828b34d8163SFrancis Kelly if (ret) { 829b34d8163SFrancis Kelly DRV_LOG(ERR, "Can't start engine."); 830b34d8163SFrancis Kelly ret = -ENODEV; 831b34d8163SFrancis Kelly goto tidyup_error; 832b34d8163SFrancis Kelly } 833b34d8163SFrancis Kelly } 834b34d8163SFrancis Kelly rte_free(rules); 835b34d8163SFrancis Kelly return 0; 836b34d8163SFrancis Kelly tidyup_error: 837b34d8163SFrancis Kelly rte_free(rules); 838b34d8163SFrancis Kelly return ret; 839b34d8163SFrancis Kelly } 840b34d8163SFrancis Kelly 841e3dbbf71SOri Kam int 842e3dbbf71SOri Kam mlx5_regex_configure(struct rte_regexdev *dev, 843e3dbbf71SOri Kam const struct rte_regexdev_config *cfg) 844e3dbbf71SOri Kam { 845e3dbbf71SOri Kam struct mlx5_regex_priv *priv = dev->data->dev_private; 846e3dbbf71SOri Kam int ret; 847e3dbbf71SOri Kam 848b34d8163SFrancis Kelly if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED) 849b34d8163SFrancis Kelly return -1; 850e3dbbf71SOri Kam priv->nb_queues = cfg->nb_queue_pairs; 851b34d8163SFrancis Kelly dev->data->dev_conf.nb_queue_pairs = priv->nb_queues; 852e3dbbf71SOri Kam priv->qps = rte_zmalloc(NULL, sizeof(struct mlx5_regex_qp) * 853e3dbbf71SOri Kam priv->nb_queues, 0); 854e3dbbf71SOri Kam if (!priv->nb_queues) { 855e3dbbf71SOri Kam DRV_LOG(ERR, "can't allocate qps memory"); 856e3dbbf71SOri Kam rte_errno = ENOMEM; 857e3dbbf71SOri Kam return -rte_errno; 858e3dbbf71SOri Kam } 859e3dbbf71SOri Kam priv->nb_max_matches = cfg->nb_max_matches; 860b34d8163SFrancis Kelly /* Setup rxp db memories. */ 861b34d8163SFrancis Kelly if (rxp_db_setup(priv)) { 862b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to setup RXP db memory"); 863b34d8163SFrancis Kelly rte_errno = ENOMEM; 864e3dbbf71SOri Kam return -rte_errno; 865e3dbbf71SOri Kam } 866b34d8163SFrancis Kelly if (cfg->rule_db != NULL) { 867b34d8163SFrancis Kelly ret = mlx5_regex_rules_db_import(dev, cfg->rule_db, 868b34d8163SFrancis Kelly cfg->rule_db_len); 869b34d8163SFrancis Kelly if (ret < 0) { 870b34d8163SFrancis Kelly DRV_LOG(ERR, "Failed to program rxp rules."); 871e3dbbf71SOri Kam rte_errno = ENODEV; 872e3dbbf71SOri Kam goto configure_error; 873e3dbbf71SOri Kam } 874b34d8163SFrancis Kelly } else 875b34d8163SFrancis Kelly DRV_LOG(DEBUG, "Regex config without rules programming!"); 876e3dbbf71SOri Kam return 0; 877e3dbbf71SOri Kam configure_error: 878e3dbbf71SOri Kam if (priv->qps) 879e3dbbf71SOri Kam rte_free(priv->qps); 880e3dbbf71SOri Kam return -rte_errno; 881e3dbbf71SOri Kam } 882