mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 05:32:00 +00:00
IB/mlx5: Implement callbacks for manipulating VFs
Implement the IB defined callbacks used to manipulate the policy for the link state, set GUIDs or get statistics information. This functionality is added into a new file that will be used to add any SRIOV related functionality to the mlx5 IB layer. The following callbacks have been added: mlx5_ib_get_vf_config mlx5_ib_set_vf_link_state mlx5_ib_get_vf_stats mlx5_ib_set_vf_guid In addition, publish whether this device is based on a virtual function. In mlx5 supported devices, virtual functions are implemented as vHCAs. vHCAs have their own QP number space so it is possible that two vHCAs will use a QP with the same number at the same time. Signed-off-by: Eli Cohen <eli@mellanox.com> Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
1f324bff9b
commit
eff901d30e
@ -1,4 +1,4 @@
|
||||
obj-$(CONFIG_MLX5_INFINIBAND) += mlx5_ib.o
|
||||
|
||||
mlx5_ib-y := main.o cq.o doorbell.o qp.o mem.o srq.o mr.o ah.o mad.o gsi.o
|
||||
mlx5_ib-y := main.o cq.o doorbell.o qp.o mem.o srq.o mr.o ah.o mad.o gsi.o ib_virt.o
|
||||
mlx5_ib-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += odp.o
|
||||
|
194
drivers/infiniband/hw/mlx5/ib_virt.c
Normal file
194
drivers/infiniband/hw/mlx5/ib_virt.c
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mlx5/vport.h>
|
||||
#include "mlx5_ib.h"
|
||||
|
||||
static inline u32 mlx_to_net_policy(enum port_state_policy mlx_policy)
|
||||
{
|
||||
switch (mlx_policy) {
|
||||
case MLX5_POLICY_DOWN:
|
||||
return IFLA_VF_LINK_STATE_DISABLE;
|
||||
case MLX5_POLICY_UP:
|
||||
return IFLA_VF_LINK_STATE_ENABLE;
|
||||
case MLX5_POLICY_FOLLOW:
|
||||
return IFLA_VF_LINK_STATE_AUTO;
|
||||
default:
|
||||
return __IFLA_VF_LINK_STATE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
int mlx5_ib_get_vf_config(struct ib_device *device, int vf, u8 port,
|
||||
struct ifla_vf_info *info)
|
||||
{
|
||||
struct mlx5_ib_dev *dev = to_mdev(device);
|
||||
struct mlx5_core_dev *mdev = dev->mdev;
|
||||
struct mlx5_hca_vport_context *rep;
|
||||
int err;
|
||||
|
||||
rep = kzalloc(sizeof(*rep), GFP_KERNEL);
|
||||
if (!rep)
|
||||
return -ENOMEM;
|
||||
|
||||
err = mlx5_query_hca_vport_context(mdev, 1, 1, vf + 1, rep);
|
||||
if (err) {
|
||||
mlx5_ib_warn(dev, "failed to query port policy for vf %d (%d)\n",
|
||||
vf, err);
|
||||
goto free;
|
||||
}
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->linkstate = mlx_to_net_policy(rep->policy);
|
||||
if (info->linkstate == __IFLA_VF_LINK_STATE_MAX)
|
||||
err = -EINVAL;
|
||||
|
||||
free:
|
||||
kfree(rep);
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline enum port_state_policy net_to_mlx_policy(int policy)
|
||||
{
|
||||
switch (policy) {
|
||||
case IFLA_VF_LINK_STATE_DISABLE:
|
||||
return MLX5_POLICY_DOWN;
|
||||
case IFLA_VF_LINK_STATE_ENABLE:
|
||||
return MLX5_POLICY_UP;
|
||||
case IFLA_VF_LINK_STATE_AUTO:
|
||||
return MLX5_POLICY_FOLLOW;
|
||||
default:
|
||||
return MLX5_POLICY_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
int mlx5_ib_set_vf_link_state(struct ib_device *device, int vf,
|
||||
u8 port, int state)
|
||||
{
|
||||
struct mlx5_ib_dev *dev = to_mdev(device);
|
||||
struct mlx5_core_dev *mdev = dev->mdev;
|
||||
struct mlx5_hca_vport_context *in;
|
||||
int err;
|
||||
|
||||
in = kzalloc(sizeof(*in), GFP_KERNEL);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
||||
in->policy = net_to_mlx_policy(state);
|
||||
if (in->policy == MLX5_POLICY_INVALID) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
in->field_select = MLX5_HCA_VPORT_SEL_STATE_POLICY;
|
||||
err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in);
|
||||
|
||||
out:
|
||||
kfree(in);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_ib_get_vf_stats(struct ib_device *device, int vf,
|
||||
u8 port, struct ifla_vf_stats *stats)
|
||||
{
|
||||
int out_sz = MLX5_ST_SZ_BYTES(query_vport_counter_out);
|
||||
struct mlx5_core_dev *mdev;
|
||||
struct mlx5_ib_dev *dev;
|
||||
void *out;
|
||||
int err;
|
||||
|
||||
dev = to_mdev(device);
|
||||
mdev = dev->mdev;
|
||||
|
||||
out = kzalloc(out_sz, GFP_KERNEL);
|
||||
if (!out)
|
||||
return -ENOMEM;
|
||||
|
||||
err = mlx5_core_query_vport_counter(mdev, true, vf, port, out, out_sz);
|
||||
if (err)
|
||||
goto ex;
|
||||
|
||||
stats->rx_packets = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_unicast.packets);
|
||||
stats->tx_packets = MLX5_GET64_PR(query_vport_counter_out, out, transmitted_ib_unicast.packets);
|
||||
stats->rx_bytes = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_unicast.octets);
|
||||
stats->tx_bytes = MLX5_GET64_PR(query_vport_counter_out, out, transmitted_ib_unicast.octets);
|
||||
stats->multicast = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_multicast.packets);
|
||||
|
||||
ex:
|
||||
kfree(out);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int set_vf_node_guid(struct ib_device *device, int vf, u8 port, u64 guid)
|
||||
{
|
||||
struct mlx5_ib_dev *dev = to_mdev(device);
|
||||
struct mlx5_core_dev *mdev = dev->mdev;
|
||||
struct mlx5_hca_vport_context *in;
|
||||
int err;
|
||||
|
||||
in = kzalloc(sizeof(*in), GFP_KERNEL);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
||||
in->field_select = MLX5_HCA_VPORT_SEL_NODE_GUID;
|
||||
in->node_guid = guid;
|
||||
err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in);
|
||||
kfree(in);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int set_vf_port_guid(struct ib_device *device, int vf, u8 port, u64 guid)
|
||||
{
|
||||
struct mlx5_ib_dev *dev = to_mdev(device);
|
||||
struct mlx5_core_dev *mdev = dev->mdev;
|
||||
struct mlx5_hca_vport_context *in;
|
||||
int err;
|
||||
|
||||
in = kzalloc(sizeof(*in), GFP_KERNEL);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
||||
in->field_select = MLX5_HCA_VPORT_SEL_PORT_GUID;
|
||||
in->port_guid = guid;
|
||||
err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in);
|
||||
kfree(in);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_ib_set_vf_guid(struct ib_device *device, int vf, u8 port,
|
||||
u64 guid, int type)
|
||||
{
|
||||
if (type == IFLA_VF_IB_NODE_GUID)
|
||||
return set_vf_node_guid(device, vf, port, guid);
|
||||
else if (type == IFLA_VF_IB_PORT_GUID)
|
||||
return set_vf_port_guid(device, vf, port, guid);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
@ -562,6 +562,9 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
|
||||
if (MLX5_CAP_GEN(mdev, cd))
|
||||
props->device_cap_flags |= IB_DEVICE_CROSS_CHANNEL;
|
||||
|
||||
if (!mlx5_core_is_pf(mdev))
|
||||
props->device_cap_flags |= IB_DEVICE_VIRTUAL_FUNCTION;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -699,6 +702,7 @@ static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port,
|
||||
props->qkey_viol_cntr = rep->qkey_violation_counter;
|
||||
props->subnet_timeout = rep->subnet_timeout;
|
||||
props->init_type_reply = rep->init_type_reply;
|
||||
props->grh_required = rep->grh_required;
|
||||
|
||||
err = mlx5_query_port_link_width_oper(mdev, &ib_link_width_oper, port);
|
||||
if (err)
|
||||
@ -2349,6 +2353,12 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
|
||||
dev->ib_dev.map_mr_sg = mlx5_ib_map_mr_sg;
|
||||
dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
|
||||
dev->ib_dev.get_port_immutable = mlx5_port_immutable;
|
||||
if (mlx5_core_is_pf(mdev)) {
|
||||
dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config;
|
||||
dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state;
|
||||
dev->ib_dev.get_vf_stats = mlx5_ib_get_vf_stats;
|
||||
dev->ib_dev.set_vf_guid = mlx5_ib_set_vf_guid;
|
||||
}
|
||||
|
||||
mlx5_ib_internal_fill_odp_caps(dev);
|
||||
|
||||
|
@ -776,6 +776,14 @@ void mlx5_ib_qp_disable_pagefaults(struct mlx5_ib_qp *qp);
|
||||
void mlx5_ib_qp_enable_pagefaults(struct mlx5_ib_qp *qp);
|
||||
void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start,
|
||||
unsigned long end);
|
||||
int mlx5_ib_get_vf_config(struct ib_device *device, int vf,
|
||||
u8 port, struct ifla_vf_info *info);
|
||||
int mlx5_ib_set_vf_link_state(struct ib_device *device, int vf,
|
||||
u8 port, int state);
|
||||
int mlx5_ib_get_vf_stats(struct ib_device *device, int vf,
|
||||
u8 port, struct ifla_vf_stats *stats);
|
||||
int mlx5_ib_set_vf_guid(struct ib_device *device, int vf, u8 port,
|
||||
u64 guid, int type);
|
||||
|
||||
#else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */
|
||||
static inline void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
|
||||
|
@ -613,7 +613,10 @@ struct mlx5_pas {
|
||||
};
|
||||
|
||||
enum port_state_policy {
|
||||
MLX5_AAA_000
|
||||
MLX5_POLICY_DOWN = 0,
|
||||
MLX5_POLICY_UP = 1,
|
||||
MLX5_POLICY_FOLLOW = 2,
|
||||
MLX5_POLICY_INVALID = 0xffffffff
|
||||
};
|
||||
|
||||
enum phy_port_state {
|
||||
|
@ -3696,6 +3696,12 @@ struct mlx5_ifc_query_hca_vport_pkey_in_bits {
|
||||
u8 pkey_index[0x10];
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_HCA_VPORT_SEL_PORT_GUID = 1 << 0,
|
||||
MLX5_HCA_VPORT_SEL_NODE_GUID = 1 << 1,
|
||||
MLX5_HCA_VPORT_SEL_STATE_POLICY = 1 << 2,
|
||||
};
|
||||
|
||||
struct mlx5_ifc_query_hca_vport_gid_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_at_8[0x18];
|
||||
|
Loading…
Reference in New Issue
Block a user