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