1 /*
2 * Copyright (c) 2013-2015, Mellanox Technologies, Ltd. 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/export.h>
34 #include <linux/etherdevice.h>
35 #include <linux/mlx5/driver.h>
36 #include <linux/mlx5/vport.h>
37 #include <linux/mlx5/eswitch.h>
38 #include "mlx5_core.h"
39 #include "eswitch.h"
40 #include "sf/sf.h"
41
42 /* Mutex to hold while enabling or disabling RoCE */
43 static DEFINE_MUTEX(mlx5_roce_en_lock);
44
mlx5_query_vport_state(struct mlx5_core_dev * mdev,u8 opmod,u16 vport)45 u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
46 {
47 u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {};
48 u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {};
49 int err;
50
51 MLX5_SET(query_vport_state_in, in, opcode,
52 MLX5_CMD_OP_QUERY_VPORT_STATE);
53 MLX5_SET(query_vport_state_in, in, op_mod, opmod);
54 MLX5_SET(query_vport_state_in, in, vport_number, vport);
55 if (vport)
56 MLX5_SET(query_vport_state_in, in, other_vport, 1);
57
58 err = mlx5_cmd_exec_inout(mdev, query_vport_state, in, out);
59 if (err)
60 return 0;
61
62 return MLX5_GET(query_vport_state_out, out, state);
63 }
64
mlx5_query_vport_admin_state(struct mlx5_core_dev * mdev,u8 opmod,u16 vport,u8 other_vport,u8 * admin_state)65 static int mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
66 u16 vport, u8 other_vport,
67 u8 *admin_state)
68 {
69 u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {};
70 u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {};
71 int err;
72
73 MLX5_SET(query_vport_state_in, in, opcode,
74 MLX5_CMD_OP_QUERY_VPORT_STATE);
75 MLX5_SET(query_vport_state_in, in, op_mod, opmod);
76 MLX5_SET(query_vport_state_in, in, vport_number, vport);
77 MLX5_SET(query_vport_state_in, in, other_vport, other_vport);
78
79 err = mlx5_cmd_exec_inout(mdev, query_vport_state, in, out);
80 if (err)
81 return err;
82
83 *admin_state = MLX5_GET(query_vport_state_out, out, admin_state);
84 return 0;
85 }
86
mlx5_modify_vport_admin_state(struct mlx5_core_dev * mdev,u8 opmod,u16 vport,u8 other_vport,u8 state)87 int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
88 u16 vport, u8 other_vport, u8 state)
89 {
90 u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {};
91
92 #ifdef CONFIG_MLX5_ESWITCH
93 lockdep_assert_held(&mdev->priv.eswitch->state_lock);
94 #endif
95
96 if (MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed) &&
97 opmod == MLX5_VPORT_STATE_OP_MOD_ESW_VPORT &&
98 vport != MLX5_VPORT_UPLINK) {
99 u32 speed = 0;
100 int err;
101
102 err = mlx5_query_vport_max_tx_speed(mdev, opmod, vport,
103 other_vport, &speed, NULL);
104 if (err) {
105 #ifdef CONFIG_MLX5_ESWITCH
106 struct mlx5_vport *esw_vport;
107
108 esw_vport = mlx5_eswitch_get_vport(mdev->priv.eswitch,
109 vport);
110 speed = IS_ERR(esw_vport) ? 0 :
111 esw_vport->agg_max_tx_speed;
112 #endif
113 mlx5_core_dbg(mdev,
114 "Failed to query vport %d max tx speed, err=%d, using cached %u\n",
115 vport, err, speed);
116 }
117 MLX5_SET(modify_vport_state_in, in, max_tx_speed, speed);
118 }
119
120 MLX5_SET(modify_vport_state_in, in, opcode,
121 MLX5_CMD_OP_MODIFY_VPORT_STATE);
122 MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
123 MLX5_SET(modify_vport_state_in, in, vport_number, vport);
124 MLX5_SET(modify_vport_state_in, in, other_vport, other_vport);
125 MLX5_SET(modify_vport_state_in, in, admin_state, state);
126
127 return mlx5_cmd_exec_in(mdev, modify_vport_state, in);
128 }
129
mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev * mdev,u8 opmod,u16 vport,u8 other_vport,u16 max_tx_speed)130 int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod,
131 u16 vport, u8 other_vport, u16 max_tx_speed)
132 {
133 u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {};
134 u8 admin_state;
135 int err;
136
137 #ifdef CONFIG_MLX5_ESWITCH
138 lockdep_assert_held(&mdev->priv.eswitch->state_lock);
139 #endif
140
141 err = mlx5_query_vport_admin_state(mdev, opmod, vport, other_vport,
142 &admin_state);
143 if (err)
144 return err;
145
146 MLX5_SET(modify_vport_state_in, in, opcode,
147 MLX5_CMD_OP_MODIFY_VPORT_STATE);
148 MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
149 MLX5_SET(modify_vport_state_in, in, vport_number, vport);
150 MLX5_SET(modify_vport_state_in, in, other_vport, other_vport);
151 MLX5_SET(modify_vport_state_in, in, admin_state, admin_state);
152 MLX5_SET(modify_vport_state_in, in, max_tx_speed, max_tx_speed);
153
154 return mlx5_cmd_exec_in(mdev, modify_vport_state, in);
155 }
156
mlx5_query_vport_max_tx_speed(struct mlx5_core_dev * mdev,u8 op_mod,u16 vport,u8 other_vport,u32 * max_tx_speed,u8 * state)157 int mlx5_query_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 op_mod,
158 u16 vport, u8 other_vport,
159 u32 *max_tx_speed, u8 *state)
160 {
161 u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {};
162 u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {};
163 int err;
164
165 MLX5_SET(query_vport_state_in, in, opcode,
166 MLX5_CMD_OP_QUERY_VPORT_STATE);
167 MLX5_SET(query_vport_state_in, in, op_mod, op_mod);
168 MLX5_SET(query_vport_state_in, in, vport_number, vport);
169 MLX5_SET(query_vport_state_in, in, other_vport, other_vport);
170
171 err = mlx5_cmd_exec_inout(mdev, query_vport_state, in, out);
172 if (err)
173 return err;
174
175 *max_tx_speed = MLX5_GET(query_vport_state_out, out, max_tx_speed);
176 if (state)
177 *state = MLX5_GET(query_vport_state_out, out, state);
178 return 0;
179 }
180 EXPORT_SYMBOL_GPL(mlx5_query_vport_max_tx_speed);
181
mlx5_query_nic_vport_context(struct mlx5_core_dev * mdev,u16 vport,bool other_vport,u32 * out)182 static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport,
183 bool other_vport, u32 *out)
184 {
185 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {};
186
187 MLX5_SET(query_nic_vport_context_in, in, opcode,
188 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
189 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
190 MLX5_SET(query_nic_vport_context_in, in, other_vport, other_vport);
191
192 return mlx5_cmd_exec_inout(mdev, query_nic_vport_context, in, out);
193 }
194
mlx5_query_nic_vport_min_inline(struct mlx5_core_dev * mdev,u16 vport,u8 * min_inline)195 int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
196 u16 vport, u8 *min_inline)
197 {
198 u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {};
199 int err;
200
201 err = mlx5_query_nic_vport_context(mdev, vport, vport > 0, out);
202 if (!err)
203 *min_inline = MLX5_GET(query_nic_vport_context_out, out,
204 nic_vport_context.min_wqe_inline_mode);
205 return err;
206 }
207 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_min_inline);
208
mlx5_query_min_inline(struct mlx5_core_dev * mdev,u8 * min_inline_mode)209 void mlx5_query_min_inline(struct mlx5_core_dev *mdev,
210 u8 *min_inline_mode)
211 {
212 switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) {
213 case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
214 if (!mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode))
215 break;
216 fallthrough;
217 case MLX5_CAP_INLINE_MODE_L2:
218 *min_inline_mode = MLX5_INLINE_MODE_L2;
219 break;
220 case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
221 *min_inline_mode = MLX5_INLINE_MODE_NONE;
222 break;
223 }
224 }
225 EXPORT_SYMBOL_GPL(mlx5_query_min_inline);
226
mlx5_modify_nic_vport_min_inline(struct mlx5_core_dev * mdev,u16 vport,u8 min_inline)227 int mlx5_modify_nic_vport_min_inline(struct mlx5_core_dev *mdev,
228 u16 vport, u8 min_inline)
229 {
230 u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {};
231 void *nic_vport_ctx;
232
233 MLX5_SET(modify_nic_vport_context_in, in,
234 field_select.min_inline, 1);
235 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
236 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
237
238 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
239 in, nic_vport_context);
240 MLX5_SET(nic_vport_context, nic_vport_ctx,
241 min_wqe_inline_mode, min_inline);
242 MLX5_SET(modify_nic_vport_context_in, in, opcode,
243 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
244
245 return mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
246 }
247
mlx5_query_nic_vport_mac_address(struct mlx5_core_dev * mdev,u16 vport,bool other,u8 * addr)248 int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev,
249 u16 vport, bool other, u8 *addr)
250 {
251 u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {};
252 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {};
253 u8 *out_addr;
254 int err;
255
256 out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out,
257 nic_vport_context.permanent_address);
258
259 MLX5_SET(query_nic_vport_context_in, in, opcode,
260 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
261 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
262 MLX5_SET(query_nic_vport_context_in, in, other_vport, other);
263
264 err = mlx5_cmd_exec_inout(mdev, query_nic_vport_context, in, out);
265 if (!err)
266 ether_addr_copy(addr, &out_addr[2]);
267
268 return err;
269 }
270 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address);
271
mlx5_query_mac_address(struct mlx5_core_dev * mdev,u8 * addr)272 int mlx5_query_mac_address(struct mlx5_core_dev *mdev, u8 *addr)
273 {
274 return mlx5_query_nic_vport_mac_address(mdev, 0, false, addr);
275 }
276 EXPORT_SYMBOL_GPL(mlx5_query_mac_address);
277
mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev * mdev,u16 vport,const u8 * addr)278 int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev,
279 u16 vport, const u8 *addr)
280 {
281 void *in;
282 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
283 int err;
284 void *nic_vport_ctx;
285 u8 *perm_mac;
286
287 in = kvzalloc(inlen, GFP_KERNEL);
288 if (!in)
289 return -ENOMEM;
290
291 MLX5_SET(modify_nic_vport_context_in, in,
292 field_select.permanent_address, 1);
293 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
294 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
295
296 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
297 in, nic_vport_context);
298 perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx,
299 permanent_address);
300
301 ether_addr_copy(&perm_mac[2], addr);
302 MLX5_SET(modify_nic_vport_context_in, in, opcode,
303 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
304
305 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
306
307 kvfree(in);
308
309 return err;
310 }
311 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_address);
312
mlx5_query_nic_vport_mtu(struct mlx5_core_dev * mdev,u16 * mtu)313 int mlx5_query_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 *mtu)
314 {
315 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
316 u32 *out;
317 int err;
318
319 out = kvzalloc(outlen, GFP_KERNEL);
320 if (!out)
321 return -ENOMEM;
322
323 err = mlx5_query_nic_vport_context(mdev, 0, false, out);
324 if (!err)
325 *mtu = MLX5_GET(query_nic_vport_context_out, out,
326 nic_vport_context.mtu);
327
328 kvfree(out);
329 return err;
330 }
331 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mtu);
332
mlx5_modify_nic_vport_mtu(struct mlx5_core_dev * mdev,u16 mtu)333 int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu)
334 {
335 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
336 void *in;
337 int err;
338
339 in = kvzalloc(inlen, GFP_KERNEL);
340 if (!in)
341 return -ENOMEM;
342
343 MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1);
344 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, mtu);
345 MLX5_SET(modify_nic_vport_context_in, in, opcode,
346 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
347
348 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
349
350 kvfree(in);
351 return err;
352 }
353 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu);
354
mlx5_vport_max_mac_list_size(struct mlx5_core_dev * dev,u16 vport,enum mlx5_list_type list_type)355 static int mlx5_vport_max_mac_list_size(struct mlx5_core_dev *dev, u16 vport,
356 enum mlx5_list_type list_type)
357 {
358 void *query_ctx, *hca_caps;
359 int ret = 0;
360
361 if (!vport && !mlx5_core_is_ecpf(dev))
362 return list_type == MLX5_NVPRT_LIST_TYPE_UC ?
363 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
364 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
365
366 query_ctx = kzalloc(MLX5_ST_SZ_BYTES(query_hca_cap_out), GFP_KERNEL);
367 if (!query_ctx)
368 return -ENOMEM;
369
370 ret = mlx5_vport_get_other_func_general_cap(dev, vport, query_ctx);
371 if (ret)
372 goto out;
373
374 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
375 ret = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
376 1 << MLX5_GET(cmd_hca_cap, hca_caps, log_max_current_uc_list) :
377 1 << MLX5_GET(cmd_hca_cap, hca_caps, log_max_current_mc_list);
378
379 out:
380 kfree(query_ctx);
381
382 return ret;
383 }
384
mlx5_query_nic_vport_mac_list(struct mlx5_core_dev * dev,u16 vport,enum mlx5_list_type list_type,u8 (** addr_list)[ETH_ALEN],int * addr_list_size)385 int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
386 u16 vport,
387 enum mlx5_list_type list_type,
388 u8 (**addr_list)[ETH_ALEN],
389 int *addr_list_size)
390 {
391 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
392 int allowed_list_size;
393 void *nic_vport_ctx;
394 int max_list_size;
395 int out_sz;
396 void *out;
397 int err;
398 int i;
399
400 if (!addr_list || !addr_list_size)
401 return -EINVAL;
402
403 *addr_list = NULL;
404 *addr_list_size = 0;
405
406 max_list_size = mlx5_vport_max_mac_list_size(dev, vport, list_type);
407 if (max_list_size < 0)
408 return max_list_size;
409
410 out_sz = MLX5_ST_SZ_BYTES(query_nic_vport_context_out) +
411 max_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
412
413 out = kvzalloc(out_sz, GFP_KERNEL);
414 if (!out)
415 return -ENOMEM;
416
417 MLX5_SET(query_nic_vport_context_in, in, opcode,
418 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
419 MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
420 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
421 if (vport || mlx5_core_is_ecpf(dev))
422 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
423
424 err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
425 if (err)
426 goto out;
427
428 nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
429 nic_vport_context);
430 allowed_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
431 allowed_list_size);
432 if (!allowed_list_size)
433 goto out;
434
435 *addr_list = kcalloc(allowed_list_size, ETH_ALEN, GFP_KERNEL);
436 if (!*addr_list) {
437 err = -ENOMEM;
438 goto out;
439 }
440
441 for (i = 0; i < allowed_list_size; i++) {
442 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
443 nic_vport_ctx,
444 current_uc_mac_address[i]) + 2;
445 ether_addr_copy((*addr_list)[i], mac_addr);
446 }
447 *addr_list_size = allowed_list_size;
448 out:
449 kvfree(out);
450 return err;
451 }
452 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list);
453
mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev * dev,enum mlx5_list_type list_type,u8 addr_list[][ETH_ALEN],int list_size)454 int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
455 enum mlx5_list_type list_type,
456 u8 addr_list[][ETH_ALEN],
457 int list_size)
458 {
459 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {};
460 void *nic_vport_ctx;
461 int max_list_size;
462 int in_sz;
463 void *in;
464 int err;
465 int i;
466
467 max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
468 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
469 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
470
471 if (list_size > max_list_size)
472 return -ENOSPC;
473
474 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
475 list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
476
477 in = kvzalloc(in_sz, GFP_KERNEL);
478 if (!in)
479 return -ENOMEM;
480
481 MLX5_SET(modify_nic_vport_context_in, in, opcode,
482 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
483 MLX5_SET(modify_nic_vport_context_in, in,
484 field_select.addresses_list, 1);
485
486 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
487 nic_vport_context);
488
489 MLX5_SET(nic_vport_context, nic_vport_ctx,
490 allowed_list_type, list_type);
491 MLX5_SET(nic_vport_context, nic_vport_ctx,
492 allowed_list_size, list_size);
493
494 for (i = 0; i < list_size; i++) {
495 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context,
496 nic_vport_ctx,
497 current_uc_mac_address[i]) + 2;
498 ether_addr_copy(curr_mac, addr_list[i]);
499 }
500
501 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
502 kvfree(in);
503 return err;
504 }
505 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
506
mlx5_modify_nic_vport_vlans(struct mlx5_core_dev * dev,u16 vlans[],int list_size)507 int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
508 u16 vlans[],
509 int list_size)
510 {
511 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
512 void *nic_vport_ctx;
513 int max_list_size;
514 int in_sz;
515 void *in;
516 int err;
517 int i;
518
519 max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
520
521 if (list_size > max_list_size)
522 return -ENOSPC;
523
524 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
525 list_size * MLX5_ST_SZ_BYTES(vlan_layout);
526
527 memset(out, 0, sizeof(out));
528 in = kvzalloc(in_sz, GFP_KERNEL);
529 if (!in)
530 return -ENOMEM;
531
532 MLX5_SET(modify_nic_vport_context_in, in, opcode,
533 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
534 MLX5_SET(modify_nic_vport_context_in, in,
535 field_select.addresses_list, 1);
536
537 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
538 nic_vport_context);
539
540 MLX5_SET(nic_vport_context, nic_vport_ctx,
541 allowed_list_type, MLX5_NVPRT_LIST_TYPE_VLAN);
542 MLX5_SET(nic_vport_context, nic_vport_ctx,
543 allowed_list_size, list_size);
544
545 for (i = 0; i < list_size; i++) {
546 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
547 nic_vport_ctx,
548 current_uc_mac_address[i]);
549 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]);
550 }
551
552 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
553 kvfree(in);
554 return err;
555 }
556 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans);
557
mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev * mdev,u64 * system_image_guid)558 int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
559 u64 *system_image_guid)
560 {
561 u32 *out;
562 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
563 int err;
564
565 out = kvzalloc(outlen, GFP_KERNEL);
566 if (!out)
567 return -ENOMEM;
568
569 err = mlx5_query_nic_vport_context(mdev, 0, false, out);
570 if (err)
571 goto out;
572
573 *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out,
574 nic_vport_context.system_image_guid);
575 out:
576 kvfree(out);
577 return err;
578 }
579 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid);
580
mlx5_query_nic_vport_sd_group(struct mlx5_core_dev * mdev,u8 * sd_group,u8 * sd_group_size)581 int mlx5_query_nic_vport_sd_group(struct mlx5_core_dev *mdev, u8 *sd_group,
582 u8 *sd_group_size)
583 {
584 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
585 u32 *out;
586 int err;
587
588 out = kvzalloc(outlen, GFP_KERNEL);
589 if (!out)
590 return -ENOMEM;
591
592 err = mlx5_query_nic_vport_context(mdev, 0, false, out);
593 if (err)
594 goto out;
595
596 *sd_group = MLX5_GET(query_nic_vport_context_out, out,
597 nic_vport_context.sd_group);
598 if (MLX5_CAP_GEN(mdev, sd_group_size))
599 *sd_group_size = MLX5_GET(query_nic_vport_context_out, out,
600 nic_vport_context.sd_group_size);
601 out:
602 kvfree(out);
603 return err;
604 }
605
mlx5_query_nic_vport_node_guid(struct mlx5_core_dev * mdev,u16 vport,bool other_vport,u64 * node_guid)606 int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev,
607 u16 vport, bool other_vport, u64 *node_guid)
608 {
609 u32 *out;
610 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
611 int err;
612
613 out = kvzalloc(outlen, GFP_KERNEL);
614 if (!out)
615 return -ENOMEM;
616
617 err = mlx5_query_nic_vport_context(mdev, vport, other_vport, out);
618 if (err)
619 goto out;
620
621 *node_guid = MLX5_GET64(query_nic_vport_context_out, out,
622 nic_vport_context.node_guid);
623 out:
624 kvfree(out);
625
626 return err;
627 }
628 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
629
mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev * mdev,u16 vport,u64 node_guid)630 int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
631 u16 vport, u64 node_guid)
632 {
633 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
634 void *nic_vport_context;
635 void *in;
636 int err;
637
638 if (!MLX5_CAP_GEN(mdev, vport_group_manager))
639 return -EACCES;
640
641 in = kvzalloc(inlen, GFP_KERNEL);
642 if (!in)
643 return -ENOMEM;
644
645 MLX5_SET(modify_nic_vport_context_in, in,
646 field_select.node_guid, 1);
647 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
648 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
649
650 nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
651 in, nic_vport_context);
652 MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid);
653 MLX5_SET(modify_nic_vport_context_in, in, opcode,
654 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
655
656 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
657
658 kvfree(in);
659
660 return err;
661 }
662
mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev * mdev,u16 * qkey_viol_cntr)663 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
664 u16 *qkey_viol_cntr)
665 {
666 u32 *out;
667 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
668 int err;
669
670 out = kvzalloc(outlen, GFP_KERNEL);
671 if (!out)
672 return -ENOMEM;
673
674 err = mlx5_query_nic_vport_context(mdev, 0, false, out);
675 if (err)
676 goto out;
677
678 *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out,
679 nic_vport_context.qkey_violation_counter);
680 out:
681 kvfree(out);
682
683 return err;
684 }
685 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr);
686
mlx5_query_hca_vport_gid(struct mlx5_core_dev * dev,u8 other_vport,u8 port_num,u16 vf_num,u16 gid_index,union ib_gid * gid)687 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
688 u8 port_num, u16 vf_num, u16 gid_index,
689 union ib_gid *gid)
690 {
691 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in);
692 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
693 int is_group_manager;
694 void *out = NULL;
695 void *in = NULL;
696 union ib_gid *tmp;
697 int tbsz;
698 int nout;
699 int err;
700
701 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
702 tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size));
703 mlx5_core_dbg(dev, "vf_num %d, index %d, gid_table_size %d\n",
704 vf_num, gid_index, tbsz);
705
706 if (gid_index > tbsz && gid_index != 0xffff)
707 return -EINVAL;
708
709 if (gid_index == 0xffff)
710 nout = tbsz;
711 else
712 nout = 1;
713
714 out_sz += nout * sizeof(*gid);
715
716 in = kvzalloc(in_sz, GFP_KERNEL);
717 out = kvzalloc(out_sz, GFP_KERNEL);
718 if (!in || !out) {
719 err = -ENOMEM;
720 goto out;
721 }
722
723 MLX5_SET(query_hca_vport_gid_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_GID);
724 if (other_vport) {
725 if (is_group_manager) {
726 MLX5_SET(query_hca_vport_gid_in, in, vport_number, vf_num);
727 MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1);
728 } else {
729 err = -EPERM;
730 goto out;
731 }
732 }
733 MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index);
734
735 if (MLX5_CAP_GEN(dev, num_ports) == 2)
736 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num);
737
738 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
739 if (err)
740 goto out;
741
742 tmp = out + MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
743 gid->global.subnet_prefix = tmp->global.subnet_prefix;
744 gid->global.interface_id = tmp->global.interface_id;
745
746 out:
747 kvfree(in);
748 kvfree(out);
749 return err;
750 }
751 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid);
752
mlx5_query_hca_vport_pkey(struct mlx5_core_dev * dev,u8 other_vport,u8 port_num,u16 vf_num,u16 pkey_index,u16 * pkey)753 int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
754 u8 port_num, u16 vf_num, u16 pkey_index,
755 u16 *pkey)
756 {
757 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in);
758 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out);
759 int is_group_manager;
760 void *out = NULL;
761 void *in = NULL;
762 void *pkarr;
763 int nout;
764 int tbsz;
765 int err;
766 int i;
767
768 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
769
770 tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size));
771 if (pkey_index > tbsz && pkey_index != 0xffff)
772 return -EINVAL;
773
774 if (pkey_index == 0xffff)
775 nout = tbsz;
776 else
777 nout = 1;
778
779 out_sz += nout * MLX5_ST_SZ_BYTES(pkey);
780
781 in = kvzalloc(in_sz, GFP_KERNEL);
782 out = kvzalloc(out_sz, GFP_KERNEL);
783 if (!in || !out) {
784 err = -ENOMEM;
785 goto out;
786 }
787
788 MLX5_SET(query_hca_vport_pkey_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY);
789 if (other_vport) {
790 if (is_group_manager) {
791 MLX5_SET(query_hca_vport_pkey_in, in, vport_number, vf_num);
792 MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1);
793 } else {
794 err = -EPERM;
795 goto out;
796 }
797 }
798 MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index);
799
800 if (MLX5_CAP_GEN(dev, num_ports) == 2)
801 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num);
802
803 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
804 if (err)
805 goto out;
806
807 pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey);
808 for (i = 0; i < nout; i++, pkey++, pkarr += MLX5_ST_SZ_BYTES(pkey))
809 *pkey = MLX5_GET_PR(pkey, pkarr, pkey);
810
811 out:
812 kvfree(in);
813 kvfree(out);
814 return err;
815 }
816 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey);
817
mlx5_query_hca_vport_context(struct mlx5_core_dev * dev,u8 other_vport,u8 port_num,u16 vf_num,struct mlx5_hca_vport_context * rep)818 int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev,
819 u8 other_vport, u8 port_num,
820 u16 vf_num,
821 struct mlx5_hca_vport_context *rep)
822 {
823 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
824 int in[MLX5_ST_SZ_DW(query_hca_vport_context_in)] = {};
825 int is_group_manager;
826 void *out;
827 void *ctx;
828 int err;
829
830 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
831
832 out = kvzalloc(out_sz, GFP_KERNEL);
833 if (!out)
834 return -ENOMEM;
835
836 MLX5_SET(query_hca_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT);
837
838 if (other_vport) {
839 if (is_group_manager) {
840 MLX5_SET(query_hca_vport_context_in, in, other_vport, 1);
841 MLX5_SET(query_hca_vport_context_in, in, vport_number, vf_num);
842 } else {
843 err = -EPERM;
844 goto ex;
845 }
846 }
847
848 if (MLX5_CAP_GEN(dev, num_ports) == 2)
849 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num);
850
851 err = mlx5_cmd_exec_inout(dev, query_hca_vport_context, in, out);
852 if (err)
853 goto ex;
854
855 ctx = MLX5_ADDR_OF(query_hca_vport_context_out, out, hca_vport_context);
856 rep->field_select = MLX5_GET_PR(hca_vport_context, ctx, field_select);
857 rep->sm_virt_aware = MLX5_GET_PR(hca_vport_context, ctx, sm_virt_aware);
858 rep->has_smi = MLX5_GET_PR(hca_vport_context, ctx, has_smi);
859 rep->has_raw = MLX5_GET_PR(hca_vport_context, ctx, has_raw);
860 rep->policy = MLX5_GET_PR(hca_vport_context, ctx, vport_state_policy);
861 rep->phys_state = MLX5_GET_PR(hca_vport_context, ctx,
862 port_physical_state);
863 rep->vport_state = MLX5_GET_PR(hca_vport_context, ctx, vport_state);
864 rep->port_physical_state = MLX5_GET_PR(hca_vport_context, ctx,
865 port_physical_state);
866 rep->port_guid = MLX5_GET64_PR(hca_vport_context, ctx, port_guid);
867 rep->node_guid = MLX5_GET64_PR(hca_vport_context, ctx, node_guid);
868 rep->cap_mask1 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask1);
869 rep->cap_mask1_perm = MLX5_GET_PR(hca_vport_context, ctx,
870 cap_mask1_field_select);
871 rep->cap_mask2 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask2);
872 rep->cap_mask2_perm = MLX5_GET_PR(hca_vport_context, ctx,
873 cap_mask2_field_select);
874 rep->lid = MLX5_GET_PR(hca_vport_context, ctx, lid);
875 rep->init_type_reply = MLX5_GET_PR(hca_vport_context, ctx,
876 init_type_reply);
877 rep->lmc = MLX5_GET_PR(hca_vport_context, ctx, lmc);
878 rep->subnet_timeout = MLX5_GET_PR(hca_vport_context, ctx,
879 subnet_timeout);
880 rep->sm_lid = MLX5_GET_PR(hca_vport_context, ctx, sm_lid);
881 rep->sm_sl = MLX5_GET_PR(hca_vport_context, ctx, sm_sl);
882 rep->qkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
883 qkey_violation_counter);
884 rep->pkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
885 pkey_violation_counter);
886 rep->grh_required = MLX5_GET_PR(hca_vport_context, ctx, grh_required);
887 rep->sys_image_guid = MLX5_GET64_PR(hca_vport_context, ctx,
888 system_image_guid);
889 rep->num_plane = MLX5_GET_PR(hca_vport_context, ctx, num_port_plane);
890
891 ex:
892 kvfree(out);
893 return err;
894 }
895 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context);
896
mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev * dev,u64 * sys_image_guid)897 int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev,
898 u64 *sys_image_guid)
899 {
900 struct mlx5_hca_vport_context *rep;
901 int err;
902
903 rep = kvzalloc_obj(*rep);
904 if (!rep)
905 return -ENOMEM;
906
907 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
908 if (!err)
909 *sys_image_guid = rep->sys_image_guid;
910
911 kvfree(rep);
912 return err;
913 }
914 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid);
915
mlx5_query_hca_vport_node_guid(struct mlx5_core_dev * dev,u64 * node_guid)916 int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
917 u64 *node_guid)
918 {
919 struct mlx5_hca_vport_context *rep;
920 int err;
921
922 rep = kvzalloc_obj(*rep);
923 if (!rep)
924 return -ENOMEM;
925
926 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
927 if (!err)
928 *node_guid = rep->node_guid;
929
930 kvfree(rep);
931 return err;
932 }
933 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
934
mlx5_query_nic_vport_promisc(struct mlx5_core_dev * mdev,u16 vport,int * promisc_uc,int * promisc_mc,int * promisc_all)935 int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
936 u16 vport,
937 int *promisc_uc,
938 int *promisc_mc,
939 int *promisc_all)
940 {
941 u32 *out;
942 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
943 int err;
944
945 out = kvzalloc(outlen, GFP_KERNEL);
946 if (!out)
947 return -ENOMEM;
948
949 err = mlx5_query_nic_vport_context(mdev, vport, vport > 0, out);
950 if (err)
951 goto out;
952
953 *promisc_uc = MLX5_GET(query_nic_vport_context_out, out,
954 nic_vport_context.promisc_uc);
955 *promisc_mc = MLX5_GET(query_nic_vport_context_out, out,
956 nic_vport_context.promisc_mc);
957 *promisc_all = MLX5_GET(query_nic_vport_context_out, out,
958 nic_vport_context.promisc_all);
959
960 out:
961 kvfree(out);
962 return err;
963 }
964 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
965
mlx5_modify_nic_vport_promisc(struct mlx5_core_dev * mdev,int promisc_uc,int promisc_mc,int promisc_all)966 int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,
967 int promisc_uc,
968 int promisc_mc,
969 int promisc_all)
970 {
971 void *in;
972 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
973 int err;
974
975 in = kvzalloc(inlen, GFP_KERNEL);
976 if (!in)
977 return -ENOMEM;
978
979 MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
980 MLX5_SET(modify_nic_vport_context_in, in,
981 nic_vport_context.promisc_uc, promisc_uc);
982 MLX5_SET(modify_nic_vport_context_in, in,
983 nic_vport_context.promisc_mc, promisc_mc);
984 MLX5_SET(modify_nic_vport_context_in, in,
985 nic_vport_context.promisc_all, promisc_all);
986 MLX5_SET(modify_nic_vport_context_in, in, opcode,
987 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
988
989 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
990
991 kvfree(in);
992
993 return err;
994 }
995 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc);
996
997 enum {
998 UC_LOCAL_LB,
999 MC_LOCAL_LB
1000 };
1001
mlx5_nic_vport_update_local_lb(struct mlx5_core_dev * mdev,bool enable)1002 int mlx5_nic_vport_update_local_lb(struct mlx5_core_dev *mdev, bool enable)
1003 {
1004 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1005 void *in;
1006 int err;
1007
1008 if (!MLX5_CAP_GEN(mdev, disable_local_lb_mc) &&
1009 !MLX5_CAP_GEN(mdev, disable_local_lb_uc))
1010 return 0;
1011
1012 in = kvzalloc(inlen, GFP_KERNEL);
1013 if (!in)
1014 return -ENOMEM;
1015
1016 MLX5_SET(modify_nic_vport_context_in, in,
1017 nic_vport_context.disable_mc_local_lb, !enable);
1018 MLX5_SET(modify_nic_vport_context_in, in,
1019 nic_vport_context.disable_uc_local_lb, !enable);
1020
1021 if (MLX5_CAP_GEN(mdev, disable_local_lb_mc))
1022 MLX5_SET(modify_nic_vport_context_in, in,
1023 field_select.disable_mc_local_lb, 1);
1024
1025 if (MLX5_CAP_GEN(mdev, disable_local_lb_uc))
1026 MLX5_SET(modify_nic_vport_context_in, in,
1027 field_select.disable_uc_local_lb, 1);
1028 MLX5_SET(modify_nic_vport_context_in, in, opcode,
1029 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
1030
1031 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
1032
1033 if (!err)
1034 mlx5_core_dbg(mdev, "%s local_lb\n",
1035 enable ? "enable" : "disable");
1036
1037 kvfree(in);
1038 return err;
1039 }
1040 EXPORT_SYMBOL_GPL(mlx5_nic_vport_update_local_lb);
1041
mlx5_nic_vport_query_local_lb(struct mlx5_core_dev * mdev,bool * status)1042 int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status)
1043 {
1044 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1045 u32 *out;
1046 int value;
1047 int err;
1048
1049 out = kvzalloc(outlen, GFP_KERNEL);
1050 if (!out)
1051 return -ENOMEM;
1052
1053 err = mlx5_query_nic_vport_context(mdev, 0, false, out);
1054 if (err)
1055 goto out;
1056
1057 value = MLX5_GET(query_nic_vport_context_out, out,
1058 nic_vport_context.disable_mc_local_lb) << MC_LOCAL_LB;
1059
1060 value |= MLX5_GET(query_nic_vport_context_out, out,
1061 nic_vport_context.disable_uc_local_lb) << UC_LOCAL_LB;
1062
1063 *status = !value;
1064
1065 out:
1066 kvfree(out);
1067 return err;
1068 }
1069 EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb);
1070
1071 enum mlx5_vport_roce_state {
1072 MLX5_VPORT_ROCE_DISABLED = 0,
1073 MLX5_VPORT_ROCE_ENABLED = 1,
1074 };
1075
mlx5_nic_vport_update_roce_state(struct mlx5_core_dev * mdev,enum mlx5_vport_roce_state state)1076 static int mlx5_nic_vport_update_roce_state(struct mlx5_core_dev *mdev,
1077 enum mlx5_vport_roce_state state)
1078 {
1079 void *in;
1080 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1081 int err;
1082
1083 in = kvzalloc(inlen, GFP_KERNEL);
1084 if (!in)
1085 return -ENOMEM;
1086
1087 MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1);
1088 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en,
1089 state);
1090 MLX5_SET(modify_nic_vport_context_in, in, opcode,
1091 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
1092
1093 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
1094
1095 kvfree(in);
1096
1097 return err;
1098 }
1099
mlx5_nic_vport_enable_roce(struct mlx5_core_dev * mdev)1100 int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev)
1101 {
1102 int err = 0;
1103
1104 mutex_lock(&mlx5_roce_en_lock);
1105 if (!mdev->roce.roce_en)
1106 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED);
1107
1108 if (!err)
1109 mdev->roce.roce_en++;
1110 mutex_unlock(&mlx5_roce_en_lock);
1111
1112 return err;
1113 }
1114 EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce);
1115
mlx5_nic_vport_disable_roce(struct mlx5_core_dev * mdev)1116 int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev)
1117 {
1118 int err = 0;
1119
1120 mutex_lock(&mlx5_roce_en_lock);
1121 if (mdev->roce.roce_en) {
1122 mdev->roce.roce_en--;
1123 if (mdev->roce.roce_en == 0)
1124 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED);
1125
1126 if (err)
1127 mdev->roce.roce_en++;
1128 }
1129 mutex_unlock(&mlx5_roce_en_lock);
1130 return err;
1131 }
1132 EXPORT_SYMBOL(mlx5_nic_vport_disable_roce);
1133
mlx5_core_query_vport_counter(struct mlx5_core_dev * dev,u8 other_vport,int vf,u8 port_num,void * out)1134 int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport,
1135 int vf, u8 port_num, void *out)
1136 {
1137 int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in);
1138 int is_group_manager;
1139 void *in;
1140 int err;
1141
1142 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1143 in = kvzalloc(in_sz, GFP_KERNEL);
1144 if (!in) {
1145 err = -ENOMEM;
1146 return err;
1147 }
1148
1149 MLX5_SET(query_vport_counter_in, in, opcode,
1150 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
1151 if (other_vport) {
1152 if (is_group_manager) {
1153 MLX5_SET(query_vport_counter_in, in, other_vport, 1);
1154 MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1);
1155 } else {
1156 err = -EPERM;
1157 goto free;
1158 }
1159 }
1160 if (MLX5_CAP_GEN(dev, num_ports) == 2)
1161 MLX5_SET(query_vport_counter_in, in, port_num, port_num);
1162
1163 err = mlx5_cmd_exec_inout(dev, query_vport_counter, in, out);
1164 free:
1165 kvfree(in);
1166 return err;
1167 }
1168 EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter);
1169
mlx5_query_vport_down_stats(struct mlx5_core_dev * mdev,u16 vport,u8 other_vport,u64 * rx_discard_vport_down,u64 * tx_discard_vport_down)1170 int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport,
1171 u8 other_vport, u64 *rx_discard_vport_down,
1172 u64 *tx_discard_vport_down)
1173 {
1174 u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {};
1175 u32 in[MLX5_ST_SZ_DW(query_vnic_env_in)] = {};
1176 int err;
1177
1178 MLX5_SET(query_vnic_env_in, in, opcode,
1179 MLX5_CMD_OP_QUERY_VNIC_ENV);
1180 MLX5_SET(query_vnic_env_in, in, op_mod, 0);
1181 MLX5_SET(query_vnic_env_in, in, vport_number, vport);
1182 MLX5_SET(query_vnic_env_in, in, other_vport, other_vport);
1183
1184 err = mlx5_cmd_exec_inout(mdev, query_vnic_env, in, out);
1185 if (err)
1186 return err;
1187
1188 *rx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out,
1189 vport_env.receive_discard_vport_down);
1190 *tx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out,
1191 vport_env.transmit_discard_vport_down);
1192 return 0;
1193 }
1194
mlx5_core_modify_hca_vport_context(struct mlx5_core_dev * dev,u8 other_vport,u8 port_num,int vf,struct mlx5_hca_vport_context * req)1195 int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev,
1196 u8 other_vport, u8 port_num,
1197 int vf,
1198 struct mlx5_hca_vport_context *req)
1199 {
1200 int in_sz = MLX5_ST_SZ_BYTES(modify_hca_vport_context_in);
1201 int is_group_manager;
1202 void *ctx;
1203 void *in;
1204 int err;
1205
1206 mlx5_core_dbg(dev, "vf %d\n", vf);
1207 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1208 in = kvzalloc(in_sz, GFP_KERNEL);
1209 if (!in)
1210 return -ENOMEM;
1211
1212 MLX5_SET(modify_hca_vport_context_in, in, opcode, MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT);
1213 if (other_vport) {
1214 if (is_group_manager) {
1215 MLX5_SET(modify_hca_vport_context_in, in, other_vport, 1);
1216 MLX5_SET(modify_hca_vport_context_in, in, vport_number, vf);
1217 } else {
1218 err = -EPERM;
1219 goto ex;
1220 }
1221 }
1222
1223 if (MLX5_CAP_GEN(dev, num_ports) > 1)
1224 MLX5_SET(modify_hca_vport_context_in, in, port_num, port_num);
1225
1226 ctx = MLX5_ADDR_OF(modify_hca_vport_context_in, in, hca_vport_context);
1227 MLX5_SET(hca_vport_context, ctx, field_select, req->field_select);
1228 if (req->field_select & MLX5_HCA_VPORT_SEL_STATE_POLICY)
1229 MLX5_SET(hca_vport_context, ctx, vport_state_policy,
1230 req->policy);
1231 if (req->field_select & MLX5_HCA_VPORT_SEL_PORT_GUID)
1232 MLX5_SET64(hca_vport_context, ctx, port_guid, req->port_guid);
1233 if (req->field_select & MLX5_HCA_VPORT_SEL_NODE_GUID)
1234 MLX5_SET64(hca_vport_context, ctx, node_guid, req->node_guid);
1235 MLX5_SET(hca_vport_context, ctx, cap_mask1, req->cap_mask1);
1236 MLX5_SET(hca_vport_context, ctx, cap_mask1_field_select,
1237 req->cap_mask1_perm);
1238 err = mlx5_cmd_exec_in(dev, modify_hca_vport_context, in);
1239 ex:
1240 kvfree(in);
1241 return err;
1242 }
1243 EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context);
1244
mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev * master_mdev,struct mlx5_core_dev * port_mdev)1245 int mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev *master_mdev,
1246 struct mlx5_core_dev *port_mdev)
1247 {
1248 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1249 void *in;
1250 int err;
1251
1252 in = kvzalloc(inlen, GFP_KERNEL);
1253 if (!in)
1254 return -ENOMEM;
1255
1256 err = mlx5_nic_vport_enable_roce(port_mdev);
1257 if (err)
1258 goto free;
1259
1260 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1);
1261 if (MLX5_CAP_GEN_2(master_mdev, sw_vhca_id_valid)) {
1262 MLX5_SET(modify_nic_vport_context_in, in,
1263 nic_vport_context.vhca_id_type, VHCA_ID_TYPE_SW);
1264 MLX5_SET(modify_nic_vport_context_in, in,
1265 nic_vport_context.affiliated_vhca_id,
1266 MLX5_CAP_GEN_2(master_mdev, sw_vhca_id));
1267 } else {
1268 MLX5_SET(modify_nic_vport_context_in, in,
1269 nic_vport_context.affiliated_vhca_id,
1270 MLX5_CAP_GEN(master_mdev, vhca_id));
1271 }
1272 MLX5_SET(modify_nic_vport_context_in, in,
1273 nic_vport_context.affiliation_criteria,
1274 MLX5_CAP_GEN(port_mdev, affiliate_nic_vport_criteria));
1275 MLX5_SET(modify_nic_vport_context_in, in, opcode,
1276 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
1277
1278 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in);
1279 if (err)
1280 mlx5_nic_vport_disable_roce(port_mdev);
1281
1282 free:
1283 kvfree(in);
1284 return err;
1285 }
1286 EXPORT_SYMBOL_GPL(mlx5_nic_vport_affiliate_multiport);
1287
mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev * port_mdev)1288 int mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev *port_mdev)
1289 {
1290 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1291 void *in;
1292 int err;
1293
1294 in = kvzalloc(inlen, GFP_KERNEL);
1295 if (!in)
1296 return -ENOMEM;
1297
1298 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1);
1299 MLX5_SET(modify_nic_vport_context_in, in,
1300 nic_vport_context.affiliated_vhca_id, 0);
1301 MLX5_SET(modify_nic_vport_context_in, in,
1302 nic_vport_context.affiliation_criteria, 0);
1303 MLX5_SET(modify_nic_vport_context_in, in, opcode,
1304 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
1305
1306 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in);
1307 if (!err)
1308 mlx5_nic_vport_disable_roce(port_mdev);
1309
1310 kvfree(in);
1311 return err;
1312 }
1313 EXPORT_SYMBOL_GPL(mlx5_nic_vport_unaffiliate_multiport);
1314
mlx5_query_nic_system_image_guid(struct mlx5_core_dev * mdev)1315 u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev)
1316 {
1317 int port_type_cap = MLX5_CAP_GEN(mdev, port_type);
1318 u64 tmp;
1319 int err;
1320
1321 if (mdev->sys_image_guid)
1322 return mdev->sys_image_guid;
1323
1324 if (port_type_cap == MLX5_CAP_PORT_TYPE_ETH)
1325 err = mlx5_query_nic_vport_system_image_guid(mdev, &tmp);
1326 else
1327 err = mlx5_query_hca_vport_system_image_guid(mdev, &tmp);
1328
1329 mdev->sys_image_guid = err ? 0 : tmp;
1330
1331 return mdev->sys_image_guid;
1332 }
1333 EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid);
1334
mlx5_query_nic_sw_system_image_guid(struct mlx5_core_dev * mdev,u8 * buf,u8 * len)1335 void mlx5_query_nic_sw_system_image_guid(struct mlx5_core_dev *mdev, u8 *buf,
1336 u8 *len)
1337 {
1338 u64 fw_system_image_guid;
1339
1340 *len = 0;
1341
1342 fw_system_image_guid = mlx5_query_nic_system_image_guid(mdev);
1343 if (!fw_system_image_guid)
1344 return;
1345
1346 memcpy(buf, &fw_system_image_guid, sizeof(fw_system_image_guid));
1347 *len += sizeof(fw_system_image_guid);
1348
1349 if (MLX5_CAP_GEN_2(mdev, load_balance_id) &&
1350 MLX5_CAP_GEN_2(mdev, lag_per_mp_group))
1351 buf[(*len)++] = MLX5_CAP_GEN_2(mdev, load_balance_id);
1352 }
1353
mlx5_vport_use_vhca_id_as_func_id(struct mlx5_core_dev * dev,u16 vport_num,u16 * vhca_id)1354 bool mlx5_vport_use_vhca_id_as_func_id(struct mlx5_core_dev *dev,
1355 u16 vport_num, u16 *vhca_id)
1356 {
1357 if (!MLX5_CAP_GEN_2(dev, function_id_type_vhca_id))
1358 return false;
1359
1360 return mlx5_esw_vport_vhca_id(dev->priv.eswitch, vport_num, vhca_id);
1361 }
1362
mlx5_vport_get_other_func_cap(struct mlx5_core_dev * dev,u16 vport,void * out,u16 opmod)1363 int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 vport, void *out,
1364 u16 opmod)
1365 {
1366 u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {};
1367 u16 vhca_id = 0, function_id = 0;
1368 bool ec_vf_func = false;
1369
1370 /* if this vport is referring to a vport on the ec PF (embedded cpu )
1371 * let the FW know which domain we are querying since vport numbers or
1372 * function_ids are not unique across the different PF domains,
1373 * unless we use vhca_id as the function_id below.
1374 */
1375 ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport);
1376 function_id = mlx5_vport_to_func_id(dev, vport, ec_vf_func);
1377
1378 if (mlx5_vport_use_vhca_id_as_func_id(dev, vport, &vhca_id)) {
1379 MLX5_SET(query_hca_cap_in, in, function_id_type, 1);
1380 function_id = vhca_id;
1381 ec_vf_func = false;
1382 mlx5_core_dbg(dev, "%s using vhca_id as function_id for vport %d vhca_id 0x%x\n",
1383 __func__, vport, vhca_id);
1384 }
1385
1386 opmod = (opmod << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01);
1387 MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
1388 MLX5_SET(query_hca_cap_in, in, op_mod, opmod);
1389 MLX5_SET(query_hca_cap_in, in, other_function, true);
1390 MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func);
1391 MLX5_SET(query_hca_cap_in, in, function_id, function_id);
1392 return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out);
1393 }
1394 EXPORT_SYMBOL_GPL(mlx5_vport_get_other_func_cap);
1395
mlx5_vport_get_vhca_id(struct mlx5_core_dev * dev,u16 vport,u16 * vhca_id)1396 int mlx5_vport_get_vhca_id(struct mlx5_core_dev *dev, u16 vport, u16 *vhca_id)
1397 {
1398 int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
1399 void *query_ctx;
1400 void *hca_caps;
1401 int err;
1402
1403 /* try get vhca_id via eswitch */
1404 if (mlx5_esw_vport_vhca_id(dev->priv.eswitch, vport, vhca_id))
1405 return 0;
1406
1407 query_ctx = kvzalloc(query_out_sz, GFP_KERNEL);
1408 if (!query_ctx)
1409 return -ENOMEM;
1410
1411 err = mlx5_vport_get_other_func_general_cap(dev, vport, query_ctx);
1412 if (err)
1413 goto out_free;
1414
1415 hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
1416 *vhca_id = MLX5_GET(cmd_hca_cap, hca_caps, vhca_id);
1417
1418 out_free:
1419 kvfree(query_ctx);
1420 return err;
1421 }
1422 EXPORT_SYMBOL_GPL(mlx5_vport_get_vhca_id);
1423
mlx5_vport_set_other_func_cap(struct mlx5_core_dev * dev,const void * hca_cap,u16 vport,u16 opmod)1424 int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap,
1425 u16 vport, u16 opmod)
1426 {
1427 int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
1428 u16 vhca_id = 0, function_id = 0;
1429 bool ec_vf_func = false;
1430 void *set_hca_cap;
1431 void *set_ctx;
1432 int ret;
1433
1434 set_ctx = kvzalloc(set_sz, GFP_KERNEL);
1435 if (!set_ctx)
1436 return -ENOMEM;
1437
1438 /* if this vport is referring to a vport on the ec PF (embedded cpu )
1439 * let the FW know which domain we are querying since vport numbers or
1440 * function_ids are not unique across the different PF domains,
1441 * unless we use vhca_id as the function_id below.
1442 */
1443 ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport);
1444 function_id = mlx5_vport_to_func_id(dev, vport, ec_vf_func);
1445
1446 if (mlx5_vport_use_vhca_id_as_func_id(dev, vport, &vhca_id)) {
1447 MLX5_SET(set_hca_cap_in, set_ctx, function_id_type, 1);
1448 function_id = vhca_id;
1449 ec_vf_func = false;
1450 mlx5_core_dbg(dev, "%s using vhca_id as function_id for vport %d vhca_id 0x%x\n",
1451 __func__, vport, vhca_id);
1452 }
1453
1454 MLX5_SET(set_hca_cap_in, set_ctx, opcode, MLX5_CMD_OP_SET_HCA_CAP);
1455 MLX5_SET(set_hca_cap_in, set_ctx, op_mod, opmod << 1);
1456 set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability);
1457 memcpy(set_hca_cap, hca_cap, MLX5_ST_SZ_BYTES(cmd_hca_cap));
1458 MLX5_SET(set_hca_cap_in, set_ctx, other_function, true);
1459 MLX5_SET(set_hca_cap_in, set_ctx, ec_vf_function, ec_vf_func);
1460 MLX5_SET(set_hca_cap_in, set_ctx, function_id, function_id);
1461 ret = mlx5_cmd_exec_in(dev, set_hca_cap, set_ctx);
1462
1463 kvfree(set_ctx);
1464 return ret;
1465 }
1466