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" | |
39 | #include "mlx5_core.h" | |
c9f1b073 | 40 | #include "eswitch.h" |
26a81453 | 41 | |
2cc43b49 MG |
42 | int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, |
43 | struct mlx5_flow_table *ft) | |
44 | { | |
c4f287c4 SM |
45 | u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {0}; |
46 | u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0}; | |
2cc43b49 MG |
47 | |
48 | MLX5_SET(set_flow_table_root_in, in, opcode, | |
49 | MLX5_CMD_OP_SET_FLOW_TABLE_ROOT); | |
50 | MLX5_SET(set_flow_table_root_in, in, table_type, ft->type); | |
51 | MLX5_SET(set_flow_table_root_in, in, table_id, ft->id); | |
efdc810b MHY |
52 | if (ft->vport) { |
53 | MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport); | |
54 | MLX5_SET(set_flow_table_root_in, in, other_vport, 1); | |
55 | } | |
2cc43b49 | 56 | |
c4f287c4 | 57 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
2cc43b49 MG |
58 | } |
59 | ||
26a81453 | 60 | int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev, |
efdc810b | 61 | u16 vport, |
aaff1bea | 62 | enum fs_flow_table_op_mod op_mod, |
26a81453 | 63 | enum fs_flow_table_type type, unsigned int level, |
f90edfd2 | 64 | unsigned int log_size, struct mlx5_flow_table |
c9f1b073 | 65 | *next_ft, unsigned int *table_id, u32 flags) |
26a81453 | 66 | { |
c9f1b073 | 67 | int en_encap_decap = !!(flags & MLX5_FLOW_TABLE_TUNNEL_EN); |
c4f287c4 SM |
68 | u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0}; |
69 | u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0}; | |
26a81453 MG |
70 | int err; |
71 | ||
26a81453 MG |
72 | MLX5_SET(create_flow_table_in, in, opcode, |
73 | MLX5_CMD_OP_CREATE_FLOW_TABLE); | |
74 | ||
75 | MLX5_SET(create_flow_table_in, in, table_type, type); | |
76 | MLX5_SET(create_flow_table_in, in, level, level); | |
77 | MLX5_SET(create_flow_table_in, in, log_size, log_size); | |
efdc810b MHY |
78 | if (vport) { |
79 | MLX5_SET(create_flow_table_in, in, vport_number, vport); | |
80 | MLX5_SET(create_flow_table_in, in, other_vport, 1); | |
81 | } | |
26a81453 | 82 | |
c9f1b073 HHZ |
83 | MLX5_SET(create_flow_table_in, in, decap_en, en_encap_decap); |
84 | MLX5_SET(create_flow_table_in, in, encap_en, en_encap_decap); | |
85 | ||
aaff1bea AH |
86 | switch (op_mod) { |
87 | case FS_FT_OP_MOD_NORMAL: | |
88 | if (next_ft) { | |
89 | MLX5_SET(create_flow_table_in, in, table_miss_mode, 1); | |
90 | MLX5_SET(create_flow_table_in, in, table_miss_id, next_ft->id); | |
91 | } | |
92 | break; | |
93 | ||
94 | case FS_FT_OP_MOD_LAG_DEMUX: | |
95 | MLX5_SET(create_flow_table_in, in, op_mod, 0x1); | |
96 | if (next_ft) | |
97 | MLX5_SET(create_flow_table_in, in, lag_master_next_table_id, | |
98 | next_ft->id); | |
99 | break; | |
100 | } | |
101 | ||
c4f287c4 | 102 | err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
26a81453 MG |
103 | if (!err) |
104 | *table_id = MLX5_GET(create_flow_table_out, out, | |
105 | table_id); | |
106 | return err; | |
107 | } | |
108 | ||
109 | int mlx5_cmd_destroy_flow_table(struct mlx5_core_dev *dev, | |
110 | struct mlx5_flow_table *ft) | |
111 | { | |
c4f287c4 SM |
112 | u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {0}; |
113 | u32 out[MLX5_ST_SZ_DW(destroy_flow_table_out)] = {0}; | |
26a81453 MG |
114 | |
115 | MLX5_SET(destroy_flow_table_in, in, opcode, | |
116 | MLX5_CMD_OP_DESTROY_FLOW_TABLE); | |
117 | MLX5_SET(destroy_flow_table_in, in, table_type, ft->type); | |
118 | MLX5_SET(destroy_flow_table_in, in, table_id, ft->id); | |
efdc810b MHY |
119 | if (ft->vport) { |
120 | MLX5_SET(destroy_flow_table_in, in, vport_number, ft->vport); | |
121 | MLX5_SET(destroy_flow_table_in, in, other_vport, 1); | |
122 | } | |
26a81453 | 123 | |
c4f287c4 | 124 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
26a81453 MG |
125 | } |
126 | ||
34a40e68 MG |
127 | int mlx5_cmd_modify_flow_table(struct mlx5_core_dev *dev, |
128 | struct mlx5_flow_table *ft, | |
129 | struct mlx5_flow_table *next_ft) | |
130 | { | |
c4f287c4 SM |
131 | u32 in[MLX5_ST_SZ_DW(modify_flow_table_in)] = {0}; |
132 | u32 out[MLX5_ST_SZ_DW(modify_flow_table_out)] = {0}; | |
34a40e68 MG |
133 | |
134 | MLX5_SET(modify_flow_table_in, in, opcode, | |
135 | MLX5_CMD_OP_MODIFY_FLOW_TABLE); | |
136 | MLX5_SET(modify_flow_table_in, in, table_type, ft->type); | |
137 | MLX5_SET(modify_flow_table_in, in, table_id, ft->id); | |
aaff1bea AH |
138 | |
139 | if (ft->op_mod == FS_FT_OP_MOD_LAG_DEMUX) { | |
140 | MLX5_SET(modify_flow_table_in, in, modify_field_select, | |
141 | MLX5_MODIFY_FLOW_TABLE_LAG_NEXT_TABLE_ID); | |
142 | if (next_ft) { | |
143 | MLX5_SET(modify_flow_table_in, in, | |
144 | lag_master_next_table_id, next_ft->id); | |
145 | } else { | |
146 | MLX5_SET(modify_flow_table_in, in, | |
147 | lag_master_next_table_id, 0); | |
148 | } | |
34a40e68 | 149 | } else { |
aaff1bea AH |
150 | if (ft->vport) { |
151 | MLX5_SET(modify_flow_table_in, in, vport_number, | |
152 | ft->vport); | |
153 | MLX5_SET(modify_flow_table_in, in, other_vport, 1); | |
154 | } | |
155 | MLX5_SET(modify_flow_table_in, in, modify_field_select, | |
156 | MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID); | |
157 | if (next_ft) { | |
158 | MLX5_SET(modify_flow_table_in, in, table_miss_mode, 1); | |
159 | MLX5_SET(modify_flow_table_in, in, table_miss_id, | |
160 | next_ft->id); | |
161 | } else { | |
162 | MLX5_SET(modify_flow_table_in, in, table_miss_mode, 0); | |
163 | } | |
34a40e68 MG |
164 | } |
165 | ||
c4f287c4 | 166 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
34a40e68 MG |
167 | } |
168 | ||
26a81453 MG |
169 | int mlx5_cmd_create_flow_group(struct mlx5_core_dev *dev, |
170 | struct mlx5_flow_table *ft, | |
171 | u32 *in, | |
172 | unsigned int *group_id) | |
173 | { | |
c4f287c4 | 174 | u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0}; |
26a81453 | 175 | int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); |
26a81453 MG |
176 | int err; |
177 | ||
26a81453 MG |
178 | MLX5_SET(create_flow_group_in, in, opcode, |
179 | MLX5_CMD_OP_CREATE_FLOW_GROUP); | |
180 | MLX5_SET(create_flow_group_in, in, table_type, ft->type); | |
181 | MLX5_SET(create_flow_group_in, in, table_id, ft->id); | |
efdc810b MHY |
182 | if (ft->vport) { |
183 | MLX5_SET(create_flow_group_in, in, vport_number, ft->vport); | |
184 | MLX5_SET(create_flow_group_in, in, other_vport, 1); | |
185 | } | |
26a81453 | 186 | |
c4f287c4 | 187 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
26a81453 MG |
188 | if (!err) |
189 | *group_id = MLX5_GET(create_flow_group_out, out, | |
190 | group_id); | |
26a81453 MG |
191 | return err; |
192 | } | |
193 | ||
194 | int mlx5_cmd_destroy_flow_group(struct mlx5_core_dev *dev, | |
195 | struct mlx5_flow_table *ft, | |
196 | unsigned int group_id) | |
197 | { | |
c4f287c4 SM |
198 | u32 out[MLX5_ST_SZ_DW(destroy_flow_group_out)] = {0}; |
199 | u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {0}; | |
26a81453 MG |
200 | |
201 | MLX5_SET(destroy_flow_group_in, in, opcode, | |
202 | MLX5_CMD_OP_DESTROY_FLOW_GROUP); | |
203 | MLX5_SET(destroy_flow_group_in, in, table_type, ft->type); | |
204 | MLX5_SET(destroy_flow_group_in, in, table_id, ft->id); | |
205 | MLX5_SET(destroy_flow_group_in, in, group_id, group_id); | |
efdc810b MHY |
206 | if (ft->vport) { |
207 | MLX5_SET(destroy_flow_group_in, in, vport_number, ft->vport); | |
208 | MLX5_SET(destroy_flow_group_in, in, other_vport, 1); | |
209 | } | |
26a81453 | 210 | |
c4f287c4 | 211 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
26a81453 MG |
212 | } |
213 | ||
214 | static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, | |
215 | int opmod, int modify_mask, | |
216 | struct mlx5_flow_table *ft, | |
217 | unsigned group_id, | |
218 | struct fs_fte *fte) | |
219 | { | |
220 | unsigned int inlen = MLX5_ST_SZ_BYTES(set_fte_in) + | |
221 | fte->dests_size * MLX5_ST_SZ_BYTES(dest_format_struct); | |
c4f287c4 | 222 | u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0}; |
26a81453 MG |
223 | struct mlx5_flow_rule *dst; |
224 | void *in_flow_context; | |
225 | void *in_match_value; | |
226 | void *in_dests; | |
227 | u32 *in; | |
228 | int err; | |
229 | ||
230 | in = mlx5_vzalloc(inlen); | |
231 | if (!in) { | |
232 | mlx5_core_warn(dev, "failed to allocate inbox\n"); | |
233 | return -ENOMEM; | |
234 | } | |
235 | ||
236 | MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY); | |
237 | MLX5_SET(set_fte_in, in, op_mod, opmod); | |
238 | MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask); | |
239 | MLX5_SET(set_fte_in, in, table_type, ft->type); | |
240 | MLX5_SET(set_fte_in, in, table_id, ft->id); | |
241 | MLX5_SET(set_fte_in, in, flow_index, fte->index); | |
efdc810b MHY |
242 | if (ft->vport) { |
243 | MLX5_SET(set_fte_in, in, vport_number, ft->vport); | |
244 | MLX5_SET(set_fte_in, in, other_vport, 1); | |
245 | } | |
26a81453 MG |
246 | |
247 | in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context); | |
248 | MLX5_SET(flow_context, in_flow_context, group_id, group_id); | |
249 | MLX5_SET(flow_context, in_flow_context, flow_tag, fte->flow_tag); | |
250 | MLX5_SET(flow_context, in_flow_context, action, fte->action); | |
66958ed9 | 251 | MLX5_SET(flow_context, in_flow_context, encap_id, fte->encap_id); |
26a81453 MG |
252 | in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context, |
253 | match_value); | |
254 | memcpy(in_match_value, &fte->val, MLX5_ST_SZ_BYTES(fte_match_param)); | |
255 | ||
bd5251db | 256 | in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination); |
60ab4584 | 257 | if (fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { |
bd5251db AV |
258 | int list_size = 0; |
259 | ||
60ab4584 AV |
260 | list_for_each_entry(dst, &fte->node.children, node.list) { |
261 | unsigned int id; | |
262 | ||
bd5251db AV |
263 | if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) |
264 | continue; | |
265 | ||
60ab4584 AV |
266 | MLX5_SET(dest_format_struct, in_dests, destination_type, |
267 | dst->dest_attr.type); | |
268 | if (dst->dest_attr.type == | |
269 | MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) { | |
270 | id = dst->dest_attr.ft->id; | |
271 | } else { | |
272 | id = dst->dest_attr.tir_num; | |
273 | } | |
274 | MLX5_SET(dest_format_struct, in_dests, destination_id, id); | |
275 | in_dests += MLX5_ST_SZ_BYTES(dest_format_struct); | |
bd5251db AV |
276 | list_size++; |
277 | } | |
278 | ||
279 | MLX5_SET(flow_context, in_flow_context, destination_list_size, | |
280 | list_size); | |
281 | } | |
282 | ||
283 | if (fte->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { | |
284 | int list_size = 0; | |
285 | ||
286 | list_for_each_entry(dst, &fte->node.children, node.list) { | |
287 | if (dst->dest_attr.type != | |
288 | MLX5_FLOW_DESTINATION_TYPE_COUNTER) | |
289 | continue; | |
290 | ||
291 | MLX5_SET(flow_counter_list, in_dests, flow_counter_id, | |
292 | dst->dest_attr.counter->id); | |
293 | in_dests += MLX5_ST_SZ_BYTES(dest_format_struct); | |
294 | list_size++; | |
60ab4584 | 295 | } |
bd5251db AV |
296 | |
297 | MLX5_SET(flow_context, in_flow_context, flow_counter_list_size, | |
298 | list_size); | |
26a81453 | 299 | } |
bd5251db | 300 | |
c4f287c4 | 301 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
26a81453 | 302 | kvfree(in); |
26a81453 MG |
303 | return err; |
304 | } | |
305 | ||
306 | int mlx5_cmd_create_fte(struct mlx5_core_dev *dev, | |
307 | struct mlx5_flow_table *ft, | |
308 | unsigned group_id, | |
309 | struct fs_fte *fte) | |
310 | { | |
c4f287c4 | 311 | return mlx5_cmd_set_fte(dev, 0, 0, ft, group_id, fte); |
26a81453 MG |
312 | } |
313 | ||
314 | int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, | |
315 | struct mlx5_flow_table *ft, | |
316 | unsigned group_id, | |
bd5251db | 317 | int modify_mask, |
26a81453 MG |
318 | struct fs_fte *fte) |
319 | { | |
320 | int opmod; | |
26a81453 MG |
321 | int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev, |
322 | flow_table_properties_nic_receive. | |
323 | flow_modify_en); | |
324 | if (!atomic_mod_cap) | |
325 | return -ENOTSUPP; | |
326 | opmod = 1; | |
26a81453 MG |
327 | |
328 | return mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, group_id, fte); | |
329 | } | |
330 | ||
331 | int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev, | |
332 | struct mlx5_flow_table *ft, | |
333 | unsigned int index) | |
334 | { | |
c4f287c4 SM |
335 | u32 out[MLX5_ST_SZ_DW(delete_fte_out)] = {0}; |
336 | u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {0}; | |
26a81453 MG |
337 | |
338 | MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); | |
339 | MLX5_SET(delete_fte_in, in, table_type, ft->type); | |
340 | MLX5_SET(delete_fte_in, in, table_id, ft->id); | |
341 | MLX5_SET(delete_fte_in, in, flow_index, index); | |
efdc810b MHY |
342 | if (ft->vport) { |
343 | MLX5_SET(delete_fte_in, in, vport_number, ft->vport); | |
344 | MLX5_SET(delete_fte_in, in, other_vport, 1); | |
345 | } | |
26a81453 | 346 | |
c4f287c4 | 347 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
26a81453 | 348 | } |
9dc0b289 AV |
349 | |
350 | int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id) | |
351 | { | |
c4f287c4 SM |
352 | u32 in[MLX5_ST_SZ_DW(alloc_flow_counter_in)] = {0}; |
353 | u32 out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0}; | |
9dc0b289 AV |
354 | int err; |
355 | ||
9dc0b289 AV |
356 | MLX5_SET(alloc_flow_counter_in, in, opcode, |
357 | MLX5_CMD_OP_ALLOC_FLOW_COUNTER); | |
358 | ||
c4f287c4 SM |
359 | err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
360 | if (!err) | |
361 | *id = MLX5_GET(alloc_flow_counter_out, out, flow_counter_id); | |
362 | return err; | |
9dc0b289 AV |
363 | } |
364 | ||
365 | int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id) | |
366 | { | |
c4f287c4 SM |
367 | u32 in[MLX5_ST_SZ_DW(dealloc_flow_counter_in)] = {0}; |
368 | u32 out[MLX5_ST_SZ_DW(dealloc_flow_counter_out)] = {0}; | |
9dc0b289 AV |
369 | |
370 | MLX5_SET(dealloc_flow_counter_in, in, opcode, | |
371 | MLX5_CMD_OP_DEALLOC_FLOW_COUNTER); | |
372 | MLX5_SET(dealloc_flow_counter_in, in, flow_counter_id, id); | |
c4f287c4 | 373 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
9dc0b289 AV |
374 | } |
375 | ||
376 | int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u16 id, | |
377 | u64 *packets, u64 *bytes) | |
378 | { | |
379 | u32 out[MLX5_ST_SZ_BYTES(query_flow_counter_out) + | |
c4f287c4 SM |
380 | MLX5_ST_SZ_BYTES(traffic_counter)] = {0}; |
381 | u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0}; | |
9dc0b289 AV |
382 | void *stats; |
383 | int err = 0; | |
384 | ||
9dc0b289 AV |
385 | MLX5_SET(query_flow_counter_in, in, opcode, |
386 | MLX5_CMD_OP_QUERY_FLOW_COUNTER); | |
387 | MLX5_SET(query_flow_counter_in, in, op_mod, 0); | |
388 | MLX5_SET(query_flow_counter_in, in, flow_counter_id, id); | |
c4f287c4 | 389 | err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
9dc0b289 AV |
390 | if (err) |
391 | return err; | |
392 | ||
393 | stats = MLX5_ADDR_OF(query_flow_counter_out, out, flow_statistics); | |
394 | *packets = MLX5_GET64(traffic_counter, stats, packets); | |
395 | *bytes = MLX5_GET64(traffic_counter, stats, octets); | |
9dc0b289 AV |
396 | return 0; |
397 | } | |
a351a1b0 AV |
398 | |
399 | struct mlx5_cmd_fc_bulk { | |
400 | u16 id; | |
401 | int num; | |
402 | int outlen; | |
403 | u32 out[0]; | |
404 | }; | |
405 | ||
406 | struct mlx5_cmd_fc_bulk * | |
407 | mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, u16 id, int num) | |
408 | { | |
409 | struct mlx5_cmd_fc_bulk *b; | |
babd6134 | 410 | int outlen = |
a351a1b0 AV |
411 | MLX5_ST_SZ_BYTES(query_flow_counter_out) + |
412 | MLX5_ST_SZ_BYTES(traffic_counter) * num; | |
413 | ||
babd6134 | 414 | b = kzalloc(sizeof(*b) + outlen, GFP_KERNEL); |
a351a1b0 AV |
415 | if (!b) |
416 | return NULL; | |
417 | ||
418 | b->id = id; | |
419 | b->num = num; | |
420 | b->outlen = outlen; | |
421 | ||
422 | return b; | |
423 | } | |
424 | ||
425 | void mlx5_cmd_fc_bulk_free(struct mlx5_cmd_fc_bulk *b) | |
426 | { | |
427 | kfree(b); | |
428 | } | |
429 | ||
430 | int | |
431 | mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, struct mlx5_cmd_fc_bulk *b) | |
432 | { | |
c4f287c4 | 433 | u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0}; |
a351a1b0 AV |
434 | |
435 | MLX5_SET(query_flow_counter_in, in, opcode, | |
436 | MLX5_CMD_OP_QUERY_FLOW_COUNTER); | |
437 | MLX5_SET(query_flow_counter_in, in, op_mod, 0); | |
438 | MLX5_SET(query_flow_counter_in, in, flow_counter_id, b->id); | |
439 | MLX5_SET(query_flow_counter_in, in, num_of_counters, b->num); | |
c4f287c4 | 440 | return mlx5_cmd_exec(dev, in, sizeof(in), b->out, b->outlen); |
a351a1b0 AV |
441 | } |
442 | ||
443 | void mlx5_cmd_fc_bulk_get(struct mlx5_core_dev *dev, | |
444 | struct mlx5_cmd_fc_bulk *b, u16 id, | |
445 | u64 *packets, u64 *bytes) | |
446 | { | |
447 | int index = id - b->id; | |
448 | void *stats; | |
449 | ||
450 | if (index < 0 || index >= b->num) { | |
451 | mlx5_core_warn(dev, "Flow counter id (0x%x) out of range (0x%x..0x%x). Counter ignored.\n", | |
452 | id, b->id, b->id + b->num - 1); | |
453 | return; | |
454 | } | |
455 | ||
456 | stats = MLX5_ADDR_OF(query_flow_counter_out, b->out, | |
457 | flow_statistics[index]); | |
458 | *packets = MLX5_GET64(traffic_counter, stats, packets); | |
459 | *bytes = MLX5_GET64(traffic_counter, stats, octets); | |
460 | } | |
575ddf58 | 461 | |
ae9f83ac HHZ |
462 | int mlx5_encap_alloc(struct mlx5_core_dev *dev, |
463 | int header_type, | |
464 | size_t size, | |
465 | void *encap_header, | |
466 | u32 *encap_id) | |
575ddf58 | 467 | { |
43f93839 | 468 | int max_encap_size = MLX5_CAP_ESW(dev, max_encap_header_size); |
575ddf58 | 469 | u32 out[MLX5_ST_SZ_DW(alloc_encap_header_out)]; |
43f93839 HHZ |
470 | void *encap_header_in; |
471 | void *header; | |
472 | int inlen; | |
575ddf58 | 473 | int err; |
43f93839 | 474 | u32 *in; |
575ddf58 | 475 | |
43f93839 | 476 | if (size > MLX5_CAP_ESW(dev, max_encap_header_size)) |
575ddf58 IL |
477 | return -EINVAL; |
478 | ||
43f93839 HHZ |
479 | in = kzalloc(MLX5_ST_SZ_BYTES(alloc_encap_header_in) + max_encap_size, |
480 | GFP_KERNEL); | |
481 | if (!in) | |
482 | return -ENOMEM; | |
483 | ||
484 | encap_header_in = MLX5_ADDR_OF(alloc_encap_header_in, in, encap_header); | |
485 | header = MLX5_ADDR_OF(encap_header_in, encap_header_in, encap_header); | |
486 | inlen = header - (void *)in + size; | |
487 | ||
575ddf58 IL |
488 | memset(in, 0, inlen); |
489 | MLX5_SET(alloc_encap_header_in, in, opcode, | |
490 | MLX5_CMD_OP_ALLOC_ENCAP_HEADER); | |
491 | MLX5_SET(encap_header_in, encap_header_in, encap_header_size, size); | |
492 | MLX5_SET(encap_header_in, encap_header_in, header_type, header_type); | |
493 | memcpy(header, encap_header, size); | |
494 | ||
495 | memset(out, 0, sizeof(out)); | |
496 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); | |
497 | ||
498 | *encap_id = MLX5_GET(alloc_encap_header_out, out, encap_id); | |
43f93839 | 499 | kfree(in); |
575ddf58 IL |
500 | return err; |
501 | } | |
502 | ||
ae9f83ac | 503 | void mlx5_encap_dealloc(struct mlx5_core_dev *dev, u32 encap_id) |
575ddf58 IL |
504 | { |
505 | u32 in[MLX5_ST_SZ_DW(dealloc_encap_header_in)]; | |
506 | u32 out[MLX5_ST_SZ_DW(dealloc_encap_header_out)]; | |
507 | ||
508 | memset(in, 0, sizeof(in)); | |
509 | MLX5_SET(dealloc_encap_header_in, in, opcode, | |
510 | MLX5_CMD_OP_DEALLOC_ENCAP_HEADER); | |
511 | MLX5_SET(dealloc_encap_header_in, in, encap_id, encap_id); | |
512 | ||
513 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); | |
514 | } |