RDMA/rxe: Enforce IBA o10-2.2.3
authorBob Pearson <rpearsonhpe@gmail.com>
Thu, 27 Jan 2022 21:37:33 +0000 (15:37 -0600)
committerJason Gunthorpe <jgg@nvidia.com>
Fri, 28 Jan 2022 18:33:28 +0000 (14:33 -0400)
Add code to check if a QP is attached to one or more multicast groups
when destroy_qp is called and return an error if so.

Link: https://lore.kernel.org/r/20220127213755.31697-5-rpearsonhpe@gmail.com
Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/sw/rxe/rxe_loc.h
drivers/infiniband/sw/rxe/rxe_mcast.c
drivers/infiniband/sw/rxe/rxe_qp.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/sw/rxe/rxe_verbs.h

index dc606241f0d6966396a375225f361c2cb22206f9..052beaaacf43f9e494bd3025c8769553b55da8b4 100644 (file)
@@ -101,26 +101,19 @@ const char *rxe_parent_name(struct rxe_dev *rxe, unsigned int port_num);
 
 /* rxe_qp.c */
 int rxe_qp_chk_init(struct rxe_dev *rxe, struct ib_qp_init_attr *init);
-
 int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
                     struct ib_qp_init_attr *init,
                     struct rxe_create_qp_resp __user *uresp,
                     struct ib_pd *ibpd, struct ib_udata *udata);
-
 int rxe_qp_to_init(struct rxe_qp *qp, struct ib_qp_init_attr *init);
-
 int rxe_qp_chk_attr(struct rxe_dev *rxe, struct rxe_qp *qp,
                    struct ib_qp_attr *attr, int mask);
-
 int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr,
                     int mask, struct ib_udata *udata);
-
 int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask);
-
 void rxe_qp_error(struct rxe_qp *qp);
-
+int rxe_qp_chk_destroy(struct rxe_qp *qp);
 void rxe_qp_destroy(struct rxe_qp *qp);
-
 void rxe_qp_cleanup(struct rxe_pool_elem *elem);
 
 static inline int qp_num(struct rxe_qp *qp)
index 949784198d801cd451c13dad38b61e779498c578..34e3c52f0b7242b1deb4f2edf6f7f049b83471f1 100644 (file)
@@ -114,6 +114,7 @@ static int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
        grp->num_qp++;
        elem->qp = qp;
        elem->grp = grp;
+       atomic_inc(&qp->mcg_num);
 
        list_add(&elem->qp_list, &grp->qp_list);
        list_add(&elem->grp_list, &qp->grp_list);
@@ -143,6 +144,7 @@ static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
                        list_del(&elem->qp_list);
                        list_del(&elem->grp_list);
                        grp->num_qp--;
+                       atomic_dec(&qp->mcg_num);
 
                        spin_unlock_bh(&grp->mcg_lock);
                        spin_unlock_bh(&qp->grp_lock);
index 5018b93876943137d7c482001dc37d0d8780e365..3325c2400e2facf8e8f9e4d6cfb90aaeb10654fb 100644 (file)
@@ -770,6 +770,20 @@ int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask)
        return 0;
 }
 
+int rxe_qp_chk_destroy(struct rxe_qp *qp)
+{
+       /* See IBA o10-2.2.3
+        * An attempt to destroy a QP while attached to a mcast group
+        * will fail immediately.
+        */
+       if (atomic_read(&qp->mcg_num)) {
+               pr_debug("Attempt to destroy QP while attached to multicast group\n");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
 /* called by the destroy qp verb */
 void rxe_qp_destroy(struct rxe_qp *qp)
 {
index f7682541f9af79a1f74d926eb9e8e748254332ef..9f0aef4b649ddc2488b72e2f0e57e1c3f3f10f46 100644 (file)
@@ -493,6 +493,11 @@ static int rxe_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 static int rxe_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 {
        struct rxe_qp *qp = to_rqp(ibqp);
+       int ret;
+
+       ret = rxe_qp_chk_destroy(qp);
+       if (ret)
+               return ret;
 
        rxe_qp_destroy(qp);
        rxe_drop_index(qp);
index 388b7dc23dd7f3b174be33cfaae221f4635bb12e..4910d0782e3372ef0731ac5a84f7c6a3e941fda8 100644 (file)
@@ -235,6 +235,7 @@ struct rxe_qp {
        /* list of mcast groups qp has joined (for cleanup) */
        struct list_head        grp_list;
        spinlock_t              grp_lock; /* guard grp_list */
+       atomic_t                mcg_num;
 
        struct sk_buff_head     req_pkts;
        struct sk_buff_head     resp_pkts;