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