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