1 /*-
2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD$
26 */
27
28 #include "opt_rss.h"
29 #include "opt_ratelimit.h"
30
31 #include <linux/types.h>
32 #include <linux/module.h>
33 #include <dev/mlx5/mlx5_ifc.h>
34 #include <dev/mlx5/device.h>
35 #include <dev/mlx5/fs.h>
36
37 #include <dev/mlx5/mlx5_core/fs_core.h>
38 #include <dev/mlx5/mlx5_core/mlx5_core.h>
39
40 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
41 enum fs_ft_type type,
42 unsigned int id)
43 {
44 u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {0};
45 u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0};
46
47 if (!dev)
48 return -EINVAL;
49
50 MLX5_SET(set_flow_table_root_in, in, opcode,
51 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
52 MLX5_SET(set_flow_table_root_in, in, table_type, type);
53 MLX5_SET(set_flow_table_root_in, in, table_id, id);
54
55 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
56 }
57
58 int mlx5_cmd_fs_create_ft(struct mlx5_core_dev *dev,
59 u16 vport,
60 enum fs_ft_type type, unsigned int level,
61 unsigned int log_size, unsigned int *table_id)
62 {
63 u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0};
64 u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
65 int err;
66
67 if (!dev)
68 return -EINVAL;
69
70 MLX5_SET(create_flow_table_in, in, opcode,
71 MLX5_CMD_OP_CREATE_FLOW_TABLE);
72
73 MLX5_SET(create_flow_table_in, in, table_type, type);
74 MLX5_SET(create_flow_table_in, in, flow_table_context.level, level);
75 MLX5_SET(create_flow_table_in, in, flow_table_context.log_size,
76 log_size);
77 if (vport) {
78 MLX5_SET(create_flow_table_in, in, vport_number, vport);
79 MLX5_SET(create_flow_table_in, in, other_vport, 1);
80 }
81
82 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
83 if (!err)
84 *table_id = MLX5_GET(create_flow_table_out, out, table_id);
85
86 return err;
87 }
88
89 int mlx5_cmd_fs_destroy_ft(struct mlx5_core_dev *dev,
90 u16 vport,
91 enum fs_ft_type type, unsigned int table_id)
92 {
93 u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {0};
94 u32 out[MLX5_ST_SZ_DW(destroy_flow_table_out)] = {0};
95
96 if (!dev)
97 return -EINVAL;
98
99 MLX5_SET(destroy_flow_table_in, in, opcode,
100 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
101 MLX5_SET(destroy_flow_table_in, in, table_type, type);
102 MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
103 if (vport) {
104 MLX5_SET(destroy_flow_table_in, in, vport_number, vport);
105 MLX5_SET(destroy_flow_table_in, in, other_vport, 1);
106 }
107
108 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
109 }
110
111 int mlx5_cmd_fs_create_fg(struct mlx5_core_dev *dev,
112 u32 *in,
113 u16 vport,
114 enum fs_ft_type type, unsigned int table_id,
115 unsigned int *group_id)
116 {
117 u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0};
118 int err;
119 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
120 if (!dev)
121 return -EINVAL;
122
123 MLX5_SET(create_flow_group_in, in, opcode,
124 MLX5_CMD_OP_CREATE_FLOW_GROUP);
125 MLX5_SET(create_flow_group_in, in, table_type, type);
126 MLX5_SET(create_flow_group_in, in, table_id, table_id);
127 if (vport) {
128 MLX5_SET(create_flow_group_in, in, vport_number, vport);
129 MLX5_SET(create_flow_group_in, in, other_vport, 1);
130 }
131
132 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
133 if (!err)
134 *group_id = MLX5_GET(create_flow_group_out, out, group_id);
135
136 return err;
137 }
138
139 int mlx5_cmd_fs_destroy_fg(struct mlx5_core_dev *dev,
140 u16 vport,
141 enum fs_ft_type type, unsigned int table_id,
142 unsigned int group_id)
143 {
144 u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {0};
145 u32 out[MLX5_ST_SZ_DW(destroy_flow_group_out)] = {0};
146
147 if (!dev)
148 return -EINVAL;
149
150 MLX5_SET(destroy_flow_group_in, in, opcode,
151 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
152 MLX5_SET(destroy_flow_group_in, in, table_type, type);
153 MLX5_SET(destroy_flow_group_in, in, table_id, table_id);
154 MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
155 if (vport) {
156 MLX5_SET(destroy_flow_group_in, in, vport_number, vport);
157 MLX5_SET(destroy_flow_group_in, in, other_vport, 1);
158 }
159
160 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
161 }
162
163 int mlx5_cmd_fs_set_fte(struct mlx5_core_dev *dev,
164 u16 vport,
165 enum fs_fte_status *fte_status,
166 u32 *match_val,
167 enum fs_ft_type type, unsigned int table_id,
168 unsigned int index, unsigned int group_id,
169 unsigned int flow_tag,
170 unsigned short action, int dest_size,
171 struct list_head *dests) /* mlx5_flow_desination */
172 {
173 u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
174 u32 *in;
175 unsigned int inlen;
176 struct mlx5_flow_rule *dst;
177 void *in_flow_context;
178 void *in_match_value;
179 void *in_dests;
180 int err;
181 int opmod = 0;
182 int modify_mask = 0;
183 int atomic_mod_cap;
184
185 if (action != MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)
186 dest_size = 0;
187
188 inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
189 dest_size * MLX5_ST_SZ_BYTES(dest_format_struct);
190
191 if (!dev)
192 return -EINVAL;
193
194 if (*fte_status & FS_FTE_STATUS_EXISTING) {
195 atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev,
196 flow_table_properties_nic_receive.
197 flow_modify_en);
198 if (!atomic_mod_cap)
199 return -ENOTSUPP;
200 opmod = 1;
201 modify_mask = 1 <<
202 MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST;
203 }
204
205 in = mlx5_vzalloc(inlen);
206 if (!in) {
207 mlx5_core_warn(dev, "failed to allocate inbox\n");
208 return -ENOMEM;
209 }
210
211 MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
212 MLX5_SET(set_fte_in, in, op_mod, opmod);
213 MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask);
214 MLX5_SET(set_fte_in, in, table_type, type);
215 MLX5_SET(set_fte_in, in, table_id, table_id);
216 MLX5_SET(set_fte_in, in, flow_index, index);
217 if (vport) {
218 MLX5_SET(set_fte_in, in, vport_number, vport);
219 MLX5_SET(set_fte_in, in, other_vport, 1);
220 }
221
222 in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
223 MLX5_SET(flow_context, in_flow_context, group_id, group_id);
224 MLX5_SET(flow_context, in_flow_context, flow_tag, flow_tag);
225 MLX5_SET(flow_context, in_flow_context, action, action);
226 MLX5_SET(flow_context, in_flow_context, destination_list_size,
227 dest_size);
228 in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
229 match_value);
230 memcpy(in_match_value, match_val, MLX5_ST_SZ_BYTES(fte_match_param));
231 if (dest_size) {
232 in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
233 list_for_each_entry(dst, dests, base.list) {
234 unsigned int id;
235
236 MLX5_SET(dest_format_struct, in_dests, destination_type,
237 dst->dest_attr.type);
238 if (dst->dest_attr.type ==
239 MLX5_FLOW_CONTEXT_DEST_TYPE_FLOW_TABLE)
240 id = dst->dest_attr.ft->id;
241 else
242 id = dst->dest_attr.tir_num;
243 MLX5_SET(dest_format_struct, in_dests, destination_id, id);
244 in_dests += MLX5_ST_SZ_BYTES(dest_format_struct);
245 }
246 }
247
248 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
249 if (!err)
250 *fte_status |= FS_FTE_STATUS_EXISTING;
251
252 kvfree(in);
253
254 return err;
255 }
256
257 int mlx5_cmd_fs_delete_fte(struct mlx5_core_dev *dev,
258 u16 vport,
259 enum fs_fte_status *fte_status,
260 enum fs_ft_type type, unsigned int table_id,
261 unsigned int index)
262 {
263 u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {0};
264 u32 out[MLX5_ST_SZ_DW(delete_fte_out)] = {0};
265 int err;
266
267 if (!(*fte_status & FS_FTE_STATUS_EXISTING))
268 return 0;
269
270 if (!dev)
271 return -EINVAL;
272
273 MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
274 MLX5_SET(delete_fte_in, in, table_type, type);
275 MLX5_SET(delete_fte_in, in, table_id, table_id);
276 MLX5_SET(delete_fte_in, in, flow_index, index);
277 if (vport) {
278 MLX5_SET(delete_fte_in, in, vport_number, vport);
279 MLX5_SET(delete_fte_in, in, other_vport, 1);
280 }
281
282 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
283 if (!err)
284 *fte_status = 0;
285
286 return err;
287 }
Cache object: a41cd3a3d55b35d90eccb4c4ccb25f19
|