
From: Roland Dreier <roland@topspin.com>

Add an rmb() between checking the ownership bit of an event queue entry and
reading the contents of the EQE.  Without this barrier, the CPU could read
stale contents of the EQE before HW writes the EQE but have the read of the
ownership bit reordered until after HW finishes writing, which leads to the
driver processing an incorrect event.  This was actually observed to happen
when multiple completion queues are in heavy use on an IBM JS20 PowerPC 970
system.

Also explain the existing rmb() in completion queue poll (there for the same
reason) and slightly improve debugging output.

Signed-off-by: Roland Dreier <roland@topspin.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/infiniband/hw/mthca/mthca_cq.c |    9 +++++++--
 25-akpm/drivers/infiniband/hw/mthca/mthca_eq.c |    8 +++++++-
 2 files changed, 14 insertions(+), 3 deletions(-)

diff -puN drivers/infiniband/hw/mthca/mthca_cq.c~infiniband-mthca-add-needed-rmb-in-event-queue-poll drivers/infiniband/hw/mthca/mthca_cq.c
--- 25/drivers/infiniband/hw/mthca/mthca_cq.c~infiniband-mthca-add-needed-rmb-in-event-queue-poll	Wed Jan 12 16:31:40 2005
+++ 25-akpm/drivers/infiniband/hw/mthca/mthca_cq.c	Wed Jan 12 16:31:40 2005
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -391,6 +391,10 @@ static inline int mthca_poll_one(struct 
 	if (!next_cqe_sw(cq))
 		return -EAGAIN;
 
+	/*
+	 * Make sure we read CQ entry contents after we've checked the
+	 * ownership bit.
+	 */
 	rmb();
 
 	cqe = get_cqe(cq, cq->cons_index);
@@ -768,7 +772,8 @@ void mthca_free_cq(struct mthca_dev *dev
 		u32 *ctx = MAILBOX_ALIGN(mailbox);
 		int j;
 
-		printk(KERN_ERR "context for CQN %x\n", cq->cqn);
+		printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
+		       cq->cqn, cq->cons_index, next_cqe_sw(cq));
 		for (j = 0; j < 16; ++j)
 			printk(KERN_ERR "[%2x] %08x\n", j * 4, be32_to_cpu(ctx[j]));
 	}
diff -puN drivers/infiniband/hw/mthca/mthca_eq.c~infiniband-mthca-add-needed-rmb-in-event-queue-poll drivers/infiniband/hw/mthca/mthca_eq.c
--- 25/drivers/infiniband/hw/mthca/mthca_eq.c~infiniband-mthca-add-needed-rmb-in-event-queue-poll	Wed Jan 12 16:31:40 2005
+++ 25-akpm/drivers/infiniband/hw/mthca/mthca_eq.c	Wed Jan 12 16:31:40 2005
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -240,6 +240,12 @@ static void mthca_eq_int(struct mthca_de
 		int set_ci = 0;
 		eqe = get_eqe(eq, eq->cons_index);
 
+		/*
+		 * Make sure we read EQ entry contents after we've
+		 * checked the ownership bit.
+		 */
+		rmb();
+
 		switch (eqe->type) {
 		case MTHCA_EVENT_TYPE_COMP:
 			disarm_cqn = be32_to_cpu(eqe->event.comp.cqn) & 0xffffff;
_
