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