2 * Copyright (c) 2013-2017, 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 struct mlx5_reg_pcap {
92 /* This function should be used after setting a port register only */
93 void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
95 enum mlx5_port_status ps;
97 mlx5_query_port_admin_status(dev, &ps);
98 mlx5_set_port_status(dev, MLX5_PORT_DOWN);
99 if (ps == MLX5_PORT_UP)
100 mlx5_set_port_status(dev, MLX5_PORT_UP);
102 EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
104 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
106 struct mlx5_reg_pcap in;
107 struct mlx5_reg_pcap out;
110 memset(&in, 0, sizeof(in));
111 in.caps_127_96 = cpu_to_be32(caps);
112 in.port_num = port_num;
114 err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
115 sizeof(out), MLX5_REG_PCAP, 0, 1);
119 EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
121 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
122 int ptys_size, int proto_mask, u8 local_port)
124 u32 in[MLX5_ST_SZ_DW(ptys_reg)];
127 memset(in, 0, sizeof(in));
128 MLX5_SET(ptys_reg, in, local_port, local_port);
129 MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
131 err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
132 ptys_size, MLX5_REG_PTYS, 0, 0);
136 EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
138 int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
139 u32 *proto_cap, int proto_mask)
141 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
144 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
148 if (proto_mask == MLX5_PTYS_EN)
149 *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
151 *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
155 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
157 int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
158 u8 *an_disable_cap, u8 *an_disable_status)
160 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
163 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
167 *an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin);
168 *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
172 EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
174 int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable,
175 u32 eth_proto_admin, int proto_mask)
177 u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
178 u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
180 u8 an_disable_status;
183 err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap,
190 MLX5_SET(ptys_reg, in, local_port, 1);
191 MLX5_SET(ptys_reg, in, an_disable_admin, disable);
192 MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
193 if (proto_mask == MLX5_PTYS_EN)
194 MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin);
196 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
197 sizeof(out), MLX5_REG_PTYS, 0, 1);
200 EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
202 int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
203 u32 *proto_admin, int proto_mask)
205 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
208 err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
212 if (proto_mask == MLX5_PTYS_EN)
213 *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
215 *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
219 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
221 int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
222 u32 *proto_oper, u8 local_port)
224 u32 out[MLX5_ST_SZ_DW(ptys_reg)];
227 err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
232 *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
236 EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
238 int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
241 u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
242 u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
245 MLX5_SET(ptys_reg, in, local_port, 1);
246 MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
247 if (proto_mask == MLX5_PTYS_EN)
248 MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
250 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
252 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
253 sizeof(out), MLX5_REG_PTYS, 0, 1);
256 EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
258 int mlx5_set_port_status(struct mlx5_core_dev *dev,
259 enum mlx5_port_status status)
261 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
262 u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
265 MLX5_SET(paos_reg, in, local_port, 1);
267 MLX5_SET(paos_reg, in, admin_status, status);
268 MLX5_SET(paos_reg, in, ase, 1);
270 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
271 sizeof(out), MLX5_REG_PAOS, 0, 1);
275 int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
277 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
278 u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
281 MLX5_SET(paos_reg, in, local_port, 1);
283 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
284 sizeof(out), MLX5_REG_PAOS, 0, 0);
288 *status = MLX5_GET(paos_reg, out, oper_status);
292 int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
293 enum mlx5_port_status *status)
295 u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
296 u32 out[MLX5_ST_SZ_DW(paos_reg)];
299 MLX5_SET(paos_reg, in, local_port, 1);
300 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
301 sizeof(out), MLX5_REG_PAOS, 0, 0);
304 *status = MLX5_GET(paos_reg, out, admin_status);
307 EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
309 static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
310 int *admin_mtu, int *max_mtu, int *oper_mtu)
312 u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
313 u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
316 MLX5_SET(pmtu_reg, in, local_port, 1);
318 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
319 sizeof(out), MLX5_REG_PMTU, 0, 0);
324 *max_mtu = MLX5_GET(pmtu_reg, out, max_mtu);
326 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
328 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
333 int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
335 u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
336 u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
338 MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
339 MLX5_SET(pmtu_reg, in, local_port, 1);
341 return mlx5_core_access_reg(dev, in, sizeof(in), out,
342 sizeof(out), MLX5_REG_PMTU, 0, 1);
344 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
346 int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
348 return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
350 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
352 int mlx5_set_port_pause_and_pfc(struct mlx5_core_dev *dev, u32 port,
353 u8 rx_pause, u8 tx_pause,
354 u8 pfc_en_rx, u8 pfc_en_tx)
356 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
357 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
359 if (pfc_en_rx || pfc_en_tx) {
360 /* PFC and global pauseframes are incompatible features */
361 if (tx_pause || rx_pause)
365 MLX5_SET(pfcc_reg, in, local_port, port);
366 MLX5_SET(pfcc_reg, in, pptx, tx_pause);
367 MLX5_SET(pfcc_reg, in, pprx, rx_pause);
368 MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx);
369 MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx);
370 MLX5_SET(pfcc_reg, in, prio_mask_tx, pfc_en_tx);
371 MLX5_SET(pfcc_reg, in, prio_mask_rx, pfc_en_rx);
373 return mlx5_core_access_reg(dev, in, sizeof(in), out,
374 sizeof(out), MLX5_REG_PFCC, 0, 1);
377 int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
378 u32 *rx_pause, u32 *tx_pause)
380 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
381 u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
384 MLX5_SET(pfcc_reg, in, local_port, port);
386 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
387 sizeof(out), MLX5_REG_PFCC, 0, 0);
391 *rx_pause = MLX5_GET(pfcc_reg, out, pprx);
392 *tx_pause = MLX5_GET(pfcc_reg, out, pptx);
397 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
399 u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {};
400 u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
403 MLX5_SET(pfcc_reg, in, local_port, 1);
404 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
405 sizeof(out), MLX5_REG_PFCC, 0, 0);
409 if (pfc_en_tx != NULL)
410 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx);
411 if (pfc_en_rx != NULL)
412 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx);
415 EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
417 int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
419 return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
421 EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
423 u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
425 u8 wol_supported = 0;
427 if (MLX5_CAP_GEN(dev, wol_s))
428 wol_supported |= MLX5_WOL_SECURED_MAGIC;
429 if (MLX5_CAP_GEN(dev, wol_g))
430 wol_supported |= MLX5_WOL_MAGIC;
431 if (MLX5_CAP_GEN(dev, wol_a))
432 wol_supported |= MLX5_WOL_ARP;
433 if (MLX5_CAP_GEN(dev, wol_b))
434 wol_supported |= MLX5_WOL_BROADCAST;
435 if (MLX5_CAP_GEN(dev, wol_m))
436 wol_supported |= MLX5_WOL_MULTICAST;
437 if (MLX5_CAP_GEN(dev, wol_u))
438 wol_supported |= MLX5_WOL_UNICAST;
439 if (MLX5_CAP_GEN(dev, wol_p))
440 wol_supported |= MLX5_WOL_PHY_ACTIVITY;
442 return wol_supported;
444 EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
446 int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
448 u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0};
449 u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0};
451 MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
452 MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
453 MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
455 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
457 EXPORT_SYMBOL_GPL(mlx5_set_wol);
459 int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout)
461 u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)] = {0};
462 u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)] = {0};
465 MLX5_SET(query_delay_drop_params_in, in, opcode,
466 MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS);
468 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
472 *timeout = MLX5_GET(query_delay_drop_params_out, out,
477 EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
479 int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout)
481 u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)] = {0};
482 u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)] = {0};
484 MLX5_SET(set_delay_drop_params_in, in, opcode,
485 MLX5_CMD_OP_SET_DELAY_DROP_PARAMS);
486 MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout);
488 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
490 EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
492 int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
493 struct mlx5_pvlc_reg *pvlc, int write)
495 int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
496 u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
497 u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
500 MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
502 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
504 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
510 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
511 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
512 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
513 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
518 EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
520 int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
521 struct mlx5_ptys_reg *ptys, int write)
523 int sz = MLX5_ST_SZ_BYTES(ptys_reg);
528 in = mlx5_vzalloc(sz);
532 out = mlx5_vzalloc(sz);
538 MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
539 MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
541 MLX5_SET(ptys_reg, in, eth_proto_capability,
542 ptys->eth_proto_cap);
543 MLX5_SET(ptys_reg, in, ib_link_width_capability,
544 ptys->ib_link_width_cap);
545 MLX5_SET(ptys_reg, in, ib_proto_capability,
547 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
548 MLX5_SET(ptys_reg, in, ib_link_width_admin,
549 ptys->ib_link_width_admin);
550 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
551 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
552 MLX5_SET(ptys_reg, in, ib_link_width_oper,
553 ptys->ib_link_width_oper);
554 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
555 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
556 ptys->eth_proto_lp_advertise);
559 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
565 ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
566 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
567 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
568 eth_proto_capability);
569 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
570 ib_link_width_capability);
571 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
572 ib_proto_capability);
573 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
575 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
576 ib_link_width_admin);
577 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
578 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
579 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
581 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
582 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
583 eth_proto_lp_advertise);
591 EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
593 static int mtu_to_ib_mtu(int mtu)
602 printf("mlx5_core: WARN: ""invalid mtu\n");
607 int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
608 struct mlx5_pmtu_reg *pmtu, int write)
610 int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
615 in = mlx5_vzalloc(sz);
619 out = mlx5_vzalloc(sz);
625 MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
627 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
629 err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
635 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
636 pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
638 pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
640 pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
649 EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
651 int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
653 u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
654 u32 out[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
658 MLX5_SET(pmlp_reg, in, local_port, 1);
660 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
661 sizeof(out), MLX5_REG_PMLP, 0, 0);
665 lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
666 *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
670 EXPORT_SYMBOL_GPL(mlx5_query_module_num);
672 int mlx5_query_eeprom(struct mlx5_core_dev *dev,
673 int i2c_addr, int page_num, int device_addr,
674 int size, int module_num, u32 *data, int *size_read)
676 u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {0};
677 u32 out[MLX5_ST_SZ_DW(mcia_reg)] = {0};
678 u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
682 size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
684 MLX5_SET(mcia_reg, in, l, 0);
685 MLX5_SET(mcia_reg, in, module, module_num);
686 MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
687 MLX5_SET(mcia_reg, in, page_number, page_num);
688 MLX5_SET(mcia_reg, in, device_address, device_addr);
689 MLX5_SET(mcia_reg, in, size, size);
691 err = mlx5_core_access_reg(dev, in, sizeof(in), out,
692 sizeof(out), MLX5_REG_MCIA, 0, 0);
696 status = MLX5_GET(mcia_reg, out, status);
700 memcpy(data, ptr, size);
704 EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
706 int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
708 u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0};
709 u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)] = {0};
712 MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
713 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
714 MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
716 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
718 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
719 mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
726 int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
728 u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {0};
729 u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)] = {0};
732 MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
733 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
734 MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
736 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
738 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
739 mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
746 int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
748 u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0};
749 u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0};
752 MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
754 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
757 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
761 EXPORT_SYMBOL_GPL(mlx5_query_wol);
763 int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
764 int priority, int *is_enable)
766 u32 in[MLX5_ST_SZ_DW(query_cong_status_in)] = {0};
767 u32 out[MLX5_ST_SZ_DW(query_cong_status_out)] = {0};
772 MLX5_SET(query_cong_status_in, in, opcode,
773 MLX5_CMD_OP_QUERY_CONG_STATUS);
774 MLX5_SET(query_cong_status_in, in, cong_protocol, protocol);
775 MLX5_SET(query_cong_status_in, in, priority, priority);
777 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
779 *is_enable = MLX5_GET(query_cong_status_out, out, enable);
783 int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
784 int priority, int enable)
786 u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)] = {0};
787 u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)] = {0};
789 MLX5_SET(modify_cong_status_in, in, opcode,
790 MLX5_CMD_OP_MODIFY_CONG_STATUS);
791 MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
792 MLX5_SET(modify_cong_status_in, in, priority, priority);
793 MLX5_SET(modify_cong_status_in, in, enable, enable);
795 return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
798 int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
799 void *out, int out_size)
801 u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = {0};
803 MLX5_SET(query_cong_params_in, in, opcode,
804 MLX5_CMD_OP_QUERY_CONG_PARAMS);
805 MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
807 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
810 static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out,
813 u32 in[MLX5_ST_SZ_DW(qtct_reg)];
815 if (!MLX5_CAP_GEN(mdev, ets))
818 memset(in, 0, sizeof(in));
819 return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen,
820 MLX5_REG_QETCR, 0, 0);
823 int mlx5_max_tc(struct mlx5_core_dev *mdev)
825 u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8;
829 EXPORT_SYMBOL_GPL(mlx5_max_tc);
831 static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
834 u32 out[MLX5_ST_SZ_DW(qtct_reg)];
836 if (!MLX5_CAP_GEN(mdev, ets))
839 return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out),
840 MLX5_REG_QETCR, 0, 1);
843 int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev,
847 u32 out[MLX5_ST_SZ_DW(qetc_reg)];
852 err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
856 for (i = 0; i <= mlx5_max_tc(mdev); i++) {
857 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
859 max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
861 max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
867 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit);
869 int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev,
870 const u8 *max_bw_value,
871 const u8 *max_bw_units)
873 u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
877 MLX5_SET(qetc_reg, in, port_number, 1);
879 for (i = 0; i <= mlx5_max_tc(mdev); i++) {
880 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]);
882 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1);
883 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units,
885 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value,
889 return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
891 EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit);
893 int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
896 u32 in[MLX5_ST_SZ_DW(qtct_reg)];
897 u32 out[MLX5_ST_SZ_DW(qtct_reg)];
900 memset(in, 0, sizeof(in));
901 memset(out, 0, sizeof(out));
903 MLX5_SET(qtct_reg, in, port_number, 1);
904 MLX5_SET(qtct_reg, in, prio, prio);
906 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
907 sizeof(out), MLX5_REG_QTCT, 0, 0);
909 *tc = MLX5_GET(qtct_reg, out, tclass);
913 EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
915 int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index,
918 u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {};
919 u32 out[MLX5_ST_SZ_DW(qtct_reg)];
922 if (prio_tc > mlx5_max_tc(mdev))
925 MLX5_SET(qtct_reg, in, prio, prio_index);
926 MLX5_SET(qtct_reg, in, tclass, prio_tc);
928 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
929 sizeof(out), MLX5_REG_QTCT, 0, 1);
933 EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
935 int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
936 void *in, int in_size)
938 u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0};
940 MLX5_SET(modify_cong_params_in, in, opcode,
941 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
943 return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
946 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
947 void *out, int out_size)
949 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0};
951 MLX5_SET(query_cong_statistics_in, in, opcode,
952 MLX5_CMD_OP_QUERY_CONG_STATISTICS);
953 MLX5_SET(query_cong_statistics_in, in, clear, clear);
955 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
958 int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
961 u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0};
963 MLX5_SET(set_diagnostic_params_in, in, opcode,
964 MLX5_CMD_OP_SET_DIAGNOSTICS);
966 return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
969 int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
970 u8 num_of_samples, u16 sample_index,
971 void *out, int out_size)
973 u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0};
975 MLX5_SET(query_diagnostic_counters_in, in, opcode,
976 MLX5_CMD_OP_QUERY_DIAGNOSTICS);
977 MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
979 MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
981 return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
984 int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state)
986 u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
987 u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
990 MLX5_SET(qpts_reg, in, local_port, 1);
991 MLX5_SET(qpts_reg, in, trust_state, trust_state);
993 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
994 sizeof(out), MLX5_REG_QPTS, 0, 1);
998 int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
1000 u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
1001 u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
1004 MLX5_SET(qpts_reg, in, local_port, 1);
1006 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
1007 sizeof(out), MLX5_REG_QPTS, 0, 0);
1009 *trust_state = MLX5_GET(qpts_reg, out, trust_state);
1014 int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio)
1016 int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1023 in = kzalloc(sz, GFP_KERNEL);
1024 out = kzalloc(sz, GFP_KERNEL);
1030 MLX5_SET(qpdpm_reg, in, local_port, 1);
1031 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1035 memcpy(in, out, sz);
1036 MLX5_SET(qpdpm_reg, in, local_port, 1);
1038 /* Update the corresponding dscp entry */
1039 for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1040 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[i]);
1041 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, dscp2prio[i]);
1042 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1);
1044 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
1051 int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
1053 int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
1060 in = kzalloc(sz, GFP_KERNEL);
1061 out = kzalloc(sz, GFP_KERNEL);
1067 MLX5_SET(qpdpm_reg, in, local_port, 1);
1068 err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
1072 for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
1073 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]);
1074 dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio);