linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / infiniband / hw / mthca / mthca_srq.c
index a01f1a8..e7e153d 100644 (file)
@@ -35,8 +35,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 
-#include <asm/io.h>
-
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
 #include "mthca_memfree.h"
@@ -51,8 +49,7 @@ struct mthca_tavor_srq_context {
        __be32 state_pd;
        __be32 lkey;
        __be32 uar;
-       __be16 limit_watermark;
-       __be16 wqe_cnt;
+       __be32 wqe_cnt;
        u32    reserved[2];
 };
 
@@ -194,7 +191,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
 
        /* Sanity check SRQ size before proceeding */
        if (attr->max_wr  > dev->limits.max_srq_wqes ||
-           attr->max_sge > dev->limits.max_srq_sge)
+           attr->max_sge > dev->limits.max_sg)
                return -EINVAL;
 
        srq->max      = attr->max_wr;
@@ -207,10 +204,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
        ds = max(64UL,
                 roundup_pow_of_two(sizeof (struct mthca_next_seg) +
                                    srq->max_gs * sizeof (struct mthca_data_seg)));
-
-       if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz))
-               return -EINVAL;
-
        srq->wqe_shift = long_log2(ds);
 
        srq->srqn = mthca_alloc(&dev->srq_table.alloc);
@@ -243,9 +236,8 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
                goto err_out_mailbox;
 
        spin_lock_init(&srq->lock);
-       srq->refcount = 1;
+       atomic_set(&srq->refcount, 1);
        init_waitqueue_head(&srq->wait);
-       mutex_init(&srq->mutex);
 
        if (mthca_is_memfree(dev))
                mthca_arbel_init_srq_context(dev, pd, srq, mailbox->buf);
@@ -279,9 +271,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
        srq->first_free = 0;
        srq->last_free  = srq->max - 1;
 
-       attr->max_wr    = (mthca_is_memfree(dev)) ? srq->max - 1 : srq->max;
-       attr->max_sge   = srq->max_gs;
-
        return 0;
 
 err_out_free_srq:
@@ -311,17 +300,6 @@ err_out:
        return err;
 }
 
-static inline int get_srq_refcount(struct mthca_dev *dev, struct mthca_srq *srq)
-{
-       int c;
-
-       spin_lock_irq(&dev->srq_table.lock);
-       c = srq->refcount;
-       spin_unlock_irq(&dev->srq_table.lock);
-
-       return c;
-}
-
 void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
 {
        struct mthca_mailbox *mailbox;
@@ -343,10 +321,10 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
        spin_lock_irq(&dev->srq_table.lock);
        mthca_array_clear(&dev->srq_table.srq,
                          srq->srqn & (dev->limits.num_srqs - 1));
-       --srq->refcount;
        spin_unlock_irq(&dev->srq_table.lock);
 
-       wait_event(srq->wait, !get_srq_refcount(dev, srq));
+       atomic_dec(&srq->refcount);
+       wait_event(srq->wait, !atomic_read(&srq->refcount));
 
        if (!srq->ibsrq.uobject) {
                mthca_free_srq_buf(dev, srq);
@@ -361,7 +339,7 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
 
 int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                     enum ib_srq_attr_mask attr_mask)
-{
+{      
        struct mthca_dev *dev = to_mdev(ibsrq->device);
        struct mthca_srq *srq = to_msrq(ibsrq);
        int ret;
@@ -372,14 +350,7 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
                return -EINVAL;
 
        if (attr_mask & IB_SRQ_LIMIT) {
-               u32 max_wr = mthca_is_memfree(dev) ? srq->max - 1 : srq->max;
-               if (attr->srq_limit > max_wr)
-                       return -EINVAL;
-
-               mutex_lock(&srq->mutex);
                ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
-               mutex_unlock(&srq->mutex);
-
                if (ret)
                        return ret;
                if (status)
@@ -389,41 +360,6 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
        return 0;
 }
 
-int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
-{
-       struct mthca_dev *dev = to_mdev(ibsrq->device);
-       struct mthca_srq *srq = to_msrq(ibsrq);
-       struct mthca_mailbox *mailbox;
-       struct mthca_arbel_srq_context *arbel_ctx;
-       struct mthca_tavor_srq_context *tavor_ctx;
-       u8 status;
-       int err;
-
-       mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
-       if (IS_ERR(mailbox))
-               return PTR_ERR(mailbox);
-
-       err = mthca_QUERY_SRQ(dev, srq->srqn, mailbox, &status);
-       if (err)
-               goto out;
-
-       if (mthca_is_memfree(dev)) {
-               arbel_ctx = mailbox->buf;
-               srq_attr->srq_limit = be16_to_cpu(arbel_ctx->limit_watermark);
-       } else {
-               tavor_ctx = mailbox->buf;
-               srq_attr->srq_limit = be16_to_cpu(tavor_ctx->limit_watermark);
-       }
-
-       srq_attr->max_wr  = (mthca_is_memfree(dev)) ? srq->max - 1 : srq->max;
-       srq_attr->max_sge = srq->max_gs;
-
-out:
-       mthca_free_mailbox(dev, mailbox);
-
-       return err;
-}
-
 void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
                     enum ib_event_type event_type)
 {
@@ -433,7 +369,7 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
        spin_lock(&dev->srq_table.lock);
        srq = mthca_array_get(&dev->srq_table.srq, srqn & (dev->limits.num_srqs - 1));
        if (srq)
-               ++srq->refcount;
+               atomic_inc(&srq->refcount);
        spin_unlock(&dev->srq_table.lock);
 
        if (!srq) {
@@ -450,10 +386,8 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
        srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);
 
 out:
-       spin_lock(&dev->srq_table.lock);
-       if (!--srq->refcount)
+       if (atomic_dec_and_test(&srq->refcount))
                wake_up(&srq->wait);
-       spin_unlock(&dev->srq_table.lock);
 }
 
 /*
@@ -498,7 +432,26 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 
        first_ind = srq->first_free;
 
-       for (nreq = 0; wr; wr = wr->next) {
+       for (nreq = 0; wr; ++nreq, wr = wr->next) {
+               if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
+                       nreq = 0;
+
+                       doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
+                       doorbell[1] = cpu_to_be32(srq->srqn << 8);
+
+                       /*
+                        * Make sure that descriptors are written
+                        * before doorbell is rung.
+                        */
+                       wmb();
+
+                       mthca_write64(doorbell,
+                                     dev->kar + MTHCA_RECEIVE_DOORBELL,
+                                     MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+
+                       first_ind = srq->first_free;
+               }
+
                ind = srq->first_free;
 
                if (ind < 0) {
@@ -558,26 +511,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 
                srq->wrid[ind]  = wr->wr_id;
                srq->first_free = next_ind;
-
-               ++nreq;
-               if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
-                       nreq = 0;
-
-                       doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
-                       doorbell[1] = cpu_to_be32(srq->srqn << 8);
-
-                       /*
-                        * Make sure that descriptors are written
-                        * before doorbell is rung.
-                        */
-                       wmb();
-
-                       mthca_write64(doorbell,
-                                     dev->kar + MTHCA_RECEIVE_DOORBELL,
-                                     MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
-
-                       first_ind = srq->first_free;
-               }
        }
 
        if (likely(nreq)) {
@@ -595,12 +528,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
                              MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
        }
 
-       /*
-        * Make sure doorbells don't leak out of SRQ spinlock and
-        * reach the HCA out of order:
-        */
-       mmiowb();
-
        spin_unlock_irqrestore(&srq->lock, flags);
        return err;
 }
@@ -688,31 +615,6 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
        return err;
 }
 
-int mthca_max_srq_sge(struct mthca_dev *dev)
-{
-       if (mthca_is_memfree(dev))
-               return dev->limits.max_sg;
-
-       /*
-        * SRQ allocations are based on powers of 2 for Tavor,
-        * (although they only need to be multiples of 16 bytes).
-        *
-        * Therefore, we need to base the max number of sg entries on
-        * the largest power of 2 descriptor size that is <= to the
-        * actual max WQE descriptor size, rather than return the
-        * max_sg value given by the firmware (which is based on WQE
-        * sizes as multiples of 16, not powers of 2).
-        *
-        * If SRQ implementation is changed for Tavor to be based on
-        * multiples of 16, the calculation below can be deleted and
-        * the FW max_sg value returned.
-        */
-       return min_t(int, dev->limits.max_sg,
-                    ((1 << (fls(dev->limits.max_desc_sz) - 1)) -
-                     sizeof (struct mthca_next_seg)) /
-                    sizeof (struct mthca_data_seg));
-}
-
 int __devinit mthca_init_srq_table(struct mthca_dev *dev)
 {
        int err;
@@ -737,7 +639,7 @@ int __devinit mthca_init_srq_table(struct mthca_dev *dev)
        return err;
 }
 
-void mthca_cleanup_srq_table(struct mthca_dev *dev)
+void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev)
 {
        if (!(dev->mthca_flags & MTHCA_FLAG_SRQ))
                return;