[openib-general] PATCH] mthca - command interface - revised

Eli Cohen eli at mellanox.co.il
Wed Feb 15 05:31:33 PST 2006


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 <eli at mellanox.co.il>

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.




More information about the general mailing list