net/mlx5e: Pass actions param to actions_match_supported()
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / en / tc / post_act.c
CommitLineData
6f0b692a
CM
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
f0da4daa 4#include "en_tc.h"
6f0b692a
CM
5#include "post_act.h"
6#include "mlx5_core.h"
ae2ee3be 7#include "fs_core.h"
6f0b692a
CM
8
9struct mlx5e_post_act {
10 enum mlx5_flow_namespace_type ns_type;
11 struct mlx5_fs_chains *chains;
12 struct mlx5_flow_table *ft;
13 struct mlx5e_priv *priv;
f0da4daa 14 struct xarray ids;
6f0b692a
CM
15};
16
f0da4daa
CM
17struct mlx5e_post_act_handle {
18 enum mlx5_flow_namespace_type ns_type;
19 struct mlx5_flow_attr *attr;
20 struct mlx5_flow_handle *rule;
21 u32 id;
22};
23
24#define MLX5_POST_ACTION_BITS (mlx5e_tc_attr_to_reg_mappings[FTEID_TO_REG].mlen)
25#define MLX5_POST_ACTION_MAX GENMASK(MLX5_POST_ACTION_BITS - 1, 0)
26#define MLX5_POST_ACTION_MASK MLX5_POST_ACTION_MAX
27
6f0b692a
CM
28struct mlx5e_post_act *
29mlx5e_tc_post_act_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains,
30 enum mlx5_flow_namespace_type ns_type)
31{
ae2ee3be
PB
32 enum fs_flow_table_type table_type = ns_type == MLX5_FLOW_NAMESPACE_FDB ?
33 FS_FT_FDB : FS_FT_NIC_RX;
6f0b692a
CM
34 struct mlx5e_post_act *post_act;
35 int err;
36
ae2ee3be
PB
37 if (!MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, ignore_flow_level, table_type)) {
38 if (priv->mdev->coredev_type != MLX5_COREDEV_VF)
39 mlx5_core_warn(priv->mdev, "firmware level support is missing\n");
6f0b692a
CM
40 err = -EOPNOTSUPP;
41 goto err_check;
42 }
43
44 post_act = kzalloc(sizeof(*post_act), GFP_KERNEL);
45 if (!post_act) {
46 err = -ENOMEM;
47 goto err_check;
48 }
49 post_act->ft = mlx5_chains_create_global_table(chains);
50 if (IS_ERR(post_act->ft)) {
51 err = PTR_ERR(post_act->ft);
52 mlx5_core_warn(priv->mdev, "failed to create post action table, err: %d\n", err);
53 goto err_ft;
54 }
55 post_act->chains = chains;
56 post_act->ns_type = ns_type;
57 post_act->priv = priv;
f0da4daa 58 xa_init_flags(&post_act->ids, XA_FLAGS_ALLOC1);
6f0b692a
CM
59 return post_act;
60
61err_ft:
62 kfree(post_act);
63err_check:
64 return ERR_PTR(err);
65}
66
67void
68mlx5e_tc_post_act_destroy(struct mlx5e_post_act *post_act)
69{
70 if (IS_ERR_OR_NULL(post_act))
71 return;
72
f0da4daa 73 xa_destroy(&post_act->ids);
6f0b692a
CM
74 mlx5_chains_destroy_global_table(post_act->chains, post_act->ft);
75 kfree(post_act);
76}
f0da4daa
CM
77
78struct mlx5e_post_act_handle *
79mlx5e_tc_post_act_add(struct mlx5e_post_act *post_act, struct mlx5_flow_attr *attr)
80{
81 u32 attr_sz = ns_to_attr_sz(post_act->ns_type);
82 struct mlx5e_post_act_handle *handle = NULL;
83 struct mlx5_flow_attr *post_attr = NULL;
84 struct mlx5_flow_spec *spec = NULL;
85 int err;
86
87 handle = kzalloc(sizeof(*handle), GFP_KERNEL);
88 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
89 post_attr = mlx5_alloc_flow_attr(post_act->ns_type);
90 if (!handle || !spec || !post_attr) {
91 kfree(post_attr);
92 kvfree(spec);
93 kfree(handle);
94 return ERR_PTR(-ENOMEM);
95 }
96
97 memcpy(post_attr, attr, attr_sz);
98 post_attr->chain = 0;
99 post_attr->prio = 0;
100 post_attr->ft = post_act->ft;
101 post_attr->inner_match_level = MLX5_MATCH_NONE;
102 post_attr->outer_match_level = MLX5_MATCH_NONE;
103 post_attr->action &= ~(MLX5_FLOW_CONTEXT_ACTION_DECAP);
84ba8062 104 post_attr->flags &= ~MLX5_ATTR_FLAG_SAMPLE;
f0da4daa
CM
105
106 handle->ns_type = post_act->ns_type;
107 /* Splits were handled before post action */
108 if (handle->ns_type == MLX5_FLOW_NAMESPACE_FDB)
109 post_attr->esw_attr->split_count = 0;
110
111 err = xa_alloc(&post_act->ids, &handle->id, post_attr,
112 XA_LIMIT(1, MLX5_POST_ACTION_MAX), GFP_KERNEL);
113 if (err)
114 goto err_xarray;
115
116 /* Post action rule matches on fte_id and executes original rule's
117 * tc rule action
118 */
119 mlx5e_tc_match_to_reg_match(spec, FTEID_TO_REG,
120 handle->id, MLX5_POST_ACTION_MASK);
121
122 handle->rule = mlx5_tc_rule_insert(post_act->priv, spec, post_attr);
123 if (IS_ERR(handle->rule)) {
124 err = PTR_ERR(handle->rule);
125 netdev_warn(post_act->priv->netdev, "Failed to add post action rule");
126 goto err_rule;
127 }
128 handle->attr = post_attr;
129
130 kvfree(spec);
131 return handle;
132
133err_rule:
134 xa_erase(&post_act->ids, handle->id);
135err_xarray:
136 kfree(post_attr);
137 kvfree(spec);
138 kfree(handle);
139 return ERR_PTR(err);
140}
141
142void
143mlx5e_tc_post_act_del(struct mlx5e_post_act *post_act, struct mlx5e_post_act_handle *handle)
144{
145 mlx5_tc_rule_delete(post_act->priv, handle->rule, handle->attr);
146 xa_erase(&post_act->ids, handle->id);
147 kfree(handle->attr);
148 kfree(handle);
149}
150
151struct mlx5_flow_table *
152mlx5e_tc_post_act_get_ft(struct mlx5e_post_act *post_act)
153{
154 return post_act->ft;
155}
156
157/* Allocate a header modify action to write the post action handle fte id to a register. */
158int
159mlx5e_tc_post_act_set_handle(struct mlx5_core_dev *dev,
160 struct mlx5e_post_act_handle *handle,
161 struct mlx5e_tc_mod_hdr_acts *acts)
162{
163 return mlx5e_tc_match_to_reg_set(dev, acts, handle->ns_type, FTEID_TO_REG, handle->id);
164}