net/mlx5: Introduce access functions to modify/query vport promisc mode
[cascardo/linux.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_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
322                              u8 port_num, u16  vf_num, u16 gid_index,
323                              union ib_gid *gid)
324 {
325         int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in);
326         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
327         int is_group_manager;
328         void *out = NULL;
329         void *in = NULL;
330         union ib_gid *tmp;
331         int tbsz;
332         int nout;
333         int err;
334
335         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
336         tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size));
337         mlx5_core_dbg(dev, "vf_num %d, index %d, gid_table_size %d\n",
338                       vf_num, gid_index, tbsz);
339
340         if (gid_index > tbsz && gid_index != 0xffff)
341                 return -EINVAL;
342
343         if (gid_index == 0xffff)
344                 nout = tbsz;
345         else
346                 nout = 1;
347
348         out_sz += nout * sizeof(*gid);
349
350         in = kzalloc(in_sz, GFP_KERNEL);
351         out = kzalloc(out_sz, GFP_KERNEL);
352         if (!in || !out) {
353                 err = -ENOMEM;
354                 goto out;
355         }
356
357         MLX5_SET(query_hca_vport_gid_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_GID);
358         if (other_vport) {
359                 if (is_group_manager) {
360                         MLX5_SET(query_hca_vport_gid_in, in, vport_number, vf_num);
361                         MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1);
362                 } else {
363                         err = -EPERM;
364                         goto out;
365                 }
366         }
367         MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index);
368
369         if (MLX5_CAP_GEN(dev, num_ports) == 2)
370                 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num);
371
372         err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
373         if (err)
374                 goto out;
375
376         err = mlx5_cmd_status_to_err_v2(out);
377         if (err)
378                 goto out;
379
380         tmp = out + MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
381         gid->global.subnet_prefix = tmp->global.subnet_prefix;
382         gid->global.interface_id = tmp->global.interface_id;
383
384 out:
385         kfree(in);
386         kfree(out);
387         return err;
388 }
389 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid);
390
391 int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
392                               u8 port_num, u16 vf_num, u16 pkey_index,
393                               u16 *pkey)
394 {
395         int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in);
396         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out);
397         int is_group_manager;
398         void *out = NULL;
399         void *in = NULL;
400         void *pkarr;
401         int nout;
402         int tbsz;
403         int err;
404         int i;
405
406         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
407
408         tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size));
409         if (pkey_index > tbsz && pkey_index != 0xffff)
410                 return -EINVAL;
411
412         if (pkey_index == 0xffff)
413                 nout = tbsz;
414         else
415                 nout = 1;
416
417         out_sz += nout * MLX5_ST_SZ_BYTES(pkey);
418
419         in = kzalloc(in_sz, GFP_KERNEL);
420         out = kzalloc(out_sz, GFP_KERNEL);
421         if (!in || !out) {
422                 err = -ENOMEM;
423                 goto out;
424         }
425
426         MLX5_SET(query_hca_vport_pkey_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY);
427         if (other_vport) {
428                 if (is_group_manager) {
429                         MLX5_SET(query_hca_vport_pkey_in, in, vport_number, vf_num);
430                         MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1);
431                 } else {
432                         err = -EPERM;
433                         goto out;
434                 }
435         }
436         MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index);
437
438         if (MLX5_CAP_GEN(dev, num_ports) == 2)
439                 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num);
440
441         err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
442         if (err)
443                 goto out;
444
445         err = mlx5_cmd_status_to_err_v2(out);
446         if (err)
447                 goto out;
448
449         pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey);
450         for (i = 0; i < nout; i++, pkey++, pkarr += MLX5_ST_SZ_BYTES(pkey))
451                 *pkey = MLX5_GET_PR(pkey, pkarr, pkey);
452
453 out:
454         kfree(in);
455         kfree(out);
456         return err;
457 }
458 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey);
459
460 int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev,
461                                  u8 other_vport, u8 port_num,
462                                  u16 vf_num,
463                                  struct mlx5_hca_vport_context *rep)
464 {
465         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
466         int in[MLX5_ST_SZ_DW(query_hca_vport_context_in)];
467         int is_group_manager;
468         void *out;
469         void *ctx;
470         int err;
471
472         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
473
474         memset(in, 0, sizeof(in));
475         out = kzalloc(out_sz, GFP_KERNEL);
476         if (!out)
477                 return -ENOMEM;
478
479         MLX5_SET(query_hca_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT);
480
481         if (other_vport) {
482                 if (is_group_manager) {
483                         MLX5_SET(query_hca_vport_context_in, in, other_vport, 1);
484                         MLX5_SET(query_hca_vport_context_in, in, vport_number, vf_num);
485                 } else {
486                         err = -EPERM;
487                         goto ex;
488                 }
489         }
490
491         if (MLX5_CAP_GEN(dev, num_ports) == 2)
492                 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num);
493
494         err = mlx5_cmd_exec(dev, in, sizeof(in), out,  out_sz);
495         if (err)
496                 goto ex;
497         err = mlx5_cmd_status_to_err_v2(out);
498         if (err)
499                 goto ex;
500
501         ctx = MLX5_ADDR_OF(query_hca_vport_context_out, out, hca_vport_context);
502         rep->field_select = MLX5_GET_PR(hca_vport_context, ctx, field_select);
503         rep->sm_virt_aware = MLX5_GET_PR(hca_vport_context, ctx, sm_virt_aware);
504         rep->has_smi = MLX5_GET_PR(hca_vport_context, ctx, has_smi);
505         rep->has_raw = MLX5_GET_PR(hca_vport_context, ctx, has_raw);
506         rep->policy = MLX5_GET_PR(hca_vport_context, ctx, vport_state_policy);
507         rep->phys_state = MLX5_GET_PR(hca_vport_context, ctx,
508                                       port_physical_state);
509         rep->vport_state = MLX5_GET_PR(hca_vport_context, ctx, vport_state);
510         rep->port_physical_state = MLX5_GET_PR(hca_vport_context, ctx,
511                                                port_physical_state);
512         rep->port_guid = MLX5_GET64_PR(hca_vport_context, ctx, port_guid);
513         rep->node_guid = MLX5_GET64_PR(hca_vport_context, ctx, node_guid);
514         rep->cap_mask1 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask1);
515         rep->cap_mask1_perm = MLX5_GET_PR(hca_vport_context, ctx,
516                                           cap_mask1_field_select);
517         rep->cap_mask2 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask2);
518         rep->cap_mask2_perm = MLX5_GET_PR(hca_vport_context, ctx,
519                                           cap_mask2_field_select);
520         rep->lid = MLX5_GET_PR(hca_vport_context, ctx, lid);
521         rep->init_type_reply = MLX5_GET_PR(hca_vport_context, ctx,
522                                            init_type_reply);
523         rep->lmc = MLX5_GET_PR(hca_vport_context, ctx, lmc);
524         rep->subnet_timeout = MLX5_GET_PR(hca_vport_context, ctx,
525                                           subnet_timeout);
526         rep->sm_lid = MLX5_GET_PR(hca_vport_context, ctx, sm_lid);
527         rep->sm_sl = MLX5_GET_PR(hca_vport_context, ctx, sm_sl);
528         rep->qkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
529                                                   qkey_violation_counter);
530         rep->pkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
531                                                   pkey_violation_counter);
532         rep->grh_required = MLX5_GET_PR(hca_vport_context, ctx, grh_required);
533         rep->sys_image_guid = MLX5_GET64_PR(hca_vport_context, ctx,
534                                             system_image_guid);
535
536 ex:
537         kfree(out);
538         return err;
539 }
540 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context);
541
542 int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev,
543                                            u64 *sys_image_guid)
544 {
545         struct mlx5_hca_vport_context *rep;
546         int err;
547
548         rep = kzalloc(sizeof(*rep), GFP_KERNEL);
549         if (!rep)
550                 return -ENOMEM;
551
552         err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
553         if (!err)
554                 *sys_image_guid = rep->sys_image_guid;
555
556         kfree(rep);
557         return err;
558 }
559 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid);
560
561 int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
562                                    u64 *node_guid)
563 {
564         struct mlx5_hca_vport_context *rep;
565         int err;
566
567         rep = kzalloc(sizeof(*rep), GFP_KERNEL);
568         if (!rep)
569                 return -ENOMEM;
570
571         err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
572         if (!err)
573                 *node_guid = rep->node_guid;
574
575         kfree(rep);
576         return err;
577 }
578 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
579
580 int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
581                                  u32 vport,
582                                  int *promisc_uc,
583                                  int *promisc_mc,
584                                  int *promisc_all)
585 {
586         u32 *out;
587         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
588         int err;
589
590         out = kzalloc(outlen, GFP_KERNEL);
591         if (!out)
592                 return -ENOMEM;
593
594         err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
595         if (err)
596                 goto out;
597
598         *promisc_uc = MLX5_GET(query_nic_vport_context_out, out,
599                                nic_vport_context.promisc_uc);
600         *promisc_mc = MLX5_GET(query_nic_vport_context_out, out,
601                                nic_vport_context.promisc_mc);
602         *promisc_all = MLX5_GET(query_nic_vport_context_out, out,
603                                 nic_vport_context.promisc_all);
604
605 out:
606         kfree(out);
607         return err;
608 }
609 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
610
611 int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,
612                                   int promisc_uc,
613                                   int promisc_mc,
614                                   int promisc_all)
615 {
616         void *in;
617         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
618         int err;
619
620         in = mlx5_vzalloc(inlen);
621         if (!in) {
622                 mlx5_core_err(mdev, "failed to allocate inbox\n");
623                 return -ENOMEM;
624         }
625
626         MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
627         MLX5_SET(modify_nic_vport_context_in, in,
628                  nic_vport_context.promisc_uc, promisc_uc);
629         MLX5_SET(modify_nic_vport_context_in, in,
630                  nic_vport_context.promisc_mc, promisc_mc);
631         MLX5_SET(modify_nic_vport_context_in, in,
632                  nic_vport_context.promisc_all, promisc_all);
633
634         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
635
636         kvfree(in);
637
638         return err;
639 }
640 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc);