[openib-general] [PATCH] RDMA/amso1100: Prevent deadlock.
Krishna Kumar
krkumar2 at in.ibm.com
Fri Nov 24 02:33:48 PST 2006
Merged two patches:
- create_qp and destroy_qp can be called from userspace
and from other kernel routines, and it is possible to
swap send_cq and recv_cq in different calls for
creating different qp's (RFC). This can result in a
deadlock, if the two locks are got out of order.
- Fix following warning in lockdep by teaching it about
nesting of lock class :
: [ INFO: possible recursive locking detected ]
: rdma_bw/3558 is trying to acquire lock:
: (&cq->lock){....}, at: [<f9398d36>] c2_free_qp+0x78/0x180 [iw_c2]
: but task is already holding lock:
: (&cq->lock){....}, at: [<f9398d29>] c2_free_qp+0x6b/0x180 [iw_c2]
Patch against 2.6.19-rc5.
Signed-off-by: Krishna Kumar <krkumar2 at in.ibm.com>
---
diff -ruNp org/drivers/infiniband/hw/amso1100/c2_qp.c new/drivers/infiniband/hw/amso1100/c2_qp.c
--- org/drivers/infiniband/hw/amso1100/c2_qp.c 2006-11-15 12:40:04.000000000 +0530
+++ new/drivers/infiniband/hw/amso1100/c2_qp.c 2006-11-16 18:10:03.000000000 +0530
@@ -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;
@@ -576,15 +602,9 @@ void c2_free_qp(struct c2_dev *c2dev, st
* 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...
More information about the general
mailing list