summaryrefslogtreecommitdiffstats
path: root/sys/dev/mlx5/mlx5_core/mlx5_port.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mlx5/mlx5_core/mlx5_port.c')
-rw-r--r--sys/dev/mlx5/mlx5_core/mlx5_port.c718
1 files changed, 718 insertions, 0 deletions
diff --git a/sys/dev/mlx5/mlx5_core/mlx5_port.c b/sys/dev/mlx5/mlx5_core/mlx5_port.c
new file mode 100644
index 0000000..1e938a6
--- /dev/null
+++ b/sys/dev/mlx5/mlx5_core/mlx5_port.c
@@ -0,0 +1,718 @@
+/*-
+ * Copyright (c) 2013-2015, Mellanox Technologies, Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <linux/module.h>
+#include <dev/mlx5/driver.h>
+#include "mlx5_core.h"
+
+int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
+ int size_in, void *data_out, int size_out,
+ u16 reg_num, int arg, int write)
+{
+ struct mlx5_access_reg_mbox_in *in = NULL;
+ struct mlx5_access_reg_mbox_out *out = NULL;
+ int err = -ENOMEM;
+
+ in = mlx5_vzalloc(sizeof(*in) + size_in);
+ if (!in)
+ return -ENOMEM;
+
+ out = mlx5_vzalloc(sizeof(*out) + size_out);
+ if (!out)
+ goto ex1;
+
+ memcpy(in->data, data_in, size_in);
+ in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ACCESS_REG);
+ in->hdr.opmod = cpu_to_be16(!write);
+ in->arg = cpu_to_be32(arg);
+ in->register_id = cpu_to_be16(reg_num);
+ err = mlx5_cmd_exec(dev, in, sizeof(*in) + size_in, out,
+ sizeof(*out) + size_out);
+ if (err)
+ goto ex2;
+
+ if (out->hdr.status)
+ err = mlx5_cmd_status_to_err(&out->hdr);
+
+ if (!err)
+ memcpy(data_out, out->data, size_out);
+
+ex2:
+ kvfree(out);
+ex1:
+ kvfree(in);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
+
+
+struct mlx5_reg_pcap {
+ u8 rsvd0;
+ u8 port_num;
+ u8 rsvd1[2];
+ __be32 caps_127_96;
+ __be32 caps_95_64;
+ __be32 caps_63_32;
+ __be32 caps_31_0;
+};
+
+int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
+{
+ struct mlx5_reg_pcap in;
+ struct mlx5_reg_pcap out;
+ int err;
+
+ memset(&in, 0, sizeof(in));
+ in.caps_127_96 = cpu_to_be32(caps);
+ in.port_num = port_num;
+
+ err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
+ sizeof(out), MLX5_REG_PCAP, 0, 1);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
+
+int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
+ int ptys_size, int proto_mask)
+{
+ u32 in[MLX5_ST_SZ_DW(ptys_reg)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ MLX5_SET(ptys_reg, in, local_port, 1);
+ MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
+
+ err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
+ ptys_size, MLX5_REG_PTYS, 0, 0);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
+
+int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
+ u32 *proto_cap, int proto_mask)
+{
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+ int err;
+
+ err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
+ if (err)
+ return err;
+
+ if (proto_mask == MLX5_PTYS_EN)
+ *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
+ else
+ *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
+
+int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
+ u32 *proto_admin, int proto_mask)
+{
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+ int err;
+
+ err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask);
+ if (err)
+ return err;
+
+ if (proto_mask == MLX5_PTYS_EN)
+ *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
+ else
+ *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
+
+int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
+ int proto_mask)
+{
+ u32 in[MLX5_ST_SZ_DW(ptys_reg)];
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(ptys_reg, in, local_port, 1);
+ MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
+ if (proto_mask == MLX5_PTYS_EN)
+ MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
+ else
+ MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
+
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PTYS, 0, 1);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
+
+int mlx5_set_port_status(struct mlx5_core_dev *dev,
+ enum mlx5_port_status status)
+{
+ u32 in[MLX5_ST_SZ_DW(paos_reg)];
+ u32 out[MLX5_ST_SZ_DW(paos_reg)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(paos_reg, in, local_port, 1);
+
+ MLX5_SET(paos_reg, in, admin_status, status);
+ MLX5_SET(paos_reg, in, ase, 1);
+
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PAOS, 0, 1);
+ return err;
+}
+
+int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
+{
+ u32 in[MLX5_ST_SZ_DW(paos_reg)];
+ u32 out[MLX5_ST_SZ_DW(paos_reg)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(paos_reg, in, local_port, 1);
+
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PAOS, 0, 0);
+ if (err)
+ return err;
+
+ *status = MLX5_GET(paos_reg, out, oper_status);
+ return err;
+}
+
+static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
+ int *admin_mtu, int *max_mtu, int *oper_mtu)
+{
+ u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
+ u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(pmtu_reg, in, local_port, 1);
+
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PMTU, 0, 0);
+ if (err)
+ return err;
+
+ if (max_mtu)
+ *max_mtu = MLX5_GET(pmtu_reg, out, max_mtu);
+ if (oper_mtu)
+ *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
+ if (admin_mtu)
+ *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
+
+ return err;
+}
+
+int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
+{
+ u32 in[MLX5_ST_SZ_DW(pmtu_reg)];
+ u32 out[MLX5_ST_SZ_DW(pmtu_reg)];
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
+ MLX5_SET(pmtu_reg, in, local_port, 1);
+
+ return mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PMTU, 0, 1);
+}
+EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
+
+int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
+{
+ return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
+
+int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 port,
+ u32 rx_pause, u32 tx_pause)
+{
+ u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
+ u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(pfcc_reg, in, local_port, port);
+ MLX5_SET(pfcc_reg, in, pptx, tx_pause);
+ MLX5_SET(pfcc_reg, in, pprx, rx_pause);
+
+ return mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PFCC, 0, 1);
+}
+
+int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
+ u32 *rx_pause, u32 *tx_pause)
+{
+ u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
+ u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(pfcc_reg, in, local_port, port);
+
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PFCC, 0, 0);
+ if (err)
+ return err;
+
+ *rx_pause = MLX5_GET(pfcc_reg, out, pprx);
+ *tx_pause = MLX5_GET(pfcc_reg, out, pptx);
+
+ return 0;
+}
+
+int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
+{
+ return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
+
+u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
+{
+ u8 wol_supported = 0;
+
+ if (MLX5_CAP_GEN(dev, wol_s))
+ wol_supported |= MLX5_WOL_SECURED_MAGIC;
+ if (MLX5_CAP_GEN(dev, wol_g))
+ wol_supported |= MLX5_WOL_MAGIC;
+ if (MLX5_CAP_GEN(dev, wol_a))
+ wol_supported |= MLX5_WOL_ARP;
+ if (MLX5_CAP_GEN(dev, wol_b))
+ wol_supported |= MLX5_WOL_BROADCAST;
+ if (MLX5_CAP_GEN(dev, wol_m))
+ wol_supported |= MLX5_WOL_MULTICAST;
+ if (MLX5_CAP_GEN(dev, wol_u))
+ wol_supported |= MLX5_WOL_UNICAST;
+ if (MLX5_CAP_GEN(dev, wol_p))
+ wol_supported |= MLX5_WOL_PHY_ACTIVITY;
+
+ return wol_supported;
+}
+EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
+
+int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
+{
+ u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)];
+ u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)];
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
+ MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
+ MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
+
+ return mlx5_cmd_exec_check_status(dev, in, sizeof(in),
+ out, sizeof(out));
+}
+EXPORT_SYMBOL_GPL(mlx5_set_wol);
+
+int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
+ struct mlx5_pvlc_reg *pvlc, int write)
+{
+ int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
+ u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)];
+ u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)];
+ int err;
+
+ memset(out, 0, sizeof(out));
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
+ if (write)
+ MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
+
+ err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
+ !!write);
+ if (err)
+ return err;
+
+ if (!write) {
+ pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
+ pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
+ pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
+ pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
+
+int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
+ struct mlx5_ptys_reg *ptys, int write)
+{
+ int sz = MLX5_ST_SZ_BYTES(ptys_reg);
+ void *out = NULL;
+ void *in = NULL;
+ int err;
+
+ in = mlx5_vzalloc(sz);
+ if (!in)
+ return -ENOMEM;
+
+ out = mlx5_vzalloc(sz);
+ if (!out) {
+ kfree(in);
+ return -ENOMEM;
+ }
+
+ MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
+ MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
+ if (write) {
+ MLX5_SET(ptys_reg, in, eth_proto_capability,
+ ptys->eth_proto_cap);
+ MLX5_SET(ptys_reg, in, ib_link_width_capability,
+ ptys->ib_link_width_cap);
+ MLX5_SET(ptys_reg, in, ib_proto_capability,
+ ptys->ib_proto_cap);
+ MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
+ MLX5_SET(ptys_reg, in, ib_link_width_admin,
+ ptys->ib_link_width_admin);
+ MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
+ MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
+ MLX5_SET(ptys_reg, in, ib_link_width_oper,
+ ptys->ib_link_width_oper);
+ MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
+ MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
+ ptys->eth_proto_lp_advertise);
+ }
+
+ err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
+ !!write);
+ if (err)
+ goto out;
+
+ if (!write) {
+ ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
+ ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
+ ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
+ eth_proto_capability);
+ ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
+ ib_link_width_capability);
+ ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
+ ib_proto_capability);
+ ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
+ eth_proto_admin);
+ ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
+ ib_link_width_admin);
+ ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
+ ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
+ ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
+ ib_link_width_oper);
+ ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
+ ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
+ eth_proto_lp_advertise);
+ }
+
+out:
+ kvfree(in);
+ kvfree(out);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
+
+static int mtu_to_ib_mtu(int mtu)
+{
+ switch (mtu) {
+ case 256: return 1;
+ case 512: return 2;
+ case 1024: return 3;
+ case 2048: return 4;
+ case 4096: return 5;
+ default:
+ printf("mlx5_core: WARN: ""invalid mtu\n");
+ return -1;
+ }
+}
+
+int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
+ struct mlx5_pmtu_reg *pmtu, int write)
+{
+ int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
+ void *out = NULL;
+ void *in = NULL;
+ int err;
+
+ in = mlx5_vzalloc(sz);
+ if (!in)
+ return -ENOMEM;
+
+ out = mlx5_vzalloc(sz);
+ if (!out) {
+ kfree(in);
+ return -ENOMEM;
+ }
+
+ MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
+ if (write)
+ MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
+
+ err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
+ !!write);
+ if (err)
+ goto out;
+
+ if (!write) {
+ pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
+ pmtu->max_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
+ max_mtu));
+ pmtu->admin_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
+ admin_mtu));
+ pmtu->oper_mtu = mtu_to_ib_mtu(MLX5_GET(pmtu_reg, out,
+ oper_mtu));
+ }
+
+out:
+ kvfree(in);
+ kvfree(out);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
+
+int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
+{
+ u32 in[MLX5_ST_SZ_DW(pmlp_reg)];
+ u32 out[MLX5_ST_SZ_DW(pmlp_reg)];
+ int lane = 0;
+ int err;
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(pmlp_reg, in, local_port, 1);
+
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_PMLP, 0, 0);
+ if (err)
+ return err;
+
+ lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
+ *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_module_num);
+
+int mlx5_query_eeprom(struct mlx5_core_dev *dev,
+ int i2c_addr, int page_num, int device_addr,
+ int size, int module_num, u32 *data, int *size_read)
+{
+ u32 in[MLX5_ST_SZ_DW(mcia_reg)];
+ u32 out[MLX5_ST_SZ_DW(mcia_reg)];
+ u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
+ int status;
+ int err;
+
+ memset(in, 0, sizeof(in));
+ size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
+
+ MLX5_SET(mcia_reg, in, l, 0);
+ MLX5_SET(mcia_reg, in, module, module_num);
+ MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
+ MLX5_SET(mcia_reg, in, page_number, page_num);
+ MLX5_SET(mcia_reg, in, device_address, device_addr);
+ MLX5_SET(mcia_reg, in, size, size);
+
+ err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_MCIA, 0, 0);
+ if (err)
+ return err;
+
+ status = MLX5_GET(mcia_reg, out, status);
+ if (status)
+ return status;
+
+ memcpy(data, ptr, size);
+ *size_read = size;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
+
+int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
+{
+ u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)];
+ u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
+ MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
+ MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
+
+ err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
+ if (err) {
+ mlx5_core_err(dev, "Failed %s, port %u, err - %d",
+ mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
+ port, err);
+ }
+
+ return err;
+}
+
+int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
+{
+ u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)];
+ u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
+ MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
+ MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
+
+ err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
+ if (err) {
+ mlx5_core_err(dev, "Failed %s, port %u, err - %d",
+ mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
+ port, err);
+ }
+
+ return err;
+}
+
+int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
+{
+ u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)];
+ u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
+
+ err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
+
+ if (!err)
+ *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_wol);
+
+int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
+ int priority, int *is_enable)
+{
+ u32 in[MLX5_ST_SZ_DW(query_cong_status_in)];
+ u32 out[MLX5_ST_SZ_DW(query_cong_status_out)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ *is_enable = 0;
+
+ MLX5_SET(query_cong_status_in, in, opcode,
+ MLX5_CMD_OP_QUERY_CONG_STATUS);
+ MLX5_SET(query_cong_status_in, in, cong_protocol, protocol);
+ MLX5_SET(query_cong_status_in, in, priority, priority);
+
+ err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
+ out, sizeof(out));
+ if (!err)
+ *is_enable = MLX5_GET(query_cong_status_out, out, enable);
+ return err;
+}
+
+int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
+ int priority, int enable)
+{
+ u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)];
+ u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)];
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(modify_cong_status_in, in, opcode,
+ MLX5_CMD_OP_MODIFY_CONG_STATUS);
+ MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
+ MLX5_SET(modify_cong_status_in, in, priority, priority);
+ MLX5_SET(modify_cong_status_in, in, enable, enable);
+
+ return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
+ out, sizeof(out));
+}
+
+int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
+ void *out, int out_size)
+{
+ u32 in[MLX5_ST_SZ_DW(query_cong_params_in)];
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(query_cong_params_in, in, opcode,
+ MLX5_CMD_OP_QUERY_CONG_PARAMS);
+ MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
+
+ return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
+ out, out_size);
+}
+
+int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
+ void *in, int in_size)
+{
+ u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)];
+
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(modify_cong_params_in, in, opcode,
+ MLX5_CMD_OP_MODIFY_CONG_PARAMS);
+
+ return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out));
+}
+
+int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
+ void *out, int out_size)
+{
+ u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)];
+
+ memset(in, 0, sizeof(in));
+
+ MLX5_SET(query_cong_statistics_in, in, opcode,
+ MLX5_CMD_OP_QUERY_CONG_STATISTICS);
+ MLX5_SET(query_cong_statistics_in, in, clear, clear);
+
+ return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
+ out, out_size);
+}
OpenPOWER on IntegriCloud