diff options
Diffstat (limited to 'drivers/infiniband')
| -rw-r--r-- | drivers/infiniband/hw/mlx5/main.c | 35 | 
1 files changed, 35 insertions, 0 deletions
| diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 8fd35ebb13e3..4a043cf35b9a 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -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); | 
