[ofa-general] [PATCH 2 of 3] IB/mthca: support multiple completion vectors
Michael S. Tsirkin
mst at dev.mellanox.co.il
Thu May 3 03:49:24 PDT 2007
Support 2 completion vectors in mthca on SMP if MSI-X is enabled
Signed-off-by: Michael S. Tsirkin <mst at dev.mellanox.co.il>
---
I don't know how many vectors make sense, so I decided to be
conservative here, since each EQ consumes a lot of memory by default.
Index: linux-2.6/drivers/infiniband/hw/mthca/mthca_cq.c
===================================================================
--- linux-2.6.orig/drivers/infiniband/hw/mthca/mthca_cq.c
+++ linux-2.6/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -779,7 +779,7 @@ int mthca_arbel_arm_cq(struct ib_cq *ibc
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,
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,
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);
Index: linux-2.6/drivers/infiniband/hw/mthca/mthca_dev.h
===================================================================
--- linux-2.6.orig/drivers/infiniband/hw/mthca/mthca_dev.h
+++ linux-2.6/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -96,7 +96,9 @@ enum {
MTHCA_EQ_CMD,
MTHCA_EQ_ASYNC,
MTHCA_EQ_COMP,
- MTHCA_NUM_EQ
+ MTHCA_NUM_EQ,
+ MTHCA_COMP_VECTORS = 2,
+ MTHCA_MAX_EQS = MTHCA_NUM_EQ + MTHCA_COMP_VECTORS - 1
};
enum {
@@ -230,7 +232,7 @@ struct mthca_eq_table {
void __iomem *clr_int;
u32 clr_mask;
u32 arm_mask;
- struct mthca_eq eq[MTHCA_NUM_EQ];
+ struct mthca_eq eq[MTHCA_MAX_EQS];
u64 icm_virt;
struct page *icm_page;
dma_addr_t icm_dma;
@@ -497,7 +499,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, in
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,
Index: linux-2.6/drivers/infiniband/hw/mthca/mthca_eq.c
===================================================================
--- linux-2.6.orig/drivers/infiniband/hw/mthca/mthca_eq.c
+++ linux-2.6/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)
@@ -579,8 +584,7 @@ static int mthca_create_eq(struct mthca_
dev->eq_table.arm_mask |= eq->eqn_mask;
- mthca_dbg(dev, "Allocated EQ %d with %d entries\n",
- eq->eqn, eq->nent);
+ mthca_dbg(dev, "Allocated EQ %d with %d entries\n", eq->eqn, eq->nent);
return err;
@@ -657,7 +661,7 @@ static void mthca_free_irqs(struct mthca
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 +828,37 @@ void mthca_unmap_eq_icm(struct mthca_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 +886,29 @@ int mthca_init_eq_table(struct mthca_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 + eqn : 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);
- if (err)
- goto err_out_cmd;
+ 0, eq_name(i), dev->eq_table.eq + i);
+ if (err) {
+ mthca_err(dev, "Failed to request IRQ %d for EQ %d (%d),"
+ " aborting.\n",
+ dev->eq_table.eq[i].msi_x_vector,
+ dev->eq_table.eq[i].eqn, i);
+ goto err_out_irq;
+ }
dev->eq_table.eq[i].have_irq = 1;
}
} else {
@@ -898,8 +917,11 @@ int mthca_init_eq_table(struct mthca_dev
mthca_arbel_interrupt :
mthca_tavor_interrupt,
IRQF_SHARED, DRV_NAME, dev);
- if (err)
- goto err_out_cmd;
+ if (err) {
+ mthca_err(dev, "Failed to request IRQ %d, aborting.\n",
+ dev->pdev->irq);
+ goto err_out_eq;
+ }
dev->eq_table.have_irq = 1;
}
@@ -921,7 +943,7 @@ int mthca_init_eq_table(struct mthca_dev
mthca_warn(dev, "MAP_EQ for cmd EQ %d returned status 0x%02x\n",
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)
if (mthca_is_memfree(dev))
arbel_eq_req_not(dev, dev->eq_table.eq[i].eqn_mask);
else
@@ -929,17 +951,13 @@ int mthca_init_eq_table(struct mthca_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 +977,7 @@ void mthca_cleanup_eq_table(struct mthca
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);
Index: linux-2.6/drivers/infiniband/hw/mthca/mthca_main.c
===================================================================
--- linux-2.6.orig/drivers/infiniband/hw/mthca/mthca_main.c
+++ linux-2.6/drivers/infiniband/hw/mthca/mthca_main.c
@@ -39,6 +39,7 @@
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <linux/cpumask.h>
#include "mthca_dev.h"
#include "mthca_config_reg.h"
@@ -976,24 +977,35 @@ static void mthca_release_regions(struct
static int mthca_enable_msi_x(struct mthca_dev *mdev)
{
- struct msix_entry entries[3];
- int err;
+ struct msix_entry entries[MTHCA_MAX_EQS];
+ int i, err, num;
- entries[0].entry = 0;
- entries[1].entry = 1;
- entries[2].entry = 2;
-
- err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries));
- if (err) {
- if (err > 0)
- mthca_info(mdev, "Only %d MSI-X vectors available, "
- "not using MSI-X\n", err);
- return err;
+ num = min(mdev->limits.num_eqs - mdev->limits.reserved_eqs, MTHCA_MAX_EQS);
+ num = min(num_possible_cpus(), num);
+
+ for (i = 0; i < num; ++i)
+ entries[i].entry = i;
+
+ for (;;) {
+ err = pci_enable_msix(mdev->pdev, entries, num);
+ if (!err)
+ break;
+ else if (err < 0)
+ return err;
+
+ if (err < MTHCA_NUM_EQ) {
+ mthca_info(mdev, "Only %d MSI-X vectors available. "
+ "Not using MSI-X\n", err);
+ pci_disable_msix(mdev->pdev);
+ return err;
+ }
+
+ num = 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 = num - MTHCA_NUM_EQ + 1;
+ for (i = 0; i < num; ++i)
+ mdev->eq_table.eq[i].msi_x_vector = entries[i].vector;
return 0;
}
@@ -1115,12 +1127,6 @@ static int __mthca_init_one(struct pci_d
goto err_free_dev;
}
- if (msi_x && !mthca_enable_msi_x(mdev))
- mdev->mthca_flags |= MTHCA_FLAG_MSI_X;
- if (msi && !(mdev->mthca_flags & MTHCA_FLAG_MSI_X) &&
- !pci_enable_msi(pdev))
- mdev->mthca_flags |= MTHCA_FLAG_MSI;
-
if (mthca_cmd_init(mdev)) {
mthca_err(mdev, "Failed to init command interface, aborting.\n");
goto err_free_dev;
@@ -1144,6 +1150,12 @@ static int __mthca_init_one(struct pci_d
mthca_warn(mdev, "If you have problems, try updating your HCA FW.\n");
}
+ if (msi_x && !mthca_enable_msi_x(mdev))
+ mdev->mthca_flags |= MTHCA_FLAG_MSI_X;
+ if (msi && !(mdev->mthca_flags & MTHCA_FLAG_MSI_X) &&
+ !pci_enable_msi(pdev))
+ mdev->mthca_flags |= MTHCA_FLAG_MSI;
+
err = mthca_setup_hca(mdev);
if (err)
goto err_close;
@@ -1180,17 +1192,17 @@ err_cleanup:
mthca_cleanup_uar_table(mdev);
err_close:
+ if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
+ pci_disable_msix(pdev);
+ if (mdev->mthca_flags & MTHCA_FLAG_MSI)
+ pci_disable_msi(pdev);
+
mthca_close_hca(mdev);
err_cmd:
mthca_cmd_cleanup(mdev);
err_free_dev:
- if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
- pci_disable_msix(pdev);
- if (mdev->mthca_flags & MTHCA_FLAG_MSI)
- pci_disable_msi(pdev);
-
ib_dealloc_device(&mdev->ib_dev);
err_free_res:
@@ -1231,14 +1243,15 @@ static void __mthca_remove_one(struct pc
iounmap(mdev->kar);
mthca_uar_free(mdev, &mdev->driver_uar);
mthca_cleanup_uar_table(mdev);
- mthca_close_hca(mdev);
- mthca_cmd_cleanup(mdev);
if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
pci_disable_msix(pdev);
if (mdev->mthca_flags & MTHCA_FLAG_MSI)
pci_disable_msi(pdev);
+ mthca_close_hca(mdev);
+ mthca_cmd_cleanup(mdev);
+
ib_dealloc_device(&mdev->ib_dev);
mthca_release_regions(pdev, mdev->mthca_flags &
MTHCA_FLAG_DDR_HIDDEN);
Index: linux-2.6/drivers/infiniband/hw/mthca/mthca_provider.c
===================================================================
--- linux-2.6.orig/drivers/infiniband/hw/mthca/mthca_provider.c
+++ linux-2.6/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -707,7 +707,7 @@ static struct ib_cq *mthca_create_cq(str
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);
Index: linux-2.6/drivers/infiniband/hw/mthca/mthca_provider.h
===================================================================
--- linux-2.6.orig/drivers/infiniband/hw/mthca/mthca_provider.h
+++ linux-2.6/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;
--
MST
More information about the general
mailing list