<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Roland Dreier &lt;roland@topspin.com&gt;

From: "Michael S. Tsirkin" &lt;mst@mellanox.co.il&gt;

Event queue handling performance improvements:
 - Only calculate EQ entry address once, and don't truncate the
   consumer index until we really need to.
 - Only read ECR once.  If a new event occurs while we're in the
   interrupt handler, we'll get another interrupt anyway, since we
   only clear events once.

Signed-off-by: Michael S. Tsirkin &lt;mst@mellanox.co.il&gt;
Signed-off-by: Roland Dreier &lt;roland@topspin.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@osdl.org&gt;
---

 25-akpm/drivers/infiniband/hw/mthca/mthca_eq.c       |   44 ++++++++++---------
 25-akpm/drivers/infiniband/hw/mthca/mthca_provider.h |    2 
 2 files changed, 25 insertions(+), 21 deletions(-)

diff -puN drivers/infiniband/hw/mthca/mthca_eq.c~infiniband-mthca-optimize-event-queue-handling drivers/infiniband/hw/mthca/mthca_eq.c
--- 25/drivers/infiniband/hw/mthca/mthca_eq.c~infiniband-mthca-optimize-event-queue-handling	2005-01-23 22:25:01.247412536 -0800
+++ 25-akpm/drivers/infiniband/hw/mthca/mthca_eq.c	2005-01-23 22:25:01.254411472 -0800
@@ -164,12 +164,12 @@ static inline u64 async_mask(struct mthc
 		MTHCA_ASYNC_EVENT_MASK;
 }
 
-static inline void set_eq_ci(struct mthca_dev *dev, int eqn, int ci)
+static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
 {
 	u32 doorbell[2];
 
-	doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eqn);
-	doorbell[1] = cpu_to_be32(ci);
+	doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eq-&gt;eqn);
+	doorbell[1] = cpu_to_be32(ci &amp; (eq-&gt;nent - 1));
 
 	mthca_write64(doorbell,
 		      dev-&gt;kar + MTHCA_EQ_DOORBELL,
@@ -200,21 +200,22 @@ static inline void disarm_cq(struct mthc
 		      MTHCA_GET_DOORBELL_LOCK(&amp;dev-&gt;doorbell_lock));
 }
 
-static inline struct mthca_eqe *get_eqe(struct mthca_eq *eq, int entry)
+static inline struct mthca_eqe *get_eqe(struct mthca_eq *eq, u32 entry)
 {
-	return eq-&gt;page_list[entry * MTHCA_EQ_ENTRY_SIZE / PAGE_SIZE].buf
-		+ (entry * MTHCA_EQ_ENTRY_SIZE) % PAGE_SIZE;
+	unsigned long off = (entry &amp; (eq-&gt;nent - 1)) * MTHCA_EQ_ENTRY_SIZE;
+	return eq-&gt;page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE;
 }
 
-static inline int next_eqe_sw(struct mthca_eq *eq)
+static inline struct mthca_eqe* next_eqe_sw(struct mthca_eq *eq)
 {
-	return !(MTHCA_EQ_ENTRY_OWNER_HW &amp;
-		 get_eqe(eq, eq-&gt;cons_index)-&gt;owner);
+	struct mthca_eqe* eqe;
+	eqe = get_eqe(eq, eq-&gt;cons_index);
+	return (MTHCA_EQ_ENTRY_OWNER_HW &amp; eqe-&gt;owner) ? NULL : eqe;
 }
 
-static inline void set_eqe_hw(struct mthca_eq *eq, int entry)
+static inline void set_eqe_hw(struct mthca_eqe *eqe)
 {
-	get_eqe(eq, entry)-&gt;owner =  MTHCA_EQ_ENTRY_OWNER_HW;
+	eqe-&gt;owner =  MTHCA_EQ_ENTRY_OWNER_HW;
 }
 
 static void port_change(struct mthca_dev *dev, int port, int active)
@@ -235,10 +236,10 @@ static void mthca_eq_int(struct mthca_de
 {
 	struct mthca_eqe *eqe;
 	int disarm_cqn;
+	int  eqes_found = 0;
 
-	while (next_eqe_sw(eq)) {
+	while ((eqe = next_eqe_sw(eq))) {
 		int set_ci = 0;
-		eqe = get_eqe(eq, eq-&gt;cons_index);
 
 		/*
 		 * Make sure we read EQ entry contents after we've
@@ -328,12 +329,13 @@ static void mthca_eq_int(struct mthca_de
 			break;
 		};
 
-		set_eqe_hw(eq, eq-&gt;cons_index);
-		eq-&gt;cons_index = (eq-&gt;cons_index + 1) &amp; (eq-&gt;nent - 1);
+		set_eqe_hw(eqe);
+		++eq-&gt;cons_index;
+		eqes_found = 1;
 
 		if (set_ci) {
 			wmb(); /* see comment below */
-			set_eq_ci(dev, eq-&gt;eqn, eq-&gt;cons_index);
+			set_eq_ci(dev, eq, eq-&gt;cons_index);
 			set_ci = 0;
 		}
 	}
@@ -347,8 +349,10 @@ static void mthca_eq_int(struct mthca_de
 	 * possibility of the HCA writing an entry and then
 	 * having set_eqe_hw() overwrite the owner field.
 	 */
-	wmb();
-	set_eq_ci(dev, eq-&gt;eqn, eq-&gt;cons_index);
+	if (likely(eqes_found)) {
+		wmb();
+		set_eq_ci(dev, eq, eq-&gt;cons_index);
+	}
 	eq_req_not(dev, eq-&gt;eqn);
 }
 
@@ -362,7 +366,7 @@ static irqreturn_t mthca_interrupt(int i
 	if (dev-&gt;eq_table.clr_mask)
 		writel(dev-&gt;eq_table.clr_mask, dev-&gt;eq_table.clr_int);
 
-	while ((ecr = readl(dev-&gt;hcr + MTHCA_ECR_OFFSET + 4)) != 0) {
+	if ((ecr = readl(dev-&gt;hcr + MTHCA_ECR_OFFSET + 4)) != 0) {
 		work = 1;
 
 		writel(ecr, dev-&gt;hcr + MTHCA_ECR_CLR_OFFSET + 4);
@@ -440,7 +444,7 @@ static int __devinit mthca_create_eq(str
 	}
 
 	for (i = 0; i &lt; nent; ++i)
-		set_eqe_hw(eq, i);
+		set_eqe_hw(get_eqe(eq, i));
 
 	eq-&gt;eqn = mthca_alloc(&amp;dev-&gt;eq_table.alloc);
 	if (eq-&gt;eqn == -1)
diff -puN drivers/infiniband/hw/mthca/mthca_provider.h~infiniband-mthca-optimize-event-queue-handling drivers/infiniband/hw/mthca/mthca_provider.h
--- 25/drivers/infiniband/hw/mthca/mthca_provider.h~infiniband-mthca-optimize-event-queue-handling	2005-01-23 22:25:01.249412232 -0800
+++ 25-akpm/drivers/infiniband/hw/mthca/mthca_provider.h	2005-01-23 22:25:01.253411624 -0800
@@ -66,11 +66,11 @@ struct mthca_eq {
 	struct mthca_dev      *dev;
 	int                    eqn;
 	u32                    ecr_mask;
+	u32                    cons_index;
 	u16                    msi_x_vector;
 	u16                    msi_x_entry;
 	int                    have_irq;
 	int                    nent;
-	int                    cons_index;
 	struct mthca_buf_list *page_list;
 	struct mthca_mr        mr;
 };
_
</pre></body></html>