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