IB/mlx5: Restore IB guid/policy for virtual functions
authorBodong Wang <bodong@mellanox.com>
Tue, 30 May 2017 07:18:24 +0000 (10:18 +0300)
committerDoug Ledford <dledford@redhat.com>
Mon, 24 Jul 2017 14:34:28 +0000 (10:34 -0400)
When a user sets port_guid, node_guid or policy of an IB virtual
function, save this information in "struct mlx5_vf_context".

This information will be restored later when pci_resume is called.
To make sure this works, one can use aer-inject to generate PCI
errors on mlx5 devices and verify if relevant fields are restored
after PCI resume.

Signed-off-by: Bodong Wang <bodong@mellanox.com>
Reviewed-by: Eli Cohen <eli@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/mlx5/ib_virt.c
drivers/net/ethernet/mellanox/mlx5/core/sriov.c
include/linux/mlx5/driver.h

index c1b9de800fe5d015777f42cf45229145f4dc6bce..649a3364f8380e802760878fb00d05e784a8ec4b 100644 (file)
@@ -96,6 +96,7 @@ int mlx5_ib_set_vf_link_state(struct ib_device *device, int vf,
        struct mlx5_ib_dev *dev = to_mdev(device);
        struct mlx5_core_dev *mdev = dev->mdev;
        struct mlx5_hca_vport_context *in;
+       struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx;
        int err;
 
        in = kzalloc(sizeof(*in), GFP_KERNEL);
@@ -109,6 +110,8 @@ int mlx5_ib_set_vf_link_state(struct ib_device *device, int vf,
        }
        in->field_select = MLX5_HCA_VPORT_SEL_STATE_POLICY;
        err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in);
+       if (!err)
+               vfs_ctx[vf].policy = in->policy;
 
 out:
        kfree(in);
@@ -151,6 +154,7 @@ 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;
+       struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx;
        int err;
 
        in = kzalloc(sizeof(*in), GFP_KERNEL);
@@ -160,6 +164,8 @@ static int set_vf_node_guid(struct ib_device *device, int vf, u8 port, u64 guid)
        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);
+       if (!err)
+               vfs_ctx[vf].node_guid = guid;
        kfree(in);
        return err;
 }
@@ -169,6 +175,7 @@ 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;
+       struct mlx5_vf_context *vfs_ctx = mdev->priv.sriov.vfs_ctx;
        int err;
 
        in = kzalloc(sizeof(*in), GFP_KERNEL);
@@ -178,6 +185,8 @@ static int set_vf_port_guid(struct ib_device *device, int vf, u8 port, u64 guid)
        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);
+       if (!err)
+               vfs_ctx[vf].port_guid = guid;
        kfree(in);
        return err;
 }
index bcdf7779c48d79ffb85f3505e122210d16e9b46d..090b29e05a6a9e24aedef1cf7a8a75d9cf7489ec 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <linux/pci.h>
 #include <linux/mlx5/driver.h>
+#include <linux/mlx5/vport.h>
 #include "mlx5_core.h"
 #ifdef CONFIG_MLX5_CORE_EN
 #include "eswitch.h"
@@ -44,6 +45,38 @@ bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev)
        return !!sriov->num_vfs;
 }
 
+static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf)
+{
+       struct mlx5_core_sriov *sriov = &dev->priv.sriov;
+       struct mlx5_hca_vport_context *in;
+       int err = 0;
+
+       /* Restore sriov guid and policy settings */
+       if (sriov->vfs_ctx[vf].node_guid ||
+           sriov->vfs_ctx[vf].port_guid ||
+           sriov->vfs_ctx[vf].policy != MLX5_POLICY_INVALID) {
+               in = kzalloc(sizeof(*in), GFP_KERNEL);
+               if (!in)
+                       return -ENOMEM;
+
+               in->node_guid = sriov->vfs_ctx[vf].node_guid;
+               in->port_guid = sriov->vfs_ctx[vf].port_guid;
+               in->policy = sriov->vfs_ctx[vf].policy;
+               in->field_select =
+                       !!(in->port_guid) * MLX5_HCA_VPORT_SEL_PORT_GUID |
+                       !!(in->node_guid) * MLX5_HCA_VPORT_SEL_NODE_GUID |
+                       !!(in->policy) * MLX5_HCA_VPORT_SEL_STATE_POLICY;
+
+               err = mlx5_core_modify_hca_vport_context(dev, 1, 1, vf + 1, in);
+               if (err)
+                       mlx5_core_warn(dev, "modify vport context failed, unable to restore VF %d settings\n", vf);
+
+               kfree(in);
+       }
+
+       return err;
+}
+
 static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
 {
        struct mlx5_core_sriov *sriov = &dev->priv.sriov;
@@ -74,6 +107,15 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
                }
                sriov->vfs_ctx[vf].enabled = 1;
                sriov->enabled_vfs++;
+               if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) {
+                       err = sriov_restore_guids(dev, vf);
+                       if (err) {
+                               mlx5_core_warn(dev,
+                                              "failed to restore VF %d settings, err %d\n",
+                                              vf, err);
+                       continue;
+                       }
+               }
                mlx5_core_dbg(dev, "successfully enabled VF* %d\n", vf);
 
        }
index df6ce59a1f954257cdef95a7733736e42c8b9491..54221be5f69e0cc4f4412658673b7dde725822f7 100644 (file)
@@ -162,6 +162,13 @@ enum dbg_rsc_type {
        MLX5_DBG_RSC_CQ,
 };
 
+enum port_state_policy {
+       MLX5_POLICY_DOWN        = 0,
+       MLX5_POLICY_UP          = 1,
+       MLX5_POLICY_FOLLOW      = 2,
+       MLX5_POLICY_INVALID     = 0xffffffff
+};
+
 struct mlx5_field_desc {
        struct dentry          *dent;
        int                     i;
@@ -525,6 +532,9 @@ struct mlx5_mkey_table {
 
 struct mlx5_vf_context {
        int     enabled;
+       u64     port_guid;
+       u64     node_guid;
+       enum port_state_policy  policy;
 };
 
 struct mlx5_core_sriov {
@@ -842,13 +852,6 @@ struct mlx5_pas {
        u8      log_sz;
 };
 
-enum port_state_policy {
-       MLX5_POLICY_DOWN        = 0,
-       MLX5_POLICY_UP          = 1,
-       MLX5_POLICY_FOLLOW      = 2,
-       MLX5_POLICY_INVALID     = 0xffffffff
-};
-
 enum phy_port_state {
        MLX5_AAA_111
 };