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