[openib-general] [PATCH] 1/2 separate locking for send and receive q in mthca

Michael S. Tsirkin mst at mellanox.co.il
Thu Feb 3 09:54:19 PST 2005


Hello!
Send and receive q posting both serialise on the same spinlock in mthca.
Not good for SMP.  The following patch solves this.
Together with my rx/tx split patch, I get about 2% more bandwidth on
ip over ib with this.

Applies on top of the "bugfix: remove unbalanced qp refcount" patch.

Now that I see real effect, I'll repost the ip over ib rx/tx split patch, too,
for completeness.

Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>

Index: hw/mthca/mthca_provider.h
===================================================================
--- hw/mthca/mthca_provider.h	(revision 1725)
+++ hw/mthca/mthca_provider.h	(working copy)
@@ -147,6 +147,7 @@ struct mthca_cq {
 };
 
 struct mthca_wq {
+	spinlock_t lock;
 	int   max;
 	int   cur;
 	int   next;
@@ -159,7 +160,6 @@ struct mthca_wq {
 
 struct mthca_qp {
 	struct ib_qp           ibqp;
-	spinlock_t             lock;
 	atomic_t               refcount;
 	u32                    qpn;
 	int                    is_direct;
Index: hw/mthca/mthca_cq.c
===================================================================
--- hw/mthca/mthca_cq.c	(revision 1725)
+++ hw/mthca/mthca_cq.c	(working copy)
@@ -370,12 +370,14 @@ static void dump_cqe(struct mthca_cqe *c
 
 static inline int mthca_poll_one(struct mthca_dev *dev,
 				 struct mthca_cq *cq,
-				 struct mthca_qp **cur_qp,
+				 struct mthca_wq **cur_wq,
 				 int *freed,
 				 struct ib_wc *entry)
 {
 	struct mthca_wq *wq;
+	struct mthca_qp *qp;
 	struct mthca_cqe *cqe;
+	u32 qpn;
 	int wqe_index;
 	int is_error;
 	int is_send;
@@ -392,9 +394,11 @@ static inline int mthca_poll_one(struct 
 	 */
 	rmb();
 
+	qpn = be32_to_cpu(cqe->my_qpn);
+
 	if (0) {
 		mthca_dbg(dev, "%x/%d: CQE -> QPN %06x, WQE @ %08x\n",
-			  cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn),
+			  cq->cqn, cq->cons_index, qpn,
 			  be32_to_cpu(cqe->wqe));
 
 		dump_cqe(cqe);
@@ -404,14 +408,21 @@ static inline int mthca_poll_one(struct 
 		MTHCA_ERROR_CQE_OPCODE_MASK;
 	is_send  = is_error ? cqe->opcode & 0x01 : cqe->is_send & 0x80;
 
-	if (!*cur_qp || be32_to_cpu(cqe->my_qpn) != (*cur_qp)->qpn) {
-		if (*cur_qp) {
+	wq = *cur_wq;
+
+	if (is_send)
+		qp = wq ? container_of(wq, struct mthca_qp, sq) : NULL;
+	else
+		qp = wq ? container_of(wq, struct mthca_qp, rq) : NULL;
+
+	if (!qp || be32_to_cpu(cqe->my_qpn) != qp->qpn) {
+		if (qp) {
 			if (*freed) {
 				wmb();
 				inc_cons_index(dev, cq, *freed);
 				*freed = 0;
 			}
-			spin_unlock(&(*cur_qp)->lock);
+			spin_unlock(&wq->lock);
 		}
 
 		/*
@@ -421,31 +430,29 @@ static inline int mthca_poll_one(struct 
 		 * because CQs will be locked while QPs are removed
 		 * from the table.
 		 */
-		*cur_qp = mthca_array_get(&dev->qp_table.qp,
+		qp = mthca_array_get(&dev->qp_table.qp,
 					  be32_to_cpu(cqe->my_qpn) &
 					  (dev->limits.num_qps - 1));
-		if (!*cur_qp) {
+		if (!qp) {
 			mthca_warn(dev, "CQ entry for unknown QP %06x\n",
 				   be32_to_cpu(cqe->my_qpn) & 0xffffff);
 			err = -EINVAL;
 			goto out;
 		}
 
-		spin_lock(&(*cur_qp)->lock);
+		*cur_wq = wq = is_send ? &qp->sq : &qp->rq;
+		spin_lock(&wq->lock);
 	}
 
-	entry->qp_num = (*cur_qp)->qpn;
+	entry->qp_num = qpn;
 
 	if (is_send) {
-		wq = &(*cur_qp)->sq;
-		wqe_index = ((be32_to_cpu(cqe->wqe) - (*cur_qp)->send_wqe_offset)
+		wqe_index = ((be32_to_cpu(cqe->wqe) - qp->send_wqe_offset)
 			     >> wq->wqe_shift);
-		entry->wr_id = (*cur_qp)->wrid[wqe_index +
-					       (*cur_qp)->rq.max];
+		entry->wr_id = qp->wrid[wqe_index + qp->rq.max];
 	} else {
-		wq = &(*cur_qp)->rq;
 		wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
-		entry->wr_id = (*cur_qp)->wrid[wqe_index];
+		entry->wr_id = qp->wrid[wqe_index];
 	}
 
 	if (wq->last_comp < wqe_index)
@@ -458,10 +465,10 @@ static inline int mthca_poll_one(struct 
 	if (0)
 		mthca_dbg(dev, "%s completion for QP %06x, index %d (nr %d)\n",
 			  is_send ? "Send" : "Receive",
-			  (*cur_qp)->qpn, wqe_index, wq->max);
+			  qp->qpn, wqe_index, wq->max);
 
 	if (is_error) {
-		err = handle_error_cqe(dev, cq, *cur_qp, wqe_index, is_send,
+		err = handle_error_cqe(dev, cq, qp, wqe_index, is_send,
 				       (struct mthca_err_cqe *) cqe,
 				       entry, &free_cqe);
 		goto out;
@@ -515,7 +522,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, in
 {
 	struct mthca_dev *dev = to_mdev(ibcq->device);
 	struct mthca_cq *cq = to_mcq(ibcq);
-	struct mthca_qp *qp = NULL;
+	struct mthca_wq *wq = NULL;
 	unsigned long flags;
 	int err = 0;
 	int freed = 0;
@@ -524,7 +531,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, in
 	spin_lock_irqsave(&cq->lock, flags);
 
 	for (npolled = 0; npolled < num_entries; ++npolled) {
-		err = mthca_poll_one(dev, cq, &qp,
+		err = mthca_poll_one(dev, cq, &wq,
 				     &freed, entry + npolled);
 		if (err)
 			break;
@@ -535,8 +542,8 @@ int mthca_poll_cq(struct ib_cq *ibcq, in
 		inc_cons_index(dev, cq, freed);
 	}
 
-	if (qp)
-		spin_unlock(&qp->lock);
+	if (wq)
+		spin_unlock(&wq->lock);
 
 	spin_unlock_irqrestore(&cq->lock, flags);
 
Index: hw/mthca/mthca_qp.c
===================================================================
--- hw/mthca/mthca_qp.c	(revision 1725)
+++ hw/mthca/mthca_qp.c	(working copy)
@@ -552,9 +552,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, 
 		else
 			cur_state = attr->cur_qp_state;
 	} else {
-		spin_lock_irq(&qp->lock);
+		spin_lock_irq(&qp->sq.lock);
+		spin_lock(&qp->rq.lock);
 		cur_state = qp->state;
-		spin_unlock_irq(&qp->lock);
+		spin_unlock(&qp->rq.lock);
+		spin_unlock_irq(&qp->sq.lock);
 	}
 
 	if (attr_mask & IB_QP_STATE) {
@@ -982,7 +984,8 @@ static int mthca_alloc_qp_common(struct 
 {
 	int err;
 
-	spin_lock_init(&qp->lock);
+	spin_lock_init(&qp->sq.lock);
+	spin_lock_init(&qp->rq.lock);
 	atomic_set(&qp->refcount, 1);
 	qp->state    	 = IB_QPS_RESET;
 	qp->atomic_rd_en = 0;
@@ -1272,7 +1275,7 @@ int mthca_post_send(struct ib_qp *ibqp, 
 		[IB_WR_ATOMIC_FETCH_AND_ADD] = MTHCA_OPCODE_ATOMIC_FA,
 	};
 
-	spin_lock_irqsave(&qp->lock, flags);
+	spin_lock_irqsave(&qp->sq.lock, flags);
 
 	/* XXX check that state is OK to post send */
 
@@ -1455,7 +1458,7 @@ out:
 	qp->sq.cur += nreq;
 	qp->sq.next = ind;
 
-	spin_unlock_irqrestore(&qp->lock, flags);
+	spin_unlock_irqrestore(&qp->sq.lock, flags);
 	return err;
 }
 
@@ -1474,7 +1477,7 @@ int mthca_post_receive(struct ib_qp *ibq
 	void *wqe;
 	void *prev_wqe;
 
-	spin_lock_irqsave(&qp->lock, flags);
+	spin_lock_irqsave(&qp->rq.lock, flags);
 
 	/* XXX check that state is OK to post receive */
 
@@ -1554,7 +1557,7 @@ out:
 	qp->rq.cur += nreq;
 	qp->rq.next = ind;
 
-	spin_unlock_irqrestore(&qp->lock, flags);
+	spin_unlock_irqrestore(&qp->rq.lock, flags);
 	return err;
 }
 
-- 
MST - Michael S. Tsirkin



More information about the general mailing list