Roland,
this patch is modified according to your comments. It also adds a kernel
configuration option which selects whether to use posting commands
through doorbells. The option is off by default.

Signed-off-by: Eli Cohen <[EMAIL PROTECTED]>

Index: linux-2.6.14.2/drivers/infiniband/hw/mthca/mthca_dev.h
===================================================================
--- linux-2.6.14.2.orig/drivers/infiniband/hw/mthca/mthca_dev.h
+++ linux-2.6.14.2/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -117,9 +117,18 @@ enum {
        MTHCA_OPCODE_INVALID        = 0xff
 };
 
+enum {
+       MTHCA_CMD_USE_EVENTS         = (1 << 0),
+       MTHCA_CMD_CAN_POST_DOORBELLS = (1 << 1),
+       MTHCA_CMD_POST_DOORBELLS     = (1 << 2)
+};
+
+enum {
+       MTHCA_CMD_NUM_DBELL_DWORDS = 8
+};
+
 struct mthca_cmd {
        struct pci_pool          *pool;
-       int                       use_events;
        struct mutex              hcr_mutex;
        struct semaphore          poll_sem;
        struct semaphore          event_sem;
@@ -128,6 +137,10 @@ struct mthca_cmd {
        int                       free_head;
        struct mthca_cmd_context *context;
        u16                       token_mask;
+       u32                       flags;
+       void __iomem             *dbell_map;
+       u64                       dbell_base;
+       u16                       dbell_offsets[MTHCA_CMD_NUM_DBELL_DWORDS];
 };
 
 struct mthca_limits {
Index: linux-2.6.14.2/drivers/infiniband/hw/mthca/mthca_cmd.c
===================================================================
--- linux-2.6.14.2.orig/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ linux-2.6.14.2/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -188,19 +188,57 @@ static inline int go_bit(struct mthca_de
                swab32(1 << HCR_GO_BIT);
 }
 
-static int mthca_cmd_post(struct mthca_dev *dev,
-                         u64 in_param,
-                         u64 out_param,
-                         u32 in_modifier,
-                         u8 op_modifier,
-                         u16 op,
-                         u16 token,
-                         int event)
+
+static void mthca_cmd_post_dbell(struct mthca_dev *dev,
+                                u64 in_param,
+                                u64 out_param,
+                                u32 in_modifier,
+                                u8 op_modifier,
+                                u16 op,
+                                u16 token)
 {
-       int err = 0;
+       void __iomem *ptr = dev->cmd.dbell_map;
+       u16 *offs = dev->cmd.dbell_offsets;
+
+       __raw_writel((__force u32) cpu_to_be32(in_param >> 32),
+                    ptr + offs[0]);
+       wmb();
+       __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful),
+                    ptr + offs[1]);
+       wmb();
+       __raw_writel((__force u32) cpu_to_be32(in_modifier),
+                    ptr + offs[2]);
+       wmb();
+       __raw_writel((__force u32) cpu_to_be32(out_param >> 32),
+                    ptr + offs[3]);
+       wmb();
+       __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful),
+                    ptr + offs[4]);
+       wmb();
+       __raw_writel((__force u32) cpu_to_be32(token << 16),
+                    ptr + offs[5]);
+       wmb();
+       __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) |
+                                              (1 << HCA_E_BIT) |
+                                              (op_modifier << HCR_OPMOD_SHIFT) 
|
+                                               op),
+                    ptr + offs[6]);
+       wmb();
+       __raw_writel((__force u32) 0,
+                    ptr + offs[7]);
+       wmb();
+}
 
-       mutex_lock(&dev->cmd.hcr_mutex);
 
+static int mthca_cmd_post_hcr(struct mthca_dev *dev,
+                             u64 in_param,
+                             u64 out_param,
+                             u32 in_modifier,
+                             u8 op_modifier,
+                             u16 op,
+                             u16 token,
+                             int event)
+{
        if (event) {
                unsigned long end = jiffies + GO_BIT_TIMEOUT;
 
@@ -210,10 +248,8 @@ static int mthca_cmd_post(struct mthca_d
                }
        }
 
-       if (go_bit(dev)) {
-               err = -EAGAIN;
-               goto out;
-       }
+       if (go_bit(dev))
+               return -EAGAIN;
 
        /*
         * We use writel (instead of something like memcpy_toio)
@@ -236,7 +272,29 @@ static int mthca_cmd_post(struct mthca_d
                                               (op_modifier << HCR_OPMOD_SHIFT) 
|
                                               op),                       
dev->hcr + 6 * 4);
 
-out:
+       return 0;
+}
+
+static int mthca_cmd_post(struct mthca_dev *dev,
+                         u64 in_param,
+                         u64 out_param,
+                         u32 in_modifier,
+                         u8 op_modifier,
+                         u16 op,
+                         u16 token,
+                         int event)
+{
+       int err = 0;
+
+       mutex_lock(&dev->cmd.hcr_mutex);
+
+       if (dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS && event)
+               mthca_cmd_post_dbell(dev, in_param, out_param, in_modifier,
+                                          op_modifier, op, token);
+       else
+               err = mthca_cmd_post_hcr(dev, in_param, out_param, in_modifier,
+                                        op_modifier, op, token, event);
+
        mutex_unlock(&dev->cmd.hcr_mutex);
        return err;
 }
@@ -386,7 +444,7 @@ static int mthca_cmd_box(struct mthca_de
                         unsigned long timeout,
                         u8 *status)
 {
-       if (dev->cmd.use_events)
+       if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
                return mthca_cmd_wait(dev, in_param, &out_param, 0,
                                      in_modifier, op_modifier, op,
                                      timeout, status);
@@ -423,7 +481,7 @@ static int mthca_cmd_imm(struct mthca_de
                         unsigned long timeout,
                         u8 *status)
 {
-       if (dev->cmd.use_events)
+       if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
                return mthca_cmd_wait(dev, in_param, out_param, 1,
                                      in_modifier, op_modifier, op,
                                      timeout, status);
@@ -437,7 +495,7 @@ int mthca_cmd_init(struct mthca_dev *dev
 {
        mutex_init(&dev->cmd.hcr_mutex);
        sema_init(&dev->cmd.poll_sem, 1);
-       dev->cmd.use_events = 0;
+       dev->cmd.flags &= ~MTHCA_CMD_USE_EVENTS;
 
        dev->hcr = ioremap(pci_resource_start(dev->pdev, 0) + MTHCA_HCR_BASE,
                           MTHCA_HCR_SIZE);
@@ -461,6 +519,8 @@ void mthca_cmd_cleanup(struct mthca_dev 
 {
        pci_pool_destroy(dev->cmd.pool);
        iounmap(dev->hcr);
+       if (dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS)
+               iounmap(dev->cmd.dbell_map);
 }
 
 /*
@@ -498,12 +558,49 @@ int mthca_cmd_use_events(struct mthca_de
                ; /* nothing */
        --dev->cmd.token_mask;
 
-       dev->cmd.use_events = 1;
+       dev->cmd.flags |= MTHCA_CMD_USE_EVENTS;
+
+
        down(&dev->cmd.poll_sem);
 
        return 0;
 }
 
+
+#ifdef CONFIG_INFINIBAND_MTHCA_CMD_UAR
+/*
+ *  attempt to post commands through doorbells
+ */
+int mthca_use_cmd_doorbells(struct mthca_dev *dev)
+{
+       int i;
+       u16 max_off = 0;
+       unsigned long pg1, pg2;
+
+       if (!dev->cmd.flags & MTHCA_CMD_CAN_POST_DOORBELLS)
+               return -ENODEV;
+
+       for (i=0; i<8; ++i)
+               if (dev->cmd.dbell_offsets[i] > max_off)
+                       max_off = dev->cmd.dbell_offsets[i];
+
+       pg1 = dev->cmd.dbell_base & PAGE_MASK;
+       pg2 = (dev->cmd.dbell_base + max_off) & PAGE_MASK;
+
+       if (pg1 != pg2)
+               return -ENOMEM;
+
+       dev->cmd.dbell_map = ioremap(dev->cmd.dbell_base, max_off + 
sizeof(u32));
+       if (!dev->cmd.dbell_map)
+               return -ENOMEM;
+
+       dev->cmd.flags |= MTHCA_CMD_POST_DOORBELLS;
+       mthca_dbg(dev, "posting commands through doorbell\n");
+
+       return 0;
+}
+#endif
+
 /*
  * Switch back to polling (used when shutting down the device)
  */
@@ -511,7 +608,7 @@ void mthca_cmd_use_polling(struct mthca_
 {
        int i;
 
-       dev->cmd.use_events = 0;
+       dev->cmd.flags &= ~MTHCA_CMD_USE_EVENTS;
 
        for (i = 0; i < dev->cmd.max_cmds; ++i)
                down(&dev->cmd.event_sem);
@@ -665,8 +762,10 @@ int mthca_QUERY_FW(struct mthca_dev *dev
 {
        struct mthca_mailbox *mailbox;
        u32 *outbox;
+       u32 tmp;
        int err = 0;
        u8 lg;
+       int i;
 
 #define QUERY_FW_OUT_SIZE             0x100
 #define QUERY_FW_VER_OFFSET            0x00
@@ -674,6 +773,11 @@ int mthca_QUERY_FW(struct mthca_dev *dev
 #define QUERY_FW_ERR_START_OFFSET      0x30
 #define QUERY_FW_ERR_SIZE_OFFSET       0x38
 
+
+#define QUERY_FW_CMD_DB_EN_OFFSET      0x10
+#define QUERY_FW_CMD_DB_OFFSET         0x50
+#define QUERY_FW_CMD_DB_BASE           0x60
+
 #define QUERY_FW_START_OFFSET          0x20
 #define QUERY_FW_END_OFFSET            0x28
 
@@ -706,6 +810,15 @@ int mthca_QUERY_FW(struct mthca_dev *dev
        dev->cmd.max_cmds = 1 << lg;
        MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET);
        MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
+       MTHCA_GET(tmp, outbox, QUERY_FW_CMD_DB_EN_OFFSET);
+       if (tmp & 0x1) {
+               mthca_dbg(dev, "FW supports commands through doorbells\n");
+               dev->cmd.flags |= MTHCA_CMD_CAN_POST_DOORBELLS;
+       }
+       MTHCA_GET(dev->cmd.dbell_base, outbox, QUERY_FW_CMD_DB_BASE);
+       for (i=0; i<MTHCA_CMD_NUM_DBELL_DWORDS; ++i)
+               MTHCA_GET(dev->cmd.dbell_offsets[i], outbox,
+                       QUERY_FW_CMD_DB_OFFSET + (i << 1));
 
        mthca_dbg(dev, "FW version %012llx, max commands %d\n",
                  (unsigned long long) dev->fw_ver, dev->cmd.max_cmds);
@@ -1659,7 +1772,6 @@ int mthca_MODIFY_QP(struct mthca_dev *de
                if (0) {
                        int i;
                        mthca_dbg(dev, "Dumping QP context:\n");
-                       printk("  opt param mask: %08x\n", 
be32_to_cpup(mailbox->buf));
                        for (i = 0; i < 0x100 / 4; ++i) {
                                if (i % 8 == 0)
                                        printk("  [%02x] ", i * 4);
Index: linux-2.6.14.2/drivers/infiniband/hw/mthca/mthca_cmd.h
===================================================================
--- linux-2.6.14.2.orig/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ linux-2.6.14.2/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -244,6 +244,14 @@ struct mthca_set_ib_param {
 int mthca_cmd_init(struct mthca_dev *dev);
 void mthca_cmd_cleanup(struct mthca_dev *dev);
 int mthca_cmd_use_events(struct mthca_dev *dev);
+#if defined(CONFIG_INFINIBAND_MTHCA_CMD_UAR)
+int mthca_use_cmd_doorbells(struct mthca_dev *dev);
+#else
+static inline int mthca_use_cmd_doorbells(struct mthca_dev *dev)
+{
+       return -ENOSYS;
+}
+#endif
 void mthca_cmd_use_polling(struct mthca_dev *dev);
 void mthca_cmd_event(struct mthca_dev *dev, u16 token,
                     u8  status, u64 out_param);
Index: linux-2.6.14.2/drivers/infiniband/hw/mthca/mthca_main.c
===================================================================
--- linux-2.6.14.2.orig/drivers/infiniband/hw/mthca/mthca_main.c
+++ linux-2.6.14.2/drivers/infiniband/hw/mthca/mthca_main.c
@@ -754,6 +754,11 @@ static int __devinit mthca_setup_hca(str
                goto err_eq_table_free;
        }
 
+       err = mthca_use_cmd_doorbells(dev);
+       if (err)
+               mthca_dbg(dev, "not using commands through doorbells\n");
+
+
        err = mthca_NOP(dev, &status);
        if (err || status) {
                mthca_err(dev, "NOP command failed to generate interrupt (IRQ 
%d), aborting.\n",
Index: linux-2.6.14.2/drivers/infiniband/hw/mthca/Kconfig
===================================================================
--- linux-2.6.14.2.orig/drivers/infiniband/hw/mthca/Kconfig
+++ linux-2.6.14.2/drivers/infiniband/hw/mthca/Kconfig
@@ -14,3 +14,12 @@ config INFINIBAND_MTHCA_DEBUG
          This option causes the mthca driver produce a bunch of debug
          messages.  Select this is you are developing the driver or
          trying to diagnose a problem.
+
+config INFINIBAND_MTHCA_CMD_UAR
+       bool "Post commands through uar0"
+       depends on INFINIBAND_MTHCA
+       default n
+       ---help---
+         This option will check if the device supports issuing commands
+         by writing to the UAR area. This can result in better CPU
+         utilization.

_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to