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