From: Bing Zhao <bi...@nvidia.com>

The available tags that can be used by the application are fixed
after startup.

A global array is used to store the information and transfer the TAG
item directly from the ID to the REG_C_x.

Signed-off-by: Bing Zhao <bi...@nvidia.com>
---
 drivers/net/mlx5/linux/mlx5_os.c |  2 +
 drivers/net/mlx5/mlx5.c          |  2 +
 drivers/net/mlx5/mlx5.h          |  1 +
 drivers/net/mlx5/mlx5_defs.h     |  2 +
 drivers/net/mlx5/mlx5_flow.c     | 11 +++++
 drivers/net/mlx5/mlx5_flow.h     | 27 ++++++++++++
 drivers/net/mlx5/mlx5_flow_hw.c  | 76 ++++++++++++++++++++++++++++++++
 7 files changed, 121 insertions(+)

diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index d1e7bcce57..12f503474a 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1558,6 +1558,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
                if (priv->vport_meta_mask)
                        flow_hw_set_port_info(eth_dev);
+               /* Only HWS requires this information. */
+               flow_hw_init_tags_set(eth_dev);
                return eth_dev;
 #else
                DRV_LOG(ERR, "DV support is missing for HWS.");
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 1d10932619..b39ef1ecbe 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1945,6 +1945,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
        flow_hw_resource_release(dev);
        flow_hw_clear_port_info(dev);
+       if (priv->sh->config.dv_flow_en == 2)
+               flow_hw_clear_tags_set(dev);
 #endif
        if (priv->rxq_privs != NULL) {
                /* XXX race condition if mlx5_rx_burst() is still running. */
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index c2c3ed81fa..aa328c3bc9 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1205,6 +1205,7 @@ struct mlx5_dev_ctx_shared {
        uint32_t drop_action_check_flag:1; /* Check Flag for drop action. */
        uint32_t flow_priority_check_flag:1; /* Check Flag for flow priority. */
        uint32_t metadata_regc_check_flag:1; /* Check Flag for metadata REGC. */
+       uint32_t hws_tags:1; /* Check if tags info for HWS initialized. */
        uint32_t max_port; /* Maximal IB device port index. */
        struct mlx5_bond_info bond; /* Bonding information. */
        struct mlx5_common_device *cdev; /* Backend mlx5 device. */
diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h
index 018d3f0f0c..585afb0a98 100644
--- a/drivers/net/mlx5/mlx5_defs.h
+++ b/drivers/net/mlx5/mlx5_defs.h
@@ -139,6 +139,8 @@
 #define MLX5_XMETA_MODE_META32 2
 /* Provide info on patrial hw miss. Implies MLX5_XMETA_MODE_META16 */
 #define MLX5_XMETA_MODE_MISS_INFO 3
+/* Only valid in HWS, 32bits extended META without MARK support in FDB. */
+#define MLX5_XMETA_MODE_META32_HWS 4
 
 /* Tx accurate scheduling on timestamps parameters. */
 #define MLX5_TXPP_WAIT_INIT_TS 1000ul /* How long to wait timestamp. */
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 72f4374c07..1543d7f75e 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -39,6 +39,17 @@
  */
 struct flow_hw_port_info mlx5_flow_hw_port_infos[RTE_MAX_ETHPORTS];
 
+/*
+ * A global structure to save the available REG_C_x for tags usage.
+ * The Meter color REG (ASO) and the last available one will be reserved
+ * for PMD internal usage.
+ * Since there is no "port" concept in the driver, it is assumed that the
+ * available tags set will be the minimum intersection.
+ * 3 - in FDB mode / 5 - in legacy mode
+ */
+uint32_t mlx5_flow_hw_avl_tags_init_cnt;
+enum modify_reg mlx5_flow_hw_avl_tags[MLX5_FLOW_HW_TAGS_MAX] = {REG_NON};
+
 struct tunnel_default_miss_ctx {
        uint16_t *queue;
        __extension__
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index c0c719dd8b..98ae7c6bda 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1334,6 +1334,10 @@ struct flow_hw_port_info {
 
 extern struct flow_hw_port_info mlx5_flow_hw_port_infos[RTE_MAX_ETHPORTS];
 
+#define MLX5_FLOW_HW_TAGS_MAX 8
+extern uint32_t mlx5_flow_hw_avl_tags_init_cnt;
+extern enum modify_reg mlx5_flow_hw_avl_tags[];
+
 /*
  * Get metadata match tag and mask for given rte_eth_dev port.
  * Used in HWS rule creation.
@@ -1375,9 +1379,32 @@ flow_hw_get_wire_port(struct ibv_context *ibctx)
 }
 #endif
 
+/*
+ * Convert metadata or tag to the actual register.
+ * META: Can only be used to match in the FDB in this stage, fixed C_1.
+ * TAG: C_x expect meter color reg and the reserved ones.
+ * TODO: Per port / device, FDB or NIC for Meta matching.
+ */
+static __rte_always_inline int
+flow_hw_get_reg_id(enum rte_flow_item_type type, uint32_t id)
+{
+       switch (type) {
+       case RTE_FLOW_ITEM_TYPE_META:
+               return REG_C_1;
+       case RTE_FLOW_ITEM_TYPE_TAG:
+               MLX5_ASSERT(id < MLX5_FLOW_HW_TAGS_MAX);
+               return mlx5_flow_hw_avl_tags[id];
+       default:
+               return REG_NON;
+       }
+}
+
 void flow_hw_set_port_info(struct rte_eth_dev *dev);
 void flow_hw_clear_port_info(struct rte_eth_dev *dev);
 
+void flow_hw_init_tags_set(struct rte_eth_dev *dev);
+void flow_hw_clear_tags_set(struct rte_eth_dev *dev);
+
 typedef int (*mlx5_flow_validate_t)(struct rte_eth_dev *dev,
                                    const struct rte_flow_attr *attr,
                                    const struct rte_flow_item items[],
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 765e5164cb..03725649c8 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -2240,6 +2240,82 @@ flow_hw_clear_port_info(struct rte_eth_dev *dev)
        info->is_wire = 0;
 }
 
+/*
+ * Initialize the information of available tag registers and an intersection
+ * of all the probed devices' REG_C_Xs.
+ * PS. No port concept in steering part, right now it cannot be per port level.
+ *
+ * @param[in] dev
+ *   Pointer to the rte_eth_dev structure.
+ */
+void flow_hw_init_tags_set(struct rte_eth_dev *dev)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       uint32_t meta_mode = priv->sh->config.dv_xmeta_en;
+       uint8_t masks = (uint8_t)priv->sh->cdev->config.hca_attr.set_reg_c;
+       uint32_t i, j;
+       enum modify_reg copy[MLX5_FLOW_HW_TAGS_MAX] = {REG_NON};
+       uint8_t unset = 0;
+       uint8_t copy_masks = 0;
+
+       /*
+        * The CAPA is global for common device but only used in net.
+        * It is shared per eswitch domain.
+        */
+       if (!!priv->sh->hws_tags)
+               return;
+       unset |= 1 << (priv->mtr_color_reg - REG_C_0);
+       unset |= 1 << (REG_C_6 - REG_C_0);
+       if (meta_mode == MLX5_XMETA_MODE_META32_HWS) {
+               unset |= 1 << (REG_C_1 - REG_C_0);
+               unset |= 1 << (REG_C_0 - REG_C_0);
+       }
+       masks &= ~unset;
+       if (mlx5_flow_hw_avl_tags_init_cnt) {
+               for (i = 0; i < MLX5_FLOW_HW_TAGS_MAX; i++) {
+                       if (mlx5_flow_hw_avl_tags[i] != REG_NON && !!((1 << i) 
& masks)) {
+                               copy[mlx5_flow_hw_avl_tags[i] - REG_C_0] =
+                                               mlx5_flow_hw_avl_tags[i];
+                               copy_masks |= (1 << i);
+                       }
+               }
+               if (copy_masks != masks) {
+                       j = 0;
+                       for (i = 0; i < MLX5_FLOW_HW_TAGS_MAX; i++)
+                               if (!!((1 << i) & copy_masks))
+                                       mlx5_flow_hw_avl_tags[j++] = copy[i];
+               }
+       } else {
+               j = 0;
+               for (i = 0; i < MLX5_FLOW_HW_TAGS_MAX; i++) {
+                       if (!!((1 << i) & masks))
+                               mlx5_flow_hw_avl_tags[j++] =
+                                       (enum modify_reg)(i + 
(uint32_t)REG_C_0);
+               }
+       }
+       priv->sh->hws_tags = 1;
+       mlx5_flow_hw_avl_tags_init_cnt++;
+}
+
+/*
+ * Reset the available tag registers information to NONE.
+ *
+ * @param[in] dev
+ *   Pointer to the rte_eth_dev structure.
+ */
+void flow_hw_clear_tags_set(struct rte_eth_dev *dev)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+
+       if (!priv->sh->hws_tags)
+               return;
+       priv->sh->hws_tags = 0;
+       mlx5_flow_hw_avl_tags_init_cnt--;
+       if (!mlx5_flow_hw_avl_tags_init_cnt)
+               memset(mlx5_flow_hw_avl_tags, REG_NON,
+                      sizeof(enum modify_reg) * MLX5_FLOW_HW_TAGS_MAX);
+}
+
 /**
  * Create shared action.
  *
-- 
2.18.1

Reply via email to