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