0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/mlx5/vport.h>
0034 #include "mlx5_ib.h"
0035
0036 static inline u32 mlx_to_net_policy(enum port_state_policy mlx_policy)
0037 {
0038 switch (mlx_policy) {
0039 case MLX5_POLICY_DOWN:
0040 return IFLA_VF_LINK_STATE_DISABLE;
0041 case MLX5_POLICY_UP:
0042 return IFLA_VF_LINK_STATE_ENABLE;
0043 case MLX5_POLICY_FOLLOW:
0044 return IFLA_VF_LINK_STATE_AUTO;
0045 default:
0046 return __IFLA_VF_LINK_STATE_MAX;
0047 }
0048 }
0049
0050 int mlx5_ib_get_vf_config(struct ib_device *device, int vf, u32 port,
0051 struct ifla_vf_info *info)
0052 {
0053 struct mlx5_ib_dev *dev = to_mdev(device);
0054 struct mlx5_core_dev *mdev = dev->mdev;
0055 struct mlx5_hca_vport_context *rep;
0056 int err;
0057
0058 rep = kzalloc(sizeof(*rep), GFP_KERNEL);
0059 if (!rep)
0060 return -ENOMEM;
0061
0062 err = mlx5_query_hca_vport_context(mdev, 1, 1, vf + 1, rep);
0063 if (err) {
0064 mlx5_ib_warn(dev, "failed to query port policy for vf %d (%d)\n",
0065 vf, err);
0066 goto free;
0067 }
0068 memset(info, 0, sizeof(*info));
0069 info->linkstate = mlx_to_net_policy(rep->policy);
0070 if (info->linkstate == __IFLA_VF_LINK_STATE_MAX)
0071 err = -EINVAL;
0072
0073 free:
0074 kfree(rep);
0075 return err;
0076 }
0077
0078 static inline enum port_state_policy net_to_mlx_policy(int policy)
0079 {
0080 switch (policy) {
0081 case IFLA_VF_LINK_STATE_DISABLE:
0082 return MLX5_POLICY_DOWN;
0083 case IFLA_VF_LINK_STATE_ENABLE:
0084 return MLX5_POLICY_UP;
0085 case IFLA_VF_LINK_STATE_AUTO:
0086 return MLX5_POLICY_FOLLOW;
0087 default:
0088 return MLX5_POLICY_INVALID;
0089 }
0090 }
0091
0092 int mlx5_ib_set_vf_link_state(struct ib_device *device, int vf,
0093 u32 port, int state)
0094 {
0095 struct mlx5_ib_dev *dev = to_mdev(device);
0096 struct mlx5_core_dev *mdev = dev->mdev;
0097 struct mlx5_hca_vport_context *in;
0098 struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx;
0099 int err;
0100
0101 in = kzalloc(sizeof(*in), GFP_KERNEL);
0102 if (!in)
0103 return -ENOMEM;
0104
0105 in->policy = net_to_mlx_policy(state);
0106 if (in->policy == MLX5_POLICY_INVALID) {
0107 err = -EINVAL;
0108 goto out;
0109 }
0110 in->field_select = MLX5_HCA_VPORT_SEL_STATE_POLICY;
0111 err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in);
0112 if (!err)
0113 vfs_ctx[vf].policy = in->policy;
0114
0115 out:
0116 kfree(in);
0117 return err;
0118 }
0119
0120 int mlx5_ib_get_vf_stats(struct ib_device *device, int vf,
0121 u32 port, struct ifla_vf_stats *stats)
0122 {
0123 int out_sz = MLX5_ST_SZ_BYTES(query_vport_counter_out);
0124 struct mlx5_core_dev *mdev;
0125 struct mlx5_ib_dev *dev;
0126 void *out;
0127 int err;
0128
0129 dev = to_mdev(device);
0130 mdev = dev->mdev;
0131
0132 out = kzalloc(out_sz, GFP_KERNEL);
0133 if (!out)
0134 return -ENOMEM;
0135
0136 err = mlx5_core_query_vport_counter(mdev, true, vf, port, out);
0137 if (err)
0138 goto ex;
0139
0140 stats->rx_packets = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_unicast.packets);
0141 stats->tx_packets = MLX5_GET64_PR(query_vport_counter_out, out, transmitted_ib_unicast.packets);
0142 stats->rx_bytes = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_unicast.octets);
0143 stats->tx_bytes = MLX5_GET64_PR(query_vport_counter_out, out, transmitted_ib_unicast.octets);
0144 stats->multicast = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_multicast.packets);
0145
0146 ex:
0147 kfree(out);
0148 return err;
0149 }
0150
0151 static int set_vf_node_guid(struct ib_device *device, int vf, u32 port,
0152 u64 guid)
0153 {
0154 struct mlx5_ib_dev *dev = to_mdev(device);
0155 struct mlx5_core_dev *mdev = dev->mdev;
0156 struct mlx5_hca_vport_context *in;
0157 struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx;
0158 int err;
0159
0160 in = kzalloc(sizeof(*in), GFP_KERNEL);
0161 if (!in)
0162 return -ENOMEM;
0163
0164 in->field_select = MLX5_HCA_VPORT_SEL_NODE_GUID;
0165 in->node_guid = guid;
0166 err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in);
0167 if (!err) {
0168 vfs_ctx[vf].node_guid = guid;
0169 vfs_ctx[vf].node_guid_valid = 1;
0170 }
0171 kfree(in);
0172 return err;
0173 }
0174
0175 static int set_vf_port_guid(struct ib_device *device, int vf, u32 port,
0176 u64 guid)
0177 {
0178 struct mlx5_ib_dev *dev = to_mdev(device);
0179 struct mlx5_core_dev *mdev = dev->mdev;
0180 struct mlx5_hca_vport_context *in;
0181 struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx;
0182 int err;
0183
0184 in = kzalloc(sizeof(*in), GFP_KERNEL);
0185 if (!in)
0186 return -ENOMEM;
0187
0188 in->field_select = MLX5_HCA_VPORT_SEL_PORT_GUID;
0189 in->port_guid = guid;
0190 err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in);
0191 if (!err) {
0192 vfs_ctx[vf].port_guid = guid;
0193 vfs_ctx[vf].port_guid_valid = 1;
0194 }
0195 kfree(in);
0196 return err;
0197 }
0198
0199 int mlx5_ib_set_vf_guid(struct ib_device *device, int vf, u32 port,
0200 u64 guid, int type)
0201 {
0202 if (type == IFLA_VF_IB_NODE_GUID)
0203 return set_vf_node_guid(device, vf, port, guid);
0204 else if (type == IFLA_VF_IB_PORT_GUID)
0205 return set_vf_port_guid(device, vf, port, guid);
0206
0207 return -EINVAL;
0208 }
0209
0210 int mlx5_ib_get_vf_guid(struct ib_device *device, int vf, u32 port,
0211 struct ifla_vf_guid *node_guid,
0212 struct ifla_vf_guid *port_guid)
0213 {
0214 struct mlx5_ib_dev *dev = to_mdev(device);
0215 struct mlx5_core_dev *mdev = dev->mdev;
0216 struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx;
0217
0218 node_guid->guid =
0219 vfs_ctx[vf].node_guid_valid ? vfs_ctx[vf].node_guid : 0;
0220 port_guid->guid =
0221 vfs_ctx[vf].port_guid_valid ? vfs_ctx[vf].port_guid : 0;
0222
0223 return 0;
0224 }