Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
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 }