1eff901d3SEli Cohen /* 2eff901d3SEli Cohen * Copyright (c) 2016, Mellanox Technologies. All rights reserved. 3eff901d3SEli Cohen * 4eff901d3SEli Cohen * This software is available to you under a choice of one of two 5eff901d3SEli Cohen * licenses. You may choose to be licensed under the terms of the GNU 6eff901d3SEli Cohen * General Public License (GPL) Version 2, available from the file 7eff901d3SEli Cohen * COPYING in the main directory of this source tree, or the 8eff901d3SEli Cohen * OpenIB.org BSD license below: 9eff901d3SEli Cohen * 10eff901d3SEli Cohen * Redistribution and use in source and binary forms, with or 11eff901d3SEli Cohen * without modification, are permitted provided that the following 12eff901d3SEli Cohen * conditions are met: 13eff901d3SEli Cohen * 14eff901d3SEli Cohen * - Redistributions of source code must retain the above 15eff901d3SEli Cohen * copyright notice, this list of conditions and the following 16eff901d3SEli Cohen * disclaimer. 17eff901d3SEli Cohen * 18eff901d3SEli Cohen * - Redistributions in binary form must reproduce the above 19eff901d3SEli Cohen * copyright notice, this list of conditions and the following 20eff901d3SEli Cohen * disclaimer in the documentation and/or other materials 21eff901d3SEli Cohen * provided with the distribution. 22eff901d3SEli Cohen * 23eff901d3SEli Cohen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24eff901d3SEli Cohen * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25eff901d3SEli Cohen * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26eff901d3SEli Cohen * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27eff901d3SEli Cohen * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28eff901d3SEli Cohen * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29eff901d3SEli Cohen * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30eff901d3SEli Cohen * SOFTWARE. 31eff901d3SEli Cohen */ 32eff901d3SEli Cohen 33eff901d3SEli Cohen #include <linux/module.h> 34eff901d3SEli Cohen #include <linux/mlx5/vport.h> 35eff901d3SEli Cohen #include "mlx5_ib.h" 36eff901d3SEli Cohen 37eff901d3SEli Cohen static inline u32 mlx_to_net_policy(enum port_state_policy mlx_policy) 38eff901d3SEli Cohen { 39eff901d3SEli Cohen switch (mlx_policy) { 40eff901d3SEli Cohen case MLX5_POLICY_DOWN: 41eff901d3SEli Cohen return IFLA_VF_LINK_STATE_DISABLE; 42eff901d3SEli Cohen case MLX5_POLICY_UP: 43eff901d3SEli Cohen return IFLA_VF_LINK_STATE_ENABLE; 44eff901d3SEli Cohen case MLX5_POLICY_FOLLOW: 45eff901d3SEli Cohen return IFLA_VF_LINK_STATE_AUTO; 46eff901d3SEli Cohen default: 47eff901d3SEli Cohen return __IFLA_VF_LINK_STATE_MAX; 48eff901d3SEli Cohen } 49eff901d3SEli Cohen } 50eff901d3SEli Cohen 51*1fb7f897SMark Bloch int mlx5_ib_get_vf_config(struct ib_device *device, int vf, u32 port, 52eff901d3SEli Cohen struct ifla_vf_info *info) 53eff901d3SEli Cohen { 54eff901d3SEli Cohen struct mlx5_ib_dev *dev = to_mdev(device); 55eff901d3SEli Cohen struct mlx5_core_dev *mdev = dev->mdev; 56eff901d3SEli Cohen struct mlx5_hca_vport_context *rep; 57eff901d3SEli Cohen int err; 58eff901d3SEli Cohen 59eff901d3SEli Cohen rep = kzalloc(sizeof(*rep), GFP_KERNEL); 60eff901d3SEli Cohen if (!rep) 61eff901d3SEli Cohen return -ENOMEM; 62eff901d3SEli Cohen 63eff901d3SEli Cohen err = mlx5_query_hca_vport_context(mdev, 1, 1, vf + 1, rep); 64eff901d3SEli Cohen if (err) { 65eff901d3SEli Cohen mlx5_ib_warn(dev, "failed to query port policy for vf %d (%d)\n", 66eff901d3SEli Cohen vf, err); 67eff901d3SEli Cohen goto free; 68eff901d3SEli Cohen } 69eff901d3SEli Cohen memset(info, 0, sizeof(*info)); 70eff901d3SEli Cohen info->linkstate = mlx_to_net_policy(rep->policy); 71eff901d3SEli Cohen if (info->linkstate == __IFLA_VF_LINK_STATE_MAX) 72eff901d3SEli Cohen err = -EINVAL; 73eff901d3SEli Cohen 74eff901d3SEli Cohen free: 75eff901d3SEli Cohen kfree(rep); 76eff901d3SEli Cohen return err; 77eff901d3SEli Cohen } 78eff901d3SEli Cohen 79eff901d3SEli Cohen static inline enum port_state_policy net_to_mlx_policy(int policy) 80eff901d3SEli Cohen { 81eff901d3SEli Cohen switch (policy) { 82eff901d3SEli Cohen case IFLA_VF_LINK_STATE_DISABLE: 83eff901d3SEli Cohen return MLX5_POLICY_DOWN; 84eff901d3SEli Cohen case IFLA_VF_LINK_STATE_ENABLE: 85eff901d3SEli Cohen return MLX5_POLICY_UP; 86eff901d3SEli Cohen case IFLA_VF_LINK_STATE_AUTO: 87eff901d3SEli Cohen return MLX5_POLICY_FOLLOW; 88eff901d3SEli Cohen default: 89eff901d3SEli Cohen return MLX5_POLICY_INVALID; 90eff901d3SEli Cohen } 91eff901d3SEli Cohen } 92eff901d3SEli Cohen 93eff901d3SEli Cohen int mlx5_ib_set_vf_link_state(struct ib_device *device, int vf, 94*1fb7f897SMark Bloch u32 port, int state) 95eff901d3SEli Cohen { 96eff901d3SEli Cohen struct mlx5_ib_dev *dev = to_mdev(device); 97eff901d3SEli Cohen struct mlx5_core_dev *mdev = dev->mdev; 98eff901d3SEli Cohen struct mlx5_hca_vport_context *in; 997ecf6d8fSBodong Wang struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx; 100eff901d3SEli Cohen int err; 101eff901d3SEli Cohen 102eff901d3SEli Cohen in = kzalloc(sizeof(*in), GFP_KERNEL); 103eff901d3SEli Cohen if (!in) 104eff901d3SEli Cohen return -ENOMEM; 105eff901d3SEli Cohen 106eff901d3SEli Cohen in->policy = net_to_mlx_policy(state); 107eff901d3SEli Cohen if (in->policy == MLX5_POLICY_INVALID) { 108eff901d3SEli Cohen err = -EINVAL; 109eff901d3SEli Cohen goto out; 110eff901d3SEli Cohen } 111eff901d3SEli Cohen in->field_select = MLX5_HCA_VPORT_SEL_STATE_POLICY; 112eff901d3SEli Cohen err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in); 1137ecf6d8fSBodong Wang if (!err) 1147ecf6d8fSBodong Wang vfs_ctx[vf].policy = in->policy; 115eff901d3SEli Cohen 116eff901d3SEli Cohen out: 117eff901d3SEli Cohen kfree(in); 118eff901d3SEli Cohen return err; 119eff901d3SEli Cohen } 120eff901d3SEli Cohen 121eff901d3SEli Cohen int mlx5_ib_get_vf_stats(struct ib_device *device, int vf, 122*1fb7f897SMark Bloch u32 port, struct ifla_vf_stats *stats) 123eff901d3SEli Cohen { 124eff901d3SEli Cohen int out_sz = MLX5_ST_SZ_BYTES(query_vport_counter_out); 125eff901d3SEli Cohen struct mlx5_core_dev *mdev; 126eff901d3SEli Cohen struct mlx5_ib_dev *dev; 127eff901d3SEli Cohen void *out; 128eff901d3SEli Cohen int err; 129eff901d3SEli Cohen 130eff901d3SEli Cohen dev = to_mdev(device); 131eff901d3SEli Cohen mdev = dev->mdev; 132eff901d3SEli Cohen 133eff901d3SEli Cohen out = kzalloc(out_sz, GFP_KERNEL); 134eff901d3SEli Cohen if (!out) 135eff901d3SEli Cohen return -ENOMEM; 136eff901d3SEli Cohen 1375d1c9a11SLeon Romanovsky err = mlx5_core_query_vport_counter(mdev, true, vf, port, out); 138eff901d3SEli Cohen if (err) 139eff901d3SEli Cohen goto ex; 140eff901d3SEli Cohen 141eff901d3SEli Cohen stats->rx_packets = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_unicast.packets); 142eff901d3SEli Cohen stats->tx_packets = MLX5_GET64_PR(query_vport_counter_out, out, transmitted_ib_unicast.packets); 143eff901d3SEli Cohen stats->rx_bytes = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_unicast.octets); 144eff901d3SEli Cohen stats->tx_bytes = MLX5_GET64_PR(query_vport_counter_out, out, transmitted_ib_unicast.octets); 145eff901d3SEli Cohen stats->multicast = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_multicast.packets); 146eff901d3SEli Cohen 147eff901d3SEli Cohen ex: 148eff901d3SEli Cohen kfree(out); 149eff901d3SEli Cohen return err; 150eff901d3SEli Cohen } 151eff901d3SEli Cohen 152*1fb7f897SMark Bloch static int set_vf_node_guid(struct ib_device *device, int vf, u32 port, 153*1fb7f897SMark Bloch u64 guid) 154eff901d3SEli Cohen { 155eff901d3SEli Cohen struct mlx5_ib_dev *dev = to_mdev(device); 156eff901d3SEli Cohen struct mlx5_core_dev *mdev = dev->mdev; 157eff901d3SEli Cohen struct mlx5_hca_vport_context *in; 1587ecf6d8fSBodong Wang struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx; 159eff901d3SEli Cohen int err; 160eff901d3SEli Cohen 161eff901d3SEli Cohen in = kzalloc(sizeof(*in), GFP_KERNEL); 162eff901d3SEli Cohen if (!in) 163eff901d3SEli Cohen return -ENOMEM; 164eff901d3SEli Cohen 165eff901d3SEli Cohen in->field_select = MLX5_HCA_VPORT_SEL_NODE_GUID; 166eff901d3SEli Cohen in->node_guid = guid; 167eff901d3SEli Cohen err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in); 1684bbd4923SDanit Goldberg if (!err) { 1697ecf6d8fSBodong Wang vfs_ctx[vf].node_guid = guid; 1704bbd4923SDanit Goldberg vfs_ctx[vf].node_guid_valid = 1; 1714bbd4923SDanit Goldberg } 172eff901d3SEli Cohen kfree(in); 173eff901d3SEli Cohen return err; 174eff901d3SEli Cohen } 175eff901d3SEli Cohen 176*1fb7f897SMark Bloch static int set_vf_port_guid(struct ib_device *device, int vf, u32 port, 177*1fb7f897SMark Bloch u64 guid) 178eff901d3SEli Cohen { 179eff901d3SEli Cohen struct mlx5_ib_dev *dev = to_mdev(device); 180eff901d3SEli Cohen struct mlx5_core_dev *mdev = dev->mdev; 181eff901d3SEli Cohen struct mlx5_hca_vport_context *in; 1827ecf6d8fSBodong Wang struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx; 183eff901d3SEli Cohen int err; 184eff901d3SEli Cohen 185eff901d3SEli Cohen in = kzalloc(sizeof(*in), GFP_KERNEL); 186eff901d3SEli Cohen if (!in) 187eff901d3SEli Cohen return -ENOMEM; 188eff901d3SEli Cohen 189eff901d3SEli Cohen in->field_select = MLX5_HCA_VPORT_SEL_PORT_GUID; 190eff901d3SEli Cohen in->port_guid = guid; 191eff901d3SEli Cohen err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in); 1924bbd4923SDanit Goldberg if (!err) { 1937ecf6d8fSBodong Wang vfs_ctx[vf].port_guid = guid; 1944bbd4923SDanit Goldberg vfs_ctx[vf].port_guid_valid = 1; 1954bbd4923SDanit Goldberg } 196eff901d3SEli Cohen kfree(in); 197eff901d3SEli Cohen return err; 198eff901d3SEli Cohen } 199eff901d3SEli Cohen 200*1fb7f897SMark Bloch int mlx5_ib_set_vf_guid(struct ib_device *device, int vf, u32 port, 201eff901d3SEli Cohen u64 guid, int type) 202eff901d3SEli Cohen { 203eff901d3SEli Cohen if (type == IFLA_VF_IB_NODE_GUID) 204eff901d3SEli Cohen return set_vf_node_guid(device, vf, port, guid); 205eff901d3SEli Cohen else if (type == IFLA_VF_IB_PORT_GUID) 206eff901d3SEli Cohen return set_vf_port_guid(device, vf, port, guid); 207eff901d3SEli Cohen 208eff901d3SEli Cohen return -EINVAL; 209eff901d3SEli Cohen } 2109c0015efSDanit Goldberg 211*1fb7f897SMark Bloch int mlx5_ib_get_vf_guid(struct ib_device *device, int vf, u32 port, 2129c0015efSDanit Goldberg struct ifla_vf_guid *node_guid, 2139c0015efSDanit Goldberg struct ifla_vf_guid *port_guid) 2149c0015efSDanit Goldberg { 2159c0015efSDanit Goldberg struct mlx5_ib_dev *dev = to_mdev(device); 2169c0015efSDanit Goldberg struct mlx5_core_dev *mdev = dev->mdev; 2174bbd4923SDanit Goldberg struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx; 2189c0015efSDanit Goldberg 2194bbd4923SDanit Goldberg node_guid->guid = 2204bbd4923SDanit Goldberg vfs_ctx[vf].node_guid_valid ? vfs_ctx[vf].node_guid : 0; 2214bbd4923SDanit Goldberg port_guid->guid = 2224bbd4923SDanit Goldberg vfs_ctx[vf].port_guid_valid ? vfs_ctx[vf].port_guid : 0; 2239c0015efSDanit Goldberg 2244bbd4923SDanit Goldberg return 0; 2259c0015efSDanit Goldberg } 226