Commit | Line | Data |
---|---|---|
26a81453 MG |
1 | /* |
2 | * Copyright (c) 2015, 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/mlx5/driver.h> | |
34 | #include <linux/mlx5/device.h> | |
35 | #include <linux/mlx5/mlx5_ifc.h> | |
36 | ||
37 | #include "fs_core.h" | |
38 | #include "fs_cmd.h" | |
4a98544d | 39 | #include "fs_ft_pool.h" |
26a81453 | 40 | #include "mlx5_core.h" |
c9f1b073 | 41 | #include "eswitch.h" |
26a81453 | 42 | |
ae288a48 | 43 | static int mlx5_cmd_stub_update_root_ft(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
44 | struct mlx5_flow_table *ft, |
45 | u32 underlay_qpn, | |
46 | bool disconnect) | |
47 | { | |
48 | return 0; | |
49 | } | |
50 | ||
ae288a48 MG |
51 | static int mlx5_cmd_stub_create_flow_table(struct mlx5_flow_root_namespace *ns, |
52 | struct mlx5_flow_table *ft, | |
04745afb | 53 | unsigned int size, |
ae288a48 | 54 | struct mlx5_flow_table *next_ft) |
af76c501 | 55 | { |
04745afb PB |
56 | ft->max_fte = size ? roundup_pow_of_two(size) : 1; |
57 | ||
af76c501 MB |
58 | return 0; |
59 | } | |
60 | ||
ae288a48 | 61 | static int mlx5_cmd_stub_destroy_flow_table(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
62 | struct mlx5_flow_table *ft) |
63 | { | |
64 | return 0; | |
65 | } | |
66 | ||
ae288a48 | 67 | static int mlx5_cmd_stub_modify_flow_table(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
68 | struct mlx5_flow_table *ft, |
69 | struct mlx5_flow_table *next_ft) | |
70 | { | |
71 | return 0; | |
72 | } | |
73 | ||
ae288a48 | 74 | static int mlx5_cmd_stub_create_flow_group(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
75 | struct mlx5_flow_table *ft, |
76 | u32 *in, | |
ae288a48 | 77 | struct mlx5_flow_group *fg) |
af76c501 MB |
78 | { |
79 | return 0; | |
80 | } | |
81 | ||
ae288a48 | 82 | static int mlx5_cmd_stub_destroy_flow_group(struct mlx5_flow_root_namespace *ns, |
af76c501 | 83 | struct mlx5_flow_table *ft, |
ae288a48 | 84 | struct mlx5_flow_group *fg) |
af76c501 MB |
85 | { |
86 | return 0; | |
87 | } | |
88 | ||
ae288a48 | 89 | static int mlx5_cmd_stub_create_fte(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
90 | struct mlx5_flow_table *ft, |
91 | struct mlx5_flow_group *group, | |
92 | struct fs_fte *fte) | |
93 | { | |
94 | return 0; | |
95 | } | |
96 | ||
ae288a48 | 97 | static int mlx5_cmd_stub_update_fte(struct mlx5_flow_root_namespace *ns, |
af76c501 | 98 | struct mlx5_flow_table *ft, |
ae288a48 | 99 | struct mlx5_flow_group *group, |
af76c501 MB |
100 | int modify_mask, |
101 | struct fs_fte *fte) | |
102 | { | |
103 | return -EOPNOTSUPP; | |
104 | } | |
105 | ||
ae288a48 | 106 | static int mlx5_cmd_stub_delete_fte(struct mlx5_flow_root_namespace *ns, |
af76c501 | 107 | struct mlx5_flow_table *ft, |
e810bf5e | 108 | struct fs_fte *fte) |
af76c501 MB |
109 | { |
110 | return 0; | |
111 | } | |
112 | ||
2b688ea5 MG |
113 | static int mlx5_cmd_stub_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns, |
114 | int reformat_type, | |
115 | size_t size, | |
116 | void *reformat_data, | |
117 | enum mlx5_flow_namespace_type namespace, | |
118 | struct mlx5_pkt_reformat *pkt_reformat) | |
119 | { | |
120 | return 0; | |
121 | } | |
122 | ||
123 | static void mlx5_cmd_stub_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns, | |
124 | struct mlx5_pkt_reformat *pkt_reformat) | |
125 | { | |
126 | } | |
127 | ||
128 | static int mlx5_cmd_stub_modify_header_alloc(struct mlx5_flow_root_namespace *ns, | |
129 | u8 namespace, u8 num_actions, | |
130 | void *modify_actions, | |
131 | struct mlx5_modify_hdr *modify_hdr) | |
132 | { | |
133 | return 0; | |
134 | } | |
135 | ||
136 | static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace *ns, | |
137 | struct mlx5_modify_hdr *modify_hdr) | |
138 | { | |
139 | } | |
140 | ||
6a48faee MG |
141 | static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns, |
142 | struct mlx5_flow_root_namespace *peer_ns) | |
143 | { | |
144 | return 0; | |
145 | } | |
146 | ||
147 | static int mlx5_cmd_stub_create_ns(struct mlx5_flow_root_namespace *ns) | |
148 | { | |
149 | return 0; | |
150 | } | |
151 | ||
152 | static int mlx5_cmd_stub_destroy_ns(struct mlx5_flow_root_namespace *ns) | |
153 | { | |
154 | return 0; | |
155 | } | |
156 | ||
ae288a48 | 157 | static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
158 | struct mlx5_flow_table *ft, u32 underlay_qpn, |
159 | bool disconnect) | |
2cc43b49 | 160 | { |
31a0956e | 161 | u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {}; |
ae288a48 | 162 | struct mlx5_core_dev *dev = ns->dev; |
2cc43b49 | 163 | |
b3ba5149 | 164 | if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) && |
50854114 | 165 | underlay_qpn == 0) |
b3ba5149 ES |
166 | return 0; |
167 | ||
2cc43b49 MG |
168 | MLX5_SET(set_flow_table_root_in, in, opcode, |
169 | MLX5_CMD_OP_SET_FLOW_TABLE_ROOT); | |
170 | MLX5_SET(set_flow_table_root_in, in, table_type, ft->type); | |
dae37456 | 171 | |
31a0956e | 172 | if (disconnect) |
dae37456 | 173 | MLX5_SET(set_flow_table_root_in, in, op_mod, 1); |
31a0956e | 174 | else |
dae37456 | 175 | MLX5_SET(set_flow_table_root_in, in, table_id, ft->id); |
dae37456 | 176 | |
50854114 | 177 | MLX5_SET(set_flow_table_root_in, in, underlay_qpn, underlay_qpn); |
617b860c PP |
178 | MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport); |
179 | MLX5_SET(set_flow_table_root_in, in, other_vport, | |
180 | !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); | |
2cc43b49 | 181 | |
31a0956e | 182 | return mlx5_cmd_exec_in(dev, set_flow_table_root, in); |
2cc43b49 MG |
183 | } |
184 | ||
ae288a48 MG |
185 | static int mlx5_cmd_create_flow_table(struct mlx5_flow_root_namespace *ns, |
186 | struct mlx5_flow_table *ft, | |
04745afb | 187 | unsigned int size, |
ae288a48 | 188 | struct mlx5_flow_table *next_ft) |
26a81453 | 189 | { |
ae288a48 MG |
190 | int en_encap = !!(ft->flags & MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT); |
191 | int en_decap = !!(ft->flags & MLX5_FLOW_TABLE_TUNNEL_EN_DECAP); | |
c6d4e45d | 192 | int term = !!(ft->flags & MLX5_FLOW_TABLE_TERMINATION); |
31a0956e LR |
193 | u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {}; |
194 | u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {}; | |
ae288a48 | 195 | struct mlx5_core_dev *dev = ns->dev; |
26a81453 MG |
196 | int err; |
197 | ||
4a98544d PB |
198 | if (size != POOL_NEXT_SIZE) |
199 | size = roundup_pow_of_two(size); | |
200 | size = mlx5_ft_pool_get_avail_sz(dev, ft->type, size); | |
201 | if (!size) | |
202 | return -ENOSPC; | |
04745afb | 203 | |
26a81453 MG |
204 | MLX5_SET(create_flow_table_in, in, opcode, |
205 | MLX5_CMD_OP_CREATE_FLOW_TABLE); | |
206 | ||
ae288a48 MG |
207 | MLX5_SET(create_flow_table_in, in, table_type, ft->type); |
208 | MLX5_SET(create_flow_table_in, in, flow_table_context.level, ft->level); | |
4a98544d | 209 | MLX5_SET(create_flow_table_in, in, flow_table_context.log_size, size ? ilog2(size) : 0); |
617b860c PP |
210 | MLX5_SET(create_flow_table_in, in, vport_number, ft->vport); |
211 | MLX5_SET(create_flow_table_in, in, other_vport, | |
212 | !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); | |
26a81453 | 213 | |
0c90e9c6 | 214 | MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en, |
61444b45 | 215 | en_decap); |
60786f09 | 216 | MLX5_SET(create_flow_table_in, in, flow_table_context.reformat_en, |
61444b45 | 217 | en_encap); |
c6d4e45d EB |
218 | MLX5_SET(create_flow_table_in, in, flow_table_context.termination_table, |
219 | term); | |
c9f1b073 | 220 | |
ae288a48 | 221 | switch (ft->op_mod) { |
aaff1bea AH |
222 | case FS_FT_OP_MOD_NORMAL: |
223 | if (next_ft) { | |
0c90e9c6 | 224 | MLX5_SET(create_flow_table_in, in, |
f6f7d6b5 MG |
225 | flow_table_context.table_miss_action, |
226 | MLX5_FLOW_TABLE_MISS_ACTION_FWD); | |
0c90e9c6 MG |
227 | MLX5_SET(create_flow_table_in, in, |
228 | flow_table_context.table_miss_id, next_ft->id); | |
f6f7d6b5 MG |
229 | } else { |
230 | MLX5_SET(create_flow_table_in, in, | |
231 | flow_table_context.table_miss_action, | |
f66ad830 | 232 | ft->def_miss_action); |
aaff1bea AH |
233 | } |
234 | break; | |
235 | ||
236 | case FS_FT_OP_MOD_LAG_DEMUX: | |
237 | MLX5_SET(create_flow_table_in, in, op_mod, 0x1); | |
238 | if (next_ft) | |
0c90e9c6 MG |
239 | MLX5_SET(create_flow_table_in, in, |
240 | flow_table_context.lag_master_next_table_id, | |
aaff1bea AH |
241 | next_ft->id); |
242 | break; | |
243 | } | |
244 | ||
31a0956e | 245 | err = mlx5_cmd_exec_inout(dev, create_flow_table, in, out); |
4a98544d | 246 | if (!err) { |
ae288a48 MG |
247 | ft->id = MLX5_GET(create_flow_table_out, out, |
248 | table_id); | |
4a98544d PB |
249 | ft->max_fte = size; |
250 | } else { | |
251 | mlx5_ft_pool_put_sz(ns->dev, size); | |
252 | } | |
253 | ||
26a81453 MG |
254 | return err; |
255 | } | |
256 | ||
ae288a48 | 257 | static int mlx5_cmd_destroy_flow_table(struct mlx5_flow_root_namespace *ns, |
af76c501 | 258 | struct mlx5_flow_table *ft) |
26a81453 | 259 | { |
31a0956e | 260 | u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {}; |
ae288a48 | 261 | struct mlx5_core_dev *dev = ns->dev; |
4a98544d | 262 | int err; |
26a81453 MG |
263 | |
264 | MLX5_SET(destroy_flow_table_in, in, opcode, | |
265 | MLX5_CMD_OP_DESTROY_FLOW_TABLE); | |
266 | MLX5_SET(destroy_flow_table_in, in, table_type, ft->type); | |
267 | MLX5_SET(destroy_flow_table_in, in, table_id, ft->id); | |
617b860c PP |
268 | MLX5_SET(destroy_flow_table_in, in, vport_number, ft->vport); |
269 | MLX5_SET(destroy_flow_table_in, in, other_vport, | |
270 | !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); | |
26a81453 | 271 | |
4a98544d PB |
272 | err = mlx5_cmd_exec_in(dev, destroy_flow_table, in); |
273 | if (!err) | |
274 | mlx5_ft_pool_put_sz(ns->dev, ft->max_fte); | |
275 | ||
276 | return err; | |
26a81453 MG |
277 | } |
278 | ||
ae288a48 | 279 | static int mlx5_cmd_modify_flow_table(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
280 | struct mlx5_flow_table *ft, |
281 | struct mlx5_flow_table *next_ft) | |
34a40e68 | 282 | { |
31a0956e | 283 | u32 in[MLX5_ST_SZ_DW(modify_flow_table_in)] = {}; |
ae288a48 | 284 | struct mlx5_core_dev *dev = ns->dev; |
34a40e68 MG |
285 | |
286 | MLX5_SET(modify_flow_table_in, in, opcode, | |
287 | MLX5_CMD_OP_MODIFY_FLOW_TABLE); | |
288 | MLX5_SET(modify_flow_table_in, in, table_type, ft->type); | |
289 | MLX5_SET(modify_flow_table_in, in, table_id, ft->id); | |
aaff1bea AH |
290 | |
291 | if (ft->op_mod == FS_FT_OP_MOD_LAG_DEMUX) { | |
292 | MLX5_SET(modify_flow_table_in, in, modify_field_select, | |
293 | MLX5_MODIFY_FLOW_TABLE_LAG_NEXT_TABLE_ID); | |
294 | if (next_ft) { | |
295 | MLX5_SET(modify_flow_table_in, in, | |
0c90e9c6 | 296 | flow_table_context.lag_master_next_table_id, next_ft->id); |
aaff1bea AH |
297 | } else { |
298 | MLX5_SET(modify_flow_table_in, in, | |
0c90e9c6 | 299 | flow_table_context.lag_master_next_table_id, 0); |
aaff1bea | 300 | } |
34a40e68 | 301 | } else { |
617b860c PP |
302 | MLX5_SET(modify_flow_table_in, in, vport_number, ft->vport); |
303 | MLX5_SET(modify_flow_table_in, in, other_vport, | |
304 | !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); | |
aaff1bea AH |
305 | MLX5_SET(modify_flow_table_in, in, modify_field_select, |
306 | MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID); | |
307 | if (next_ft) { | |
0c90e9c6 | 308 | MLX5_SET(modify_flow_table_in, in, |
f6f7d6b5 MG |
309 | flow_table_context.table_miss_action, |
310 | MLX5_FLOW_TABLE_MISS_ACTION_FWD); | |
0c90e9c6 MG |
311 | MLX5_SET(modify_flow_table_in, in, |
312 | flow_table_context.table_miss_id, | |
aaff1bea AH |
313 | next_ft->id); |
314 | } else { | |
0c90e9c6 | 315 | MLX5_SET(modify_flow_table_in, in, |
f6f7d6b5 | 316 | flow_table_context.table_miss_action, |
f66ad830 | 317 | ft->def_miss_action); |
aaff1bea | 318 | } |
34a40e68 MG |
319 | } |
320 | ||
31a0956e | 321 | return mlx5_cmd_exec_in(dev, modify_flow_table, in); |
34a40e68 MG |
322 | } |
323 | ||
ae288a48 | 324 | static int mlx5_cmd_create_flow_group(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
325 | struct mlx5_flow_table *ft, |
326 | u32 *in, | |
ae288a48 | 327 | struct mlx5_flow_group *fg) |
26a81453 | 328 | { |
31a0956e | 329 | u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {}; |
ae288a48 | 330 | struct mlx5_core_dev *dev = ns->dev; |
26a81453 MG |
331 | int err; |
332 | ||
26a81453 MG |
333 | MLX5_SET(create_flow_group_in, in, opcode, |
334 | MLX5_CMD_OP_CREATE_FLOW_GROUP); | |
335 | MLX5_SET(create_flow_group_in, in, table_type, ft->type); | |
336 | MLX5_SET(create_flow_group_in, in, table_id, ft->id); | |
efdc810b MHY |
337 | if (ft->vport) { |
338 | MLX5_SET(create_flow_group_in, in, vport_number, ft->vport); | |
339 | MLX5_SET(create_flow_group_in, in, other_vport, 1); | |
340 | } | |
26a81453 | 341 | |
617b860c PP |
342 | MLX5_SET(create_flow_group_in, in, vport_number, ft->vport); |
343 | MLX5_SET(create_flow_group_in, in, other_vport, | |
344 | !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); | |
31a0956e | 345 | err = mlx5_cmd_exec_inout(dev, create_flow_group, in, out); |
26a81453 | 346 | if (!err) |
ae288a48 MG |
347 | fg->id = MLX5_GET(create_flow_group_out, out, |
348 | group_id); | |
26a81453 MG |
349 | return err; |
350 | } | |
351 | ||
ae288a48 | 352 | static int mlx5_cmd_destroy_flow_group(struct mlx5_flow_root_namespace *ns, |
af76c501 | 353 | struct mlx5_flow_table *ft, |
ae288a48 | 354 | struct mlx5_flow_group *fg) |
26a81453 | 355 | { |
31a0956e | 356 | u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {}; |
ae288a48 | 357 | struct mlx5_core_dev *dev = ns->dev; |
26a81453 MG |
358 | |
359 | MLX5_SET(destroy_flow_group_in, in, opcode, | |
360 | MLX5_CMD_OP_DESTROY_FLOW_GROUP); | |
361 | MLX5_SET(destroy_flow_group_in, in, table_type, ft->type); | |
362 | MLX5_SET(destroy_flow_group_in, in, table_id, ft->id); | |
ae288a48 | 363 | MLX5_SET(destroy_flow_group_in, in, group_id, fg->id); |
617b860c PP |
364 | MLX5_SET(destroy_flow_group_in, in, vport_number, ft->vport); |
365 | MLX5_SET(destroy_flow_group_in, in, other_vport, | |
366 | !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); | |
31a0956e | 367 | return mlx5_cmd_exec_in(dev, destroy_flow_group, in); |
26a81453 MG |
368 | } |
369 | ||
a2c6162b EB |
370 | static int mlx5_set_extended_dest(struct mlx5_core_dev *dev, |
371 | struct fs_fte *fte, bool *extended_dest) | |
372 | { | |
373 | int fw_log_max_fdb_encap_uplink = | |
374 | MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink); | |
375 | int num_fwd_destinations = 0; | |
376 | struct mlx5_flow_rule *dst; | |
377 | int num_encap = 0; | |
378 | ||
379 | *extended_dest = false; | |
380 | if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)) | |
381 | return 0; | |
382 | ||
383 | list_for_each_entry(dst, &fte->node.children, node.list) { | |
384 | if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) | |
385 | continue; | |
386 | if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_VPORT && | |
387 | dst->dest_attr.vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID) | |
388 | num_encap++; | |
389 | num_fwd_destinations++; | |
390 | } | |
391 | if (num_fwd_destinations > 1 && num_encap > 0) | |
392 | *extended_dest = true; | |
393 | ||
394 | if (*extended_dest && !fw_log_max_fdb_encap_uplink) { | |
395 | mlx5_core_warn(dev, "FW does not support extended destination"); | |
396 | return -EOPNOTSUPP; | |
397 | } | |
398 | if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) { | |
399 | mlx5_core_warn(dev, "FW does not support more than %d encaps", | |
400 | 1 << fw_log_max_fdb_encap_uplink); | |
401 | return -EOPNOTSUPP; | |
402 | } | |
403 | ||
404 | return 0; | |
405 | } | |
26a81453 MG |
406 | static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, |
407 | int opmod, int modify_mask, | |
408 | struct mlx5_flow_table *ft, | |
409 | unsigned group_id, | |
410 | struct fs_fte *fte) | |
411 | { | |
c4f287c4 | 412 | u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0}; |
a2c6162b | 413 | bool extended_dest = false; |
26a81453 | 414 | struct mlx5_flow_rule *dst; |
0c06897a | 415 | void *in_flow_context, *vlan; |
26a81453 | 416 | void *in_match_value; |
a2c6162b EB |
417 | unsigned int inlen; |
418 | int dst_cnt_size; | |
26a81453 MG |
419 | void *in_dests; |
420 | u32 *in; | |
421 | int err; | |
422 | ||
a2c6162b EB |
423 | if (mlx5_set_extended_dest(dev, fte, &extended_dest)) |
424 | return -EOPNOTSUPP; | |
425 | ||
426 | if (!extended_dest) | |
427 | dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct); | |
428 | else | |
429 | dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format); | |
430 | ||
431 | inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size; | |
1b9a07ee LR |
432 | in = kvzalloc(inlen, GFP_KERNEL); |
433 | if (!in) | |
26a81453 | 434 | return -ENOMEM; |
26a81453 MG |
435 | |
436 | MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY); | |
437 | MLX5_SET(set_fte_in, in, op_mod, opmod); | |
438 | MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask); | |
439 | MLX5_SET(set_fte_in, in, table_type, ft->type); | |
440 | MLX5_SET(set_fte_in, in, table_id, ft->id); | |
441 | MLX5_SET(set_fte_in, in, flow_index, fte->index); | |
ff189b43 PB |
442 | MLX5_SET(set_fte_in, in, ignore_flow_level, |
443 | !!(fte->action.flags & FLOW_ACT_IGNORE_FLOW_LEVEL)); | |
444 | ||
617b860c PP |
445 | MLX5_SET(set_fte_in, in, vport_number, ft->vport); |
446 | MLX5_SET(set_fte_in, in, other_vport, | |
447 | !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); | |
26a81453 MG |
448 | |
449 | in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context); | |
450 | MLX5_SET(flow_context, in_flow_context, group_id, group_id); | |
0c06897a | 451 | |
bb0ee7dc JL |
452 | MLX5_SET(flow_context, in_flow_context, flow_tag, |
453 | fte->flow_context.flow_tag); | |
8d212ff0 JL |
454 | MLX5_SET(flow_context, in_flow_context, flow_source, |
455 | fte->flow_context.flow_source); | |
456 | ||
a2c6162b EB |
457 | MLX5_SET(flow_context, in_flow_context, extended_destination, |
458 | extended_dest); | |
459 | if (extended_dest) { | |
460 | u32 action; | |
461 | ||
462 | action = fte->action.action & | |
463 | ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; | |
464 | MLX5_SET(flow_context, in_flow_context, action, action); | |
465 | } else { | |
466 | MLX5_SET(flow_context, in_flow_context, action, | |
467 | fte->action.action); | |
2b688ea5 MG |
468 | if (fte->action.pkt_reformat) |
469 | MLX5_SET(flow_context, in_flow_context, packet_reformat_id, | |
470 | fte->action.pkt_reformat->id); | |
a2c6162b | 471 | } |
2b688ea5 MG |
472 | if (fte->action.modify_hdr) |
473 | MLX5_SET(flow_context, in_flow_context, modify_header_id, | |
474 | fte->action.modify_hdr->id); | |
0c06897a | 475 | |
5e466345 HN |
476 | MLX5_SET(flow_context, in_flow_context, ipsec_obj_id, fte->action.ipsec_obj_id); |
477 | ||
0c06897a OG |
478 | vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan); |
479 | ||
8da6fe2a JL |
480 | MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype); |
481 | MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid); | |
482 | MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio); | |
483 | ||
484 | vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2); | |
485 | ||
486 | MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype); | |
487 | MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid); | |
488 | MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio); | |
0c06897a | 489 | |
26a81453 MG |
490 | in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context, |
491 | match_value); | |
667cb65a | 492 | memcpy(in_match_value, &fte->val, sizeof(fte->val)); |
26a81453 | 493 | |
bd5251db | 494 | in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination); |
d2ec6a35 | 495 | if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { |
bd5251db AV |
496 | int list_size = 0; |
497 | ||
60ab4584 | 498 | list_for_each_entry(dst, &fte->node.children, node.list) { |
664000b6 | 499 | unsigned int id, type = dst->dest_attr.type; |
60ab4584 | 500 | |
664000b6 | 501 | if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) |
bd5251db AV |
502 | continue; |
503 | ||
664000b6 YH |
504 | switch (type) { |
505 | case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM: | |
506 | id = dst->dest_attr.ft_num; | |
507 | type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; | |
508 | break; | |
509 | case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: | |
60ab4584 | 510 | id = dst->dest_attr.ft->id; |
664000b6 YH |
511 | break; |
512 | case MLX5_FLOW_DESTINATION_TYPE_VPORT: | |
b17f7fc1 SK |
513 | id = dst->dest_attr.vport.num; |
514 | MLX5_SET(dest_format_struct, in_dests, | |
515 | destination_eswitch_owner_vhca_id_valid, | |
aa39c2c0 EB |
516 | !!(dst->dest_attr.vport.flags & |
517 | MLX5_FLOW_DEST_VPORT_VHCA_ID)); | |
b17f7fc1 SK |
518 | MLX5_SET(dest_format_struct, in_dests, |
519 | destination_eswitch_owner_vhca_id, | |
520 | dst->dest_attr.vport.vhca_id); | |
0fd79b1e EB |
521 | if (extended_dest && |
522 | dst->dest_attr.vport.pkt_reformat) { | |
a2c6162b EB |
523 | MLX5_SET(dest_format_struct, in_dests, |
524 | packet_reformat, | |
525 | !!(dst->dest_attr.vport.flags & | |
526 | MLX5_FLOW_DEST_VPORT_REFORMAT_ID)); | |
527 | MLX5_SET(extended_dest_format, in_dests, | |
528 | packet_reformat_id, | |
2b688ea5 | 529 | dst->dest_attr.vport.pkt_reformat->id); |
a2c6162b | 530 | } |
664000b6 | 531 | break; |
38730630 CM |
532 | case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER: |
533 | id = dst->dest_attr.sampler_id; | |
534 | break; | |
664000b6 | 535 | default: |
60ab4584 AV |
536 | id = dst->dest_attr.tir_num; |
537 | } | |
664000b6 YH |
538 | |
539 | MLX5_SET(dest_format_struct, in_dests, destination_type, | |
540 | type); | |
60ab4584 | 541 | MLX5_SET(dest_format_struct, in_dests, destination_id, id); |
a2c6162b | 542 | in_dests += dst_cnt_size; |
bd5251db AV |
543 | list_size++; |
544 | } | |
545 | ||
546 | MLX5_SET(flow_context, in_flow_context, destination_list_size, | |
547 | list_size); | |
548 | } | |
549 | ||
d2ec6a35 | 550 | if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { |
16f1c5bb RS |
551 | int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev, |
552 | log_max_flow_counter, | |
553 | ft->type)); | |
bd5251db AV |
554 | int list_size = 0; |
555 | ||
556 | list_for_each_entry(dst, &fte->node.children, node.list) { | |
557 | if (dst->dest_attr.type != | |
558 | MLX5_FLOW_DESTINATION_TYPE_COUNTER) | |
559 | continue; | |
560 | ||
561 | MLX5_SET(flow_counter_list, in_dests, flow_counter_id, | |
171c7625 | 562 | dst->dest_attr.counter_id); |
a2c6162b | 563 | in_dests += dst_cnt_size; |
bd5251db | 564 | list_size++; |
60ab4584 | 565 | } |
16f1c5bb RS |
566 | if (list_size > max_list_size) { |
567 | err = -EINVAL; | |
568 | goto err_out; | |
569 | } | |
bd5251db AV |
570 | |
571 | MLX5_SET(flow_context, in_flow_context, flow_counter_list_size, | |
572 | list_size); | |
26a81453 | 573 | } |
bd5251db | 574 | |
c4f287c4 | 575 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
16f1c5bb | 576 | err_out: |
26a81453 | 577 | kvfree(in); |
26a81453 MG |
578 | return err; |
579 | } | |
580 | ||
ae288a48 | 581 | static int mlx5_cmd_create_fte(struct mlx5_flow_root_namespace *ns, |
af76c501 MB |
582 | struct mlx5_flow_table *ft, |
583 | struct mlx5_flow_group *group, | |
584 | struct fs_fte *fte) | |
26a81453 | 585 | { |
ae288a48 | 586 | struct mlx5_core_dev *dev = ns->dev; |
af76c501 MB |
587 | unsigned int group_id = group->id; |
588 | ||
c4f287c4 | 589 | return mlx5_cmd_set_fte(dev, 0, 0, ft, group_id, fte); |
26a81453 MG |
590 | } |
591 | ||
ae288a48 | 592 | static int mlx5_cmd_update_fte(struct mlx5_flow_root_namespace *ns, |
af76c501 | 593 | struct mlx5_flow_table *ft, |
ae288a48 | 594 | struct mlx5_flow_group *fg, |
af76c501 MB |
595 | int modify_mask, |
596 | struct fs_fte *fte) | |
26a81453 MG |
597 | { |
598 | int opmod; | |
ae288a48 | 599 | struct mlx5_core_dev *dev = ns->dev; |
26a81453 MG |
600 | int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev, |
601 | flow_table_properties_nic_receive. | |
602 | flow_modify_en); | |
603 | if (!atomic_mod_cap) | |
9eb78923 | 604 | return -EOPNOTSUPP; |
26a81453 | 605 | opmod = 1; |
26a81453 | 606 | |
ae288a48 | 607 | return mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, fg->id, fte); |
26a81453 MG |
608 | } |
609 | ||
ae288a48 | 610 | static int mlx5_cmd_delete_fte(struct mlx5_flow_root_namespace *ns, |
af76c501 | 611 | struct mlx5_flow_table *ft, |
e810bf5e | 612 | struct fs_fte *fte) |
26a81453 | 613 | { |
31a0956e | 614 | u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {}; |
ae288a48 | 615 | struct mlx5_core_dev *dev = ns->dev; |
26a81453 MG |
616 | |
617 | MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); | |
618 | MLX5_SET(delete_fte_in, in, table_type, ft->type); | |
619 | MLX5_SET(delete_fte_in, in, table_id, ft->id); | |
e810bf5e | 620 | MLX5_SET(delete_fte_in, in, flow_index, fte->index); |
617b860c PP |
621 | MLX5_SET(delete_fte_in, in, vport_number, ft->vport); |
622 | MLX5_SET(delete_fte_in, in, other_vport, | |
623 | !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); | |
26a81453 | 624 | |
31a0956e | 625 | return mlx5_cmd_exec_in(dev, delete_fte, in); |
26a81453 | 626 | } |
9dc0b289 | 627 | |
8536a6bf GT |
628 | int mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, |
629 | enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask, | |
630 | u32 *id) | |
9dc0b289 | 631 | { |
31a0956e LR |
632 | u32 out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {}; |
633 | u32 in[MLX5_ST_SZ_DW(alloc_flow_counter_in)] = {}; | |
9dc0b289 AV |
634 | int err; |
635 | ||
9dc0b289 AV |
636 | MLX5_SET(alloc_flow_counter_in, in, opcode, |
637 | MLX5_CMD_OP_ALLOC_FLOW_COUNTER); | |
8536a6bf | 638 | MLX5_SET(alloc_flow_counter_in, in, flow_counter_bulk, alloc_bitmask); |
9dc0b289 | 639 | |
31a0956e | 640 | err = mlx5_cmd_exec_inout(dev, alloc_flow_counter, in, out); |
c4f287c4 SM |
641 | if (!err) |
642 | *id = MLX5_GET(alloc_flow_counter_out, out, flow_counter_id); | |
643 | return err; | |
9dc0b289 AV |
644 | } |
645 | ||
8536a6bf GT |
646 | int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id) |
647 | { | |
648 | return mlx5_cmd_fc_bulk_alloc(dev, 0, id); | |
649 | } | |
650 | ||
a8ffcc74 | 651 | int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u32 id) |
9dc0b289 | 652 | { |
31a0956e | 653 | u32 in[MLX5_ST_SZ_DW(dealloc_flow_counter_in)] = {}; |
9dc0b289 AV |
654 | |
655 | MLX5_SET(dealloc_flow_counter_in, in, opcode, | |
656 | MLX5_CMD_OP_DEALLOC_FLOW_COUNTER); | |
657 | MLX5_SET(dealloc_flow_counter_in, in, flow_counter_id, id); | |
31a0956e | 658 | return mlx5_cmd_exec_in(dev, dealloc_flow_counter, in); |
9dc0b289 AV |
659 | } |
660 | ||
a8ffcc74 | 661 | int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u32 id, |
9dc0b289 AV |
662 | u64 *packets, u64 *bytes) |
663 | { | |
664 | u32 out[MLX5_ST_SZ_BYTES(query_flow_counter_out) + | |
31a0956e LR |
665 | MLX5_ST_SZ_BYTES(traffic_counter)] = {}; |
666 | u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {}; | |
9dc0b289 AV |
667 | void *stats; |
668 | int err = 0; | |
669 | ||
9dc0b289 AV |
670 | MLX5_SET(query_flow_counter_in, in, opcode, |
671 | MLX5_CMD_OP_QUERY_FLOW_COUNTER); | |
672 | MLX5_SET(query_flow_counter_in, in, op_mod, 0); | |
673 | MLX5_SET(query_flow_counter_in, in, flow_counter_id, id); | |
c4f287c4 | 674 | err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
9dc0b289 AV |
675 | if (err) |
676 | return err; | |
677 | ||
678 | stats = MLX5_ADDR_OF(query_flow_counter_out, out, flow_statistics); | |
679 | *packets = MLX5_GET64(traffic_counter, stats, packets); | |
680 | *bytes = MLX5_GET64(traffic_counter, stats, octets); | |
9dc0b289 AV |
681 | return 0; |
682 | } | |
a351a1b0 | 683 | |
6f06e04b | 684 | int mlx5_cmd_fc_get_bulk_query_out_len(int bulk_len) |
a351a1b0 | 685 | { |
6f06e04b GT |
686 | return MLX5_ST_SZ_BYTES(query_flow_counter_out) + |
687 | MLX5_ST_SZ_BYTES(traffic_counter) * bulk_len; | |
a351a1b0 AV |
688 | } |
689 | ||
6f06e04b GT |
690 | int mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, u32 base_id, int bulk_len, |
691 | u32 *out) | |
a351a1b0 | 692 | { |
6f06e04b | 693 | int outlen = mlx5_cmd_fc_get_bulk_query_out_len(bulk_len); |
31a0956e | 694 | u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {}; |
a351a1b0 AV |
695 | |
696 | MLX5_SET(query_flow_counter_in, in, opcode, | |
697 | MLX5_CMD_OP_QUERY_FLOW_COUNTER); | |
6f06e04b GT |
698 | MLX5_SET(query_flow_counter_in, in, flow_counter_id, base_id); |
699 | MLX5_SET(query_flow_counter_in, in, num_of_counters, bulk_len); | |
700 | return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); | |
a351a1b0 | 701 | } |
575ddf58 | 702 | |
2b688ea5 MG |
703 | static int mlx5_cmd_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns, |
704 | int reformat_type, | |
705 | size_t size, | |
706 | void *reformat_data, | |
707 | enum mlx5_flow_namespace_type namespace, | |
708 | struct mlx5_pkt_reformat *pkt_reformat) | |
575ddf58 | 709 | { |
31a0956e | 710 | u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {}; |
2b688ea5 | 711 | struct mlx5_core_dev *dev = ns->dev; |
60786f09 | 712 | void *packet_reformat_context_in; |
31ca3648 | 713 | int max_encap_size; |
60786f09 | 714 | void *reformat; |
43f93839 | 715 | int inlen; |
575ddf58 | 716 | int err; |
43f93839 | 717 | u32 *in; |
575ddf58 | 718 | |
31ca3648 MB |
719 | if (namespace == MLX5_FLOW_NAMESPACE_FDB) |
720 | max_encap_size = MLX5_CAP_ESW(dev, max_encap_header_size); | |
721 | else | |
722 | max_encap_size = MLX5_CAP_FLOWTABLE(dev, max_encap_header_size); | |
723 | ||
073ff3c8 OG |
724 | if (size > max_encap_size) { |
725 | mlx5_core_warn(dev, "encap size %zd too big, max supported is %d\n", | |
726 | size, max_encap_size); | |
575ddf58 | 727 | return -EINVAL; |
073ff3c8 | 728 | } |
575ddf58 | 729 | |
60786f09 | 730 | in = kzalloc(MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in) + size, |
43f93839 HHZ |
731 | GFP_KERNEL); |
732 | if (!in) | |
733 | return -ENOMEM; | |
734 | ||
60786f09 MB |
735 | packet_reformat_context_in = MLX5_ADDR_OF(alloc_packet_reformat_context_in, |
736 | in, packet_reformat_context); | |
737 | reformat = MLX5_ADDR_OF(packet_reformat_context_in, | |
738 | packet_reformat_context_in, | |
739 | reformat_data); | |
740 | inlen = reformat - (void *)in + size; | |
43f93839 | 741 | |
60786f09 MB |
742 | MLX5_SET(alloc_packet_reformat_context_in, in, opcode, |
743 | MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT); | |
744 | MLX5_SET(packet_reformat_context_in, packet_reformat_context_in, | |
745 | reformat_data_size, size); | |
746 | MLX5_SET(packet_reformat_context_in, packet_reformat_context_in, | |
747 | reformat_type, reformat_type); | |
748 | memcpy(reformat, reformat_data, size); | |
575ddf58 | 749 | |
575ddf58 IL |
750 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
751 | ||
2b688ea5 MG |
752 | pkt_reformat->id = MLX5_GET(alloc_packet_reformat_context_out, |
753 | out, packet_reformat_id); | |
43f93839 | 754 | kfree(in); |
575ddf58 IL |
755 | return err; |
756 | } | |
757 | ||
2b688ea5 MG |
758 | static void mlx5_cmd_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns, |
759 | struct mlx5_pkt_reformat *pkt_reformat) | |
575ddf58 | 760 | { |
31a0956e | 761 | u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {}; |
2b688ea5 | 762 | struct mlx5_core_dev *dev = ns->dev; |
575ddf58 | 763 | |
60786f09 MB |
764 | MLX5_SET(dealloc_packet_reformat_context_in, in, opcode, |
765 | MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT); | |
766 | MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id, | |
2b688ea5 | 767 | pkt_reformat->id); |
575ddf58 | 768 | |
31a0956e | 769 | mlx5_cmd_exec_in(dev, dealloc_packet_reformat_context, in); |
575ddf58 | 770 | } |
2de24fed | 771 | |
2b688ea5 MG |
772 | static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns, |
773 | u8 namespace, u8 num_actions, | |
774 | void *modify_actions, | |
775 | struct mlx5_modify_hdr *modify_hdr) | |
2de24fed | 776 | { |
31a0956e | 777 | u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {}; |
2de24fed | 778 | int max_actions, actions_size, inlen, err; |
2b688ea5 | 779 | struct mlx5_core_dev *dev = ns->dev; |
2de24fed OG |
780 | void *actions_in; |
781 | u8 table_type; | |
782 | u32 *in; | |
783 | ||
784 | switch (namespace) { | |
785 | case MLX5_FLOW_NAMESPACE_FDB: | |
786 | max_actions = MLX5_CAP_ESW_FLOWTABLE_FDB(dev, max_modify_header_actions); | |
787 | table_type = FS_FT_FDB; | |
788 | break; | |
789 | case MLX5_FLOW_NAMESPACE_KERNEL: | |
c3c062f8 | 790 | case MLX5_FLOW_NAMESPACE_BYPASS: |
2de24fed OG |
791 | max_actions = MLX5_CAP_FLOWTABLE_NIC_RX(dev, max_modify_header_actions); |
792 | table_type = FS_FT_NIC_RX; | |
793 | break; | |
c3c062f8 | 794 | case MLX5_FLOW_NAMESPACE_EGRESS: |
ee92e4f1 HN |
795 | #ifdef CONFIG_MLX5_IPSEC |
796 | case MLX5_FLOW_NAMESPACE_EGRESS_KERNEL: | |
797 | #endif | |
c3c062f8 MB |
798 | max_actions = MLX5_CAP_FLOWTABLE_NIC_TX(dev, max_modify_header_actions); |
799 | table_type = FS_FT_NIC_TX; | |
800 | break; | |
84b0d6a7 JL |
801 | case MLX5_FLOW_NAMESPACE_ESW_INGRESS: |
802 | max_actions = MLX5_CAP_ESW_INGRESS_ACL(dev, max_modify_header_actions); | |
803 | table_type = FS_FT_ESW_INGRESS_ACL; | |
804 | break; | |
ecf814e0 MG |
805 | case MLX5_FLOW_NAMESPACE_RDMA_TX: |
806 | max_actions = MLX5_CAP_FLOWTABLE_RDMA_TX(dev, max_modify_header_actions); | |
807 | table_type = FS_FT_RDMA_TX; | |
808 | break; | |
2de24fed OG |
809 | default: |
810 | return -EOPNOTSUPP; | |
811 | } | |
812 | ||
813 | if (num_actions > max_actions) { | |
814 | mlx5_core_warn(dev, "too many modify header actions %d, max supported %d\n", | |
815 | num_actions, max_actions); | |
816 | return -EOPNOTSUPP; | |
817 | } | |
818 | ||
d65dbedf | 819 | actions_size = MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto) * num_actions; |
2de24fed OG |
820 | inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) + actions_size; |
821 | ||
822 | in = kzalloc(inlen, GFP_KERNEL); | |
823 | if (!in) | |
824 | return -ENOMEM; | |
825 | ||
826 | MLX5_SET(alloc_modify_header_context_in, in, opcode, | |
827 | MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT); | |
828 | MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type); | |
829 | MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_actions); | |
830 | ||
831 | actions_in = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions); | |
832 | memcpy(actions_in, modify_actions, actions_size); | |
833 | ||
2de24fed OG |
834 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
835 | ||
2b688ea5 | 836 | modify_hdr->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id); |
2de24fed OG |
837 | kfree(in); |
838 | return err; | |
839 | } | |
840 | ||
2b688ea5 MG |
841 | static void mlx5_cmd_modify_header_dealloc(struct mlx5_flow_root_namespace *ns, |
842 | struct mlx5_modify_hdr *modify_hdr) | |
2de24fed | 843 | { |
31a0956e | 844 | u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {}; |
2b688ea5 | 845 | struct mlx5_core_dev *dev = ns->dev; |
2de24fed | 846 | |
2de24fed OG |
847 | MLX5_SET(dealloc_modify_header_context_in, in, opcode, |
848 | MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT); | |
849 | MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id, | |
2b688ea5 | 850 | modify_hdr->id); |
2de24fed | 851 | |
31a0956e | 852 | mlx5_cmd_exec_in(dev, dealloc_modify_header_context, in); |
2de24fed | 853 | } |
af76c501 MB |
854 | |
855 | static const struct mlx5_flow_cmds mlx5_flow_cmds = { | |
856 | .create_flow_table = mlx5_cmd_create_flow_table, | |
857 | .destroy_flow_table = mlx5_cmd_destroy_flow_table, | |
858 | .modify_flow_table = mlx5_cmd_modify_flow_table, | |
859 | .create_flow_group = mlx5_cmd_create_flow_group, | |
860 | .destroy_flow_group = mlx5_cmd_destroy_flow_group, | |
861 | .create_fte = mlx5_cmd_create_fte, | |
862 | .update_fte = mlx5_cmd_update_fte, | |
863 | .delete_fte = mlx5_cmd_delete_fte, | |
864 | .update_root_ft = mlx5_cmd_update_root_ft, | |
2b688ea5 MG |
865 | .packet_reformat_alloc = mlx5_cmd_packet_reformat_alloc, |
866 | .packet_reformat_dealloc = mlx5_cmd_packet_reformat_dealloc, | |
867 | .modify_header_alloc = mlx5_cmd_modify_header_alloc, | |
6a48faee MG |
868 | .modify_header_dealloc = mlx5_cmd_modify_header_dealloc, |
869 | .set_peer = mlx5_cmd_stub_set_peer, | |
870 | .create_ns = mlx5_cmd_stub_create_ns, | |
871 | .destroy_ns = mlx5_cmd_stub_destroy_ns, | |
af76c501 MB |
872 | }; |
873 | ||
874 | static const struct mlx5_flow_cmds mlx5_flow_cmd_stubs = { | |
875 | .create_flow_table = mlx5_cmd_stub_create_flow_table, | |
876 | .destroy_flow_table = mlx5_cmd_stub_destroy_flow_table, | |
877 | .modify_flow_table = mlx5_cmd_stub_modify_flow_table, | |
878 | .create_flow_group = mlx5_cmd_stub_create_flow_group, | |
879 | .destroy_flow_group = mlx5_cmd_stub_destroy_flow_group, | |
880 | .create_fte = mlx5_cmd_stub_create_fte, | |
881 | .update_fte = mlx5_cmd_stub_update_fte, | |
882 | .delete_fte = mlx5_cmd_stub_delete_fte, | |
883 | .update_root_ft = mlx5_cmd_stub_update_root_ft, | |
2b688ea5 MG |
884 | .packet_reformat_alloc = mlx5_cmd_stub_packet_reformat_alloc, |
885 | .packet_reformat_dealloc = mlx5_cmd_stub_packet_reformat_dealloc, | |
886 | .modify_header_alloc = mlx5_cmd_stub_modify_header_alloc, | |
6a48faee MG |
887 | .modify_header_dealloc = mlx5_cmd_stub_modify_header_dealloc, |
888 | .set_peer = mlx5_cmd_stub_set_peer, | |
889 | .create_ns = mlx5_cmd_stub_create_ns, | |
890 | .destroy_ns = mlx5_cmd_stub_destroy_ns, | |
af76c501 MB |
891 | }; |
892 | ||
6a48faee | 893 | const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void) |
af76c501 MB |
894 | { |
895 | return &mlx5_flow_cmds; | |
896 | } | |
897 | ||
898 | static const struct mlx5_flow_cmds *mlx5_fs_cmd_get_stub_cmds(void) | |
899 | { | |
900 | return &mlx5_flow_cmd_stubs; | |
901 | } | |
902 | ||
903 | const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type type) | |
904 | { | |
905 | switch (type) { | |
906 | case FS_FT_NIC_RX: | |
907 | case FS_FT_ESW_EGRESS_ACL: | |
908 | case FS_FT_ESW_INGRESS_ACL: | |
909 | case FS_FT_FDB: | |
910 | case FS_FT_SNIFFER_RX: | |
911 | case FS_FT_SNIFFER_TX: | |
5f418378 | 912 | case FS_FT_NIC_TX: |
d83eb50e | 913 | case FS_FT_RDMA_RX: |
24670b1a | 914 | case FS_FT_RDMA_TX: |
8ce78257 | 915 | return mlx5_fs_cmd_get_fw_cmds(); |
af76c501 MB |
916 | default: |
917 | return mlx5_fs_cmd_get_stub_cmds(); | |
918 | } | |
919 | } |