Merge tag 'for-linus-ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford...
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / sriov.c
index bf99d40e30b4e07a234ea68366d226267d365d7b..28d8472b36f130cc670fdc2843eac6b13bbee1d4 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);
 
        }