[openib-general] [PATCH 4/5] [RFC] libmthca changes for resize CQ

Roland Dreier rolandd at cisco.com
Thu Jan 26 11:23:33 PST 2006


libmthca implementation of resizing CQs.  This is the real guts of
it -- there is some slightly tricky code to handle the transition from
the old CQ buffer to the new one.

---

--- libmthca/src/verbs.c	(revision 5192)
+++ libmthca/src/verbs.c	(working copy)
@@ -41,6 +41,7 @@
 #include <stdio.h>
 #include <strings.h>
 #include <pthread.h>
+#include <errno.h>
 #include <netinet/in.h>
 
 #include "mthca.h"
@@ -154,6 +155,16 @@ int mthca_dereg_mr(struct ibv_mr *mr)
 	return 0;
 }
 
+static int align_cq_size(int cqe)
+{
+	int nent;
+
+	for (nent = 1; nent <= cqe; nent <<= 1)
+		; /* nothing */
+
+	return nent;
+}
+
 struct ibv_cq *mthca_create_cq(struct ibv_context *context, int cqe,
 			       struct ibv_comp_channel *channel,
 			       int comp_vector)
@@ -161,27 +172,24 @@ struct ibv_cq *mthca_create_cq(struct ib
 	struct mthca_create_cq      cmd;
 	struct mthca_create_cq_resp resp;
 	struct mthca_cq      	   *cq;
-	int                  	    nent;
 	int                  	    ret;
 
 	cq = malloc(sizeof *cq);
 	if (!cq)
 		return NULL;
 
+	cq->cons_index = 0;
+
 	if (pthread_spin_init(&cq->lock, PTHREAD_PROCESS_PRIVATE))
 		goto err;
 
-	for (nent = 1; nent <= cqe; nent <<= 1)
-		; /* nothing */
-
-	if (posix_memalign(&cq->buf, to_mdev(context->device)->page_size,
-			   align(nent * MTHCA_CQ_ENTRY_SIZE, to_mdev(context->device)->page_size)))
+	cqe = align_cq_size(cqe);
+	cq->buf = mthca_alloc_cq_buf(to_mdev(context->device), cqe);
+	if (!cq->buf)
 		goto err;
 
-	mthca_init_cq_buf(cq, nent);
-
 	cq->mr = __mthca_reg_mr(to_mctx(context)->pd, cq->buf,
-				nent * MTHCA_CQ_ENTRY_SIZE,
+				cqe * MTHCA_CQ_ENTRY_SIZE,
 				0, IBV_ACCESS_LOCAL_WRITE);
 	if (!cq->mr)
 		goto err_buf;
@@ -210,7 +218,7 @@ struct ibv_cq *mthca_create_cq(struct ib
 
 	cmd.lkey   = cq->mr->lkey;
 	cmd.pdn    = to_mpd(to_mctx(context)->pd)->pdn;
-	ret = ibv_cmd_create_cq(context, nent - 1, channel, comp_vector,
+	ret = ibv_cmd_create_cq(context, cqe - 1, channel, comp_vector,
 				&cq->ibv_cq, &cmd.ibv_cmd, sizeof cmd,
 				&resp.ibv_resp, sizeof resp);
 	if (ret)
@@ -247,6 +255,63 @@ err:
 	return NULL;
 }
 
+int mthca_resize_cq(struct ibv_cq *ibcq, int cqe)
+{
+	struct mthca_cq *cq = to_mcq(ibcq);
+	struct mthca_resize_cq cmd;
+	struct ibv_mr *mr;
+	void *buf;
+	int old_cqe;
+	int ret;
+
+	pthread_spin_lock(&cq->lock);
+
+	cqe = align_cq_size(cqe);
+	if (cqe == ibcq->cqe + 1) {
+		ret = 0;
+		goto out;
+	}
+
+	buf = mthca_alloc_cq_buf(to_mdev(ibcq->context->device), cqe);
+	if (!buf) {
+		ret = ENOMEM;
+		goto out;
+	}
+
+	mr = __mthca_reg_mr(to_mctx(ibcq->context)->pd, buf,
+			    cqe * MTHCA_CQ_ENTRY_SIZE,
+			    0, IBV_ACCESS_LOCAL_WRITE);
+	if (!mr) {
+		free(buf);
+		ret = ENOMEM;
+		goto out;
+	}
+
+	mr->context = ibcq->context;
+
+	old_cqe = ibcq->cqe;
+
+	cmd.lkey = mr->lkey;
+	ret = ibv_cmd_resize_cq(ibcq, cqe - 1, &cmd.ibv_cmd, sizeof cmd);
+	if (ret) {
+		mthca_dereg_mr(mr);
+		free(buf);
+		goto out;
+	}
+
+	mthca_cq_resize_copy_cqes(cq, buf, old_cqe);
+
+	mthca_dereg_mr(cq->mr);
+	free(cq->buf);
+	
+	cq->buf = buf;
+	cq->mr  = mr;
+
+out:
+	pthread_spin_unlock(&cq->lock);
+	return ret;
+}
+
 int mthca_destroy_cq(struct ibv_cq *cq)
 {
 	int ret;
--- libmthca/src/mthca.h	(revision 5192)
+++ libmthca/src/mthca.h	(working copy)
@@ -281,6 +281,7 @@ extern int mthca_dereg_mr(struct ibv_mr 
 struct ibv_cq *mthca_create_cq(struct ibv_context *context, int cqe,
 			       struct ibv_comp_channel *channel,
 			       int comp_vector);
+extern int mthca_resize_cq(struct ibv_cq *cq, int cqe);
 extern int mthca_destroy_cq(struct ibv_cq *cq);
 extern int mthca_poll_cq(struct ibv_cq *cq, int ne, struct ibv_wc *wc);
 extern int mthca_tavor_arm_cq(struct ibv_cq *cq, int solicited);
@@ -288,7 +289,8 @@ extern int mthca_arbel_arm_cq(struct ibv
 extern void mthca_arbel_cq_event(struct ibv_cq *cq);
 extern void mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn,
 			   struct mthca_srq *srq);
-extern void mthca_init_cq_buf(struct mthca_cq *cq, int nent);
+extern void mthca_cq_resize_copy_cqes(struct mthca_cq *cq, void *buf, int new_cqe);
+extern void *mthca_alloc_cq_buf(struct mthca_device *dev, int cqe);
 
 extern struct ibv_srq *mthca_create_srq(struct ibv_pd *pd,
 					struct ibv_srq_init_attr *attr);
--- libmthca/src/cq.c	(revision 5192)
+++ libmthca/src/cq.c	(working copy)
@@ -38,8 +38,9 @@
 #endif /* HAVE_CONFIG_H */
 
 #include <stdio.h>
-#include <netinet/in.h>
+#include <stdlib.h>
 #include <pthread.h>
+#include <netinet/in.h>
 
 #include <infiniband/opcode.h>
 
@@ -578,12 +579,38 @@ void mthca_cq_clean(struct mthca_cq *cq,
 	pthread_spin_unlock(&cq->lock);
 }
 
-void mthca_init_cq_buf(struct mthca_cq *cq, int nent)
+void mthca_cq_resize_copy_cqes(struct mthca_cq *cq, void *buf, int old_cqe)
+{
+	int i;
+
+	/*
+	 * In Tavor mode, the hardware keeps the consumer and producer
+	 * indices mod the CQ size.  Since we might be making the CQ
+	 * bigger, we need to deal with the case where the producer
+	 * index wrapped around before the CQ was resized.
+	 */
+	if (!mthca_is_memfree(cq->ibv_cq.context) && old_cqe < cq->ibv_cq.cqe) {
+		cq->cons_index &= old_cqe;
+		if (cqe_sw(cq, old_cqe))
+			cq->cons_index -= old_cqe + 1;
+	}
+
+	for (i = cq->cons_index; cqe_sw(cq, i & old_cqe); ++i)
+		memcpy(buf + (i & cq->ibv_cq.cqe) * MTHCA_CQ_ENTRY_SIZE,
+		       get_cqe(cq, i & old_cqe), MTHCA_CQ_ENTRY_SIZE);
+}
+
+void *mthca_alloc_cq_buf(struct mthca_device *dev, int nent)
 {
+	void *buf;
 	int i;
 
+	if (posix_memalign(&buf, dev->page_size,
+			   align(nent * MTHCA_CQ_ENTRY_SIZE, dev->page_size)))
+		return NULL;
+
 	for (i = 0; i < nent; ++i)
-		set_cqe_hw(get_cqe(cq, i));
+		((struct mthca_cqe *) buf)[i].owner = MTHCA_CQ_ENTRY_OWNER_HW;
 
-	cq->cons_index = 0;
+	return buf;
 }
--- libmthca/src/mthca-abi.h	(revision 5192)
+++ libmthca/src/mthca-abi.h	(working copy)
@@ -65,6 +65,12 @@ struct mthca_create_cq_resp {
 	__u32				reserved;
 };
 
+struct mthca_resize_cq {
+	struct ibv_resize_cq		ibv_cmd;
+	__u32				lkey;
+	__u32				reserved;
+};
+
 struct mthca_create_srq {
 	struct ibv_create_srq		ibv_cmd;
 	__u32				lkey;
--- libmthca/src/mthca.c	(revision 5192)
+++ libmthca/src/mthca.c	(working copy)
@@ -105,6 +105,7 @@ static struct ibv_context_ops mthca_ctx_
 	.dereg_mr      = mthca_dereg_mr,
 	.create_cq     = mthca_create_cq,
 	.poll_cq       = mthca_poll_cq,
+	.resize_cq     = mthca_resize_cq,
 	.destroy_cq    = mthca_destroy_cq,
 	.create_srq    = mthca_create_srq,
 	.modify_srq    = mthca_modify_srq,
--- libmthca/ChangeLog	(revision 5192)
+++ libmthca/ChangeLog	(working copy)
@@ -1,3 +1,10 @@
+2006-01-26  Roland Dreier  <rdreier at cisco.com>
+
+	* src/mthca.h, src/verbs.c, src/cq.c, src/mthca.c: Add
+	implementation of resize CQ operation.
+
+	* src/mthca-abi.h: Add mthca-specific resize CQ ABI.
+
 2006-01-22  Roland Dreier  <rdreier at cisco.com>
 
 	* Release version 1.0-rc5.



More information about the general mailing list