]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mlx5/mlx5_core/mlx5_port.c
MFS r353184, r353186, r353188, r353190, r353192, r353194, r353196, r353198,
[FreeBSD/FreeBSD.git] / sys / dev / mlx5 / mlx5_core / mlx5_port.c
1 /*-
2  * Copyright (c) 2013-2018, 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/port.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         int outlen = MLX5_ST_SZ_BYTES(access_register_out) + size_out;
37         int inlen = MLX5_ST_SZ_BYTES(access_register_in) + size_in;
38         int err = -ENOMEM;
39         u32 *out = NULL;
40         u32 *in = NULL;
41         void *data;
42
43         in = mlx5_vzalloc(inlen);
44         out = mlx5_vzalloc(outlen);
45         if (!in || !out)
46                 goto out;
47
48         data = MLX5_ADDR_OF(access_register_in, in, register_data);
49         memcpy(data, data_in, size_in);
50
51         MLX5_SET(access_register_in, in, opcode, MLX5_CMD_OP_ACCESS_REG);
52         MLX5_SET(access_register_in, in, op_mod, !write);
53         MLX5_SET(access_register_in, in, argument, arg);
54         MLX5_SET(access_register_in, in, register_id, reg_num);
55
56         err = mlx5_cmd_exec(dev, in, inlen, out, outlen);
57         if (err)
58                 goto out;
59         data = MLX5_ADDR_OF(access_register_out, out, register_data);
60         memcpy(data_out, data, size_out);
61
62 out:
63         kvfree(out);
64         kvfree(in);
65         return err;
66 }
67 EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
68
69 int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam,
70                         u8 feature_group, u8 access_reg_group)
71 {
72         u32 in[MLX5_ST_SZ_DW(qcam_reg)] = {};
73         int sz = MLX5_ST_SZ_BYTES(qcam_reg);
74
75         MLX5_SET(qcam_reg, in, feature_group, feature_group);
76         MLX5_SET(qcam_reg, in, access_reg_group, access_reg_group);
77
78         return mlx5_core_access_reg(mdev, in, sz, qcam, sz, MLX5_REG_QCAM, 0, 0);
79 }
80 EXPORT_SYMBOL_GPL(mlx5_query_qcam_reg);
81
82 int mlx5_query_pcam_reg(struct mlx5_core_dev *dev, u32 *pcam, u8 feature_group,
83                         u8 access_reg_group)
84 {
85         u32 in[MLX5_ST_SZ_DW(pcam_reg)] = {};
86         int sz = MLX5_ST_SZ_BYTES(pcam_reg);
87
88         MLX5_SET(pcam_reg, in, feature_group, feature_group);
89         MLX5_SET(pcam_reg, in, access_reg_group, access_reg_group);
90
91         return mlx5_core_access_reg(dev, in, sz, pcam, sz, MLX5_REG_PCAM, 0, 0);
92 }
93
94 int mlx5_query_mcam_reg(struct mlx5_core_dev *dev, u32 *mcam, u8 feature_group,
95                         u8 access_reg_group)
96 {
97         u32 in[MLX5_ST_SZ_DW(mcam_reg)] = {};
98         int sz = MLX5_ST_SZ_BYTES(mcam_reg);
99
100         MLX5_SET(mcam_reg, in, feature_group, feature_group);
101         MLX5_SET(mcam_reg, in, access_reg_group, access_reg_group);
102
103         return mlx5_core_access_reg(dev, in, sz, mcam, sz, MLX5_REG_MCAM, 0, 0);
104 }
105
106 struct mlx5_reg_pcap {
107         u8                      rsvd0;
108         u8                      port_num;
109         u8                      rsvd1[2];
110         __be32                  caps_127_96;
111         __be32                  caps_95_64;
112         __be32                  caps_63_32;
113         __be32                  caps_31_0;
114 };
115
116 /* This function should be used after setting a port register only */
117 void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
118 {
119         enum mlx5_port_status ps;
120
121         mlx5_query_port_admin_status(dev, &ps);
122         mlx5_set_port_status(dev, MLX5_PORT_DOWN);
123         if (ps == MLX5_PORT_UP)
124                 mlx5_set_port_status(dev, MLX5_PORT_UP);
125 }
126 EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
127
128 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
129 {
130         struct mlx5_reg_pcap in;
131         struct mlx5_reg_pcap out;
132         int err;
133
134         memset(&in, 0, sizeof(in));
135         in.caps_127_96 = cpu_to_be32(caps);
136         in.port_num = port_num;
137
138         err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
139                                    sizeof(out), MLX5_REG_PCAP, 0, 1);
140
141         return err;
142 }
143 EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
144
145 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
146                          int ptys_size, int proto_mask, u8 local_port)
147 {
148         u32 in[MLX5_ST_SZ_DW(ptys_reg)];
149         int err;
150
151         memset(in, 0, sizeof(in));
152         MLX5_SET(ptys_reg, in, local_port, local_port);
153         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
154
155         err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
156                                    ptys_size, MLX5_REG_PTYS, 0, 0);
157
158         return err;
159 }
160 EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
161
162 int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
163                               u32 *proto_cap, int proto_mask)
164 {
165         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
166         int err;
167
168         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
169         if (err)
170                 return err;
171
172         if (proto_mask == MLX5_PTYS_EN)
173                 *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
174         else
175                 *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
176
177         return 0;
178 }
179 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
180
181 int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
182                             u8 *an_disable_cap, u8 *an_disable_status)
183 {
184         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
185         int err;
186
187         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
188         if (err)
189                 return err;
190
191         *an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin);
192         *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
193
194         return 0;
195 }
196 EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
197
198 int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable,
199                           u32 eth_proto_admin, int proto_mask)
200 {
201         u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
202         u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
203         u8 an_disable_cap;
204         u8 an_disable_status;
205         int err;
206
207         err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap,
208                                       &an_disable_status);
209         if (err)
210                 return err;
211         if (!an_disable_cap)
212                 return -EPERM;
213
214         MLX5_SET(ptys_reg, in, local_port, 1);
215         MLX5_SET(ptys_reg, in, an_disable_admin, disable);
216         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
217         if (proto_mask == MLX5_PTYS_EN)
218                 MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin);
219
220         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
221                                    sizeof(out), MLX5_REG_PTYS, 0, 1);
222         return err;
223 }
224 EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
225
226 int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
227                                 u32 *proto_admin, int proto_mask)
228 {
229         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
230         int err;
231
232         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
233         if (err)
234                 return err;
235
236         if (proto_mask == MLX5_PTYS_EN)
237                 *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
238         else
239                 *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
240
241         return 0;
242 }
243 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
244
245 int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
246                                    u32 *proto_oper, u8 local_port)
247 {
248         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
249         int err;
250
251         err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
252                                    local_port);
253         if (err)
254                 return err;
255
256         *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
257
258         return 0;
259 }
260 EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
261
262 int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
263                         int proto_mask, bool ext)
264 {
265         u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
266         u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
267         int err;
268
269         MLX5_SET(ptys_reg, in, local_port, 1);
270         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
271         if (proto_mask == MLX5_PTYS_EN) {
272                 if (ext)
273                         MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin);
274                 else
275                         MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
276         } else {
277                 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
278         }
279
280         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
281                                    sizeof(out), MLX5_REG_PTYS, 0, 1);
282         return err;
283 }
284 EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
285
286 int mlx5_set_port_status(struct mlx5_core_dev *dev,
287                          enum mlx5_port_status status)
288 {
289         u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
290         u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
291         int err;
292
293         MLX5_SET(paos_reg, in, local_port, 1);
294
295         MLX5_SET(paos_reg, in, admin_status, status);
296         MLX5_SET(paos_reg, in, ase, 1);
297
298         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
299                                    sizeof(out), MLX5_REG_PAOS, 0, 1);
300         return err;
301 }
302
303 int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
304 {
305         u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
306         u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
307         int err;
308
309         MLX5_SET(paos_reg, in, local_port, 1);
310
311         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
312                                    sizeof(out), MLX5_REG_PAOS, 0, 0);
313         if (err)
314                 return err;
315
316         *status = MLX5_GET(paos_reg, out, oper_status);
317         return err;
318 }
319
320 int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
321                                  enum mlx5_port_status *status)
322 {
323         u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
324         u32 out[MLX5_ST_SZ_DW(paos_reg)];
325         int err;
326
327         MLX5_SET(paos_reg, in, local_port, 1);
328         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
329                                    sizeof(out), MLX5_REG_PAOS, 0, 0);
330         if (err)
331                 return err;
332         *status = MLX5_GET(paos_reg, out, admin_status);
333         return 0;
334 }
335 EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
336
337 static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
338                                int *admin_mtu, int *max_mtu, int *oper_mtu)
339 {
340         u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
341         u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
342         int err;
343
344         MLX5_SET(pmtu_reg, in, local_port, 1);
345
346         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
347                                    sizeof(out), MLX5_REG_PMTU, 0, 0);
348         if (err)
349                 return err;
350
351         if (max_mtu)
352                 *max_mtu  = MLX5_GET(pmtu_reg, out, max_mtu);
353         if (oper_mtu)
354                 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
355         if (admin_mtu)
356                 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
357
358         return err;
359 }
360
361 int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
362 {
363         u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
364         u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
365
366         MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
367         MLX5_SET(pmtu_reg, in, local_port, 1);
368
369         return mlx5_core_access_reg(dev, in, sizeof(in), out,
370                                    sizeof(out), MLX5_REG_PMTU, 0, 1);
371 }
372 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
373
374 int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
375 {
376         return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
377 }
378 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
379
380 int mlx5_set_port_pause_and_pfc(struct mlx5_core_dev *dev, u32 port,
381                                 u8 rx_pause, u8 tx_pause,
382                                 u8 pfc_en_rx, u8 pfc_en_tx)
383 {
384         u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
385         u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
386
387         if (pfc_en_rx || pfc_en_tx) {
388                 /* PFC and global pauseframes are incompatible features */
389                 if (tx_pause || rx_pause)
390                         return -EINVAL;
391         }
392
393         MLX5_SET(pfcc_reg, in, local_port, port);
394         MLX5_SET(pfcc_reg, in, pptx, tx_pause);
395         MLX5_SET(pfcc_reg, in, pprx, rx_pause);
396         MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx);
397         MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx);
398         MLX5_SET(pfcc_reg, in, prio_mask_tx, pfc_en_tx);
399         MLX5_SET(pfcc_reg, in, prio_mask_rx, pfc_en_rx);
400
401         return mlx5_core_access_reg(dev, in, sizeof(in), out,
402                                    sizeof(out), MLX5_REG_PFCC, 0, 1);
403 }
404
405 int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
406                           u32 *rx_pause, u32 *tx_pause)
407 {
408         u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
409         u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
410         int err;
411
412         MLX5_SET(pfcc_reg, in, local_port, port);
413
414         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
415                                    sizeof(out), MLX5_REG_PFCC, 0, 0);
416         if (err)
417                 return err;
418
419         *rx_pause = MLX5_GET(pfcc_reg, out, pprx);
420         *tx_pause = MLX5_GET(pfcc_reg, out, pptx);
421
422         return 0;
423 }
424
425 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
426 {
427         u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {};
428         u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
429         int err;
430
431         MLX5_SET(pfcc_reg, in, local_port, 1);
432         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
433                                    sizeof(out), MLX5_REG_PFCC, 0, 0);
434         if (err)
435                 return err;
436
437         if (pfc_en_tx != NULL)
438                 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx);
439         if (pfc_en_rx != NULL)
440                 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx);
441         return 0;
442 }
443 EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
444
445 int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
446 {
447         return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
448 }
449 EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
450
451 u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
452 {
453         u8 wol_supported = 0;
454
455         if (MLX5_CAP_GEN(dev, wol_s))
456                 wol_supported |= MLX5_WOL_SECURED_MAGIC;
457         if (MLX5_CAP_GEN(dev, wol_g))
458                 wol_supported |= MLX5_WOL_MAGIC;
459         if (MLX5_CAP_GEN(dev, wol_a))
460                 wol_supported |= MLX5_WOL_ARP;
461         if (MLX5_CAP_GEN(dev, wol_b))
462                 wol_supported |= MLX5_WOL_BROADCAST;
463         if (MLX5_CAP_GEN(dev, wol_m))
464                 wol_supported |= MLX5_WOL_MULTICAST;
465         if (MLX5_CAP_GEN(dev, wol_u))
466                 wol_supported |= MLX5_WOL_UNICAST;
467         if (MLX5_CAP_GEN(dev, wol_p))
468                 wol_supported |= MLX5_WOL_PHY_ACTIVITY;
469
470         return wol_supported;
471 }
472 EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
473
474 int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
475 {
476         u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0};
477         u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0};
478
479         MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
480         MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
481         MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
482
483         return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
484 }
485 EXPORT_SYMBOL_GPL(mlx5_set_wol);
486
487 int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout)
488 {
489         u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)] = {0};
490         u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)] = {0};
491         int err = 0;
492
493         MLX5_SET(query_delay_drop_params_in, in, opcode,
494                  MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS);
495
496         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
497         if (err)
498                 return err;
499
500         *timeout = MLX5_GET(query_delay_drop_params_out, out,
501                             delay_drop_timeout);
502
503         return 0;
504 }
505 EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
506
507 int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout)
508 {
509         u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)] = {0};
510         u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)] = {0};
511
512         MLX5_SET(set_delay_drop_params_in, in, opcode,
513                  MLX5_CMD_OP_SET_DELAY_DROP_PARAMS);
514         MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout);
515
516         return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
517 }
518 EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
519
520 int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
521                           struct mlx5_pvlc_reg *pvlc, int write)
522 {
523         int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
524         u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
525         u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
526         int err;
527
528         MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
529         if (write)
530                 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
531
532         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
533                                    !!write);
534         if (err)
535                 return err;
536
537         if (!write) {
538                 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
539                 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
540                 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
541                 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
542         }
543
544         return 0;
545 }
546 EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
547
548 int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
549                           struct mlx5_ptys_reg *ptys, int write)
550 {
551         int sz = MLX5_ST_SZ_BYTES(ptys_reg);
552         void *out = NULL;
553         void *in = NULL;
554         int err;
555
556         in = mlx5_vzalloc(sz);
557         if (!in)
558                 return -ENOMEM;
559
560         out = mlx5_vzalloc(sz);
561         if (!out) {
562                 kfree(in);
563                 return -ENOMEM;
564         }
565
566         MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
567         MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
568         if (write) {
569                 MLX5_SET(ptys_reg, in, eth_proto_capability,
570                          ptys->eth_proto_cap);
571                 MLX5_SET(ptys_reg, in, ib_link_width_capability,
572                          ptys->ib_link_width_cap);
573                 MLX5_SET(ptys_reg, in, ib_proto_capability,
574                          ptys->ib_proto_cap);
575                 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
576                 MLX5_SET(ptys_reg, in, ib_link_width_admin,
577                          ptys->ib_link_width_admin);
578                 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
579                 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
580                 MLX5_SET(ptys_reg, in, ib_link_width_oper,
581                          ptys->ib_link_width_oper);
582                 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
583                 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
584                          ptys->eth_proto_lp_advertise);
585         }
586
587         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
588                                    !!write);
589         if (err)
590                 goto out;
591
592         if (!write) {
593                 ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
594                 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
595                 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
596                                                eth_proto_capability);
597                 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
598                                            ib_link_width_capability);
599                 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
600                                               ib_proto_capability);
601                 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
602                                                  eth_proto_admin);
603                 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
604                                                      ib_link_width_admin);
605                 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
606                 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
607                 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
608                                                     ib_link_width_oper);
609                 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
610                 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
611                                                         eth_proto_lp_advertise);
612         }
613
614 out:
615         kvfree(in);
616         kvfree(out);
617         return err;
618 }
619 EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
620
621 static int mtu_to_ib_mtu(struct mlx5_core_dev *dev, int mtu)
622 {
623         switch (mtu) {
624         case 256: return 1;
625         case 512: return 2;
626         case 1024: return 3;
627         case 2048: return 4;
628         case 4096: return 5;
629         default:
630                 mlx5_core_warn(dev, "invalid mtu\n");
631                 return -1;
632         }
633 }
634
635 int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
636                           struct mlx5_pmtu_reg *pmtu, int write)
637 {
638         int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
639         void *out = NULL;
640         void *in = NULL;
641         int err;
642
643         in = mlx5_vzalloc(sz);
644         if (!in)
645                 return -ENOMEM;
646
647         out = mlx5_vzalloc(sz);
648         if (!out) {
649                 kfree(in);
650                 return -ENOMEM;
651         }
652
653         MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
654         if (write)
655                 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
656
657         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
658                                    !!write);
659         if (err)
660                 goto out;
661
662         if (!write) {
663                 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
664                 pmtu->max_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
665                                                        max_mtu));
666                 pmtu->admin_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
667                                                          admin_mtu));
668                 pmtu->oper_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
669                                                         oper_mtu));
670         }
671
672 out:
673         kvfree(in);
674         kvfree(out);
675         return err;
676 }
677 EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
678
679 int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
680 {
681         u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
682         u32 out[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
683         int lane = 0;
684         int err;
685
686         MLX5_SET(pmlp_reg, in, local_port, 1);
687
688         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
689                                    sizeof(out), MLX5_REG_PMLP, 0, 0);
690         if (err)
691                 return err;
692
693         lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
694         *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
695
696         return 0;
697 }
698 EXPORT_SYMBOL_GPL(mlx5_query_module_num);
699
700 int mlx5_query_eeprom(struct mlx5_core_dev *dev,
701                       int i2c_addr, int page_num, int device_addr,
702                       int size, int module_num, u32 *data, int *size_read)
703 {
704         u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {0};
705         u32 out[MLX5_ST_SZ_DW(mcia_reg)] = {0};
706         u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
707         int status;
708         int err;
709
710         size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
711
712         MLX5_SET(mcia_reg, in, l, 0);
713         MLX5_SET(mcia_reg, in, module, module_num);
714         MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
715         MLX5_SET(mcia_reg, in, page_number, page_num);
716         MLX5_SET(mcia_reg, in, device_address, device_addr);
717         MLX5_SET(mcia_reg, in, size, size);
718
719         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
720                                    sizeof(out), MLX5_REG_MCIA, 0, 0);
721         if (err)
722                 return err;
723
724         status = MLX5_GET(mcia_reg, out, status);
725         if (status)
726                 return status;
727
728         memcpy(data, ptr, size);
729         *size_read = size;
730         return 0;
731 }
732 EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
733
734 int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
735 {
736         u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0};
737         u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)] = {0};
738         int err;
739
740         MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
741                  MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
742         MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
743
744         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
745         if (err) {
746                 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
747                               mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
748                               port, err);
749         }
750
751         return err;
752 }
753
754 int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
755 {
756         u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {0};
757         u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)] = {0};
758         int err;
759
760         MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
761                  MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
762         MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
763
764         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
765         if (err) {
766                 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
767                               mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
768                               port, err);
769         }
770
771         return err;
772 }
773
774 int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
775 {
776         u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0};
777         u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0};
778         int err;
779
780         MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
781
782         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
783
784         if (!err)
785                 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
786
787         return err;
788 }
789 EXPORT_SYMBOL_GPL(mlx5_query_wol);
790
791 int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
792                                 int priority, int *is_enable)
793 {
794         u32 in[MLX5_ST_SZ_DW(query_cong_status_in)] = {0};
795         u32 out[MLX5_ST_SZ_DW(query_cong_status_out)] = {0};
796         int err;
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(mdev, in, sizeof(in), out, sizeof(out));
806         if (!err)
807                 *is_enable = MLX5_GET(query_cong_status_out, out, enable);
808         return err;
809 }
810
811 int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
812                                  int priority, int enable)
813 {
814         u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)] = {0};
815         u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)] = {0};
816
817         MLX5_SET(modify_cong_status_in, in, opcode,
818                  MLX5_CMD_OP_MODIFY_CONG_STATUS);
819         MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
820         MLX5_SET(modify_cong_status_in, in, priority, priority);
821         MLX5_SET(modify_cong_status_in, in, enable, enable);
822
823         return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
824 }
825
826 int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
827                                 void *out, int out_size)
828 {
829         u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = {0};
830
831         MLX5_SET(query_cong_params_in, in, opcode,
832                  MLX5_CMD_OP_QUERY_CONG_PARAMS);
833         MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
834
835         return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
836 }
837
838 static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out,
839                                      int outlen)
840 {
841         u32 in[MLX5_ST_SZ_DW(qetc_reg)];
842
843         if (!MLX5_CAP_GEN(mdev, ets))
844                 return -ENOTSUPP;
845
846         memset(in, 0, sizeof(in));
847         return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen,
848                                     MLX5_REG_QETCR, 0, 0);
849 }
850
851 int mlx5_max_tc(struct mlx5_core_dev *mdev)
852 {
853         u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8;
854
855         return num_tc - 1;
856 }
857 EXPORT_SYMBOL_GPL(mlx5_max_tc);
858
859 static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
860                                    int inlen)
861 {
862         u32 out[MLX5_ST_SZ_DW(qetc_reg)];
863
864         if (!MLX5_CAP_GEN(mdev, ets))
865                 return -ENOTSUPP;
866
867         return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out),
868                                     MLX5_REG_QETCR, 0, 1);
869 }
870
871 int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev,
872                                    u8 *max_bw_value,
873                                    u8 *max_bw_units)
874 {
875         u32 out[MLX5_ST_SZ_DW(qetc_reg)];
876         void *ets_tcn_conf;
877         int err;
878         int i;
879
880         err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
881         if (err)
882                 return err;
883
884         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
885                 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
886
887                 max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
888                                            max_bw_value);
889                 max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
890                                            max_bw_units);
891         }
892
893         return 0;
894 }
895 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit);
896
897 int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev,
898                                    const u8 *max_bw_value,
899                                    const u8 *max_bw_units)
900 {
901         u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
902         void *ets_tcn_conf;
903         int i;
904
905         MLX5_SET(qetc_reg, in, port_number, 1);
906
907         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
908                 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]);
909
910                 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1);
911                 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units,
912                          max_bw_units[i]);
913                 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value,
914                          max_bw_value[i]);
915         }
916
917         return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
918 }
919 EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit);
920
921 int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
922                             u8 prio, u8 *tc)
923 {
924         u32 in[MLX5_ST_SZ_DW(qtct_reg)];
925         u32 out[MLX5_ST_SZ_DW(qtct_reg)];
926         int err;
927
928         memset(in, 0, sizeof(in));
929         memset(out, 0, sizeof(out));
930
931         MLX5_SET(qtct_reg, in, port_number, 1);
932         MLX5_SET(qtct_reg, in, prio, prio);
933
934         err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
935                                    sizeof(out), MLX5_REG_QTCT, 0, 0);
936         if (!err)
937                 *tc = MLX5_GET(qtct_reg, out, tclass);
938
939         return err;
940 }
941 EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
942
943 int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index,
944                           const u8 prio_tc)
945 {
946         u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {};
947         u32 out[MLX5_ST_SZ_DW(qtct_reg)];
948         int err;
949
950         if (prio_tc > mlx5_max_tc(mdev))
951                 return -EINVAL;
952
953         MLX5_SET(qtct_reg, in, prio, prio_index);
954         MLX5_SET(qtct_reg, in, tclass, prio_tc);
955
956         err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
957                                    sizeof(out), MLX5_REG_QTCT, 0, 1);
958
959         return (err);
960 }
961 EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
962
963 int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, const u8 *tc_group)
964 {
965         u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
966         int i;
967
968         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
969                 MLX5_SET(qetc_reg, in, tc_configuration[i].g, 1);
970                 MLX5_SET(qetc_reg, in, tc_configuration[i].group, tc_group[i]);
971         }
972
973         return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
974 }
975 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group);
976
977 int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev,
978                              u8 tc, u8 *tc_group)
979 {
980         u32 out[MLX5_ST_SZ_DW(qetc_reg)];
981         void *ets_tcn_conf;
982         int err;
983
984         err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
985         if (err)
986                 return err;
987
988         ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
989                                     tc_configuration[tc]);
990
991         *tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
992                              group);
993
994         return 0;
995 }
996 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group);
997
998 int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, const u8 *tc_bw)
999 {
1000         u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
1001         int i;
1002
1003         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
1004                 MLX5_SET(qetc_reg, in, tc_configuration[i].b, 1);
1005                 MLX5_SET(qetc_reg, in, tc_configuration[i].bw_allocation, tc_bw[i]);
1006         }
1007
1008         return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
1009 }
1010 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc);
1011
1012 int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *bw_pct)
1013 {
1014         u32 out[MLX5_ST_SZ_DW(qetc_reg)];
1015         void *ets_tcn_conf;
1016         int err;
1017         int i;
1018
1019         err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
1020         if (err)
1021                 return err;
1022
1023         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
1024                 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
1025                 bw_pct[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, bw_allocation);
1026         }
1027         return 0;
1028 }
1029 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc);
1030
1031 int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
1032                                  void *in, int in_size)
1033 {
1034         u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0};
1035
1036         MLX5_SET(modify_cong_params_in, in, opcode,
1037                  MLX5_CMD_OP_MODIFY_CONG_PARAMS);
1038
1039         return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
1040 }
1041
1042 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
1043                                     void *out, int out_size)
1044 {
1045         u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0};
1046
1047         MLX5_SET(query_cong_statistics_in, in, opcode,
1048                  MLX5_CMD_OP_QUERY_CONG_STATISTICS);
1049         MLX5_SET(query_cong_statistics_in, in, clear, clear);
1050
1051         return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1052 }
1053
1054 int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
1055                                int in_size)
1056 {
1057         u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0};
1058
1059         MLX5_SET(set_diagnostic_params_in, in, opcode,
1060                  MLX5_CMD_OP_SET_DIAGNOSTICS);
1061
1062         return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
1063 }
1064
1065 int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
1066                                    u8 num_of_samples, u16 sample_index,
1067                                    void *out, int out_size)
1068 {
1069         u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0};
1070
1071         MLX5_SET(query_diagnostic_counters_in, in, opcode,
1072                  MLX5_CMD_OP_QUERY_DIAGNOSTICS);
1073         MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
1074                  num_of_samples);
1075         MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
1076
1077         return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1078 }
1079
1080 int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state)
1081 {
1082         u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1083         u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1084         int err;
1085
1086         MLX5_SET(qpts_reg, in, local_port, 1);
1087         MLX5_SET(qpts_reg, in, trust_state, trust_state);
1088
1089         err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1090                                    sizeof(out), MLX5_REG_QPTS, 0, 1);
1091         return err;
1092 }
1093
1094 int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
1095 {
1096         u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1097         u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1098         int err;
1099
1100         MLX5_SET(qpts_reg, in, local_port, 1);
1101
1102         err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1103                                    sizeof(out), MLX5_REG_QPTS, 0, 0);
1104         if (!err)
1105                 *trust_state = MLX5_GET(qpts_reg, out, trust_state);
1106
1107         return err;
1108 }
1109
1110 int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio)
1111 {
1112         int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1113         void *qpdpm_dscp;
1114         void *out;
1115         void *in;
1116         int err;
1117         int i;
1118
1119         in = kzalloc(sz, GFP_KERNEL);
1120         out = kzalloc(sz, GFP_KERNEL);
1121         if (!in || !out) {
1122                 err = -ENOMEM;
1123                 goto out;
1124         }
1125
1126         MLX5_SET(qpdpm_reg, in, local_port, 1);
1127         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1128         if (err)
1129                 goto out;
1130
1131         memcpy(in, out, sz);
1132         MLX5_SET(qpdpm_reg, in, local_port, 1);
1133
1134         /* Update the corresponding dscp entry */
1135         for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1136                 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[i]);
1137                 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, dscp2prio[i]);
1138                 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1);
1139         }
1140         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
1141 out:
1142         kfree(in);
1143         kfree(out);
1144         return err;
1145 }
1146
1147 int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
1148 {
1149         int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1150         void *qpdpm_dscp;
1151         void *out;
1152         void *in;
1153         int err;
1154         int i;
1155
1156         in = kzalloc(sz, GFP_KERNEL);
1157         out = kzalloc(sz, GFP_KERNEL);
1158         if (!in || !out) {
1159                 err = -ENOMEM;
1160                 goto out;
1161         }
1162
1163         MLX5_SET(qpdpm_reg, in, local_port, 1);
1164         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1165         if (err)
1166                 goto out;
1167
1168         for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1169                 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]);
1170                 dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio);
1171         }
1172 out:
1173         kfree(in);
1174         kfree(out);
1175         return err;
1176 }
1177
1178 int mlx5_query_pddr_range_info(struct mlx5_core_dev *mdev, u8 local_port, u8 *is_er_type)
1179 {
1180         u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {};
1181         int sz = MLX5_ST_SZ_BYTES(pddr_reg);
1182         int error;
1183         u8 ecc;
1184         u8 ci;
1185
1186         MLX5_SET(pddr_reg, pddr_reg, local_port, local_port);
1187         MLX5_SET(pddr_reg, pddr_reg, page_select, 3 /* module info page */);
1188
1189         error = mlx5_core_access_reg(mdev, pddr_reg, sz, pddr_reg, sz,
1190             MLX5_ACCESS_REG_SUMMARY_CTRL_ID_PDDR, 0, 0);
1191         if (error != 0)
1192                 return (error);
1193
1194         ecc = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.ethernet_compliance_code);
1195         ci = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.cable_identifier);
1196
1197         switch (ci) {
1198         case 0: /* QSFP28 */
1199         case 1: /* QSFP+ */
1200                 *is_er_type = 0;
1201                 break;
1202         case 2: /* SFP28/SFP+ */
1203         case 3: /* QSA (QSFP->SFP) */
1204                 *is_er_type = ((ecc & (1 << 7)) != 0);
1205                 break;
1206         default:
1207                 *is_er_type = 0;
1208                 break;
1209         }
1210         return (0);
1211 }
1212 EXPORT_SYMBOL_GPL(mlx5_query_pddr_range_info);
1213
1214 int
1215 mlx5_query_mfrl_reg(struct mlx5_core_dev *mdev, u8 *reset_level)
1216 {
1217         u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {};
1218         int sz = MLX5_ST_SZ_BYTES(mfrl_reg);
1219         int err;
1220
1221         err = mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL,
1222             0, 0);
1223         if (err == 0)
1224                 *reset_level = MLX5_GET(mfrl_reg, mfrl, reset_level);
1225         return (err);
1226 }
1227
1228 int
1229 mlx5_set_mfrl_reg(struct mlx5_core_dev *mdev, u8 reset_level)
1230 {
1231         u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {};
1232         int sz = MLX5_ST_SZ_BYTES(mfrl_reg);
1233
1234         MLX5_SET(mfrl_reg, mfrl, reset_level, reset_level);
1235
1236         return (mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL,
1237             0, 1));
1238 }
1239
1240 /* speed in units of 1Mb */
1241 static const u32 mlx5e_link_speed[/*MLX5E_LINK_MODES_NUMBER*/] = {
1242         [MLX5E_1000BASE_CX_SGMII] = 1000,
1243         [MLX5E_1000BASE_KX]       = 1000,
1244         [MLX5E_10GBASE_CX4]       = 10000,
1245         [MLX5E_10GBASE_KX4]       = 10000,
1246         [MLX5E_10GBASE_KR]        = 10000,
1247         [MLX5E_20GBASE_KR2]       = 20000,
1248         [MLX5E_40GBASE_CR4]       = 40000,
1249         [MLX5E_40GBASE_KR4]       = 40000,
1250         [MLX5E_56GBASE_R4]        = 56000,
1251         [MLX5E_10GBASE_CR]        = 10000,
1252         [MLX5E_10GBASE_SR]        = 10000,
1253         [MLX5E_10GBASE_ER_LR]     = 10000,
1254         [MLX5E_40GBASE_SR4]       = 40000,
1255         [MLX5E_40GBASE_LR4_ER4]   = 40000,
1256         [MLX5E_50GBASE_SR2]       = 50000,
1257         [MLX5E_100GBASE_CR4]      = 100000,
1258         [MLX5E_100GBASE_SR4]      = 100000,
1259         [MLX5E_100GBASE_KR4]      = 100000,
1260         [MLX5E_100GBASE_LR4]      = 100000,
1261         [MLX5E_100BASE_TX]        = 100,
1262         [MLX5E_1000BASE_T]        = 1000,
1263         [MLX5E_10GBASE_T]         = 10000,
1264         [MLX5E_25GBASE_CR]        = 25000,
1265         [MLX5E_25GBASE_KR]        = 25000,
1266         [MLX5E_25GBASE_SR]        = 25000,
1267         [MLX5E_50GBASE_CR2]       = 50000,
1268         [MLX5E_50GBASE_KR2]       = 50000,
1269 };
1270
1271 static const u32 mlx5e_ext_link_speed[/*MLX5E_EXT_LINK_MODES_NUMBER*/] = {
1272         [MLX5E_SGMII_100M]                      = 100,
1273         [MLX5E_1000BASE_X_SGMII]                = 1000,
1274         [MLX5E_5GBASE_R]                        = 5000,
1275         [MLX5E_10GBASE_XFI_XAUI_1]              = 10000,
1276         [MLX5E_40GBASE_XLAUI_4_XLPPI_4]         = 40000,
1277         [MLX5E_25GAUI_1_25GBASE_CR_KR]          = 25000,
1278         [MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2] = 50000,
1279         [MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR]   = 50000,
1280         [MLX5E_CAUI_4_100GBASE_CR4_KR4]         = 100000,
1281         [MLX5E_200GAUI_4_200GBASE_CR4_KR4]      = 200000,
1282         [MLX5E_400GAUI_8]                       = 400000,
1283 };
1284
1285 static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
1286                                      const u32 **arr, u32 *size)
1287 {
1288         bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
1289
1290         *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
1291                       ARRAY_SIZE(mlx5e_link_speed);
1292         *arr  = ext ? mlx5e_ext_link_speed : mlx5e_link_speed;
1293 }
1294
1295 u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
1296 {
1297         unsigned long temp = eth_proto_oper;
1298         const u32 *table;
1299         u32 speed = 0;
1300         u32 max_size;
1301         int i;
1302
1303         mlx5e_port_get_speed_arr(mdev, &table, &max_size);
1304         i = find_first_bit(&temp, max_size);
1305         if (i < max_size)
1306                 speed = table[i];
1307         return speed;
1308 }
1309
1310 int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
1311                               struct mlx5e_port_eth_proto *eproto)
1312 {
1313         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
1314         int err;
1315
1316         if (!eproto)
1317                 return -EINVAL;
1318
1319         err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
1320         if (err)
1321                 return err;
1322
1323         eproto->cap   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
1324                                            eth_proto_capability);
1325         eproto->admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_admin);
1326         eproto->oper  = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
1327         return 0;
1328 }
1329
1330 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
1331 {
1332         struct mlx5e_port_eth_proto eproto;
1333         bool ext;
1334         int err;
1335
1336         ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
1337         err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
1338         if (err)
1339                 goto out;
1340
1341         *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
1342         if (!(*speed))
1343                 err = -EINVAL;
1344
1345 out:
1346         return err;
1347 }
1348
1349 int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out)
1350 {
1351         int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
1352         void *in;
1353         int err;
1354
1355         in = kzalloc(sz, GFP_KERNEL);
1356         if (!in)
1357                 return -ENOMEM;
1358
1359         MLX5_SET(pbmc_reg, in, local_port, 1);
1360         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0);
1361
1362         kfree(in);
1363         return err;
1364 }
1365
1366 int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in)
1367 {
1368         int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
1369         void *out;
1370         int err;
1371
1372         out = kzalloc(sz, GFP_KERNEL);
1373         if (!out)
1374                 return -ENOMEM;
1375
1376         MLX5_SET(pbmc_reg, in, local_port, 1);
1377         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1);
1378
1379         kfree(out);
1380         return err;
1381 }
1382
1383 /* buffer[i]: buffer that priority i mapped to */
1384 int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
1385 {
1386         int sz = MLX5_ST_SZ_BYTES(pptb_reg);
1387         u32 prio_x_buff;
1388         void *out;
1389         void *in;
1390         int prio;
1391         int err;
1392
1393         in = kzalloc(sz, GFP_KERNEL);
1394         out = kzalloc(sz, GFP_KERNEL);
1395         if (!in || !out) {
1396                 err = -ENOMEM;
1397                 goto out;
1398         }
1399
1400         MLX5_SET(pptb_reg, in, local_port, 1);
1401         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
1402         if (err)
1403                 goto out;
1404
1405         prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff);
1406         for (prio = 0; prio < 8; prio++) {
1407                 buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF;
1408                 mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]);
1409         }
1410 out:
1411         kfree(in);
1412         kfree(out);
1413         return err;
1414 }
1415
1416 int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
1417 {
1418         int sz = MLX5_ST_SZ_BYTES(pptb_reg);
1419         u32 prio_x_buff;
1420         void *out;
1421         void *in;
1422         int prio;
1423         int err;
1424
1425         in = kzalloc(sz, GFP_KERNEL);
1426         out = kzalloc(sz, GFP_KERNEL);
1427         if (!in || !out) {
1428                 err = -ENOMEM;
1429                 goto out;
1430         }
1431
1432         /* First query the pptb register */
1433         MLX5_SET(pptb_reg, in, local_port, 1);
1434         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
1435         if (err)
1436                 goto out;
1437
1438         memcpy(in, out, sz);
1439         MLX5_SET(pptb_reg, in, local_port, 1);
1440
1441         /* Update the pm and prio_x_buff */
1442         MLX5_SET(pptb_reg, in, pm, 0xFF);
1443
1444         prio_x_buff = 0;
1445         for (prio = 0; prio < 8; prio++)
1446                 prio_x_buff |= (buffer[prio] << (4 * prio));
1447         MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff);
1448
1449         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1);
1450
1451 out:
1452         kfree(in);
1453         kfree(out);
1454         return err;
1455 }