[ofa-general] [PATCH RFC] comp_vector support

Michael S. Tsirkin mst at dev.mellanox.co.il
Wed May 2 11:53:51 PDT 2007


The following untested patch does the following:

1. extends ib_create_cq to pass in comp_vector parameter, and updates all ULP/providers.
2. mthca is enhanced to support multiple vectors if MSI-X is enabled.
3. uverbs and IPoIB CM are enhanced to use multiple vectors if available

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

---

I plan to test and repost this in earnest soon, but wanted to first hear
what do people think about the API.
Note this closely parallels what we already have for userspace.

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 7fabb42..45d269b 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -161,9 +161,14 @@ static int alloc_name(char *name)
  */
 struct ib_device *ib_alloc_device(size_t size)
 {
+	struct ib_device *dev;
 	BUG_ON(size < sizeof (struct ib_device));
 
-	return kzalloc(size, GFP_KERNEL);
+	dev = kzalloc(size, GFP_KERNEL);
+	if (dev)
+		dev->num_comp_vectors = 1;
+
+	return dev;
 }
 EXPORT_SYMBOL(ib_alloc_device);
 
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 6edfecf..85ccf13 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -2771,7 +2771,7 @@ static int ib_mad_port_open(struct ib_device *device,
 	cq_size = (IB_MAD_QP_SEND_SIZE + IB_MAD_QP_RECV_SIZE) * 2;
 	port_priv->cq = ib_create_cq(port_priv->device,
 				     ib_mad_thread_completion_handler,
-				     NULL, port_priv, cq_size);
+				     NULL, port_priv, cq_size, 0);
 	if (IS_ERR(port_priv->cq)) {
 		printk(KERN_ERR PFX "Couldn't create ib_mad CQ\n");
 		ret = PTR_ERR(port_priv->cq);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 4fd75af..6b9390f 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -802,7 +802,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
 	INIT_LIST_HEAD(&obj->async_list);
 
 	cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
-					     file->ucontext, &udata);
+					     cmd.comp_vector, file->ucontext, &udata);
 	if (IS_ERR(cq)) {
 		ret = PTR_ERR(cq);
 		goto err_file;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index f8bc822..d44e547 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -752,7 +752,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
 	spin_unlock(&map_lock);
 
 	uverbs_dev->ib_dev           = device;
-	uverbs_dev->num_comp_vectors = 1;
+	uverbs_dev->num_comp_vectors = device->num_comp_vectors;
 
 	uverbs_dev->dev = cdev_alloc();
 	if (!uverbs_dev->dev)
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index ccdf93d..86ed8af 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -609,11 +609,11 @@ EXPORT_SYMBOL(ib_destroy_qp);
 struct ib_cq *ib_create_cq(struct ib_device *device,
 			   ib_comp_handler comp_handler,
 			   void (*event_handler)(struct ib_event *, void *),
-			   void *cq_context, int cqe)
+			   void *cq_context, int cqe, int comp_vector)
 {
 	struct ib_cq *cq;
 
-	cq = device->create_cq(device, cqe, NULL, NULL);
+	cq = device->create_cq(device, cqe, comp_vector, NULL, NULL);
 
 	if (!IS_ERR(cq)) {
 		cq->device        = device;
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
index 607c09b..46ea16b 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -290,7 +290,7 @@ static int c2_destroy_qp(struct ib_qp *ib_qp)
 	return 0;
 }
 
-static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries,
+static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries, int comp_vector,
 				  struct ib_ucontext *context,
 				  struct ib_udata *udata)
 {
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index af28a31..4f76b2e 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -139,7 +139,7 @@ static int iwch_destroy_cq(struct ib_cq *ib_cq)
 	return 0;
 }
 
-static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries,
+static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int comp_vector,
 			     struct ib_ucontext *ib_context,
 			     struct ib_udata *udata)
 {
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index e2cdc1a..67f0670 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -113,7 +113,7 @@ struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num)
 	return ret;
 }
 
-struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
+struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
 			     struct ib_ucontext *context,
 			     struct ib_udata *udata)
 {
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index 95fd59f..aff96ac 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -123,7 +123,7 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq);
 void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq);
 
 
-struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
+struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
 			     struct ib_ucontext *context,
 			     struct ib_udata *udata);
 
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 3b23d67..dbe2723 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -375,7 +375,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
 		return -EPERM;
 	}
 
-	ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void*)(-1), 10);
+	ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void*)(-1), 10, 0);
 	if (IS_ERR(ibcq)) {
 		ehca_err(&shca->ib_device, "Cannot create AQP1 CQ.");
 		return PTR_ERR(ibcq);
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
index ea78e6d..cfca5d1 100644
--- a/drivers/infiniband/hw/ipath/ipath_cq.c
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -204,7 +204,7 @@ static void send_complete(unsigned long data)
  *
  * Called by ib_create_cq() in the generic verbs code.
  */
-struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, int comp_vector,
 			      struct ib_ucontext *context,
 			      struct ib_udata *udata)
 {
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
index 7c4929f..865966d 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -734,7 +734,7 @@ int ipath_destroy_srq(struct ib_srq *ibsrq);
 
 int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
 
-struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, int comp_vector,
 			      struct ib_ucontext *context,
 			      struct ib_udata *udata);
 
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index efd79ef..61ff333 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -779,7 +779,7 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
 	return 0;
 }
 
-int mthca_init_cq(struct mthca_dev *dev, int nent,
+int mthca_init_cq(struct mthca_dev *dev, int nent, int comp_vector,
 		  struct mthca_ucontext *ctx, u32 pdn,
 		  struct mthca_cq *cq)
 {
@@ -790,6 +790,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 
 	cq->ibcq.cqe  = nent - 1;
 	cq->is_kernel = !ctx;
+	cq->eq = MTHCA_EQ_COMP + comp_vector;
 
 	cq->cqn = mthca_alloc(&dev->cq_table.alloc);
 	if (cq->cqn == -1)
@@ -844,7 +845,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 	else
 		cq_context->logsize_usrpage |= cpu_to_be32(dev->driver_uar.index);
 	cq_context->error_eqn       = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
-	cq_context->comp_eqn        = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn);
+	cq_context->comp_eqn        = cpu_to_be32(dev->eq_table.eq[cq->eq].eqn);
 	cq_context->pd              = cpu_to_be32(pdn);
 	cq_context->lkey            = cpu_to_be32(cq->buf.mr.ibmr.lkey);
 	cq_context->cqn             = cpu_to_be32(cq->cqn);
@@ -954,7 +955,7 @@ void mthca_free_cq(struct mthca_dev *dev,
 	spin_unlock_irq(&dev->cq_table.lock);
 
 	if (dev->mthca_flags & MTHCA_FLAG_MSI_X)
-		synchronize_irq(dev->eq_table.eq[MTHCA_EQ_COMP].msi_x_vector);
+		synchronize_irq(dev->eq_table.eq[cq->eq].msi_x_vector);
 	else
 		synchronize_irq(dev->pdev->irq);
 
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index b7e42ef..fcfb0e2 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -96,7 +96,8 @@ enum {
 	MTHCA_EQ_CMD,
 	MTHCA_EQ_ASYNC,
 	MTHCA_EQ_COMP,
-	MTHCA_NUM_EQ
+	MTHCA_NUM_EQ,
+	MTHCA_NUM_EQS = 32
 };
 
 enum {
@@ -497,7 +498,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
 		  struct ib_wc *entry);
 int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
 int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
-int mthca_init_cq(struct mthca_dev *dev, int nent,
+int mthca_init_cq(struct mthca_dev *dev, int nent, int comp_vector,
 		  struct mthca_ucontext *ctx, u32 pdn,
 		  struct mthca_cq *cq);
 void mthca_free_cq(struct mthca_dev *dev,
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 8ec9fa1..6e38f2a 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -161,6 +161,11 @@ struct mthca_eqe {
 	u8 owner;
 } __attribute__((packed));
 
+static inline int mthca_num_eq(struct mthca_dev *dev)
+{
+	return dev->ib_dev.num_comp_vectors + MTHCA_NUM_EQ - 1;
+}
+
 #define  MTHCA_EQ_ENTRY_OWNER_SW      (0 << 7)
 #define  MTHCA_EQ_ENTRY_OWNER_HW      (1 << 7)
 
@@ -657,7 +662,7 @@ static void mthca_free_irqs(struct mthca_dev *dev)
 
 	if (dev->eq_table.have_irq)
 		free_irq(dev->pdev->irq, dev);
-	for (i = 0; i < MTHCA_NUM_EQ; ++i)
+	for (i = 0; i < mthca_num_eq(dev); ++i)
 		if (dev->eq_table.eq[i].have_irq)
 			free_irq(dev->eq_table.eq[i].msi_x_vector,
 				 dev->eq_table.eq + i);
@@ -824,12 +829,37 @@ void mthca_unmap_eq_icm(struct mthca_dev *dev)
 	__free_page(dev->eq_table.icm_page);
 }
 
+static inline const char *eq_name(int i)
+{
+	switch (i) {
+	case MTHCA_EQ_ASYNC:
+		return DRV_NAME " (async)";
+	case MTHCA_EQ_CMD:
+		return DRV_NAME " (cmd)";
+	default:
+		return DRV_NAME " (comp)";
+	}
+}
+
+static inline int eq_size(struct mthca_dev *dev, int i)
+{
+	switch (i) {
+	case MTHCA_EQ_ASYNC:
+		return MTHCA_NUM_ASYNC_EQE;
+	case MTHCA_EQ_CMD:
+		return MTHCA_NUM_CMD_EQE;
+	default:
+		return dev->limits.num_cqs;
+	}
+}
+
+
 int mthca_init_eq_table(struct mthca_dev *dev)
 {
 	int err;
 	u8 status;
 	u8 intr;
-	int i;
+	int i, eqn;
 
 	err = mthca_alloc_init(&dev->eq_table.alloc,
 			       dev->limits.num_eqs,
@@ -857,39 +887,23 @@ int mthca_init_eq_table(struct mthca_dev *dev)
 	intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
 		128 : dev->eq_table.inta_pin;
 
-	err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
-			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
-			      &dev->eq_table.eq[MTHCA_EQ_COMP]);
-	if (err)
-		goto err_out_unmap;
-
-	err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE,
-			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr,
-			      &dev->eq_table.eq[MTHCA_EQ_ASYNC]);
-	if (err)
-		goto err_out_comp;
-
-	err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE,
-			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr,
-			      &dev->eq_table.eq[MTHCA_EQ_CMD]);
-	if (err)
-		goto err_out_async;
+	for (eqn = 0; eqn < mthca_num_eq(dev); ++eqn) {
+		err = mthca_create_eq(dev, eq_size(dev, eqn) + MTHCA_NUM_SPARE_EQE,
+				      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
+				      &dev->eq_table.eq[eqn]);
+		if (err)
+			goto err_out_eq;
+	}
 
 	if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
-		static const char *eq_name[] = {
-			[MTHCA_EQ_COMP]  = DRV_NAME " (comp)",
-			[MTHCA_EQ_ASYNC] = DRV_NAME " (async)",
-			[MTHCA_EQ_CMD]   = DRV_NAME " (cmd)"
-		};
-
-		for (i = 0; i < MTHCA_NUM_EQ; ++i) {
+		for (i = 0; i < mthca_num_eq(dev); ++i) {
 			err = request_irq(dev->eq_table.eq[i].msi_x_vector,
 					  mthca_is_memfree(dev) ?
 					  mthca_arbel_msi_x_interrupt :
 					  mthca_tavor_msi_x_interrupt,
-					  0, eq_name[i], dev->eq_table.eq + i);
+					  0, eq_name(i), dev->eq_table.eq + i);
 			if (err)
-				goto err_out_cmd;
+				goto err_out_irq;
 			dev->eq_table.eq[i].have_irq = 1;
 		}
 	} else {
@@ -899,7 +913,7 @@ int mthca_init_eq_table(struct mthca_dev *dev)
 				  mthca_tavor_interrupt,
 				  IRQF_SHARED, DRV_NAME, dev);
 		if (err)
-			goto err_out_cmd;
+			goto err_out_eq;
 		dev->eq_table.have_irq = 1;
 	}
 
@@ -929,17 +943,13 @@ int mthca_init_eq_table(struct mthca_dev *dev)
 
 	return 0;
 
-err_out_cmd:
+err_out_irq:
 	mthca_free_irqs(dev);
-	mthca_free_eq(dev, &dev->eq_table.eq[MTHCA_EQ_CMD]);
 
-err_out_async:
-	mthca_free_eq(dev, &dev->eq_table.eq[MTHCA_EQ_ASYNC]);
-
-err_out_comp:
-	mthca_free_eq(dev, &dev->eq_table.eq[MTHCA_EQ_COMP]);
+err_out_eq:
+	for (i = 0; i < eqn; ++i)
+		mthca_free_eq(dev, &dev->eq_table.eq[i]);
 
-err_out_unmap:
 	mthca_unmap_eq_regs(dev);
 
 err_out_free:
@@ -959,7 +969,7 @@ void mthca_cleanup_eq_table(struct mthca_dev *dev)
 	mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
 		     1, dev->eq_table.eq[MTHCA_EQ_CMD].eqn, &status);
 
-	for (i = 0; i < MTHCA_NUM_EQ; ++i)
+	for (i = 0; i < mthca_num_eq(dev); ++i)
 		mthca_free_eq(dev, &dev->eq_table.eq[i]);
 
 	mthca_unmap_eq_regs(dev);
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 773145e..83a54df 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -976,24 +976,27 @@ static void mthca_release_regions(struct pci_dev *pdev,
 
 static int mthca_enable_msi_x(struct mthca_dev *mdev)
 {
-	struct msix_entry entries[3];
-	int err;
+	struct msix_entry entries[MTHCA_NUM_EQS];
+	int i, err;
 
-	entries[0].entry = 0;
-	entries[1].entry = 1;
-	entries[2].entry = 2;
+	for (i = 0; i < MTHCA_NUM_EQS; ++i)
+		entries[i].entry = i;
 
-	err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries));
+	err = pci_enable_msix(mdev->pdev, entries, MTHCA_NUM_EQS);
 	if (err) {
 		if (err > 0)
-			mthca_info(mdev, "Only %d MSI-X vectors available, "
-				   "not using MSI-X\n", err);
-		return err;
+			mthca_info(mdev, "Only %d MSI-X vectors available.", err);
+
+		if (err < MTHCA_NUM_EQ) {
+			mthca_info(mdev, "Not using MSI-X: %d\n", err);
+			pci_disable_msix(mdev->pdev);
+			return err;
+		}
 	}
 
-	mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector = entries[0].vector;
-	mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector = entries[1].vector;
-	mdev->eq_table.eq[MTHCA_EQ_CMD  ].msi_x_vector = entries[2].vector;
+	mdev->ib_dev.num_comp_vectors = err - MTHCA_NUM_EQ + 1;
+	for (i = 0; i < err; ++i)
+		mdev->eq_table.eq[i ].msi_x_vector = entries[i].vector;
 
 	return 0;
 }
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
index 26bf86d..834b303 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.c
+++ b/drivers/infiniband/hw/mthca/mthca_profile.c
@@ -59,7 +59,6 @@ enum {
 };
 
 enum {
-	MTHCA_NUM_EQS = 32,
 	MTHCA_NUM_PDS = 1 << 15
 };
 
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 47e6fd4..0b125b0 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -663,6 +663,7 @@ static int mthca_destroy_qp(struct ib_qp *qp)
 }
 
 static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
+				     int comp_vector,
 				     struct ib_ucontext *context,
 				     struct ib_udata *udata)
 {
@@ -706,7 +707,7 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
 	for (nent = 1; nent <= entries; nent <<= 1)
 		; /* nothing */
 
-	err = mthca_init_cq(to_mdev(ibdev), nent,
+	err = mthca_init_cq(to_mdev(ibdev), nent, comp_vector,
 			    context ? to_mucontext(context) : NULL,
 			    context ? ucmd.pdn : to_mdev(ibdev)->driver_pd.pd_num,
 			    cq);
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 1d266ac..591d953 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -202,6 +202,7 @@ struct mthca_cq {
 	spinlock_t		lock;
 	int			refcount;
 	int			cqn;
+	int			eq;
 	u32			cons_index;
 	struct mthca_cq_buf	buf;
 	struct mthca_cq_resize *resize_buf;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 0c4e59b..1778fd6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -789,7 +789,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
 	}
 
 	p->cq = ib_create_cq(priv->ca, ipoib_cm_tx_completion, NULL, p,
-			     ipoib_sendq_size + 1);
+			     ipoib_sendq_size + 1, priv->ca->num_comp_vectors > 1);
 	if (IS_ERR(p->cq)) {
 		ret = PTR_ERR(p->cq);
 		ipoib_warn(priv, "failed to allocate tx cq: %d\n", ret);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 7f3ec20..5c3c6a4 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -187,7 +187,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
 	if (!ret)
 		size += ipoib_recvq_size;
 
-	priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size);
+	priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
 	if (IS_ERR(priv->cq)) {
 		printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
 		goto out_free_mr;
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 1fc9674..89d6008 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -76,7 +76,7 @@ static int iser_create_device_ib_res(struct iser_device *device)
 				  iser_cq_callback,
 				  iser_cq_event_callback,
 				  (void *)device,
-				  ISER_MAX_CQ_LEN);
+				  ISER_MAX_CQ_LEN, 0);
 	if (IS_ERR(device->cq))
 		goto cq_err;
 
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 5e8ac57..33c249a 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -197,7 +197,7 @@ static int srp_create_target_ib(struct srp_target_port *target)
 		return -ENOMEM;
 
 	target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion,
-				  NULL, target, SRP_CQ_SIZE);
+				  NULL, target, SRP_CQ_SIZE, 0);
 	if (IS_ERR(target->cq)) {
 		ret = PTR_ERR(target->cq);
 		goto out;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 765589f..a16e509 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -912,6 +912,8 @@ struct ib_device {
 
 	u32                           flags;
 
+	int                           num_comp_vectors;
+
 	struct iw_cm_verbs	     *iwcm;
 
 	int		           (*query_device)(struct ib_device *device,
@@ -978,6 +980,7 @@ struct ib_device {
 						struct ib_recv_wr *recv_wr,
 						struct ib_recv_wr **bad_recv_wr);
 	struct ib_cq *             (*create_cq)(struct ib_device *device, int cqe,
+						int comp_vector,
 						struct ib_ucontext *context,
 						struct ib_udata *udata);
 	int                        (*destroy_cq)(struct ib_cq *cq);
@@ -1358,13 +1361,15 @@ static inline int ib_post_recv(struct ib_qp *qp,
  * @cq_context: Context associated with the CQ returned to the user via
  *   the associated completion and event handlers.
  * @cqe: The minimum size of the CQ.
+ * @comp_vector - Completion vector used to signal completion events.
+ *     Must be >= 0 and < context->num_comp_vectors.
  *
  * Users can examine the cq structure to determine the actual CQ size.
  */
 struct ib_cq *ib_create_cq(struct ib_device *device,
 			   ib_comp_handler comp_handler,
 			   void (*event_handler)(struct ib_event *, void *),
-			   void *cq_context, int cqe);
+			   void *cq_context, int cqe, int comp_vector);
 
 /**
  * ib_resize_cq - Modifies the capacity of the CQ.

-- 
MST



More information about the general mailing list