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