]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mlx5/mlx5_core/mlx5_port.c
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
[FreeBSD/FreeBSD.git] / sys / dev / mlx5 / mlx5_core / mlx5_port.c
1 /*-
2  * Copyright (c) 2013-2015, 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/module.h>
29 #include <dev/mlx5/driver.h>
30 #include "mlx5_core.h"
31
32 int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
33                          int size_in, void *data_out, int size_out,
34                          u16 reg_num, int arg, int write)
35 {
36         struct mlx5_access_reg_mbox_in *in = NULL;
37         struct mlx5_access_reg_mbox_out *out = NULL;
38         int err = -ENOMEM;
39
40         in = mlx5_vzalloc(sizeof(*in) + size_in);
41         if (!in)
42                 return -ENOMEM;
43
44         out = mlx5_vzalloc(sizeof(*out) + size_out);
45         if (!out)
46                 goto ex1;
47
48         memcpy(in->data, data_in, size_in);
49         in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ACCESS_REG);
50         in->hdr.opmod = cpu_to_be16(!write);
51         in->arg = cpu_to_be32(arg);
52         in->register_id = cpu_to_be16(reg_num);
53         err = mlx5_cmd_exec(dev, in, sizeof(*in) + size_in, out,
54                             sizeof(*out) + size_out);
55         if (err)
56                 goto ex2;
57
58         if (out->hdr.status)
59                 err = mlx5_cmd_status_to_err(&out->hdr);
60
61         if (!err)
62                 memcpy(data_out, out->data, size_out);
63
64 ex2:
65         kvfree(out);
66 ex1:
67         kvfree(in);
68         return err;
69 }
70 EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
71
72
73 struct mlx5_reg_pcap {
74         u8                      rsvd0;
75         u8                      port_num;
76         u8                      rsvd1[2];
77         __be32                  caps_127_96;
78         __be32                  caps_95_64;
79         __be32                  caps_63_32;
80         __be32                  caps_31_0;
81 };
82
83 /* This function should be used after setting a port register only */
84 void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
85 {
86         enum mlx5_port_status ps;
87
88         mlx5_query_port_admin_status(dev, &ps);
89         mlx5_set_port_status(dev, MLX5_PORT_DOWN);
90         if (ps == MLX5_PORT_UP)
91                 mlx5_set_port_status(dev, MLX5_PORT_UP);
92 }
93 EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
94
95 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
96 {
97         struct mlx5_reg_pcap in;
98         struct mlx5_reg_pcap out;
99         int err;
100
101         memset(&in, 0, sizeof(in));
102         in.caps_127_96 = cpu_to_be32(caps);
103         in.port_num = port_num;
104
105         err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
106                                    sizeof(out), MLX5_REG_PCAP, 0, 1);
107
108         return err;
109 }
110 EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
111
112 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
113                          int ptys_size, int proto_mask)
114 {
115         u32 in[MLX5_ST_SZ_DW(ptys_reg)];
116         int err;
117
118         memset(in, 0, sizeof(in));
119         MLX5_SET(ptys_reg, in, local_port, 1);
120         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
121
122         err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
123                                    ptys_size, MLX5_REG_PTYS, 0, 0);
124
125         return err;
126 }
127 EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
128
129 int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
130                               u32 *proto_cap, int proto_mask)
131 {
132         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
133         int err;
134
135         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
136         if (err)
137                 return err;
138
139         if (proto_mask == MLX5_PTYS_EN)
140                 *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
141         else
142                 *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
143
144         return 0;
145 }
146 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
147
148 int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
149                             u8 *an_disable_cap, u8 *an_disable_status)
150 {
151         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
152         int err;
153
154         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
155         if (err)
156                 return err;
157
158         *an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin);
159         *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
160
161         return 0;
162 }
163 EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
164
165 int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable,
166                           u32 eth_proto_admin, int proto_mask)
167 {
168         u32 in[MLX5_ST_SZ_DW(ptys_reg)];
169         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
170         u8 an_disable_cap;
171         u8 an_disable_status;
172         int err;
173
174         err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap,
175                                       &an_disable_status);
176         if (err)
177                 return err;
178         if (!an_disable_cap)
179                 return -EPERM;
180
181         memset(in, 0, sizeof(in));
182
183         MLX5_SET(ptys_reg, in, local_port, 1);
184         MLX5_SET(ptys_reg, in, an_disable_admin, disable);
185         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
186         if (proto_mask == MLX5_PTYS_EN)
187                 MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin);
188
189         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
190                                    sizeof(out), MLX5_REG_PTYS, 0, 1);
191         return err;
192 }
193 EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
194
195 int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
196                                 u32 *proto_admin, int proto_mask)
197 {
198         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
199         int err;
200
201         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
202         if (err)
203                 return err;
204
205         if (proto_mask == MLX5_PTYS_EN)
206                 *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
207         else
208                 *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
209
210         return 0;
211 }
212 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
213
214 int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
215                         int proto_mask)
216 {
217         u32 in[MLX5_ST_SZ_DW(ptys_reg)];
218         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
219         int err;
220
221         memset(in, 0, sizeof(in));
222
223         MLX5_SET(ptys_reg, in, local_port, 1);
224         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
225         if (proto_mask == MLX5_PTYS_EN)
226                 MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
227         else
228                 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
229
230         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
231                                    sizeof(out), MLX5_REG_PTYS, 0, 1);
232         return err;
233 }
234 EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
235
236 int mlx5_set_port_status(struct mlx5_core_dev *dev,
237                          enum mlx5_port_status status)
238 {
239         u32 in[MLX5_ST_SZ_DW(paos_reg)];
240         u32 out[MLX5_ST_SZ_DW(paos_reg)];
241         int err;
242
243         memset(in, 0, sizeof(in));
244
245         MLX5_SET(paos_reg, in, local_port, 1);
246
247         MLX5_SET(paos_reg, in, admin_status, status);
248         MLX5_SET(paos_reg, in, ase, 1);
249
250         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
251                                    sizeof(out), MLX5_REG_PAOS, 0, 1);
252         return err;
253 }
254
255 int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
256 {
257         u32 in[MLX5_ST_SZ_DW(paos_reg)];
258         u32 out[MLX5_ST_SZ_DW(paos_reg)];
259         int err;
260
261         memset(in, 0, sizeof(in));
262
263         MLX5_SET(paos_reg, in, local_port, 1);
264
265         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
266                                    sizeof(out), MLX5_REG_PAOS, 0, 0);
267         if (err)
268                 return err;
269
270         *status = MLX5_GET(paos_reg, out, oper_status);
271         return err;
272 }
273
274 int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
275                                  enum mlx5_port_status *status)
276 {
277         u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
278         u32 out[MLX5_ST_SZ_DW(paos_reg)];
279         int err;
280
281         MLX5_SET(paos_reg, in, local_port, 1);
282         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
283                                    sizeof(out), MLX5_REG_PAOS, 0, 0);
284         if (err)
285                 return err;
286         *status = MLX5_GET(paos_reg, out, admin_status);
287         return 0;
288 }
289 EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
290
291 static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
292                                int *admin_mtu, int *max_mtu, int *oper_mtu)
293 {
294         u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
295         u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
296         int err;
297
298         memset(in, 0, sizeof(in));
299
300         MLX5_SET(pmtu_reg, in, local_port, 1);
301
302         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
303                                    sizeof(out), MLX5_REG_PMTU, 0, 0);
304         if (err)
305                 return err;
306
307         if (max_mtu)
308                 *max_mtu  = MLX5_GET(pmtu_reg, out, max_mtu);
309         if (oper_mtu)
310                 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
311         if (admin_mtu)
312                 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
313
314         return err;
315 }
316
317 int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
318 {
319         u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
320         u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
321
322         memset(in, 0, sizeof(in));
323
324         MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
325         MLX5_SET(pmtu_reg, in, local_port, 1);
326
327         return mlx5_core_access_reg(dev, in, sizeof(in), out,
328                                    sizeof(out), MLX5_REG_PMTU, 0, 1);
329 }
330 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
331
332 int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
333 {
334         return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
335 }
336 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
337
338 int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 port,
339                         u32 rx_pause, u32 tx_pause)
340 {
341         u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
342         u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
343
344         memset(in, 0, sizeof(in));
345         memset(out, 0, sizeof(out));
346
347         MLX5_SET(pfcc_reg, in, local_port, port);
348         MLX5_SET(pfcc_reg, in, pptx, tx_pause);
349         MLX5_SET(pfcc_reg, in, pprx, rx_pause);
350
351         return mlx5_core_access_reg(dev, in, sizeof(in), out,
352                                    sizeof(out), MLX5_REG_PFCC, 0, 1);
353 }
354
355 int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
356                           u32 *rx_pause, u32 *tx_pause)
357 {
358         u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
359         u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
360         int err;
361
362         memset(in, 0, sizeof(in));
363         memset(out, 0, sizeof(out));
364
365         MLX5_SET(pfcc_reg, in, local_port, port);
366
367         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
368                                    sizeof(out), MLX5_REG_PFCC, 0, 0);
369         if (err)
370                 return err;
371
372         *rx_pause = MLX5_GET(pfcc_reg, out, pprx);
373         *tx_pause = MLX5_GET(pfcc_reg, out, pptx);
374
375         return 0;
376 }
377
378 int mlx5_set_port_pfc(struct mlx5_core_dev *dev, u8 pfc_en_tx, u8 pfc_en_rx)
379 {
380         u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
381         u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
382
383         MLX5_SET(pfcc_reg, in, local_port, 1);
384         MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx);
385         MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx);
386         MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_tx);
387         MLX5_SET_TO_ONES(pfcc_reg, in, prio_mask_rx);
388
389         return mlx5_core_access_reg(dev, in, sizeof(in), out,
390                                     sizeof(out), MLX5_REG_PFCC, 0, 1);
391 }
392 EXPORT_SYMBOL_GPL(mlx5_set_port_pfc);
393
394 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
395 {
396         u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
397         u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
398         int err;
399
400         MLX5_SET(pfcc_reg, in, local_port, 1);
401         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
402                                    sizeof(out), MLX5_REG_PFCC, 0, 0);
403         if (err)
404                 return err;
405
406         if (pfc_en_tx)
407                 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx);
408
409         if (pfc_en_rx)
410                 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx);
411
412         return 0;
413 }
414 EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
415
416 int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
417 {
418         return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
419 }
420 EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
421
422 u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
423 {
424         u8 wol_supported = 0;
425
426         if (MLX5_CAP_GEN(dev, wol_s))
427                 wol_supported |= MLX5_WOL_SECURED_MAGIC;
428         if (MLX5_CAP_GEN(dev, wol_g))
429                 wol_supported |= MLX5_WOL_MAGIC;
430         if (MLX5_CAP_GEN(dev, wol_a))
431                 wol_supported |= MLX5_WOL_ARP;
432         if (MLX5_CAP_GEN(dev, wol_b))
433                 wol_supported |= MLX5_WOL_BROADCAST;
434         if (MLX5_CAP_GEN(dev, wol_m))
435                 wol_supported |= MLX5_WOL_MULTICAST;
436         if (MLX5_CAP_GEN(dev, wol_u))
437                 wol_supported |= MLX5_WOL_UNICAST;
438         if (MLX5_CAP_GEN(dev, wol_p))
439                 wol_supported |= MLX5_WOL_PHY_ACTIVITY;
440
441         return wol_supported;
442 }
443 EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
444
445 int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
446 {
447         u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)];
448         u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)];
449
450         memset(in, 0, sizeof(in));
451         memset(out, 0, sizeof(out));
452
453         MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
454         MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
455         MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
456
457         return mlx5_cmd_exec_check_status(dev, in, sizeof(in),
458                                           out, sizeof(out));
459 }
460 EXPORT_SYMBOL_GPL(mlx5_set_wol);
461
462 int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout)
463 {
464         u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)];
465         u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)];
466         int err = 0;
467
468         memset(in, 0, sizeof(in));
469         memset(out, 0, sizeof(out));
470
471         MLX5_SET(query_delay_drop_params_in, in, opcode,
472                  MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS);
473
474         err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
475         if (err)
476                 return err;
477
478         *timeout = MLX5_GET(query_delay_drop_params_out, out,
479                             delay_drop_timeout);
480
481         return 0;
482 }
483 EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
484
485 int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout)
486 {
487         u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)];
488         u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)];
489
490         memset(in, 0, sizeof(in));
491         memset(out, 0, sizeof(out));
492
493         MLX5_SET(set_delay_drop_params_in, in, opcode,
494                  MLX5_CMD_OP_SET_DELAY_DROP_PARAMS);
495         MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout);
496
497         return mlx5_cmd_exec_check_status(dev, in, sizeof(in),
498                                            out, sizeof(out));
499 }
500 EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
501
502 int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
503                           struct mlx5_pvlc_reg *pvlc, int write)
504 {
505         int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
506         u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)];
507         u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)];
508         int err;
509
510         memset(out, 0, sizeof(out));
511         memset(in, 0, sizeof(in));
512
513         MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
514         if (write)
515                 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
516
517         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
518                                    !!write);
519         if (err)
520                 return err;
521
522         if (!write) {
523                 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
524                 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
525                 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
526                 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
527         }
528
529         return 0;
530 }
531 EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
532
533 int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
534                           struct mlx5_ptys_reg *ptys, int write)
535 {
536         int sz = MLX5_ST_SZ_BYTES(ptys_reg);
537         void *out = NULL;
538         void *in = NULL;
539         int err;
540
541         in = mlx5_vzalloc(sz);
542         if (!in)
543                 return -ENOMEM;
544
545         out = mlx5_vzalloc(sz);
546         if (!out) {
547                 kfree(in);
548                 return -ENOMEM;
549         }
550
551         MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
552         MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
553         if (write) {
554                 MLX5_SET(ptys_reg, in, eth_proto_capability,
555                          ptys->eth_proto_cap);
556                 MLX5_SET(ptys_reg, in, ib_link_width_capability,
557                          ptys->ib_link_width_cap);
558                 MLX5_SET(ptys_reg, in, ib_proto_capability,
559                          ptys->ib_proto_cap);
560                 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
561                 MLX5_SET(ptys_reg, in, ib_link_width_admin,
562                          ptys->ib_link_width_admin);
563                 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
564                 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
565                 MLX5_SET(ptys_reg, in, ib_link_width_oper,
566                          ptys->ib_link_width_oper);
567                 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
568                 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
569                          ptys->eth_proto_lp_advertise);
570         }
571
572         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
573                                    !!write);
574         if (err)
575                 goto out;
576
577         if (!write) {
578                 ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
579                 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
580                 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
581                                                eth_proto_capability);
582                 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
583                                            ib_link_width_capability);
584                 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
585                                               ib_proto_capability);
586                 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
587                                                  eth_proto_admin);
588                 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
589                                                      ib_link_width_admin);
590                 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
591                 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
592                 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
593                                                     ib_link_width_oper);
594                 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
595                 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
596                                                         eth_proto_lp_advertise);
597         }
598
599 out:
600         kvfree(in);
601         kvfree(out);
602         return err;
603 }
604 EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
605
606 static int mtu_to_ib_mtu(int mtu)
607 {
608         switch (mtu) {
609         case 256: return 1;
610         case 512: return 2;
611         case 1024: return 3;
612         case 2048: return 4;
613         case 4096: return 5;
614         default:
615                 printf("mlx5_core: WARN: ""invalid mtu\n");
616                 return -1;
617         }
618 }
619
620 int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
621                           struct mlx5_pmtu_reg *pmtu, int write)
622 {
623         int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
624         void *out = NULL;
625         void *in = NULL;
626         int err;
627
628         in = mlx5_vzalloc(sz);
629         if (!in)
630                 return -ENOMEM;
631
632         out = mlx5_vzalloc(sz);
633         if (!out) {
634                 kfree(in);
635                 return -ENOMEM;
636         }
637
638         MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
639         if (write)
640                 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
641
642         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
643                                    !!write);
644         if (err)
645                 goto out;
646
647         if (!write) {
648                 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
649                 pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
650                                                        max_mtu));
651                 pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
652                                                          admin_mtu));
653                 pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
654                                                         oper_mtu));
655         }
656
657 out:
658         kvfree(in);
659         kvfree(out);
660         return err;
661 }
662 EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
663
664 int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
665 {
666         u32 in[MLX5_ST_SZ_DW(pmlp_reg)];
667         u32 out[MLX5_ST_SZ_DW(pmlp_reg)];
668         int lane = 0;
669         int err;
670
671         memset(in, 0, sizeof(in));
672
673         MLX5_SET(pmlp_reg, in, local_port, 1);
674
675         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
676                                    sizeof(out), MLX5_REG_PMLP, 0, 0);
677         if (err)
678                 return err;
679
680         lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
681         *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
682
683         return 0;
684 }
685 EXPORT_SYMBOL_GPL(mlx5_query_module_num);
686
687 int mlx5_query_eeprom(struct mlx5_core_dev *dev,
688                       int i2c_addr, int page_num, int device_addr,
689                       int size, int module_num, u32 *data, int *size_read)
690 {
691         u32 in[MLX5_ST_SZ_DW(mcia_reg)];
692         u32 out[MLX5_ST_SZ_DW(mcia_reg)];
693         u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
694         int status;
695         int err;
696
697         memset(in, 0, sizeof(in));
698         size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
699
700         MLX5_SET(mcia_reg, in, l, 0);
701         MLX5_SET(mcia_reg, in, module, module_num);
702         MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
703         MLX5_SET(mcia_reg, in, page_number, page_num);
704         MLX5_SET(mcia_reg, in, device_address, device_addr);
705         MLX5_SET(mcia_reg, in, size, size);
706
707         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
708                                    sizeof(out), MLX5_REG_MCIA, 0, 0);
709         if (err)
710                 return err;
711
712         status = MLX5_GET(mcia_reg, out, status);
713         if (status)
714                 return status;
715
716         memcpy(data, ptr, size);
717         *size_read = size;
718         return 0;
719 }
720 EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
721
722 int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
723 {
724         u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)];
725         u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)];
726         int err;
727
728         memset(in, 0, sizeof(in));
729         memset(out, 0, sizeof(out));
730
731         MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
732                  MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
733         MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
734
735         err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
736         if (err) {
737                 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
738                               mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
739                               port, err);
740         }
741
742         return err;
743 }
744
745 int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
746 {
747         u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)];
748         u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)];
749         int err;
750
751         memset(in, 0, sizeof(in));
752         memset(out, 0, sizeof(out));
753
754         MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
755                  MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
756         MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
757
758         err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
759         if (err) {
760                 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
761                               mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
762                               port, err);
763         }
764
765         return err;
766 }
767
768 int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
769 {
770         u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)];
771         u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)];
772         int err;
773
774         memset(in, 0, sizeof(in));
775         memset(out, 0, sizeof(out));
776
777         MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
778
779         err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
780
781         if (!err)
782                 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
783
784         return err;
785 }
786 EXPORT_SYMBOL_GPL(mlx5_query_wol);
787
788 int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
789                                 int priority, int *is_enable)
790 {
791         u32 in[MLX5_ST_SZ_DW(query_cong_status_in)];
792         u32 out[MLX5_ST_SZ_DW(query_cong_status_out)];
793         int err;
794
795         memset(in, 0, sizeof(in));
796         memset(out, 0, sizeof(out));
797
798         *is_enable = 0;
799
800         MLX5_SET(query_cong_status_in, in, opcode,
801                  MLX5_CMD_OP_QUERY_CONG_STATUS);
802         MLX5_SET(query_cong_status_in, in, cong_protocol, protocol);
803         MLX5_SET(query_cong_status_in, in, priority, priority);
804
805         err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
806                                          out, sizeof(out));
807         if (!err)
808                 *is_enable = MLX5_GET(query_cong_status_out, out, enable);
809         return err;
810 }
811
812 int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
813                                  int priority, int enable)
814 {
815         u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)];
816         u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)];
817
818         memset(in, 0, sizeof(in));
819         memset(out, 0, sizeof(out));
820
821         MLX5_SET(modify_cong_status_in, in, opcode,
822                  MLX5_CMD_OP_MODIFY_CONG_STATUS);
823         MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
824         MLX5_SET(modify_cong_status_in, in, priority, priority);
825         MLX5_SET(modify_cong_status_in, in, enable, enable);
826
827         return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
828                                           out, sizeof(out));
829 }
830
831 int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
832                                 void *out, int out_size)
833 {
834         u32 in[MLX5_ST_SZ_DW(query_cong_params_in)];
835
836         memset(in, 0, sizeof(in));
837
838         MLX5_SET(query_cong_params_in, in, opcode,
839                  MLX5_CMD_OP_QUERY_CONG_PARAMS);
840         MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
841
842         return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
843                                           out, out_size);
844 }
845
846 int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
847                                  void *in, int in_size)
848 {
849         u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)];
850
851         memset(out, 0, sizeof(out));
852
853         MLX5_SET(modify_cong_params_in, in, opcode,
854                  MLX5_CMD_OP_MODIFY_CONG_PARAMS);
855
856         return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out));
857 }
858
859 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
860                                     void *out, int out_size)
861 {
862         u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)];
863
864         memset(in, 0, sizeof(in));
865
866         MLX5_SET(query_cong_statistics_in, in, opcode,
867                  MLX5_CMD_OP_QUERY_CONG_STATISTICS);
868         MLX5_SET(query_cong_statistics_in, in, clear, clear);
869
870         return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
871                                           out, out_size);
872 }
873
874 int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
875                                int in_size)
876 {
877         u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)];
878
879         memset(out, 0, sizeof(out));
880
881         MLX5_SET(set_diagnostic_params_in, in, opcode,
882                  MLX5_CMD_OP_SET_DIAGNOSTICS);
883
884         return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out));
885 }
886
887 int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
888                                    u8 num_of_samples, u16 sample_index,
889                                    void *out, int out_size)
890 {
891         u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)];
892
893         memset(in, 0, sizeof(in));
894
895         MLX5_SET(query_diagnostic_counters_in, in, opcode,
896                  MLX5_CMD_OP_QUERY_DIAGNOSTICS);
897         MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
898                  num_of_samples);
899         MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
900
901         return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, out_size);
902 }