Blame SOURCES/0228-netdrv-net-mlx5-E-Switch-Get-reg_c0-value-on-CQE.patch

d8f823
From 5090598d1fb3b4c5e13188a61519c1a76d07d0be Mon Sep 17 00:00:00 2001
d8f823
From: Alaa Hleihel <ahleihel@redhat.com>
d8f823
Date: Tue, 19 May 2020 07:48:50 -0400
d8f823
Subject: [PATCH 228/312] [netdrv] net/mlx5: E-Switch, Get reg_c0 value on CQE
d8f823
d8f823
Message-id: <20200519074934.6303-20-ahleihel@redhat.com>
d8f823
Patchwork-id: 310522
d8f823
Patchwork-instance: patchwork
d8f823
O-Subject: [RHEL8.3 BZ 1663246 19/63] net/mlx5: E-Switch, Get reg_c0 value on CQE
d8f823
Bugzilla: 1790219 1790218 1663246
d8f823
RH-Acked-by: Marcelo Leitner <mleitner@redhat.com>
d8f823
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
d8f823
RH-Acked-by: John Linville <linville@redhat.com>
d8f823
RH-Acked-by: Ivan Vecera <ivecera@redhat.com>
d8f823
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
d8f823
RH-Acked-by: Kamal Heib <kheib@redhat.com>
d8f823
d8f823
Bugzilla: http://bugzilla.redhat.com/1663246
d8f823
Bugzilla: http://bugzilla.redhat.com/1790219
d8f823
Bugzilla: http://bugzilla.redhat.com/1790218
d8f823
Upstream: v5.7-rc1
d8f823
Conflicts:
d8f823
 - drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
d8f823
   Apply same conflict resolution as done in upstream merge commit:
d8f823
   bf3347c4d15e ("Merge branch 'ct-offload' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux")
d8f823
   ---> Keep OFFLOADS_MAX_FT defined to 2.
d8f823
d8f823
commit 11b717d6152699623fb1133759f9b8f235935a51
d8f823
Author: Paul Blakey <paulb@mellanox.com>
d8f823
Date:   Sun Feb 16 12:01:27 2020 +0200
d8f823
d8f823
    net/mlx5: E-Switch, Get reg_c0 value on CQE
d8f823
d8f823
    On RX side create a restore table in OFFLOADS namespace.
d8f823
    This table will match on all values for reg_c0 we will use,
d8f823
    and set it to the flow_tag. This flow tag can then be read on the CQE.
d8f823
d8f823
    As there is no copy action from reg c0 to flow tag, instead we have to
d8f823
    set the flow tag explictily. We add an API so callers can add all the used
d8f823
    reg_c0 values (tags) and for each of those we add a restore rule.
d8f823
d8f823
    This will be used in a following patch to save the miss chain mapping
d8f823
    tag on reg_c0 and from it restore the tc chain on the skb.
d8f823
d8f823
    Signed-off-by: Paul Blakey <paulb@mellanox.com>
d8f823
    Reviewed-by: Roi Dayan <roid@mellanox.com>
d8f823
    Reviewed-by: Oz Shlomo <ozsh@mellanox.com>
d8f823
    Reviewed-by: Mark Bloch <markb@mellanox.com>
d8f823
    Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
d8f823
d8f823
Signed-off-by: Alaa Hleihel <ahleihel@redhat.com>
d8f823
Signed-off-by: Frantisek Hrbata <fhrbata@redhat.com>
d8f823
---
d8f823
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.h  |  16 +++
d8f823
 .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 147 +++++++++++++++++++--
d8f823
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c  |   4 +-
d8f823
 include/linux/mlx5/eswitch.h                       |   2 +
d8f823
 4 files changed, 158 insertions(+), 11 deletions(-)
d8f823
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
d8f823
index bd229bda630e..a384cab195c1 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
d8f823
@@ -230,6 +230,11 @@ struct mlx5_eswitch_fdb {
d8f823
 };
d8f823
 
d8f823
 struct mlx5_esw_offload {
d8f823
+#ifndef __GENKSYMS__
d8f823
+	struct mlx5_flow_table *ft_offloads_restore;
d8f823
+	struct mlx5_flow_group *restore_group;
d8f823
+#endif
d8f823
+
d8f823
 	struct mlx5_flow_table *ft_offloads;
d8f823
 	struct mlx5_flow_group *vport_rx_group;
d8f823
 	struct mlx5_eswitch_rep *vport_reps;
d8f823
@@ -677,6 +682,11 @@ esw_vport_destroy_offloads_acl_tables(struct mlx5_eswitch *esw,
d8f823
 int mlx5_esw_vport_tbl_get(struct mlx5_eswitch *esw);
d8f823
 void mlx5_esw_vport_tbl_put(struct mlx5_eswitch *esw);
d8f823
 
d8f823
+struct mlx5_flow_handle *
d8f823
+esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag);
d8f823
+u32
d8f823
+esw_get_max_restore_tag(struct mlx5_eswitch *esw);
d8f823
+
d8f823
 #else  /* CONFIG_MLX5_ESWITCH */
d8f823
 /* eswitch API stubs */
d8f823
 static inline int  mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }
d8f823
@@ -692,6 +702,12 @@ static inline const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
d8f823
 
d8f823
 static inline void mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, const int num_vfs) {}
d8f823
 
d8f823
+static struct mlx5_flow_handle *
d8f823
+esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
d8f823
+{
d8f823
+	return ERR_PTR(-EOPNOTSUPP);
d8f823
+}
d8f823
+
d8f823
 #endif /* CONFIG_MLX5_ESWITCH */
d8f823
 
d8f823
 #endif /* __MLX5_ESWITCH_H__ */
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
d8f823
index 0db21244ca31..eab876a2208a 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
d8f823
@@ -1022,6 +1022,54 @@ static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
d8f823
 	return err;
d8f823
 }
d8f823
 
d8f823
+struct mlx5_flow_handle *
d8f823
+esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
d8f823
+{
d8f823
+	struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, };
d8f823
+	struct mlx5_flow_table *ft = esw->offloads.ft_offloads_restore;
d8f823
+	struct mlx5_flow_context *flow_context;
d8f823
+	struct mlx5_flow_handle *flow_rule;
d8f823
+	struct mlx5_flow_destination dest;
d8f823
+	struct mlx5_flow_spec *spec;
d8f823
+	void *misc;
d8f823
+
d8f823
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
d8f823
+	if (!spec)
d8f823
+		return ERR_PTR(-ENOMEM);
d8f823
+
d8f823
+	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
d8f823
+			    misc_parameters_2);
d8f823
+	MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
d8f823
+		 ESW_CHAIN_TAG_METADATA_MASK);
d8f823
+	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
d8f823
+			    misc_parameters_2);
d8f823
+	MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, tag);
d8f823
+	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
d8f823
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
d8f823
+
d8f823
+	flow_context = &spec->flow_context;
d8f823
+	flow_context->flags |= FLOW_CONTEXT_HAS_TAG;
d8f823
+	flow_context->flow_tag = tag;
d8f823
+	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
d8f823
+	dest.ft = esw->offloads.ft_offloads;
d8f823
+
d8f823
+	flow_rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
d8f823
+	kfree(spec);
d8f823
+
d8f823
+	if (IS_ERR(flow_rule))
d8f823
+		esw_warn(esw->dev,
d8f823
+			 "Failed to create restore rule for tag: %d, err(%d)\n",
d8f823
+			 tag, (int)PTR_ERR(flow_rule));
d8f823
+
d8f823
+	return flow_rule;
d8f823
+}
d8f823
+
d8f823
+u32
d8f823
+esw_get_max_restore_tag(struct mlx5_eswitch *esw)
d8f823
+{
d8f823
+	return ESW_CHAIN_TAG_METADATA_MASK;
d8f823
+}
d8f823
+
d8f823
 #define MAX_PF_SQ 256
d8f823
 #define MAX_SQ_NVPORTS 32
d8f823
 
d8f823
@@ -1245,6 +1293,7 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw, int nvports)
d8f823
 	}
d8f823
 
d8f823
 	ft_attr.max_fte = nvports + MLX5_ESW_MISS_FLOWS;
d8f823
+	ft_attr.prio = 1;
d8f823
 
d8f823
 	ft_offloads = mlx5_create_flow_table(ns, &ft_attr);
d8f823
 	if (IS_ERR(ft_offloads)) {
d8f823
@@ -1351,6 +1400,81 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
d8f823
 	return flow_rule;
d8f823
 }
d8f823
 
d8f823
+static void esw_destroy_restore_table(struct mlx5_eswitch *esw)
d8f823
+{
d8f823
+	struct mlx5_esw_offload *offloads = &esw->offloads;
d8f823
+
d8f823
+	mlx5_destroy_flow_group(offloads->restore_group);
d8f823
+	mlx5_destroy_flow_table(offloads->ft_offloads_restore);
d8f823
+}
d8f823
+
d8f823
+static int esw_create_restore_table(struct mlx5_eswitch *esw)
d8f823
+{
d8f823
+	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
d8f823
+	struct mlx5_flow_table_attr ft_attr = {};
d8f823
+	struct mlx5_core_dev *dev = esw->dev;
d8f823
+	struct mlx5_flow_namespace *ns;
d8f823
+	void *match_criteria, *misc;
d8f823
+	struct mlx5_flow_table *ft;
d8f823
+	struct mlx5_flow_group *g;
d8f823
+	u32 *flow_group_in;
d8f823
+	int err = 0;
d8f823
+
d8f823
+	ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
d8f823
+	if (!ns) {
d8f823
+		esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
d8f823
+		return -EOPNOTSUPP;
d8f823
+	}
d8f823
+
d8f823
+	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
d8f823
+	if (!flow_group_in) {
d8f823
+		err = -ENOMEM;
d8f823
+		goto out_free;
d8f823
+	}
d8f823
+
d8f823
+	ft_attr.max_fte = 1 << ESW_CHAIN_TAG_METADATA_BITS;
d8f823
+	ft = mlx5_create_flow_table(ns, &ft_attr);
d8f823
+	if (IS_ERR(ft)) {
d8f823
+		err = PTR_ERR(ft);
d8f823
+		esw_warn(esw->dev, "Failed to create restore table, err %d\n",
d8f823
+			 err);
d8f823
+		goto out_free;
d8f823
+	}
d8f823
+
d8f823
+	memset(flow_group_in, 0, inlen);
d8f823
+	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
d8f823
+				      match_criteria);
d8f823
+	misc = MLX5_ADDR_OF(fte_match_param, match_criteria,
d8f823
+			    misc_parameters_2);
d8f823
+
d8f823
+	MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
d8f823
+		 ESW_CHAIN_TAG_METADATA_MASK);
d8f823
+	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
d8f823
+	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
d8f823
+		 ft_attr.max_fte - 1);
d8f823
+	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
d8f823
+		 MLX5_MATCH_MISC_PARAMETERS_2);
d8f823
+	g = mlx5_create_flow_group(ft, flow_group_in);
d8f823
+	if (IS_ERR(g)) {
d8f823
+		err = PTR_ERR(g);
d8f823
+		esw_warn(dev, "Failed to create restore flow group, err: %d\n",
d8f823
+			 err);
d8f823
+		goto err_group;
d8f823
+	}
d8f823
+
d8f823
+	esw->offloads.ft_offloads_restore = ft;
d8f823
+	esw->offloads.restore_group = g;
d8f823
+
d8f823
+	return 0;
d8f823
+
d8f823
+err_group:
d8f823
+	mlx5_destroy_flow_table(ft);
d8f823
+out_free:
d8f823
+	kvfree(flow_group_in);
d8f823
+
d8f823
+	return err;
d8f823
+}
d8f823
+
d8f823
 static int esw_offloads_start(struct mlx5_eswitch *esw,
d8f823
 			      struct netlink_ext_ack *extack)
d8f823
 {
d8f823
@@ -2122,13 +2246,17 @@ static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
d8f823
 	if (err)
d8f823
 		return err;
d8f823
 
d8f823
-	err = esw_create_offloads_fdb_tables(esw, total_vports);
d8f823
+	err = esw_create_offloads_table(esw, total_vports);
d8f823
 	if (err)
d8f823
-		goto create_fdb_err;
d8f823
+		goto create_offloads_err;
d8f823
 
d8f823
-	err = esw_create_offloads_table(esw, total_vports);
d8f823
+	err = esw_create_restore_table(esw);
d8f823
 	if (err)
d8f823
-		goto create_ft_err;
d8f823
+		goto create_restore_err;
d8f823
+
d8f823
+	err = esw_create_offloads_fdb_tables(esw, total_vports);
d8f823
+	if (err)
d8f823
+		goto create_fdb_err;
d8f823
 
d8f823
 	err = esw_create_vport_rx_group(esw, total_vports);
d8f823
 	if (err)
d8f823
@@ -2140,12 +2268,12 @@ static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
d8f823
 	return 0;
d8f823
 
d8f823
 create_fg_err:
d8f823
-	esw_destroy_offloads_table(esw);
d8f823
-
d8f823
-create_ft_err:
d8f823
 	esw_destroy_offloads_fdb_tables(esw);
d8f823
-
d8f823
 create_fdb_err:
d8f823
+	esw_destroy_restore_table(esw);
d8f823
+create_restore_err:
d8f823
+	esw_destroy_offloads_table(esw);
d8f823
+create_offloads_err:
d8f823
 	esw_destroy_uplink_offloads_acl_tables(esw);
d8f823
 
d8f823
 	return err;
d8f823
@@ -2155,8 +2283,9 @@ static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
d8f823
 {
d8f823
 	mutex_destroy(&esw->fdb_table.offloads.vports.lock);
d8f823
 	esw_destroy_vport_rx_group(esw);
d8f823
-	esw_destroy_offloads_table(esw);
d8f823
 	esw_destroy_offloads_fdb_tables(esw);
d8f823
+	esw_destroy_restore_table(esw);
d8f823
+	esw_destroy_offloads_table(esw);
d8f823
 	esw_destroy_uplink_offloads_acl_tables(esw);
d8f823
 }
d8f823
 
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
d8f823
index 344e5470a81c..f44e366ecfa8 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
d8f823
@@ -111,8 +111,8 @@
d8f823
 #define ANCHOR_MIN_LEVEL (BY_PASS_MIN_LEVEL + 1)
d8f823
 
d8f823
 #define OFFLOADS_MAX_FT 2
d8f823
-#define OFFLOADS_NUM_PRIOS 1
d8f823
-#define OFFLOADS_MIN_LEVEL (ANCHOR_MIN_LEVEL + 1)
d8f823
+#define OFFLOADS_NUM_PRIOS 2
d8f823
+#define OFFLOADS_MIN_LEVEL (ANCHOR_MIN_LEVEL + OFFLOADS_NUM_PRIOS)
d8f823
 
d8f823
 #define LAG_PRIO_NUM_LEVELS 1
d8f823
 #define LAG_NUM_PRIOS 1
d8f823
diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h
d8f823
index 9338c8cc6092..92e39e8a30f0 100644
d8f823
--- a/include/linux/mlx5/eswitch.h
d8f823
+++ b/include/linux/mlx5/eswitch.h
d8f823
@@ -84,6 +84,8 @@ bool mlx5_eswitch_vport_match_metadata_enabled(const struct mlx5_eswitch *esw);
d8f823
 #define ESW_SOURCE_PORT_METADATA_BITS (ESW_VHCA_ID_BITS + ESW_VPORT_BITS)
d8f823
 #define ESW_SOURCE_PORT_METADATA_OFFSET (32 - ESW_SOURCE_PORT_METADATA_BITS)
d8f823
 #define ESW_CHAIN_TAG_METADATA_BITS (32 - ESW_SOURCE_PORT_METADATA_BITS)
d8f823
+#define ESW_CHAIN_TAG_METADATA_MASK GENMASK(ESW_CHAIN_TAG_METADATA_BITS - 1,\
d8f823
+					    0)
d8f823
 
d8f823
 static inline u32 mlx5_eswitch_get_vport_metadata_mask(void)
d8f823
 {
d8f823
-- 
d8f823
2.13.6
d8f823