DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/4] regex/mlx5: pmd improvements
@ 2020-12-17  8:51 Ori Kam
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 1/4] regex/mlx5: fix memory rule alignment Ori Kam
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Ori Kam @ 2020-12-17  8:51 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev

This series adds a few fixes and improvements to the Nvidia RegEx PMD.

Ori Kam (4):
  regex/mlx5: fix memory rule alignment
  regex/mlx5: add support for combined rule file
  regex/mlx5: fix support for group id
  regex/mlx5: add support for priority match

 drivers/regex/mlx5/mlx5_regex.c          |   9 +
 drivers/regex/mlx5/mlx5_regex.h          |   1 +
 drivers/regex/mlx5/mlx5_regex_fastpath.c |  23 +-
 drivers/regex/mlx5/mlx5_rxp.c            | 827 ++++++++++-------------
 drivers/regex/mlx5/mlx5_rxp_csrs.h       |   3 +
 5 files changed, 372 insertions(+), 491 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH 1/4] regex/mlx5: fix memory rule alignment
  2020-12-17  8:51 [dpdk-dev] [PATCH 0/4] regex/mlx5: pmd improvements Ori Kam
@ 2020-12-17  8:51 ` Ori Kam
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 2/4] regex/mlx5: add support for combined rule file Ori Kam
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2020-12-17  8:51 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev, stable

Due to Kernel requirement the memory allocated must be aligned to 2M.

Fixes: b34d816363b5 ("regex/mlx5: support rules import")

Cc: stable@dpdk.org

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 drivers/regex/mlx5/mlx5_rxp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/regex/mlx5/mlx5_rxp.c b/drivers/regex/mlx5/mlx5_rxp.c
index fcbc766441..bd721f0b11 100644
--- a/drivers/regex/mlx5/mlx5_rxp.c
+++ b/drivers/regex/mlx5/mlx5_rxp.c
@@ -892,7 +892,7 @@ rxp_db_setup(struct mlx5_regex_priv *priv)
 
 	/* Setup database memories for both RXP engines + reprogram memory. */
 	for (i = 0; i < (priv->nb_engines + MLX5_RXP_EM_COUNT); i++) {
-		priv->db[i].ptr = rte_malloc("", MLX5_MAX_DB_SIZE, 0);
+		priv->db[i].ptr = rte_malloc("", MLX5_MAX_DB_SIZE, 1 << 21);
 		if (!priv->db[i].ptr) {
 			DRV_LOG(ERR, "Failed to alloc db memory!");
 			ret = ENODEV;
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH 2/4] regex/mlx5: add support for combined rule file
  2020-12-17  8:51 [dpdk-dev] [PATCH 0/4] regex/mlx5: pmd improvements Ori Kam
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 1/4] regex/mlx5: fix memory rule alignment Ori Kam
@ 2020-12-17  8:51 ` Ori Kam
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 3/4] regex/mlx5: fix support for group id Ori Kam
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2020-12-17  8:51 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev

The rof file holds programming instructions for
a given HW version.
In order to support future generation of HW it
was decided that the rof file will hold number
of rule configurations, and the driver will use
the one that matches the HW version.

In current code we force sync after each write block.
This has impact on performance.

The solution is to move the sync to the end of the
entire programming sequence.

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 drivers/regex/mlx5/mlx5_regex.c    |   9 +
 drivers/regex/mlx5/mlx5_regex.h    |   1 +
 drivers/regex/mlx5/mlx5_rxp.c      | 825 ++++++++++++-----------------
 drivers/regex/mlx5/mlx5_rxp_csrs.h |   3 +
 4 files changed, 352 insertions(+), 486 deletions(-)

diff --git a/drivers/regex/mlx5/mlx5_regex.c b/drivers/regex/mlx5/mlx5_regex.c
index c91c444dda..25eaec5802 100644
--- a/drivers/regex/mlx5/mlx5_regex.c
+++ b/drivers/regex/mlx5/mlx5_regex.c
@@ -119,6 +119,7 @@ mlx5_regex_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	struct mlx5_hca_attr attr;
 	char name[RTE_REGEXDEV_NAME_MAX_LEN];
 	int ret;
+	uint32_t val;
 
 	ibv = mlx5_regex_get_ib_device_match(&pci_dev->addr);
 	if (!ibv) {
@@ -161,6 +162,14 @@ mlx5_regex_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	priv->ctx = ctx;
 	priv->nb_engines = 2; /* attr.regexp_num_of_engines */
+	ret = mlx5_devx_regex_register_read(priv->ctx, 0,
+					    MLX5_RXP_CSR_IDENTIFIER, &val);
+	if (ret) {
+		DRV_LOG(ERR, "CSR read failed!");
+		return -1;
+	}
+	if (val == MLX5_RXP_BF2_IDENTIFIER)
+		priv->is_bf2 = 1;
 	/* Default RXP programming mode to Shared. */
 	priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE;
 	mlx5_regex_get_name(name, pci_dev);
diff --git a/drivers/regex/mlx5/mlx5_regex.h b/drivers/regex/mlx5/mlx5_regex.h
index 2c4877c37d..60f29a84d2 100644
--- a/drivers/regex/mlx5/mlx5_regex.h
+++ b/drivers/regex/mlx5/mlx5_regex.h
@@ -80,6 +80,7 @@ struct mlx5_regex_priv {
 	struct ibv_pd *pd;
 	struct mlx5_dbr_page_list dbrpgs; /* Door-bell pages. */
 	struct mlx5_mr_share_cache mr_scache; /* Global shared MR cache. */
+	uint8_t is_bf2; /* The device is BF2 device. */
 };
 
 /* mlx5_regex.c */
diff --git a/drivers/regex/mlx5/mlx5_rxp.c b/drivers/regex/mlx5/mlx5_rxp.c
index bd721f0b11..7bd3b669bc 100644
--- a/drivers/regex/mlx5/mlx5_rxp.c
+++ b/drivers/regex/mlx5/mlx5_rxp.c
@@ -8,6 +8,7 @@
 #include <rte_regexdev.h>
 #include <rte_regexdev_core.h>
 #include <rte_regexdev_driver.h>
+#include <sys/mman.h>
 
 #include <mlx5_glue.h>
 #include <mlx5_devx_cmds.h>
@@ -24,6 +25,8 @@
 #define MLX5_REGEX_MAX_RULES_PER_GROUP UINT32_MAX
 #define MLX5_REGEX_MAX_GROUPS MLX5_RXP_MAX_SUBSETS
 
+#define MLX5_REGEX_RXP_ROF2_LINE_LEN 34
+
 /* Private Declarations */
 static int
 rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value,
@@ -36,30 +39,15 @@ mlnx_resume_database(struct mlx5_regex_priv *priv, uint8_t id);
 static int
 mlnx_update_database(struct mlx5_regex_priv *priv, uint8_t id);
 static int
-program_rxp_rules(struct mlx5_regex_priv *priv,
-		  struct mlx5_rxp_ctl_rules_pgm *rules, uint8_t id);
+program_rxp_rules(struct mlx5_regex_priv *priv, const char *buf, uint32_t len,
+		  uint8_t id);
 static int
 rxp_init_eng(struct mlx5_regex_priv *priv, uint8_t id);
 static int
-write_private_rules(struct mlx5_regex_priv *priv,
-		    struct mlx5_rxp_ctl_rules_pgm *rules,
-		    uint8_t id);
-static int
-write_shared_rules(struct mlx5_regex_priv *priv,
-		   struct mlx5_rxp_ctl_rules_pgm *rules, uint32_t count,
-		   uint8_t db_to_program);
-static int
 rxp_db_setup(struct mlx5_regex_priv *priv);
 static void
 rxp_dump_csrs(struct ibv_context *ctx, uint8_t id);
 static int
-rxp_write_rules_via_cp(struct ibv_context *ctx,
-		       struct mlx5_rxp_rof_entry *rules,
-		       int count, uint8_t id);
-static int
-rxp_flush_rules(struct ibv_context *ctx, struct mlx5_rxp_rof_entry *rules,
-		int count, uint8_t id);
-static int
 rxp_start_engine(struct ibv_context *ctx, uint8_t id);
 static int
 rxp_stop_engine(struct ibv_context *ctx, uint8_t id);
@@ -123,110 +111,6 @@ mlx5_regex_info_get(struct rte_regexdev *dev __rte_unused,
 	return 0;
 }
 
-/**
- * Actual writing of RXP instructions to RXP via CSRs.
- */
-static int
-rxp_write_rules_via_cp(struct ibv_context *ctx,
-		       struct mlx5_rxp_rof_entry *rules,
-		       int count, uint8_t id)
-{
-	int i, ret = 0;
-	uint32_t tmp;
-
-	for (i = 0; i < count; i++) {
-		tmp = (uint32_t)rules[i].value;
-		ret |= mlx5_devx_regex_register_write(ctx, id,
-						      MLX5_RXP_RTRU_CSR_DATA_0,
-						      tmp);
-		tmp = (uint32_t)(rules[i].value >> 32);
-		ret |= mlx5_devx_regex_register_write(ctx, id,
-						      MLX5_RXP_RTRU_CSR_DATA_0 +
-						      MLX5_RXP_CSR_WIDTH, tmp);
-		tmp = rules[i].addr;
-		ret |= mlx5_devx_regex_register_write(ctx, id,
-						      MLX5_RXP_RTRU_CSR_ADDR,
-						      tmp);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to copy instructions to RXP.");
-			return -1;
-		}
-	}
-	DRV_LOG(DEBUG, "Written %d instructions", count);
-	return 0;
-}
-
-static int
-rxp_flush_rules(struct ibv_context *ctx, struct mlx5_rxp_rof_entry *rules,
-		int count, uint8_t id)
-{
-	uint32_t val, fifo_depth;
-	int ret;
-
-	ret = rxp_write_rules_via_cp(ctx, rules, count, id);
-	if (ret < 0) {
-		DRV_LOG(ERR, "Failed to write rules via CSRs.");
-		return -1;
-	}
-	ret = mlx5_devx_regex_register_read(ctx, id,
-					    MLX5_RXP_RTRU_CSR_CAPABILITY,
-					    &fifo_depth);
-	if (ret) {
-		DRV_LOG(ERR, "CSR read failed!");
-		return -1;
-	}
-	ret = rxp_poll_csr_for_value(ctx, &val, MLX5_RXP_RTRU_CSR_FIFO_STAT,
-				     count, ~0,
-				     MLX5_RXP_POLL_CSR_FOR_VALUE_TIMEOUT, id);
-	if (ret < 0) {
-		if (ret == -EBUSY)
-			DRV_LOG(ERR, "Rules not rx by RXP: credit: %d, depth:"
-				" %d", val, fifo_depth);
-		else
-			DRV_LOG(ERR, "CSR poll failed, can't read value!");
-		return ret;
-	}
-	DRV_LOG(DEBUG, "RTRU FIFO depth: 0x%x", fifo_depth);
-	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
-					    &val);
-	if (ret) {
-		DRV_LOG(ERR, "CSR read failed!");
-		return -1;
-	}
-	val |= MLX5_RXP_RTRU_CSR_CTRL_GO;
-	ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
-					     val);
-	if (ret) {
-		DRV_LOG(ERR, "CSR write failed!");
-		return -1;
-	}
-	ret = rxp_poll_csr_for_value(ctx, &val, MLX5_RXP_RTRU_CSR_STATUS,
-				     MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE,
-				     MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE,
-				     MLX5_RXP_POLL_CSR_FOR_VALUE_TIMEOUT, id);
-	if (ret < 0) {
-		if (ret == -EBUSY)
-			DRV_LOG(ERR, "Rules update timeout: 0x%08X", val);
-		else
-			DRV_LOG(ERR, "CSR poll failed, can't read value!");
-		return ret;
-	}
-	if (mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
-					  &val)) {
-		DRV_LOG(ERR, "CSR read failed!");
-		return -1;
-	}
-	val &= ~(MLX5_RXP_RTRU_CSR_CTRL_GO);
-	if (mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
-					   val)) {
-		DRV_LOG(ERR, "CSR write failed!");
-		return -1;
-	}
-
-	DRV_LOG(DEBUG, "RXP Flush rules finished.");
-	return 0;
-}
-
 static int
 rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value,
 		       uint32_t address, uint32_t expected_value,
@@ -278,13 +162,14 @@ rxp_stop_engine(struct ibv_context *ctx, uint8_t id)
 }
 
 static int
-rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits)
+rxp_init_rtru(struct mlx5_regex_priv *priv, uint8_t id, uint32_t init_bits)
 {
 	uint32_t ctrl_value;
 	uint32_t poll_value;
 	uint32_t expected_value;
 	uint32_t expected_mask;
-	int ret;
+	struct ibv_context *ctx = priv->ctx;
+	int ret = 0;
 
 	/* Read the rtru ctrl CSR. */
 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
@@ -317,13 +202,15 @@ rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits)
 	/* Check that the following bits are set in the RTRU_CSR. */
 	if (init_bits == MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2) {
 		/* Must be incremental mode */
-		expected_value = MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE |
-			MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
+		expected_value = MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE;
 	} else {
 		expected_value = MLX5_RXP_RTRU_CSR_STATUS_IM_INIT_DONE |
-			MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE |
-			MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
+			MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE;
 	}
+	if (priv->is_bf2)
+		expected_value |= MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
+
+
 	expected_mask = expected_value;
 	ret = rxp_poll_csr_for_value(ctx, &poll_value,
 				     MLX5_RXP_RTRU_CSR_STATUS,
@@ -340,69 +227,274 @@ rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits)
 }
 
 static int
-rxp_parse_rof(const char *buf, uint32_t len,
-	      struct mlx5_rxp_ctl_rules_pgm **rules)
+rxp_parse_line(char *line, uint32_t *type, uint32_t *address, uint64_t *value)
+{
+	char *cur_pos;
+
+	if (*line == '\0' || *line == '#')
+		return  1;
+	*type = strtoul(line, &cur_pos, 10);
+	if (*cur_pos != ',' && *cur_pos != '\0')
+		return -1;
+	*address = strtoul(cur_pos+1, &cur_pos, 16);
+	if (*cur_pos != ',' && *cur_pos != '\0')
+		return -1;
+	*value = strtoul(cur_pos+1, &cur_pos, 16);
+	if (*cur_pos != ',' && *cur_pos != '\0')
+		return -1;
+	return 0;
+}
+
+static uint32_t
+rxp_get_reg_address(uint32_t address)
+{
+	uint32_t block;
+	uint32_t reg;
+
+	block = (address >> 16) & 0xFFFF;
+	if (block == 0)
+		reg = MLX5_RXP_CSR_BASE_ADDRESS;
+	else if (block == 1)
+		reg = MLX5_RXP_RTRU_CSR_BASE_ADDRESS;
+	else {
+		DRV_LOG(ERR, "Invalid ROF register 0x%08X!", address);
+			return UINT32_MAX;
+	}
+	reg += (address & 0xFFFF) * MLX5_RXP_CSR_WIDTH;
+	return reg;
+}
+
+static int
+rxp_program_rof(struct mlx5_regex_priv *priv, const char *buf, uint32_t len,
+		uint8_t id)
 {
 	static const char del[] = "\n\r";
 	char *line;
 	char *tmp;
-	char *cur_pos;
-	uint32_t lines = 0;
-	uint32_t entries;
-	struct mlx5_rxp_rof_entry *curentry;
+	uint32_t type = 0;
+	uint32_t address;
+	uint64_t val;
+	uint32_t reg_val;
+	int ret;
+	int skip = -1;
+	int last = 0;
+	uint32_t temp;
+	uint32_t tmp_addr;
+	uint32_t rof_rule_addr;
+	uint64_t tmp_write_swap[4];
+	struct mlx5_rxp_rof_entry rules[8];
+	int i;
+	int db_free;
+	int j;
 
 	tmp = rte_malloc("", len, 0);
 	if (!tmp)
 		return -ENOMEM;
 	memcpy(tmp, buf, len);
-	line = strtok(tmp, del);
-	while (line) {
-		if (line[0] != '#' && line[0] != '\0')
-			lines++;
-		line = strtok(NULL, del);
-	}
-	*rules = rte_malloc("", lines * sizeof(*curentry) + sizeof(**rules), 0);
-	if (!(*rules)) {
+	db_free = mlnx_update_database(priv, id);
+	if (db_free < 0) {
+		DRV_LOG(ERR, "Failed to setup db memory!");
 		rte_free(tmp);
-		return -ENOMEM;
+		return db_free;
 	}
-	memset(*rules, 0, lines * sizeof(curentry) + sizeof(**rules));
-	curentry = (*rules)->rules;
-	(*rules)->hdr.cmd = MLX5_RXP_CTL_RULES_PGM;
-	entries = 0;
-	memcpy(tmp, buf, len);
-	line = strtok(tmp, del);
-	while (line) {
-		if (line[0] == '#' || line[0] == '\0') {
-			line = strtok(NULL, del);
+	for (line = strtok(tmp, del), j = 0; line; line = strtok(NULL, del),
+	     j++, last = type) {
+		ret = rxp_parse_line(line, &type, &address, &val);
+		if (ret != 0) {
+			if (ret < 0)
+				goto parse_error;
 			continue;
 		}
-		curentry->type = strtoul(line, &cur_pos, 10);
-		if (cur_pos == line || cur_pos[0] != ',')
-			goto parse_error;
-		cur_pos++;
-		curentry->addr = strtoul(cur_pos, &cur_pos, 16);
-		if (cur_pos[0] != ',')
-			goto parse_error;
-		cur_pos++;
-		curentry->value = strtoull(cur_pos, &cur_pos, 16);
-		if (cur_pos[0] != '\0' && cur_pos[0] != '\n')
-			goto parse_error;
-		curentry++;
-		entries++;
-		if (entries > lines)
-			goto parse_error;
-		line = strtok(NULL, del);
-	}
-	(*rules)->count = entries;
-	(*rules)->hdr.len = entries * sizeof(*curentry) + sizeof(**rules);
+		switch (type) {
+		case MLX5_RXP_ROF_ENTRY_EQ:
+			if (skip == 0 && address == 0)
+				skip = 1;
+			tmp_addr = rxp_get_reg_address(address);
+			if (tmp_addr == UINT32_MAX)
+				goto parse_error;
+			ret = mlx5_devx_regex_register_read(priv->ctx, id,
+							    tmp_addr, &reg_val);
+			if (ret)
+				goto parse_error;
+			if (skip == -1 && address == 0) {
+				if (val == reg_val) {
+					skip = 0;
+					continue;
+				}
+			} else if (skip == 0) {
+				if (val != reg_val) {
+					DRV_LOG(ERR,
+						"got %08X expected == %" PRIx64,
+						reg_val, val);
+					goto parse_error;
+				}
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_GTE:
+			if (skip == 0 && address == 0)
+				skip = 1;
+			tmp_addr = rxp_get_reg_address(address);
+			if (tmp_addr == UINT32_MAX)
+				goto parse_error;
+			ret = mlx5_devx_regex_register_read(priv->ctx, id,
+							    tmp_addr, &reg_val);
+			if (ret)
+				goto parse_error;
+			if (skip == -1 && address == 0) {
+				if (reg_val >= val) {
+					skip = 0;
+					continue;
+				}
+			} else if (skip == 0) {
+				if (reg_val < val) {
+					DRV_LOG(ERR,
+						"got %08X expected >= %" PRIx64,
+						reg_val, val);
+					goto parse_error;
+				}
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_LTE:
+			tmp_addr = rxp_get_reg_address(address);
+			if (tmp_addr == UINT32_MAX)
+				goto parse_error;
+			ret = mlx5_devx_regex_register_read(priv->ctx, id,
+							    tmp_addr, &reg_val);
+			if (ret)
+				goto parse_error;
+			if (skip == 0 && address == 0 &&
+			    last != MLX5_RXP_ROF_ENTRY_GTE) {
+				skip = 1;
+			} else if (skip == 0 && address == 0 &&
+				   last == MLX5_RXP_ROF_ENTRY_GTE) {
+				if (reg_val > val)
+					skip = -1;
+				continue;
+			}
+			if (skip == -1 && address == 0) {
+				if (reg_val <= val) {
+					skip = 0;
+					continue;
+				}
+			} else if (skip == 0) {
+				if (reg_val > val) {
+					DRV_LOG(ERR,
+						"got %08X expected <= %" PRIx64,
+						reg_val, val);
+					goto parse_error;
+				}
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_CHECKSUM:
+			break;
+		case MLX5_RXP_ROF_ENTRY_CHECKSUM_EX_EM:
+			if (skip)
+				continue;
+			tmp_addr = rxp_get_reg_address(address);
+			if (tmp_addr == UINT32_MAX)
+				goto parse_error;
+
+			ret = mlx5_devx_regex_register_read(priv->ctx, id,
+							    tmp_addr, &reg_val);
+			if (ret) {
+				DRV_LOG(ERR, "RXP CSR read failed!");
+				return ret;
+			}
+			if (reg_val != val) {
+				DRV_LOG(ERR, "got %08X expected <= %" PRIx64,
+					reg_val, val);
+				goto parse_error;
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_IM:
+			if (skip)
+				continue;
+			/*
+			 * NOTE: All rules written to RXP must be carried out in
+			 * triplets of: 2xData + 1xAddr.
+			 * No optimisation is currently allowed in this
+			 * sequence to perform less writes.
+			 */
+			temp = val;
+			ret |= mlx5_devx_regex_register_write
+					(priv->ctx, id,
+					 MLX5_RXP_RTRU_CSR_DATA_0, temp);
+			temp = (uint32_t)(val >> 32);
+			ret |= mlx5_devx_regex_register_write
+					(priv->ctx, id,
+					 MLX5_RXP_RTRU_CSR_DATA_0 +
+					 MLX5_RXP_CSR_WIDTH, temp);
+			temp = address;
+			ret |= mlx5_devx_regex_register_write
+					(priv->ctx, id, MLX5_RXP_RTRU_CSR_ADDR,
+					 temp);
+			if (ret) {
+				DRV_LOG(ERR,
+					"Failed to copy instructions to RXP.");
+				goto parse_error;
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_EM:
+			if (skip)
+				continue;
+			for (i = 0; i < 7; i++) {
+				ret = rxp_parse_line(line, &type,
+						     &rules[i].addr,
+						     &rules[i].value);
+				if (ret != 0)
+					goto parse_error;
+				line = strtok(NULL, del);
+				if (!line)
+					goto parse_error;
+			}
+			if ((uint8_t *)((uint8_t *)
+					priv->db[id].ptr +
+					((rules[7].addr <<
+					 MLX5_RXP_INST_OFFSET))) >=
+					((uint8_t *)((uint8_t *)
+					priv->db[id].ptr + MLX5_MAX_DB_SIZE))) {
+				DRV_LOG(ERR, "DB exceeded memory!");
+				goto parse_error;
+			}
+			/*
+			 * Rule address Offset to align with RXP
+			 * external instruction offset.
+			 */
+			rof_rule_addr = (rules[0].addr << MLX5_RXP_INST_OFFSET);
+			/* 32 byte instruction swap (sw work around)! */
+			tmp_write_swap[0] = le64toh(rules[4].value);
+			tmp_write_swap[1] = le64toh(rules[5].value);
+			tmp_write_swap[2] = le64toh(rules[6].value);
+			tmp_write_swap[3] = le64toh(rules[7].value);
+			/* Write only 4 of the 8 instructions. */
+			memcpy((uint8_t *)((uint8_t *)
+				priv->db[id].ptr + rof_rule_addr),
+				&tmp_write_swap, (sizeof(uint64_t) * 4));
+			/* Write 1st 4 rules of block after last 4. */
+			rof_rule_addr = (rules[4].addr << MLX5_RXP_INST_OFFSET);
+			tmp_write_swap[0] = le64toh(rules[0].value);
+			tmp_write_swap[1] = le64toh(rules[1].value);
+			tmp_write_swap[2] = le64toh(rules[2].value);
+			tmp_write_swap[3] = le64toh(rules[3].value);
+			memcpy((uint8_t *)((uint8_t *)
+				priv->db[id].ptr + rof_rule_addr),
+				&tmp_write_swap, (sizeof(uint64_t) * 4));
+			break;
+		default:
+			break;
+		}
+
+	}
+	ret = mlnx_set_database(priv, id, db_free);
+	if (ret < 0) {
+		DRV_LOG(ERR, "Failed to register db memory!");
+		goto parse_error;
+	}
 	rte_free(tmp);
 	return 0;
 parse_error:
 	rte_free(tmp);
-	if (*rules)
-		rte_free(*rules);
-	return -EINVAL;
+	return ret;
 }
 
 static int
@@ -488,43 +580,81 @@ mlnx_update_database(struct mlx5_regex_priv *priv, uint8_t id)
  * Program RXP instruction db to RXP engine/s.
  */
 static int
-program_rxp_rules(struct mlx5_regex_priv *priv,
-		  struct mlx5_rxp_ctl_rules_pgm *rules, uint8_t id)
+program_rxp_rules(struct mlx5_regex_priv *priv, const char *buf, uint32_t len,
+		  uint8_t id)
 {
-	int ret, db_free;
-	uint32_t rule_cnt;
+	int ret;
+	int db_free;
+	uint32_t val;
 
-	rule_cnt = rules->count;
 	db_free = mlnx_update_database(priv, id);
 	if (db_free < 0) {
 		DRV_LOG(ERR, "Failed to setup db memory!");
 		return db_free;
 	}
-	if (priv->prog_mode == MLX5_RXP_PRIVATE_PROG_MODE) {
-		/* Register early to ensure RXP writes to EM use valid addr. */
-		ret = mlnx_set_database(priv, id, db_free);
-		if (ret < 0) {
-			DRV_LOG(ERR, "Failed to register db memory!");
-			return ret;
-		}
-	}
-	ret = write_private_rules(priv, rules, id);
-	if (ret < 0) {
-		DRV_LOG(ERR, "Failed to write rules!");
+	ret = rxp_init_eng(priv, id);
+	if (ret < 0)
 		return ret;
+	/* Confirm the RXP is initialised. */
+	if (mlx5_devx_regex_register_read(priv->ctx, id,
+					    MLX5_RXP_CSR_STATUS, &val)) {
+		DRV_LOG(ERR, "Failed to read from RXP!");
+		return -ENODEV;
+	}
+	if (!(val & MLX5_RXP_CSR_STATUS_INIT_DONE)) {
+		DRV_LOG(ERR, "RXP not initialised...");
+		return -EBUSY;
+	}
+	ret = mlx5_devx_regex_register_read(priv->ctx, id,
+					    MLX5_RXP_RTRU_CSR_CTRL, &val);
+	if (ret) {
+		DRV_LOG(ERR, "CSR read failed!");
+		return -1;
 	}
-	if (priv->prog_mode == MLX5_RXP_SHARED_PROG_MODE) {
-		/* Write external rules directly to EM. */
-		rules->count = rule_cnt;
-	       /* Now write external instructions to EM. */
-		ret = write_shared_rules(priv, rules, rules->hdr.len, db_free);
+	val |= MLX5_RXP_RTRU_CSR_CTRL_GO;
+	ret = mlx5_devx_regex_register_write(priv->ctx, id,
+					     MLX5_RXP_RTRU_CSR_CTRL, val);
+	if (ret) {
+		DRV_LOG(ERR, "Can't program rof file!");
+		return -1;
+	}
+	ret = rxp_program_rof(priv, buf, len, id);
+	if (ret) {
+		DRV_LOG(ERR, "Can't program rof file!");
+		return -1;
+	}
+	if (priv->is_bf2) {
+		ret = rxp_poll_csr_for_value
+			(priv->ctx, &val, MLX5_RXP_RTRU_CSR_STATUS,
+			 MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE,
+			 MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE,
+			 MLX5_RXP_POLL_CSR_FOR_VALUE_TIMEOUT, id);
 		if (ret < 0) {
-			DRV_LOG(ERR, "Failed to write EM rules!");
+			DRV_LOG(ERR, "Rules update timeout: 0x%08X", val);
 			return ret;
 		}
-		ret = mlnx_set_database(priv, id, db_free);
-		if (ret < 0) {
-			DRV_LOG(ERR, "Failed to register db memory!");
+		DRV_LOG(DEBUG, "Rules update took %d cycles", ret);
+	}
+	if (mlx5_devx_regex_register_read(priv->ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
+					  &val)) {
+		DRV_LOG(ERR, "CSR read failed!");
+		return -1;
+	}
+	val &= ~(MLX5_RXP_RTRU_CSR_CTRL_GO);
+	if (mlx5_devx_regex_register_write(priv->ctx, id,
+					   MLX5_RXP_RTRU_CSR_CTRL, val)) {
+		DRV_LOG(ERR, "CSR write write failed!");
+		return -1;
+	}
+	if (priv->is_bf2) {
+		ret = rxp_poll_csr_for_value(priv->ctx, &val,
+					     MLX5_RXP_CSR_STATUS,
+					     MLX5_RXP_CSR_STATUS_INIT_DONE,
+					     MLX5_RXP_CSR_STATUS_INIT_DONE,
+					     MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT,
+					     id);
+		if (ret) {
+			DRV_LOG(ERR, "Device init failed!");
 			return ret;
 		}
 	}
@@ -533,9 +663,9 @@ program_rxp_rules(struct mlx5_regex_priv *priv,
 		DRV_LOG(ERR, "Failed to resume engine!");
 		return ret;
 	}
-	DRV_LOG(DEBUG, "Programmed RXP Engine %d\n", id);
-	rules->count = rule_cnt;
-	return 0;
+
+	return ret;
+
 }
 
 static int
@@ -579,7 +709,8 @@ rxp_init_eng(struct mlx5_regex_priv *priv, uint8_t id)
 					     ctrl);
 	if (ret)
 		return ret;
-	ret = rxp_init_rtru(ctx, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2);
+	ret = rxp_init_rtru(priv, id,
+			    MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2);
 	if (ret)
 		return ret;
 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CAPABILITY_5,
@@ -605,285 +736,6 @@ rxp_init_eng(struct mlx5_regex_priv *priv, uint8_t id)
 	return ret;
 }
 
-static int
-write_private_rules(struct mlx5_regex_priv *priv,
-		    struct mlx5_rxp_ctl_rules_pgm *rules,
-		    uint8_t id)
-{
-	unsigned int pending;
-	uint32_t block, reg, val, rule_cnt, rule_offset, rtru_max_num_entries;
-	int ret = 1;
-
-	if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED)
-		return -EINVAL;
-	if (rules->hdr.len == 0 || rules->hdr.cmd < MLX5_RXP_CTL_RULES_PGM ||
-				   rules->hdr.cmd > MLX5_RXP_CTL_RULES_PGM_INCR)
-		return -EINVAL;
-	/* For a non-incremental rules program, re-init the RXP. */
-	if (rules->hdr.cmd == MLX5_RXP_CTL_RULES_PGM) {
-		ret = rxp_init_eng(priv, id);
-		if (ret < 0)
-			return ret;
-	} else if (rules->hdr.cmd == MLX5_RXP_CTL_RULES_PGM_INCR) {
-		/* Flush RXP L1 and L2 cache by using MODE_L1_L2. */
-		ret = rxp_init_rtru(priv->ctx, id,
-				    MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2);
-		if (ret < 0)
-			return ret;
-	}
-	if (rules->count == 0)
-		return -EINVAL;
-	/* Confirm the RXP is initialised. */
-	if (mlx5_devx_regex_register_read(priv->ctx, id,
-					    MLX5_RXP_CSR_STATUS, &val)) {
-		DRV_LOG(ERR, "Failed to read from RXP!");
-		return -ENODEV;
-	}
-	if (!(val & MLX5_RXP_CSR_STATUS_INIT_DONE)) {
-		DRV_LOG(ERR, "RXP not initialised...");
-		return -EBUSY;
-	}
-	/* Get the RTRU maximum number of entries allowed. */
-	if (mlx5_devx_regex_register_read(priv->ctx, id,
-			MLX5_RXP_RTRU_CSR_CAPABILITY, &rtru_max_num_entries)) {
-		DRV_LOG(ERR, "Failed to read RTRU capability!");
-		return -ENODEV;
-	}
-	rtru_max_num_entries = (rtru_max_num_entries & 0x00FF);
-	rule_cnt = 0;
-	pending = 0;
-	while (rules->count > 0) {
-		if ((rules->rules[rule_cnt].type == MLX5_RXP_ROF_ENTRY_INST) ||
-		    (rules->rules[rule_cnt].type == MLX5_RXP_ROF_ENTRY_IM) ||
-		    (rules->rules[rule_cnt].type == MLX5_RXP_ROF_ENTRY_EM)) {
-			if ((rules->rules[rule_cnt].type ==
-			     MLX5_RXP_ROF_ENTRY_EM) &&
-			    (priv->prog_mode == MLX5_RXP_SHARED_PROG_MODE)) {
-				/* Skip EM rules programming. */
-				if (pending > 0) {
-					/* Flush any rules that are pending. */
-					rule_offset = (rule_cnt - pending);
-					ret = rxp_flush_rules(priv->ctx,
-						&rules->rules[rule_offset],
-						pending, id);
-					if (ret < 0) {
-						DRV_LOG(ERR, "Flushing rules.");
-						return -ENODEV;
-					}
-					pending = 0;
-				}
-				rule_cnt++;
-			} else {
-				pending++;
-				rule_cnt++;
-				/*
-				 * If parsing the last rule, or if reached the
-				 * maximum number of rules for this batch, then
-				 * flush the rules batch to the RXP.
-				 */
-				if ((rules->count == 1) ||
-				    (pending == rtru_max_num_entries)) {
-					rule_offset = (rule_cnt - pending);
-					ret = rxp_flush_rules(priv->ctx,
-						&rules->rules[rule_offset],
-						pending, id);
-					if (ret < 0) {
-						DRV_LOG(ERR, "Flushing rules.");
-						return -ENODEV;
-					}
-					pending = 0;
-				}
-			}
-		} else if ((rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_EQ) ||
-			 (rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_GTE) ||
-			 (rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_LTE) ||
-			 (rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_CHECKSUM) ||
-			 (rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_CHECKSUM_EX_EM)) {
-			if (pending) {
-				/* Flush rules before checking reg values. */
-				rule_offset = (rule_cnt - pending);
-				ret = rxp_flush_rules(priv->ctx,
-					&rules->rules[rule_offset],
-					pending, id);
-				if (ret < 0) {
-					DRV_LOG(ERR, "Failed to flush rules.");
-					return -ENODEV;
-				}
-			}
-			block = (rules->rules[rule_cnt].addr >> 16) & 0xFFFF;
-			if (block == 0)
-				reg = MLX5_RXP_CSR_BASE_ADDRESS;
-			else if (block == 1)
-				reg = MLX5_RXP_RTRU_CSR_BASE_ADDRESS;
-			else {
-				DRV_LOG(ERR, "Invalid ROF register 0x%08X!",
-					rules->rules[rule_cnt].addr);
-				return -EINVAL;
-			}
-			reg += (rules->rules[rule_cnt].addr & 0xFFFF) *
-				MLX5_RXP_CSR_WIDTH;
-			ret = mlx5_devx_regex_register_read(priv->ctx, id,
-							    reg, &val);
-			if (ret) {
-				DRV_LOG(ERR, "RXP CSR read failed!");
-				return ret;
-			}
-			if ((priv->prog_mode == MLX5_RXP_SHARED_PROG_MODE) &&
-			    ((rules->rules[rule_cnt].type ==
-			    MLX5_RXP_ROF_ENTRY_CHECKSUM_EX_EM) &&
-			    (val != rules->rules[rule_cnt].value))) {
-				DRV_LOG(ERR, "Unexpected value for register:");
-				DRV_LOG(ERR, "reg %x" PRIu32 " got %x" PRIu32,
-					rules->rules[rule_cnt].addr, val);
-				DRV_LOG(ERR, "expected %" PRIx64 ".",
-					rules->rules[rule_cnt].value);
-					return -EINVAL;
-			} else if ((priv->prog_mode ==
-				 MLX5_RXP_PRIVATE_PROG_MODE) &&
-				 (rules->rules[rule_cnt].type ==
-				 MLX5_RXP_ROF_ENTRY_CHECKSUM) &&
-				 (val != rules->rules[rule_cnt].value)) {
-				DRV_LOG(ERR, "Unexpected value for register:");
-				DRV_LOG(ERR, "reg %x" PRIu32 " got %x" PRIu32,
-					rules->rules[rule_cnt].addr, val);
-				DRV_LOG(ERR, "expected %" PRIx64 ".",
-					rules->rules[rule_cnt].value);
-				return -EINVAL;
-			} else if ((rules->rules[rule_cnt].type ==
-					MLX5_RXP_ROF_ENTRY_EQ) &&
-				  (val != rules->rules[rule_cnt].value)) {
-				DRV_LOG(ERR, "Unexpected value for register:");
-				DRV_LOG(ERR, "reg %x" PRIu32 " got %x" PRIu32,
-					rules->rules[rule_cnt].addr, val);
-				DRV_LOG(ERR, "expected %" PRIx64 ".",
-					rules->rules[rule_cnt].value);
-					return -EINVAL;
-			} else if ((rules->rules[rule_cnt].type ==
-					MLX5_RXP_ROF_ENTRY_GTE) &&
-				 (val < rules->rules[rule_cnt].value)) {
-				DRV_LOG(ERR, "Unexpected value reg 0x%08X,",
-					rules->rules[rule_cnt].addr);
-				DRV_LOG(ERR, "got %X, expected >= %" PRIx64 ".",
-					val, rules->rules[rule_cnt].value);
-				return -EINVAL;
-			} else if ((rules->rules[rule_cnt].type ==
-					MLX5_RXP_ROF_ENTRY_LTE) &&
-				 (val > rules->rules[rule_cnt].value)) {
-				DRV_LOG(ERR, "Unexpected value reg 0x%08X,",
-					rules->rules[rule_cnt].addr);
-				DRV_LOG(ERR, "got %08X expected <= %" PRIx64,
-					val, rules->rules[rule_cnt].value);
-				return -EINVAL;
-			}
-			rule_cnt++;
-			pending = 0;
-		} else {
-			DRV_LOG(ERR, "Error: Invalid rule type %d!",
-				rules->rules[rule_cnt].type);
-			return -EINVAL;
-		}
-		rules->count--;
-	}
-	return ret;
-}
-
-/*
- * Shared memory programming mode, here all external db instructions are written
- * to EM via the host.
- */
-static int
-write_shared_rules(struct mlx5_regex_priv *priv,
-		   struct mlx5_rxp_ctl_rules_pgm *rules, uint32_t count,
-		   uint8_t db_to_program)
-{
-	uint32_t rule_cnt, rof_rule_addr;
-	uint64_t tmp_write_swap[4];
-
-	if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED)
-		return -EINVAL;
-	if ((rules->count == 0) || (count == 0))
-		return -EINVAL;
-	rule_cnt = 0;
-	/*
-	 * Note the following section of code carries out a 32byte swap of
-	 * instruction to coincide with HW 32byte swap. This may need removed
-	 * in new variants of this programming function!
-	 */
-	while (rule_cnt < rules->count) {
-		if ((rules->rules[rule_cnt].type == MLX5_RXP_ROF_ENTRY_EM) &&
-		    (priv->prog_mode == MLX5_RXP_SHARED_PROG_MODE)) {
-			/*
-			 * Note there are always blocks of 8 instructions for
-			 * 7's written sequentially. However there is no
-			 * guarantee that all blocks are sequential!
-			 */
-			if (count >= (rule_cnt + MLX5_RXP_INST_BLOCK_SIZE)) {
-				/*
-				 * Ensure memory write not exceeding boundary
-				 * Check essential to ensure 0x10000 offset
-				 * accounted for!
-				 */
-				if ((uint8_t *)((uint8_t *)
-				    priv->db[db_to_program].ptr +
-				    ((rules->rules[rule_cnt + 7].addr <<
-				    MLX5_RXP_INST_OFFSET))) >=
-				    ((uint8_t *)((uint8_t *)
-				    priv->db[db_to_program].ptr +
-				    MLX5_MAX_DB_SIZE))) {
-					DRV_LOG(ERR, "DB exceeded memory!");
-					return -ENODEV;
-				}
-				/*
-				 * Rule address Offset to align with RXP
-				 * external instruction offset.
-				 */
-				rof_rule_addr = (rules->rules[rule_cnt].addr <<
-						 MLX5_RXP_INST_OFFSET);
-				/* 32 byte instruction swap (sw work around)! */
-				tmp_write_swap[0] = le64toh(
-					rules->rules[(rule_cnt + 4)].value);
-				tmp_write_swap[1] = le64toh(
-					rules->rules[(rule_cnt + 5)].value);
-				tmp_write_swap[2] = le64toh(
-					rules->rules[(rule_cnt + 6)].value);
-				tmp_write_swap[3] = le64toh(
-					rules->rules[(rule_cnt + 7)].value);
-				/* Write only 4 of the 8 instructions. */
-				memcpy((uint8_t *)((uint8_t *)
-				       priv->db[db_to_program].ptr +
-				       rof_rule_addr), &tmp_write_swap,
-				       (sizeof(uint64_t) * 4));
-				/* Write 1st 4 rules of block after last 4. */
-				rof_rule_addr = (rules->rules[
-						 (rule_cnt + 4)].addr <<
-						 MLX5_RXP_INST_OFFSET);
-				tmp_write_swap[0] = le64toh(
-					rules->rules[(rule_cnt + 0)].value);
-				tmp_write_swap[1] = le64toh(
-					rules->rules[(rule_cnt + 1)].value);
-				tmp_write_swap[2] = le64toh(
-					rules->rules[(rule_cnt + 2)].value);
-				tmp_write_swap[3] = le64toh(
-					rules->rules[(rule_cnt + 3)].value);
-				memcpy((uint8_t *)((uint8_t *)
-				       priv->db[db_to_program].ptr +
-				       rof_rule_addr), &tmp_write_swap,
-				       (sizeof(uint64_t) * 4));
-			} else
-				return -1;
-			/* Fast forward as already handled block of 8. */
-			rule_cnt += MLX5_RXP_INST_BLOCK_SIZE;
-		} else
-			rule_cnt++; /* Must be something other than EM rule. */
-	}
-	return 0;
-}
-
 static int
 rxp_db_setup(struct mlx5_regex_priv *priv)
 {
@@ -933,6 +785,7 @@ mlx5_regex_rules_db_import(struct rte_regexdev *dev,
 	struct mlx5_rxp_ctl_rules_pgm *rules = NULL;
 	uint32_t id;
 	int ret;
+	uint32_t ver;
 
 	if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED) {
 		DRV_LOG(ERR, "RXP programming mode not set!");
@@ -944,10 +797,10 @@ mlx5_regex_rules_db_import(struct rte_regexdev *dev,
 	}
 	if (rule_db_len == 0)
 		return -EINVAL;
-	ret = rxp_parse_rof(rule_db, rule_db_len, &rules);
-	if (ret) {
-		DRV_LOG(ERR, "Can't parse ROF file.");
-		return ret;
+	if (mlx5_devx_regex_register_read(priv->ctx, 0,
+					  MLX5_RXP_CSR_BASE_ADDRESS, &ver)) {
+		DRV_LOG(ERR, "Failed to read Main CSRs Engine 0!");
+		return -1;
 	}
 	/* Need to ensure RXP not busy before stop! */
 	for (id = 0; id < priv->nb_engines; id++) {
@@ -957,7 +810,7 @@ mlx5_regex_rules_db_import(struct rte_regexdev *dev,
 			ret = -ENODEV;
 			goto tidyup_error;
 		}
-		ret = program_rxp_rules(priv, rules, id);
+		ret = program_rxp_rules(priv, rule_db, rule_db_len, id);
 		if (ret < 0) {
 			DRV_LOG(ERR, "Failed to program rxp rules.");
 			ret = -ENODEV;
diff --git a/drivers/regex/mlx5/mlx5_rxp_csrs.h b/drivers/regex/mlx5/mlx5_rxp_csrs.h
index d92b3fff53..f3ffdfdef2 100644
--- a/drivers/regex/mlx5/mlx5_rxp_csrs.h
+++ b/drivers/regex/mlx5/mlx5_rxp_csrs.h
@@ -5,6 +5,9 @@
 #ifndef _MLX5_RXP_CSRS_H_
 #define _MLX5_RXP_CSRS_H_
 
+/* BF types */
+#define MLX5_RXP_BF2_IDENTIFIER 0x07055254ul
+
 /*
  * Common to all RXP implementations
  */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH 3/4] regex/mlx5: fix support for group id
  2020-12-17  8:51 [dpdk-dev] [PATCH 0/4] regex/mlx5: pmd improvements Ori Kam
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 1/4] regex/mlx5: fix memory rule alignment Ori Kam
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 2/4] regex/mlx5: add support for combined rule file Ori Kam
@ 2020-12-17  8:51 ` Ori Kam
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 4/4] regex/mlx5: add support for priority match Ori Kam
  2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
  4 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2020-12-17  8:51 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev, stable

In order to know which groups in the RegEx engine
should be used there is a need to check the req_flags.

This commit adds the missing check.

Cc: stable@dpdk.org

Fixes: 4d4e245ad637 ("regex/mlx5: support enqueue")

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 drivers/regex/mlx5/mlx5_regex_fastpath.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/regex/mlx5/mlx5_regex_fastpath.c b/drivers/regex/mlx5/mlx5_regex_fastpath.c
index 5857617282..8d134ac98e 100644
--- a/drivers/regex/mlx5/mlx5_regex_fastpath.c
+++ b/drivers/regex/mlx5/mlx5_regex_fastpath.c
@@ -105,7 +105,21 @@ prep_one(struct mlx5_regex_priv *priv, struct mlx5_regex_qp *qp,
 {
 	size_t wqe_offset = (sq->pi & (sq_size_get(sq) - 1)) * MLX5_SEND_WQE_BB;
 	uint32_t lkey;
-
+	uint16_t group0 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID0_VALID_F ?
+				op->group_id0 : 0;
+	uint16_t group1 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID1_VALID_F ?
+				op->group_id1 : 0;
+	uint16_t group2 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID2_VALID_F ?
+				op->group_id2 : 0;
+	uint16_t group3 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID3_VALID_F ?
+				op->group_id3 : 0;
+
+	/* For backward compatibility. */
+	if (!(op->req_flags & (RTE_REGEX_OPS_REQ_GROUP_ID0_VALID_F |
+			       RTE_REGEX_OPS_REQ_GROUP_ID1_VALID_F |
+			       RTE_REGEX_OPS_REQ_GROUP_ID2_VALID_F |
+			       RTE_REGEX_OPS_REQ_GROUP_ID3_VALID_F)))
+		group0 = op->group_id0;
 	lkey = mlx5_mr_addr2mr_bh(priv->pd, 0,
 				  &priv->mr_scache, &qp->mr_ctrl,
 				  rte_pktmbuf_mtod(op->mbuf, uintptr_t),
@@ -116,9 +130,8 @@ prep_one(struct mlx5_regex_priv *priv, struct mlx5_regex_qp *qp,
 	set_wqe_ctrl_seg((struct mlx5_wqe_ctrl_seg *)wqe, sq->pi,
 			 MLX5_OPCODE_MMO, MLX5_OPC_MOD_MMO_REGEX, sq->obj->id,
 			 0, ds, 0, 0);
-	set_regex_ctrl_seg(wqe + 12, 0, op->group_id0, op->group_id1,
-			   op->group_id2,
-			   op->group_id3, 0);
+	set_regex_ctrl_seg(wqe + 12, 0, group0, group1, group2, group3,
+			   0);
 	struct mlx5_wqe_data_seg *input_seg =
 		(struct mlx5_wqe_data_seg *)(wqe +
 					     MLX5_REGEX_WQE_GATHER_OFFSET);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH 4/4] regex/mlx5: add support for priority match
  2020-12-17  8:51 [dpdk-dev] [PATCH 0/4] regex/mlx5: pmd improvements Ori Kam
                   ` (2 preceding siblings ...)
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 3/4] regex/mlx5: fix support for group id Ori Kam
@ 2020-12-17  8:51 ` Ori Kam
  2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
  4 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2020-12-17  8:51 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev

The high priority match request flags means that the
RegEx engine should stop on the first match.

This commit add this flag check to the RegEx engine.

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 drivers/regex/mlx5/mlx5_regex_fastpath.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/regex/mlx5/mlx5_regex_fastpath.c b/drivers/regex/mlx5/mlx5_regex_fastpath.c
index 8d134ac98e..ee72f89c99 100644
--- a/drivers/regex/mlx5/mlx5_regex_fastpath.c
+++ b/drivers/regex/mlx5/mlx5_regex_fastpath.c
@@ -113,6 +113,8 @@ prep_one(struct mlx5_regex_priv *priv, struct mlx5_regex_qp *qp,
 				op->group_id2 : 0;
 	uint16_t group3 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID3_VALID_F ?
 				op->group_id3 : 0;
+	uint8_t control = op->req_flags &
+				RTE_REGEX_OPS_REQ_MATCH_HIGH_PRIORITY_F ? 1 : 0;
 
 	/* For backward compatibility. */
 	if (!(op->req_flags & (RTE_REGEX_OPS_REQ_GROUP_ID0_VALID_F |
@@ -131,7 +133,7 @@ prep_one(struct mlx5_regex_priv *priv, struct mlx5_regex_qp *qp,
 			 MLX5_OPCODE_MMO, MLX5_OPC_MOD_MMO_REGEX, sq->obj->id,
 			 0, ds, 0, 0);
 	set_regex_ctrl_seg(wqe + 12, 0, group0, group1, group2, group3,
-			   0);
+			   control);
 	struct mlx5_wqe_data_seg *input_seg =
 		(struct mlx5_wqe_data_seg *)(wqe +
 					     MLX5_REGEX_WQE_GATHER_OFFSET);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH v2 0/5]  regex/mlx5: pmd improvements
  2020-12-17  8:51 [dpdk-dev] [PATCH 0/4] regex/mlx5: pmd improvements Ori Kam
                   ` (3 preceding siblings ...)
  2020-12-17  8:51 ` [dpdk-dev] [PATCH 4/4] regex/mlx5: add support for priority match Ori Kam
@ 2021-01-07 16:57 ` Ori Kam
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 1/5] regex/mlx5: fix memory rule alignment Ori Kam
                     ` (5 more replies)
  4 siblings, 6 replies; 12+ messages in thread
From: Ori Kam @ 2021-01-07 16:57 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev

This series adds a few fixes and improvements to the Nvidia RegEx PMD.

V2:
* Fix small issue in combined rule patch.
* Add new patch for number of queues.

Ori Kam (5):
  regex/mlx5: fix memory rule alignment
  regex/mlx5: add support for combined rule file
  regex/mlx5: fix support for group id
  regex/mlx5: add support for priority match
  regex/mlx5: fix num of supported queues

 drivers/regex/mlx5/mlx5_regex.c          |   9 +
 drivers/regex/mlx5/mlx5_regex.h          |   1 +
 drivers/regex/mlx5/mlx5_regex_fastpath.c |  23 +-
 drivers/regex/mlx5/mlx5_rxp.c            | 846 ++++++++++-------------
 drivers/regex/mlx5/mlx5_rxp_csrs.h       |   3 +
 5 files changed, 385 insertions(+), 497 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH v2 1/5] regex/mlx5: fix memory rule alignment
  2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
@ 2021-01-07 16:57   ` Ori Kam
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 2/5] regex/mlx5: add support for combined rule file Ori Kam
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2021-01-07 16:57 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev, stable

Due to Kernel requirement the memory allocated must be aligned to 2M.

Fixes: b34d816363b5 ("regex/mlx5: support rules import")

Cc: stable@dpdk.org

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 drivers/regex/mlx5/mlx5_rxp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/regex/mlx5/mlx5_rxp.c b/drivers/regex/mlx5/mlx5_rxp.c
index fcbc766441..bd721f0b11 100644
--- a/drivers/regex/mlx5/mlx5_rxp.c
+++ b/drivers/regex/mlx5/mlx5_rxp.c
@@ -892,7 +892,7 @@ rxp_db_setup(struct mlx5_regex_priv *priv)
 
 	/* Setup database memories for both RXP engines + reprogram memory. */
 	for (i = 0; i < (priv->nb_engines + MLX5_RXP_EM_COUNT); i++) {
-		priv->db[i].ptr = rte_malloc("", MLX5_MAX_DB_SIZE, 0);
+		priv->db[i].ptr = rte_malloc("", MLX5_MAX_DB_SIZE, 1 << 21);
 		if (!priv->db[i].ptr) {
 			DRV_LOG(ERR, "Failed to alloc db memory!");
 			ret = ENODEV;
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH v2 2/5] regex/mlx5: add support for combined rule file
  2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 1/5] regex/mlx5: fix memory rule alignment Ori Kam
@ 2021-01-07 16:57   ` Ori Kam
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 3/5] regex/mlx5: fix support for group id Ori Kam
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2021-01-07 16:57 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev

The rof file holds programming instructions for
a given HW version.
In order to support future generation of HW it
was decided that the rof file will hold number
of rule configurations, and the driver will use
the one that matches the HW version.

In current code we force sync after each write block.
This has impact on performance.

The solution is to move the sync to the end of the
entire programming sequence.

Signed-off-by: Ori Kam <orika@nvidia.com>
---
V2:
* fix issue with external rules.

---
 drivers/regex/mlx5/mlx5_regex.c    |   9 +
 drivers/regex/mlx5/mlx5_regex.h    |   1 +
 drivers/regex/mlx5/mlx5_rxp.c      | 841 ++++++++++++-----------------
 drivers/regex/mlx5/mlx5_rxp_csrs.h |   3 +
 4 files changed, 364 insertions(+), 490 deletions(-)

diff --git a/drivers/regex/mlx5/mlx5_regex.c b/drivers/regex/mlx5/mlx5_regex.c
index c91c444dda..25eaec5802 100644
--- a/drivers/regex/mlx5/mlx5_regex.c
+++ b/drivers/regex/mlx5/mlx5_regex.c
@@ -119,6 +119,7 @@ mlx5_regex_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	struct mlx5_hca_attr attr;
 	char name[RTE_REGEXDEV_NAME_MAX_LEN];
 	int ret;
+	uint32_t val;
 
 	ibv = mlx5_regex_get_ib_device_match(&pci_dev->addr);
 	if (!ibv) {
@@ -161,6 +162,14 @@ mlx5_regex_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	}
 	priv->ctx = ctx;
 	priv->nb_engines = 2; /* attr.regexp_num_of_engines */
+	ret = mlx5_devx_regex_register_read(priv->ctx, 0,
+					    MLX5_RXP_CSR_IDENTIFIER, &val);
+	if (ret) {
+		DRV_LOG(ERR, "CSR read failed!");
+		return -1;
+	}
+	if (val == MLX5_RXP_BF2_IDENTIFIER)
+		priv->is_bf2 = 1;
 	/* Default RXP programming mode to Shared. */
 	priv->prog_mode = MLX5_RXP_SHARED_PROG_MODE;
 	mlx5_regex_get_name(name, pci_dev);
diff --git a/drivers/regex/mlx5/mlx5_regex.h b/drivers/regex/mlx5/mlx5_regex.h
index 2c4877c37d..60f29a84d2 100644
--- a/drivers/regex/mlx5/mlx5_regex.h
+++ b/drivers/regex/mlx5/mlx5_regex.h
@@ -80,6 +80,7 @@ struct mlx5_regex_priv {
 	struct ibv_pd *pd;
 	struct mlx5_dbr_page_list dbrpgs; /* Door-bell pages. */
 	struct mlx5_mr_share_cache mr_scache; /* Global shared MR cache. */
+	uint8_t is_bf2; /* The device is BF2 device. */
 };
 
 /* mlx5_regex.c */
diff --git a/drivers/regex/mlx5/mlx5_rxp.c b/drivers/regex/mlx5/mlx5_rxp.c
index bd721f0b11..66cbc1f481 100644
--- a/drivers/regex/mlx5/mlx5_rxp.c
+++ b/drivers/regex/mlx5/mlx5_rxp.c
@@ -8,6 +8,7 @@
 #include <rte_regexdev.h>
 #include <rte_regexdev_core.h>
 #include <rte_regexdev_driver.h>
+#include <sys/mman.h>
 
 #include <mlx5_glue.h>
 #include <mlx5_devx_cmds.h>
@@ -24,6 +25,8 @@
 #define MLX5_REGEX_MAX_RULES_PER_GROUP UINT32_MAX
 #define MLX5_REGEX_MAX_GROUPS MLX5_RXP_MAX_SUBSETS
 
+#define MLX5_REGEX_RXP_ROF2_LINE_LEN 34
+
 /* Private Declarations */
 static int
 rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value,
@@ -36,30 +39,15 @@ mlnx_resume_database(struct mlx5_regex_priv *priv, uint8_t id);
 static int
 mlnx_update_database(struct mlx5_regex_priv *priv, uint8_t id);
 static int
-program_rxp_rules(struct mlx5_regex_priv *priv,
-		  struct mlx5_rxp_ctl_rules_pgm *rules, uint8_t id);
+program_rxp_rules(struct mlx5_regex_priv *priv, const char *buf, uint32_t len,
+		  uint8_t id);
 static int
 rxp_init_eng(struct mlx5_regex_priv *priv, uint8_t id);
 static int
-write_private_rules(struct mlx5_regex_priv *priv,
-		    struct mlx5_rxp_ctl_rules_pgm *rules,
-		    uint8_t id);
-static int
-write_shared_rules(struct mlx5_regex_priv *priv,
-		   struct mlx5_rxp_ctl_rules_pgm *rules, uint32_t count,
-		   uint8_t db_to_program);
-static int
 rxp_db_setup(struct mlx5_regex_priv *priv);
 static void
 rxp_dump_csrs(struct ibv_context *ctx, uint8_t id);
 static int
-rxp_write_rules_via_cp(struct ibv_context *ctx,
-		       struct mlx5_rxp_rof_entry *rules,
-		       int count, uint8_t id);
-static int
-rxp_flush_rules(struct ibv_context *ctx, struct mlx5_rxp_rof_entry *rules,
-		int count, uint8_t id);
-static int
 rxp_start_engine(struct ibv_context *ctx, uint8_t id);
 static int
 rxp_stop_engine(struct ibv_context *ctx, uint8_t id);
@@ -123,110 +111,6 @@ mlx5_regex_info_get(struct rte_regexdev *dev __rte_unused,
 	return 0;
 }
 
-/**
- * Actual writing of RXP instructions to RXP via CSRs.
- */
-static int
-rxp_write_rules_via_cp(struct ibv_context *ctx,
-		       struct mlx5_rxp_rof_entry *rules,
-		       int count, uint8_t id)
-{
-	int i, ret = 0;
-	uint32_t tmp;
-
-	for (i = 0; i < count; i++) {
-		tmp = (uint32_t)rules[i].value;
-		ret |= mlx5_devx_regex_register_write(ctx, id,
-						      MLX5_RXP_RTRU_CSR_DATA_0,
-						      tmp);
-		tmp = (uint32_t)(rules[i].value >> 32);
-		ret |= mlx5_devx_regex_register_write(ctx, id,
-						      MLX5_RXP_RTRU_CSR_DATA_0 +
-						      MLX5_RXP_CSR_WIDTH, tmp);
-		tmp = rules[i].addr;
-		ret |= mlx5_devx_regex_register_write(ctx, id,
-						      MLX5_RXP_RTRU_CSR_ADDR,
-						      tmp);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to copy instructions to RXP.");
-			return -1;
-		}
-	}
-	DRV_LOG(DEBUG, "Written %d instructions", count);
-	return 0;
-}
-
-static int
-rxp_flush_rules(struct ibv_context *ctx, struct mlx5_rxp_rof_entry *rules,
-		int count, uint8_t id)
-{
-	uint32_t val, fifo_depth;
-	int ret;
-
-	ret = rxp_write_rules_via_cp(ctx, rules, count, id);
-	if (ret < 0) {
-		DRV_LOG(ERR, "Failed to write rules via CSRs.");
-		return -1;
-	}
-	ret = mlx5_devx_regex_register_read(ctx, id,
-					    MLX5_RXP_RTRU_CSR_CAPABILITY,
-					    &fifo_depth);
-	if (ret) {
-		DRV_LOG(ERR, "CSR read failed!");
-		return -1;
-	}
-	ret = rxp_poll_csr_for_value(ctx, &val, MLX5_RXP_RTRU_CSR_FIFO_STAT,
-				     count, ~0,
-				     MLX5_RXP_POLL_CSR_FOR_VALUE_TIMEOUT, id);
-	if (ret < 0) {
-		if (ret == -EBUSY)
-			DRV_LOG(ERR, "Rules not rx by RXP: credit: %d, depth:"
-				" %d", val, fifo_depth);
-		else
-			DRV_LOG(ERR, "CSR poll failed, can't read value!");
-		return ret;
-	}
-	DRV_LOG(DEBUG, "RTRU FIFO depth: 0x%x", fifo_depth);
-	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
-					    &val);
-	if (ret) {
-		DRV_LOG(ERR, "CSR read failed!");
-		return -1;
-	}
-	val |= MLX5_RXP_RTRU_CSR_CTRL_GO;
-	ret = mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
-					     val);
-	if (ret) {
-		DRV_LOG(ERR, "CSR write failed!");
-		return -1;
-	}
-	ret = rxp_poll_csr_for_value(ctx, &val, MLX5_RXP_RTRU_CSR_STATUS,
-				     MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE,
-				     MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE,
-				     MLX5_RXP_POLL_CSR_FOR_VALUE_TIMEOUT, id);
-	if (ret < 0) {
-		if (ret == -EBUSY)
-			DRV_LOG(ERR, "Rules update timeout: 0x%08X", val);
-		else
-			DRV_LOG(ERR, "CSR poll failed, can't read value!");
-		return ret;
-	}
-	if (mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
-					  &val)) {
-		DRV_LOG(ERR, "CSR read failed!");
-		return -1;
-	}
-	val &= ~(MLX5_RXP_RTRU_CSR_CTRL_GO);
-	if (mlx5_devx_regex_register_write(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
-					   val)) {
-		DRV_LOG(ERR, "CSR write failed!");
-		return -1;
-	}
-
-	DRV_LOG(DEBUG, "RXP Flush rules finished.");
-	return 0;
-}
-
 static int
 rxp_poll_csr_for_value(struct ibv_context *ctx, uint32_t *value,
 		       uint32_t address, uint32_t expected_value,
@@ -278,13 +162,14 @@ rxp_stop_engine(struct ibv_context *ctx, uint8_t id)
 }
 
 static int
-rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits)
+rxp_init_rtru(struct mlx5_regex_priv *priv, uint8_t id, uint32_t init_bits)
 {
 	uint32_t ctrl_value;
 	uint32_t poll_value;
 	uint32_t expected_value;
 	uint32_t expected_mask;
-	int ret;
+	struct ibv_context *ctx = priv->ctx;
+	int ret = 0;
 
 	/* Read the rtru ctrl CSR. */
 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
@@ -317,13 +202,15 @@ rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits)
 	/* Check that the following bits are set in the RTRU_CSR. */
 	if (init_bits == MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2) {
 		/* Must be incremental mode */
-		expected_value = MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE |
-			MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
+		expected_value = MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE;
 	} else {
 		expected_value = MLX5_RXP_RTRU_CSR_STATUS_IM_INIT_DONE |
-			MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE |
-			MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
+			MLX5_RXP_RTRU_CSR_STATUS_L1C_INIT_DONE;
 	}
+	if (priv->is_bf2)
+		expected_value |= MLX5_RXP_RTRU_CSR_STATUS_L2C_INIT_DONE;
+
+
 	expected_mask = expected_value;
 	ret = rxp_poll_csr_for_value(ctx, &poll_value,
 				     MLX5_RXP_RTRU_CSR_STATUS,
@@ -340,69 +227,278 @@ rxp_init_rtru(struct ibv_context *ctx, uint8_t id, uint32_t init_bits)
 }
 
 static int
-rxp_parse_rof(const char *buf, uint32_t len,
-	      struct mlx5_rxp_ctl_rules_pgm **rules)
+rxp_parse_line(char *line, uint32_t *type, uint32_t *address, uint64_t *value)
+{
+	char *cur_pos;
+
+	if (*line == '\0' || *line == '#')
+		return  1;
+	*type = strtoul(line, &cur_pos, 10);
+	if (*cur_pos != ',' && *cur_pos != '\0')
+		return -1;
+	*address = strtoul(cur_pos+1, &cur_pos, 16);
+	if (*cur_pos != ',' && *cur_pos != '\0')
+		return -1;
+	*value = strtoul(cur_pos+1, &cur_pos, 16);
+	if (*cur_pos != ',' && *cur_pos != '\0')
+		return -1;
+	return 0;
+}
+
+static uint32_t
+rxp_get_reg_address(uint32_t address)
+{
+	uint32_t block;
+	uint32_t reg;
+
+	block = (address >> 16) & 0xFFFF;
+	if (block == 0)
+		reg = MLX5_RXP_CSR_BASE_ADDRESS;
+	else if (block == 1)
+		reg = MLX5_RXP_RTRU_CSR_BASE_ADDRESS;
+	else {
+		DRV_LOG(ERR, "Invalid ROF register 0x%08X!", address);
+			return UINT32_MAX;
+	}
+	reg += (address & 0xFFFF) * MLX5_RXP_CSR_WIDTH;
+	return reg;
+}
+
+#define MLX5_RXP_NUM_LINES_PER_BLOCK 8
+
+static int
+rxp_program_rof(struct mlx5_regex_priv *priv, const char *buf, uint32_t len,
+		uint8_t id)
 {
 	static const char del[] = "\n\r";
 	char *line;
 	char *tmp;
-	char *cur_pos;
-	uint32_t lines = 0;
-	uint32_t entries;
-	struct mlx5_rxp_rof_entry *curentry;
+	uint32_t type = 0;
+	uint32_t address;
+	uint64_t val;
+	uint32_t reg_val;
+	int ret;
+	int skip = -1;
+	int last = 0;
+	uint32_t temp;
+	uint32_t tmp_addr;
+	uint32_t rof_rule_addr;
+	uint64_t tmp_write_swap[4];
+	struct mlx5_rxp_rof_entry rules[8];
+	int i;
+	int db_free;
+	int j;
 
 	tmp = rte_malloc("", len, 0);
 	if (!tmp)
 		return -ENOMEM;
 	memcpy(tmp, buf, len);
-	line = strtok(tmp, del);
-	while (line) {
-		if (line[0] != '#' && line[0] != '\0')
-			lines++;
-		line = strtok(NULL, del);
-	}
-	*rules = rte_malloc("", lines * sizeof(*curentry) + sizeof(**rules), 0);
-	if (!(*rules)) {
+	db_free = mlnx_update_database(priv, id);
+	if (db_free < 0) {
+		DRV_LOG(ERR, "Failed to setup db memory!");
 		rte_free(tmp);
-		return -ENOMEM;
+		return db_free;
 	}
-	memset(*rules, 0, lines * sizeof(curentry) + sizeof(**rules));
-	curentry = (*rules)->rules;
-	(*rules)->hdr.cmd = MLX5_RXP_CTL_RULES_PGM;
-	entries = 0;
-	memcpy(tmp, buf, len);
-	line = strtok(tmp, del);
-	while (line) {
-		if (line[0] == '#' || line[0] == '\0') {
-			line = strtok(NULL, del);
+	for (line = strtok(tmp, del), j = 0; line; line = strtok(NULL, del),
+	     j++, last = type) {
+		ret = rxp_parse_line(line, &type, &address, &val);
+		if (ret != 0) {
+			if (ret < 0)
+				goto parse_error;
 			continue;
 		}
-		curentry->type = strtoul(line, &cur_pos, 10);
-		if (cur_pos == line || cur_pos[0] != ',')
-			goto parse_error;
-		cur_pos++;
-		curentry->addr = strtoul(cur_pos, &cur_pos, 16);
-		if (cur_pos[0] != ',')
-			goto parse_error;
-		cur_pos++;
-		curentry->value = strtoull(cur_pos, &cur_pos, 16);
-		if (cur_pos[0] != '\0' && cur_pos[0] != '\n')
-			goto parse_error;
-		curentry++;
-		entries++;
-		if (entries > lines)
-			goto parse_error;
-		line = strtok(NULL, del);
-	}
-	(*rules)->count = entries;
-	(*rules)->hdr.len = entries * sizeof(*curentry) + sizeof(**rules);
+		switch (type) {
+		case MLX5_RXP_ROF_ENTRY_EQ:
+			if (skip == 0 && address == 0)
+				skip = 1;
+			tmp_addr = rxp_get_reg_address(address);
+			if (tmp_addr == UINT32_MAX)
+				goto parse_error;
+			ret = mlx5_devx_regex_register_read(priv->ctx, id,
+							    tmp_addr, &reg_val);
+			if (ret)
+				goto parse_error;
+			if (skip == -1 && address == 0) {
+				if (val == reg_val) {
+					skip = 0;
+					continue;
+				}
+			} else if (skip == 0) {
+				if (val != reg_val) {
+					DRV_LOG(ERR,
+						"got %08X expected == %" PRIx64,
+						reg_val, val);
+					goto parse_error;
+				}
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_GTE:
+			if (skip == 0 && address == 0)
+				skip = 1;
+			tmp_addr = rxp_get_reg_address(address);
+			if (tmp_addr == UINT32_MAX)
+				goto parse_error;
+			ret = mlx5_devx_regex_register_read(priv->ctx, id,
+							    tmp_addr, &reg_val);
+			if (ret)
+				goto parse_error;
+			if (skip == -1 && address == 0) {
+				if (reg_val >= val) {
+					skip = 0;
+					continue;
+				}
+			} else if (skip == 0) {
+				if (reg_val < val) {
+					DRV_LOG(ERR,
+						"got %08X expected >= %" PRIx64,
+						reg_val, val);
+					goto parse_error;
+				}
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_LTE:
+			tmp_addr = rxp_get_reg_address(address);
+			if (tmp_addr == UINT32_MAX)
+				goto parse_error;
+			ret = mlx5_devx_regex_register_read(priv->ctx, id,
+							    tmp_addr, &reg_val);
+			if (ret)
+				goto parse_error;
+			if (skip == 0 && address == 0 &&
+			    last != MLX5_RXP_ROF_ENTRY_GTE) {
+				skip = 1;
+			} else if (skip == 0 && address == 0 &&
+				   last == MLX5_RXP_ROF_ENTRY_GTE) {
+				if (reg_val > val)
+					skip = -1;
+				continue;
+			}
+			if (skip == -1 && address == 0) {
+				if (reg_val <= val) {
+					skip = 0;
+					continue;
+				}
+			} else if (skip == 0) {
+				if (reg_val > val) {
+					DRV_LOG(ERR,
+						"got %08X expected <= %" PRIx64,
+						reg_val, val);
+					goto parse_error;
+				}
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_CHECKSUM:
+			break;
+		case MLX5_RXP_ROF_ENTRY_CHECKSUM_EX_EM:
+			if (skip)
+				continue;
+			tmp_addr = rxp_get_reg_address(address);
+			if (tmp_addr == UINT32_MAX)
+				goto parse_error;
+
+			ret = mlx5_devx_regex_register_read(priv->ctx, id,
+							    tmp_addr, &reg_val);
+			if (ret) {
+				DRV_LOG(ERR, "RXP CSR read failed!");
+				return ret;
+			}
+			if (reg_val != val) {
+				DRV_LOG(ERR, "got %08X expected <= %" PRIx64,
+					reg_val, val);
+				goto parse_error;
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_IM:
+			if (skip)
+				continue;
+			/*
+			 * NOTE: All rules written to RXP must be carried out in
+			 * triplets of: 2xData + 1xAddr.
+			 * No optimisation is currently allowed in this
+			 * sequence to perform less writes.
+			 */
+			temp = val;
+			ret |= mlx5_devx_regex_register_write
+					(priv->ctx, id,
+					 MLX5_RXP_RTRU_CSR_DATA_0, temp);
+			temp = (uint32_t)(val >> 32);
+			ret |= mlx5_devx_regex_register_write
+					(priv->ctx, id,
+					 MLX5_RXP_RTRU_CSR_DATA_0 +
+					 MLX5_RXP_CSR_WIDTH, temp);
+			temp = address;
+			ret |= mlx5_devx_regex_register_write
+					(priv->ctx, id, MLX5_RXP_RTRU_CSR_ADDR,
+					 temp);
+			if (ret) {
+				DRV_LOG(ERR,
+					"Failed to copy instructions to RXP.");
+				goto parse_error;
+			}
+			break;
+		case MLX5_RXP_ROF_ENTRY_EM:
+			if (skip)
+				continue;
+			for (i = 0; i < MLX5_RXP_NUM_LINES_PER_BLOCK; i++) {
+				ret = rxp_parse_line(line, &type,
+						     &rules[i].addr,
+						     &rules[i].value);
+				if (ret != 0)
+					goto parse_error;
+				if (i < (MLX5_RXP_NUM_LINES_PER_BLOCK - 1)) {
+					line = strtok(NULL, del);
+					if (!line)
+						goto parse_error;
+				}
+			}
+			if ((uint8_t *)((uint8_t *)
+					priv->db[id].ptr +
+					((rules[7].addr <<
+					 MLX5_RXP_INST_OFFSET))) >=
+					((uint8_t *)((uint8_t *)
+					priv->db[id].ptr + MLX5_MAX_DB_SIZE))) {
+				DRV_LOG(ERR, "DB exceeded memory!");
+				goto parse_error;
+			}
+			/*
+			 * Rule address Offset to align with RXP
+			 * external instruction offset.
+			 */
+			rof_rule_addr = (rules[0].addr << MLX5_RXP_INST_OFFSET);
+			/* 32 byte instruction swap (sw work around)! */
+			tmp_write_swap[0] = le64toh(rules[4].value);
+			tmp_write_swap[1] = le64toh(rules[5].value);
+			tmp_write_swap[2] = le64toh(rules[6].value);
+			tmp_write_swap[3] = le64toh(rules[7].value);
+			/* Write only 4 of the 8 instructions. */
+			memcpy((uint8_t *)((uint8_t *)
+				priv->db[id].ptr + rof_rule_addr),
+				&tmp_write_swap, (sizeof(uint64_t) * 4));
+			/* Write 1st 4 rules of block after last 4. */
+			rof_rule_addr = (rules[4].addr << MLX5_RXP_INST_OFFSET);
+			tmp_write_swap[0] = le64toh(rules[0].value);
+			tmp_write_swap[1] = le64toh(rules[1].value);
+			tmp_write_swap[2] = le64toh(rules[2].value);
+			tmp_write_swap[3] = le64toh(rules[3].value);
+			memcpy((uint8_t *)((uint8_t *)
+				priv->db[id].ptr + rof_rule_addr),
+				&tmp_write_swap, (sizeof(uint64_t) * 4));
+			break;
+		default:
+			break;
+		}
+
+	}
+	ret = mlnx_set_database(priv, id, db_free);
+	if (ret < 0) {
+		DRV_LOG(ERR, "Failed to register db memory!");
+		goto parse_error;
+	}
 	rte_free(tmp);
 	return 0;
 parse_error:
 	rte_free(tmp);
-	if (*rules)
-		rte_free(*rules);
-	return -EINVAL;
+	return ret;
 }
 
 static int
@@ -488,43 +584,85 @@ mlnx_update_database(struct mlx5_regex_priv *priv, uint8_t id)
  * Program RXP instruction db to RXP engine/s.
  */
 static int
-program_rxp_rules(struct mlx5_regex_priv *priv,
-		  struct mlx5_rxp_ctl_rules_pgm *rules, uint8_t id)
+program_rxp_rules(struct mlx5_regex_priv *priv, const char *buf, uint32_t len,
+		  uint8_t id)
 {
-	int ret, db_free;
-	uint32_t rule_cnt;
+	int ret;
+	uint32_t val;
 
-	rule_cnt = rules->count;
-	db_free = mlnx_update_database(priv, id);
-	if (db_free < 0) {
-		DRV_LOG(ERR, "Failed to setup db memory!");
-		return db_free;
+	ret = rxp_init_eng(priv, id);
+	if (ret < 0)
+		return ret;
+	/* Confirm the RXP is initialised. */
+	if (mlx5_devx_regex_register_read(priv->ctx, id,
+					    MLX5_RXP_CSR_STATUS, &val)) {
+		DRV_LOG(ERR, "Failed to read from RXP!");
+		return -ENODEV;
 	}
-	if (priv->prog_mode == MLX5_RXP_PRIVATE_PROG_MODE) {
-		/* Register early to ensure RXP writes to EM use valid addr. */
-		ret = mlnx_set_database(priv, id, db_free);
-		if (ret < 0) {
-			DRV_LOG(ERR, "Failed to register db memory!");
-			return ret;
-		}
+	if (!(val & MLX5_RXP_CSR_STATUS_INIT_DONE)) {
+		DRV_LOG(ERR, "RXP not initialised...");
+		return -EBUSY;
 	}
-	ret = write_private_rules(priv, rules, id);
-	if (ret < 0) {
-		DRV_LOG(ERR, "Failed to write rules!");
-		return ret;
+	ret = mlx5_devx_regex_register_read(priv->ctx, id,
+					    MLX5_RXP_RTRU_CSR_CTRL, &val);
+	if (ret) {
+		DRV_LOG(ERR, "CSR read failed!");
+		return -1;
 	}
-	if (priv->prog_mode == MLX5_RXP_SHARED_PROG_MODE) {
-		/* Write external rules directly to EM. */
-		rules->count = rule_cnt;
-	       /* Now write external instructions to EM. */
-		ret = write_shared_rules(priv, rules, rules->hdr.len, db_free);
+	val |= MLX5_RXP_RTRU_CSR_CTRL_GO;
+	ret = mlx5_devx_regex_register_write(priv->ctx, id,
+					     MLX5_RXP_RTRU_CSR_CTRL, val);
+	if (ret) {
+		DRV_LOG(ERR, "Can't program rof file!");
+		return -1;
+	}
+	ret = rxp_program_rof(priv, buf, len, id);
+	if (ret) {
+		DRV_LOG(ERR, "Can't program rof file!");
+		return -1;
+	}
+	if (priv->is_bf2) {
+		ret = rxp_poll_csr_for_value
+			(priv->ctx, &val, MLX5_RXP_RTRU_CSR_STATUS,
+			 MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE,
+			 MLX5_RXP_RTRU_CSR_STATUS_UPDATE_DONE,
+			 MLX5_RXP_POLL_CSR_FOR_VALUE_TIMEOUT, id);
 		if (ret < 0) {
-			DRV_LOG(ERR, "Failed to write EM rules!");
+			DRV_LOG(ERR, "Rules update timeout: 0x%08X", val);
 			return ret;
 		}
-		ret = mlnx_set_database(priv, id, db_free);
-		if (ret < 0) {
-			DRV_LOG(ERR, "Failed to register db memory!");
+		DRV_LOG(DEBUG, "Rules update took %d cycles", ret);
+	}
+	if (mlx5_devx_regex_register_read(priv->ctx, id, MLX5_RXP_RTRU_CSR_CTRL,
+					  &val)) {
+		DRV_LOG(ERR, "CSR read failed!");
+		return -1;
+	}
+	val &= ~(MLX5_RXP_RTRU_CSR_CTRL_GO);
+	if (mlx5_devx_regex_register_write(priv->ctx, id,
+					   MLX5_RXP_RTRU_CSR_CTRL, val)) {
+		DRV_LOG(ERR, "CSR write write failed!");
+		return -1;
+	}
+	ret = mlx5_devx_regex_register_read(priv->ctx, id, MLX5_RXP_CSR_CTRL,
+					    &val);
+	if (ret)
+		return ret;
+	val &= ~MLX5_RXP_CSR_CTRL_INIT;
+	ret = mlx5_devx_regex_register_write(priv->ctx, id, MLX5_RXP_CSR_CTRL,
+					     val);
+	if (ret)
+		return ret;
+	rxp_init_rtru(priv, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2);
+	if (priv->is_bf2) {
+		ret = rxp_poll_csr_for_value(priv->ctx, &val,
+					     MLX5_RXP_CSR_STATUS,
+					     MLX5_RXP_CSR_STATUS_INIT_DONE,
+					     MLX5_RXP_CSR_STATUS_INIT_DONE,
+					     MLX5_RXP_CSR_STATUS_TRIAL_TIMEOUT,
+					     id);
+		if (ret) {
+			DRV_LOG(ERR, "Device init failed!");
 			return ret;
 		}
 	}
@@ -533,9 +671,9 @@ program_rxp_rules(struct mlx5_regex_priv *priv,
 		DRV_LOG(ERR, "Failed to resume engine!");
 		return ret;
 	}
-	DRV_LOG(DEBUG, "Programmed RXP Engine %d\n", id);
-	rules->count = rule_cnt;
-	return 0;
+
+	return ret;
+
 }
 
 static int
@@ -579,7 +717,8 @@ rxp_init_eng(struct mlx5_regex_priv *priv, uint8_t id)
 					     ctrl);
 	if (ret)
 		return ret;
-	ret = rxp_init_rtru(ctx, id, MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2);
+	ret = rxp_init_rtru(priv, id,
+			    MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_IM_L1_L2);
 	if (ret)
 		return ret;
 	ret = mlx5_devx_regex_register_read(ctx, id, MLX5_RXP_CSR_CAPABILITY_5,
@@ -605,285 +744,6 @@ rxp_init_eng(struct mlx5_regex_priv *priv, uint8_t id)
 	return ret;
 }
 
-static int
-write_private_rules(struct mlx5_regex_priv *priv,
-		    struct mlx5_rxp_ctl_rules_pgm *rules,
-		    uint8_t id)
-{
-	unsigned int pending;
-	uint32_t block, reg, val, rule_cnt, rule_offset, rtru_max_num_entries;
-	int ret = 1;
-
-	if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED)
-		return -EINVAL;
-	if (rules->hdr.len == 0 || rules->hdr.cmd < MLX5_RXP_CTL_RULES_PGM ||
-				   rules->hdr.cmd > MLX5_RXP_CTL_RULES_PGM_INCR)
-		return -EINVAL;
-	/* For a non-incremental rules program, re-init the RXP. */
-	if (rules->hdr.cmd == MLX5_RXP_CTL_RULES_PGM) {
-		ret = rxp_init_eng(priv, id);
-		if (ret < 0)
-			return ret;
-	} else if (rules->hdr.cmd == MLX5_RXP_CTL_RULES_PGM_INCR) {
-		/* Flush RXP L1 and L2 cache by using MODE_L1_L2. */
-		ret = rxp_init_rtru(priv->ctx, id,
-				    MLX5_RXP_RTRU_CSR_CTRL_INIT_MODE_L1_L2);
-		if (ret < 0)
-			return ret;
-	}
-	if (rules->count == 0)
-		return -EINVAL;
-	/* Confirm the RXP is initialised. */
-	if (mlx5_devx_regex_register_read(priv->ctx, id,
-					    MLX5_RXP_CSR_STATUS, &val)) {
-		DRV_LOG(ERR, "Failed to read from RXP!");
-		return -ENODEV;
-	}
-	if (!(val & MLX5_RXP_CSR_STATUS_INIT_DONE)) {
-		DRV_LOG(ERR, "RXP not initialised...");
-		return -EBUSY;
-	}
-	/* Get the RTRU maximum number of entries allowed. */
-	if (mlx5_devx_regex_register_read(priv->ctx, id,
-			MLX5_RXP_RTRU_CSR_CAPABILITY, &rtru_max_num_entries)) {
-		DRV_LOG(ERR, "Failed to read RTRU capability!");
-		return -ENODEV;
-	}
-	rtru_max_num_entries = (rtru_max_num_entries & 0x00FF);
-	rule_cnt = 0;
-	pending = 0;
-	while (rules->count > 0) {
-		if ((rules->rules[rule_cnt].type == MLX5_RXP_ROF_ENTRY_INST) ||
-		    (rules->rules[rule_cnt].type == MLX5_RXP_ROF_ENTRY_IM) ||
-		    (rules->rules[rule_cnt].type == MLX5_RXP_ROF_ENTRY_EM)) {
-			if ((rules->rules[rule_cnt].type ==
-			     MLX5_RXP_ROF_ENTRY_EM) &&
-			    (priv->prog_mode == MLX5_RXP_SHARED_PROG_MODE)) {
-				/* Skip EM rules programming. */
-				if (pending > 0) {
-					/* Flush any rules that are pending. */
-					rule_offset = (rule_cnt - pending);
-					ret = rxp_flush_rules(priv->ctx,
-						&rules->rules[rule_offset],
-						pending, id);
-					if (ret < 0) {
-						DRV_LOG(ERR, "Flushing rules.");
-						return -ENODEV;
-					}
-					pending = 0;
-				}
-				rule_cnt++;
-			} else {
-				pending++;
-				rule_cnt++;
-				/*
-				 * If parsing the last rule, or if reached the
-				 * maximum number of rules for this batch, then
-				 * flush the rules batch to the RXP.
-				 */
-				if ((rules->count == 1) ||
-				    (pending == rtru_max_num_entries)) {
-					rule_offset = (rule_cnt - pending);
-					ret = rxp_flush_rules(priv->ctx,
-						&rules->rules[rule_offset],
-						pending, id);
-					if (ret < 0) {
-						DRV_LOG(ERR, "Flushing rules.");
-						return -ENODEV;
-					}
-					pending = 0;
-				}
-			}
-		} else if ((rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_EQ) ||
-			 (rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_GTE) ||
-			 (rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_LTE) ||
-			 (rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_CHECKSUM) ||
-			 (rules->rules[rule_cnt].type ==
-				MLX5_RXP_ROF_ENTRY_CHECKSUM_EX_EM)) {
-			if (pending) {
-				/* Flush rules before checking reg values. */
-				rule_offset = (rule_cnt - pending);
-				ret = rxp_flush_rules(priv->ctx,
-					&rules->rules[rule_offset],
-					pending, id);
-				if (ret < 0) {
-					DRV_LOG(ERR, "Failed to flush rules.");
-					return -ENODEV;
-				}
-			}
-			block = (rules->rules[rule_cnt].addr >> 16) & 0xFFFF;
-			if (block == 0)
-				reg = MLX5_RXP_CSR_BASE_ADDRESS;
-			else if (block == 1)
-				reg = MLX5_RXP_RTRU_CSR_BASE_ADDRESS;
-			else {
-				DRV_LOG(ERR, "Invalid ROF register 0x%08X!",
-					rules->rules[rule_cnt].addr);
-				return -EINVAL;
-			}
-			reg += (rules->rules[rule_cnt].addr & 0xFFFF) *
-				MLX5_RXP_CSR_WIDTH;
-			ret = mlx5_devx_regex_register_read(priv->ctx, id,
-							    reg, &val);
-			if (ret) {
-				DRV_LOG(ERR, "RXP CSR read failed!");
-				return ret;
-			}
-			if ((priv->prog_mode == MLX5_RXP_SHARED_PROG_MODE) &&
-			    ((rules->rules[rule_cnt].type ==
-			    MLX5_RXP_ROF_ENTRY_CHECKSUM_EX_EM) &&
-			    (val != rules->rules[rule_cnt].value))) {
-				DRV_LOG(ERR, "Unexpected value for register:");
-				DRV_LOG(ERR, "reg %x" PRIu32 " got %x" PRIu32,
-					rules->rules[rule_cnt].addr, val);
-				DRV_LOG(ERR, "expected %" PRIx64 ".",
-					rules->rules[rule_cnt].value);
-					return -EINVAL;
-			} else if ((priv->prog_mode ==
-				 MLX5_RXP_PRIVATE_PROG_MODE) &&
-				 (rules->rules[rule_cnt].type ==
-				 MLX5_RXP_ROF_ENTRY_CHECKSUM) &&
-				 (val != rules->rules[rule_cnt].value)) {
-				DRV_LOG(ERR, "Unexpected value for register:");
-				DRV_LOG(ERR, "reg %x" PRIu32 " got %x" PRIu32,
-					rules->rules[rule_cnt].addr, val);
-				DRV_LOG(ERR, "expected %" PRIx64 ".",
-					rules->rules[rule_cnt].value);
-				return -EINVAL;
-			} else if ((rules->rules[rule_cnt].type ==
-					MLX5_RXP_ROF_ENTRY_EQ) &&
-				  (val != rules->rules[rule_cnt].value)) {
-				DRV_LOG(ERR, "Unexpected value for register:");
-				DRV_LOG(ERR, "reg %x" PRIu32 " got %x" PRIu32,
-					rules->rules[rule_cnt].addr, val);
-				DRV_LOG(ERR, "expected %" PRIx64 ".",
-					rules->rules[rule_cnt].value);
-					return -EINVAL;
-			} else if ((rules->rules[rule_cnt].type ==
-					MLX5_RXP_ROF_ENTRY_GTE) &&
-				 (val < rules->rules[rule_cnt].value)) {
-				DRV_LOG(ERR, "Unexpected value reg 0x%08X,",
-					rules->rules[rule_cnt].addr);
-				DRV_LOG(ERR, "got %X, expected >= %" PRIx64 ".",
-					val, rules->rules[rule_cnt].value);
-				return -EINVAL;
-			} else if ((rules->rules[rule_cnt].type ==
-					MLX5_RXP_ROF_ENTRY_LTE) &&
-				 (val > rules->rules[rule_cnt].value)) {
-				DRV_LOG(ERR, "Unexpected value reg 0x%08X,",
-					rules->rules[rule_cnt].addr);
-				DRV_LOG(ERR, "got %08X expected <= %" PRIx64,
-					val, rules->rules[rule_cnt].value);
-				return -EINVAL;
-			}
-			rule_cnt++;
-			pending = 0;
-		} else {
-			DRV_LOG(ERR, "Error: Invalid rule type %d!",
-				rules->rules[rule_cnt].type);
-			return -EINVAL;
-		}
-		rules->count--;
-	}
-	return ret;
-}
-
-/*
- * Shared memory programming mode, here all external db instructions are written
- * to EM via the host.
- */
-static int
-write_shared_rules(struct mlx5_regex_priv *priv,
-		   struct mlx5_rxp_ctl_rules_pgm *rules, uint32_t count,
-		   uint8_t db_to_program)
-{
-	uint32_t rule_cnt, rof_rule_addr;
-	uint64_t tmp_write_swap[4];
-
-	if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED)
-		return -EINVAL;
-	if ((rules->count == 0) || (count == 0))
-		return -EINVAL;
-	rule_cnt = 0;
-	/*
-	 * Note the following section of code carries out a 32byte swap of
-	 * instruction to coincide with HW 32byte swap. This may need removed
-	 * in new variants of this programming function!
-	 */
-	while (rule_cnt < rules->count) {
-		if ((rules->rules[rule_cnt].type == MLX5_RXP_ROF_ENTRY_EM) &&
-		    (priv->prog_mode == MLX5_RXP_SHARED_PROG_MODE)) {
-			/*
-			 * Note there are always blocks of 8 instructions for
-			 * 7's written sequentially. However there is no
-			 * guarantee that all blocks are sequential!
-			 */
-			if (count >= (rule_cnt + MLX5_RXP_INST_BLOCK_SIZE)) {
-				/*
-				 * Ensure memory write not exceeding boundary
-				 * Check essential to ensure 0x10000 offset
-				 * accounted for!
-				 */
-				if ((uint8_t *)((uint8_t *)
-				    priv->db[db_to_program].ptr +
-				    ((rules->rules[rule_cnt + 7].addr <<
-				    MLX5_RXP_INST_OFFSET))) >=
-				    ((uint8_t *)((uint8_t *)
-				    priv->db[db_to_program].ptr +
-				    MLX5_MAX_DB_SIZE))) {
-					DRV_LOG(ERR, "DB exceeded memory!");
-					return -ENODEV;
-				}
-				/*
-				 * Rule address Offset to align with RXP
-				 * external instruction offset.
-				 */
-				rof_rule_addr = (rules->rules[rule_cnt].addr <<
-						 MLX5_RXP_INST_OFFSET);
-				/* 32 byte instruction swap (sw work around)! */
-				tmp_write_swap[0] = le64toh(
-					rules->rules[(rule_cnt + 4)].value);
-				tmp_write_swap[1] = le64toh(
-					rules->rules[(rule_cnt + 5)].value);
-				tmp_write_swap[2] = le64toh(
-					rules->rules[(rule_cnt + 6)].value);
-				tmp_write_swap[3] = le64toh(
-					rules->rules[(rule_cnt + 7)].value);
-				/* Write only 4 of the 8 instructions. */
-				memcpy((uint8_t *)((uint8_t *)
-				       priv->db[db_to_program].ptr +
-				       rof_rule_addr), &tmp_write_swap,
-				       (sizeof(uint64_t) * 4));
-				/* Write 1st 4 rules of block after last 4. */
-				rof_rule_addr = (rules->rules[
-						 (rule_cnt + 4)].addr <<
-						 MLX5_RXP_INST_OFFSET);
-				tmp_write_swap[0] = le64toh(
-					rules->rules[(rule_cnt + 0)].value);
-				tmp_write_swap[1] = le64toh(
-					rules->rules[(rule_cnt + 1)].value);
-				tmp_write_swap[2] = le64toh(
-					rules->rules[(rule_cnt + 2)].value);
-				tmp_write_swap[3] = le64toh(
-					rules->rules[(rule_cnt + 3)].value);
-				memcpy((uint8_t *)((uint8_t *)
-				       priv->db[db_to_program].ptr +
-				       rof_rule_addr), &tmp_write_swap,
-				       (sizeof(uint64_t) * 4));
-			} else
-				return -1;
-			/* Fast forward as already handled block of 8. */
-			rule_cnt += MLX5_RXP_INST_BLOCK_SIZE;
-		} else
-			rule_cnt++; /* Must be something other than EM rule. */
-	}
-	return 0;
-}
-
 static int
 rxp_db_setup(struct mlx5_regex_priv *priv)
 {
@@ -933,6 +793,7 @@ mlx5_regex_rules_db_import(struct rte_regexdev *dev,
 	struct mlx5_rxp_ctl_rules_pgm *rules = NULL;
 	uint32_t id;
 	int ret;
+	uint32_t ver;
 
 	if (priv->prog_mode == MLX5_RXP_MODE_NOT_DEFINED) {
 		DRV_LOG(ERR, "RXP programming mode not set!");
@@ -944,10 +805,10 @@ mlx5_regex_rules_db_import(struct rte_regexdev *dev,
 	}
 	if (rule_db_len == 0)
 		return -EINVAL;
-	ret = rxp_parse_rof(rule_db, rule_db_len, &rules);
-	if (ret) {
-		DRV_LOG(ERR, "Can't parse ROF file.");
-		return ret;
+	if (mlx5_devx_regex_register_read(priv->ctx, 0,
+					  MLX5_RXP_CSR_BASE_ADDRESS, &ver)) {
+		DRV_LOG(ERR, "Failed to read Main CSRs Engine 0!");
+		return -1;
 	}
 	/* Need to ensure RXP not busy before stop! */
 	for (id = 0; id < priv->nb_engines; id++) {
@@ -957,7 +818,7 @@ mlx5_regex_rules_db_import(struct rte_regexdev *dev,
 			ret = -ENODEV;
 			goto tidyup_error;
 		}
-		ret = program_rxp_rules(priv, rules, id);
+		ret = program_rxp_rules(priv, rule_db, rule_db_len, id);
 		if (ret < 0) {
 			DRV_LOG(ERR, "Failed to program rxp rules.");
 			ret = -ENODEV;
diff --git a/drivers/regex/mlx5/mlx5_rxp_csrs.h b/drivers/regex/mlx5/mlx5_rxp_csrs.h
index d92b3fff53..f3ffdfdef2 100644
--- a/drivers/regex/mlx5/mlx5_rxp_csrs.h
+++ b/drivers/regex/mlx5/mlx5_rxp_csrs.h
@@ -5,6 +5,9 @@
 #ifndef _MLX5_RXP_CSRS_H_
 #define _MLX5_RXP_CSRS_H_
 
+/* BF types */
+#define MLX5_RXP_BF2_IDENTIFIER 0x07055254ul
+
 /*
  * Common to all RXP implementations
  */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH v2 3/5] regex/mlx5: fix support for group id
  2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 1/5] regex/mlx5: fix memory rule alignment Ori Kam
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 2/5] regex/mlx5: add support for combined rule file Ori Kam
@ 2021-01-07 16:57   ` Ori Kam
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 4/5] regex/mlx5: add support for priority match Ori Kam
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2021-01-07 16:57 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev, stable

In order to know which groups in the RegEx engine
should be used there is a need to check the req_flags.

This commit adds the missing check.

Cc: stable@dpdk.org

Fixes: 4d4e245ad637 ("regex/mlx5: support enqueue")

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 drivers/regex/mlx5/mlx5_regex_fastpath.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/regex/mlx5/mlx5_regex_fastpath.c b/drivers/regex/mlx5/mlx5_regex_fastpath.c
index 5857617282..8d134ac98e 100644
--- a/drivers/regex/mlx5/mlx5_regex_fastpath.c
+++ b/drivers/regex/mlx5/mlx5_regex_fastpath.c
@@ -105,7 +105,21 @@ prep_one(struct mlx5_regex_priv *priv, struct mlx5_regex_qp *qp,
 {
 	size_t wqe_offset = (sq->pi & (sq_size_get(sq) - 1)) * MLX5_SEND_WQE_BB;
 	uint32_t lkey;
-
+	uint16_t group0 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID0_VALID_F ?
+				op->group_id0 : 0;
+	uint16_t group1 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID1_VALID_F ?
+				op->group_id1 : 0;
+	uint16_t group2 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID2_VALID_F ?
+				op->group_id2 : 0;
+	uint16_t group3 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID3_VALID_F ?
+				op->group_id3 : 0;
+
+	/* For backward compatibility. */
+	if (!(op->req_flags & (RTE_REGEX_OPS_REQ_GROUP_ID0_VALID_F |
+			       RTE_REGEX_OPS_REQ_GROUP_ID1_VALID_F |
+			       RTE_REGEX_OPS_REQ_GROUP_ID2_VALID_F |
+			       RTE_REGEX_OPS_REQ_GROUP_ID3_VALID_F)))
+		group0 = op->group_id0;
 	lkey = mlx5_mr_addr2mr_bh(priv->pd, 0,
 				  &priv->mr_scache, &qp->mr_ctrl,
 				  rte_pktmbuf_mtod(op->mbuf, uintptr_t),
@@ -116,9 +130,8 @@ prep_one(struct mlx5_regex_priv *priv, struct mlx5_regex_qp *qp,
 	set_wqe_ctrl_seg((struct mlx5_wqe_ctrl_seg *)wqe, sq->pi,
 			 MLX5_OPCODE_MMO, MLX5_OPC_MOD_MMO_REGEX, sq->obj->id,
 			 0, ds, 0, 0);
-	set_regex_ctrl_seg(wqe + 12, 0, op->group_id0, op->group_id1,
-			   op->group_id2,
-			   op->group_id3, 0);
+	set_regex_ctrl_seg(wqe + 12, 0, group0, group1, group2, group3,
+			   0);
 	struct mlx5_wqe_data_seg *input_seg =
 		(struct mlx5_wqe_data_seg *)(wqe +
 					     MLX5_REGEX_WQE_GATHER_OFFSET);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH v2 4/5] regex/mlx5: add support for priority match
  2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
                     ` (2 preceding siblings ...)
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 3/5] regex/mlx5: fix support for group id Ori Kam
@ 2021-01-07 16:57   ` Ori Kam
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 5/5] regex/mlx5: fix num of supported queues Ori Kam
  2021-01-19 17:08   ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Thomas Monjalon
  5 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2021-01-07 16:57 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev

The high priority match request flags means that the
RegEx engine should stop on the first match.

This commit add this flag check to the RegEx engine.

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 drivers/regex/mlx5/mlx5_regex_fastpath.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/regex/mlx5/mlx5_regex_fastpath.c b/drivers/regex/mlx5/mlx5_regex_fastpath.c
index 8d134ac98e..ee72f89c99 100644
--- a/drivers/regex/mlx5/mlx5_regex_fastpath.c
+++ b/drivers/regex/mlx5/mlx5_regex_fastpath.c
@@ -113,6 +113,8 @@ prep_one(struct mlx5_regex_priv *priv, struct mlx5_regex_qp *qp,
 				op->group_id2 : 0;
 	uint16_t group3 = op->req_flags & RTE_REGEX_OPS_REQ_GROUP_ID3_VALID_F ?
 				op->group_id3 : 0;
+	uint8_t control = op->req_flags &
+				RTE_REGEX_OPS_REQ_MATCH_HIGH_PRIORITY_F ? 1 : 0;
 
 	/* For backward compatibility. */
 	if (!(op->req_flags & (RTE_REGEX_OPS_REQ_GROUP_ID0_VALID_F |
@@ -131,7 +133,7 @@ prep_one(struct mlx5_regex_priv *priv, struct mlx5_regex_qp *qp,
 			 MLX5_OPCODE_MMO, MLX5_OPC_MOD_MMO_REGEX, sq->obj->id,
 			 0, ds, 0, 0);
 	set_regex_ctrl_seg(wqe + 12, 0, group0, group1, group2, group3,
-			   0);
+			   control);
 	struct mlx5_wqe_data_seg *input_seg =
 		(struct mlx5_wqe_data_seg *)(wqe +
 					     MLX5_REGEX_WQE_GATHER_OFFSET);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [dpdk-dev] [PATCH v2 5/5] regex/mlx5: fix num of supported queues
  2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
                     ` (3 preceding siblings ...)
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 4/5] regex/mlx5: add support for priority match Ori Kam
@ 2021-01-07 16:57   ` Ori Kam
  2021-01-19 17:08   ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Thomas Monjalon
  5 siblings, 0 replies; 12+ messages in thread
From: Ori Kam @ 2021-01-07 16:57 UTC (permalink / raw)
  To: thomas; +Cc: orika, dev, stable

The RegEx engine as no limitation on number of queues.
This commits modifies the max supported queues reported to the application.

Fixes: fbc8c7003b93 ("regex/mlx5: add completion queue creation")

Cc: stable@dpdk.org

Signed-off-by: Ori Kam <orika@nvidia.com>
---
 drivers/regex/mlx5/mlx5_rxp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/regex/mlx5/mlx5_rxp.c b/drivers/regex/mlx5/mlx5_rxp.c
index 66cbc1f481..e5d9b9245a 100644
--- a/drivers/regex/mlx5/mlx5_rxp.c
+++ b/drivers/regex/mlx5/mlx5_rxp.c
@@ -103,11 +103,10 @@ mlx5_regex_info_get(struct rte_regexdev *dev __rte_unused,
 	info->max_payload_size = MLX5_REGEX_MAX_PAYLOAD_SIZE;
 	info->max_rules_per_group = MLX5_REGEX_MAX_RULES_PER_GROUP;
 	info->max_groups = MLX5_REGEX_MAX_GROUPS;
-	info->max_queue_pairs = 1;
 	info->regexdev_capa = RTE_REGEXDEV_SUPP_PCRE_GREEDY_F |
 			      RTE_REGEXDEV_CAPA_QUEUE_PAIR_OOS_F;
 	info->rule_flags = 0;
-	info->max_queue_pairs = 10;
+	info->max_queue_pairs = UINT16_MAX;
 	return 0;
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/5]  regex/mlx5: pmd improvements
  2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
                     ` (4 preceding siblings ...)
  2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 5/5] regex/mlx5: fix num of supported queues Ori Kam
@ 2021-01-19 17:08   ` Thomas Monjalon
  5 siblings, 0 replies; 12+ messages in thread
From: Thomas Monjalon @ 2021-01-19 17:08 UTC (permalink / raw)
  To: Ori Kam; +Cc: dev

> Ori Kam (5):
>   regex/mlx5: fix memory rule alignment
>   regex/mlx5: add support for combined rule file
>   regex/mlx5: fix support for group id
>   regex/mlx5: add support for priority match
>   regex/mlx5: fix num of supported queues

Applied, thanks




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-01-19 17:08 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-17  8:51 [dpdk-dev] [PATCH 0/4] regex/mlx5: pmd improvements Ori Kam
2020-12-17  8:51 ` [dpdk-dev] [PATCH 1/4] regex/mlx5: fix memory rule alignment Ori Kam
2020-12-17  8:51 ` [dpdk-dev] [PATCH 2/4] regex/mlx5: add support for combined rule file Ori Kam
2020-12-17  8:51 ` [dpdk-dev] [PATCH 3/4] regex/mlx5: fix support for group id Ori Kam
2020-12-17  8:51 ` [dpdk-dev] [PATCH 4/4] regex/mlx5: add support for priority match Ori Kam
2021-01-07 16:57 ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Ori Kam
2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 1/5] regex/mlx5: fix memory rule alignment Ori Kam
2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 2/5] regex/mlx5: add support for combined rule file Ori Kam
2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 3/5] regex/mlx5: fix support for group id Ori Kam
2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 4/5] regex/mlx5: add support for priority match Ori Kam
2021-01-07 16:57   ` [dpdk-dev] [PATCH v2 5/5] regex/mlx5: fix num of supported queues Ori Kam
2021-01-19 17:08   ` [dpdk-dev] [PATCH v2 0/5] regex/mlx5: pmd improvements Thomas Monjalon

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git