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
40 /* Mutex to hold while enabling or disabling RoCE */
41 static DEFINE_MUTEX(mlx5_roce_en_lock);
42
mlx5_query_vport_state(struct mlx5_core_dev * mdev,u8 opmod,u16 vport)43 u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
44 {
45 u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {};
46 u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {};
47 int err;
48
49 MLX5_SET(query_vport_state_in, in, opcode,
50 MLX5_CMD_OP_QUERY_VPORT_STATE);
51 MLX5_SET(query_vport_state_in, in, op_mod, opmod);
52 MLX5_SET(query_vport_state_in, in, vport_number, vport);
53 if (vport)
54 MLX5_SET(query_vport_state_in, in, other_vport, 1);
55
56 err = mlx5_cmd_exec_inout(mdev, query_vport_state, in, out);
57 if (err)
58 return 0;
59
60 return MLX5_GET(query_vport_state_out, out, state);
61 }
62
mlx5_modify_vport_admin_state(struct mlx5_core_dev * mdev,u8 opmod,u16 vport,u8 other_vport,u8 state)63 int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
64 u16 vport, u8 other_vport, u8 state)
65 {
66 u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {};
67
68 MLX5_SET(modify_vport_state_in, in, opcode,
69 MLX5_CMD_OP_MODIFY_VPORT_STATE);
70 MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
71 MLX5_SET(modify_vport_state_in, in, vport_number, vport);
72 MLX5_SET(modify_vport_state_in, in, other_vport, other_vport);
73 MLX5_SET(modify_vport_state_in, in, admin_state, state);
74
75 return mlx5_cmd_exec_in(mdev, modify_vport_state, in);
76 }
77
mlx5_query_nic_vport_context(struct mlx5_core_dev * mdev,u16 vport,u32 * out)78 static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport,
79 u32 *out)
80 {
81 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {};
82
83 MLX5_SET(query_nic_vport_context_in, in, opcode,
84 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
85 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
86 if (vport)
87 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
88
89 return mlx5_cmd_exec_inout(mdev, query_nic_vport_context, in, out);
90 }
91
mlx5_query_nic_vport_min_inline(struct mlx5_core_dev * mdev,u16 vport,u8 * min_inline)92 int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
93 u16 vport, u8 *min_inline)
94 {
95 u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {};
96 int err;
97
98 err = mlx5_query_nic_vport_context(mdev, vport, out);
99 if (!err)
100 *min_inline = MLX5_GET(query_nic_vport_context_out, out,
101 nic_vport_context.min_wqe_inline_mode);
102 return err;
103 }
104 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_min_inline);
105
mlx5_query_min_inline(struct mlx5_core_dev * mdev,u8 * min_inline_mode)106 void mlx5_query_min_inline(struct mlx5_core_dev *mdev,
107 u8 *min_inline_mode)
108 {
109 switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) {
110 case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
111 if (!mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode))
112 break;
113 fallthrough;
114 case MLX5_CAP_INLINE_MODE_L2:
115 *min_inline_mode = MLX5_INLINE_MODE_L2;
116 break;
117 case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
118 *min_inline_mode = MLX5_INLINE_MODE_NONE;
119 break;
120 }
121 }
122 EXPORT_SYMBOL_GPL(mlx5_query_min_inline);
123
mlx5_modify_nic_vport_min_inline(struct mlx5_core_dev * mdev,u16 vport,u8 min_inline)124 int mlx5_modify_nic_vport_min_inline(struct mlx5_core_dev *mdev,
125 u16 vport, u8 min_inline)
126 {
127 u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {};
128 void *nic_vport_ctx;
129
130 MLX5_SET(modify_nic_vport_context_in, in,
131 field_select.min_inline, 1);
132 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
133 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
134
135 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
136 in, nic_vport_context);
137 MLX5_SET(nic_vport_context, nic_vport_ctx,
138 min_wqe_inline_mode, min_inline);
139 MLX5_SET(modify_nic_vport_context_in, in, opcode,
140 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
141
142 return mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
143 }
144
mlx5_query_nic_vport_mac_address(struct mlx5_core_dev * mdev,u16 vport,bool other,u8 * addr)145 int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev,
146 u16 vport, bool other, u8 *addr)
147 {
148 u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {};
149 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {};
150 u8 *out_addr;
151 int err;
152
153 out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out,
154 nic_vport_context.permanent_address);
155
156 MLX5_SET(query_nic_vport_context_in, in, opcode,
157 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
158 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
159 MLX5_SET(query_nic_vport_context_in, in, other_vport, other);
160
161 err = mlx5_cmd_exec_inout(mdev, query_nic_vport_context, in, out);
162 if (!err)
163 ether_addr_copy(addr, &out_addr[2]);
164
165 return err;
166 }
167 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address);
168
mlx5_query_mac_address(struct mlx5_core_dev * mdev,u8 * addr)169 int mlx5_query_mac_address(struct mlx5_core_dev *mdev, u8 *addr)
170 {
171 return mlx5_query_nic_vport_mac_address(mdev, 0, false, addr);
172 }
173 EXPORT_SYMBOL_GPL(mlx5_query_mac_address);
174
mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev * mdev,u16 vport,const u8 * addr)175 int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev,
176 u16 vport, const u8 *addr)
177 {
178 void *in;
179 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
180 int err;
181 void *nic_vport_ctx;
182 u8 *perm_mac;
183
184 in = kvzalloc(inlen, GFP_KERNEL);
185 if (!in)
186 return -ENOMEM;
187
188 MLX5_SET(modify_nic_vport_context_in, in,
189 field_select.permanent_address, 1);
190 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
191 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
192
193 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
194 in, nic_vport_context);
195 perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx,
196 permanent_address);
197
198 ether_addr_copy(&perm_mac[2], addr);
199 MLX5_SET(modify_nic_vport_context_in, in, opcode,
200 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
201
202 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
203
204 kvfree(in);
205
206 return err;
207 }
208 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_address);
209
mlx5_query_nic_vport_mtu(struct mlx5_core_dev * mdev,u16 * mtu)210 int mlx5_query_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 *mtu)
211 {
212 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
213 u32 *out;
214 int err;
215
216 out = kvzalloc(outlen, GFP_KERNEL);
217 if (!out)
218 return -ENOMEM;
219
220 err = mlx5_query_nic_vport_context(mdev, 0, out);
221 if (!err)
222 *mtu = MLX5_GET(query_nic_vport_context_out, out,
223 nic_vport_context.mtu);
224
225 kvfree(out);
226 return err;
227 }
228 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mtu);
229
mlx5_modify_nic_vport_mtu(struct mlx5_core_dev * mdev,u16 mtu)230 int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu)
231 {
232 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
233 void *in;
234 int err;
235
236 in = kvzalloc(inlen, GFP_KERNEL);
237 if (!in)
238 return -ENOMEM;
239
240 MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1);
241 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, mtu);
242 MLX5_SET(modify_nic_vport_context_in, in, opcode,
243 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
244
245 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
246
247 kvfree(in);
248 return err;
249 }
250 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu);
251
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 * list_size)252 int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
253 u16 vport,
254 enum mlx5_list_type list_type,
255 u8 addr_list[][ETH_ALEN],
256 int *list_size)
257 {
258 u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
259 void *nic_vport_ctx;
260 int max_list_size;
261 int req_list_size;
262 int out_sz;
263 void *out;
264 int err;
265 int i;
266
267 req_list_size = *list_size;
268
269 max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
270 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
271 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
272
273 if (req_list_size > max_list_size) {
274 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
275 req_list_size, max_list_size);
276 req_list_size = max_list_size;
277 }
278
279 out_sz = MLX5_ST_SZ_BYTES(query_nic_vport_context_in) +
280 req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
281
282 out = kzalloc(out_sz, GFP_KERNEL);
283 if (!out)
284 return -ENOMEM;
285
286 MLX5_SET(query_nic_vport_context_in, in, opcode,
287 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
288 MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
289 MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
290 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
291
292 err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
293 if (err)
294 goto out;
295
296 nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
297 nic_vport_context);
298 req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
299 allowed_list_size);
300
301 *list_size = req_list_size;
302 for (i = 0; i < req_list_size; i++) {
303 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
304 nic_vport_ctx,
305 current_uc_mac_address[i]) + 2;
306 ether_addr_copy(addr_list[i], mac_addr);
307 }
308 out:
309 kfree(out);
310 return err;
311 }
312 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list);
313
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)314 int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
315 enum mlx5_list_type list_type,
316 u8 addr_list[][ETH_ALEN],
317 int list_size)
318 {
319 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {};
320 void *nic_vport_ctx;
321 int max_list_size;
322 int in_sz;
323 void *in;
324 int err;
325 int i;
326
327 max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
328 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
329 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
330
331 if (list_size > max_list_size)
332 return -ENOSPC;
333
334 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
335 list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
336
337 in = kzalloc(in_sz, GFP_KERNEL);
338 if (!in)
339 return -ENOMEM;
340
341 MLX5_SET(modify_nic_vport_context_in, in, opcode,
342 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
343 MLX5_SET(modify_nic_vport_context_in, in,
344 field_select.addresses_list, 1);
345
346 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
347 nic_vport_context);
348
349 MLX5_SET(nic_vport_context, nic_vport_ctx,
350 allowed_list_type, list_type);
351 MLX5_SET(nic_vport_context, nic_vport_ctx,
352 allowed_list_size, list_size);
353
354 for (i = 0; i < list_size; i++) {
355 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context,
356 nic_vport_ctx,
357 current_uc_mac_address[i]) + 2;
358 ether_addr_copy(curr_mac, addr_list[i]);
359 }
360
361 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
362 kfree(in);
363 return err;
364 }
365 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
366
mlx5_modify_nic_vport_vlans(struct mlx5_core_dev * dev,u16 vlans[],int list_size)367 int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
368 u16 vlans[],
369 int list_size)
370 {
371 u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
372 void *nic_vport_ctx;
373 int max_list_size;
374 int in_sz;
375 void *in;
376 int err;
377 int i;
378
379 max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
380
381 if (list_size > max_list_size)
382 return -ENOSPC;
383
384 in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
385 list_size * MLX5_ST_SZ_BYTES(vlan_layout);
386
387 memset(out, 0, sizeof(out));
388 in = kzalloc(in_sz, GFP_KERNEL);
389 if (!in)
390 return -ENOMEM;
391
392 MLX5_SET(modify_nic_vport_context_in, in, opcode,
393 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
394 MLX5_SET(modify_nic_vport_context_in, in,
395 field_select.addresses_list, 1);
396
397 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
398 nic_vport_context);
399
400 MLX5_SET(nic_vport_context, nic_vport_ctx,
401 allowed_list_type, MLX5_NVPRT_LIST_TYPE_VLAN);
402 MLX5_SET(nic_vport_context, nic_vport_ctx,
403 allowed_list_size, list_size);
404
405 for (i = 0; i < list_size; i++) {
406 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
407 nic_vport_ctx,
408 current_uc_mac_address[i]);
409 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]);
410 }
411
412 err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
413 kfree(in);
414 return err;
415 }
416 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans);
417
mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev * mdev,u64 * system_image_guid)418 int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
419 u64 *system_image_guid)
420 {
421 u32 *out;
422 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
423
424 out = kvzalloc(outlen, GFP_KERNEL);
425 if (!out)
426 return -ENOMEM;
427
428 mlx5_query_nic_vport_context(mdev, 0, out);
429
430 *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out,
431 nic_vport_context.system_image_guid);
432
433 kvfree(out);
434
435 return 0;
436 }
437 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid);
438
mlx5_query_nic_vport_node_guid(struct mlx5_core_dev * mdev,u64 * node_guid)439 int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
440 {
441 u32 *out;
442 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
443
444 out = kvzalloc(outlen, GFP_KERNEL);
445 if (!out)
446 return -ENOMEM;
447
448 mlx5_query_nic_vport_context(mdev, 0, out);
449
450 *node_guid = MLX5_GET64(query_nic_vport_context_out, out,
451 nic_vport_context.node_guid);
452
453 kvfree(out);
454
455 return 0;
456 }
457 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
458
mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev * mdev,u16 vport,u64 node_guid)459 int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
460 u16 vport, u64 node_guid)
461 {
462 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
463 void *nic_vport_context;
464 void *in;
465 int err;
466
467 if (!vport)
468 return -EINVAL;
469 if (!MLX5_CAP_GEN(mdev, vport_group_manager))
470 return -EACCES;
471
472 in = kvzalloc(inlen, GFP_KERNEL);
473 if (!in)
474 return -ENOMEM;
475
476 MLX5_SET(modify_nic_vport_context_in, in,
477 field_select.node_guid, 1);
478 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
479 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
480
481 nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
482 in, nic_vport_context);
483 MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid);
484 MLX5_SET(modify_nic_vport_context_in, in, opcode,
485 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
486
487 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
488
489 kvfree(in);
490
491 return err;
492 }
493
mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev * mdev,u16 * qkey_viol_cntr)494 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
495 u16 *qkey_viol_cntr)
496 {
497 u32 *out;
498 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
499
500 out = kvzalloc(outlen, GFP_KERNEL);
501 if (!out)
502 return -ENOMEM;
503
504 mlx5_query_nic_vport_context(mdev, 0, out);
505
506 *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out,
507 nic_vport_context.qkey_violation_counter);
508
509 kvfree(out);
510
511 return 0;
512 }
513 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr);
514
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)515 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
516 u8 port_num, u16 vf_num, u16 gid_index,
517 union ib_gid *gid)
518 {
519 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in);
520 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
521 int is_group_manager;
522 void *out = NULL;
523 void *in = NULL;
524 union ib_gid *tmp;
525 int tbsz;
526 int nout;
527 int err;
528
529 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
530 tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size));
531 mlx5_core_dbg(dev, "vf_num %d, index %d, gid_table_size %d\n",
532 vf_num, gid_index, tbsz);
533
534 if (gid_index > tbsz && gid_index != 0xffff)
535 return -EINVAL;
536
537 if (gid_index == 0xffff)
538 nout = tbsz;
539 else
540 nout = 1;
541
542 out_sz += nout * sizeof(*gid);
543
544 in = kzalloc(in_sz, GFP_KERNEL);
545 out = kzalloc(out_sz, GFP_KERNEL);
546 if (!in || !out) {
547 err = -ENOMEM;
548 goto out;
549 }
550
551 MLX5_SET(query_hca_vport_gid_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_GID);
552 if (other_vport) {
553 if (is_group_manager) {
554 MLX5_SET(query_hca_vport_gid_in, in, vport_number, vf_num);
555 MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1);
556 } else {
557 err = -EPERM;
558 goto out;
559 }
560 }
561 MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index);
562
563 if (MLX5_CAP_GEN(dev, num_ports) == 2)
564 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num);
565
566 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
567 if (err)
568 goto out;
569
570 tmp = out + MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
571 gid->global.subnet_prefix = tmp->global.subnet_prefix;
572 gid->global.interface_id = tmp->global.interface_id;
573
574 out:
575 kfree(in);
576 kfree(out);
577 return err;
578 }
579 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid);
580
mlx5_query_hca_vport_pkey(struct mlx5_core_dev * dev,u8 other_vport,u8 port_num,u16 vf_num,u16 pkey_index,u16 * pkey)581 int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
582 u8 port_num, u16 vf_num, u16 pkey_index,
583 u16 *pkey)
584 {
585 int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in);
586 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out);
587 int is_group_manager;
588 void *out = NULL;
589 void *in = NULL;
590 void *pkarr;
591 int nout;
592 int tbsz;
593 int err;
594 int i;
595
596 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
597
598 tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size));
599 if (pkey_index > tbsz && pkey_index != 0xffff)
600 return -EINVAL;
601
602 if (pkey_index == 0xffff)
603 nout = tbsz;
604 else
605 nout = 1;
606
607 out_sz += nout * MLX5_ST_SZ_BYTES(pkey);
608
609 in = kzalloc(in_sz, GFP_KERNEL);
610 out = kzalloc(out_sz, GFP_KERNEL);
611 if (!in || !out) {
612 err = -ENOMEM;
613 goto out;
614 }
615
616 MLX5_SET(query_hca_vport_pkey_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY);
617 if (other_vport) {
618 if (is_group_manager) {
619 MLX5_SET(query_hca_vport_pkey_in, in, vport_number, vf_num);
620 MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1);
621 } else {
622 err = -EPERM;
623 goto out;
624 }
625 }
626 MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index);
627
628 if (MLX5_CAP_GEN(dev, num_ports) == 2)
629 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num);
630
631 err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
632 if (err)
633 goto out;
634
635 pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey);
636 for (i = 0; i < nout; i++, pkey++, pkarr += MLX5_ST_SZ_BYTES(pkey))
637 *pkey = MLX5_GET_PR(pkey, pkarr, pkey);
638
639 out:
640 kfree(in);
641 kfree(out);
642 return err;
643 }
644 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey);
645
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)646 int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev,
647 u8 other_vport, u8 port_num,
648 u16 vf_num,
649 struct mlx5_hca_vport_context *rep)
650 {
651 int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
652 int in[MLX5_ST_SZ_DW(query_hca_vport_context_in)] = {};
653 int is_group_manager;
654 void *out;
655 void *ctx;
656 int err;
657
658 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
659
660 out = kzalloc(out_sz, GFP_KERNEL);
661 if (!out)
662 return -ENOMEM;
663
664 MLX5_SET(query_hca_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT);
665
666 if (other_vport) {
667 if (is_group_manager) {
668 MLX5_SET(query_hca_vport_context_in, in, other_vport, 1);
669 MLX5_SET(query_hca_vport_context_in, in, vport_number, vf_num);
670 } else {
671 err = -EPERM;
672 goto ex;
673 }
674 }
675
676 if (MLX5_CAP_GEN(dev, num_ports) == 2)
677 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num);
678
679 err = mlx5_cmd_exec_inout(dev, query_hca_vport_context, in, out);
680 if (err)
681 goto ex;
682
683 ctx = MLX5_ADDR_OF(query_hca_vport_context_out, out, hca_vport_context);
684 rep->field_select = MLX5_GET_PR(hca_vport_context, ctx, field_select);
685 rep->sm_virt_aware = MLX5_GET_PR(hca_vport_context, ctx, sm_virt_aware);
686 rep->has_smi = MLX5_GET_PR(hca_vport_context, ctx, has_smi);
687 rep->has_raw = MLX5_GET_PR(hca_vport_context, ctx, has_raw);
688 rep->policy = MLX5_GET_PR(hca_vport_context, ctx, vport_state_policy);
689 rep->phys_state = MLX5_GET_PR(hca_vport_context, ctx,
690 port_physical_state);
691 rep->vport_state = MLX5_GET_PR(hca_vport_context, ctx, vport_state);
692 rep->port_physical_state = MLX5_GET_PR(hca_vport_context, ctx,
693 port_physical_state);
694 rep->port_guid = MLX5_GET64_PR(hca_vport_context, ctx, port_guid);
695 rep->node_guid = MLX5_GET64_PR(hca_vport_context, ctx, node_guid);
696 rep->cap_mask1 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask1);
697 rep->cap_mask1_perm = MLX5_GET_PR(hca_vport_context, ctx,
698 cap_mask1_field_select);
699 rep->cap_mask2 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask2);
700 rep->cap_mask2_perm = MLX5_GET_PR(hca_vport_context, ctx,
701 cap_mask2_field_select);
702 rep->lid = MLX5_GET_PR(hca_vport_context, ctx, lid);
703 rep->init_type_reply = MLX5_GET_PR(hca_vport_context, ctx,
704 init_type_reply);
705 rep->lmc = MLX5_GET_PR(hca_vport_context, ctx, lmc);
706 rep->subnet_timeout = MLX5_GET_PR(hca_vport_context, ctx,
707 subnet_timeout);
708 rep->sm_lid = MLX5_GET_PR(hca_vport_context, ctx, sm_lid);
709 rep->sm_sl = MLX5_GET_PR(hca_vport_context, ctx, sm_sl);
710 rep->qkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
711 qkey_violation_counter);
712 rep->pkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
713 pkey_violation_counter);
714 rep->grh_required = MLX5_GET_PR(hca_vport_context, ctx, grh_required);
715 rep->sys_image_guid = MLX5_GET64_PR(hca_vport_context, ctx,
716 system_image_guid);
717
718 ex:
719 kfree(out);
720 return err;
721 }
722 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context);
723
mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev * dev,u64 * sys_image_guid)724 int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev,
725 u64 *sys_image_guid)
726 {
727 struct mlx5_hca_vport_context *rep;
728 int err;
729
730 rep = kzalloc(sizeof(*rep), GFP_KERNEL);
731 if (!rep)
732 return -ENOMEM;
733
734 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
735 if (!err)
736 *sys_image_guid = rep->sys_image_guid;
737
738 kfree(rep);
739 return err;
740 }
741 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid);
742
mlx5_query_hca_vport_node_guid(struct mlx5_core_dev * dev,u64 * node_guid)743 int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
744 u64 *node_guid)
745 {
746 struct mlx5_hca_vport_context *rep;
747 int err;
748
749 rep = kzalloc(sizeof(*rep), GFP_KERNEL);
750 if (!rep)
751 return -ENOMEM;
752
753 err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
754 if (!err)
755 *node_guid = rep->node_guid;
756
757 kfree(rep);
758 return err;
759 }
760 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
761
mlx5_query_nic_vport_promisc(struct mlx5_core_dev * mdev,u16 vport,int * promisc_uc,int * promisc_mc,int * promisc_all)762 int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
763 u16 vport,
764 int *promisc_uc,
765 int *promisc_mc,
766 int *promisc_all)
767 {
768 u32 *out;
769 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
770 int err;
771
772 out = kzalloc(outlen, GFP_KERNEL);
773 if (!out)
774 return -ENOMEM;
775
776 err = mlx5_query_nic_vport_context(mdev, vport, out);
777 if (err)
778 goto out;
779
780 *promisc_uc = MLX5_GET(query_nic_vport_context_out, out,
781 nic_vport_context.promisc_uc);
782 *promisc_mc = MLX5_GET(query_nic_vport_context_out, out,
783 nic_vport_context.promisc_mc);
784 *promisc_all = MLX5_GET(query_nic_vport_context_out, out,
785 nic_vport_context.promisc_all);
786
787 out:
788 kfree(out);
789 return err;
790 }
791 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
792
mlx5_modify_nic_vport_promisc(struct mlx5_core_dev * mdev,int promisc_uc,int promisc_mc,int promisc_all)793 int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,
794 int promisc_uc,
795 int promisc_mc,
796 int promisc_all)
797 {
798 void *in;
799 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
800 int err;
801
802 in = kvzalloc(inlen, GFP_KERNEL);
803 if (!in)
804 return -ENOMEM;
805
806 MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
807 MLX5_SET(modify_nic_vport_context_in, in,
808 nic_vport_context.promisc_uc, promisc_uc);
809 MLX5_SET(modify_nic_vport_context_in, in,
810 nic_vport_context.promisc_mc, promisc_mc);
811 MLX5_SET(modify_nic_vport_context_in, in,
812 nic_vport_context.promisc_all, promisc_all);
813 MLX5_SET(modify_nic_vport_context_in, in, opcode,
814 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
815
816 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
817
818 kvfree(in);
819
820 return err;
821 }
822 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc);
823
824 enum {
825 UC_LOCAL_LB,
826 MC_LOCAL_LB
827 };
828
mlx5_nic_vport_update_local_lb(struct mlx5_core_dev * mdev,bool enable)829 int mlx5_nic_vport_update_local_lb(struct mlx5_core_dev *mdev, bool enable)
830 {
831 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
832 void *in;
833 int err;
834
835 if (!MLX5_CAP_GEN(mdev, disable_local_lb_mc) &&
836 !MLX5_CAP_GEN(mdev, disable_local_lb_uc))
837 return 0;
838
839 in = kvzalloc(inlen, GFP_KERNEL);
840 if (!in)
841 return -ENOMEM;
842
843 MLX5_SET(modify_nic_vport_context_in, in,
844 nic_vport_context.disable_mc_local_lb, !enable);
845 MLX5_SET(modify_nic_vport_context_in, in,
846 nic_vport_context.disable_uc_local_lb, !enable);
847
848 if (MLX5_CAP_GEN(mdev, disable_local_lb_mc))
849 MLX5_SET(modify_nic_vport_context_in, in,
850 field_select.disable_mc_local_lb, 1);
851
852 if (MLX5_CAP_GEN(mdev, disable_local_lb_uc))
853 MLX5_SET(modify_nic_vport_context_in, in,
854 field_select.disable_uc_local_lb, 1);
855 MLX5_SET(modify_nic_vport_context_in, in, opcode,
856 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
857
858 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
859
860 if (!err)
861 mlx5_core_dbg(mdev, "%s local_lb\n",
862 enable ? "enable" : "disable");
863
864 kvfree(in);
865 return err;
866 }
867 EXPORT_SYMBOL_GPL(mlx5_nic_vport_update_local_lb);
868
mlx5_nic_vport_query_local_lb(struct mlx5_core_dev * mdev,bool * status)869 int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status)
870 {
871 int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
872 u32 *out;
873 int value;
874 int err;
875
876 out = kzalloc(outlen, GFP_KERNEL);
877 if (!out)
878 return -ENOMEM;
879
880 err = mlx5_query_nic_vport_context(mdev, 0, out);
881 if (err)
882 goto out;
883
884 value = MLX5_GET(query_nic_vport_context_out, out,
885 nic_vport_context.disable_mc_local_lb) << MC_LOCAL_LB;
886
887 value |= MLX5_GET(query_nic_vport_context_out, out,
888 nic_vport_context.disable_uc_local_lb) << UC_LOCAL_LB;
889
890 *status = !value;
891
892 out:
893 kfree(out);
894 return err;
895 }
896 EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb);
897
898 enum mlx5_vport_roce_state {
899 MLX5_VPORT_ROCE_DISABLED = 0,
900 MLX5_VPORT_ROCE_ENABLED = 1,
901 };
902
mlx5_nic_vport_update_roce_state(struct mlx5_core_dev * mdev,enum mlx5_vport_roce_state state)903 static int mlx5_nic_vport_update_roce_state(struct mlx5_core_dev *mdev,
904 enum mlx5_vport_roce_state state)
905 {
906 void *in;
907 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
908 int err;
909
910 in = kvzalloc(inlen, GFP_KERNEL);
911 if (!in)
912 return -ENOMEM;
913
914 MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1);
915 MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en,
916 state);
917 MLX5_SET(modify_nic_vport_context_in, in, opcode,
918 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
919
920 err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in);
921
922 kvfree(in);
923
924 return err;
925 }
926
mlx5_nic_vport_enable_roce(struct mlx5_core_dev * mdev)927 int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev)
928 {
929 int err = 0;
930
931 mutex_lock(&mlx5_roce_en_lock);
932 if (!mdev->roce.roce_en)
933 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED);
934
935 if (!err)
936 mdev->roce.roce_en++;
937 mutex_unlock(&mlx5_roce_en_lock);
938
939 return err;
940 }
941 EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce);
942
mlx5_nic_vport_disable_roce(struct mlx5_core_dev * mdev)943 int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev)
944 {
945 int err = 0;
946
947 mutex_lock(&mlx5_roce_en_lock);
948 if (mdev->roce.roce_en) {
949 mdev->roce.roce_en--;
950 if (mdev->roce.roce_en == 0)
951 err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED);
952
953 if (err)
954 mdev->roce.roce_en++;
955 }
956 mutex_unlock(&mlx5_roce_en_lock);
957 return err;
958 }
959 EXPORT_SYMBOL(mlx5_nic_vport_disable_roce);
960
mlx5_core_query_vport_counter(struct mlx5_core_dev * dev,u8 other_vport,int vf,u8 port_num,void * out)961 int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport,
962 int vf, u8 port_num, void *out)
963 {
964 int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in);
965 int is_group_manager;
966 void *in;
967 int err;
968
969 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
970 in = kvzalloc(in_sz, GFP_KERNEL);
971 if (!in) {
972 err = -ENOMEM;
973 return err;
974 }
975
976 MLX5_SET(query_vport_counter_in, in, opcode,
977 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
978 if (other_vport) {
979 if (is_group_manager) {
980 MLX5_SET(query_vport_counter_in, in, other_vport, 1);
981 MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1);
982 } else {
983 err = -EPERM;
984 goto free;
985 }
986 }
987 if (MLX5_CAP_GEN(dev, num_ports) == 2)
988 MLX5_SET(query_vport_counter_in, in, port_num, port_num);
989
990 err = mlx5_cmd_exec_inout(dev, query_vport_counter, in, out);
991 free:
992 kvfree(in);
993 return err;
994 }
995 EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter);
996
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)997 int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport,
998 u8 other_vport, u64 *rx_discard_vport_down,
999 u64 *tx_discard_vport_down)
1000 {
1001 u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {};
1002 u32 in[MLX5_ST_SZ_DW(query_vnic_env_in)] = {};
1003 int err;
1004
1005 MLX5_SET(query_vnic_env_in, in, opcode,
1006 MLX5_CMD_OP_QUERY_VNIC_ENV);
1007 MLX5_SET(query_vnic_env_in, in, op_mod, 0);
1008 MLX5_SET(query_vnic_env_in, in, vport_number, vport);
1009 MLX5_SET(query_vnic_env_in, in, other_vport, other_vport);
1010
1011 err = mlx5_cmd_exec_inout(mdev, query_vnic_env, in, out);
1012 if (err)
1013 return err;
1014
1015 *rx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out,
1016 vport_env.receive_discard_vport_down);
1017 *tx_discard_vport_down = MLX5_GET64(query_vnic_env_out, out,
1018 vport_env.transmit_discard_vport_down);
1019 return 0;
1020 }
1021
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)1022 int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev,
1023 u8 other_vport, u8 port_num,
1024 int vf,
1025 struct mlx5_hca_vport_context *req)
1026 {
1027 int in_sz = MLX5_ST_SZ_BYTES(modify_hca_vport_context_in);
1028 int is_group_manager;
1029 void *ctx;
1030 void *in;
1031 int err;
1032
1033 mlx5_core_dbg(dev, "vf %d\n", vf);
1034 is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1035 in = kzalloc(in_sz, GFP_KERNEL);
1036 if (!in)
1037 return -ENOMEM;
1038
1039 MLX5_SET(modify_hca_vport_context_in, in, opcode, MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT);
1040 if (other_vport) {
1041 if (is_group_manager) {
1042 MLX5_SET(modify_hca_vport_context_in, in, other_vport, 1);
1043 MLX5_SET(modify_hca_vport_context_in, in, vport_number, vf);
1044 } else {
1045 err = -EPERM;
1046 goto ex;
1047 }
1048 }
1049
1050 if (MLX5_CAP_GEN(dev, num_ports) > 1)
1051 MLX5_SET(modify_hca_vport_context_in, in, port_num, port_num);
1052
1053 ctx = MLX5_ADDR_OF(modify_hca_vport_context_in, in, hca_vport_context);
1054 MLX5_SET(hca_vport_context, ctx, field_select, req->field_select);
1055 if (req->field_select & MLX5_HCA_VPORT_SEL_STATE_POLICY)
1056 MLX5_SET(hca_vport_context, ctx, vport_state_policy,
1057 req->policy);
1058 if (req->field_select & MLX5_HCA_VPORT_SEL_PORT_GUID)
1059 MLX5_SET64(hca_vport_context, ctx, port_guid, req->port_guid);
1060 if (req->field_select & MLX5_HCA_VPORT_SEL_NODE_GUID)
1061 MLX5_SET64(hca_vport_context, ctx, node_guid, req->node_guid);
1062 MLX5_SET(hca_vport_context, ctx, cap_mask1, req->cap_mask1);
1063 MLX5_SET(hca_vport_context, ctx, cap_mask1_field_select,
1064 req->cap_mask1_perm);
1065 err = mlx5_cmd_exec_in(dev, modify_hca_vport_context, in);
1066 ex:
1067 kfree(in);
1068 return err;
1069 }
1070 EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context);
1071
mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev * master_mdev,struct mlx5_core_dev * port_mdev)1072 int mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev *master_mdev,
1073 struct mlx5_core_dev *port_mdev)
1074 {
1075 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1076 void *in;
1077 int err;
1078
1079 in = kvzalloc(inlen, GFP_KERNEL);
1080 if (!in)
1081 return -ENOMEM;
1082
1083 err = mlx5_nic_vport_enable_roce(port_mdev);
1084 if (err)
1085 goto free;
1086
1087 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1);
1088 MLX5_SET(modify_nic_vport_context_in, in,
1089 nic_vport_context.affiliated_vhca_id,
1090 MLX5_CAP_GEN(master_mdev, vhca_id));
1091 MLX5_SET(modify_nic_vport_context_in, in,
1092 nic_vport_context.affiliation_criteria,
1093 MLX5_CAP_GEN(port_mdev, affiliate_nic_vport_criteria));
1094 MLX5_SET(modify_nic_vport_context_in, in, opcode,
1095 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
1096
1097 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in);
1098 if (err)
1099 mlx5_nic_vport_disable_roce(port_mdev);
1100
1101 free:
1102 kvfree(in);
1103 return err;
1104 }
1105 EXPORT_SYMBOL_GPL(mlx5_nic_vport_affiliate_multiport);
1106
mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev * port_mdev)1107 int mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev *port_mdev)
1108 {
1109 int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1110 void *in;
1111 int err;
1112
1113 in = kvzalloc(inlen, GFP_KERNEL);
1114 if (!in)
1115 return -ENOMEM;
1116
1117 MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1);
1118 MLX5_SET(modify_nic_vport_context_in, in,
1119 nic_vport_context.affiliated_vhca_id, 0);
1120 MLX5_SET(modify_nic_vport_context_in, in,
1121 nic_vport_context.affiliation_criteria, 0);
1122 MLX5_SET(modify_nic_vport_context_in, in, opcode,
1123 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
1124
1125 err = mlx5_cmd_exec_in(port_mdev, modify_nic_vport_context, in);
1126 if (!err)
1127 mlx5_nic_vport_disable_roce(port_mdev);
1128
1129 kvfree(in);
1130 return err;
1131 }
1132 EXPORT_SYMBOL_GPL(mlx5_nic_vport_unaffiliate_multiport);
1133
mlx5_query_nic_system_image_guid(struct mlx5_core_dev * mdev)1134 u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev)
1135 {
1136 int port_type_cap = MLX5_CAP_GEN(mdev, port_type);
1137 u64 tmp = 0;
1138
1139 if (mdev->sys_image_guid)
1140 return mdev->sys_image_guid;
1141
1142 if (port_type_cap == MLX5_CAP_PORT_TYPE_ETH)
1143 mlx5_query_nic_vport_system_image_guid(mdev, &tmp);
1144 else
1145 mlx5_query_hca_vport_system_image_guid(mdev, &tmp);
1146
1147 mdev->sys_image_guid = tmp;
1148
1149 return tmp;
1150 }
1151 EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid);
1152
1153 /**
1154 * mlx5_eswitch_get_total_vports - Get total vports of the eswitch
1155 *
1156 * @dev: Pointer to core device
1157 *
1158 * mlx5_eswitch_get_total_vports returns total number of vports for
1159 * the eswitch.
1160 */
mlx5_eswitch_get_total_vports(const struct mlx5_core_dev * dev)1161 u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev)
1162 {
1163 return MLX5_SPECIAL_VPORTS(dev) + mlx5_core_max_vfs(dev);
1164 }
1165 EXPORT_SYMBOL_GPL(mlx5_eswitch_get_total_vports);
1166