]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
net/mlx5: E-Switch, Add offloads table
[mirror_ubuntu-eoan-kernel.git] / drivers / net / ethernet / mellanox / mlx5 / core / eswitch_offloads.c
CommitLineData
69697b6e
OG
1/*
2 * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33#include <linux/etherdevice.h>
34#include <linux/mlx5/driver.h>
35#include <linux/mlx5/mlx5_ifc.h>
36#include <linux/mlx5/vport.h>
37#include <linux/mlx5/fs.h>
38#include "mlx5_core.h"
39#include "eswitch.h"
40
ab22be9b
OG
41struct mlx5_flow_rule *
42mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn)
43{
44 struct mlx5_flow_destination dest;
45 struct mlx5_flow_rule *flow_rule;
46 int match_header = MLX5_MATCH_MISC_PARAMETERS;
47 u32 *match_v, *match_c;
48 void *misc;
49
50 match_v = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
51 match_c = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
52 if (!match_v || !match_c) {
53 esw_warn(esw->dev, "FDB: Failed to alloc match parameters\n");
54 flow_rule = ERR_PTR(-ENOMEM);
55 goto out;
56 }
57
58 misc = MLX5_ADDR_OF(fte_match_param, match_v, misc_parameters);
59 MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn);
60 MLX5_SET(fte_match_set_misc, misc, source_port, 0x0); /* source vport is 0 */
61
62 misc = MLX5_ADDR_OF(fte_match_param, match_c, misc_parameters);
63 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn);
64 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
65
66 dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
67 dest.vport_num = vport;
68
69 flow_rule = mlx5_add_flow_rule(esw->fdb_table.fdb, match_header, match_c,
70 match_v, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
71 0, &dest);
72 if (IS_ERR(flow_rule))
73 esw_warn(esw->dev, "FDB: Failed to add send to vport rule err %ld\n", PTR_ERR(flow_rule));
74out:
75 kfree(match_v);
76 kfree(match_c);
77 return flow_rule;
78}
79
3aa33572
OG
80static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
81{
82 struct mlx5_flow_destination dest;
83 struct mlx5_flow_rule *flow_rule = NULL;
84 u32 *match_v, *match_c;
85 int err = 0;
86
87 match_v = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
88 match_c = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
89 if (!match_v || !match_c) {
90 esw_warn(esw->dev, "FDB: Failed to alloc match parameters\n");
91 err = -ENOMEM;
92 goto out;
93 }
94
95 dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
96 dest.vport_num = 0;
97
98 flow_rule = mlx5_add_flow_rule(esw->fdb_table.fdb, 0, match_c, match_v,
99 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, 0, &dest);
100 if (IS_ERR(flow_rule)) {
101 err = PTR_ERR(flow_rule);
102 esw_warn(esw->dev, "FDB: Failed to add miss flow rule err %d\n", err);
103 goto out;
104 }
105
106 esw->fdb_table.offloads.miss_rule = flow_rule;
107out:
108 kfree(match_v);
109 kfree(match_c);
110 return err;
111}
112
69697b6e
OG
113#define MAX_PF_SQ 256
114
115int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
116{
117 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
118 struct mlx5_core_dev *dev = esw->dev;
119 struct mlx5_flow_namespace *root_ns;
120 struct mlx5_flow_table *fdb = NULL;
121 struct mlx5_flow_group *g;
122 u32 *flow_group_in;
123 void *match_criteria;
124 int table_size, ix, err = 0;
125
126 flow_group_in = mlx5_vzalloc(inlen);
127 if (!flow_group_in)
128 return -ENOMEM;
129
130 root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
131 if (!root_ns) {
132 esw_warn(dev, "Failed to get FDB flow namespace\n");
133 goto ns_err;
134 }
135
136 esw_debug(dev, "Create offloads FDB table, log_max_size(%d)\n",
137 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
138
139 table_size = nvports + MAX_PF_SQ + 1;
140 fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0);
141 if (IS_ERR(fdb)) {
142 err = PTR_ERR(fdb);
143 esw_warn(dev, "Failed to create FDB Table err %d\n", err);
144 goto fdb_err;
145 }
146 esw->fdb_table.fdb = fdb;
147
148 /* create send-to-vport group */
149 memset(flow_group_in, 0, inlen);
150 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
151 MLX5_MATCH_MISC_PARAMETERS);
152
153 match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
154
155 MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_sqn);
156 MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
157
158 ix = nvports + MAX_PF_SQ;
159 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
160 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix - 1);
161
162 g = mlx5_create_flow_group(fdb, flow_group_in);
163 if (IS_ERR(g)) {
164 err = PTR_ERR(g);
165 esw_warn(dev, "Failed to create send-to-vport flow group err(%d)\n", err);
166 goto send_vport_err;
167 }
168 esw->fdb_table.offloads.send_to_vport_grp = g;
169
170 /* create miss group */
171 memset(flow_group_in, 0, inlen);
172 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, 0);
173
174 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
175 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix + 1);
176
177 g = mlx5_create_flow_group(fdb, flow_group_in);
178 if (IS_ERR(g)) {
179 err = PTR_ERR(g);
180 esw_warn(dev, "Failed to create miss flow group err(%d)\n", err);
181 goto miss_err;
182 }
183 esw->fdb_table.offloads.miss_grp = g;
184
3aa33572
OG
185 err = esw_add_fdb_miss_rule(esw);
186 if (err)
187 goto miss_rule_err;
188
69697b6e
OG
189 return 0;
190
3aa33572
OG
191miss_rule_err:
192 mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
69697b6e
OG
193miss_err:
194 mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
195send_vport_err:
196 mlx5_destroy_flow_table(fdb);
197fdb_err:
198ns_err:
199 kvfree(flow_group_in);
200 return err;
201}
202
203void esw_destroy_offloads_fdb_table(struct mlx5_eswitch *esw)
204{
205 if (!esw->fdb_table.fdb)
206 return;
207
208 esw_debug(esw->dev, "Destroy offloads FDB Table\n");
3aa33572 209 mlx5_del_flow_rule(esw->fdb_table.offloads.miss_rule);
69697b6e
OG
210 mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
211 mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
212
213 mlx5_destroy_flow_table(esw->fdb_table.fdb);
214}
c116c6ee
OG
215
216static int esw_create_offloads_table(struct mlx5_eswitch *esw)
217{
218 struct mlx5_flow_namespace *ns;
219 struct mlx5_flow_table *ft_offloads;
220 struct mlx5_core_dev *dev = esw->dev;
221 int err = 0;
222
223 ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
224 if (!ns) {
225 esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
226 return -ENOMEM;
227 }
228
229 ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0);
230 if (IS_ERR(ft_offloads)) {
231 err = PTR_ERR(ft_offloads);
232 esw_warn(esw->dev, "Failed to create offloads table, err %d\n", err);
233 return err;
234 }
235
236 esw->offloads.ft_offloads = ft_offloads;
237 return 0;
238}
239
240static void esw_destroy_offloads_table(struct mlx5_eswitch *esw)
241{
242 struct mlx5_esw_offload *offloads = &esw->offloads;
243
244 mlx5_destroy_flow_table(offloads->ft_offloads);
245}