IB/mlx5: Fix configuration of port capabilities
authorEli Cohen <eli@mellanox.com>
Tue, 14 Feb 2017 05:25:38 +0000 (07:25 +0200)
committerDoug Ledford <dledford@redhat.com>
Wed, 15 Feb 2017 14:29:37 +0000 (09:29 -0500)
When the "ib_virt" cap is set, configuration of port capabilities need
to be done through mlx5_core_modify_hca_vport_context.
Since modify_hca_vport_context accepts mask and value, there is no need
to read the port capabilities and calculate the new cap values so we
avoid the mutex when ib_virt is set.

Signed-off-by: Eli Cohen <eli@mellanox.com>
Reviewed-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/mlx5/main.c

index 8fd35eb..4a043cf 100644 (file)
@@ -995,6 +995,31 @@ static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask,
        return err;
 }
 
+static int set_port_caps_atomic(struct mlx5_ib_dev *dev, u8 port_num, u32 mask,
+                               u32 value)
+{
+       struct mlx5_hca_vport_context ctx = {};
+       int err;
+
+       err = mlx5_query_hca_vport_context(dev->mdev, 0,
+                                          port_num, 0, &ctx);
+       if (err)
+               return err;
+
+       if (~ctx.cap_mask1_perm & mask) {
+               mlx5_ib_warn(dev, "trying to change bitmask 0x%X but change supported 0x%X\n",
+                            mask, ctx.cap_mask1_perm);
+               return -EINVAL;
+       }
+
+       ctx.cap_mask1 = value;
+       ctx.cap_mask1_perm = mask;
+       err = mlx5_core_modify_hca_vport_context(dev->mdev, 0,
+                                                port_num, 0, &ctx);
+
+       return err;
+}
+
 static int mlx5_ib_modify_port(struct ib_device *ibdev, u8 port, int mask,
                               struct ib_port_modify *props)
 {
@@ -1002,6 +1027,16 @@ static int mlx5_ib_modify_port(struct ib_device *ibdev, u8 port, int mask,
        struct ib_port_attr attr;
        u32 tmp;
        int err;
+       u32 change_mask;
+       u32 value;
+       bool is_ib = (mlx5_ib_port_link_layer(ibdev, port) ==
+                     IB_LINK_LAYER_INFINIBAND);
+
+       if (MLX5_CAP_GEN(dev->mdev, ib_virt) && is_ib) {
+               change_mask = props->clr_port_cap_mask | props->set_port_cap_mask;
+               value = ~props->clr_port_cap_mask | props->set_port_cap_mask;
+               return set_port_caps_atomic(dev, port, change_mask, value);
+       }
 
        mutex_lock(&dev->cap_mask_mutex);