net/mlx5e: Add TC tunnel release action for SRIOV offloads
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx5 / core / eswitch_offloads.c
index c55ad8d00c05714710b36b568ed57ab1026bd8cb..c2dc470bdff3ff4c8fe9ff912d332d1bab3503ce 100644 (file)
@@ -43,32 +43,35 @@ enum {
        FDB_SLOW_PATH
 };
 
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
 mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
                                struct mlx5_flow_spec *spec,
                                struct mlx5_esw_flow_attr *attr)
 {
-       struct mlx5_flow_destination dest = { 0 };
+       struct mlx5_flow_destination dest[2] = {};
+       struct mlx5_flow_act flow_act = {0};
        struct mlx5_fc *counter = NULL;
-       struct mlx5_flow_rule *rule;
+       struct mlx5_flow_handle *rule;
        void *misc;
-       int action;
+       int i = 0;
 
        if (esw->mode != SRIOV_OFFLOADS)
                return ERR_PTR(-EOPNOTSUPP);
 
-       action = attr->action;
+       flow_act.action = attr->action;
 
-       if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
-               dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
-               dest.vport_num = attr->out_rep->vport;
-               action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
-       } else if (action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
+               dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
+               dest[i].vport_num = attr->out_rep->vport;
+               i++;
+       }
+       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
                counter = mlx5_fc_create(esw->dev, true);
                if (IS_ERR(counter))
                        return ERR_CAST(counter);
-               dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-               dest.counter = counter;
+               dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+               dest[i].counter = counter;
+               i++;
        }
 
        misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
@@ -79,10 +82,11 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 
        spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
                                      MLX5_MATCH_MISC_PARAMETERS;
+       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
+               spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
 
-       rule = mlx5_add_flow_rule((struct mlx5_flow_table *)esw->fdb_table.fdb,
-                                 spec, action, 0, &dest);
-
+       rule = mlx5_add_flow_rules((struct mlx5_flow_table *)esw->fdb_table.fdb,
+                                  spec, &flow_act, dest, i);
        if (IS_ERR(rule))
                mlx5_fc_destroy(esw->dev, counter);
 
@@ -269,11 +273,12 @@ out:
        return err;
 }
 
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
 mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn)
 {
+       struct mlx5_flow_act flow_act = {0};
        struct mlx5_flow_destination dest;
-       struct mlx5_flow_rule *flow_rule;
+       struct mlx5_flow_handle *flow_rule;
        struct mlx5_flow_spec *spec;
        void *misc;
 
@@ -295,10 +300,10 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn
        spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
        dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
        dest.vport_num = vport;
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 
-       flow_rule = mlx5_add_flow_rule(esw->fdb_table.offloads.fdb, spec,
-                                      MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-                                      0, &dest);
+       flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.fdb, spec,
+                                       &flow_act, &dest, 1);
        if (IS_ERR(flow_rule))
                esw_warn(esw->dev, "FDB: Failed to add send to vport rule err %ld\n", PTR_ERR(flow_rule));
 out:
@@ -315,7 +320,7 @@ void mlx5_eswitch_sqs2vport_stop(struct mlx5_eswitch *esw,
                return;
 
        list_for_each_entry_safe(esw_sq, tmp, &rep->vport_sqs_list, list) {
-               mlx5_del_flow_rule(esw_sq->send_to_vport_rule);
+               mlx5_del_flow_rules(esw_sq->send_to_vport_rule);
                list_del(&esw_sq->list);
                kfree(esw_sq);
        }
@@ -325,7 +330,7 @@ int mlx5_eswitch_sqs2vport_start(struct mlx5_eswitch *esw,
                                 struct mlx5_eswitch_rep *rep,
                                 u16 *sqns_array, int sqns_num)
 {
-       struct mlx5_flow_rule *flow_rule;
+       struct mlx5_flow_handle *flow_rule;
        struct mlx5_esw_sq *esw_sq;
        int err;
        int i;
@@ -361,8 +366,9 @@ out_err:
 
 static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
 {
+       struct mlx5_flow_act flow_act = {0};
        struct mlx5_flow_destination dest;
-       struct mlx5_flow_rule *flow_rule = NULL;
+       struct mlx5_flow_handle *flow_rule = NULL;
        struct mlx5_flow_spec *spec;
        int err = 0;
 
@@ -375,10 +381,10 @@ static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
 
        dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
        dest.vport_num = 0;
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 
-       flow_rule = mlx5_add_flow_rule(esw->fdb_table.offloads.fdb, spec,
-                                      MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-                                      0, &dest);
+       flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.fdb, spec,
+                                       &flow_act, &dest, 1);
        if (IS_ERR(flow_rule)) {
                err = PTR_ERR(flow_rule);
                esw_warn(esw->dev,  "FDB: Failed to add miss flow rule err %d\n", err);
@@ -405,6 +411,7 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
        u32 *flow_group_in;
        void *match_criteria;
        int table_size, ix, err = 0;
+       u32 flags = 0;
 
        flow_group_in = mlx5_vzalloc(inlen);
        if (!flow_group_in)
@@ -419,9 +426,14 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
        esw_debug(dev, "Create offloads FDB table, log_max_size(%d)\n",
                  MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
 
+       if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) &&
+           MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
+               flags |= MLX5_FLOW_TABLE_TUNNEL_EN;
+
        fdb = mlx5_create_auto_grouped_flow_table(root_ns, FDB_FAST_PATH,
                                                  ESW_OFFLOADS_NUM_ENTRIES,
-                                                 ESW_OFFLOADS_NUM_GROUPS, 0);
+                                                 ESW_OFFLOADS_NUM_GROUPS, 0,
+                                                 flags);
        if (IS_ERR(fdb)) {
                err = PTR_ERR(fdb);
                esw_warn(dev, "Failed to create Fast path FDB Table err %d\n", err);
@@ -430,7 +442,7 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
        esw->fdb_table.fdb = fdb;
 
        table_size = nvports + MAX_PF_SQ + 1;
-       fdb = mlx5_create_flow_table(root_ns, FDB_SLOW_PATH, table_size, 0);
+       fdb = mlx5_create_flow_table(root_ns, FDB_SLOW_PATH, table_size, 0, 0);
        if (IS_ERR(fdb)) {
                err = PTR_ERR(fdb);
                esw_warn(dev, "Failed to create slow path FDB Table err %d\n", err);
@@ -501,7 +513,7 @@ static void esw_destroy_offloads_fdb_table(struct mlx5_eswitch *esw)
                return;
 
        esw_debug(esw->dev, "Destroy offloads FDB Table\n");
-       mlx5_del_flow_rule(esw->fdb_table.offloads.miss_rule);
+       mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule);
        mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
        mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
 
@@ -522,7 +534,7 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw)
                return -ENOMEM;
        }
 
-       ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0);
+       ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0, 0);
        if (IS_ERR(ft_offloads)) {
                err = PTR_ERR(ft_offloads);
                esw_warn(esw->dev, "Failed to create offloads table, err %d\n", err);
@@ -585,11 +597,12 @@ static void esw_destroy_vport_rx_group(struct mlx5_eswitch *esw)
        mlx5_destroy_flow_group(esw->offloads.vport_rx_group);
 }
 
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
 mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn)
 {
+       struct mlx5_flow_act flow_act = {0};
        struct mlx5_flow_destination dest;
-       struct mlx5_flow_rule *flow_rule;
+       struct mlx5_flow_handle *flow_rule;
        struct mlx5_flow_spec *spec;
        void *misc;
 
@@ -610,9 +623,9 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn)
        dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
        dest.tir_num = tirn;
 
-       flow_rule = mlx5_add_flow_rule(esw->offloads.ft_offloads, spec,
-                                      MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-                                      0, &dest);
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+       flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
+                                      &flow_act, &dest, 1);
        if (IS_ERR(flow_rule)) {
                esw_warn(esw->dev, "fs offloads: Failed to add vport rx rule err %ld\n", PTR_ERR(flow_rule));
                goto out;