Skip to content

Commit

Permalink
RDMA/amso1100: Prevent deadlock in destroy QP
Browse files Browse the repository at this point in the history
It is possible to swap the CQs used for send_cq and recv_cq when
creating two different QPs.  If these two QPs are then destroyed at
the same time, an AB-BA deadlock can occur because the CQ locks are
taken our of order.  Fix this by always taking CQ locks in a fixed
order.

Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Krishna Kumar authored and Roland Dreier committed Nov 29, 2006
1 parent 7013696 commit c9edea2
Showing 1 changed file with 28 additions and 8 deletions.
36 changes: 28 additions & 8 deletions drivers/infiniband/hw/amso1100/c2_qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,32 @@ int c2_alloc_qp(struct c2_dev *c2dev,
return err;
}

static inline void c2_lock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq)
{
if (send_cq == recv_cq)
spin_lock_irq(&send_cq->lock);
else if (send_cq > recv_cq) {
spin_lock_irq(&send_cq->lock);
spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
} else {
spin_lock_irq(&recv_cq->lock);
spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
}
}

static inline void c2_unlock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq)
{
if (send_cq == recv_cq)
spin_unlock_irq(&send_cq->lock);
else if (send_cq > recv_cq) {
spin_unlock(&recv_cq->lock);
spin_unlock_irq(&send_cq->lock);
} else {
spin_unlock(&send_cq->lock);
spin_unlock_irq(&recv_cq->lock);
}
}

void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp)
{
struct c2_cq *send_cq;
Expand All @@ -576,15 +602,9 @@ void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp)
* Lock CQs here, so that CQ polling code can do QP lookup
* without taking a lock.
*/
spin_lock_irq(&send_cq->lock);
if (send_cq != recv_cq)
spin_lock(&recv_cq->lock);

c2_lock_cqs(send_cq, recv_cq);
c2_free_qpn(c2dev, qp->qpn);

if (send_cq != recv_cq)
spin_unlock(&recv_cq->lock);
spin_unlock_irq(&send_cq->lock);
c2_unlock_cqs(send_cq, recv_cq);

/*
* Destory qp in the rnic...
Expand Down

0 comments on commit c9edea2

Please sign in to comment.