]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mlx5/mlx5_core/mlx5_vport.c
MFV r330973: 9164 assert: newds == os->os_dsl_dataset
[FreeBSD/FreeBSD.git] / sys / dev / mlx5 / mlx5_core / mlx5_vport.c
1 /*-
2  * Copyright (c) 2013-2017, Mellanox Technologies, Ltd.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27
28 #include <linux/etherdevice.h>
29 #include <dev/mlx5/driver.h>
30 #include <dev/mlx5/vport.h>
31 #include "mlx5_core.h"
32
33 static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in,
34                                          int inlen);
35
36 static int _mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod,
37                                    u16 vport, u32 *out, int outlen)
38 {
39         int err;
40         u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {0};
41
42         MLX5_SET(query_vport_state_in, in, opcode,
43                  MLX5_CMD_OP_QUERY_VPORT_STATE);
44         MLX5_SET(query_vport_state_in, in, op_mod, opmod);
45         MLX5_SET(query_vport_state_in, in, vport_number, vport);
46         if (vport)
47                 MLX5_SET(query_vport_state_in, in, other_vport, 1);
48
49         err = mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
50         if (err)
51                 mlx5_core_warn(mdev, "MLX5_CMD_OP_QUERY_VPORT_STATE failed\n");
52
53         return err;
54 }
55
56 u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
57 {
58         u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0};
59
60         _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out));
61
62         return MLX5_GET(query_vport_state_out, out, state);
63 }
64 EXPORT_SYMBOL_GPL(mlx5_query_vport_state);
65
66 u8 mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
67 {
68         u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0};
69
70         _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out));
71
72         return MLX5_GET(query_vport_state_out, out, admin_state);
73 }
74 EXPORT_SYMBOL(mlx5_query_vport_admin_state);
75
76 int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
77                                   u16 vport, u8 state)
78 {
79         u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {0};
80         u32 out[MLX5_ST_SZ_DW(modify_vport_state_out)] = {0};
81         int err;
82
83         MLX5_SET(modify_vport_state_in, in, opcode,
84                  MLX5_CMD_OP_MODIFY_VPORT_STATE);
85         MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
86         MLX5_SET(modify_vport_state_in, in, vport_number, vport);
87
88         if (vport)
89                 MLX5_SET(modify_vport_state_in, in, other_vport, 1);
90
91         MLX5_SET(modify_vport_state_in, in, admin_state, state);
92
93         err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
94         if (err)
95                 mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_VPORT_STATE failed\n");
96
97         return err;
98 }
99 EXPORT_SYMBOL(mlx5_modify_vport_admin_state);
100
101 static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport,
102                                         u32 *out, int outlen)
103 {
104         u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
105
106         MLX5_SET(query_nic_vport_context_in, in, opcode,
107                  MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
108
109         MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
110         if (vport)
111                 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
112
113         return mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
114 }
115
116 static u32 mlx5_vport_max_q_counter_allocator(struct mlx5_core_dev *mdev,
117                                               int client_id)
118 {
119         switch (client_id) {
120         case MLX5_INTERFACE_PROTOCOL_IB:
121                 return (MLX5_CAP_GEN(mdev, max_qp_cnt) -
122                         MLX5_QCOUNTER_SETS_NETDEV);
123         case MLX5_INTERFACE_PROTOCOL_ETH:
124                 return MLX5_QCOUNTER_SETS_NETDEV;
125         default:
126                 mlx5_core_warn(mdev, "Unknown Client: %d\n", client_id);
127                 return 0;
128         }
129 }
130
131 int mlx5_vport_alloc_q_counter(struct mlx5_core_dev *mdev,
132                                int client_id, u16 *counter_set_id)
133 {
134         u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {0};
135         u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {0};
136         int err;
137
138         if (mdev->num_q_counter_allocated[client_id] >
139             mlx5_vport_max_q_counter_allocator(mdev, client_id))
140                 return -EINVAL;
141
142         MLX5_SET(alloc_q_counter_in, in, opcode,
143                  MLX5_CMD_OP_ALLOC_Q_COUNTER);
144
145         err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
146
147         if (!err)
148                 *counter_set_id = MLX5_GET(alloc_q_counter_out, out,
149                                            counter_set_id);
150
151         mdev->num_q_counter_allocated[client_id]++;
152
153         return err;
154 }
155
156 int mlx5_vport_dealloc_q_counter(struct mlx5_core_dev *mdev,
157                                  int client_id, u16 counter_set_id)
158 {
159         u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {0};
160         u32 out[MLX5_ST_SZ_DW(dealloc_q_counter_out)] = {0};
161         int err;
162
163         if (mdev->num_q_counter_allocated[client_id] <= 0)
164                 return -EINVAL;
165
166         MLX5_SET(dealloc_q_counter_in, in, opcode,
167                  MLX5_CMD_OP_DEALLOC_Q_COUNTER);
168         MLX5_SET(dealloc_q_counter_in, in, counter_set_id,
169                  counter_set_id);
170
171         err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
172
173         mdev->num_q_counter_allocated[client_id]--;
174
175         return err;
176 }
177
178 int mlx5_vport_query_q_counter(struct mlx5_core_dev *mdev,
179                                       u16 counter_set_id,
180                                       int reset,
181                                       void *out,
182                                       int out_size)
183 {
184         u32 in[MLX5_ST_SZ_DW(query_q_counter_in)] = {0};
185
186         MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER);
187         MLX5_SET(query_q_counter_in, in, clear, reset);
188         MLX5_SET(query_q_counter_in, in, counter_set_id, counter_set_id);
189
190         return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
191 }
192
193 int mlx5_vport_query_out_of_rx_buffer(struct mlx5_core_dev *mdev,
194                                       u16 counter_set_id,
195                                       u32 *out_of_rx_buffer)
196 {
197         u32 out[MLX5_ST_SZ_DW(query_q_counter_out)] = {0};
198         int err;
199
200         err = mlx5_vport_query_q_counter(mdev, counter_set_id, 0, out,
201                                          sizeof(out));
202
203         if (err)
204                 return err;
205
206         *out_of_rx_buffer = MLX5_GET(query_q_counter_out, out,
207                                      out_of_buffer);
208         return err;
209 }
210
211 int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev,
212                                      u16 vport, u8 *addr)
213 {
214         u32 *out;
215         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
216         u8 *out_addr;
217         int err;
218
219         out = mlx5_vzalloc(outlen);
220         if (!out)
221                 return -ENOMEM;
222
223         out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out,
224                                 nic_vport_context.permanent_address);
225
226         err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
227         if (err)
228                 goto out;
229
230         ether_addr_copy(addr, &out_addr[2]);
231
232 out:
233         kvfree(out);
234         return err;
235 }
236 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address);
237
238 int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev,
239                                       u16 vport, u8 *addr)
240 {
241         void *in;
242         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
243         int err;
244         void *nic_vport_ctx;
245         u8 *perm_mac;
246
247         in = mlx5_vzalloc(inlen);
248         if (!in) {
249                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
250                 return -ENOMEM;
251         }
252
253         MLX5_SET(modify_nic_vport_context_in, in,
254                  field_select.permanent_address, 1);
255         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
256
257         if (vport)
258                 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
259
260         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
261                                      in, nic_vport_context);
262         perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx,
263                                 permanent_address);
264
265         ether_addr_copy(&perm_mac[2], addr);
266
267         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
268
269         kvfree(in);
270
271         return err;
272 }
273 EXPORT_SYMBOL(mlx5_modify_nic_vport_mac_address);
274
275 int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
276                                            u64 *system_image_guid)
277 {
278         u32 *out;
279         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
280         int err;
281
282         out = mlx5_vzalloc(outlen);
283         if (!out)
284                 return -ENOMEM;
285
286         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
287         if (err)
288                 goto out;
289
290         *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out,
291                                         nic_vport_context.system_image_guid);
292 out:
293         kvfree(out);
294         return err;
295 }
296 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid);
297
298 int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
299 {
300         u32 *out;
301         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
302         int err;
303
304         out = mlx5_vzalloc(outlen);
305         if (!out)
306                 return -ENOMEM;
307
308         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
309         if (err)
310                 goto out;
311
312         *node_guid = MLX5_GET64(query_nic_vport_context_out, out,
313                                 nic_vport_context.node_guid);
314
315 out:
316         kvfree(out);
317         return err;
318 }
319 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
320
321 static int mlx5_query_nic_vport_port_guid(struct mlx5_core_dev *mdev,
322                                           u64 *port_guid)
323 {
324         u32 *out;
325         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
326         int err;
327
328         out = mlx5_vzalloc(outlen);
329         if (!out)
330                 return -ENOMEM;
331
332         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
333         if (err)
334                 goto out;
335
336         *port_guid = MLX5_GET64(query_nic_vport_context_out, out,
337                                 nic_vport_context.port_guid);
338
339 out:
340         kvfree(out);
341         return err;
342 }
343
344 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
345                                         u16 *qkey_viol_cntr)
346 {
347         u32 *out;
348         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
349         int err;
350
351         out = mlx5_vzalloc(outlen);
352         if (!out)
353                 return -ENOMEM;
354
355         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
356         if (err)
357                 goto out;
358
359         *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out,
360                                 nic_vport_context.qkey_violation_counter);
361
362 out:
363         kvfree(out);
364         return err;
365 }
366 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr);
367
368 static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in,
369                                          int inlen)
370 {
371         u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0};
372
373         MLX5_SET(modify_nic_vport_context_in, in, opcode,
374                  MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
375
376         return mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
377 }
378
379 static int mlx5_nic_vport_enable_disable_roce(struct mlx5_core_dev *mdev,
380                                               int enable_disable)
381 {
382         void *in;
383         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
384         int err;
385
386         in = mlx5_vzalloc(inlen);
387         if (!in) {
388                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
389                 return -ENOMEM;
390         }
391
392         MLX5_SET(modify_nic_vport_context_in, in, field_select.roce_en, 1);
393         MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.roce_en,
394                  enable_disable);
395
396         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
397
398         kvfree(in);
399
400         return err;
401 }
402
403 int mlx5_set_nic_vport_current_mac(struct mlx5_core_dev *mdev, int vport,
404                                    bool other_vport, u8 *addr)
405 {
406         void *in;
407         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)
408                   + MLX5_ST_SZ_BYTES(mac_address_layout);
409         u8  *mac_layout;
410         u8  *mac_ptr;
411         int err;
412
413         in = mlx5_vzalloc(inlen);
414         if (!in) {
415                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
416                 return -ENOMEM;
417         }
418
419         MLX5_SET(modify_nic_vport_context_in, in,
420                  opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
421         MLX5_SET(modify_nic_vport_context_in, in,
422                  vport_number, vport);
423         MLX5_SET(modify_nic_vport_context_in, in,
424                  other_vport, other_vport);
425         MLX5_SET(modify_nic_vport_context_in, in,
426                  field_select.addresses_list, 1);
427         MLX5_SET(modify_nic_vport_context_in, in,
428                  nic_vport_context.allowed_list_type,
429                  MLX5_NIC_VPORT_LIST_TYPE_UC);
430         MLX5_SET(modify_nic_vport_context_in, in,
431                  nic_vport_context.allowed_list_size, 1);
432
433         mac_layout = (u8 *)MLX5_ADDR_OF(modify_nic_vport_context_in, in,
434                 nic_vport_context.current_uc_mac_address);
435         mac_ptr = (u8 *)MLX5_ADDR_OF(mac_address_layout, mac_layout,
436                 mac_addr_47_32);
437         ether_addr_copy(mac_ptr, addr);
438
439         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
440
441         kvfree(in);
442
443         return err;
444 }
445 EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_current_mac);
446
447 int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
448                                     u32 vport, u64 node_guid)
449 {
450         void *in;
451         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
452         int err;
453         void *nic_vport_context;
454
455         if (!vport)
456                 return -EINVAL;
457         if (!MLX5_CAP_GEN(mdev, vport_group_manager))
458                 return -EPERM;
459         if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify))
460                 return -ENOTSUPP;
461
462         in = mlx5_vzalloc(inlen);
463         if (!in) {
464                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
465                 return -ENOMEM;
466         }
467
468         MLX5_SET(modify_nic_vport_context_in, in,
469                  field_select.node_guid, 1);
470         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
471
472         MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
473
474         nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
475                                          in, nic_vport_context);
476         MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid);
477
478         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
479
480         kvfree(in);
481
482         return err;
483 }
484 EXPORT_SYMBOL(mlx5_modify_nic_vport_node_guid);
485
486 int mlx5_modify_nic_vport_port_guid(struct mlx5_core_dev *mdev,
487                                     u32 vport, u64 port_guid)
488 {
489         void *in;
490         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
491         int err;
492         void *nic_vport_context;
493
494         if (!vport)
495                 return -EINVAL;
496         if (!MLX5_CAP_GEN(mdev, vport_group_manager))
497                 return -EPERM;
498         if (!MLX5_CAP_ESW(mdev, nic_vport_port_guid_modify))
499                 return -ENOTSUPP;
500
501         in = mlx5_vzalloc(inlen);
502         if (!in) {
503                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
504                 return -ENOMEM;
505         }
506
507         MLX5_SET(modify_nic_vport_context_in, in,
508                  field_select.port_guid, 1);
509         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
510
511         MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
512
513         nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
514                                          in, nic_vport_context);
515         MLX5_SET64(nic_vport_context, nic_vport_context, port_guid, port_guid);
516
517         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
518
519         kvfree(in);
520
521         return err;
522 }
523 EXPORT_SYMBOL(mlx5_modify_nic_vport_port_guid);
524
525 int mlx5_set_nic_vport_vlan_list(struct mlx5_core_dev *dev, u16 vport,
526                                  u16 *vlan_list, int list_len)
527 {
528         void *in, *ctx;
529         int i, err;
530         int  inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)
531                 + MLX5_ST_SZ_BYTES(vlan_layout) * (int)list_len;
532
533         int max_list_size = 1 << MLX5_CAP_GEN_MAX(dev, log_max_vlan_list);
534
535         if (list_len > max_list_size) {
536                 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
537                                list_len, max_list_size);
538                 return -ENOSPC;
539         }
540
541         in = mlx5_vzalloc(inlen);
542         if (!in) {
543                 mlx5_core_warn(dev, "failed to allocate inbox\n");
544                 return -ENOMEM;
545         }
546
547         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
548         if (vport)
549                 MLX5_SET(modify_nic_vport_context_in, in,
550                          other_vport, 1);
551         MLX5_SET(modify_nic_vport_context_in, in,
552                  field_select.addresses_list, 1);
553
554         ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context);
555
556         MLX5_SET(nic_vport_context, ctx, allowed_list_type,
557                  MLX5_NIC_VPORT_LIST_TYPE_VLAN);
558         MLX5_SET(nic_vport_context, ctx, allowed_list_size, list_len);
559
560         for (i = 0; i < list_len; i++) {
561                 u8 *vlan_lout = MLX5_ADDR_OF(nic_vport_context, ctx,
562                                          current_uc_mac_address[i]);
563                 MLX5_SET(vlan_layout, vlan_lout, vlan, vlan_list[i]);
564         }
565
566         err = mlx5_modify_nic_vport_context(dev, in, inlen);
567
568         kvfree(in);
569         return err;
570 }
571 EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_vlan_list);
572
573 int mlx5_set_nic_vport_mc_list(struct mlx5_core_dev *mdev, int vport,
574                                u64 *addr_list, size_t addr_list_len)
575 {
576         void *in, *ctx;
577         int  inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)
578                   + MLX5_ST_SZ_BYTES(mac_address_layout) * (int)addr_list_len;
579         int err;
580         size_t i;
581         int max_list_sz = 1 << MLX5_CAP_GEN_MAX(mdev, log_max_current_mc_list);
582
583         if ((int)addr_list_len > max_list_sz) {
584                 mlx5_core_warn(mdev, "Requested list size (%d) > (%d) max_list_size\n",
585                                (int)addr_list_len, max_list_sz);
586                 return -ENOSPC;
587         }
588
589         in = mlx5_vzalloc(inlen);
590         if (!in) {
591                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
592                 return -ENOMEM;
593         }
594
595         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
596         if (vport)
597                 MLX5_SET(modify_nic_vport_context_in, in,
598                          other_vport, 1);
599         MLX5_SET(modify_nic_vport_context_in, in,
600                  field_select.addresses_list, 1);
601
602         ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context);
603
604         MLX5_SET(nic_vport_context, ctx, allowed_list_type,
605                  MLX5_NIC_VPORT_LIST_TYPE_MC);
606         MLX5_SET(nic_vport_context, ctx, allowed_list_size, addr_list_len);
607
608         for (i = 0; i < addr_list_len; i++) {
609                 u8 *mac_lout = (u8 *)MLX5_ADDR_OF(nic_vport_context, ctx,
610                                                   current_uc_mac_address[i]);
611                 u8 *mac_ptr = (u8 *)MLX5_ADDR_OF(mac_address_layout, mac_lout,
612                                                  mac_addr_47_32);
613                 ether_addr_copy(mac_ptr, (u8 *)&addr_list[i]);
614         }
615
616         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
617
618         kvfree(in);
619
620         return err;
621 }
622 EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_mc_list);
623
624 int mlx5_set_nic_vport_promisc(struct mlx5_core_dev *mdev, int vport,
625                                bool promisc_mc, bool promisc_uc,
626                                bool promisc_all)
627 {
628         u8  in[MLX5_ST_SZ_BYTES(modify_nic_vport_context_in)];
629         u8 *ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
630                                nic_vport_context);
631
632         memset(in, 0, MLX5_ST_SZ_BYTES(modify_nic_vport_context_in));
633
634         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
635         if (vport)
636                 MLX5_SET(modify_nic_vport_context_in, in,
637                          other_vport, 1);
638         MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
639         if (promisc_mc)
640                 MLX5_SET(nic_vport_context, ctx, promisc_mc, 1);
641         if (promisc_uc)
642                 MLX5_SET(nic_vport_context, ctx, promisc_uc, 1);
643         if (promisc_all)
644                 MLX5_SET(nic_vport_context, ctx, promisc_all, 1);
645
646         return mlx5_modify_nic_vport_context(mdev, in, sizeof(in));
647 }
648 EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_promisc);
649
650 int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
651                                   u16 vport,
652                                   enum mlx5_list_type list_type,
653                                   u8 addr_list[][ETH_ALEN],
654                                   int *list_size)
655 {
656         u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
657         void *nic_vport_ctx;
658         int max_list_size;
659         int req_list_size;
660         int out_sz;
661         void *out;
662         int err;
663         int i;
664
665         req_list_size = *list_size;
666
667         max_list_size = (list_type == MLX5_NIC_VPORT_LIST_TYPE_UC) ?
668                         1 << MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list) :
669                         1 << MLX5_CAP_GEN_MAX(dev, log_max_current_mc_list);
670
671         if (req_list_size > max_list_size) {
672                 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
673                                req_list_size, max_list_size);
674                 req_list_size = max_list_size;
675         }
676
677         out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
678                  req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
679
680         out = kzalloc(out_sz, GFP_KERNEL);
681         if (!out)
682                 return -ENOMEM;
683
684         MLX5_SET(query_nic_vport_context_in, in, opcode,
685                  MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
686         MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
687         MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
688
689         if (vport)
690                 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
691
692         err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
693         if (err)
694                 goto out;
695
696         nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
697                                      nic_vport_context);
698         req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
699                                  allowed_list_size);
700
701         *list_size = req_list_size;
702         for (i = 0; i < req_list_size; i++) {
703                 u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
704                                         nic_vport_ctx,
705                                         current_uc_mac_address[i]) + 2;
706                 ether_addr_copy(addr_list[i], mac_addr);
707         }
708 out:
709         kfree(out);
710         return err;
711 }
712 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list);
713
714 int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
715                                    enum mlx5_list_type list_type,
716                                    u8 addr_list[][ETH_ALEN],
717                                    int list_size)
718 {
719         u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0};
720         void *nic_vport_ctx;
721         int max_list_size;
722         int in_sz;
723         void *in;
724         int err;
725         int i;
726
727         max_list_size = list_type == MLX5_NIC_VPORT_LIST_TYPE_UC ?
728                  1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
729                  1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
730
731         if (list_size > max_list_size)
732                 return -ENOSPC;
733
734         in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
735                 list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
736
737         in = kzalloc(in_sz, GFP_KERNEL);
738         if (!in)
739                 return -ENOMEM;
740
741         MLX5_SET(modify_nic_vport_context_in, in, opcode,
742                  MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
743         MLX5_SET(modify_nic_vport_context_in, in,
744                  field_select.addresses_list, 1);
745
746         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
747                                      nic_vport_context);
748
749         MLX5_SET(nic_vport_context, nic_vport_ctx,
750                  allowed_list_type, list_type);
751         MLX5_SET(nic_vport_context, nic_vport_ctx,
752                  allowed_list_size, list_size);
753
754         for (i = 0; i < list_size; i++) {
755                 u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context,
756                                             nic_vport_ctx,
757                                             current_uc_mac_address[i]) + 2;
758                 ether_addr_copy(curr_mac, addr_list[i]);
759         }
760
761         err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
762         kfree(in);
763         return err;
764 }
765 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
766
767 int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,
768                                u16 vport,
769                                u16 vlans[],
770                                int *size)
771 {
772         u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
773         void *nic_vport_ctx;
774         int req_list_size;
775         int max_list_size;
776         int out_sz;
777         void *out;
778         int err;
779         int i;
780
781         req_list_size = *size;
782         max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
783         if (req_list_size > max_list_size) {
784                 mlx5_core_warn(dev, "Requested list size (%d) > (%d) max list size\n",
785                                req_list_size, max_list_size);
786                 req_list_size = max_list_size;
787         }
788
789         out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
790                  req_list_size * MLX5_ST_SZ_BYTES(vlan_layout);
791
792         out = kzalloc(out_sz, GFP_KERNEL);
793         if (!out)
794                 return -ENOMEM;
795
796         MLX5_SET(query_nic_vport_context_in, in, opcode,
797                  MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
798         MLX5_SET(query_nic_vport_context_in, in, allowed_list_type,
799                  MLX5_NIC_VPORT_CONTEXT_ALLOWED_LIST_TYPE_VLAN_LIST);
800         MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
801
802         if (vport)
803                 MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
804
805         err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
806         if (err)
807                 goto out;
808
809         nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
810                                      nic_vport_context);
811         req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
812                                  allowed_list_size);
813
814         *size = req_list_size;
815         for (i = 0; i < req_list_size; i++) {
816                 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
817                                                nic_vport_ctx,
818                                          current_uc_mac_address[i]);
819                 vlans[i] = MLX5_GET(vlan_layout, vlan_addr, vlan);
820         }
821 out:
822         kfree(out);
823         return err;
824 }
825 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_vlans);
826
827 int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
828                                 u16 vlans[],
829                                 int list_size)
830 {
831         u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)] = {0};
832         void *nic_vport_ctx;
833         int max_list_size;
834         int in_sz;
835         void *in;
836         int err;
837         int i;
838
839         max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
840
841         if (list_size > max_list_size)
842                 return -ENOSPC;
843
844         in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
845                 list_size * MLX5_ST_SZ_BYTES(vlan_layout);
846
847         in = kzalloc(in_sz, GFP_KERNEL);
848         if (!in)
849                 return -ENOMEM;
850
851         MLX5_SET(modify_nic_vport_context_in, in, opcode,
852                  MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
853         MLX5_SET(modify_nic_vport_context_in, in,
854                  field_select.addresses_list, 1);
855
856         nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
857                                      nic_vport_context);
858
859         MLX5_SET(nic_vport_context, nic_vport_ctx,
860                  allowed_list_type, MLX5_NIC_VPORT_LIST_TYPE_VLAN);
861         MLX5_SET(nic_vport_context, nic_vport_ctx,
862                  allowed_list_size, list_size);
863
864         for (i = 0; i < list_size; i++) {
865                 void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
866                                                nic_vport_ctx,
867                                                current_uc_mac_address[i]);
868                 MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]);
869         }
870
871         err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
872         kfree(in);
873         return err;
874 }
875 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans);
876
877 int mlx5_query_nic_vport_roce_en(struct mlx5_core_dev *mdev, u8 *enable)
878 {
879         u32 *out;
880         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
881         int err;
882
883         out = kzalloc(outlen, GFP_KERNEL);
884         if (!out)
885                 return -ENOMEM;
886
887         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
888         if (err)
889                 goto out;
890
891         *enable = MLX5_GET(query_nic_vport_context_out, out,
892                                 nic_vport_context.roce_en);
893
894 out:
895         kfree(out);
896         return err;
897 }
898 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_roce_en);
899
900 int mlx5_set_nic_vport_permanent_mac(struct mlx5_core_dev *mdev, int vport,
901                                      u8 *addr)
902 {
903         void *in;
904         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
905         u8  *mac_ptr;
906         int err;
907
908         in = mlx5_vzalloc(inlen);
909         if (!in) {
910                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
911                 return -ENOMEM;
912         }
913
914         MLX5_SET(modify_nic_vport_context_in, in,
915                  opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
916         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
917         MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
918         MLX5_SET(modify_nic_vport_context_in, in,
919                  field_select.permanent_address, 1);
920         mac_ptr = (u8 *)MLX5_ADDR_OF(modify_nic_vport_context_in, in,
921                 nic_vport_context.permanent_address.mac_addr_47_32);
922         ether_addr_copy(mac_ptr, addr);
923
924         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
925
926         kvfree(in);
927
928         return err;
929 }
930 EXPORT_SYMBOL_GPL(mlx5_set_nic_vport_permanent_mac);
931
932 int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev)
933 {
934         return mlx5_nic_vport_enable_disable_roce(mdev, 1);
935 }
936 EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce);
937
938 int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev)
939 {
940         return mlx5_nic_vport_enable_disable_roce(mdev, 0);
941 }
942 EXPORT_SYMBOL_GPL(mlx5_nic_vport_disable_roce);
943
944 int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport,
945                                   int vf, u8 port_num, void *out,
946                                   size_t out_sz)
947 {
948         int     in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in);
949         int     is_group_manager;
950         void   *in;
951         int     err;
952
953         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
954         in = mlx5_vzalloc(in_sz);
955         if (!in) {
956                 err = -ENOMEM;
957                 return err;
958         }
959
960         MLX5_SET(query_vport_counter_in, in, opcode,
961                  MLX5_CMD_OP_QUERY_VPORT_COUNTER);
962         if (other_vport) {
963                 if (is_group_manager) {
964                         MLX5_SET(query_vport_counter_in, in, other_vport, 1);
965                         MLX5_SET(query_vport_counter_in, in, vport_number, vf + 1);
966                 } else {
967                         err = -EPERM;
968                         goto free;
969                 }
970         }
971         if (MLX5_CAP_GEN(dev, num_ports) == 2)
972                 MLX5_SET(query_vport_counter_in, in, port_num, port_num);
973
974         err = mlx5_cmd_exec(dev, in, in_sz, out,  out_sz);
975 free:
976         kvfree(in);
977         return err;
978 }
979 EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter);
980
981 int mlx5_query_hca_vport_context(struct mlx5_core_dev *mdev,
982                                  u8 port_num, u8 vport_num, u32 *out,
983                                  int outlen)
984 {
985         u32 in[MLX5_ST_SZ_DW(query_hca_vport_context_in)] = {0};
986         int is_group_manager;
987
988         is_group_manager = MLX5_CAP_GEN(mdev, vport_group_manager);
989
990         MLX5_SET(query_hca_vport_context_in, in, opcode,
991                  MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT);
992
993         if (vport_num) {
994                 if (is_group_manager) {
995                         MLX5_SET(query_hca_vport_context_in, in, other_vport,
996                                  1);
997                         MLX5_SET(query_hca_vport_context_in, in, vport_number,
998                                  vport_num);
999                 } else {
1000                         return -EPERM;
1001                 }
1002         }
1003
1004         if (MLX5_CAP_GEN(mdev, num_ports) == 2)
1005                 MLX5_SET(query_hca_vport_context_in, in, port_num, port_num);
1006
1007         return mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
1008 }
1009
1010 int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *mdev,
1011                                            u64 *system_image_guid)
1012 {
1013         u32 *out;
1014         int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1015         int err;
1016
1017         out = mlx5_vzalloc(outlen);
1018         if (!out)
1019                 return -ENOMEM;
1020
1021         err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen);
1022         if (err)
1023                 goto out;
1024
1025         *system_image_guid = MLX5_GET64(query_hca_vport_context_out, out,
1026                                         hca_vport_context.system_image_guid);
1027
1028 out:
1029         kvfree(out);
1030         return err;
1031 }
1032 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid);
1033
1034 int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
1035 {
1036         u32 *out;
1037         int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1038         int err;
1039
1040         out = mlx5_vzalloc(outlen);
1041         if (!out)
1042                 return -ENOMEM;
1043
1044         err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen);
1045         if (err)
1046                 goto out;
1047
1048         *node_guid = MLX5_GET64(query_hca_vport_context_out, out,
1049                                 hca_vport_context.node_guid);
1050
1051 out:
1052         kvfree(out);
1053         return err;
1054 }
1055 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
1056
1057 static int mlx5_query_hca_vport_port_guid(struct mlx5_core_dev *mdev,
1058                                           u64 *port_guid)
1059 {
1060         u32 *out;
1061         int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1062         int err;
1063
1064         out = mlx5_vzalloc(outlen);
1065         if (!out)
1066                 return -ENOMEM;
1067
1068         err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen);
1069         if (err)
1070                 goto out;
1071
1072         *port_guid = MLX5_GET64(query_hca_vport_context_out, out,
1073                                 hca_vport_context.port_guid);
1074
1075 out:
1076         kvfree(out);
1077         return err;
1078 }
1079
1080 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 port_num,
1081                              u16 vport_num, u16 gid_index, union ib_gid *gid)
1082 {
1083         int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_in);
1084         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_gid_out);
1085         int is_group_manager;
1086         void *out = NULL;
1087         void *in = NULL;
1088         union ib_gid *tmp;
1089         int tbsz;
1090         int nout;
1091         int err;
1092
1093         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1094         tbsz = mlx5_get_gid_table_len(MLX5_CAP_GEN(dev, gid_table_size));
1095
1096         if (gid_index > tbsz && gid_index != 0xffff)
1097                 return -EINVAL;
1098
1099         if (gid_index == 0xffff)
1100                 nout = tbsz;
1101         else
1102                 nout = 1;
1103
1104         out_sz += nout * sizeof(*gid);
1105
1106         in = mlx5_vzalloc(in_sz);
1107         out = mlx5_vzalloc(out_sz);
1108         if (!in || !out) {
1109                 err = -ENOMEM;
1110                 goto out;
1111         }
1112
1113         MLX5_SET(query_hca_vport_gid_in, in, opcode,
1114                  MLX5_CMD_OP_QUERY_HCA_VPORT_GID);
1115         if (vport_num) {
1116                 if (is_group_manager) {
1117                         MLX5_SET(query_hca_vport_gid_in, in, vport_number,
1118                                  vport_num);
1119                         MLX5_SET(query_hca_vport_gid_in, in, other_vport, 1);
1120                 } else {
1121                         err = -EPERM;
1122                         goto out;
1123                 }
1124         }
1125
1126         MLX5_SET(query_hca_vport_gid_in, in, gid_index, gid_index);
1127
1128         if (MLX5_CAP_GEN(dev, num_ports) == 2)
1129                 MLX5_SET(query_hca_vport_gid_in, in, port_num, port_num);
1130
1131         err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
1132         if (err)
1133                 goto out;
1134
1135         tmp = (union ib_gid *)MLX5_ADDR_OF(query_hca_vport_gid_out, out, gid);
1136         gid->global.subnet_prefix = tmp->global.subnet_prefix;
1137         gid->global.interface_id = tmp->global.interface_id;
1138
1139 out:
1140         kvfree(in);
1141         kvfree(out);
1142         return err;
1143 }
1144 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid);
1145
1146 int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
1147                               u8 port_num, u16 vf_num, u16 pkey_index,
1148                               u16 *pkey)
1149 {
1150         int in_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_in);
1151         int out_sz = MLX5_ST_SZ_BYTES(query_hca_vport_pkey_out);
1152         int is_group_manager;
1153         void *out = NULL;
1154         void *in = NULL;
1155         void *pkarr;
1156         int nout;
1157         int tbsz;
1158         int err;
1159         int i;
1160
1161         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1162
1163         tbsz = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size));
1164         if (pkey_index > tbsz && pkey_index != 0xffff)
1165                 return -EINVAL;
1166
1167         if (pkey_index == 0xffff)
1168                 nout = tbsz;
1169         else
1170                 nout = 1;
1171
1172         out_sz += nout * MLX5_ST_SZ_BYTES(pkey);
1173
1174         in = kzalloc(in_sz, GFP_KERNEL);
1175         out = kzalloc(out_sz, GFP_KERNEL);
1176
1177         MLX5_SET(query_hca_vport_pkey_in, in, opcode,
1178                  MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY);
1179         if (other_vport) {
1180                 if (is_group_manager) {
1181                         MLX5_SET(query_hca_vport_pkey_in, in, vport_number,
1182                                  vf_num);
1183                         MLX5_SET(query_hca_vport_pkey_in, in, other_vport, 1);
1184                 } else {
1185                         err = -EPERM;
1186                         goto out;
1187                 }
1188         }
1189         MLX5_SET(query_hca_vport_pkey_in, in, pkey_index, pkey_index);
1190
1191         if (MLX5_CAP_GEN(dev, num_ports) == 2)
1192                 MLX5_SET(query_hca_vport_pkey_in, in, port_num, port_num);
1193
1194         err = mlx5_cmd_exec(dev, in, in_sz, out, out_sz);
1195         if (err)
1196                 goto out;
1197
1198         pkarr = MLX5_ADDR_OF(query_hca_vport_pkey_out, out, pkey);
1199         for (i = 0; i < nout; i++, pkey++,
1200              pkarr += MLX5_ST_SZ_BYTES(pkey))
1201                 *pkey = MLX5_GET_PR(pkey, pkarr, pkey);
1202
1203 out:
1204         kfree(in);
1205         kfree(out);
1206         return err;
1207 }
1208 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey);
1209
1210 static int mlx5_query_hca_min_wqe_header(struct mlx5_core_dev *mdev,
1211                                          int *min_header)
1212 {
1213         u32 *out;
1214         u32 outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1215         int err;
1216
1217         out = mlx5_vzalloc(outlen);
1218         if (!out)
1219                 return -ENOMEM;
1220
1221         err = mlx5_query_hca_vport_context(mdev, 1, 0, out, outlen);
1222         if (err)
1223                 goto out;
1224
1225         *min_header = MLX5_GET(query_hca_vport_context_out, out,
1226                                hca_vport_context.min_wqe_inline_mode);
1227
1228 out:
1229         kvfree(out);
1230         return err;
1231 }
1232
1233 static int mlx5_modify_eswitch_vport_context(struct mlx5_core_dev *mdev,
1234                                              u16 vport, void *in, int inlen)
1235 {
1236         u32 out[MLX5_ST_SZ_DW(modify_esw_vport_context_out)] = {0};
1237         int err;
1238
1239         MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport);
1240         if (vport)
1241                 MLX5_SET(modify_esw_vport_context_in, in, other_vport, 1);
1242
1243         MLX5_SET(modify_esw_vport_context_in, in, opcode,
1244                  MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT);
1245
1246         err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
1247         if (err)
1248                 mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT failed\n");
1249
1250         return err;
1251 }
1252
1253 int mlx5_set_eswitch_cvlan_info(struct mlx5_core_dev *mdev, u8 vport,
1254                                 u8 insert_mode, u8 strip_mode,
1255                                 u16 vlan, u8 cfi, u8 pcp)
1256 {
1257         u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)];
1258
1259         memset(in, 0, sizeof(in));
1260
1261         if (insert_mode != MLX5_MODIFY_ESW_VPORT_CONTEXT_CVLAN_INSERT_NONE) {
1262                 MLX5_SET(modify_esw_vport_context_in, in,
1263                          esw_vport_context.cvlan_cfi, cfi);
1264                 MLX5_SET(modify_esw_vport_context_in, in,
1265                          esw_vport_context.cvlan_pcp, pcp);
1266                 MLX5_SET(modify_esw_vport_context_in, in,
1267                          esw_vport_context.cvlan_id, vlan);
1268         }
1269
1270         MLX5_SET(modify_esw_vport_context_in, in,
1271                  esw_vport_context.vport_cvlan_insert, insert_mode);
1272
1273         MLX5_SET(modify_esw_vport_context_in, in,
1274                  esw_vport_context.vport_cvlan_strip, strip_mode);
1275
1276         MLX5_SET(modify_esw_vport_context_in, in, field_select,
1277                  MLX5_MODIFY_ESW_VPORT_CONTEXT_FIELD_SELECT_CVLAN_STRIP |
1278                  MLX5_MODIFY_ESW_VPORT_CONTEXT_FIELD_SELECT_CVLAN_INSERT);
1279
1280         return mlx5_modify_eswitch_vport_context(mdev, vport, in, sizeof(in));
1281 }
1282 EXPORT_SYMBOL_GPL(mlx5_set_eswitch_cvlan_info);
1283
1284 int mlx5_query_vport_mtu(struct mlx5_core_dev *mdev, int *mtu)
1285 {
1286         u32 *out;
1287         u32 outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1288         int err;
1289
1290         out = mlx5_vzalloc(outlen);
1291         if (!out)
1292                 return -ENOMEM;
1293
1294         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
1295         if (err)
1296                 goto out;
1297
1298         *mtu = MLX5_GET(query_nic_vport_context_out, out,
1299                         nic_vport_context.mtu);
1300
1301 out:
1302         kvfree(out);
1303         return err;
1304 }
1305 EXPORT_SYMBOL_GPL(mlx5_query_vport_mtu);
1306
1307 int mlx5_set_vport_mtu(struct mlx5_core_dev *mdev, int mtu)
1308 {
1309         u32 *in;
1310         u32 inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1311         int err;
1312
1313         in = mlx5_vzalloc(inlen);
1314         if (!in)
1315                 return -ENOMEM;
1316
1317         MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1);
1318         MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, mtu);
1319
1320         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
1321
1322         kvfree(in);
1323         return err;
1324 }
1325 EXPORT_SYMBOL_GPL(mlx5_set_vport_mtu);
1326
1327 static int mlx5_query_vport_min_wqe_header(struct mlx5_core_dev *mdev,
1328                                            int *min_header)
1329 {
1330         u32 *out;
1331         u32 outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1332         int err;
1333
1334         out = mlx5_vzalloc(outlen);
1335         if (!out)
1336                 return -ENOMEM;
1337
1338         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
1339         if (err)
1340                 goto out;
1341
1342         *min_header = MLX5_GET(query_nic_vport_context_out, out,
1343                                nic_vport_context.min_wqe_inline_mode);
1344
1345 out:
1346         kvfree(out);
1347         return err;
1348 }
1349
1350 int mlx5_set_vport_min_wqe_header(struct mlx5_core_dev *mdev,
1351                                   u8 vport, int min_header)
1352 {
1353         u32 *in;
1354         u32 inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1355         int err;
1356
1357         in = mlx5_vzalloc(inlen);
1358         if (!in)
1359                 return -ENOMEM;
1360
1361         MLX5_SET(modify_nic_vport_context_in, in,
1362                  field_select.min_wqe_inline_mode, 1);
1363         MLX5_SET(modify_nic_vport_context_in, in,
1364                  nic_vport_context.min_wqe_inline_mode, min_header);
1365         MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
1366         MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
1367
1368         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
1369
1370         kvfree(in);
1371         return err;
1372 }
1373 EXPORT_SYMBOL_GPL(mlx5_set_vport_min_wqe_header);
1374
1375 int mlx5_query_min_wqe_header(struct mlx5_core_dev *dev, int *min_header)
1376 {
1377         switch (MLX5_CAP_GEN(dev, port_type)) {
1378         case MLX5_CMD_HCA_CAP_PORT_TYPE_IB:
1379                 return mlx5_query_hca_min_wqe_header(dev, min_header);
1380
1381         case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET:
1382                 return mlx5_query_vport_min_wqe_header(dev, min_header);
1383
1384         default:
1385                 return -EINVAL;
1386         }
1387 }
1388 EXPORT_SYMBOL_GPL(mlx5_query_min_wqe_header);
1389
1390 int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
1391                                  u16 vport,
1392                                  int *promisc_uc,
1393                                  int *promisc_mc,
1394                                  int *promisc_all)
1395 {
1396         u32 *out;
1397         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1398         int err;
1399
1400         out = kzalloc(outlen, GFP_KERNEL);
1401         if (!out)
1402                 return -ENOMEM;
1403
1404         err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
1405         if (err)
1406                 goto out;
1407
1408         *promisc_uc = MLX5_GET(query_nic_vport_context_out, out,
1409                                nic_vport_context.promisc_uc);
1410         *promisc_mc = MLX5_GET(query_nic_vport_context_out, out,
1411                                nic_vport_context.promisc_mc);
1412         *promisc_all = MLX5_GET(query_nic_vport_context_out, out,
1413                                 nic_vport_context.promisc_all);
1414
1415 out:
1416         kfree(out);
1417         return err;
1418 }
1419 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
1420
1421 int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,
1422                                   int promisc_uc,
1423                                   int promisc_mc,
1424                                   int promisc_all)
1425 {
1426         void *in;
1427         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1428         int err;
1429
1430         in = mlx5_vzalloc(inlen);
1431         if (!in) {
1432                 mlx5_core_err(mdev, "failed to allocate inbox\n");
1433                 return -ENOMEM;
1434         }
1435
1436         MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
1437         MLX5_SET(modify_nic_vport_context_in, in,
1438                  nic_vport_context.promisc_uc, promisc_uc);
1439         MLX5_SET(modify_nic_vport_context_in, in,
1440                  nic_vport_context.promisc_mc, promisc_mc);
1441         MLX5_SET(modify_nic_vport_context_in, in,
1442                  nic_vport_context.promisc_all, promisc_all);
1443
1444         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
1445         kvfree(in);
1446         return err;
1447 }
1448 EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc);
1449
1450 int mlx5_nic_vport_modify_local_lb(struct mlx5_core_dev *mdev,
1451                                    enum mlx5_local_lb_selection selection,
1452                                    u8 value)
1453 {
1454         void *in;
1455         int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
1456         int err;
1457
1458         in = mlx5_vzalloc(inlen);
1459         if (!in) {
1460                 mlx5_core_warn(mdev, "failed to allocate inbox\n");
1461                 return -ENOMEM;
1462         }
1463
1464         MLX5_SET(modify_nic_vport_context_in, in, vport_number, 0);
1465
1466         if (selection == MLX5_LOCAL_MC_LB) {
1467                 MLX5_SET(modify_nic_vport_context_in, in,
1468                          field_select.disable_mc_local_lb, 1);
1469                 MLX5_SET(modify_nic_vport_context_in, in,
1470                          nic_vport_context.disable_mc_local_lb,
1471                          value);
1472         } else {
1473                 MLX5_SET(modify_nic_vport_context_in, in,
1474                          field_select.disable_uc_local_lb, 1);
1475                 MLX5_SET(modify_nic_vport_context_in, in,
1476                          nic_vport_context.disable_uc_local_lb,
1477                          value);
1478         }
1479
1480         err = mlx5_modify_nic_vport_context(mdev, in, inlen);
1481
1482         kvfree(in);
1483         return err;
1484 }
1485 EXPORT_SYMBOL_GPL(mlx5_nic_vport_modify_local_lb);
1486
1487 int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev,
1488                                   enum mlx5_local_lb_selection selection,
1489                                   u8 *value)
1490 {
1491         void *out;
1492         int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
1493         int err;
1494
1495         out = kzalloc(outlen, GFP_KERNEL);
1496         if (!out)
1497                 return -ENOMEM;
1498
1499         err = mlx5_query_nic_vport_context(mdev, 0, out, outlen);
1500         if (err)
1501                 goto done;
1502
1503         if (selection == MLX5_LOCAL_MC_LB)
1504                 *value = MLX5_GET(query_nic_vport_context_out, out,
1505                                   nic_vport_context.disable_mc_local_lb);
1506         else
1507                 *value = MLX5_GET(query_nic_vport_context_out, out,
1508                                   nic_vport_context.disable_uc_local_lb);
1509
1510 done:
1511         kfree(out);
1512         return err;
1513 }
1514 EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb);
1515
1516 int mlx5_query_vport_counter(struct mlx5_core_dev *dev,
1517                              u8 port_num, u16 vport_num,
1518                              void *out, int out_size)
1519 {
1520         int in_sz = MLX5_ST_SZ_BYTES(query_vport_counter_in);
1521         int is_group_manager;
1522         void *in;
1523         int err;
1524
1525         is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
1526
1527         in = mlx5_vzalloc(in_sz);
1528         if (!in)
1529                 return -ENOMEM;
1530
1531         MLX5_SET(query_vport_counter_in, in, opcode,
1532                  MLX5_CMD_OP_QUERY_VPORT_COUNTER);
1533         if (vport_num) {
1534                 if (is_group_manager) {
1535                         MLX5_SET(query_vport_counter_in, in, other_vport, 1);
1536                         MLX5_SET(query_vport_counter_in, in, vport_number,
1537                                  vport_num);
1538                 } else {
1539                         err = -EPERM;
1540                         goto ex;
1541                 }
1542         }
1543         if (MLX5_CAP_GEN(dev, num_ports) == 2)
1544                 MLX5_SET(query_vport_counter_in, in, port_num, port_num);
1545
1546         err = mlx5_cmd_exec(dev, in, in_sz, out,  out_size);
1547
1548         kvfree(in);
1549 ex:
1550         return err;
1551 }
1552 EXPORT_SYMBOL_GPL(mlx5_query_vport_counter);
1553
1554 int mlx5_get_vport_counters(struct mlx5_core_dev *dev, u8 port_num,
1555                             struct mlx5_vport_counters *vc)
1556 {
1557         int out_sz = MLX5_ST_SZ_BYTES(query_vport_counter_out);
1558         void *out;
1559         int err;
1560
1561         out = mlx5_vzalloc(out_sz);
1562         if (!out)
1563                 return -ENOMEM;
1564
1565         err = mlx5_query_vport_counter(dev, port_num, 0, out, out_sz);
1566         if (err)
1567                 goto ex;
1568
1569         vc->received_errors.packets =
1570                 MLX5_GET64(query_vport_counter_out,
1571                            out, received_errors.packets);
1572         vc->received_errors.octets =
1573                 MLX5_GET64(query_vport_counter_out,
1574                            out, received_errors.octets);
1575         vc->transmit_errors.packets =
1576                 MLX5_GET64(query_vport_counter_out,
1577                            out, transmit_errors.packets);
1578         vc->transmit_errors.octets =
1579                 MLX5_GET64(query_vport_counter_out,
1580                            out, transmit_errors.octets);
1581         vc->received_ib_unicast.packets =
1582                 MLX5_GET64(query_vport_counter_out,
1583                            out, received_ib_unicast.packets);
1584         vc->received_ib_unicast.octets =
1585                 MLX5_GET64(query_vport_counter_out,
1586                            out, received_ib_unicast.octets);
1587         vc->transmitted_ib_unicast.packets =
1588                 MLX5_GET64(query_vport_counter_out,
1589                            out, transmitted_ib_unicast.packets);
1590         vc->transmitted_ib_unicast.octets =
1591                 MLX5_GET64(query_vport_counter_out,
1592                            out, transmitted_ib_unicast.octets);
1593         vc->received_ib_multicast.packets =
1594                 MLX5_GET64(query_vport_counter_out,
1595                            out, received_ib_multicast.packets);
1596         vc->received_ib_multicast.octets =
1597                 MLX5_GET64(query_vport_counter_out,
1598                            out, received_ib_multicast.octets);
1599         vc->transmitted_ib_multicast.packets =
1600                 MLX5_GET64(query_vport_counter_out,
1601                            out, transmitted_ib_multicast.packets);
1602         vc->transmitted_ib_multicast.octets =
1603                 MLX5_GET64(query_vport_counter_out,
1604                            out, transmitted_ib_multicast.octets);
1605         vc->received_eth_broadcast.packets =
1606                 MLX5_GET64(query_vport_counter_out,
1607                            out, received_eth_broadcast.packets);
1608         vc->received_eth_broadcast.octets =
1609                 MLX5_GET64(query_vport_counter_out,
1610                            out, received_eth_broadcast.octets);
1611         vc->transmitted_eth_broadcast.packets =
1612                 MLX5_GET64(query_vport_counter_out,
1613                            out, transmitted_eth_broadcast.packets);
1614         vc->transmitted_eth_broadcast.octets =
1615                 MLX5_GET64(query_vport_counter_out,
1616                            out, transmitted_eth_broadcast.octets);
1617         vc->received_eth_unicast.octets =
1618                 MLX5_GET64(query_vport_counter_out,
1619                            out, received_eth_unicast.octets);
1620         vc->received_eth_unicast.packets =
1621                 MLX5_GET64(query_vport_counter_out,
1622                            out, received_eth_unicast.packets);
1623         vc->transmitted_eth_unicast.octets =
1624                 MLX5_GET64(query_vport_counter_out,
1625                            out, transmitted_eth_unicast.octets);
1626         vc->transmitted_eth_unicast.packets =
1627                 MLX5_GET64(query_vport_counter_out,
1628                            out, transmitted_eth_unicast.packets);
1629         vc->received_eth_multicast.octets =
1630                 MLX5_GET64(query_vport_counter_out,
1631                            out, received_eth_multicast.octets);
1632         vc->received_eth_multicast.packets =
1633                 MLX5_GET64(query_vport_counter_out,
1634                            out, received_eth_multicast.packets);
1635         vc->transmitted_eth_multicast.octets =
1636                 MLX5_GET64(query_vport_counter_out,
1637                            out, transmitted_eth_multicast.octets);
1638         vc->transmitted_eth_multicast.packets =
1639                 MLX5_GET64(query_vport_counter_out,
1640                            out, transmitted_eth_multicast.packets);
1641
1642 ex:
1643         kvfree(out);
1644         return err;
1645 }
1646
1647 int mlx5_query_vport_system_image_guid(struct mlx5_core_dev *dev,
1648                                        u64 *sys_image_guid)
1649 {
1650         switch (MLX5_CAP_GEN(dev, port_type)) {
1651         case MLX5_CMD_HCA_CAP_PORT_TYPE_IB:
1652                 return mlx5_query_hca_vport_system_image_guid(dev,
1653                                                               sys_image_guid);
1654
1655         case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET:
1656                 return mlx5_query_nic_vport_system_image_guid(dev,
1657                                                               sys_image_guid);
1658
1659         default:
1660                 return -EINVAL;
1661         }
1662 }
1663 EXPORT_SYMBOL_GPL(mlx5_query_vport_system_image_guid);
1664
1665 int mlx5_query_vport_node_guid(struct mlx5_core_dev *dev, u64 *node_guid)
1666 {
1667         switch (MLX5_CAP_GEN(dev, port_type)) {
1668         case MLX5_CMD_HCA_CAP_PORT_TYPE_IB:
1669                 return mlx5_query_hca_vport_node_guid(dev, node_guid);
1670
1671         case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET:
1672                 return mlx5_query_nic_vport_node_guid(dev, node_guid);
1673
1674         default:
1675                 return -EINVAL;
1676         }
1677 }
1678 EXPORT_SYMBOL_GPL(mlx5_query_vport_node_guid);
1679
1680 int mlx5_query_vport_port_guid(struct mlx5_core_dev *dev, u64 *port_guid)
1681 {
1682         switch (MLX5_CAP_GEN(dev, port_type)) {
1683         case MLX5_CMD_HCA_CAP_PORT_TYPE_IB:
1684                 return mlx5_query_hca_vport_port_guid(dev, port_guid);
1685
1686         case MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET:
1687                 return mlx5_query_nic_vport_port_guid(dev, port_guid);
1688
1689         default:
1690                 return -EINVAL;
1691         }
1692 }
1693 EXPORT_SYMBOL_GPL(mlx5_query_vport_port_guid);
1694
1695 int mlx5_query_hca_vport_state(struct mlx5_core_dev *dev, u8 *vport_state)
1696 {
1697         u32 *out;
1698         int outlen = MLX5_ST_SZ_BYTES(query_hca_vport_context_out);
1699         int err;
1700
1701         out = mlx5_vzalloc(outlen);
1702         if (!out)
1703                 return -ENOMEM;
1704
1705         err = mlx5_query_hca_vport_context(dev, 1, 0, out, outlen);
1706         if (err)
1707                 goto out;
1708
1709         *vport_state = MLX5_GET(query_hca_vport_context_out, out,
1710                                 hca_vport_context.vport_state);
1711
1712 out:
1713         kvfree(out);
1714         return err;
1715 }
1716 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_state);
1717
1718 int mlx5_core_query_ib_ppcnt(struct mlx5_core_dev *dev,
1719                              u8 port_num, void *out, size_t sz)
1720 {
1721         u32 *in;
1722         int err;
1723
1724         in  = mlx5_vzalloc(sz);
1725         if (!in) {
1726                 err = -ENOMEM;
1727                 return err;
1728         }
1729
1730         MLX5_SET(ppcnt_reg, in, local_port, port_num);
1731
1732         MLX5_SET(ppcnt_reg, in, grp, MLX5_INFINIBAND_PORT_COUNTERS_GROUP);
1733         err = mlx5_core_access_reg(dev, in, sz, out,
1734                                    sz, MLX5_REG_PPCNT, 0, 0);
1735
1736         kvfree(in);
1737         return err;
1738 }