[openib-general] [RFC] [PATCH] RDMA/iwcm: Prevent deadlock in locking.

Krishna Kumar krkumar2 at in.ibm.com
Thu Nov 16 20:31:30 PST 2006


Since create_qp and destroy_qp can be called from
userspace and from other kernel routines, 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.

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_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
-
+	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