mlx5_vport.c revision 341972
1284345Ssjg/*-
2284345Ssjg * Copyright (c) 2013-2017, Mellanox Technologies, Ltd.  All rights reserved.
3284345Ssjg *
4284345Ssjg * Redistribution and use in source and binary forms, with or without
5284345Ssjg * modification, are permitted provided that the following conditions
6284345Ssjg * are met:
7284345Ssjg * 1. Redistributions of source code must retain the above copyright
8284345Ssjg *    notice, this list of conditions and the following disclaimer.
9284345Ssjg * 2. Redistributions in binary form must reproduce the above copyright
10284345Ssjg *    notice, this list of conditions and the following disclaimer in the
11284345Ssjg *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD: stable/11/sys/dev/mlx5/mlx5_core/mlx5_vport.c 341972 2018-12-12 13:00:56Z hselasky $
26 */
27
28#include <linux/etherdevice.h>
29#include <dev/mlx5/driver.h>
30#include <dev/mlx5/vport.h>
31#include "mlx5_core.h"
32
33static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in,
34					 int inlen);
35
36static int _mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod,
37				   u16 vport, u32 *out, int outlen)
38{
39	int err;
40	u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {0};
41
42	MLX5_SET(query_vport_state_in, in, opcode,
43		 MLX5_CMD_OP_QUERY_VPORT_STATE);
44	MLX5_SET(query_vport_state_in, in, op_mod, opmod);
45	MLX5_SET(query_vport_state_in, in, vport_number, vport);
46	if (vport)
47		MLX5_SET(query_vport_state_in, in, other_vport, 1);
48
49	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
50	if (err)
51		mlx5_core_warn(mdev, "MLX5_CMD_OP_QUERY_VPORT_STATE failed\n");
52
53	return err;
54}
55
56u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
57{
58	u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0};
59
60	_mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out));
61
62	return MLX5_GET(query_vport_state_out, out, state);
63}
64EXPORT_SYMBOL_GPL(mlx5_query_vport_state);
65
66u8 mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
67{
68	u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0};
69
70	_mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out));
71
72	return MLX5_GET(query_vport_state_out, out, admin_state);
73}
74EXPORT_SYMBOL(mlx5_query_vport_admin_state);
75
76int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
77				  u16 vport, u8 state)
78{
79	u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {0};
80	u32 out[MLX5_ST_SZ_DW(modify_vport_state_out)] = {0};
81	int err;
82
83	MLX5_SET(modify_vport_state_in, in, opcode,
84		 MLX5_CMD_OP_MODIFY_VPORT_STATE);
85	MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
86	MLX5_SET(modify_vport_state_in, in, vport_number, vport);
87
88	if (vport)
89		MLX5_SET(modify_vport_state_in, in, other_vport, 1);
90
91	MLX5_SET(modify_vport_state_in, in, admin_state, state);
92
93	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
94	if (err)
95		mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_VPORT_STATE failed\n");
96
97	return err;
98}
99EXPORT_SYMBOL(mlx5_modify_vport_admin_state);
100
101static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport,
102					u32 *out, int outlen)
103{
104	u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
105
106	MLX5_SET(query_nic_vport_context_in, in, opcode,
107		 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
108
109	MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
110	if (vport)
111		MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
112
113	return mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
114}
115
116static u32 mlx5_vport_max_q_counter_allocator(struct mlx5_core_dev *mdev,
117					      int client_id)
118{
119	switch (client_id) {
120	case MLX5_INTERFACE_PROTOCOL_IB:
121		return (MLX5_CAP_GEN(mdev, max_qp_cnt) -
122			MLX5_QCOUNTER_SETS_NETDEV);
123	case MLX5_INTERFACE_PROTOCOL_ETH:
124		return MLX5_QCOUNTER_SETS_NETDEV;
125	default:
126		mlx5_core_warn(mdev, "Unknown Client: %d\n", client_id);
127		return 0;
128	}
129}
130
131int mlx5_vport_alloc_q_counter(struct mlx5_core_dev *mdev,
132			       int client_id, u16 *counter_set_id)
133{
134	u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {0};
135	u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {0};
136	int err;
137
138	if (mdev->num_q_counter_allocated[client_id] >
139	    mlx5_vport_max_q_counter_allocator(mdev, client_id))
140		return -EINVAL;
141
142	MLX5_SET(alloc_q_counter_in, in, opcode,
143		 MLX5_CMD_OP_ALLOC_Q_COUNTER);
144
145	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
146
147	if (!err)
148		*counter_set_id = MLX5_GET(alloc_q_counter_out, out,
149					   counter_set_id);
150
151	mdev->num_q_counter_allocated[client_id]++;
152
153	return err;
154}
155
156int mlx5_vport_dealloc_q_counter(struct mlx5_core_dev *mdev,
157				 int client_id, u16 counter_set_id)
158{
159	u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {0};
160	u32 out[MLX5_ST_SZ_DW(dealloc_q_counter_out)] = {0};
161	int err;
162
163	if (mdev->num_q_counter_allocated[client_id] <= 0)
164		return -EINVAL;
165
166	MLX5_SET(dealloc_q_counter_in, in, opcode,
167		 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
168	MLX5_SET(dealloc_q_counter_in, in, counter_set_id,
169		 counter_set_id);
170
171	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
172
173	mdev->num_q_counter_allocated[client_id]--;
174
175	return err;
176}
177
178int mlx5_vport_query_q_counter(struct mlx5_core_dev *mdev,
179				      u16 counter_set_id,
180				      int reset,
181				      void *out,
182				      int out_size)
183{
184	u32 in[MLX5_ST_SZ_DW(query_q_counter_in)] = {0};
185
186	MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER);
187	MLX5_SET(query_q_counter_in, in, clear, reset);
188	MLX5_SET(query_q_counter_in, in, counter_set_id, counter_set_id);
189
190	return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
191}
192
193int mlx5_vport_query_out_of_rx_buffer(struct mlx5_core_dev *mdev,
194				      u16 counter_set_id,
195				      u32 *out_of_rx_buffer)
196{
197	u32 out[MLX5_ST_SZ_DW(query_q_counter_out)] = {0};
198	int err;
199
200	err = mlx5_vport_query_q_counter(mdev, counter_set_id, 0, out,
201					 sizeof(out));
202
203	if (err)
204		return err;
205
206	*out_of_rx_buffer = MLX5_GET(query_q_counter_out, out,
207				     out_of_buffer);
208	return err;
209}
210
211int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
212				    u16 vport, u8 *min_inline)
213{
214	u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {0};
215	int err;
216
217	err = mlx5_query_nic_vport_context(mdev, vport, out, sizeof(out));
218	if (!err)
219		*min_inline = MLX5_GET(query_nic_vport_context_out, out,
220				       nic_vport_context.min_wqe_inline_mode);
221	return err;
222}
223EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_min_inline);
224
225int mlx5_query_min_inline(struct mlx5_core_dev *mdev,
226			  u8 *min_inline_mode)
227{
228	int err;
229
230	switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) {
231	case MLX5_CAP_INLINE_MODE_L2:
232		*min_inline_mode = MLX5_INLINE_MODE_L2;
233		err = 0;
234		break;
235	case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
236		err = mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode);
237		break;
238	case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
239		*min_inline_mode = MLX5_INLINE_MODE_NONE;
240		err = 0;
241		break;
242	default:
243		err = -EINVAL;
244		break;
245	}
246	return err;
247}
248EXPORT_SYMBOL_GPL(mlx5_query_min_inline);
249
250int mlx5_modify_nic_vport_min_inline(struct mlx5_core_dev *mdev,
251				     u16 vport, u8 min_inline)
252{
253	u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {0};
254	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
255	void *nic_vport_ctx;
256
257	MLX5_SET(modify_nic_vport_context_in, in,
258		 field_select.min_wqe_inline_mode, 1);
259	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
260	MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
261
262	nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
263				     in, nic_vport_context);
264	MLX5_SET(nic_vport_context, nic_vport_ctx,
265		 min_wqe_inline_mode, min_inline);
266
267	return mlx5_modify_nic_vport_context(mdev, in, inlen);
268}
269EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_min_inline);
270
271int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev,
272				     u16 vport, u8 *addr)
273{
274	u32 *out;
275	int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
276	u8 *out_addr;
277	int err;
278
279	out = mlx5_vzalloc(outlen);
280	if (!out)
281		return -ENOMEM;
282
283	out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out,
284				nic_vport_context.permanent_address);
285
286	err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
287	if (err)
288		goto out;
289
290	ether_addr_copy(addr, &out_addr[2]);
291
292out:
293	kvfree(out);
294	return err;
295}
296EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address);
297
298int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev,
299				      u16 vport, u8 *addr)
300{
301	void *in;
302	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
303	int err;
304	void *nic_vport_ctx;
305	u8 *perm_mac;
306
307	in = mlx5_vzalloc(inlen);
308	if (!in) {
309		mlx5_core_warn(mdev, "failed to allocate inbox\n");
310		return -ENOMEM;
311	}
312
313	MLX5_SET(modify_nic_vport_context_in, in,
314		 field_select.permanent_address, 1);
315	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
316
317	if (vport)
318		MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
319
320	nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
321				     in, nic_vport_context);
322	perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx,
323				permanent_address);
324
325	ether_addr_copy(&perm_mac[2], addr);
326
327	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
328
329	kvfree(in);
330
331	return err;
332}
333EXPORT_SYMBOL(mlx5_modify_nic_vport_mac_address);
334
335int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
336					   u64 *system_image_guid)
337{
338	u32 *out;
339	int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
340	int err;
341
342	out = mlx5_vzalloc(outlen);
343	if (!out)
344		return -ENOMEM;
345
346	err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
347	if (err)
348		goto out;
349
350	*system_image_guid = MLX5_GET64(query_nic_vport_context_out, out,
351					nic_vport_context.system_image_guid);
352out:
353	kvfree(out);
354	return err;
355}
356EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid);
357
358int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
359{
360	u32 *out;
361	int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
362	int err;
363
364	out = mlx5_vzalloc(outlen);
365	if (!out)
366		return -ENOMEM;
367
368	err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
369	if (err)
370		goto out;
371
372	*node_guid = MLX5_GET64(query_nic_vport_context_out, out,
373				nic_vport_context.node_guid);
374
375out:
376	kvfree(out);
377	return err;
378}
379EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
380
381static int mlx5_query_nic_vport_port_guid(struct mlx5_core_dev *mdev,
382					  u64 *port_guid)
383{
384	u32 *out;
385	int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
386	int err;
387
388	out = mlx5_vzalloc(outlen);
389	if (!out)
390		return -ENOMEM;
391
392	err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
393	if (err)
394		goto out;
395
396	*port_guid = MLX5_GET64(query_nic_vport_context_out, out,
397				nic_vport_context.port_guid);
398
399out:
400	kvfree(out);
401	return err;
402}
403
404int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
405					u16 *qkey_viol_cntr)
406{
407	u32 *out;
408	int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
409	int err;
410
411	out = mlx5_vzalloc(outlen);
412	if (!out)
413		return -ENOMEM;
414
415	err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
416	if (err)
417		goto out;
418
419	*qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out,
420				nic_vport_context.qkey_violation_counter);
421
422out:
423	kvfree(out);
424	return err;
425}
426EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr);
427
428static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in,
429					 int inlen)
430{
431	u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0};
432
433	MLX5_SET(modify_nic_vport_context_in, in, opcode,
434		 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
435
436	return mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
437}
438
439static int mlx5_nic_vport_enable_disable_roce(struct mlx5_core_dev *mdev,
440					      int enable_disable)
441{
442	void *in;
443	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
444	int err;
445
446	in = mlx5_vzalloc(inlen);
447	if (!in) {
448		mlx5_core_warn(mdev, "failed to allocate inbox\n");
449		return -ENOMEM;
450	}
451
452	MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1);
453	MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en,
454		 enable_disable);
455
456	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
457
458	kvfree(in);
459
460	return err;
461}
462
463int mlx5_set_nic_vport_current_mac(struct mlx5_core_dev *mdev, int vport,
464				   bool other_vport, u8 *addr)
465{
466	void *in;
467	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)
468		  + MLX5_ST_SZ_BYTES(mac_address_layout);
469	u8  *mac_layout;
470	u8  *mac_ptr;
471	int err;
472
473	in = mlx5_vzalloc(inlen);
474	if (!in) {
475		mlx5_core_warn(mdev, "failed to allocate inbox\n");
476		return -ENOMEM;
477	}
478
479	MLX5_SET(modify_nic_vport_context_in, in,
480		 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
481	MLX5_SET(modify_nic_vport_context_in, in,
482		 vport_number, vport);
483	MLX5_SET(modify_nic_vport_context_in, in,
484		 other_vport, other_vport);
485	MLX5_SET(modify_nic_vport_context_in, in,
486		 field_select.addresses_list, 1);
487	MLX5_SET(modify_nic_vport_context_in, in,
488		 nic_vport_context.allowed_list_type,
489		 MLX5_NIC_VPORT_LIST_TYPE_UC);
490	MLX5_SET(modify_nic_vport_context_in, in,
491		 nic_vport_context.allowed_list_size, 1);
492
493	mac_layout = (u8 *)MLX5_ADDR_OF(modify_nic_vport_context_in, in,
494		nic_vport_context.current_uc_mac_address);
495	mac_ptr = (u8 *)MLX5_ADDR_OF(mac_address_layout, mac_layout,
496		mac_addr_47_32);
497	ether_addr_copy(mac_ptr, addr);
498
499	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
500
501	kvfree(in);
502
503	return err;
504}
505EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_current_mac);
506
507int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
508				    u32 vport, u64 node_guid)
509{
510	void *in;
511	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
512	int err;
513	void *nic_vport_context;
514
515	if (!vport)
516		return -EINVAL;
517	if (!MLX5_CAP_GEN(mdev, vport_group_manager))
518		return -EPERM;
519	if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify))
520		return -ENOTSUPP;
521
522	in = mlx5_vzalloc(inlen);
523	if (!in) {
524		mlx5_core_warn(mdev, "failed to allocate inbox\n");
525		return -ENOMEM;
526	}
527
528	MLX5_SET(modify_nic_vport_context_in, in,
529		 field_select.node_guid, 1);
530	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
531
532	MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
533
534	nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
535					 in, nic_vport_context);
536	MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid);
537
538	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
539
540	kvfree(in);
541
542	return err;
543}
544EXPORT_SYMBOL(mlx5_modify_nic_vport_node_guid);
545
546int mlx5_modify_nic_vport_port_guid(struct mlx5_core_dev *mdev,
547				    u32 vport, u64 port_guid)
548{
549	void *in;
550	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
551	int err;
552	void *nic_vport_context;
553
554	if (!vport)
555		return -EINVAL;
556	if (!MLX5_CAP_GEN(mdev, vport_group_manager))
557		return -EPERM;
558	if (!MLX5_CAP_ESW(mdev, nic_vport_port_guid_modify))
559		return -ENOTSUPP;
560
561	in = mlx5_vzalloc(inlen);
562	if (!in) {
563		mlx5_core_warn(mdev, "failed to allocate inbox\n");
564		return -ENOMEM;
565	}
566
567	MLX5_SET(modify_nic_vport_context_in, in,
568		 field_select.port_guid, 1);
569	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
570
571	MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
572
573	nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
574					 in, nic_vport_context);
575	MLX5_SET64(nic_vport_context, nic_vport_context, port_guid, port_guid);
576
577	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
578
579	kvfree(in);
580
581	return err;
582}
583EXPORT_SYMBOL(mlx5_modify_nic_vport_port_guid);
584
585int mlx5_set_nic_vport_vlan_list(struct mlx5_core_dev *dev, u16 vport,
586				 u16 *vlan_list, int list_len)
587{
588	void *in, *ctx;
589	int i, err;
590	int  inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)
591		+ MLX5_ST_SZ_BYTES(vlan_layout) * (int)list_len;
592
593	int max_list_size = 1 << MLX5_CAP_GEN_MAX(dev, log_max_vlan_list);
594
595	if (list_len > max_list_size) {
596		mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
597			       list_len, max_list_size);
598		return -ENOSPC;
599	}
600
601	in = mlx5_vzalloc(inlen);
602	if (!in) {
603		mlx5_core_warn(dev, "failed to allocate inbox\n");
604		return -ENOMEM;
605	}
606
607	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
608	if (vport)
609		MLX5_SET(modify_nic_vport_context_in, in,
610			 other_vport, 1);
611	MLX5_SET(modify_nic_vport_context_in, in,
612		 field_select.addresses_list, 1);
613
614	ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context);
615
616	MLX5_SET(nic_vport_context, ctx, allowed_list_type,
617		 MLX5_NIC_VPORT_LIST_TYPE_VLAN);
618	MLX5_SET(nic_vport_context, ctx, allowed_list_size, list_len);
619
620	for (i = 0; i < list_len; i++) {
621		u8 *vlan_lout = MLX5_ADDR_OF(nic_vport_context, ctx,
622					 current_uc_mac_address[i]);
623		MLX5_SET(vlan_layout, vlan_lout, vlan, vlan_list[i]);
624	}
625
626	err = mlx5_modify_nic_vport_context(dev, in, inlen);
627
628	kvfree(in);
629	return err;
630}
631EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_vlan_list);
632
633int mlx5_set_nic_vport_mc_list(struct mlx5_core_dev *mdev, int vport,
634			       u64 *addr_list, size_t addr_list_len)
635{
636	void *in, *ctx;
637	int  inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)
638		  + MLX5_ST_SZ_BYTES(mac_address_layout) * (int)addr_list_len;
639	int err;
640	size_t i;
641	int max_list_sz = 1 << MLX5_CAP_GEN_MAX(mdev, log_max_current_mc_list);
642
643	if ((int)addr_list_len > max_list_sz) {
644		mlx5_core_warn(mdev, "Requested list size (%d) > (%d) max_list_size\n",
645			       (int)addr_list_len, max_list_sz);
646		return -ENOSPC;
647	}
648
649	in = mlx5_vzalloc(inlen);
650	if (!in) {
651		mlx5_core_warn(mdev, "failed to allocate inbox\n");
652		return -ENOMEM;
653	}
654
655	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
656	if (vport)
657		MLX5_SET(modify_nic_vport_context_in, in,
658			 other_vport, 1);
659	MLX5_SET(modify_nic_vport_context_in, in,
660		 field_select.addresses_list, 1);
661
662	ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context);
663
664	MLX5_SET(nic_vport_context, ctx, allowed_list_type,
665		 MLX5_NIC_VPORT_LIST_TYPE_MC);
666	MLX5_SET(nic_vport_context, ctx, allowed_list_size, addr_list_len);
667
668	for (i = 0; i < addr_list_len; i++) {
669		u8 *mac_lout = (u8 *)MLX5_ADDR_OF(nic_vport_context, ctx,
670						  current_uc_mac_address[i]);
671		u8 *mac_ptr = (u8 *)MLX5_ADDR_OF(mac_address_layout, mac_lout,
672						 mac_addr_47_32);
673		ether_addr_copy(mac_ptr, (u8 *)&addr_list[i]);
674	}
675
676	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
677
678	kvfree(in);
679
680	return err;
681}
682EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_mc_list);
683
684int mlx5_set_nic_vport_promisc(struct mlx5_core_dev *mdev, int vport,
685			       bool promisc_mc, bool promisc_uc,
686			       bool promisc_all)
687{
688	u8  in[MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)];
689	u8 *ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
690			       nic_vport_context);
691
692	memset(in, 0, MLX5_ST_SZ_BYTES(modify_nic_vport_context_in));
693
694	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
695	if (vport)
696		MLX5_SET(modify_nic_vport_context_in, in,
697			 other_vport, 1);
698	MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
699	if (promisc_mc)
700		MLX5_SET(nic_vport_context, ctx, promisc_mc, 1);
701	if (promisc_uc)
702		MLX5_SET(nic_vport_context, ctx, promisc_uc, 1);
703	if (promisc_all)
704		MLX5_SET(nic_vport_context, ctx, promisc_all, 1);
705
706	return mlx5_modify_nic_vport_context(mdev, in, sizeof(in));
707}
708EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_promisc);
709
710int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
711				  u16 vport,
712				  enum mlx5_list_type list_type,
713				  u8 addr_list[][ETH_ALEN],
714				  int *list_size)
715{
716	u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
717	void *nic_vport_ctx;
718	int max_list_size;
719	int req_list_size;
720	int out_sz;
721	void *out;
722	int err;
723	int i;
724
725	req_list_size = *list_size;
726
727	max_list_size = (list_type == MLX5_NIC_VPORT_LIST_TYPE_UC) ?
728			1 << MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list) :
729			1 << MLX5_CAP_GEN_MAX(dev, log_max_current_mc_list);
730
731	if (req_list_size > max_list_size) {
732		mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
733			       req_list_size, max_list_size);
734		req_list_size = max_list_size;
735	}
736
737	out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
738		 req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
739
740	out = kzalloc(out_sz, GFP_KERNEL);
741	if (!out)
742		return -ENOMEM;
743
744	MLX5_SET(query_nic_vport_context_in, in, opcode,
745		 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
746	MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
747	MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
748
749	if (vport)
750		MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
751
752	err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
753	if (err)
754		goto out;
755
756	nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
757				     nic_vport_context);
758	req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
759				 allowed_list_size);
760
761	*list_size = req_list_size;
762	for (i = 0; i < req_list_size; i++) {
763		u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
764					nic_vport_ctx,
765					current_uc_mac_address[i]) + 2;
766		ether_addr_copy(addr_list[i], mac_addr);
767	}
768out:
769	kfree(out);
770	return err;
771}
772EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list);
773
774int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
775				   enum mlx5_list_type list_type,
776				   u8 addr_list[][ETH_ALEN],
777				   int list_size)
778{
779	u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0};
780	void *nic_vport_ctx;
781	int max_list_size;
782	int in_sz;
783	void *in;
784	int err;
785	int i;
786
787	max_list_size = list_type == MLX5_NIC_VPORT_LIST_TYPE_UC ?
788		 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
789		 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
790
791	if (list_size > max_list_size)
792		return -ENOSPC;
793
794	in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
795		list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
796
797	in = kzalloc(in_sz, GFP_KERNEL);
798	if (!in)
799		return -ENOMEM;
800
801	MLX5_SET(modify_nic_vport_context_in, in, opcode,
802		 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
803	MLX5_SET(modify_nic_vport_context_in, in,
804		 field_select.addresses_list, 1);
805
806	nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
807				     nic_vport_context);
808
809	MLX5_SET(nic_vport_context, nic_vport_ctx,
810		 allowed_list_type, list_type);
811	MLX5_SET(nic_vport_context, nic_vport_ctx,
812		 allowed_list_size, list_size);
813
814	for (i = 0; i < list_size; i++) {
815		u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context,
816					    nic_vport_ctx,
817					    current_uc_mac_address[i]) + 2;
818		ether_addr_copy(curr_mac, addr_list[i]);
819	}
820
821	err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
822	kfree(in);
823	return err;
824}
825EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
826
827int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,
828			       u16 vport,
829			       u16 vlans[],
830			       int *size)
831{
832	u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
833	void *nic_vport_ctx;
834	int req_list_size;
835	int max_list_size;
836	int out_sz;
837	void *out;
838	int err;
839	int i;
840
841	req_list_size = *size;
842	max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
843	if (req_list_size > max_list_size) {
844		mlx5_core_warn(dev, "Requested list size (%d) > (%d) max list size\n",
845			       req_list_size, max_list_size);
846		req_list_size = max_list_size;
847	}
848
849	out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
850		 req_list_size * MLX5_ST_SZ_BYTES(vlan_layout);
851
852	out = kzalloc(out_sz, GFP_KERNEL);
853	if (!out)
854		return -ENOMEM;
855
856	MLX5_SET(query_nic_vport_context_in, in, opcode,
857		 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
858	MLX5_SET(query_nic_vport_context_in, in, allowed_list_type,
859		 MLX5_NIC_VPORT_CONTEXT_ALLOWED_LIST_TYPE_VLAN_LIST);
860	MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
861
862	if (vport)
863		MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
864
865	err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
866	if (err)
867		goto out;
868
869	nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
870				     nic_vport_context);
871	req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
872				 allowed_list_size);
873
874	*size = req_list_size;
875	for (i = 0; i < req_list_size; i++) {
876		void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
877					       nic_vport_ctx,
878					 current_uc_mac_address[i]);
879		vlans[i] = MLX5_GET(vlan_layout, vlan_addr, vlan);
880	}
881out:
882	kfree(out);
883	return err;
884}
885EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_vlans);
886
887int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
888				u16 vlans[],
889				int list_size)
890{
891	u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0};
892	void *nic_vport_ctx;
893	int max_list_size;
894	int in_sz;
895	void *in;
896	int err;
897	int i;
898
899	max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
900
901	if (list_size > max_list_size)
902		return -ENOSPC;
903
904	in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
905		list_size * MLX5_ST_SZ_BYTES(vlan_layout);
906
907	in = kzalloc(in_sz, GFP_KERNEL);
908	if (!in)
909		return -ENOMEM;
910
911	MLX5_SET(modify_nic_vport_context_in, in, opcode,
912		 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
913	MLX5_SET(modify_nic_vport_context_in, in,
914		 field_select.addresses_list, 1);
915
916	nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
917				     nic_vport_context);
918
919	MLX5_SET(nic_vport_context, nic_vport_ctx,
920		 allowed_list_type, MLX5_NIC_VPORT_LIST_TYPE_VLAN);
921	MLX5_SET(nic_vport_context, nic_vport_ctx,
922		 allowed_list_size, list_size);
923
924	for (i = 0; i < list_size; i++) {
925		void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
926					       nic_vport_ctx,
927					       current_uc_mac_address[i]);
928		MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]);
929	}
930
931	err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
932	kfree(in);
933	return err;
934}
935EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans);
936
937int mlx5_query_nic_vport_roce_en(struct mlx5_core_dev *mdev, u8 *enable)
938{
939	u32 *out;
940	int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
941	int err;
942
943	out = kzalloc(outlen, GFP_KERNEL);
944	if (!out)
945		return -ENOMEM;
946
947	err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
948	if (err)
949		goto out;
950
951	*enable = MLX5_GET(query_nic_vport_context_out, out,
952				nic_vport_context.roce_en);
953
954out:
955	kfree(out);
956	return err;
957}
958EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_roce_en);
959
960int mlx5_set_nic_vport_permanent_mac(struct mlx5_core_dev *mdev, int vport,
961				     u8 *addr)
962{
963	void *in;
964	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
965	u8  *mac_ptr;
966	int err;
967
968	in = mlx5_vzalloc(inlen);
969	if (!in) {
970		mlx5_core_warn(mdev, "failed to allocate inbox\n");
971		return -ENOMEM;
972	}
973
974	MLX5_SET(modify_nic_vport_context_in, in,
975		 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
976	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
977	MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
978	MLX5_SET(modify_nic_vport_context_in, in,
979		 field_select.permanent_address, 1);
980	mac_ptr = (u8 *)MLX5_ADDR_OF(modify_nic_vport_context_in, in,
981		nic_vport_context.permanent_address.mac_addr_47_32);
982	ether_addr_copy(mac_ptr, addr);
983
984	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
985
986	kvfree(in);
987
988	return err;
989}
990EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_permanent_mac);
991
992int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev)
993{
994	return mlx5_nic_vport_enable_disable_roce(mdev, 1);
995}
996EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce);
997
998int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev)
999{
1000	return mlx5_nic_vport_enable_disable_roce(mdev, 0);
1001}
1002EXPORT_SYMBOL_GPL(mlx5_nic_vport_disable_roce);
1003
1004int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport,
1005				  int vf, u8 port_num, void *out,
1006				  size_t out_sz)
1007{
1008	int	in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in);
1009	int	is_group_manager;
1010	void   *in;
1011	int	err;
1012
1013	is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1014	in = mlx5_vzalloc(in_sz);
1015	if (!in) {
1016		err = -ENOMEM;
1017		return err;
1018	}
1019
1020	MLX5_SET(query_vport_counter_in, in, opcode,
1021		 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
1022	if (other_vport) {
1023		if (is_group_manager) {
1024			MLX5_SET(query_vport_counter_in, in, other_vport, 1);
1025			MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1);
1026		} else {
1027			err = -EPERM;
1028			goto free;
1029		}
1030	}
1031	if (MLX5_CAP_GEN(dev, num_ports) == 2)
1032		MLX5_SET(query_vport_counter_in, in, port_num, port_num);
1033
1034	err = mlx5_cmd_exec(dev, in, in_sz, out,  out_sz);
1035free:
1036	kvfree(in);
1037	return err;
1038}
1039EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter);
1040
1041int mlx5_query_hca_vport_context(struct mlx5_core_dev *mdev,
1042				 u8 port_num, u8 vport_num, u32 *out,
1043				 int outlen)
1044{
1045	u32 in[MLX5_ST_SZ_DW(query_hca_vport_context_in)] = {0};
1046	int is_group_manager;
1047
1048	is_group_manager = MLX5_CAP_GEN(mdev, vport_group_manager);
1049
1050	MLX5_SET(query_hca_vport_context_in, in, opcode,
1051		 MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT);
1052
1053	if (vport_num) {
1054		if (is_group_manager) {
1055			MLX5_SET(query_hca_vport_context_in, in, other_vport,
1056				 1);
1057			MLX5_SET(query_hca_vport_context_in, in, vport_number,
1058				 vport_num);
1059		} else {
1060			return -EPERM;
1061		}
1062	}
1063
1064	if (MLX5_CAP_GEN(mdev, num_ports) == 2)
1065		MLX5_SET(query_hca_vport_context_in, in, port_num, port_num);
1066
1067	return mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
1068}
1069
1070int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *mdev,
1071					   u64 *system_image_guid)
1072{
1073	u32 *out;
1074	int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1075	int err;
1076
1077	out = mlx5_vzalloc(outlen);
1078	if (!out)
1079		return -ENOMEM;
1080
1081	err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen);
1082	if (err)
1083		goto out;
1084
1085	*system_image_guid = MLX5_GET64(query_hca_vport_context_out, out,
1086					hca_vport_context.system_image_guid);
1087
1088out:
1089	kvfree(out);
1090	return err;
1091}
1092EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid);
1093
1094int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
1095{
1096	u32 *out;
1097	int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1098	int err;
1099
1100	out = mlx5_vzalloc(outlen);
1101	if (!out)
1102		return -ENOMEM;
1103
1104	err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen);
1105	if (err)
1106		goto out;
1107
1108	*node_guid = MLX5_GET64(query_hca_vport_context_out, out,
1109				hca_vport_context.node_guid);
1110
1111out:
1112	kvfree(out);
1113	return err;
1114}
1115EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
1116
1117static int mlx5_query_hca_vport_port_guid(struct mlx5_core_dev *mdev,
1118					  u64 *port_guid)
1119{
1120	u32 *out;
1121	int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1122	int err;
1123
1124	out = mlx5_vzalloc(outlen);
1125	if (!out)
1126		return -ENOMEM;
1127
1128	err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen);
1129	if (err)
1130		goto out;
1131
1132	*port_guid = MLX5_GET64(query_hca_vport_context_out, out,
1133				hca_vport_context.port_guid);
1134
1135out:
1136	kvfree(out);
1137	return err;
1138}
1139
1140int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 port_num,
1141			     u16 vport_num, u16 gid_index, union ib_gid *gid)
1142{
1143	int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in);
1144	int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
1145	int is_group_manager;
1146	void *out = NULL;
1147	void *in = NULL;
1148	union ib_gid *tmp;
1149	int tbsz;
1150	int nout;
1151	int err;
1152
1153	is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1154	tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size));
1155
1156	if (gid_index > tbsz && gid_index != 0xffff)
1157		return -EINVAL;
1158
1159	if (gid_index == 0xffff)
1160		nout = tbsz;
1161	else
1162		nout = 1;
1163
1164	out_sz += nout * sizeof(*gid);
1165
1166	in = mlx5_vzalloc(in_sz);
1167	out = mlx5_vzalloc(out_sz);
1168	if (!in || !out) {
1169		err = -ENOMEM;
1170		goto out;
1171	}
1172
1173	MLX5_SET(query_hca_vport_gid_in, in, opcode,
1174		 MLX5_CMD_OP_QUERY_HCA_VPORT_GID);
1175	if (vport_num) {
1176		if (is_group_manager) {
1177			MLX5_SET(query_hca_vport_gid_in, in, vport_number,
1178				 vport_num);
1179			MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1);
1180		} else {
1181			err = -EPERM;
1182			goto out;
1183		}
1184	}
1185
1186	MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index);
1187
1188	if (MLX5_CAP_GEN(dev, num_ports) == 2)
1189		MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num);
1190
1191	err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
1192	if (err)
1193		goto out;
1194
1195	tmp = (union ib_gid *)MLX5_ADDR_OF(query_hca_vport_gid_out, out, gid);
1196	gid->global.subnet_prefix = tmp->global.subnet_prefix;
1197	gid->global.interface_id = tmp->global.interface_id;
1198
1199out:
1200	kvfree(in);
1201	kvfree(out);
1202	return err;
1203}
1204EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid);
1205
1206int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
1207			      u8 port_num, u16 vf_num, u16 pkey_index,
1208			      u16 *pkey)
1209{
1210	int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in);
1211	int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out);
1212	int is_group_manager;
1213	void *out = NULL;
1214	void *in = NULL;
1215	void *pkarr;
1216	int nout;
1217	int tbsz;
1218	int err;
1219	int i;
1220
1221	is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1222
1223	tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size));
1224	if (pkey_index > tbsz && pkey_index != 0xffff)
1225		return -EINVAL;
1226
1227	if (pkey_index == 0xffff)
1228		nout = tbsz;
1229	else
1230		nout = 1;
1231
1232	out_sz += nout * MLX5_ST_SZ_BYTES(pkey);
1233
1234	in = kzalloc(in_sz, GFP_KERNEL);
1235	out = kzalloc(out_sz, GFP_KERNEL);
1236
1237	MLX5_SET(query_hca_vport_pkey_in, in, opcode,
1238		 MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY);
1239	if (other_vport) {
1240		if (is_group_manager) {
1241			MLX5_SET(query_hca_vport_pkey_in, in, vport_number,
1242				 vf_num);
1243			MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1);
1244		} else {
1245			err = -EPERM;
1246			goto out;
1247		}
1248	}
1249	MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index);
1250
1251	if (MLX5_CAP_GEN(dev, num_ports) == 2)
1252		MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num);
1253
1254	err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
1255	if (err)
1256		goto out;
1257
1258	pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey);
1259	for (i = 0; i < nout; i++, pkey++,
1260	     pkarr += MLX5_ST_SZ_BYTES(pkey))
1261		*pkey = MLX5_GET_PR(pkey, pkarr, pkey);
1262
1263out:
1264	kfree(in);
1265	kfree(out);
1266	return err;
1267}
1268EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey);
1269
1270static int mlx5_query_hca_min_wqe_header(struct mlx5_core_dev *mdev,
1271					 int *min_header)
1272{
1273	u32 *out;
1274	u32 outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1275	int err;
1276
1277	out = mlx5_vzalloc(outlen);
1278	if (!out)
1279		return -ENOMEM;
1280
1281	err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen);
1282	if (err)
1283		goto out;
1284
1285	*min_header = MLX5_GET(query_hca_vport_context_out, out,
1286			       hca_vport_context.min_wqe_inline_mode);
1287
1288out:
1289	kvfree(out);
1290	return err;
1291}
1292
1293static int mlx5_modify_eswitch_vport_context(struct mlx5_core_dev *mdev,
1294					     u16 vport, void *in, int inlen)
1295{
1296	u32 out[MLX5_ST_SZ_DW(modify_esw_vport_context_out)] = {0};
1297	int err;
1298
1299	MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport);
1300	if (vport)
1301		MLX5_SET(modify_esw_vport_context_in, in, other_vport, 1);
1302
1303	MLX5_SET(modify_esw_vport_context_in, in, opcode,
1304		 MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT);
1305
1306	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
1307	if (err)
1308		mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT failed\n");
1309
1310	return err;
1311}
1312
1313int mlx5_set_eswitch_cvlan_info(struct mlx5_core_dev *mdev, u8 vport,
1314				u8 insert_mode, u8 strip_mode,
1315				u16 vlan, u8 cfi, u8 pcp)
1316{
1317	u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)];
1318
1319	memset(in, 0, sizeof(in));
1320
1321	if (insert_mode != MLX5_MODIFY_ESW_VPORT_CONTEXT_CVLAN_INSERT_NONE) {
1322		MLX5_SET(modify_esw_vport_context_in, in,
1323			 esw_vport_context.cvlan_cfi, cfi);
1324		MLX5_SET(modify_esw_vport_context_in, in,
1325			 esw_vport_context.cvlan_pcp, pcp);
1326		MLX5_SET(modify_esw_vport_context_in, in,
1327			 esw_vport_context.cvlan_id, vlan);
1328	}
1329
1330	MLX5_SET(modify_esw_vport_context_in, in,
1331		 esw_vport_context.vport_cvlan_insert, insert_mode);
1332
1333	MLX5_SET(modify_esw_vport_context_in, in,
1334		 esw_vport_context.vport_cvlan_strip, strip_mode);
1335
1336	MLX5_SET(modify_esw_vport_context_in, in, field_select,
1337		 MLX5_MODIFY_ESW_VPORT_CONTEXT_FIELD_SELECT_CVLAN_STRIP |
1338		 MLX5_MODIFY_ESW_VPORT_CONTEXT_FIELD_SELECT_CVLAN_INSERT);
1339
1340	return mlx5_modify_eswitch_vport_context(mdev, vport, in, sizeof(in));
1341}
1342EXPORT_SYMBOL_GPL(mlx5_set_eswitch_cvlan_info);
1343
1344int mlx5_query_vport_mtu(struct mlx5_core_dev *mdev, int *mtu)
1345{
1346	u32 *out;
1347	u32 outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1348	int err;
1349
1350	out = mlx5_vzalloc(outlen);
1351	if (!out)
1352		return -ENOMEM;
1353
1354	err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
1355	if (err)
1356		goto out;
1357
1358	*mtu = MLX5_GET(query_nic_vport_context_out, out,
1359			nic_vport_context.mtu);
1360
1361out:
1362	kvfree(out);
1363	return err;
1364}
1365EXPORT_SYMBOL_GPL(mlx5_query_vport_mtu);
1366
1367int mlx5_set_vport_mtu(struct mlx5_core_dev *mdev, int mtu)
1368{
1369	u32 *in;
1370	u32 inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1371	int err;
1372
1373	in = mlx5_vzalloc(inlen);
1374	if (!in)
1375		return -ENOMEM;
1376
1377	MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1);
1378	MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, mtu);
1379
1380	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
1381
1382	kvfree(in);
1383	return err;
1384}
1385EXPORT_SYMBOL_GPL(mlx5_set_vport_mtu);
1386
1387static int mlx5_query_vport_min_wqe_header(struct mlx5_core_dev *mdev,
1388					   int *min_header)
1389{
1390	u32 *out;
1391	u32 outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1392	int err;
1393
1394	out = mlx5_vzalloc(outlen);
1395	if (!out)
1396		return -ENOMEM;
1397
1398	err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
1399	if (err)
1400		goto out;
1401
1402	*min_header = MLX5_GET(query_nic_vport_context_out, out,
1403			       nic_vport_context.min_wqe_inline_mode);
1404
1405out:
1406	kvfree(out);
1407	return err;
1408}
1409
1410int mlx5_set_vport_min_wqe_header(struct mlx5_core_dev *mdev,
1411				  u8 vport, int min_header)
1412{
1413	u32 *in;
1414	u32 inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1415	int err;
1416
1417	in = mlx5_vzalloc(inlen);
1418	if (!in)
1419		return -ENOMEM;
1420
1421	MLX5_SET(modify_nic_vport_context_in, in,
1422		 field_select.min_wqe_inline_mode, 1);
1423	MLX5_SET(modify_nic_vport_context_in, in,
1424		 nic_vport_context.min_wqe_inline_mode, min_header);
1425	MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
1426	MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
1427
1428	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
1429
1430	kvfree(in);
1431	return err;
1432}
1433EXPORT_SYMBOL_GPL(mlx5_set_vport_min_wqe_header);
1434
1435int mlx5_query_min_wqe_header(struct mlx5_core_dev *dev, int *min_header)
1436{
1437	switch (MLX5_CAP_GEN(dev, port_type)) {
1438	case MLX5_CMD_HCA_CAP_PORT_TYPE_IB:
1439		return mlx5_query_hca_min_wqe_header(dev, min_header);
1440
1441	case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET:
1442		return mlx5_query_vport_min_wqe_header(dev, min_header);
1443
1444	default:
1445		return -EINVAL;
1446	}
1447}
1448EXPORT_SYMBOL_GPL(mlx5_query_min_wqe_header);
1449
1450int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
1451				 u16 vport,
1452				 int *promisc_uc,
1453				 int *promisc_mc,
1454				 int *promisc_all)
1455{
1456	u32 *out;
1457	int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1458	int err;
1459
1460	out = kzalloc(outlen, GFP_KERNEL);
1461	if (!out)
1462		return -ENOMEM;
1463
1464	err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
1465	if (err)
1466		goto out;
1467
1468	*promisc_uc = MLX5_GET(query_nic_vport_context_out, out,
1469			       nic_vport_context.promisc_uc);
1470	*promisc_mc = MLX5_GET(query_nic_vport_context_out, out,
1471			       nic_vport_context.promisc_mc);
1472	*promisc_all = MLX5_GET(query_nic_vport_context_out, out,
1473				nic_vport_context.promisc_all);
1474
1475out:
1476	kfree(out);
1477	return err;
1478}
1479EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
1480
1481int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,
1482				  int promisc_uc,
1483				  int promisc_mc,
1484				  int promisc_all)
1485{
1486	void *in;
1487	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1488	int err;
1489
1490	in = mlx5_vzalloc(inlen);
1491	if (!in) {
1492		mlx5_core_err(mdev, "failed to allocate inbox\n");
1493		return -ENOMEM;
1494	}
1495
1496	MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
1497	MLX5_SET(modify_nic_vport_context_in, in,
1498		 nic_vport_context.promisc_uc, promisc_uc);
1499	MLX5_SET(modify_nic_vport_context_in, in,
1500		 nic_vport_context.promisc_mc, promisc_mc);
1501	MLX5_SET(modify_nic_vport_context_in, in,
1502		 nic_vport_context.promisc_all, promisc_all);
1503
1504	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
1505	kvfree(in);
1506	return err;
1507}
1508EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc);
1509
1510int mlx5_nic_vport_modify_local_lb(struct mlx5_core_dev *mdev,
1511				   enum mlx5_local_lb_selection selection,
1512				   u8 value)
1513{
1514	void *in;
1515	int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1516	int err;
1517
1518	in = mlx5_vzalloc(inlen);
1519	if (!in) {
1520		mlx5_core_warn(mdev, "failed to allocate inbox\n");
1521		return -ENOMEM;
1522	}
1523
1524	MLX5_SET(modify_nic_vport_context_in, in, vport_number, 0);
1525
1526	if (selection == MLX5_LOCAL_MC_LB) {
1527		MLX5_SET(modify_nic_vport_context_in, in,
1528			 field_select.disable_mc_local_lb, 1);
1529		MLX5_SET(modify_nic_vport_context_in, in,
1530			 nic_vport_context.disable_mc_local_lb,
1531			 value);
1532	} else {
1533		MLX5_SET(modify_nic_vport_context_in, in,
1534			 field_select.disable_uc_local_lb, 1);
1535		MLX5_SET(modify_nic_vport_context_in, in,
1536			 nic_vport_context.disable_uc_local_lb,
1537			 value);
1538	}
1539
1540	err = mlx5_modify_nic_vport_context(mdev, in, inlen);
1541
1542	kvfree(in);
1543	return err;
1544}
1545EXPORT_SYMBOL_GPL(mlx5_nic_vport_modify_local_lb);
1546
1547int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev,
1548				  enum mlx5_local_lb_selection selection,
1549				  u8 *value)
1550{
1551	void *out;
1552	int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1553	int err;
1554
1555	out = kzalloc(outlen, GFP_KERNEL);
1556	if (!out)
1557		return -ENOMEM;
1558
1559	err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
1560	if (err)
1561		goto done;
1562
1563	if (selection == MLX5_LOCAL_MC_LB)
1564		*value = MLX5_GET(query_nic_vport_context_out, out,
1565				  nic_vport_context.disable_mc_local_lb);
1566	else
1567		*value = MLX5_GET(query_nic_vport_context_out, out,
1568				  nic_vport_context.disable_uc_local_lb);
1569
1570done:
1571	kfree(out);
1572	return err;
1573}
1574EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb);
1575
1576int mlx5_query_vport_counter(struct mlx5_core_dev *dev,
1577			     u8 port_num, u16 vport_num,
1578			     void *out, int out_size)
1579{
1580	int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in);
1581	int is_group_manager;
1582	void *in;
1583	int err;
1584
1585	is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1586
1587	in = mlx5_vzalloc(in_sz);
1588	if (!in)
1589		return -ENOMEM;
1590
1591	MLX5_SET(query_vport_counter_in, in, opcode,
1592		 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
1593	if (vport_num) {
1594		if (is_group_manager) {
1595			MLX5_SET(query_vport_counter_in, in, other_vport, 1);
1596			MLX5_SET(query_vport_counter_in, in, vport_number,
1597				 vport_num);
1598		} else {
1599			err = -EPERM;
1600			goto ex;
1601		}
1602	}
1603	if (MLX5_CAP_GEN(dev, num_ports) == 2)
1604		MLX5_SET(query_vport_counter_in, in, port_num, port_num);
1605
1606	err = mlx5_cmd_exec(dev, in, in_sz, out,  out_size);
1607
1608ex:
1609	kvfree(in);
1610	return err;
1611}
1612EXPORT_SYMBOL_GPL(mlx5_query_vport_counter);
1613
1614int mlx5_get_vport_counters(struct mlx5_core_dev *dev, u8 port_num,
1615			    struct mlx5_vport_counters *vc)
1616{
1617	int out_sz = MLX5_ST_SZ_BYTES(query_vport_counter_out);
1618	void *out;
1619	int err;
1620
1621	out = mlx5_vzalloc(out_sz);
1622	if (!out)
1623		return -ENOMEM;
1624
1625	err = mlx5_query_vport_counter(dev, port_num, 0, out, out_sz);
1626	if (err)
1627		goto ex;
1628
1629	vc->received_errors.packets =
1630		MLX5_GET64(query_vport_counter_out,
1631			   out, received_errors.packets);
1632	vc->received_errors.octets =
1633		MLX5_GET64(query_vport_counter_out,
1634			   out, received_errors.octets);
1635	vc->transmit_errors.packets =
1636		MLX5_GET64(query_vport_counter_out,
1637			   out, transmit_errors.packets);
1638	vc->transmit_errors.octets =
1639		MLX5_GET64(query_vport_counter_out,
1640			   out, transmit_errors.octets);
1641	vc->received_ib_unicast.packets =
1642		MLX5_GET64(query_vport_counter_out,
1643			   out, received_ib_unicast.packets);
1644	vc->received_ib_unicast.octets =
1645		MLX5_GET64(query_vport_counter_out,
1646			   out, received_ib_unicast.octets);
1647	vc->transmitted_ib_unicast.packets =
1648		MLX5_GET64(query_vport_counter_out,
1649			   out, transmitted_ib_unicast.packets);
1650	vc->transmitted_ib_unicast.octets =
1651		MLX5_GET64(query_vport_counter_out,
1652			   out, transmitted_ib_unicast.octets);
1653	vc->received_ib_multicast.packets =
1654		MLX5_GET64(query_vport_counter_out,
1655			   out, received_ib_multicast.packets);
1656	vc->received_ib_multicast.octets =
1657		MLX5_GET64(query_vport_counter_out,
1658			   out, received_ib_multicast.octets);
1659	vc->transmitted_ib_multicast.packets =
1660		MLX5_GET64(query_vport_counter_out,
1661			   out, transmitted_ib_multicast.packets);
1662	vc->transmitted_ib_multicast.octets =
1663		MLX5_GET64(query_vport_counter_out,
1664			   out, transmitted_ib_multicast.octets);
1665	vc->received_eth_broadcast.packets =
1666		MLX5_GET64(query_vport_counter_out,
1667			   out, received_eth_broadcast.packets);
1668	vc->received_eth_broadcast.octets =
1669		MLX5_GET64(query_vport_counter_out,
1670			   out, received_eth_broadcast.octets);
1671	vc->transmitted_eth_broadcast.packets =
1672		MLX5_GET64(query_vport_counter_out,
1673			   out, transmitted_eth_broadcast.packets);
1674	vc->transmitted_eth_broadcast.octets =
1675		MLX5_GET64(query_vport_counter_out,
1676			   out, transmitted_eth_broadcast.octets);
1677	vc->received_eth_unicast.octets =
1678		MLX5_GET64(query_vport_counter_out,
1679			   out, received_eth_unicast.octets);
1680	vc->received_eth_unicast.packets =
1681		MLX5_GET64(query_vport_counter_out,
1682			   out, received_eth_unicast.packets);
1683	vc->transmitted_eth_unicast.octets =
1684		MLX5_GET64(query_vport_counter_out,
1685			   out, transmitted_eth_unicast.octets);
1686	vc->transmitted_eth_unicast.packets =
1687		MLX5_GET64(query_vport_counter_out,
1688			   out, transmitted_eth_unicast.packets);
1689	vc->received_eth_multicast.octets =
1690		MLX5_GET64(query_vport_counter_out,
1691			   out, received_eth_multicast.octets);
1692	vc->received_eth_multicast.packets =
1693		MLX5_GET64(query_vport_counter_out,
1694			   out, received_eth_multicast.packets);
1695	vc->transmitted_eth_multicast.octets =
1696		MLX5_GET64(query_vport_counter_out,
1697			   out, transmitted_eth_multicast.octets);
1698	vc->transmitted_eth_multicast.packets =
1699		MLX5_GET64(query_vport_counter_out,
1700			   out, transmitted_eth_multicast.packets);
1701
1702ex:
1703	kvfree(out);
1704	return err;
1705}
1706
1707int mlx5_query_vport_system_image_guid(struct mlx5_core_dev *dev,
1708				       u64 *sys_image_guid)
1709{
1710	switch (MLX5_CAP_GEN(dev, port_type)) {
1711	case MLX5_CMD_HCA_CAP_PORT_TYPE_IB:
1712		return mlx5_query_hca_vport_system_image_guid(dev,
1713							      sys_image_guid);
1714
1715	case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET:
1716		return mlx5_query_nic_vport_system_image_guid(dev,
1717							      sys_image_guid);
1718
1719	default:
1720		return -EINVAL;
1721	}
1722}
1723EXPORT_SYMBOL_GPL(mlx5_query_vport_system_image_guid);
1724
1725int mlx5_query_vport_node_guid(struct mlx5_core_dev *dev, u64 *node_guid)
1726{
1727	switch (MLX5_CAP_GEN(dev, port_type)) {
1728	case MLX5_CMD_HCA_CAP_PORT_TYPE_IB:
1729		return mlx5_query_hca_vport_node_guid(dev, node_guid);
1730
1731	case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET:
1732		return mlx5_query_nic_vport_node_guid(dev, node_guid);
1733
1734	default:
1735		return -EINVAL;
1736	}
1737}
1738EXPORT_SYMBOL_GPL(mlx5_query_vport_node_guid);
1739
1740int mlx5_query_vport_port_guid(struct mlx5_core_dev *dev, u64 *port_guid)
1741{
1742	switch (MLX5_CAP_GEN(dev, port_type)) {
1743	case MLX5_CMD_HCA_CAP_PORT_TYPE_IB:
1744		return mlx5_query_hca_vport_port_guid(dev, port_guid);
1745
1746	case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET:
1747		return mlx5_query_nic_vport_port_guid(dev, port_guid);
1748
1749	default:
1750		return -EINVAL;
1751	}
1752}
1753EXPORT_SYMBOL_GPL(mlx5_query_vport_port_guid);
1754
1755int mlx5_query_hca_vport_state(struct mlx5_core_dev *dev, u8 *vport_state)
1756{
1757	u32 *out;
1758	int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1759	int err;
1760
1761	out = mlx5_vzalloc(outlen);
1762	if (!out)
1763		return -ENOMEM;
1764
1765	err = mlx5_query_hca_vport_context(dev, 1, 0, out, outlen);
1766	if (err)
1767		goto out;
1768
1769	*vport_state = MLX5_GET(query_hca_vport_context_out, out,
1770				hca_vport_context.vport_state);
1771
1772out:
1773	kvfree(out);
1774	return err;
1775}
1776EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_state);
1777
1778int mlx5_core_query_ib_ppcnt(struct mlx5_core_dev *dev,
1779			     u8 port_num, void *out, size_t sz)
1780{
1781	u32 *in;
1782	int err;
1783
1784	in  = mlx5_vzalloc(sz);
1785	if (!in) {
1786		err = -ENOMEM;
1787		return err;
1788	}
1789
1790	MLX5_SET(ppcnt_reg, in, local_port, port_num);
1791
1792	MLX5_SET(ppcnt_reg, in, grp, MLX5_INFINIBAND_PORT_COUNTERS_GROUP);
1793	err = mlx5_core_access_reg(dev, in, sz, out,
1794				   sz, MLX5_REG_PPCNT, 0, 0);
1795
1796	kvfree(in);
1797	return err;
1798}
1799