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