RDMA: Check attr_mask during modify_qp
authorJason Gunthorpe <jgg@nvidia.com>
Sat, 3 Oct 2020 23:20:06 +0000 (20:20 -0300)
committerJason Gunthorpe <jgg@nvidia.com>
Mon, 26 Oct 2020 22:27:58 +0000 (19:27 -0300)
Each driver should check that it can support the provided attr_mask during
modify_qp. IB_USER_VERBS_EX_CMD_MODIFY_QP was being used to block
modify_qp_ex because the driver didn't check RATE_LIMIT.

Link: https://lore.kernel.org/r/6-v1-caa70ba3d1ab+1436e-ucmd_mask_jgg@nvidia.com
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
21 files changed:
drivers/infiniband/core/device.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/hns/hns_roce_hw_v1.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qedr/verbs.c
drivers/infiniband/hw/usnic/usnic_ib_verbs.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/sw/siw/siw_verbs.c
include/rdma/ib_verbs.h
include/uapi/rdma/ib_user_verbs.h

index efcadbda44095c9dda1c4f335822acb4d575c053..6d2603571771462a58f6427f7ff8a6ced7ac63b3 100644 (file)
@@ -639,6 +639,7 @@ struct ib_device *_ib_alloc_device(size_t size)
                BIT_ULL(IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL) |
                BIT_ULL(IB_USER_VERBS_EX_CMD_DESTROY_WQ) |
                BIT_ULL(IB_USER_VERBS_EX_CMD_MODIFY_CQ) |
+               BIT_ULL(IB_USER_VERBS_EX_CMD_MODIFY_QP) |
                BIT_ULL(IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
                BIT_ULL(IB_USER_VERBS_EX_CMD_QUERY_DEVICE);
 
index f85a61175772967372c0e30c3c23dbbad5ce83f1..54c3eb463da85d39fad39c78b3be3c67ec85f3b6 100644 (file)
@@ -1906,8 +1906,7 @@ static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs)
        if (ret)
                return ret;
 
-       if (cmd.base.attr_mask &
-           ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1))
+       if (cmd.base.attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
                return -EOPNOTSUPP;
 
        return modify_qp(attrs, &cmd);
@@ -1929,10 +1928,7 @@ static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs)
         * Last bit is reserved for extending the attr_mask by
         * using another field.
         */
-       BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1ULL << 31));
-
-       if (cmd.base.attr_mask &
-           ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1))
+       if (cmd.base.attr_mask & ~(IB_QP_ATTR_STANDARD_BITS | IB_QP_RATE_LIMIT))
                return -EOPNOTSUPP;
 
        ret = modify_qp(attrs, &cmd);
index f9c999d5ba28efa47aea921b1a032821149f13c9..f3ec6d3fba625991f9b5584fb06761050a1f97ea 100644 (file)
@@ -1829,6 +1829,9 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
        unsigned int flags;
        u8 nw_type;
 
+       if (qp_attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        qp->qplib_qp.modify_flags = 0;
        if (qp_attr_mask & IB_QP_STATE) {
                curr_qp_state = __to_ib_qp_state(qp->qplib_qp.cur_qp_state);
index d2b46c5c1645e4b727df9f7b567b8e86ee8ea791..79e69d449b074809a12c8d906eac859f42c80b36 100644 (file)
@@ -2374,6 +2374,9 @@ int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 
        pr_debug("ib_qp %p\n", ibqp);
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        /* iwarp does not support the RTR state */
        if ((attr_mask & IB_QP_STATE) && (attr->qp_state == IB_QPS_RTR))
                attr_mask &= ~IB_QP_STATE;
index 191e0843f090c87d1c1bb3d69811b22a9e8a3419..e3d9a5a5f4d992e3ecce22a7be747fdc78f2bbf2 100644 (file)
@@ -917,6 +917,9 @@ int efa_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
        enum ib_qp_state new_state;
        int err;
 
+       if (qp_attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        if (udata->inlen &&
            !ib_is_udata_cleared(udata, 0, udata->inlen)) {
                ibdev_dbg(&dev->ibdev,
index b3d5ba8ef439a3f3765689e7bda14162776e041f..f18380f827dd87e61c7c8b19b40feea6a2bd814f 100644 (file)
@@ -3256,6 +3256,8 @@ static int hns_roce_v1_modify_qp(struct ib_qp *ibqp,
                                 enum ib_qp_state cur_state,
                                 enum ib_qp_state new_state)
 {
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
 
        if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI)
                return hns_roce_v1_m_sqp(ibqp, attr, attr_mask, cur_state,
index 6d30850696c518d02f326e821b4267601b024dcc..a0b679254a8e56855535fe80ca52d743c162648a 100644 (file)
@@ -4757,6 +4757,9 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
        unsigned long rq_flag = 0;
        int ret;
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        /*
         * In v2 engine, software pass context and context mask to hardware
         * when modifying qp. If software need modify some fields in context,
index 76f7d8bb3b6059e14153cc2ad3d41d23718e9783..acc5e945d30369d42d82f0402df70ab5d228ca72 100644 (file)
@@ -855,6 +855,9 @@ int i40iw_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        u32 err;
        unsigned long flags;
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        memset(&info, 0, sizeof(info));
        ctx_info = &iwqp->ctx_info;
        iwarp_info = &iwqp->iwarp_info;
index 5cb8e602294ca9ad1e89000991c307d84b3984a1..8834629615bc6d546b7a22c45afd07c7b7946d8e 100644 (file)
@@ -2787,6 +2787,9 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        struct mlx4_ib_qp *mqp = to_mqp(ibqp);
        int ret;
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        ret = _mlx4_ib_modify_qp(ibqp, attr, attr_mask, udata);
 
        if (mqp->mlx4_ib_qp_type == MLX4_IB_QPT_GSI) {
index ab469bc835dcb95e616d2a0f3cfe82d3ef11b03b..b9a12a1d1c5c92f9a17a850cac756377bea2853c 100644 (file)
@@ -4144,8 +4144,7 @@ static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
                (1ull << IB_USER_VERBS_CMD_DESTROY_AH);
        dev->ib_dev.uverbs_ex_cmd_mask |=
                (1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ)        |
-               (1ull << IB_USER_VERBS_EX_CMD_CREATE_QP)        |
-               (1ull << IB_USER_VERBS_EX_CMD_MODIFY_QP);
+               (1ull << IB_USER_VERBS_EX_CMD_CREATE_QP);
 
        if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads) &&
            IS_ENABLED(CONFIG_MLX5_CORE_IPOIB))
index 600e056798c0a1230ef152c550e38a92d8d8b691..19361132336cb91ce71c2d1bda9da6a1eab3e583 100644 (file)
@@ -4247,6 +4247,9 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        int err = -EINVAL;
        int port;
 
+       if (attr_mask & ~(IB_QP_ATTR_STANDARD_BITS | IB_QP_RATE_LIMIT))
+               return -EOPNOTSUPP;
+
        if (ibqp->rwq_ind_tbl)
                return -ENOSYS;
 
index 08a2a7afafd3d2c4199418c462232516392f749e..07cfc0934b17d5efe8f812ffbb2f3452a741ea61 100644 (file)
@@ -863,6 +863,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
        enum ib_qp_state cur_state, new_state;
        int err = -EINVAL;
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        mutex_lock(&qp->mutex);
        if (attr_mask & IB_QP_CUR_STATE) {
                cur_state = attr->cur_qp_state;
index b392e15d7592b6e0799be9ae7abf23f7cc50c1c9..244dd22d53efa7c09444991f63d3fc398a83b704 100644 (file)
@@ -1391,6 +1391,9 @@ int ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        struct ocrdma_dev *dev;
        enum ib_qp_state old_qps, new_qps;
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        qp = get_ocrdma_qp(ibqp);
        dev = get_ocrdma_dev(ibqp->device);
 
index 29a96ff6fc66b66e8df5a98f48d642cd852c92f6..34c07a18c2c218dfcaf2334d22c6a881d56d42c1 100644 (file)
@@ -2472,6 +2472,9 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                 "modify qp: qp %p attr_mask=0x%x, state=%d", qp, attr_mask,
                 attr->qp_state);
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        old_qp_state = qedr_get_ibqp_state(qp->state);
        if (attr_mask & IB_QP_STATE)
                new_qp_state = attr->qp_state;
index 9e961f8ffa10dee25902a32ab107c7b889ee94a8..a89d5816685af663bbeed3de3284e1e92b653c4b 100644 (file)
@@ -557,6 +557,9 @@ int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        int status;
        usnic_dbg("\n");
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        qp_grp = to_uqp_grp(ibqp);
 
        mutex_lock(&qp_grp->vf->pf->usdev_lock);
index 428256c5506571146592e004f114fee42e1335c1..9fdec5b9553c4ef4651d39857c62ec275987f02e 100644 (file)
@@ -544,6 +544,9 @@ int pvrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        enum ib_qp_state cur_state, next_state;
        int ret;
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        /* Sanity checking. Should need lock here */
        mutex_lock(&qp->mutex);
        cur_state = (attr_mask & IB_QP_CUR_STATE) ? attr->cur_qp_state :
index ee48befc8978619b477cfa7325d66be1f622773f..7b93e7bb0072a2a0b2b81438dba2c54cdc0733f5 100644 (file)
@@ -1469,6 +1469,9 @@ int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        int pmtu = 0; /* for gcc warning only */
        int opa_ah;
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        spin_lock_irq(&qp->r_lock);
        spin_lock(&qp->s_hlock);
        spin_lock(&qp->s_lock);
index d40ebb2e0fce6ced16bc7c469f9d4118cd276204..dafcc0329148ef6abb4e1ee5e091acc09e7060fb 100644 (file)
@@ -436,6 +436,9 @@ static int rxe_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        struct rxe_dev *rxe = to_rdev(ibqp->device);
        struct rxe_qp *qp = to_rqp(ibqp);
 
+       if (mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        err = rxe_qp_chk_attr(rxe, qp, attr, mask);
        if (err)
                goto err1;
index 1c469f967ab9b2695d832a87d1728fb08d62eeb7..947b8b1cbe9af6cae2d02b8bbf9ddb4a980d2c3b 100644 (file)
@@ -544,6 +544,9 @@ int siw_verbs_modify_qp(struct ib_qp *base_qp, struct ib_qp_attr *attr,
        if (!attr_mask)
                return 0;
 
+       if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
+               return -EOPNOTSUPP;
+
        memset(&new_attrs, 0, sizeof(new_attrs));
 
        if (attr_mask & IB_QP_ACCESS_FLAGS) {
index 9bf6c319a670e2472dc0fcf3fbc55324b51a5cfb..0f9ce27bedcb5d36f9d2fad6dcc809bf4339008f 100644 (file)
@@ -1234,6 +1234,8 @@ enum ib_qp_attr_mask {
        IB_QP_RESERVED3                 = (1<<23),
        IB_QP_RESERVED4                 = (1<<24),
        IB_QP_RATE_LIMIT                = (1<<25),
+
+       IB_QP_ATTR_STANDARD_BITS = GENMASK(20, 0),
 };
 
 enum ib_qp_state {
index 456438c18c2c35b894d7e2ce52e75c2be1147674..7ee73a0652f1afa933fe60a049c8ebb77a267b9a 100644 (file)
@@ -596,20 +596,6 @@ enum {
        IB_UVERBS_CREATE_QP_SUP_COMP_MASK = IB_UVERBS_CREATE_QP_MASK_IND_TABLE,
 };
 
-enum {
-       /*
-        * This value is equal to IB_QP_DEST_QPN.
-        */
-       IB_USER_LEGACY_LAST_QP_ATTR_MASK = 1ULL << 20,
-};
-
-enum {
-       /*
-        * This value is equal to IB_QP_RATE_LIMIT.
-        */
-       IB_USER_LAST_QP_ATTR_MASK = 1ULL << 25,
-};
-
 struct ib_uverbs_ex_create_qp {
        __aligned_u64 user_handle;
        __u32 pd_handle;