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