]> git.itanic.dy.fi Git - linux-stable/commitdiff
RDMA/mlx5: Fix validation of max_rd_atomic caps for DC
authorMaor Gottlieb <maorg@nvidia.com>
Wed, 28 Dec 2022 12:56:10 +0000 (14:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Jan 2023 10:59:13 +0000 (11:59 +0100)
[ Upstream commit 8de8482fe5732fbef4f5af82bc0c0362c804cd1f ]

Currently, when modifying DC, we validate max_rd_atomic user attribute
against the RC cap, validate against DC. RC and DC QP types have different
device limitations.

This can cause userspace created DC QPs to malfunction.

Fixes: c32a4f296e1d ("IB/mlx5: Add support for DC Initiator QP")
Link: https://lore.kernel.org/r/0c5aee72cea188c3bb770f4207cce7abc9b6fc74.1672231736.git.leonro@nvidia.com
Signed-off-by: Maor Gottlieb <maorg@nvidia.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/infiniband/hw/mlx5/qp.c

index e5abbcfc1d5748abf6716c46fce1b8fb466b42db..55b05a3e31b8e2d74a64e619b1ff92dca7ffb70c 100644 (file)
@@ -4499,6 +4499,40 @@ static bool mlx5_ib_modify_qp_allowed(struct mlx5_ib_dev *dev,
        return false;
 }
 
+static int validate_rd_atomic(struct mlx5_ib_dev *dev, struct ib_qp_attr *attr,
+                             int attr_mask, enum ib_qp_type qp_type)
+{
+       int log_max_ra_res;
+       int log_max_ra_req;
+
+       if (qp_type == MLX5_IB_QPT_DCI) {
+               log_max_ra_res = 1 << MLX5_CAP_GEN(dev->mdev,
+                                                  log_max_ra_res_dc);
+               log_max_ra_req = 1 << MLX5_CAP_GEN(dev->mdev,
+                                                  log_max_ra_req_dc);
+       } else {
+               log_max_ra_res = 1 << MLX5_CAP_GEN(dev->mdev,
+                                                  log_max_ra_res_qp);
+               log_max_ra_req = 1 << MLX5_CAP_GEN(dev->mdev,
+                                                  log_max_ra_req_qp);
+       }
+
+       if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
+           attr->max_rd_atomic > log_max_ra_res) {
+               mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n",
+                           attr->max_rd_atomic);
+               return false;
+       }
+
+       if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
+           attr->max_dest_rd_atomic > log_max_ra_req) {
+               mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n",
+                           attr->max_dest_rd_atomic);
+               return false;
+       }
+       return true;
+}
+
 int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                      int attr_mask, struct ib_udata *udata)
 {
@@ -4586,21 +4620,8 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                goto out;
        }
 
-       if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
-           attr->max_rd_atomic >
-           (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_res_qp))) {
-               mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n",
-                           attr->max_rd_atomic);
-               goto out;
-       }
-
-       if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
-           attr->max_dest_rd_atomic >
-           (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_req_qp))) {
-               mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n",
-                           attr->max_dest_rd_atomic);
+       if (!validate_rd_atomic(dev, attr, attr_mask, qp_type))
                goto out;
-       }
 
        if (cur_state == new_state && cur_state == IB_QPS_RESET) {
                err = 0;