2 * Copyright (c) 2013-2018, Mellanox Technologies, Ltd. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
28 #include <linux/module.h>
29 #include <dev/mlx5/port.h>
30 #include "mlx5_core.h"
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)
36 int outlen = MLX5_ST_SZ_BYTES(access_register_out) + size_out;
37 int inlen = MLX5_ST_SZ_BYTES(access_register_in) + size_in;
43 in = mlx5_vzalloc(inlen);
44 out = mlx5_vzalloc(outlen);
48 data = MLX5_ADDR_OF(access_register_in, in, register_data);
49 memcpy(data, data_in, size_in);
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);
56 err = mlx5_cmd_exec(dev, in, inlen, out, outlen);
59 data = MLX5_ADDR_OF(access_register_out, out, register_data);
60 memcpy(data_out, data, size_out);
67 EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
69 int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam,
70 u8 feature_group, u8 access_reg_group)
72 u32 in[MLX5_ST_SZ_DW(qcam_reg)] = {};
73 int sz = MLX5_ST_SZ_BYTES(qcam_reg);
75 MLX5_SET(qcam_reg, in, feature_group, feature_group);
76 MLX5_SET(qcam_reg, in, access_reg_group, access_reg_group);
78 return mlx5_core_access_reg(mdev, in, sz, qcam, sz, MLX5_REG_QCAM, 0, 0);
80 EXPORT_SYMBOL_GPL(mlx5_query_qcam_reg);
82 int mlx5_query_pcam_reg(struct mlx5_core_dev *dev, u32 *pcam, u8 feature_group,
85 u32 in[MLX5_ST_SZ_DW(pcam_reg)] = {};
86 int sz = MLX5_ST_SZ_BYTES(pcam_reg);
88 MLX5_SET(pcam_reg, in, feature_group, feature_group);
89 MLX5_SET(pcam_reg, in, access_reg_group, access_reg_group);
91 return mlx5_core_access_reg(dev, in, sz, pcam, sz, MLX5_REG_PCAM, 0, 0);
94 int mlx5_query_mcam_reg(struct mlx5_core_dev *dev, u32 *mcam, u8 feature_group,
97 u32 in[MLX5_ST_SZ_DW(mcam_reg)] = {};
98 int sz = MLX5_ST_SZ_BYTES(mcam_reg);
100 MLX5_SET(mcam_reg, in, feature_group, feature_group);
101 MLX5_SET(mcam_reg, in, access_reg_group, access_reg_group);
103 return mlx5_core_access_reg(dev, in, sz, mcam, sz, MLX5_REG_MCAM, 0, 0);
106 struct mlx5_reg_pcap {
116 /* This function should be used after setting a port register only */
117 void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
119 enum mlx5_port_status ps;
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);
126 EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
128 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
130 struct mlx5_reg_pcap in;
131 struct mlx5_reg_pcap out;
134 memset(&in, 0, sizeof(in));
135 in.caps_127_96 = cpu_to_be32(caps);
136 in.port_num = port_num;
138 err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
139 sizeof(out), MLX5_REG_PCAP, 0, 1);
143 EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
145 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
146 int ptys_size, int proto_mask, u8 local_port)
148 u32 in[MLX5_ST_SZ_DW(ptys_reg)];
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);
155 err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
156 ptys_size, MLX5_REG_PTYS, 0, 0);
160 EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
162 int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
163 u32 *proto_cap, int proto_mask)
165 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
168 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
172 if (proto_mask == MLX5_PTYS_EN)
173 *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
175 *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
179 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
181 int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
182 u8 *an_disable_cap, u8 *an_disable_status)
184 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
187 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
191 *an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin);
192 *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
196 EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
198 int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable,
199 u32 eth_proto_admin, int proto_mask)
201 u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
202 u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
204 u8 an_disable_status;
207 err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap,
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);
220 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
221 sizeof(out), MLX5_REG_PTYS, 0, 1);
224 EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
226 int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
227 u32 *proto_admin, int proto_mask)
229 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
232 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
236 if (proto_mask == MLX5_PTYS_EN)
237 *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
239 *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
243 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
245 int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
246 u32 *proto_oper, u8 local_port)
248 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
251 err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
256 *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
260 EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
262 int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
263 int proto_mask, bool ext)
265 u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
266 u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
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) {
273 MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin);
275 MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
277 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
280 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
281 sizeof(out), MLX5_REG_PTYS, 0, 1);
284 EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
286 int mlx5_set_port_status(struct mlx5_core_dev *dev,
287 enum mlx5_port_status status)
289 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
290 u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
293 MLX5_SET(paos_reg, in, local_port, 1);
295 MLX5_SET(paos_reg, in, admin_status, status);
296 MLX5_SET(paos_reg, in, ase, 1);
298 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
299 sizeof(out), MLX5_REG_PAOS, 0, 1);
303 int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
305 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
306 u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
309 MLX5_SET(paos_reg, in, local_port, 1);
311 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
312 sizeof(out), MLX5_REG_PAOS, 0, 0);
316 *status = MLX5_GET(paos_reg, out, oper_status);
320 int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
321 enum mlx5_port_status *status)
323 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
324 u32 out[MLX5_ST_SZ_DW(paos_reg)];
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);
332 *status = MLX5_GET(paos_reg, out, admin_status);
335 EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
337 static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
338 int *admin_mtu, int *max_mtu, int *oper_mtu)
340 u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
341 u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
344 MLX5_SET(pmtu_reg, in, local_port, 1);
346 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
347 sizeof(out), MLX5_REG_PMTU, 0, 0);
352 *max_mtu = MLX5_GET(pmtu_reg, out, max_mtu);
354 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
356 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
361 int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
363 u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
364 u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
366 MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
367 MLX5_SET(pmtu_reg, in, local_port, 1);
369 return mlx5_core_access_reg(dev, in, sizeof(in), out,
370 sizeof(out), MLX5_REG_PMTU, 0, 1);
372 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
374 int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
376 return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
378 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
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)
384 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
385 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
387 if (pfc_en_rx || pfc_en_tx) {
388 /* PFC and global pauseframes are incompatible features */
389 if (tx_pause || rx_pause)
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);
401 return mlx5_core_access_reg(dev, in, sizeof(in), out,
402 sizeof(out), MLX5_REG_PFCC, 0, 1);
405 int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
406 u32 *rx_pause, u32 *tx_pause)
408 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
409 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
412 MLX5_SET(pfcc_reg, in, local_port, port);
414 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
415 sizeof(out), MLX5_REG_PFCC, 0, 0);
419 *rx_pause = MLX5_GET(pfcc_reg, out, pprx);
420 *tx_pause = MLX5_GET(pfcc_reg, out, pptx);
425 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
427 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {};
428 u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
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);
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);
443 EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
445 int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
447 return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
449 EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
451 u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
453 u8 wol_supported = 0;
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;
470 return wol_supported;
472 EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
474 int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
476 u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0};
477 u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0};
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);
483 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
485 EXPORT_SYMBOL_GPL(mlx5_set_wol);
487 int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout)
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};
493 MLX5_SET(query_delay_drop_params_in, in, opcode,
494 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS);
496 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
500 *timeout = MLX5_GET(query_delay_drop_params_out, out,
505 EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
507 int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout)
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};
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);
516 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
518 EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
520 int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
521 struct mlx5_pvlc_reg *pvlc, int write)
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};
528 MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
530 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
532 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
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);
546 EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
548 int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
549 struct mlx5_ptys_reg *ptys, int write)
551 int sz = MLX5_ST_SZ_BYTES(ptys_reg);
556 in = mlx5_vzalloc(sz);
560 out = mlx5_vzalloc(sz);
566 MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
567 MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
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,
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);
587 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
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,
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,
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);
619 EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
621 static int mtu_to_ib_mtu(struct mlx5_core_dev *dev, int mtu)
630 mlx5_core_warn(dev, "invalid mtu\n");
635 int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
636 struct mlx5_pmtu_reg *pmtu, int write)
638 int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
643 in = mlx5_vzalloc(sz);
647 out = mlx5_vzalloc(sz);
653 MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
655 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
657 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
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,
666 pmtu->admin_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
668 pmtu->oper_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
677 EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
679 int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
681 u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
682 u32 out[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
686 MLX5_SET(pmlp_reg, in, local_port, 1);
688 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
689 sizeof(out), MLX5_REG_PMLP, 0, 0);
693 lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
694 *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
698 EXPORT_SYMBOL_GPL(mlx5_query_module_num);
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)
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);
710 size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
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);
719 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
720 sizeof(out), MLX5_REG_MCIA, 0, 0);
724 status = MLX5_GET(mcia_reg, out, status);
728 memcpy(data, ptr, size);
732 EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
734 int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
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};
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);
744 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
746 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
747 mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
754 int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
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};
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);
764 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
766 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
767 mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
774 int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
776 u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0};
777 u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0};
780 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
782 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
785 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
789 EXPORT_SYMBOL_GPL(mlx5_query_wol);
791 int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
792 int priority, int *is_enable)
794 u32 in[MLX5_ST_SZ_DW(query_cong_status_in)] = {0};
795 u32 out[MLX5_ST_SZ_DW(query_cong_status_out)] = {0};
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);
805 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
807 *is_enable = MLX5_GET(query_cong_status_out, out, enable);
811 int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
812 int priority, int enable)
814 u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)] = {0};
815 u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)] = {0};
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);
823 return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
826 int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
827 void *out, int out_size)
829 u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = {0};
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);
835 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
838 static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out,
841 u32 in[MLX5_ST_SZ_DW(qetc_reg)];
843 if (!MLX5_CAP_GEN(mdev, ets))
846 memset(in, 0, sizeof(in));
847 return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen,
848 MLX5_REG_QETCR, 0, 0);
851 int mlx5_max_tc(struct mlx5_core_dev *mdev)
853 u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8;
857 EXPORT_SYMBOL_GPL(mlx5_max_tc);
859 static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
862 u32 out[MLX5_ST_SZ_DW(qetc_reg)];
864 if (!MLX5_CAP_GEN(mdev, ets))
867 return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out),
868 MLX5_REG_QETCR, 0, 1);
871 int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev,
875 u32 out[MLX5_ST_SZ_DW(qetc_reg)];
880 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
884 for (i = 0; i <= mlx5_max_tc(mdev); i++) {
885 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
887 max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
889 max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
895 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit);
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)
901 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
905 MLX5_SET(qetc_reg, in, port_number, 1);
907 for (i = 0; i <= mlx5_max_tc(mdev); i++) {
908 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]);
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,
913 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value,
917 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
919 EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit);
921 int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
924 u32 in[MLX5_ST_SZ_DW(qtct_reg)];
925 u32 out[MLX5_ST_SZ_DW(qtct_reg)];
928 memset(in, 0, sizeof(in));
929 memset(out, 0, sizeof(out));
931 MLX5_SET(qtct_reg, in, port_number, 1);
932 MLX5_SET(qtct_reg, in, prio, prio);
934 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
935 sizeof(out), MLX5_REG_QTCT, 0, 0);
937 *tc = MLX5_GET(qtct_reg, out, tclass);
941 EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
943 int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index,
946 u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {};
947 u32 out[MLX5_ST_SZ_DW(qtct_reg)];
950 if (prio_tc > mlx5_max_tc(mdev))
953 MLX5_SET(qtct_reg, in, prio, prio_index);
954 MLX5_SET(qtct_reg, in, tclass, prio_tc);
956 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
957 sizeof(out), MLX5_REG_QTCT, 0, 1);
961 EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
963 int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, const u8 *tc_group)
965 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
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]);
973 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
975 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group);
977 int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev,
980 u32 out[MLX5_ST_SZ_DW(qetc_reg)];
984 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
988 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
989 tc_configuration[tc]);
991 *tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
996 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group);
998 int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, const u8 *tc_bw)
1000 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
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]);
1008 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
1010 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc);
1012 int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *bw_pct)
1014 u32 out[MLX5_ST_SZ_DW(qetc_reg)];
1019 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
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);
1029 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc);
1031 int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
1032 void *in, int in_size)
1034 u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0};
1036 MLX5_SET(modify_cong_params_in, in, opcode,
1037 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
1039 return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
1042 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
1043 void *out, int out_size)
1045 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0};
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);
1051 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1054 int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
1057 u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0};
1059 MLX5_SET(set_diagnostic_params_in, in, opcode,
1060 MLX5_CMD_OP_SET_DIAGNOSTICS);
1062 return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
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)
1069 u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0};
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,
1075 MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
1077 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1080 int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state)
1082 u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1083 u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1086 MLX5_SET(qpts_reg, in, local_port, 1);
1087 MLX5_SET(qpts_reg, in, trust_state, trust_state);
1089 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1090 sizeof(out), MLX5_REG_QPTS, 0, 1);
1094 int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
1096 u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1097 u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1100 MLX5_SET(qpts_reg, in, local_port, 1);
1102 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1103 sizeof(out), MLX5_REG_QPTS, 0, 0);
1105 *trust_state = MLX5_GET(qpts_reg, out, trust_state);
1110 int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio)
1112 int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1119 in = kzalloc(sz, GFP_KERNEL);
1120 out = kzalloc(sz, GFP_KERNEL);
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);
1131 memcpy(in, out, sz);
1132 MLX5_SET(qpdpm_reg, in, local_port, 1);
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);
1140 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
1147 int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
1149 int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1156 in = kzalloc(sz, GFP_KERNEL);
1157 out = kzalloc(sz, GFP_KERNEL);
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);
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);
1178 int mlx5_query_pddr_range_info(struct mlx5_core_dev *mdev, u8 local_port, u8 *is_er_type)
1180 u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {};
1181 int sz = MLX5_ST_SZ_BYTES(pddr_reg);
1186 MLX5_SET(pddr_reg, pddr_reg, local_port, local_port);
1187 MLX5_SET(pddr_reg, pddr_reg, page_select, 3 /* module info page */);
1189 error = mlx5_core_access_reg(mdev, pddr_reg, sz, pddr_reg, sz,
1190 MLX5_ACCESS_REG_SUMMARY_CTRL_ID_PDDR, 0, 0);
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);
1198 case 0: /* QSFP28 */
1202 case 2: /* SFP28/SFP+ */
1203 case 3: /* QSA (QSFP->SFP) */
1204 *is_er_type = ((ecc & (1 << 7)) != 0);
1212 EXPORT_SYMBOL_GPL(mlx5_query_pddr_range_info);
1215 mlx5_query_mfrl_reg(struct mlx5_core_dev *mdev, u8 *reset_level)
1217 u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {};
1218 int sz = MLX5_ST_SZ_BYTES(mfrl_reg);
1221 err = mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL,
1224 *reset_level = MLX5_GET(mfrl_reg, mfrl, reset_level);
1229 mlx5_set_mfrl_reg(struct mlx5_core_dev *mdev, u8 reset_level)
1231 u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {};
1232 int sz = MLX5_ST_SZ_BYTES(mfrl_reg);
1234 MLX5_SET(mfrl_reg, mfrl, reset_level, reset_level);
1236 return (mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL,
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,
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,
1285 static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
1286 const u32 **arr, u32 *size)
1288 bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
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;
1295 u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
1297 unsigned long temp = eth_proto_oper;
1303 mlx5e_port_get_speed_arr(mdev, &table, &max_size);
1304 i = find_first_bit(&temp, max_size);
1310 int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
1311 struct mlx5e_port_eth_proto *eproto)
1313 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
1319 err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
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);
1330 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
1332 struct mlx5e_port_eth_proto eproto;
1336 ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
1337 err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
1341 *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
1349 int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out)
1351 int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
1355 in = kzalloc(sz, GFP_KERNEL);
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);
1366 int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in)
1368 int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
1372 out = kzalloc(sz, GFP_KERNEL);
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);
1383 /* buffer[i]: buffer that priority i mapped to */
1384 int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
1386 int sz = MLX5_ST_SZ_BYTES(pptb_reg);
1393 in = kzalloc(sz, GFP_KERNEL);
1394 out = kzalloc(sz, GFP_KERNEL);
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);
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]);
1416 int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
1418 int sz = MLX5_ST_SZ_BYTES(pptb_reg);
1425 in = kzalloc(sz, GFP_KERNEL);
1426 out = kzalloc(sz, GFP_KERNEL);
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);
1438 memcpy(in, out, sz);
1439 MLX5_SET(pptb_reg, in, local_port, 1);
1441 /* Update the pm and prio_x_buff */
1442 MLX5_SET(pptb_reg, in, pm, 0xFF);
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);
1449 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1);