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 51eff901d3SEli Cohen int mlx5_ib_get_vf_config(struct ib_device *device, int vf, u8 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, 94eff901d3SEli Cohen u8 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; 99*7ecf6d8fSBodong 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); 113*7ecf6d8fSBodong Wang if (!err) 114*7ecf6d8fSBodong 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, 122eff901d3SEli Cohen u8 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 137eff901d3SEli Cohen err = mlx5_core_query_vport_counter(mdev, true, vf, port, out, out_sz); 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 152eff901d3SEli Cohen static int set_vf_node_guid(struct ib_device *device, int vf, u8 port, u64 guid) 153eff901d3SEli Cohen { 154eff901d3SEli Cohen struct mlx5_ib_dev *dev = to_mdev(device); 155eff901d3SEli Cohen struct mlx5_core_dev *mdev = dev->mdev; 156eff901d3SEli Cohen struct mlx5_hca_vport_context *in; 157*7ecf6d8fSBodong Wang struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx; 158eff901d3SEli Cohen int err; 159eff901d3SEli Cohen 160eff901d3SEli Cohen in = kzalloc(sizeof(*in), GFP_KERNEL); 161eff901d3SEli Cohen if (!in) 162eff901d3SEli Cohen return -ENOMEM; 163eff901d3SEli Cohen 164eff901d3SEli Cohen in->field_select = MLX5_HCA_VPORT_SEL_NODE_GUID; 165eff901d3SEli Cohen in->node_guid = guid; 166eff901d3SEli Cohen err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in); 167*7ecf6d8fSBodong Wang if (!err) 168*7ecf6d8fSBodong Wang vfs_ctx[vf].node_guid = guid; 169eff901d3SEli Cohen kfree(in); 170eff901d3SEli Cohen return err; 171eff901d3SEli Cohen } 172eff901d3SEli Cohen 173eff901d3SEli Cohen static int set_vf_port_guid(struct ib_device *device, int vf, u8 port, u64 guid) 174eff901d3SEli Cohen { 175eff901d3SEli Cohen struct mlx5_ib_dev *dev = to_mdev(device); 176eff901d3SEli Cohen struct mlx5_core_dev *mdev = dev->mdev; 177eff901d3SEli Cohen struct mlx5_hca_vport_context *in; 178*7ecf6d8fSBodong Wang struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx; 179eff901d3SEli Cohen int err; 180eff901d3SEli Cohen 181eff901d3SEli Cohen in = kzalloc(sizeof(*in), GFP_KERNEL); 182eff901d3SEli Cohen if (!in) 183eff901d3SEli Cohen return -ENOMEM; 184eff901d3SEli Cohen 185eff901d3SEli Cohen in->field_select = MLX5_HCA_VPORT_SEL_PORT_GUID; 186eff901d3SEli Cohen in->port_guid = guid; 187eff901d3SEli Cohen err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in); 188*7ecf6d8fSBodong Wang if (!err) 189*7ecf6d8fSBodong Wang vfs_ctx[vf].port_guid = guid; 190eff901d3SEli Cohen kfree(in); 191eff901d3SEli Cohen return err; 192eff901d3SEli Cohen } 193eff901d3SEli Cohen 194eff901d3SEli Cohen int mlx5_ib_set_vf_guid(struct ib_device *device, int vf, u8 port, 195eff901d3SEli Cohen u64 guid, int type) 196eff901d3SEli Cohen { 197eff901d3SEli Cohen if (type == IFLA_VF_IB_NODE_GUID) 198eff901d3SEli Cohen return set_vf_node_guid(device, vf, port, guid); 199eff901d3SEli Cohen else if (type == IFLA_VF_IB_PORT_GUID) 200eff901d3SEli Cohen return set_vf_port_guid(device, vf, port, guid); 201eff901d3SEli Cohen 202eff901d3SEli Cohen return -EINVAL; 203eff901d3SEli Cohen } 204