[v1,06/19] net/mlx5: provide the available tag registers
Checks
Commit Message
From: Bing Zhao <bingz@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 <bingz@nvidia.com>
---
drivers/net/mlx5/linux/mlx5_os.c | 5 ++-
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, 123 insertions(+), 1 deletion(-)
@@ -1542,8 +1542,11 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
rte_rwlock_init(&priv->ind_tbls_lock);
if (priv->vport_meta_mask)
flow_hw_set_port_info(eth_dev);
- if (priv->sh->config.dv_flow_en == 2)
+ if (priv->sh->config.dv_flow_en == 2) {
+ /* Only HWS requires this information. */
+ flow_hw_init_tags_set(eth_dev);
return eth_dev;
+ }
/* Port representor shares the same max priority with pf port. */
if (!priv->sh->flow_priority_check_flag) {
/* Supported Verbs flow priority number detection. */
@@ -1946,6 +1946,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
flow_hw_resource_release(dev);
#endif
flow_hw_clear_port_info(dev);
+ if (priv->sh->config.dv_flow_en == 2)
+ flow_hw_clear_tags_set(dev);
if (priv->rxq_privs != NULL) {
/* XXX race condition if mlx5_rx_burst() is still running. */
rte_delay_us_sleep(1000);
@@ -1200,6 +1200,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. */
@@ -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. */
@@ -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__
@@ -1328,6 +1328,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.
@@ -1367,9 +1371,32 @@ flow_hw_get_wire_port(struct ibv_context *ibctx)
return NULL;
}
+/*
+ * 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[],
@@ -2237,6 +2237,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.
*