diff mbox series

[for-next] RDMA/rxe: Revert changes from irqsave to bh locks

Message ID 20220215194448.44369-1-rpearsonhpe@gmail.com (mailing list archive)
State Accepted
Commit a099b08599e6ae6b8e9faccee83760dab622c11e
Delegated to: Jason Gunthorpe
Headers show
Series [for-next] RDMA/rxe: Revert changes from irqsave to bh locks | expand

Commit Message

Bob Pearson Feb. 15, 2022, 7:44 p.m. UTC
A previous patch replaced all irqsave locks in rxe with bh locks.
This ran into problems because rdmacm has a bad habit of
calling rdma verbs APIs while disabling irqs. This is not allowed
during spin_unlock_bh() causing programs that use rdmacm to fail.
This patch reverts the changes to locks that had this problem or
got dragged into the same mess. After this patch blktests/check -q srp
now runs correctly.

This patch applies cleanly to current for-next

commit: 2f1b2820b546 ("Merge branch 'irdma_dscp' into rdma.git for-next")

Reported-by: Guoqing Jiang <guoqing.jiang@linux.dev>
Reported-by: Bart Van Assche <bvanassche@acm.org>
Fixes: 21adfa7a3c4e ("RDMA/rxe: Replace irqsave locks with bh locks")
Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
---
 drivers/infiniband/sw/rxe/rxe_cq.c    | 20 +++++++++++-------
 drivers/infiniband/sw/rxe/rxe_mcast.c | 19 ++++++++++-------
 drivers/infiniband/sw/rxe/rxe_pool.c  | 30 ++++++++++++++++-----------
 drivers/infiniband/sw/rxe/rxe_queue.c | 10 +++++----
 drivers/infiniband/sw/rxe/rxe_resp.c  | 11 +++++-----
 drivers/infiniband/sw/rxe/rxe_verbs.c | 27 ++++++++++++++----------
 6 files changed, 69 insertions(+), 48 deletions(-)

Comments

Bart Van Assche Feb. 15, 2022, 9:02 p.m. UTC | #1
On 2/15/22 11:44, Bob Pearson wrote:
> A previous patch replaced all irqsave locks in rxe with bh locks.
> This ran into problems because rdmacm has a bad habit of
> calling rdma verbs APIs while disabling irqs. This is not allowed
> during spin_unlock_bh() causing programs that use rdmacm to fail.
> This patch reverts the changes to locks that had this problem or
> got dragged into the same mess. After this patch blktests/check -q srp
> now runs correctly.

Tested-by: Bart Van Assche <bvanassche@acm.org>
Zhu Yanjun Feb. 16, 2022, 1:09 a.m. UTC | #2
On Wed, Feb 16, 2022 at 3:49 AM Bob Pearson <rpearsonhpe@gmail.com> wrote:
>
> A previous patch replaced all irqsave locks in rxe with bh locks.
> This ran into problems because rdmacm has a bad habit of
> calling rdma verbs APIs while disabling irqs. This is not allowed
> during spin_unlock_bh() causing programs that use rdmacm to fail.
> This patch reverts the changes to locks that had this problem or
> got dragged into the same mess. After this patch blktests/check -q srp
> now runs correctly.
>
> This patch applies cleanly to current for-next
>
> commit: 2f1b2820b546 ("Merge branch 'irdma_dscp' into rdma.git for-next")
>
> Reported-by: Guoqing Jiang <guoqing.jiang@linux.dev>
> Reported-by: Bart Van Assche <bvanassche@acm.org>
> Fixes: 21adfa7a3c4e ("RDMA/rxe: Replace irqsave locks with bh locks")
> Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>

Thanks.

Acked-by: Zhu Yanjun <zyjzyj2000@gmail.com>

Zhu Yanjun
> ---
>  drivers/infiniband/sw/rxe/rxe_cq.c    | 20 +++++++++++-------
>  drivers/infiniband/sw/rxe/rxe_mcast.c | 19 ++++++++++-------
>  drivers/infiniband/sw/rxe/rxe_pool.c  | 30 ++++++++++++++++-----------
>  drivers/infiniband/sw/rxe/rxe_queue.c | 10 +++++----
>  drivers/infiniband/sw/rxe/rxe_resp.c  | 11 +++++-----
>  drivers/infiniband/sw/rxe/rxe_verbs.c | 27 ++++++++++++++----------
>  6 files changed, 69 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c
> index 6baaaa34458e..642b52539ac3 100644
> --- a/drivers/infiniband/sw/rxe/rxe_cq.c
> +++ b/drivers/infiniband/sw/rxe/rxe_cq.c
> @@ -42,13 +42,14 @@ int rxe_cq_chk_attr(struct rxe_dev *rxe, struct rxe_cq *cq,
>  static void rxe_send_complete(struct tasklet_struct *t)
>  {
>         struct rxe_cq *cq = from_tasklet(cq, t, comp_task);
> +       unsigned long flags;
>
> -       spin_lock_bh(&cq->cq_lock);
> +       spin_lock_irqsave(&cq->cq_lock, flags);
>         if (cq->is_dying) {
> -               spin_unlock_bh(&cq->cq_lock);
> +               spin_unlock_irqrestore(&cq->cq_lock, flags);
>                 return;
>         }
> -       spin_unlock_bh(&cq->cq_lock);
> +       spin_unlock_irqrestore(&cq->cq_lock, flags);
>
>         cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
>  }
> @@ -107,12 +108,13 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
>         struct ib_event ev;
>         int full;
>         void *addr;
> +       unsigned long flags;
>
> -       spin_lock_bh(&cq->cq_lock);
> +       spin_lock_irqsave(&cq->cq_lock, flags);
>
>         full = queue_full(cq->queue, QUEUE_TYPE_TO_CLIENT);
>         if (unlikely(full)) {
> -               spin_unlock_bh(&cq->cq_lock);
> +               spin_unlock_irqrestore(&cq->cq_lock, flags);
>                 if (cq->ibcq.event_handler) {
>                         ev.device = cq->ibcq.device;
>                         ev.element.cq = &cq->ibcq;
> @@ -128,7 +130,7 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
>
>         queue_advance_producer(cq->queue, QUEUE_TYPE_TO_CLIENT);
>
> -       spin_unlock_bh(&cq->cq_lock);
> +       spin_unlock_irqrestore(&cq->cq_lock, flags);
>
>         if ((cq->notify == IB_CQ_NEXT_COMP) ||
>             (cq->notify == IB_CQ_SOLICITED && solicited)) {
> @@ -141,9 +143,11 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
>
>  void rxe_cq_disable(struct rxe_cq *cq)
>  {
> -       spin_lock_bh(&cq->cq_lock);
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&cq->cq_lock, flags);
>         cq->is_dying = true;
> -       spin_unlock_bh(&cq->cq_lock);
> +       spin_unlock_irqrestore(&cq->cq_lock, flags);
>  }
>
>  void rxe_cq_cleanup(struct rxe_pool_elem *elem)
> diff --git a/drivers/infiniband/sw/rxe/rxe_mcast.c b/drivers/infiniband/sw/rxe/rxe_mcast.c
> index 9336295c4ee2..2878a56d9994 100644
> --- a/drivers/infiniband/sw/rxe/rxe_mcast.c
> +++ b/drivers/infiniband/sw/rxe/rxe_mcast.c
> @@ -58,11 +58,12 @@ static int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
>         int err;
>         struct rxe_mcg *grp;
>         struct rxe_pool *pool = &rxe->mc_grp_pool;
> +       unsigned long flags;
>
>         if (rxe->attr.max_mcast_qp_attach == 0)
>                 return -EINVAL;
>
> -       write_lock_bh(&pool->pool_lock);
> +       write_lock_irqsave(&pool->pool_lock, flags);
>
>         grp = rxe_pool_get_key_locked(pool, mgid);
>         if (grp)
> @@ -70,13 +71,13 @@ static int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
>
>         grp = create_grp(rxe, pool, mgid);
>         if (IS_ERR(grp)) {
> -               write_unlock_bh(&pool->pool_lock);
> +               write_unlock_irqrestore(&pool->pool_lock, flags);
>                 err = PTR_ERR(grp);
>                 return err;
>         }
>
>  done:
> -       write_unlock_bh(&pool->pool_lock);
> +       write_unlock_irqrestore(&pool->pool_lock, flags);
>         *grp_p = grp;
>         return 0;
>  }
> @@ -86,9 +87,10 @@ static int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>  {
>         int err;
>         struct rxe_mca *elem;
> +       unsigned long flags;
>
>         /* check to see of the qp is already a member of the group */
> -       spin_lock_bh(&grp->mcg_lock);
> +       spin_lock_irqsave(&grp->mcg_lock, flags);
>         list_for_each_entry(elem, &grp->qp_list, qp_list) {
>                 if (elem->qp == qp) {
>                         err = 0;
> @@ -118,7 +120,7 @@ static int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>
>         err = 0;
>  out:
> -       spin_unlock_bh(&grp->mcg_lock);
> +       spin_unlock_irqrestore(&grp->mcg_lock, flags);
>         return err;
>  }
>
> @@ -127,12 +129,13 @@ static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>  {
>         struct rxe_mcg *grp;
>         struct rxe_mca *elem, *tmp;
> +       unsigned long flags;
>
>         grp = rxe_pool_get_key(&rxe->mc_grp_pool, mgid);
>         if (!grp)
>                 goto err1;
>
> -       spin_lock_bh(&grp->mcg_lock);
> +       spin_lock_irqsave(&grp->mcg_lock, flags);
>
>         list_for_each_entry_safe(elem, tmp, &grp->qp_list, qp_list) {
>                 if (elem->qp == qp) {
> @@ -140,7 +143,7 @@ static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>                         grp->num_qp--;
>                         atomic_dec(&qp->mcg_num);
>
> -                       spin_unlock_bh(&grp->mcg_lock);
> +                       spin_unlock_irqrestore(&grp->mcg_lock, flags);
>                         rxe_drop_ref(elem);
>                         rxe_drop_ref(grp);      /* ref held by QP */
>                         rxe_drop_ref(grp);      /* ref from get_key */
> @@ -148,7 +151,7 @@ static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>                 }
>         }
>
> -       spin_unlock_bh(&grp->mcg_lock);
> +       spin_unlock_irqrestore(&grp->mcg_lock, flags);
>         rxe_drop_ref(grp);                      /* ref from get_key */
>  err1:
>         return -EINVAL;
> diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c
> index 63c594173565..a11dab13c192 100644
> --- a/drivers/infiniband/sw/rxe/rxe_pool.c
> +++ b/drivers/infiniband/sw/rxe/rxe_pool.c
> @@ -260,11 +260,12 @@ int __rxe_add_key_locked(struct rxe_pool_elem *elem, void *key)
>  int __rxe_add_key(struct rxe_pool_elem *elem, void *key)
>  {
>         struct rxe_pool *pool = elem->pool;
> +       unsigned long flags;
>         int err;
>
> -       write_lock_bh(&pool->pool_lock);
> +       write_lock_irqsave(&pool->pool_lock, flags);
>         err = __rxe_add_key_locked(elem, key);
> -       write_unlock_bh(&pool->pool_lock);
> +       write_unlock_irqrestore(&pool->pool_lock, flags);
>
>         return err;
>  }
> @@ -279,10 +280,11 @@ void __rxe_drop_key_locked(struct rxe_pool_elem *elem)
>  void __rxe_drop_key(struct rxe_pool_elem *elem)
>  {
>         struct rxe_pool *pool = elem->pool;
> +       unsigned long flags;
>
> -       write_lock_bh(&pool->pool_lock);
> +       write_lock_irqsave(&pool->pool_lock, flags);
>         __rxe_drop_key_locked(elem);
> -       write_unlock_bh(&pool->pool_lock);
> +       write_unlock_irqrestore(&pool->pool_lock, flags);
>  }
>
>  int __rxe_add_index_locked(struct rxe_pool_elem *elem)
> @@ -299,11 +301,12 @@ int __rxe_add_index_locked(struct rxe_pool_elem *elem)
>  int __rxe_add_index(struct rxe_pool_elem *elem)
>  {
>         struct rxe_pool *pool = elem->pool;
> +       unsigned long flags;
>         int err;
>
> -       write_lock_bh(&pool->pool_lock);
> +       write_lock_irqsave(&pool->pool_lock, flags);
>         err = __rxe_add_index_locked(elem);
> -       write_unlock_bh(&pool->pool_lock);
> +       write_unlock_irqrestore(&pool->pool_lock, flags);
>
>         return err;
>  }
> @@ -319,10 +322,11 @@ void __rxe_drop_index_locked(struct rxe_pool_elem *elem)
>  void __rxe_drop_index(struct rxe_pool_elem *elem)
>  {
>         struct rxe_pool *pool = elem->pool;
> +       unsigned long flags;
>
> -       write_lock_bh(&pool->pool_lock);
> +       write_lock_irqsave(&pool->pool_lock, flags);
>         __rxe_drop_index_locked(elem);
> -       write_unlock_bh(&pool->pool_lock);
> +       write_unlock_irqrestore(&pool->pool_lock, flags);
>  }
>
>  void *rxe_alloc_locked(struct rxe_pool *pool)
> @@ -440,11 +444,12 @@ void *rxe_pool_get_index_locked(struct rxe_pool *pool, u32 index)
>
>  void *rxe_pool_get_index(struct rxe_pool *pool, u32 index)
>  {
> +       unsigned long flags;
>         void *obj;
>
> -       read_lock_bh(&pool->pool_lock);
> +       read_lock_irqsave(&pool->pool_lock, flags);
>         obj = rxe_pool_get_index_locked(pool, index);
> -       read_unlock_bh(&pool->pool_lock);
> +       read_unlock_irqrestore(&pool->pool_lock, flags);
>
>         return obj;
>  }
> @@ -484,11 +489,12 @@ void *rxe_pool_get_key_locked(struct rxe_pool *pool, void *key)
>
>  void *rxe_pool_get_key(struct rxe_pool *pool, void *key)
>  {
> +       unsigned long flags;
>         void *obj;
>
> -       read_lock_bh(&pool->pool_lock);
> +       read_lock_irqsave(&pool->pool_lock, flags);
>         obj = rxe_pool_get_key_locked(pool, key);
> -       read_unlock_bh(&pool->pool_lock);
> +       read_unlock_irqrestore(&pool->pool_lock, flags);
>
>         return obj;
>  }
> diff --git a/drivers/infiniband/sw/rxe/rxe_queue.c b/drivers/infiniband/sw/rxe/rxe_queue.c
> index a1b283dd2d4c..dbd4971039c0 100644
> --- a/drivers/infiniband/sw/rxe/rxe_queue.c
> +++ b/drivers/infiniband/sw/rxe/rxe_queue.c
> @@ -151,6 +151,8 @@ int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
>         struct rxe_queue *new_q;
>         unsigned int num_elem = *num_elem_p;
>         int err;
> +       unsigned long producer_flags;
> +       unsigned long consumer_flags;
>
>         new_q = rxe_queue_init(q->rxe, &num_elem, elem_size, q->type);
>         if (!new_q)
> @@ -164,17 +166,17 @@ int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
>                 goto err1;
>         }
>
> -       spin_lock_bh(consumer_lock);
> +       spin_lock_irqsave(consumer_lock, consumer_flags);
>
>         if (producer_lock) {
> -               spin_lock_bh(producer_lock);
> +               spin_lock_irqsave(producer_lock, producer_flags);
>                 err = resize_finish(q, new_q, num_elem);
> -               spin_unlock_bh(producer_lock);
> +               spin_unlock_irqrestore(producer_lock, producer_flags);
>         } else {
>                 err = resize_finish(q, new_q, num_elem);
>         }
>
> -       spin_unlock_bh(consumer_lock);
> +       spin_unlock_irqrestore(consumer_lock, consumer_flags);
>
>         rxe_queue_cleanup(new_q);       /* new/old dep on err */
>         if (err)
> diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
> index 380934e38923..c369d78fc8e8 100644
> --- a/drivers/infiniband/sw/rxe/rxe_resp.c
> +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
> @@ -297,21 +297,22 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp)
>         struct ib_event ev;
>         unsigned int count;
>         size_t size;
> +       unsigned long flags;
>
>         if (srq->error)
>                 return RESPST_ERR_RNR;
>
> -       spin_lock_bh(&srq->rq.consumer_lock);
> +       spin_lock_irqsave(&srq->rq.consumer_lock, flags);
>
>         wqe = queue_head(q, QUEUE_TYPE_FROM_CLIENT);
>         if (!wqe) {
> -               spin_unlock_bh(&srq->rq.consumer_lock);
> +               spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
>                 return RESPST_ERR_RNR;
>         }
>
>         /* don't trust user space data */
>         if (unlikely(wqe->dma.num_sge > srq->rq.max_sge)) {
> -               spin_unlock_bh(&srq->rq.consumer_lock);
> +               spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
>                 pr_warn("%s: invalid num_sge in SRQ entry\n", __func__);
>                 return RESPST_ERR_MALFORMED_WQE;
>         }
> @@ -327,11 +328,11 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp)
>                 goto event;
>         }
>
> -       spin_unlock_bh(&srq->rq.consumer_lock);
> +       spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
>         return RESPST_CHK_LENGTH;
>
>  event:
> -       spin_unlock_bh(&srq->rq.consumer_lock);
> +       spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
>         ev.device = qp->ibqp.device;
>         ev.element.srq = qp->ibqp.srq;
>         ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
> diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
> index 9f0aef4b649d..80df9a8f71a1 100644
> --- a/drivers/infiniband/sw/rxe/rxe_verbs.c
> +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
> @@ -384,8 +384,9 @@ static int rxe_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
>  {
>         int err = 0;
>         struct rxe_srq *srq = to_rsrq(ibsrq);
> +       unsigned long flags;
>
> -       spin_lock_bh(&srq->rq.producer_lock);
> +       spin_lock_irqsave(&srq->rq.producer_lock, flags);
>
>         while (wr) {
>                 err = post_one_recv(&srq->rq, wr);
> @@ -394,7 +395,7 @@ static int rxe_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
>                 wr = wr->next;
>         }
>
> -       spin_unlock_bh(&srq->rq.producer_lock);
> +       spin_unlock_irqrestore(&srq->rq.producer_lock, flags);
>
>         if (err)
>                 *bad_wr = wr;
> @@ -643,18 +644,19 @@ static int post_one_send(struct rxe_qp *qp, const struct ib_send_wr *ibwr,
>         int err;
>         struct rxe_sq *sq = &qp->sq;
>         struct rxe_send_wqe *send_wqe;
> +       unsigned long flags;
>         int full;
>
>         err = validate_send_wr(qp, ibwr, mask, length);
>         if (err)
>                 return err;
>
> -       spin_lock_bh(&qp->sq.sq_lock);
> +       spin_lock_irqsave(&qp->sq.sq_lock, flags);
>
>         full = queue_full(sq->queue, QUEUE_TYPE_TO_DRIVER);
>
>         if (unlikely(full)) {
> -               spin_unlock_bh(&qp->sq.sq_lock);
> +               spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
>                 return -ENOMEM;
>         }
>
> @@ -663,7 +665,7 @@ static int post_one_send(struct rxe_qp *qp, const struct ib_send_wr *ibwr,
>
>         queue_advance_producer(sq->queue, QUEUE_TYPE_TO_DRIVER);
>
> -       spin_unlock_bh(&qp->sq.sq_lock);
> +       spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
>
>         return 0;
>  }
> @@ -743,6 +745,7 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
>         int err = 0;
>         struct rxe_qp *qp = to_rqp(ibqp);
>         struct rxe_rq *rq = &qp->rq;
> +       unsigned long flags;
>
>         if (unlikely((qp_state(qp) < IB_QPS_INIT) || !qp->valid)) {
>                 *bad_wr = wr;
> @@ -756,7 +759,7 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
>                 goto err1;
>         }
>
> -       spin_lock_bh(&rq->producer_lock);
> +       spin_lock_irqsave(&rq->producer_lock, flags);
>
>         while (wr) {
>                 err = post_one_recv(rq, wr);
> @@ -767,7 +770,7 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
>                 wr = wr->next;
>         }
>
> -       spin_unlock_bh(&rq->producer_lock);
> +       spin_unlock_irqrestore(&rq->producer_lock, flags);
>
>         if (qp->resp.state == QP_STATE_ERROR)
>                 rxe_run_task(&qp->resp.task, 1);
> @@ -848,8 +851,9 @@ static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
>         int i;
>         struct rxe_cq *cq = to_rcq(ibcq);
>         struct rxe_cqe *cqe;
> +       unsigned long flags;
>
> -       spin_lock_bh(&cq->cq_lock);
> +       spin_lock_irqsave(&cq->cq_lock, flags);
>         for (i = 0; i < num_entries; i++) {
>                 cqe = queue_head(cq->queue, QUEUE_TYPE_FROM_DRIVER);
>                 if (!cqe)
> @@ -858,7 +862,7 @@ static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
>                 memcpy(wc++, &cqe->ibwc, sizeof(*wc));
>                 queue_advance_consumer(cq->queue, QUEUE_TYPE_FROM_DRIVER);
>         }
> -       spin_unlock_bh(&cq->cq_lock);
> +       spin_unlock_irqrestore(&cq->cq_lock, flags);
>
>         return i;
>  }
> @@ -878,8 +882,9 @@ static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
>         struct rxe_cq *cq = to_rcq(ibcq);
>         int ret = 0;
>         int empty;
> +       unsigned long irq_flags;
>
> -       spin_lock_bh(&cq->cq_lock);
> +       spin_lock_irqsave(&cq->cq_lock, irq_flags);
>         if (cq->notify != IB_CQ_NEXT_COMP)
>                 cq->notify = flags & IB_CQ_SOLICITED_MASK;
>
> @@ -888,7 +893,7 @@ static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
>         if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && !empty)
>                 ret = 1;
>
> -       spin_unlock_bh(&cq->cq_lock);
> +       spin_unlock_irqrestore(&cq->cq_lock, irq_flags);
>
>         return ret;
>  }
> --
> 2.32.0
>
Leon Romanovsky Feb. 16, 2022, 7:07 a.m. UTC | #3
On Tue, Feb 15, 2022 at 01:44:49PM -0600, Bob Pearson wrote:
> A previous patch replaced all irqsave locks in rxe with bh locks.
> This ran into problems because rdmacm has a bad habit of
> calling rdma verbs APIs while disabling irqs. This is not allowed
> during spin_unlock_bh() causing programs that use rdmacm to fail.
> This patch reverts the changes to locks that had this problem or
> got dragged into the same mess. After this patch blktests/check -q srp
> now runs correctly.
> 
> This patch applies cleanly to current for-next
> 
> commit: 2f1b2820b546 ("Merge branch 'irdma_dscp' into rdma.git for-next")

The three lines above shouldn't be part of commit message.

Thanks

> 
> Reported-by: Guoqing Jiang <guoqing.jiang@linux.dev>
> Reported-by: Bart Van Assche <bvanassche@acm.org>
> Fixes: 21adfa7a3c4e ("RDMA/rxe: Replace irqsave locks with bh locks")
> Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
> ---
>  drivers/infiniband/sw/rxe/rxe_cq.c    | 20 +++++++++++-------
>  drivers/infiniband/sw/rxe/rxe_mcast.c | 19 ++++++++++-------
>  drivers/infiniband/sw/rxe/rxe_pool.c  | 30 ++++++++++++++++-----------
>  drivers/infiniband/sw/rxe/rxe_queue.c | 10 +++++----
>  drivers/infiniband/sw/rxe/rxe_resp.c  | 11 +++++-----
>  drivers/infiniband/sw/rxe/rxe_verbs.c | 27 ++++++++++++++----------
>  6 files changed, 69 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c
> index 6baaaa34458e..642b52539ac3 100644
> --- a/drivers/infiniband/sw/rxe/rxe_cq.c
> +++ b/drivers/infiniband/sw/rxe/rxe_cq.c
> @@ -42,13 +42,14 @@ int rxe_cq_chk_attr(struct rxe_dev *rxe, struct rxe_cq *cq,
>  static void rxe_send_complete(struct tasklet_struct *t)
>  {
>  	struct rxe_cq *cq = from_tasklet(cq, t, comp_task);
> +	unsigned long flags;
>  
> -	spin_lock_bh(&cq->cq_lock);
> +	spin_lock_irqsave(&cq->cq_lock, flags);
>  	if (cq->is_dying) {
> -		spin_unlock_bh(&cq->cq_lock);
> +		spin_unlock_irqrestore(&cq->cq_lock, flags);
>  		return;
>  	}
> -	spin_unlock_bh(&cq->cq_lock);
> +	spin_unlock_irqrestore(&cq->cq_lock, flags);
>  
>  	cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
>  }
> @@ -107,12 +108,13 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
>  	struct ib_event ev;
>  	int full;
>  	void *addr;
> +	unsigned long flags;
>  
> -	spin_lock_bh(&cq->cq_lock);
> +	spin_lock_irqsave(&cq->cq_lock, flags);
>  
>  	full = queue_full(cq->queue, QUEUE_TYPE_TO_CLIENT);
>  	if (unlikely(full)) {
> -		spin_unlock_bh(&cq->cq_lock);
> +		spin_unlock_irqrestore(&cq->cq_lock, flags);
>  		if (cq->ibcq.event_handler) {
>  			ev.device = cq->ibcq.device;
>  			ev.element.cq = &cq->ibcq;
> @@ -128,7 +130,7 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
>  
>  	queue_advance_producer(cq->queue, QUEUE_TYPE_TO_CLIENT);
>  
> -	spin_unlock_bh(&cq->cq_lock);
> +	spin_unlock_irqrestore(&cq->cq_lock, flags);
>  
>  	if ((cq->notify == IB_CQ_NEXT_COMP) ||
>  	    (cq->notify == IB_CQ_SOLICITED && solicited)) {
> @@ -141,9 +143,11 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
>  
>  void rxe_cq_disable(struct rxe_cq *cq)
>  {
> -	spin_lock_bh(&cq->cq_lock);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&cq->cq_lock, flags);
>  	cq->is_dying = true;
> -	spin_unlock_bh(&cq->cq_lock);
> +	spin_unlock_irqrestore(&cq->cq_lock, flags);
>  }
>  
>  void rxe_cq_cleanup(struct rxe_pool_elem *elem)
> diff --git a/drivers/infiniband/sw/rxe/rxe_mcast.c b/drivers/infiniband/sw/rxe/rxe_mcast.c
> index 9336295c4ee2..2878a56d9994 100644
> --- a/drivers/infiniband/sw/rxe/rxe_mcast.c
> +++ b/drivers/infiniband/sw/rxe/rxe_mcast.c
> @@ -58,11 +58,12 @@ static int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
>  	int err;
>  	struct rxe_mcg *grp;
>  	struct rxe_pool *pool = &rxe->mc_grp_pool;
> +	unsigned long flags;
>  
>  	if (rxe->attr.max_mcast_qp_attach == 0)
>  		return -EINVAL;
>  
> -	write_lock_bh(&pool->pool_lock);
> +	write_lock_irqsave(&pool->pool_lock, flags);
>  
>  	grp = rxe_pool_get_key_locked(pool, mgid);
>  	if (grp)
> @@ -70,13 +71,13 @@ static int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
>  
>  	grp = create_grp(rxe, pool, mgid);
>  	if (IS_ERR(grp)) {
> -		write_unlock_bh(&pool->pool_lock);
> +		write_unlock_irqrestore(&pool->pool_lock, flags);
>  		err = PTR_ERR(grp);
>  		return err;
>  	}
>  
>  done:
> -	write_unlock_bh(&pool->pool_lock);
> +	write_unlock_irqrestore(&pool->pool_lock, flags);
>  	*grp_p = grp;
>  	return 0;
>  }
> @@ -86,9 +87,10 @@ static int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>  {
>  	int err;
>  	struct rxe_mca *elem;
> +	unsigned long flags;
>  
>  	/* check to see of the qp is already a member of the group */
> -	spin_lock_bh(&grp->mcg_lock);
> +	spin_lock_irqsave(&grp->mcg_lock, flags);
>  	list_for_each_entry(elem, &grp->qp_list, qp_list) {
>  		if (elem->qp == qp) {
>  			err = 0;
> @@ -118,7 +120,7 @@ static int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>  
>  	err = 0;
>  out:
> -	spin_unlock_bh(&grp->mcg_lock);
> +	spin_unlock_irqrestore(&grp->mcg_lock, flags);
>  	return err;
>  }
>  
> @@ -127,12 +129,13 @@ static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>  {
>  	struct rxe_mcg *grp;
>  	struct rxe_mca *elem, *tmp;
> +	unsigned long flags;
>  
>  	grp = rxe_pool_get_key(&rxe->mc_grp_pool, mgid);
>  	if (!grp)
>  		goto err1;
>  
> -	spin_lock_bh(&grp->mcg_lock);
> +	spin_lock_irqsave(&grp->mcg_lock, flags);
>  
>  	list_for_each_entry_safe(elem, tmp, &grp->qp_list, qp_list) {
>  		if (elem->qp == qp) {
> @@ -140,7 +143,7 @@ static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>  			grp->num_qp--;
>  			atomic_dec(&qp->mcg_num);
>  
> -			spin_unlock_bh(&grp->mcg_lock);
> +			spin_unlock_irqrestore(&grp->mcg_lock, flags);
>  			rxe_drop_ref(elem);
>  			rxe_drop_ref(grp);	/* ref held by QP */
>  			rxe_drop_ref(grp);	/* ref from get_key */
> @@ -148,7 +151,7 @@ static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
>  		}
>  	}
>  
> -	spin_unlock_bh(&grp->mcg_lock);
> +	spin_unlock_irqrestore(&grp->mcg_lock, flags);
>  	rxe_drop_ref(grp);			/* ref from get_key */
>  err1:
>  	return -EINVAL;
> diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c
> index 63c594173565..a11dab13c192 100644
> --- a/drivers/infiniband/sw/rxe/rxe_pool.c
> +++ b/drivers/infiniband/sw/rxe/rxe_pool.c
> @@ -260,11 +260,12 @@ int __rxe_add_key_locked(struct rxe_pool_elem *elem, void *key)
>  int __rxe_add_key(struct rxe_pool_elem *elem, void *key)
>  {
>  	struct rxe_pool *pool = elem->pool;
> +	unsigned long flags;
>  	int err;
>  
> -	write_lock_bh(&pool->pool_lock);
> +	write_lock_irqsave(&pool->pool_lock, flags);
>  	err = __rxe_add_key_locked(elem, key);
> -	write_unlock_bh(&pool->pool_lock);
> +	write_unlock_irqrestore(&pool->pool_lock, flags);
>  
>  	return err;
>  }
> @@ -279,10 +280,11 @@ void __rxe_drop_key_locked(struct rxe_pool_elem *elem)
>  void __rxe_drop_key(struct rxe_pool_elem *elem)
>  {
>  	struct rxe_pool *pool = elem->pool;
> +	unsigned long flags;
>  
> -	write_lock_bh(&pool->pool_lock);
> +	write_lock_irqsave(&pool->pool_lock, flags);
>  	__rxe_drop_key_locked(elem);
> -	write_unlock_bh(&pool->pool_lock);
> +	write_unlock_irqrestore(&pool->pool_lock, flags);
>  }
>  
>  int __rxe_add_index_locked(struct rxe_pool_elem *elem)
> @@ -299,11 +301,12 @@ int __rxe_add_index_locked(struct rxe_pool_elem *elem)
>  int __rxe_add_index(struct rxe_pool_elem *elem)
>  {
>  	struct rxe_pool *pool = elem->pool;
> +	unsigned long flags;
>  	int err;
>  
> -	write_lock_bh(&pool->pool_lock);
> +	write_lock_irqsave(&pool->pool_lock, flags);
>  	err = __rxe_add_index_locked(elem);
> -	write_unlock_bh(&pool->pool_lock);
> +	write_unlock_irqrestore(&pool->pool_lock, flags);
>  
>  	return err;
>  }
> @@ -319,10 +322,11 @@ void __rxe_drop_index_locked(struct rxe_pool_elem *elem)
>  void __rxe_drop_index(struct rxe_pool_elem *elem)
>  {
>  	struct rxe_pool *pool = elem->pool;
> +	unsigned long flags;
>  
> -	write_lock_bh(&pool->pool_lock);
> +	write_lock_irqsave(&pool->pool_lock, flags);
>  	__rxe_drop_index_locked(elem);
> -	write_unlock_bh(&pool->pool_lock);
> +	write_unlock_irqrestore(&pool->pool_lock, flags);
>  }
>  
>  void *rxe_alloc_locked(struct rxe_pool *pool)
> @@ -440,11 +444,12 @@ void *rxe_pool_get_index_locked(struct rxe_pool *pool, u32 index)
>  
>  void *rxe_pool_get_index(struct rxe_pool *pool, u32 index)
>  {
> +	unsigned long flags;
>  	void *obj;
>  
> -	read_lock_bh(&pool->pool_lock);
> +	read_lock_irqsave(&pool->pool_lock, flags);
>  	obj = rxe_pool_get_index_locked(pool, index);
> -	read_unlock_bh(&pool->pool_lock);
> +	read_unlock_irqrestore(&pool->pool_lock, flags);
>  
>  	return obj;
>  }
> @@ -484,11 +489,12 @@ void *rxe_pool_get_key_locked(struct rxe_pool *pool, void *key)
>  
>  void *rxe_pool_get_key(struct rxe_pool *pool, void *key)
>  {
> +	unsigned long flags;
>  	void *obj;
>  
> -	read_lock_bh(&pool->pool_lock);
> +	read_lock_irqsave(&pool->pool_lock, flags);
>  	obj = rxe_pool_get_key_locked(pool, key);
> -	read_unlock_bh(&pool->pool_lock);
> +	read_unlock_irqrestore(&pool->pool_lock, flags);
>  
>  	return obj;
>  }
> diff --git a/drivers/infiniband/sw/rxe/rxe_queue.c b/drivers/infiniband/sw/rxe/rxe_queue.c
> index a1b283dd2d4c..dbd4971039c0 100644
> --- a/drivers/infiniband/sw/rxe/rxe_queue.c
> +++ b/drivers/infiniband/sw/rxe/rxe_queue.c
> @@ -151,6 +151,8 @@ int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
>  	struct rxe_queue *new_q;
>  	unsigned int num_elem = *num_elem_p;
>  	int err;
> +	unsigned long producer_flags;
> +	unsigned long consumer_flags;
>  
>  	new_q = rxe_queue_init(q->rxe, &num_elem, elem_size, q->type);
>  	if (!new_q)
> @@ -164,17 +166,17 @@ int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
>  		goto err1;
>  	}
>  
> -	spin_lock_bh(consumer_lock);
> +	spin_lock_irqsave(consumer_lock, consumer_flags);
>  
>  	if (producer_lock) {
> -		spin_lock_bh(producer_lock);
> +		spin_lock_irqsave(producer_lock, producer_flags);
>  		err = resize_finish(q, new_q, num_elem);
> -		spin_unlock_bh(producer_lock);
> +		spin_unlock_irqrestore(producer_lock, producer_flags);
>  	} else {
>  		err = resize_finish(q, new_q, num_elem);
>  	}
>  
> -	spin_unlock_bh(consumer_lock);
> +	spin_unlock_irqrestore(consumer_lock, consumer_flags);
>  
>  	rxe_queue_cleanup(new_q);	/* new/old dep on err */
>  	if (err)
> diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
> index 380934e38923..c369d78fc8e8 100644
> --- a/drivers/infiniband/sw/rxe/rxe_resp.c
> +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
> @@ -297,21 +297,22 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp)
>  	struct ib_event ev;
>  	unsigned int count;
>  	size_t size;
> +	unsigned long flags;
>  
>  	if (srq->error)
>  		return RESPST_ERR_RNR;
>  
> -	spin_lock_bh(&srq->rq.consumer_lock);
> +	spin_lock_irqsave(&srq->rq.consumer_lock, flags);
>  
>  	wqe = queue_head(q, QUEUE_TYPE_FROM_CLIENT);
>  	if (!wqe) {
> -		spin_unlock_bh(&srq->rq.consumer_lock);
> +		spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
>  		return RESPST_ERR_RNR;
>  	}
>  
>  	/* don't trust user space data */
>  	if (unlikely(wqe->dma.num_sge > srq->rq.max_sge)) {
> -		spin_unlock_bh(&srq->rq.consumer_lock);
> +		spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
>  		pr_warn("%s: invalid num_sge in SRQ entry\n", __func__);
>  		return RESPST_ERR_MALFORMED_WQE;
>  	}
> @@ -327,11 +328,11 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp)
>  		goto event;
>  	}
>  
> -	spin_unlock_bh(&srq->rq.consumer_lock);
> +	spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
>  	return RESPST_CHK_LENGTH;
>  
>  event:
> -	spin_unlock_bh(&srq->rq.consumer_lock);
> +	spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
>  	ev.device = qp->ibqp.device;
>  	ev.element.srq = qp->ibqp.srq;
>  	ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
> diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
> index 9f0aef4b649d..80df9a8f71a1 100644
> --- a/drivers/infiniband/sw/rxe/rxe_verbs.c
> +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
> @@ -384,8 +384,9 @@ static int rxe_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
>  {
>  	int err = 0;
>  	struct rxe_srq *srq = to_rsrq(ibsrq);
> +	unsigned long flags;
>  
> -	spin_lock_bh(&srq->rq.producer_lock);
> +	spin_lock_irqsave(&srq->rq.producer_lock, flags);
>  
>  	while (wr) {
>  		err = post_one_recv(&srq->rq, wr);
> @@ -394,7 +395,7 @@ static int rxe_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
>  		wr = wr->next;
>  	}
>  
> -	spin_unlock_bh(&srq->rq.producer_lock);
> +	spin_unlock_irqrestore(&srq->rq.producer_lock, flags);
>  
>  	if (err)
>  		*bad_wr = wr;
> @@ -643,18 +644,19 @@ static int post_one_send(struct rxe_qp *qp, const struct ib_send_wr *ibwr,
>  	int err;
>  	struct rxe_sq *sq = &qp->sq;
>  	struct rxe_send_wqe *send_wqe;
> +	unsigned long flags;
>  	int full;
>  
>  	err = validate_send_wr(qp, ibwr, mask, length);
>  	if (err)
>  		return err;
>  
> -	spin_lock_bh(&qp->sq.sq_lock);
> +	spin_lock_irqsave(&qp->sq.sq_lock, flags);
>  
>  	full = queue_full(sq->queue, QUEUE_TYPE_TO_DRIVER);
>  
>  	if (unlikely(full)) {
> -		spin_unlock_bh(&qp->sq.sq_lock);
> +		spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
>  		return -ENOMEM;
>  	}
>  
> @@ -663,7 +665,7 @@ static int post_one_send(struct rxe_qp *qp, const struct ib_send_wr *ibwr,
>  
>  	queue_advance_producer(sq->queue, QUEUE_TYPE_TO_DRIVER);
>  
> -	spin_unlock_bh(&qp->sq.sq_lock);
> +	spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
>  
>  	return 0;
>  }
> @@ -743,6 +745,7 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
>  	int err = 0;
>  	struct rxe_qp *qp = to_rqp(ibqp);
>  	struct rxe_rq *rq = &qp->rq;
> +	unsigned long flags;
>  
>  	if (unlikely((qp_state(qp) < IB_QPS_INIT) || !qp->valid)) {
>  		*bad_wr = wr;
> @@ -756,7 +759,7 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
>  		goto err1;
>  	}
>  
> -	spin_lock_bh(&rq->producer_lock);
> +	spin_lock_irqsave(&rq->producer_lock, flags);
>  
>  	while (wr) {
>  		err = post_one_recv(rq, wr);
> @@ -767,7 +770,7 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
>  		wr = wr->next;
>  	}
>  
> -	spin_unlock_bh(&rq->producer_lock);
> +	spin_unlock_irqrestore(&rq->producer_lock, flags);
>  
>  	if (qp->resp.state == QP_STATE_ERROR)
>  		rxe_run_task(&qp->resp.task, 1);
> @@ -848,8 +851,9 @@ static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
>  	int i;
>  	struct rxe_cq *cq = to_rcq(ibcq);
>  	struct rxe_cqe *cqe;
> +	unsigned long flags;
>  
> -	spin_lock_bh(&cq->cq_lock);
> +	spin_lock_irqsave(&cq->cq_lock, flags);
>  	for (i = 0; i < num_entries; i++) {
>  		cqe = queue_head(cq->queue, QUEUE_TYPE_FROM_DRIVER);
>  		if (!cqe)
> @@ -858,7 +862,7 @@ static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
>  		memcpy(wc++, &cqe->ibwc, sizeof(*wc));
>  		queue_advance_consumer(cq->queue, QUEUE_TYPE_FROM_DRIVER);
>  	}
> -	spin_unlock_bh(&cq->cq_lock);
> +	spin_unlock_irqrestore(&cq->cq_lock, flags);
>  
>  	return i;
>  }
> @@ -878,8 +882,9 @@ static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
>  	struct rxe_cq *cq = to_rcq(ibcq);
>  	int ret = 0;
>  	int empty;
> +	unsigned long irq_flags;
>  
> -	spin_lock_bh(&cq->cq_lock);
> +	spin_lock_irqsave(&cq->cq_lock, irq_flags);
>  	if (cq->notify != IB_CQ_NEXT_COMP)
>  		cq->notify = flags & IB_CQ_SOLICITED_MASK;
>  
> @@ -888,7 +893,7 @@ static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
>  	if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && !empty)
>  		ret = 1;
>  
> -	spin_unlock_bh(&cq->cq_lock);
> +	spin_unlock_irqrestore(&cq->cq_lock, irq_flags);
>  
>  	return ret;
>  }
> -- 
> 2.32.0
>
Jason Gunthorpe Feb. 16, 2022, 5:44 p.m. UTC | #4
On Tue, Feb 15, 2022 at 01:44:49PM -0600, Bob Pearson wrote:
> A previous patch replaced all irqsave locks in rxe with bh locks.
> This ran into problems because rdmacm has a bad habit of
> calling rdma verbs APIs while disabling irqs. This is not allowed
> during spin_unlock_bh() causing programs that use rdmacm to fail.
> This patch reverts the changes to locks that had this problem or
> got dragged into the same mess. After this patch blktests/check -q srp
> now runs correctly.
> 
> This patch applies cleanly to current for-next
> 
> commit: 2f1b2820b546 ("Merge branch 'irdma_dscp' into rdma.git for-next")
> 
> Reported-by: Guoqing Jiang <guoqing.jiang@linux.dev>
> Reported-by: Bart Van Assche <bvanassche@acm.org>
> Fixes: 21adfa7a3c4e ("RDMA/rxe: Replace irqsave locks with bh locks")
> Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
> ---
>  drivers/infiniband/sw/rxe/rxe_cq.c    | 20 +++++++++++-------
>  drivers/infiniband/sw/rxe/rxe_mcast.c | 19 ++++++++++-------
>  drivers/infiniband/sw/rxe/rxe_pool.c  | 30 ++++++++++++++++-----------
>  drivers/infiniband/sw/rxe/rxe_queue.c | 10 +++++----
>  drivers/infiniband/sw/rxe/rxe_resp.c  | 11 +++++-----
>  drivers/infiniband/sw/rxe/rxe_verbs.c | 27 ++++++++++++++----------
>  6 files changed, 69 insertions(+), 48 deletions(-)

Applied to for-next, thanks

I also rebased the other patches I took on top of this, you should
probably check the wip branch

Jason
Guoqing Jiang Feb. 17, 2022, 2:03 a.m. UTC | #5
On 2/16/22 3:44 AM, Bob Pearson wrote:
> A previous patch replaced all irqsave locks in rxe with bh locks.
> This ran into problems because rdmacm has a bad habit of
> calling rdma verbs APIs while disabling irqs. This is not allowed
> during spin_unlock_bh() causing programs that use rdmacm to fail.
> This patch reverts the changes to locks that had this problem or
> got dragged into the same mess. After this patch blktests/check -q srp
> now runs correctly.
>
> This patch applies cleanly to current for-next
>
> commit: 2f1b2820b546 ("Merge branch 'irdma_dscp' into rdma.git for-next")
>
> Reported-by: Guoqing Jiang <guoqing.jiang@linux.dev>
> Reported-by: Bart Van Assche <bvanassche@acm.org>
> Fixes: 21adfa7a3c4e ("RDMA/rxe: Replace irqsave locks with bh locks")
> Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
> ---

Acked-by: Guoqing Jiang<guoqing.jiang@linux.dev>

Thanks,
Guoqing
diff mbox series

Patch

diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c
index 6baaaa34458e..642b52539ac3 100644
--- a/drivers/infiniband/sw/rxe/rxe_cq.c
+++ b/drivers/infiniband/sw/rxe/rxe_cq.c
@@ -42,13 +42,14 @@  int rxe_cq_chk_attr(struct rxe_dev *rxe, struct rxe_cq *cq,
 static void rxe_send_complete(struct tasklet_struct *t)
 {
 	struct rxe_cq *cq = from_tasklet(cq, t, comp_task);
+	unsigned long flags;
 
-	spin_lock_bh(&cq->cq_lock);
+	spin_lock_irqsave(&cq->cq_lock, flags);
 	if (cq->is_dying) {
-		spin_unlock_bh(&cq->cq_lock);
+		spin_unlock_irqrestore(&cq->cq_lock, flags);
 		return;
 	}
-	spin_unlock_bh(&cq->cq_lock);
+	spin_unlock_irqrestore(&cq->cq_lock, flags);
 
 	cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
 }
@@ -107,12 +108,13 @@  int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
 	struct ib_event ev;
 	int full;
 	void *addr;
+	unsigned long flags;
 
-	spin_lock_bh(&cq->cq_lock);
+	spin_lock_irqsave(&cq->cq_lock, flags);
 
 	full = queue_full(cq->queue, QUEUE_TYPE_TO_CLIENT);
 	if (unlikely(full)) {
-		spin_unlock_bh(&cq->cq_lock);
+		spin_unlock_irqrestore(&cq->cq_lock, flags);
 		if (cq->ibcq.event_handler) {
 			ev.device = cq->ibcq.device;
 			ev.element.cq = &cq->ibcq;
@@ -128,7 +130,7 @@  int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
 
 	queue_advance_producer(cq->queue, QUEUE_TYPE_TO_CLIENT);
 
-	spin_unlock_bh(&cq->cq_lock);
+	spin_unlock_irqrestore(&cq->cq_lock, flags);
 
 	if ((cq->notify == IB_CQ_NEXT_COMP) ||
 	    (cq->notify == IB_CQ_SOLICITED && solicited)) {
@@ -141,9 +143,11 @@  int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
 
 void rxe_cq_disable(struct rxe_cq *cq)
 {
-	spin_lock_bh(&cq->cq_lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&cq->cq_lock, flags);
 	cq->is_dying = true;
-	spin_unlock_bh(&cq->cq_lock);
+	spin_unlock_irqrestore(&cq->cq_lock, flags);
 }
 
 void rxe_cq_cleanup(struct rxe_pool_elem *elem)
diff --git a/drivers/infiniband/sw/rxe/rxe_mcast.c b/drivers/infiniband/sw/rxe/rxe_mcast.c
index 9336295c4ee2..2878a56d9994 100644
--- a/drivers/infiniband/sw/rxe/rxe_mcast.c
+++ b/drivers/infiniband/sw/rxe/rxe_mcast.c
@@ -58,11 +58,12 @@  static int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
 	int err;
 	struct rxe_mcg *grp;
 	struct rxe_pool *pool = &rxe->mc_grp_pool;
+	unsigned long flags;
 
 	if (rxe->attr.max_mcast_qp_attach == 0)
 		return -EINVAL;
 
-	write_lock_bh(&pool->pool_lock);
+	write_lock_irqsave(&pool->pool_lock, flags);
 
 	grp = rxe_pool_get_key_locked(pool, mgid);
 	if (grp)
@@ -70,13 +71,13 @@  static int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
 
 	grp = create_grp(rxe, pool, mgid);
 	if (IS_ERR(grp)) {
-		write_unlock_bh(&pool->pool_lock);
+		write_unlock_irqrestore(&pool->pool_lock, flags);
 		err = PTR_ERR(grp);
 		return err;
 	}
 
 done:
-	write_unlock_bh(&pool->pool_lock);
+	write_unlock_irqrestore(&pool->pool_lock, flags);
 	*grp_p = grp;
 	return 0;
 }
@@ -86,9 +87,10 @@  static int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
 {
 	int err;
 	struct rxe_mca *elem;
+	unsigned long flags;
 
 	/* check to see of the qp is already a member of the group */
-	spin_lock_bh(&grp->mcg_lock);
+	spin_lock_irqsave(&grp->mcg_lock, flags);
 	list_for_each_entry(elem, &grp->qp_list, qp_list) {
 		if (elem->qp == qp) {
 			err = 0;
@@ -118,7 +120,7 @@  static int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
 
 	err = 0;
 out:
-	spin_unlock_bh(&grp->mcg_lock);
+	spin_unlock_irqrestore(&grp->mcg_lock, flags);
 	return err;
 }
 
@@ -127,12 +129,13 @@  static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
 {
 	struct rxe_mcg *grp;
 	struct rxe_mca *elem, *tmp;
+	unsigned long flags;
 
 	grp = rxe_pool_get_key(&rxe->mc_grp_pool, mgid);
 	if (!grp)
 		goto err1;
 
-	spin_lock_bh(&grp->mcg_lock);
+	spin_lock_irqsave(&grp->mcg_lock, flags);
 
 	list_for_each_entry_safe(elem, tmp, &grp->qp_list, qp_list) {
 		if (elem->qp == qp) {
@@ -140,7 +143,7 @@  static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
 			grp->num_qp--;
 			atomic_dec(&qp->mcg_num);
 
-			spin_unlock_bh(&grp->mcg_lock);
+			spin_unlock_irqrestore(&grp->mcg_lock, flags);
 			rxe_drop_ref(elem);
 			rxe_drop_ref(grp);	/* ref held by QP */
 			rxe_drop_ref(grp);	/* ref from get_key */
@@ -148,7 +151,7 @@  static int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
 		}
 	}
 
-	spin_unlock_bh(&grp->mcg_lock);
+	spin_unlock_irqrestore(&grp->mcg_lock, flags);
 	rxe_drop_ref(grp);			/* ref from get_key */
 err1:
 	return -EINVAL;
diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c
index 63c594173565..a11dab13c192 100644
--- a/drivers/infiniband/sw/rxe/rxe_pool.c
+++ b/drivers/infiniband/sw/rxe/rxe_pool.c
@@ -260,11 +260,12 @@  int __rxe_add_key_locked(struct rxe_pool_elem *elem, void *key)
 int __rxe_add_key(struct rxe_pool_elem *elem, void *key)
 {
 	struct rxe_pool *pool = elem->pool;
+	unsigned long flags;
 	int err;
 
-	write_lock_bh(&pool->pool_lock);
+	write_lock_irqsave(&pool->pool_lock, flags);
 	err = __rxe_add_key_locked(elem, key);
-	write_unlock_bh(&pool->pool_lock);
+	write_unlock_irqrestore(&pool->pool_lock, flags);
 
 	return err;
 }
@@ -279,10 +280,11 @@  void __rxe_drop_key_locked(struct rxe_pool_elem *elem)
 void __rxe_drop_key(struct rxe_pool_elem *elem)
 {
 	struct rxe_pool *pool = elem->pool;
+	unsigned long flags;
 
-	write_lock_bh(&pool->pool_lock);
+	write_lock_irqsave(&pool->pool_lock, flags);
 	__rxe_drop_key_locked(elem);
-	write_unlock_bh(&pool->pool_lock);
+	write_unlock_irqrestore(&pool->pool_lock, flags);
 }
 
 int __rxe_add_index_locked(struct rxe_pool_elem *elem)
@@ -299,11 +301,12 @@  int __rxe_add_index_locked(struct rxe_pool_elem *elem)
 int __rxe_add_index(struct rxe_pool_elem *elem)
 {
 	struct rxe_pool *pool = elem->pool;
+	unsigned long flags;
 	int err;
 
-	write_lock_bh(&pool->pool_lock);
+	write_lock_irqsave(&pool->pool_lock, flags);
 	err = __rxe_add_index_locked(elem);
-	write_unlock_bh(&pool->pool_lock);
+	write_unlock_irqrestore(&pool->pool_lock, flags);
 
 	return err;
 }
@@ -319,10 +322,11 @@  void __rxe_drop_index_locked(struct rxe_pool_elem *elem)
 void __rxe_drop_index(struct rxe_pool_elem *elem)
 {
 	struct rxe_pool *pool = elem->pool;
+	unsigned long flags;
 
-	write_lock_bh(&pool->pool_lock);
+	write_lock_irqsave(&pool->pool_lock, flags);
 	__rxe_drop_index_locked(elem);
-	write_unlock_bh(&pool->pool_lock);
+	write_unlock_irqrestore(&pool->pool_lock, flags);
 }
 
 void *rxe_alloc_locked(struct rxe_pool *pool)
@@ -440,11 +444,12 @@  void *rxe_pool_get_index_locked(struct rxe_pool *pool, u32 index)
 
 void *rxe_pool_get_index(struct rxe_pool *pool, u32 index)
 {
+	unsigned long flags;
 	void *obj;
 
-	read_lock_bh(&pool->pool_lock);
+	read_lock_irqsave(&pool->pool_lock, flags);
 	obj = rxe_pool_get_index_locked(pool, index);
-	read_unlock_bh(&pool->pool_lock);
+	read_unlock_irqrestore(&pool->pool_lock, flags);
 
 	return obj;
 }
@@ -484,11 +489,12 @@  void *rxe_pool_get_key_locked(struct rxe_pool *pool, void *key)
 
 void *rxe_pool_get_key(struct rxe_pool *pool, void *key)
 {
+	unsigned long flags;
 	void *obj;
 
-	read_lock_bh(&pool->pool_lock);
+	read_lock_irqsave(&pool->pool_lock, flags);
 	obj = rxe_pool_get_key_locked(pool, key);
-	read_unlock_bh(&pool->pool_lock);
+	read_unlock_irqrestore(&pool->pool_lock, flags);
 
 	return obj;
 }
diff --git a/drivers/infiniband/sw/rxe/rxe_queue.c b/drivers/infiniband/sw/rxe/rxe_queue.c
index a1b283dd2d4c..dbd4971039c0 100644
--- a/drivers/infiniband/sw/rxe/rxe_queue.c
+++ b/drivers/infiniband/sw/rxe/rxe_queue.c
@@ -151,6 +151,8 @@  int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
 	struct rxe_queue *new_q;
 	unsigned int num_elem = *num_elem_p;
 	int err;
+	unsigned long producer_flags;
+	unsigned long consumer_flags;
 
 	new_q = rxe_queue_init(q->rxe, &num_elem, elem_size, q->type);
 	if (!new_q)
@@ -164,17 +166,17 @@  int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
 		goto err1;
 	}
 
-	spin_lock_bh(consumer_lock);
+	spin_lock_irqsave(consumer_lock, consumer_flags);
 
 	if (producer_lock) {
-		spin_lock_bh(producer_lock);
+		spin_lock_irqsave(producer_lock, producer_flags);
 		err = resize_finish(q, new_q, num_elem);
-		spin_unlock_bh(producer_lock);
+		spin_unlock_irqrestore(producer_lock, producer_flags);
 	} else {
 		err = resize_finish(q, new_q, num_elem);
 	}
 
-	spin_unlock_bh(consumer_lock);
+	spin_unlock_irqrestore(consumer_lock, consumer_flags);
 
 	rxe_queue_cleanup(new_q);	/* new/old dep on err */
 	if (err)
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
index 380934e38923..c369d78fc8e8 100644
--- a/drivers/infiniband/sw/rxe/rxe_resp.c
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -297,21 +297,22 @@  static enum resp_states get_srq_wqe(struct rxe_qp *qp)
 	struct ib_event ev;
 	unsigned int count;
 	size_t size;
+	unsigned long flags;
 
 	if (srq->error)
 		return RESPST_ERR_RNR;
 
-	spin_lock_bh(&srq->rq.consumer_lock);
+	spin_lock_irqsave(&srq->rq.consumer_lock, flags);
 
 	wqe = queue_head(q, QUEUE_TYPE_FROM_CLIENT);
 	if (!wqe) {
-		spin_unlock_bh(&srq->rq.consumer_lock);
+		spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
 		return RESPST_ERR_RNR;
 	}
 
 	/* don't trust user space data */
 	if (unlikely(wqe->dma.num_sge > srq->rq.max_sge)) {
-		spin_unlock_bh(&srq->rq.consumer_lock);
+		spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
 		pr_warn("%s: invalid num_sge in SRQ entry\n", __func__);
 		return RESPST_ERR_MALFORMED_WQE;
 	}
@@ -327,11 +328,11 @@  static enum resp_states get_srq_wqe(struct rxe_qp *qp)
 		goto event;
 	}
 
-	spin_unlock_bh(&srq->rq.consumer_lock);
+	spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
 	return RESPST_CHK_LENGTH;
 
 event:
-	spin_unlock_bh(&srq->rq.consumer_lock);
+	spin_unlock_irqrestore(&srq->rq.consumer_lock, flags);
 	ev.device = qp->ibqp.device;
 	ev.element.srq = qp->ibqp.srq;
 	ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 9f0aef4b649d..80df9a8f71a1 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -384,8 +384,9 @@  static int rxe_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
 {
 	int err = 0;
 	struct rxe_srq *srq = to_rsrq(ibsrq);
+	unsigned long flags;
 
-	spin_lock_bh(&srq->rq.producer_lock);
+	spin_lock_irqsave(&srq->rq.producer_lock, flags);
 
 	while (wr) {
 		err = post_one_recv(&srq->rq, wr);
@@ -394,7 +395,7 @@  static int rxe_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
 		wr = wr->next;
 	}
 
-	spin_unlock_bh(&srq->rq.producer_lock);
+	spin_unlock_irqrestore(&srq->rq.producer_lock, flags);
 
 	if (err)
 		*bad_wr = wr;
@@ -643,18 +644,19 @@  static int post_one_send(struct rxe_qp *qp, const struct ib_send_wr *ibwr,
 	int err;
 	struct rxe_sq *sq = &qp->sq;
 	struct rxe_send_wqe *send_wqe;
+	unsigned long flags;
 	int full;
 
 	err = validate_send_wr(qp, ibwr, mask, length);
 	if (err)
 		return err;
 
-	spin_lock_bh(&qp->sq.sq_lock);
+	spin_lock_irqsave(&qp->sq.sq_lock, flags);
 
 	full = queue_full(sq->queue, QUEUE_TYPE_TO_DRIVER);
 
 	if (unlikely(full)) {
-		spin_unlock_bh(&qp->sq.sq_lock);
+		spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
 		return -ENOMEM;
 	}
 
@@ -663,7 +665,7 @@  static int post_one_send(struct rxe_qp *qp, const struct ib_send_wr *ibwr,
 
 	queue_advance_producer(sq->queue, QUEUE_TYPE_TO_DRIVER);
 
-	spin_unlock_bh(&qp->sq.sq_lock);
+	spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
 
 	return 0;
 }
@@ -743,6 +745,7 @@  static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
 	int err = 0;
 	struct rxe_qp *qp = to_rqp(ibqp);
 	struct rxe_rq *rq = &qp->rq;
+	unsigned long flags;
 
 	if (unlikely((qp_state(qp) < IB_QPS_INIT) || !qp->valid)) {
 		*bad_wr = wr;
@@ -756,7 +759,7 @@  static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
 		goto err1;
 	}
 
-	spin_lock_bh(&rq->producer_lock);
+	spin_lock_irqsave(&rq->producer_lock, flags);
 
 	while (wr) {
 		err = post_one_recv(rq, wr);
@@ -767,7 +770,7 @@  static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
 		wr = wr->next;
 	}
 
-	spin_unlock_bh(&rq->producer_lock);
+	spin_unlock_irqrestore(&rq->producer_lock, flags);
 
 	if (qp->resp.state == QP_STATE_ERROR)
 		rxe_run_task(&qp->resp.task, 1);
@@ -848,8 +851,9 @@  static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
 	int i;
 	struct rxe_cq *cq = to_rcq(ibcq);
 	struct rxe_cqe *cqe;
+	unsigned long flags;
 
-	spin_lock_bh(&cq->cq_lock);
+	spin_lock_irqsave(&cq->cq_lock, flags);
 	for (i = 0; i < num_entries; i++) {
 		cqe = queue_head(cq->queue, QUEUE_TYPE_FROM_DRIVER);
 		if (!cqe)
@@ -858,7 +862,7 @@  static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
 		memcpy(wc++, &cqe->ibwc, sizeof(*wc));
 		queue_advance_consumer(cq->queue, QUEUE_TYPE_FROM_DRIVER);
 	}
-	spin_unlock_bh(&cq->cq_lock);
+	spin_unlock_irqrestore(&cq->cq_lock, flags);
 
 	return i;
 }
@@ -878,8 +882,9 @@  static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
 	struct rxe_cq *cq = to_rcq(ibcq);
 	int ret = 0;
 	int empty;
+	unsigned long irq_flags;
 
-	spin_lock_bh(&cq->cq_lock);
+	spin_lock_irqsave(&cq->cq_lock, irq_flags);
 	if (cq->notify != IB_CQ_NEXT_COMP)
 		cq->notify = flags & IB_CQ_SOLICITED_MASK;
 
@@ -888,7 +893,7 @@  static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
 	if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && !empty)
 		ret = 1;
 
-	spin_unlock_bh(&cq->cq_lock);
+	spin_unlock_irqrestore(&cq->cq_lock, irq_flags);
 
 	return ret;
 }