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