fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / infiniband / hw / mthca / mthca_cq.c
index 205854e..1159c8a 100644 (file)
  * $Id: mthca_cq.c 1369 2004-12-20 16:17:07Z roland $
  */
 
-#include <linux/init.h>
 #include <linux/hardirq.h>
 
+#include <asm/io.h>
+
 #include <rdma/ib_pack.h>
 
 #include "mthca_dev.h"
@@ -53,6 +54,10 @@ enum {
        MTHCA_CQ_ENTRY_SIZE = 0x20
 };
 
+enum {
+       MTHCA_ATOMIC_BYTE_LEN = 8
+};
+
 /*
  * Must be packed because start is 64 bits but only aligned to 32 bits.
  */
@@ -210,6 +215,11 @@ static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
                mthca_write64(doorbell,
                              dev->kar + MTHCA_CQ_DOORBELL,
                              MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+               /*
+                * Make sure doorbells don't leak out of CQ spinlock
+                * and reach the HCA out of order:
+                */
+               mmiowb();
        }
 }
 
@@ -540,8 +550,17 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
                entry->wr_id = srq->wrid[wqe_index];
                mthca_free_srq_wqe(srq, wqe);
        } else {
+               s32 wqe;
                wq = &(*cur_qp)->rq;
-               wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
+               wqe = be32_to_cpu(cqe->wqe);
+               wqe_index = wqe >> wq->wqe_shift;
+               /*
+                * WQE addr == base - 1 might be reported in receive completion
+                * with error instead of (rq size - 1) by Sinai FW 1.0.800 and
+                * Arbel FW 5.1.400.  This bug should be fixed in later FW revs.
+                */
+               if (unlikely(wqe_index < 0))
+                       wqe_index = wq->max - 1;
                entry->wr_id = (*cur_qp)->wrid[wqe_index];
        }
 
@@ -584,11 +603,11 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
                        break;
                case MTHCA_OPCODE_ATOMIC_CS:
                        entry->opcode    = IB_WC_COMP_SWAP;
-                       entry->byte_len  = be32_to_cpu(cqe->byte_cnt);
+                       entry->byte_len  = MTHCA_ATOMIC_BYTE_LEN;
                        break;
                case MTHCA_OPCODE_ATOMIC_FA:
                        entry->opcode    = IB_WC_FETCH_ADD;
-                       entry->byte_len  = be32_to_cpu(cqe->byte_cnt);
+                       entry->byte_len  = MTHCA_ATOMIC_BYTE_LEN;
                        break;
                case MTHCA_OPCODE_BIND_MW:
                        entry->opcode    = IB_WC_BIND_MW;
@@ -813,6 +832,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        spin_lock_init(&cq->lock);
        cq->refcount = 1;
        init_waitqueue_head(&cq->wait);
+       mutex_init(&cq->mutex);
 
        memset(cq_context, 0, sizeof *cq_context);
        cq_context->flags           = cpu_to_be32(MTHCA_CQ_STATUS_OK      |
@@ -953,7 +973,7 @@ void mthca_free_cq(struct mthca_dev *dev,
        mthca_free_mailbox(dev, mailbox);
 }
 
-int __devinit mthca_init_cq_table(struct mthca_dev *dev)
+int mthca_init_cq_table(struct mthca_dev *dev)
 {
        int err;