Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
[deliverable/linux.git] / drivers / net / ethernet / mellanox / mlx5 / core / vport.c
index ecb274ae9a815c8f4072d90222ee1d9757370c8e..c7398b95aecdc0286480f85564e5a42660275bd6 100644 (file)
 #include <linux/mlx5/vport.h>
 #include "mlx5_core.h"
 
-u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod)
+static int _mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod,
+                                  u16 vport, u32 *out, int outlen)
 {
-       u32 in[MLX5_ST_SZ_DW(query_vport_state_in)];
-       u32 out[MLX5_ST_SZ_DW(query_vport_state_out)];
        int err;
+       u32 in[MLX5_ST_SZ_DW(query_vport_state_in)];
 
        memset(in, 0, sizeof(in));
 
        MLX5_SET(query_vport_state_in, in, opcode,
                 MLX5_CMD_OP_QUERY_VPORT_STATE);
        MLX5_SET(query_vport_state_in, in, op_mod, opmod);
+       MLX5_SET(query_vport_state_in, in, vport_number, vport);
+       if (vport)
+               MLX5_SET(query_vport_state_in, in, other_vport, 1);
 
-       err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out,
-                                        sizeof(out));
+       err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, outlen);
        if (err)
                mlx5_core_warn(mdev, "MLX5_CMD_OP_QUERY_VPORT_STATE failed\n");
 
+       return err;
+}
+
+u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
+{
+       u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0};
+
+       _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out));
+
        return MLX5_GET(query_vport_state_out, out, state);
 }
-EXPORT_SYMBOL(mlx5_query_vport_state);
+EXPORT_SYMBOL_GPL(mlx5_query_vport_state);
+
+u8 mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport)
+{
+       u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {0};
+
+       _mlx5_query_vport_state(mdev, opmod, vport, out, sizeof(out));
+
+       return MLX5_GET(query_vport_state_out, out, admin_state);
+}
+EXPORT_SYMBOL_GPL(mlx5_query_vport_admin_state);
 
-static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u32 *out,
-                                       int outlen)
+int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
+                                 u16 vport, u8 state)
+{
+       u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)];
+       u32 out[MLX5_ST_SZ_DW(modify_vport_state_out)];
+       int err;
+
+       memset(in, 0, sizeof(in));
+
+       MLX5_SET(modify_vport_state_in, in, opcode,
+                MLX5_CMD_OP_MODIFY_VPORT_STATE);
+       MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
+       MLX5_SET(modify_vport_state_in, in, vport_number, vport);
+
+       if (vport)
+               MLX5_SET(modify_vport_state_in, in, other_vport, 1);
+
+       MLX5_SET(modify_vport_state_in, in, admin_state, state);
+
+       err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out,
+                                        sizeof(out));
+       if (err)
+               mlx5_core_warn(mdev, "MLX5_CMD_OP_MODIFY_VPORT_STATE failed\n");
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_modify_vport_admin_state);
+
+static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vport,
+                                       u32 *out, int outlen)
 {
        u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];
 
@@ -67,6 +116,10 @@ static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u32 *out,
        MLX5_SET(query_nic_vport_context_in, in, opcode,
                 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
 
+       MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
+       if (vport)
+               MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
+
        return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, outlen);
 }
 
@@ -78,10 +131,12 @@ static int mlx5_modify_nic_vport_context(struct mlx5_core_dev *mdev, void *in,
        MLX5_SET(modify_nic_vport_context_in, in, opcode,
                 MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
 
+       memset(out, 0, sizeof(out));
        return mlx5_cmd_exec_check_status(mdev, in, inlen, out, sizeof(out));
 }
 
-void mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev, u8 *addr)
+int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev,
+                                    u16 vport, u8 *addr)
 {
        u32 *out;
        int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
@@ -90,18 +145,287 @@ void mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev, u8 *addr)
 
        out = mlx5_vzalloc(outlen);
        if (!out)
-               return;
+               return -ENOMEM;
 
        out_addr = MLX5_ADDR_OF(query_nic_vport_context_out, out,
                                nic_vport_context.permanent_address);
 
-       err = mlx5_query_nic_vport_context(mdev, out, outlen);
+       err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
        if (!err)
                ether_addr_copy(addr, &out_addr[2]);
 
        kvfree(out);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_address);
+
+int mlx5_modify_nic_vport_mac_address(struct mlx5_core_dev *mdev,
+                                     u16 vport, u8 *addr)
+{
+       void *in;
+       int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
+       int err;
+       void *nic_vport_ctx;
+       u8 *perm_mac;
+
+       in = mlx5_vzalloc(inlen);
+       if (!in) {
+               mlx5_core_warn(mdev, "failed to allocate inbox\n");
+               return -ENOMEM;
+       }
+
+       MLX5_SET(modify_nic_vport_context_in, in,
+                field_select.permanent_address, 1);
+       MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
+
+       if (vport)
+               MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
+
+       nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
+                                    in, nic_vport_context);
+       perm_mac = MLX5_ADDR_OF(nic_vport_context, nic_vport_ctx,
+                               permanent_address);
+
+       ether_addr_copy(&perm_mac[2], addr);
+
+       err = mlx5_modify_nic_vport_context(mdev, in, inlen);
+
+       kvfree(in);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_address);
+
+int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
+                                 u32 vport,
+                                 enum mlx5_list_type list_type,
+                                 u8 addr_list[][ETH_ALEN],
+                                 int *list_size)
+{
+       u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];
+       void *nic_vport_ctx;
+       int max_list_size;
+       int req_list_size;
+       int out_sz;
+       void *out;
+       int err;
+       int i;
+
+       req_list_size = *list_size;
+
+       max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
+               1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
+               1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
+
+       if (req_list_size > max_list_size) {
+               mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
+                              req_list_size, max_list_size);
+               req_list_size = max_list_size;
+       }
+
+       out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
+                       req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
+
+       memset(in, 0, sizeof(in));
+       out = kzalloc(out_sz, GFP_KERNEL);
+       if (!out)
+               return -ENOMEM;
+
+       MLX5_SET(query_nic_vport_context_in, in, opcode,
+                MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
+       MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
+       MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
+
+       if (vport)
+               MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
+
+       err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_sz);
+       if (err)
+               goto out;
+
+       nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
+                                    nic_vport_context);
+       req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
+                                allowed_list_size);
+
+       *list_size = req_list_size;
+       for (i = 0; i < req_list_size; i++) {
+               u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
+                                       nic_vport_ctx,
+                                       current_uc_mac_address[i]) + 2;
+               ether_addr_copy(addr_list[i], mac_addr);
+       }
+out:
+       kfree(out);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list);
+
+int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
+                                  enum mlx5_list_type list_type,
+                                  u8 addr_list[][ETH_ALEN],
+                                  int list_size)
+{
+       u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
+       void *nic_vport_ctx;
+       int max_list_size;
+       int in_sz;
+       void *in;
+       int err;
+       int i;
+
+       max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
+                1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
+                1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
+
+       if (list_size > max_list_size)
+               return -ENOSPC;
+
+       in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
+               list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
+
+       memset(out, 0, sizeof(out));
+       in = kzalloc(in_sz, GFP_KERNEL);
+       if (!in)
+               return -ENOMEM;
+
+       MLX5_SET(modify_nic_vport_context_in, in, opcode,
+                MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
+       MLX5_SET(modify_nic_vport_context_in, in,
+                field_select.addresses_list, 1);
+
+       nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
+                                    nic_vport_context);
+
+       MLX5_SET(nic_vport_context, nic_vport_ctx,
+                allowed_list_type, list_type);
+       MLX5_SET(nic_vport_context, nic_vport_ctx,
+                allowed_list_size, list_size);
+
+       for (i = 0; i < list_size; i++) {
+               u8 *curr_mac = MLX5_ADDR_OF(nic_vport_context,
+                                           nic_vport_ctx,
+                                           current_uc_mac_address[i]) + 2;
+               ether_addr_copy(curr_mac, addr_list[i]);
+       }
+
+       err = mlx5_cmd_exec_check_status(dev, in, in_sz, out, sizeof(out));
+       kfree(in);
+       return err;
 }
-EXPORT_SYMBOL(mlx5_query_nic_vport_mac_address);
+EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
+
+int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,
+                              u32 vport,
+                              u16 vlans[],
+                              int *size)
+{
+       u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];
+       void *nic_vport_ctx;
+       int req_list_size;
+       int max_list_size;
+       int out_sz;
+       void *out;
+       int err;
+       int i;
+
+       req_list_size = *size;
+       max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
+       if (req_list_size > max_list_size) {
+               mlx5_core_warn(dev, "Requested list size (%d) > (%d) max list size\n",
+                              req_list_size, max_list_size);
+               req_list_size = max_list_size;
+       }
+
+       out_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
+                       req_list_size * MLX5_ST_SZ_BYTES(vlan_layout);
+
+       memset(in, 0, sizeof(in));
+       out = kzalloc(out_sz, GFP_KERNEL);
+       if (!out)
+               return -ENOMEM;
+
+       MLX5_SET(query_nic_vport_context_in, in, opcode,
+                MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
+       MLX5_SET(query_nic_vport_context_in, in, allowed_list_type,
+                MLX5_NVPRT_LIST_TYPE_VLAN);
+       MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
+
+       if (vport)
+               MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
+
+       err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, out_sz);
+       if (err)
+               goto out;
+
+       nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
+                                    nic_vport_context);
+       req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
+                                allowed_list_size);
+
+       *size = req_list_size;
+       for (i = 0; i < req_list_size; i++) {
+               void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
+                                              nic_vport_ctx,
+                                              current_uc_mac_address[i]);
+               vlans[i] = MLX5_GET(vlan_layout, vlan_addr, vlan);
+       }
+out:
+       kfree(out);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_vlans);
+
+int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
+                               u16 vlans[],
+                               int list_size)
+{
+       u32 out[MLX5_ST_SZ_DW(modify_nic_vport_context_out)];
+       void *nic_vport_ctx;
+       int max_list_size;
+       int in_sz;
+       void *in;
+       int err;
+       int i;
+
+       max_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);
+
+       if (list_size > max_list_size)
+               return -ENOSPC;
+
+       in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
+               list_size * MLX5_ST_SZ_BYTES(vlan_layout);
+
+       memset(out, 0, sizeof(out));
+       in = kzalloc(in_sz, GFP_KERNEL);
+       if (!in)
+               return -ENOMEM;
+
+       MLX5_SET(modify_nic_vport_context_in, in, opcode,
+                MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
+       MLX5_SET(modify_nic_vport_context_in, in,
+                field_select.addresses_list, 1);
+
+       nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in,
+                                    nic_vport_context);
+
+       MLX5_SET(nic_vport_context, nic_vport_ctx,
+                allowed_list_type, MLX5_NVPRT_LIST_TYPE_VLAN);
+       MLX5_SET(nic_vport_context, nic_vport_ctx,
+                allowed_list_size, list_size);
+
+       for (i = 0; i < list_size; i++) {
+               void *vlan_addr = MLX5_ADDR_OF(nic_vport_context,
+                                              nic_vport_ctx,
+                                              current_uc_mac_address[i]);
+               MLX5_SET(vlan_layout, vlan_addr, vlan, vlans[i]);
+       }
+
+       err = mlx5_cmd_exec_check_status(dev, in, in_sz, out, sizeof(out));
+       kfree(in);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans);
 
 int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
                                           u64 *system_image_guid)
@@ -113,7 +437,7 @@ int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
        if (!out)
                return -ENOMEM;
 
-       mlx5_query_nic_vport_context(mdev, out, outlen);
+       mlx5_query_nic_vport_context(mdev, 0, out, outlen);
 
        *system_image_guid = MLX5_GET64(query_nic_vport_context_out, out,
                                        nic_vport_context.system_image_guid);
@@ -133,7 +457,7 @@ int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
        if (!out)
                return -ENOMEM;
 
-       mlx5_query_nic_vport_context(mdev, out, outlen);
+       mlx5_query_nic_vport_context(mdev, 0, out, outlen);
 
        *node_guid = MLX5_GET64(query_nic_vport_context_out, out,
                                nic_vport_context.node_guid);
@@ -154,7 +478,7 @@ int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
        if (!out)
                return -ENOMEM;
 
-       mlx5_query_nic_vport_context(mdev, out, outlen);
+       mlx5_query_nic_vport_context(mdev, 0, out, outlen);
 
        *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out,
                                   nic_vport_context.qkey_violation_counter);
@@ -424,6 +748,68 @@ int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
 }
 EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
 
+int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
+                                u32 vport,
+                                int *promisc_uc,
+                                int *promisc_mc,
+                                int *promisc_all)
+{
+       u32 *out;
+       int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
+       int err;
+
+       out = kzalloc(outlen, GFP_KERNEL);
+       if (!out)
+               return -ENOMEM;
+
+       err = mlx5_query_nic_vport_context(mdev, vport, out, outlen);
+       if (err)
+               goto out;
+
+       *promisc_uc = MLX5_GET(query_nic_vport_context_out, out,
+                              nic_vport_context.promisc_uc);
+       *promisc_mc = MLX5_GET(query_nic_vport_context_out, out,
+                              nic_vport_context.promisc_mc);
+       *promisc_all = MLX5_GET(query_nic_vport_context_out, out,
+                               nic_vport_context.promisc_all);
+
+out:
+       kfree(out);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
+
+int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,
+                                 int promisc_uc,
+                                 int promisc_mc,
+                                 int promisc_all)
+{
+       void *in;
+       int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
+       int err;
+
+       in = mlx5_vzalloc(inlen);
+       if (!in) {
+               mlx5_core_err(mdev, "failed to allocate inbox\n");
+               return -ENOMEM;
+       }
+
+       MLX5_SET(modify_nic_vport_context_in, in, field_select.promisc, 1);
+       MLX5_SET(modify_nic_vport_context_in, in,
+                nic_vport_context.promisc_uc, promisc_uc);
+       MLX5_SET(modify_nic_vport_context_in, in,
+                nic_vport_context.promisc_mc, promisc_mc);
+       MLX5_SET(modify_nic_vport_context_in, in,
+                nic_vport_context.promisc_all, promisc_all);
+
+       err = mlx5_modify_nic_vport_context(mdev, in, inlen);
+
+       kvfree(in);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_promisc);
+
 enum mlx5_vport_roce_state {
        MLX5_VPORT_ROCE_DISABLED = 0,
        MLX5_VPORT_ROCE_ENABLED  = 1,
This page took 0.033867 seconds and 5 git commands to generate.