daf44cd4c566f45649b9efe1e4417b4e868c9048
[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_GPL(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_GPL(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                 ether_addr_copy(addr, &out_addr[2]);
156
157         kvfree(out);
158         return err;
159 }
160 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address);
161
162 int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev,
163                                       u16 vport, u8 *addr)
164 {
165         void *in;
166         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
167         int err;
168         void *nic_vport_ctx;
169         u8 *perm_mac;
170
171         in = mlx5_vzalloc(inlen);
172         if (!in) {
173                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
174                 return -ENOMEM;
175         }
176
177         MLX5_SET(modify_nic_vport_context_in, in,
178                  field_select.permanent_address, 1);
179         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
180
181         if (vport)
182                 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
183
184         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
185                                      in, nic_vport_context);
186         perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx,
187                                 permanent_address);
188
189         ether_addr_copy(&perm_mac[2], addr);
190
191         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
192
193         kvfree(in);
194
195         return err;
196 }
197 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_address);
198
199 int mlx5_query_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 *mtu)
200 {
201         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
202         u32 *out;
203         int err;
204
205         out = mlx5_vzalloc(outlen);
206         if (!out)
207                 return -ENOMEM;
208
209         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
210         if (!err)
211                 *mtu = MLX5_GET(query_nic_vport_context_out, out,
212                                 nic_vport_context.mtu);
213
214         kvfree(out);
215         return err;
216 }
217 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mtu);
218
219 int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu)
220 {
221         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
222         void *in;
223         int err;
224
225         in = mlx5_vzalloc(inlen);
226         if (!in)
227                 return -ENOMEM;
228
229         MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1);
230         MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, mtu);
231
232         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
233
234         kvfree(in);
235         return err;
236 }
237 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu);
238
239 int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
240                                   u32 vport,
241                                   enum mlx5_list_type list_type,
242                                   u8 addr_list[][ETH_ALEN],
243                                   int *list_size)
244 {
245         u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];
246         void *nic_vport_ctx;
247         int max_list_size;
248         int req_list_size;
249         int out_sz;
250         void *out;
251         int err;
252         int i;
253
254         req_list_size = *list_size;
255
256         max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
257                 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
258                 1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
259
260         if (req_list_size > max_list_size) {
261                 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
262                                req_list_size, max_list_size);
263                 req_list_size = max_list_size;
264         }
265
266         out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
267                         req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
268
269         memset(in, 0, sizeof(in));
270         out = kzalloc(out_sz, GFP_KERNEL);
271         if (!out)
272                 return -ENOMEM;
273
274         MLX5_SET(query_nic_vport_context_in, in, opcode,
275                  MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
276         MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
277         MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
278
279         if (vport)
280                 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
281
282         err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_sz);
283         if (err)
284                 goto out;
285
286         nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
287                                      nic_vport_context);
288         req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
289                                  allowed_list_size);
290
291         *list_size = req_list_size;
292         for (i = 0; i < req_list_size; i++) {
293                 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
294                                         nic_vport_ctx,
295                                         current_uc_mac_address[i]) + 2;
296                 ether_addr_copy(addr_list[i], mac_addr);
297         }
298 out:
299         kfree(out);
300         return err;
301 }
302 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list);
303
304 int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
305                                    enum mlx5_list_type list_type,
306                                    u8 addr_list[][ETH_ALEN],
307                                    int list_size)
308 {
309         u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
310         void *nic_vport_ctx;
311         int max_list_size;
312         int in_sz;
313         void *in;
314         int err;
315         int i;
316
317         max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
318                  1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
319                  1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
320
321         if (list_size > max_list_size)
322                 return -ENOSPC;
323
324         in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
325                 list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
326
327         memset(out, 0, sizeof(out));
328         in = kzalloc(in_sz, GFP_KERNEL);
329         if (!in)
330                 return -ENOMEM;
331
332         MLX5_SET(modify_nic_vport_context_in, in, opcode,
333                  MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
334         MLX5_SET(modify_nic_vport_context_in, in,
335                  field_select.addresses_list, 1);
336
337         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
338                                      nic_vport_context);
339
340         MLX5_SET(nic_vport_context, nic_vport_ctx,
341                  allowed_list_type, list_type);
342         MLX5_SET(nic_vport_context, nic_vport_ctx,
343                  allowed_list_size, list_size);
344
345         for (i = 0; i < list_size; i++) {
346                 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context,
347                                             nic_vport_ctx,
348                                             current_uc_mac_address[i]) + 2;
349                 ether_addr_copy(curr_mac, addr_list[i]);
350         }
351
352         err = mlx5_cmd_exec_check_status(dev, in, in_sz, out, sizeof(out));
353         kfree(in);
354         return err;
355 }
356 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
357
358 int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,
359                                u32 vport,
360                                u16 vlans[],
361                                int *size)
362 {
363         u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];
364         void *nic_vport_ctx;
365         int req_list_size;
366         int max_list_size;
367         int out_sz;
368         void *out;
369         int err;
370         int i;
371
372         req_list_size = *size;
373         max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
374         if (req_list_size > max_list_size) {
375                 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max list size\n",
376                                req_list_size, max_list_size);
377                 req_list_size = max_list_size;
378         }
379
380         out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
381                         req_list_size * MLX5_ST_SZ_BYTES(vlan_layout);
382
383         memset(in, 0, sizeof(in));
384         out = kzalloc(out_sz, GFP_KERNEL);
385         if (!out)
386                 return -ENOMEM;
387
388         MLX5_SET(query_nic_vport_context_in, in, opcode,
389                  MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
390         MLX5_SET(query_nic_vport_context_in, in, allowed_list_type,
391                  MLX5_NVPRT_LIST_TYPE_VLAN);
392         MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
393
394         if (vport)
395                 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
396
397         err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_sz);
398         if (err)
399                 goto out;
400
401         nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
402                                      nic_vport_context);
403         req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
404                                  allowed_list_size);
405
406         *size = req_list_size;
407         for (i = 0; i < req_list_size; i++) {
408                 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
409                                                nic_vport_ctx,
410                                                current_uc_mac_address[i]);
411                 vlans[i] = MLX5_GET(vlan_layout, vlan_addr, vlan);
412         }
413 out:
414         kfree(out);
415         return err;
416 }
417 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_vlans);
418
419 int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
420                                 u16 vlans[],
421                                 int list_size)
422 {
423         u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
424         void *nic_vport_ctx;
425         int max_list_size;
426         int in_sz;
427         void *in;
428         int err;
429         int i;
430
431         max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
432
433         if (list_size > max_list_size)
434                 return -ENOSPC;
435
436         in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
437                 list_size * MLX5_ST_SZ_BYTES(vlan_layout);
438
439         memset(out, 0, sizeof(out));
440         in = kzalloc(in_sz, GFP_KERNEL);
441         if (!in)
442                 return -ENOMEM;
443
444         MLX5_SET(modify_nic_vport_context_in, in, opcode,
445                  MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
446         MLX5_SET(modify_nic_vport_context_in, in,
447                  field_select.addresses_list, 1);
448
449         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
450                                      nic_vport_context);
451
452         MLX5_SET(nic_vport_context, nic_vport_ctx,
453                  allowed_list_type, MLX5_NVPRT_LIST_TYPE_VLAN);
454         MLX5_SET(nic_vport_context, nic_vport_ctx,
455                  allowed_list_size, list_size);
456
457         for (i = 0; i < list_size; i++) {
458                 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
459                                                nic_vport_ctx,
460                                                current_uc_mac_address[i]);
461                 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]);
462         }
463
464         err = mlx5_cmd_exec_check_status(dev, in, in_sz, out, sizeof(out));
465         kfree(in);
466         return err;
467 }
468 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans);
469
470 int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
471                                            u64 *system_image_guid)
472 {
473         u32 *out;
474         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
475
476         out = mlx5_vzalloc(outlen);
477         if (!out)
478                 return -ENOMEM;
479
480         mlx5_query_nic_vport_context(mdev, 0, out, outlen);
481
482         *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out,
483                                         nic_vport_context.system_image_guid);
484
485         kfree(out);
486
487         return 0;
488 }
489 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid);
490
491 int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
492 {
493         u32 *out;
494         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
495
496         out = mlx5_vzalloc(outlen);
497         if (!out)
498                 return -ENOMEM;
499
500         mlx5_query_nic_vport_context(mdev, 0, out, outlen);
501
502         *node_guid = MLX5_GET64(query_nic_vport_context_out, out,
503                                 nic_vport_context.node_guid);
504
505         kfree(out);
506
507         return 0;
508 }
509 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
510
511 int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
512                                     u32 vport, u64 node_guid)
513 {
514         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
515         void *nic_vport_context;
516         u8 *guid;
517         void *in;
518         int err;
519
520         if (!vport)
521                 return -EINVAL;
522         if (!MLX5_CAP_GEN(mdev, vport_group_manager))
523                 return -EACCES;
524         if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify))
525                 return -ENOTSUPP;
526
527         in = mlx5_vzalloc(inlen);
528         if (!in)
529                 return -ENOMEM;
530
531         MLX5_SET(modify_nic_vport_context_in, in,
532                  field_select.node_guid, 1);
533         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
534         MLX5_SET(modify_nic_vport_context_in, in, other_vport, !!vport);
535
536         nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
537                                          in, nic_vport_context);
538         guid = MLX5_ADDR_OF(nic_vport_context, nic_vport_context,
539                             node_guid);
540         MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid);
541
542         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
543
544         kvfree(in);
545
546         return err;
547 }
548
549 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
550                                         u16 *qkey_viol_cntr)
551 {
552         u32 *out;
553         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
554
555         out = mlx5_vzalloc(outlen);
556         if (!out)
557                 return -ENOMEM;
558
559         mlx5_query_nic_vport_context(mdev, 0, out, outlen);
560
561         *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out,
562                                    nic_vport_context.qkey_violation_counter);
563
564         kfree(out);
565
566         return 0;
567 }
568 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr);
569
570 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
571                              u8 port_num, u16  vf_num, u16 gid_index,
572                              union ib_gid *gid)
573 {
574         int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in);
575         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
576         int is_group_manager;
577         void *out = NULL;
578         void *in = NULL;
579         union ib_gid *tmp;
580         int tbsz;
581         int nout;
582         int err;
583
584         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
585         tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size));
586         mlx5_core_dbg(dev, "vf_num %d, index %d, gid_table_size %d\n",
587                       vf_num, gid_index, tbsz);
588
589         if (gid_index > tbsz && gid_index != 0xffff)
590                 return -EINVAL;
591
592         if (gid_index == 0xffff)
593                 nout = tbsz;
594         else
595                 nout = 1;
596
597         out_sz += nout * sizeof(*gid);
598
599         in = kzalloc(in_sz, GFP_KERNEL);
600         out = kzalloc(out_sz, GFP_KERNEL);
601         if (!in || !out) {
602                 err = -ENOMEM;
603                 goto out;
604         }
605
606         MLX5_SET(query_hca_vport_gid_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_GID);
607         if (other_vport) {
608                 if (is_group_manager) {
609                         MLX5_SET(query_hca_vport_gid_in, in, vport_number, vf_num);
610                         MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1);
611                 } else {
612                         err = -EPERM;
613                         goto out;
614                 }
615         }
616         MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index);
617
618         if (MLX5_CAP_GEN(dev, num_ports) == 2)
619                 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num);
620
621         err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
622         if (err)
623                 goto out;
624
625         err = mlx5_cmd_status_to_err_v2(out);
626         if (err)
627                 goto out;
628
629         tmp = out + MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
630         gid->global.subnet_prefix = tmp->global.subnet_prefix;
631         gid->global.interface_id = tmp->global.interface_id;
632
633 out:
634         kfree(in);
635         kfree(out);
636         return err;
637 }
638 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid);
639
640 int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
641                               u8 port_num, u16 vf_num, u16 pkey_index,
642                               u16 *pkey)
643 {
644         int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in);
645         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out);
646         int is_group_manager;
647         void *out = NULL;
648         void *in = NULL;
649         void *pkarr;
650         int nout;
651         int tbsz;
652         int err;
653         int i;
654
655         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
656
657         tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size));
658         if (pkey_index > tbsz && pkey_index != 0xffff)
659                 return -EINVAL;
660
661         if (pkey_index == 0xffff)
662                 nout = tbsz;
663         else
664                 nout = 1;
665
666         out_sz += nout * MLX5_ST_SZ_BYTES(pkey);
667
668         in = kzalloc(in_sz, GFP_KERNEL);
669         out = kzalloc(out_sz, GFP_KERNEL);
670         if (!in || !out) {
671                 err = -ENOMEM;
672                 goto out;
673         }
674
675         MLX5_SET(query_hca_vport_pkey_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY);
676         if (other_vport) {
677                 if (is_group_manager) {
678                         MLX5_SET(query_hca_vport_pkey_in, in, vport_number, vf_num);
679                         MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1);
680                 } else {
681                         err = -EPERM;
682                         goto out;
683                 }
684         }
685         MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index);
686
687         if (MLX5_CAP_GEN(dev, num_ports) == 2)
688                 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num);
689
690         err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
691         if (err)
692                 goto out;
693
694         err = mlx5_cmd_status_to_err_v2(out);
695         if (err)
696                 goto out;
697
698         pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey);
699         for (i = 0; i < nout; i++, pkey++, pkarr += MLX5_ST_SZ_BYTES(pkey))
700                 *pkey = MLX5_GET_PR(pkey, pkarr, pkey);
701
702 out:
703         kfree(in);
704         kfree(out);
705         return err;
706 }
707 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey);
708
709 int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev,
710                                  u8 other_vport, u8 port_num,
711                                  u16 vf_num,
712                                  struct mlx5_hca_vport_context *rep)
713 {
714         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
715         int in[MLX5_ST_SZ_DW(query_hca_vport_context_in)];
716         int is_group_manager;
717         void *out;
718         void *ctx;
719         int err;
720
721         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
722
723         memset(in, 0, sizeof(in));
724         out = kzalloc(out_sz, GFP_KERNEL);
725         if (!out)
726                 return -ENOMEM;
727
728         MLX5_SET(query_hca_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT);
729
730         if (other_vport) {
731                 if (is_group_manager) {
732                         MLX5_SET(query_hca_vport_context_in, in, other_vport, 1);
733                         MLX5_SET(query_hca_vport_context_in, in, vport_number, vf_num);
734                 } else {
735                         err = -EPERM;
736                         goto ex;
737                 }
738         }
739
740         if (MLX5_CAP_GEN(dev, num_ports) == 2)
741                 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num);
742
743         err = mlx5_cmd_exec(dev, in, sizeof(in), out,  out_sz);
744         if (err)
745                 goto ex;
746         err = mlx5_cmd_status_to_err_v2(out);
747         if (err)
748                 goto ex;
749
750         ctx = MLX5_ADDR_OF(query_hca_vport_context_out, out, hca_vport_context);
751         rep->field_select = MLX5_GET_PR(hca_vport_context, ctx, field_select);
752         rep->sm_virt_aware = MLX5_GET_PR(hca_vport_context, ctx, sm_virt_aware);
753         rep->has_smi = MLX5_GET_PR(hca_vport_context, ctx, has_smi);
754         rep->has_raw = MLX5_GET_PR(hca_vport_context, ctx, has_raw);
755         rep->policy = MLX5_GET_PR(hca_vport_context, ctx, vport_state_policy);
756         rep->phys_state = MLX5_GET_PR(hca_vport_context, ctx,
757                                       port_physical_state);
758         rep->vport_state = MLX5_GET_PR(hca_vport_context, ctx, vport_state);
759         rep->port_physical_state = MLX5_GET_PR(hca_vport_context, ctx,
760                                                port_physical_state);
761         rep->port_guid = MLX5_GET64_PR(hca_vport_context, ctx, port_guid);
762         rep->node_guid = MLX5_GET64_PR(hca_vport_context, ctx, node_guid);
763         rep->cap_mask1 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask1);
764         rep->cap_mask1_perm = MLX5_GET_PR(hca_vport_context, ctx,
765                                           cap_mask1_field_select);
766         rep->cap_mask2 = MLX5_GET_PR(hca_vport_context, ctx, cap_mask2);
767         rep->cap_mask2_perm = MLX5_GET_PR(hca_vport_context, ctx,
768                                           cap_mask2_field_select);
769         rep->lid = MLX5_GET_PR(hca_vport_context, ctx, lid);
770         rep->init_type_reply = MLX5_GET_PR(hca_vport_context, ctx,
771                                            init_type_reply);
772         rep->lmc = MLX5_GET_PR(hca_vport_context, ctx, lmc);
773         rep->subnet_timeout = MLX5_GET_PR(hca_vport_context, ctx,
774                                           subnet_timeout);
775         rep->sm_lid = MLX5_GET_PR(hca_vport_context, ctx, sm_lid);
776         rep->sm_sl = MLX5_GET_PR(hca_vport_context, ctx, sm_sl);
777         rep->qkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
778                                                   qkey_violation_counter);
779         rep->pkey_violation_counter = MLX5_GET_PR(hca_vport_context, ctx,
780                                                   pkey_violation_counter);
781         rep->grh_required = MLX5_GET_PR(hca_vport_context, ctx, grh_required);
782         rep->sys_image_guid = MLX5_GET64_PR(hca_vport_context, ctx,
783                                             system_image_guid);
784
785 ex:
786         kfree(out);
787         return err;
788 }
789 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context);
790
791 int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev,
792                                            u64 *sys_image_guid)
793 {
794         struct mlx5_hca_vport_context *rep;
795         int err;
796
797         rep = kzalloc(sizeof(*rep), GFP_KERNEL);
798         if (!rep)
799                 return -ENOMEM;
800
801         err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
802         if (!err)
803                 *sys_image_guid = rep->sys_image_guid;
804
805         kfree(rep);
806         return err;
807 }
808 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid);
809
810 int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
811                                    u64 *node_guid)
812 {
813         struct mlx5_hca_vport_context *rep;
814         int err;
815
816         rep = kzalloc(sizeof(*rep), GFP_KERNEL);
817         if (!rep)
818                 return -ENOMEM;
819
820         err = mlx5_query_hca_vport_context(dev, 0, 1, 0, rep);
821         if (!err)
822                 *node_guid = rep->node_guid;
823
824         kfree(rep);
825         return err;
826 }
827 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
828
829 int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
830                                  u32 vport,
831                                  int *promisc_uc,
832                                  int *promisc_mc,
833                                  int *promisc_all)
834 {
835         u32 *out;
836         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
837         int err;
838
839         out = kzalloc(outlen, GFP_KERNEL);
840         if (!out)
841                 return -ENOMEM;
842
843         err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
844         if (err)
845                 goto out;
846
847         *promisc_uc = MLX5_GET(query_nic_vport_context_out, out,
848                                nic_vport_context.promisc_uc);
849         *promisc_mc = MLX5_GET(query_nic_vport_context_out, out,
850                                nic_vport_context.promisc_mc);
851         *promisc_all = MLX5_GET(query_nic_vport_context_out, out,
852                                 nic_vport_context.promisc_all);
853
854 out:
855         kfree(out);
856         return err;
857 }
858 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
859
860 int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,
861                                   int promisc_uc,
862                                   int promisc_mc,
863                                   int promisc_all)
864 {
865         void *in;
866         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
867         int err;
868
869         in = mlx5_vzalloc(inlen);
870         if (!in) {
871                 mlx5_core_err(mdev, "failed to allocate inbox\n");
872                 return -ENOMEM;
873         }
874
875         MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
876         MLX5_SET(modify_nic_vport_context_in, in,
877                  nic_vport_context.promisc_uc, promisc_uc);
878         MLX5_SET(modify_nic_vport_context_in, in,
879                  nic_vport_context.promisc_mc, promisc_mc);
880         MLX5_SET(modify_nic_vport_context_in, in,
881                  nic_vport_context.promisc_all, promisc_all);
882
883         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
884
885         kvfree(in);
886
887         return err;
888 }
889 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc);
890
891 enum mlx5_vport_roce_state {
892         MLX5_VPORT_ROCE_DISABLED = 0,
893         MLX5_VPORT_ROCE_ENABLED  = 1,
894 };
895
896 static int mlx5_nic_vport_update_roce_state(struct mlx5_core_dev *mdev,
897                                             enum mlx5_vport_roce_state state)
898 {
899         void *in;
900         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
901         int err;
902
903         in = mlx5_vzalloc(inlen);
904         if (!in) {
905                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
906                 return -ENOMEM;
907         }
908
909         MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1);
910         MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en,
911                  state);
912
913         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
914
915         kvfree(in);
916
917         return err;
918 }
919
920 int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev)
921 {
922         return mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED);
923 }
924 EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce);
925
926 int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev)
927 {
928         return mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED);
929 }
930 EXPORT_SYMBOL_GPL(mlx5_nic_vport_disable_roce);
931
932 int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport,
933                                   int vf, u8 port_num, void *out,
934                                   size_t out_sz)
935 {
936         int     in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in);
937         int     is_group_manager;
938         void   *in;
939         int     err;
940
941         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
942         in = mlx5_vzalloc(in_sz);
943         if (!in) {
944                 err = -ENOMEM;
945                 return err;
946         }
947
948         MLX5_SET(query_vport_counter_in, in, opcode,
949                  MLX5_CMD_OP_QUERY_VPORT_COUNTER);
950         if (other_vport) {
951                 if (is_group_manager) {
952                         MLX5_SET(query_vport_counter_in, in, other_vport, 1);
953                         MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1);
954                 } else {
955                         err = -EPERM;
956                         goto free;
957                 }
958         }
959         if (MLX5_CAP_GEN(dev, num_ports) == 2)
960                 MLX5_SET(query_vport_counter_in, in, port_num, port_num);
961
962         err = mlx5_cmd_exec(dev, in, in_sz, out,  out_sz);
963         if (err)
964                 goto free;
965         err = mlx5_cmd_status_to_err_v2(out);
966
967 free:
968         kvfree(in);
969         return err;
970 }
971 EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter);
972
973 int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev,
974                                        u8 other_vport, u8 port_num,
975                                        int vf,
976                                        struct mlx5_hca_vport_context *req)
977 {
978         int in_sz = MLX5_ST_SZ_BYTES(modify_hca_vport_context_in);
979         u8 out[MLX5_ST_SZ_BYTES(modify_hca_vport_context_out)];
980         int is_group_manager;
981         void *in;
982         int err;
983         void *ctx;
984
985         mlx5_core_dbg(dev, "vf %d\n", vf);
986         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
987         in = kzalloc(in_sz, GFP_KERNEL);
988         if (!in)
989                 return -ENOMEM;
990
991         memset(out, 0, sizeof(out));
992         MLX5_SET(modify_hca_vport_context_in, in, opcode, MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT);
993         if (other_vport) {
994                 if (is_group_manager) {
995                         MLX5_SET(modify_hca_vport_context_in, in, other_vport, 1);
996                         MLX5_SET(modify_hca_vport_context_in, in, vport_number, vf);
997                 } else {
998                         err = -EPERM;
999                         goto ex;
1000                 }
1001         }
1002
1003         if (MLX5_CAP_GEN(dev, num_ports) > 1)
1004                 MLX5_SET(modify_hca_vport_context_in, in, port_num, port_num);
1005
1006         ctx = MLX5_ADDR_OF(modify_hca_vport_context_in, in, hca_vport_context);
1007         MLX5_SET(hca_vport_context, ctx, field_select, req->field_select);
1008         MLX5_SET(hca_vport_context, ctx, sm_virt_aware, req->sm_virt_aware);
1009         MLX5_SET(hca_vport_context, ctx, has_smi, req->has_smi);
1010         MLX5_SET(hca_vport_context, ctx, has_raw, req->has_raw);
1011         MLX5_SET(hca_vport_context, ctx, vport_state_policy, req->policy);
1012         MLX5_SET(hca_vport_context, ctx, port_physical_state, req->phys_state);
1013         MLX5_SET(hca_vport_context, ctx, vport_state, req->vport_state);
1014         MLX5_SET64(hca_vport_context, ctx, port_guid, req->port_guid);
1015         MLX5_SET64(hca_vport_context, ctx, node_guid, req->node_guid);
1016         MLX5_SET(hca_vport_context, ctx, cap_mask1, req->cap_mask1);
1017         MLX5_SET(hca_vport_context, ctx, cap_mask1_field_select, req->cap_mask1_perm);
1018         MLX5_SET(hca_vport_context, ctx, cap_mask2, req->cap_mask2);
1019         MLX5_SET(hca_vport_context, ctx, cap_mask2_field_select, req->cap_mask2_perm);
1020         MLX5_SET(hca_vport_context, ctx, lid, req->lid);
1021         MLX5_SET(hca_vport_context, ctx, init_type_reply, req->init_type_reply);
1022         MLX5_SET(hca_vport_context, ctx, lmc, req->lmc);
1023         MLX5_SET(hca_vport_context, ctx, subnet_timeout, req->subnet_timeout);
1024         MLX5_SET(hca_vport_context, ctx, sm_lid, req->sm_lid);
1025         MLX5_SET(hca_vport_context, ctx, sm_sl, req->sm_sl);
1026         MLX5_SET(hca_vport_context, ctx, qkey_violation_counter, req->qkey_violation_counter);
1027         MLX5_SET(hca_vport_context, ctx, pkey_violation_counter, req->pkey_violation_counter);
1028         err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
1029         if (err)
1030                 goto ex;
1031
1032         err = mlx5_cmd_status_to_err_v2(out);
1033
1034 ex:
1035         kfree(in);
1036         return err;
1037 }
1038 EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context);