Merge tag 'ntb-4.5' of git://github.com/jonmason/ntb
[linux-2.6-block.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 static int _mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod,
40                                    u16 vport, u32 *out, int outlen)
41 {
42         int err;
43         u32 in[MLX5_ST_SZ_DW(query_vport_state_in)];
44
45         memset(in, 0, sizeof(in));
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         err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, outlen);
55         if (err)
56                 mlx5_core_warn(mdev, "MLX5_CMD_OP_QUERY_VPORT_STATE failed\n");
57
58         return err;
59 }
60
61 u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
62 {
63         u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0};
64
65         _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out));
66
67         return MLX5_GET(query_vport_state_out, out, state);
68 }
69 EXPORT_SYMBOL_GPL(mlx5_query_vport_state);
70
71 u8 mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
72 {
73         u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0};
74
75         _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out));
76
77         return MLX5_GET(query_vport_state_out, out, admin_state);
78 }
79 EXPORT_SYMBOL(mlx5_query_vport_admin_state);
80
81 int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
82                                   u16 vport, u8 state)
83 {
84         u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)];
85         u32 out[MLX5_ST_SZ_DW(modify_vport_state_out)];
86         int err;
87
88         memset(in, 0, sizeof(in));
89
90         MLX5_SET(modify_vport_state_in, in, opcode,
91                  MLX5_CMD_OP_MODIFY_VPORT_STATE);
92         MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
93         MLX5_SET(modify_vport_state_in, in, vport_number, vport);
94
95         if (vport)
96                 MLX5_SET(modify_vport_state_in, in, other_vport, 1);
97
98         MLX5_SET(modify_vport_state_in, in, admin_state, state);
99
100         err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out,
101                                          sizeof(out));
102         if (err)
103                 mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_VPORT_STATE failed\n");
104
105         return err;
106 }
107 EXPORT_SYMBOL(mlx5_modify_vport_admin_state);
108
109 static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport,
110                                         u32 *out, int outlen)
111 {
112         u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];
113
114         memset(in, 0, sizeof(in));
115
116         MLX5_SET(query_nic_vport_context_in, in, opcode,
117                  MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
118
119         MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
120         if (vport)
121                 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
122
123         return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, outlen);
124 }
125
126 static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in,
127                                          int inlen)
128 {
129         u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
130
131         MLX5_SET(modify_nic_vport_context_in, in, opcode,
132                  MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
133
134         memset(out, 0, sizeof(out));
135         return mlx5_cmd_exec_check_status(mdev, in, inlen, out, sizeof(out));
136 }
137
138 int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev,
139                                      u16 vport, u8 *addr)
140 {
141         u32 *out;
142         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
143         u8 *out_addr;
144         int err;
145
146         out = mlx5_vzalloc(outlen);
147         if (!out)
148                 return -ENOMEM;
149
150         out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out,
151                                 nic_vport_context.permanent_address);
152
153         err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
154         if (err)
155                 goto out;
156
157         ether_addr_copy(addr, &out_addr[2]);
158
159 out:
160         kvfree(out);
161         return err;
162 }
163 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address);
164
165 int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev,
166                                       u16 vport, u8 *addr)
167 {
168         void *in;
169         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
170         int err;
171         void *nic_vport_ctx;
172         u8 *perm_mac;
173
174         in = mlx5_vzalloc(inlen);
175         if (!in) {
176                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
177                 return -ENOMEM;
178         }
179
180         MLX5_SET(modify_nic_vport_context_in, in,
181                  field_select.permanent_address, 1);
182         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
183
184         if (vport)
185                 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
186
187         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
188                                      in, nic_vport_context);
189         perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx,
190                                 permanent_address);
191
192         ether_addr_copy(&perm_mac[2], addr);
193
194         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
195
196         kvfree(in);
197
198         return err;
199 }
200 EXPORT_SYMBOL(mlx5_modify_nic_vport_mac_address);
201
202 int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
203                                   u32 vport,
204                                   enum mlx5_list_type list_type,
205                                   u8 addr_list[][ETH_ALEN],
206                                   int *list_size)
207 {
208         u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];
209         void *nic_vport_ctx;
210         int max_list_size;
211         int req_list_size;
212         int out_sz;
213         void *out;
214         int err;
215         int i;
216
217         req_list_size = *list_size;
218
219         max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
220                 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
221                 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
222
223         if (req_list_size > max_list_size) {
224                 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
225                                req_list_size, max_list_size);
226                 req_list_size = max_list_size;
227         }
228
229         out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
230                         req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
231
232         memset(in, 0, sizeof(in));
233         out = kzalloc(out_sz, GFP_KERNEL);
234         if (!out)
235                 return -ENOMEM;
236
237         MLX5_SET(query_nic_vport_context_in, in, opcode,
238                  MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
239         MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
240         MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
241
242         if (vport)
243                 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
244
245         err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_sz);
246         if (err)
247                 goto out;
248
249         nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
250                                      nic_vport_context);
251         req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
252                                  allowed_list_size);
253
254         *list_size = req_list_size;
255         for (i = 0; i < req_list_size; i++) {
256                 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
257                                         nic_vport_ctx,
258                                         current_uc_mac_address[i]) + 2;
259                 ether_addr_copy(addr_list[i], mac_addr);
260         }
261 out:
262         kfree(out);
263         return err;
264 }
265 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list);
266
267 int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
268                                    enum mlx5_list_type list_type,
269                                    u8 addr_list[][ETH_ALEN],
270                                    int list_size)
271 {
272         u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
273         void *nic_vport_ctx;
274         int max_list_size;
275         int in_sz;
276         void *in;
277         int err;
278         int i;
279
280         max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
281                  1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
282                  1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
283
284         if (list_size > max_list_size)
285                 return -ENOSPC;
286
287         in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
288                 list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
289
290         memset(out, 0, sizeof(out));
291         in = kzalloc(in_sz, GFP_KERNEL);
292         if (!in)
293                 return -ENOMEM;
294
295         MLX5_SET(modify_nic_vport_context_in, in, opcode,
296                  MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
297         MLX5_SET(modify_nic_vport_context_in, in,
298                  field_select.addresses_list, 1);
299
300         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
301                                      nic_vport_context);
302
303         MLX5_SET(nic_vport_context, nic_vport_ctx,
304                  allowed_list_type, list_type);
305         MLX5_SET(nic_vport_context, nic_vport_ctx,
306                  allowed_list_size, list_size);
307
308         for (i = 0; i < list_size; i++) {
309                 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context,
310                                             nic_vport_ctx,
311                                             current_uc_mac_address[i]) + 2;
312                 ether_addr_copy(curr_mac, addr_list[i]);
313         }
314
315         err = mlx5_cmd_exec_check_status(dev, in, in_sz, out, sizeof(out));
316         kfree(in);
317         return err;
318 }
319 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
320
321 int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,
322                                u32 vport,
323                                u16 vlans[],
324                                int *size)
325 {
326         u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];
327         void *nic_vport_ctx;
328         int req_list_size;
329         int max_list_size;
330         int out_sz;
331         void *out;
332         int err;
333         int i;
334
335         req_list_size = *size;
336         max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
337         if (req_list_size > max_list_size) {
338                 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max list size\n",
339                                req_list_size, max_list_size);
340                 req_list_size = max_list_size;
341         }
342
343         out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
344                         req_list_size * MLX5_ST_SZ_BYTES(vlan_layout);
345
346         memset(in, 0, sizeof(in));
347         out = kzalloc(out_sz, GFP_KERNEL);
348         if (!out)
349                 return -ENOMEM;
350
351         MLX5_SET(query_nic_vport_context_in, in, opcode,
352                  MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
353         MLX5_SET(query_nic_vport_context_in, in, allowed_list_type,
354                  MLX5_NVPRT_LIST_TYPE_VLAN);
355         MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
356
357         if (vport)
358                 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
359
360         err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_sz);
361         if (err)
362                 goto out;
363
364         nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
365                                      nic_vport_context);
366         req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
367                                  allowed_list_size);
368
369         *size = req_list_size;
370         for (i = 0; i < req_list_size; i++) {
371                 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
372                                                nic_vport_ctx,
373                                                current_uc_mac_address[i]);
374                 vlans[i] = MLX5_GET(vlan_layout, vlan_addr, vlan);
375         }
376 out:
377         kfree(out);
378         return err;
379 }
380 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_vlans);
381
382 int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
383                                 u16 vlans[],
384                                 int list_size)
385 {
386         u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
387         void *nic_vport_ctx;
388         int max_list_size;
389         int in_sz;
390         void *in;
391         int err;
392         int i;
393
394         max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
395
396         if (list_size > max_list_size)
397                 return -ENOSPC;
398
399         in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
400                 list_size * MLX5_ST_SZ_BYTES(vlan_layout);
401
402         memset(out, 0, sizeof(out));
403         in = kzalloc(in_sz, GFP_KERNEL);
404         if (!in)
405                 return -ENOMEM;
406
407         MLX5_SET(modify_nic_vport_context_in, in, opcode,
408                  MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
409         MLX5_SET(modify_nic_vport_context_in, in,
410                  field_select.addresses_list, 1);
411
412         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
413                                      nic_vport_context);
414
415         MLX5_SET(nic_vport_context, nic_vport_ctx,
416                  allowed_list_type, MLX5_NVPRT_LIST_TYPE_VLAN);
417         MLX5_SET(nic_vport_context, nic_vport_ctx,
418                  allowed_list_size, list_size);
419
420         for (i = 0; i < list_size; i++) {
421                 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
422                                                nic_vport_ctx,
423                                                current_uc_mac_address[i]);
424                 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]);
425         }
426
427         err = mlx5_cmd_exec_check_status(dev, in, in_sz, out, sizeof(out));
428         kfree(in);
429         return err;
430 }
431 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans);
432
433 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
434                              u8 port_num, u16  vf_num, u16 gid_index,
435                              union ib_gid *gid)
436 {
437         int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in);
438         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
439         int is_group_manager;
440         void *out = NULL;
441         void *in = NULL;
442         union ib_gid *tmp;
443         int tbsz;
444         int nout;
445         int err;
446
447         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
448         tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size));
449         mlx5_core_dbg(dev, "vf_num %d, index %d, gid_table_size %d\n",
450                       vf_num, gid_index, tbsz);
451
452         if (gid_index > tbsz && gid_index != 0xffff)
453                 return -EINVAL;
454
455         if (gid_index == 0xffff)
456                 nout = tbsz;
457         else
458                 nout = 1;
459
460         out_sz += nout * sizeof(*gid);
461
462         in = kzalloc(in_sz, GFP_KERNEL);
463         out = kzalloc(out_sz, GFP_KERNEL);
464         if (!in || !out) {
465                 err = -ENOMEM;
466                 goto out;
467         }
468
469         MLX5_SET(query_hca_vport_gid_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_GID);
470         if (other_vport) {
471                 if (is_group_manager) {
472                         MLX5_SET(query_hca_vport_gid_in, in, vport_number, vf_num);
473                         MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1);
474                 } else {
475                         err = -EPERM;
476                         goto out;
477                 }
478         }
479         MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index);
480
481         if (MLX5_CAP_GEN(dev, num_ports) == 2)
482                 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num);
483
484         err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
485         if (err)
486                 goto out;
487
488         err = mlx5_cmd_status_to_err_v2(out);
489         if (err)
490                 goto out;
491
492         tmp = out + MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
493         gid->global.subnet_prefix = tmp->global.subnet_prefix;
494         gid->global.interface_id = tmp->global.interface_id;
495
496 out:
497         kfree(in);
498         kfree(out);
499         return err;
500 }
501 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid);
502
503 int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
504                               u8 port_num, u16 vf_num, u16 pkey_index,
505                               u16 *pkey)
506 {
507         int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in);
508         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out);
509         int is_group_manager;
510         void *out = NULL;
511         void *in = NULL;
512         void *pkarr;
513         int nout;
514         int tbsz;
515         int err;
516         int i;
517
518         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
519
520         tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size));
521         if (pkey_index > tbsz && pkey_index != 0xffff)
522                 return -EINVAL;
523
524         if (pkey_index == 0xffff)
525                 nout = tbsz;
526         else
527                 nout = 1;
528
529         out_sz += nout * MLX5_ST_SZ_BYTES(pkey);
530
531         in = kzalloc(in_sz, GFP_KERNEL);
532         out = kzalloc(out_sz, GFP_KERNEL);
533         if (!in || !out) {
534                 err = -ENOMEM;
535                 goto out;
536         }
537
538         MLX5_SET(query_hca_vport_pkey_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY);
539         if (other_vport) {
540                 if (is_group_manager) {
541                         MLX5_SET(query_hca_vport_pkey_in, in, vport_number, vf_num);
542                         MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1);
543                 } else {
544                         err = -EPERM;
545                         goto out;
546                 }
547         }
548         MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index);
549
550         if (MLX5_CAP_GEN(dev, num_ports) == 2)
551                 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num);
552
553         err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
554         if (err)
555                 goto out;
556
557         err = mlx5_cmd_status_to_err_v2(out);
558         if (err)
559                 goto out;
560
561         pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey);
562         for (i = 0; i < nout; i++, pkey++, pkarr += MLX5_ST_SZ_BYTES(pkey))
563                 *pkey = MLX5_GET_PR(pkey, pkarr, pkey);
564
565 out:
566         kfree(in);
567         kfree(out);
568         return err;
569 }
570 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey);
571
572 int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev,
573                                  u8 other_vport, u8 port_num,
574                                  u16 vf_num,
575                                  struct mlx5_hca_vport_context *rep)
576 {
577         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
578         int in[MLX5_ST_SZ_DW(query_hca_vport_context_in)];
579         int is_group_manager;
580         void *out;
581         void *ctx;
582         int err;
583
584         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
585
586         memset(in, 0, sizeof(in));
587         out = kzalloc(out_sz, GFP_KERNEL);
588         if (!out)
589                 return -ENOMEM;
590
591         MLX5_SET(query_hca_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT);
592
593         if (other_vport) {
594                 if (is_group_manager) {
595                         MLX5_SET(query_hca_vport_context_in, in, other_vport, 1);
596                         MLX5_SET(query_hca_vport_context_in, in, vport_number, vf_num);
597                 } else {
598                         err = -EPERM;
599                         goto ex;
600                 }
601         }
602
603         if (MLX5_CAP_GEN(dev, num_ports) == 2)
604                 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num);
605
606         err = mlx5_cmd_exec(dev, in, sizeof(in), out,  out_sz);
607         if (err)
608                 goto ex;
609         err = mlx5_cmd_status_to_err_v2(out);
610         if (err)
611                 goto ex;
612
613         ctx = MLX5_ADDR_OF(query_hca_vport_context_out, out, hca_vport_context);
614         rep->field_select = MLX5_GET_PR(hca_vport_context, ctx, field_select);
615         rep->sm_virt_aware = MLX5_GET_PR(hca_vport_context, ctx, sm_virt_aware);
616         rep->has_smi = MLX5_GET_PR(hca_vport_context, ctx, has_smi);
617         rep->has_raw = MLX5_GET_PR(hca_vport_context, ctx, has_raw);
618         rep->policy = MLX5_GET_PR(hca_vport_context, ctx, vport_state_policy);
619         rep->phys_state = MLX5_GET_PR(hca_vport_context, ctx,
620                                       port_physical_state);
621         rep->vport_state = MLX5_GET_PR(hca_vport_context, ctx, vport_state);
622         rep->port_physical_state = MLX5_GET_PR(hca_vport_context, ctx,
623                                                port_physical_state);
624         rep->port_guid = MLX5_GET64_PR(hca_vport_context, ctx, port_guid);
625         rep->node_guid = MLX5_GET64_PR(hca_vport_context, ctx, node_guid);
626         rep->cap_mask1 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask1);
627         rep->cap_mask1_perm = MLX5_GET_PR(hca_vport_context, ctx,
628                                           cap_mask1_field_select);
629         rep->cap_mask2 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask2);
630         rep->cap_mask2_perm = MLX5_GET_PR(hca_vport_context, ctx,
631                                           cap_mask2_field_select);
632         rep->lid = MLX5_GET_PR(hca_vport_context, ctx, lid);
633         rep->init_type_reply = MLX5_GET_PR(hca_vport_context, ctx,
634                                            init_type_reply);
635         rep->lmc = MLX5_GET_PR(hca_vport_context, ctx, lmc);
636         rep->subnet_timeout = MLX5_GET_PR(hca_vport_context, ctx,
637                                           subnet_timeout);
638         rep->sm_lid = MLX5_GET_PR(hca_vport_context, ctx, sm_lid);
639         rep->sm_sl = MLX5_GET_PR(hca_vport_context, ctx, sm_sl);
640         rep->qkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
641                                                   qkey_violation_counter);
642         rep->pkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
643                                                   pkey_violation_counter);
644         rep->grh_required = MLX5_GET_PR(hca_vport_context, ctx, grh_required);
645         rep->sys_image_guid = MLX5_GET64_PR(hca_vport_context, ctx,
646                                             system_image_guid);
647
648 ex:
649         kfree(out);
650         return err;
651 }
652 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context);
653
654 int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev,
655                                            u64 *sys_image_guid)
656 {
657         struct mlx5_hca_vport_context *rep;
658         int err;
659
660         rep = kzalloc(sizeof(*rep), GFP_KERNEL);
661         if (!rep)
662                 return -ENOMEM;
663
664         err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
665         if (!err)
666                 *sys_image_guid = rep->sys_image_guid;
667
668         kfree(rep);
669         return err;
670 }
671 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid);
672
673 int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
674                                    u64 *node_guid)
675 {
676         struct mlx5_hca_vport_context *rep;
677         int err;
678
679         rep = kzalloc(sizeof(*rep), GFP_KERNEL);
680         if (!rep)
681                 return -ENOMEM;
682
683         err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
684         if (!err)
685                 *node_guid = rep->node_guid;
686
687         kfree(rep);
688         return err;
689 }
690 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
691
692 int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
693                                  u32 vport,
694                                  int *promisc_uc,
695                                  int *promisc_mc,
696                                  int *promisc_all)
697 {
698         u32 *out;
699         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
700         int err;
701
702         out = kzalloc(outlen, GFP_KERNEL);
703         if (!out)
704                 return -ENOMEM;
705
706         err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
707         if (err)
708                 goto out;
709
710         *promisc_uc = MLX5_GET(query_nic_vport_context_out, out,
711                                nic_vport_context.promisc_uc);
712         *promisc_mc = MLX5_GET(query_nic_vport_context_out, out,
713                                nic_vport_context.promisc_mc);
714         *promisc_all = MLX5_GET(query_nic_vport_context_out, out,
715                                 nic_vport_context.promisc_all);
716
717 out:
718         kfree(out);
719         return err;
720 }
721 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
722
723 int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,
724                                   int promisc_uc,
725                                   int promisc_mc,
726                                   int promisc_all)
727 {
728         void *in;
729         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
730         int err;
731
732         in = mlx5_vzalloc(inlen);
733         if (!in) {
734                 mlx5_core_err(mdev, "failed to allocate inbox\n");
735                 return -ENOMEM;
736         }
737
738         MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
739         MLX5_SET(modify_nic_vport_context_in, in,
740                  nic_vport_context.promisc_uc, promisc_uc);
741         MLX5_SET(modify_nic_vport_context_in, in,
742                  nic_vport_context.promisc_mc, promisc_mc);
743         MLX5_SET(modify_nic_vport_context_in, in,
744                  nic_vport_context.promisc_all, promisc_all);
745
746         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
747
748         kvfree(in);
749
750         return err;
751 }
752 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc);