[PATCH] IB uverbs: add mthca user CQ support
authorRoland Dreier <rolandd@cisco.com>
Fri, 8 Jul 2005 00:57:19 +0000 (17:57 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 8 Jul 2005 01:23:50 +0000 (18:23 -0700)
Add support for userspace completion queues (CQs) to mthca.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/infiniband/hw/mthca/mthca_cq.c
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_provider.h

index 766e9031ec4581bd05a4a727ee880b8689eeab3d..b5aea7b869f6c65bb9b820deb2f5566878126f16 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Cisco Systems, Inc. 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
@@ -742,6 +743,7 @@ err_out:
 }
 
 int mthca_init_cq(struct mthca_dev *dev, int nent,
+                 struct mthca_ucontext *ctx, u32 pdn,
                  struct mthca_cq *cq)
 {
        int size = nent * MTHCA_CQ_ENTRY_SIZE;
@@ -753,30 +755,33 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 
        might_sleep();
 
-       cq->ibcq.cqe = nent - 1;
+       cq->ibcq.cqe  = nent - 1;
+       cq->is_kernel = !ctx;
 
        cq->cqn = mthca_alloc(&dev->cq_table.alloc);
        if (cq->cqn == -1)
                return -ENOMEM;
 
        if (mthca_is_memfree(dev)) {
-               cq->arm_sn = 1;
-
                err = mthca_table_get(dev, dev->cq_table.table, cq->cqn);
                if (err)
                        goto err_out;
 
-               err = -ENOMEM;
+               if (cq->is_kernel) {
+                       cq->arm_sn = 1;
+
+                       err = -ENOMEM;
 
-               cq->set_ci_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_SET_CI,
-                                                    cq->cqn, &cq->set_ci_db);
-               if (cq->set_ci_db_index < 0)
-                       goto err_out_icm;
+                       cq->set_ci_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_SET_CI,
+                                                            cq->cqn, &cq->set_ci_db);
+                       if (cq->set_ci_db_index < 0)
+                               goto err_out_icm;
 
-               cq->arm_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_ARM,
-                                                 cq->cqn, &cq->arm_db);
-               if (cq->arm_db_index < 0)
-                       goto err_out_ci;
+                       cq->arm_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_ARM,
+                                                         cq->cqn, &cq->arm_db);
+                       if (cq->arm_db_index < 0)
+                               goto err_out_ci;
+               }
        }
 
        mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -785,12 +790,14 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 
        cq_context = mailbox->buf;
 
-       err = mthca_alloc_cq_buf(dev, size, cq);
-       if (err)
-               goto err_out_mailbox;
+       if (cq->is_kernel) {
+               err = mthca_alloc_cq_buf(dev, size, cq);
+               if (err)
+                       goto err_out_mailbox;
 
-       for (i = 0; i < nent; ++i)
-               set_cqe_hw(get_cqe(cq, i));
+               for (i = 0; i < nent; ++i)
+                       set_cqe_hw(get_cqe(cq, i));
+       }
 
        spin_lock_init(&cq->lock);
        atomic_set(&cq->refcount, 1);
@@ -801,11 +808,14 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
                                                  MTHCA_CQ_STATE_DISARMED |
                                                  MTHCA_CQ_FLAG_TR);
        cq_context->start           = cpu_to_be64(0);
-       cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24 |
-                                                 dev->driver_uar.index);
+       cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
+       if (ctx)
+               cq_context->logsize_usrpage |= cpu_to_be32(ctx->uar.index);
+       else
+               cq_context->logsize_usrpage |= cpu_to_be32(dev->driver_uar.index);
        cq_context->error_eqn       = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
        cq_context->comp_eqn        = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn);
-       cq_context->pd              = cpu_to_be32(dev->driver_pd.pd_num);
+       cq_context->pd              = cpu_to_be32(pdn);
        cq_context->lkey            = cpu_to_be32(cq->mr.ibmr.lkey);
        cq_context->cqn             = cpu_to_be32(cq->cqn);
 
@@ -843,18 +853,20 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        return 0;
 
 err_out_free_mr:
-       mthca_free_mr(dev, &cq->mr);
-       mthca_free_cq_buf(dev, cq);
+       if (cq->is_kernel) {
+               mthca_free_mr(dev, &cq->mr);
+               mthca_free_cq_buf(dev, cq);
+       }
 
 err_out_mailbox:
        mthca_free_mailbox(dev, mailbox);
 
 err_out_arm:
-       if (mthca_is_memfree(dev))
+       if (cq->is_kernel && mthca_is_memfree(dev))
                mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
 
 err_out_ci:
-       if (mthca_is_memfree(dev))
+       if (cq->is_kernel && mthca_is_memfree(dev))
                mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
 
 err_out_icm:
@@ -892,7 +904,8 @@ void mthca_free_cq(struct mthca_dev *dev,
                int j;
 
                printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
-                      cq->cqn, cq->cons_index, !!next_cqe_sw(cq));
+                      cq->cqn, cq->cons_index,
+                      cq->is_kernel ? !!next_cqe_sw(cq) : 0);
                for (j = 0; j < 16; ++j)
                        printk(KERN_ERR "[%2x] %08x\n", j * 4, be32_to_cpu(ctx[j]));
        }
@@ -910,12 +923,13 @@ void mthca_free_cq(struct mthca_dev *dev,
        atomic_dec(&cq->refcount);
        wait_event(cq->wait, !atomic_read(&cq->refcount));
 
-       mthca_free_mr(dev, &cq->mr);
-       mthca_free_cq_buf(dev, cq);
-
-       if (mthca_is_memfree(dev)) {
-               mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM,    cq->arm_db_index);
-               mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
+       if (cq->is_kernel) {
+               mthca_free_mr(dev, &cq->mr);
+               mthca_free_cq_buf(dev, cq);
+               if (mthca_is_memfree(dev)) {
+                       mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM,    cq->arm_db_index);
+                       mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
+               }
        }
 
        mthca_table_put(dev, dev->cq_table.table, cq->cqn);
index 3801facf6f1f00c3ab7781e2e965fd67e5418de1..751f69479a785cc20d7f0c32e3ae2c061a12caa6 100644 (file)
@@ -414,6 +414,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
 int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
 int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
 int mthca_init_cq(struct mthca_dev *dev, int nent,
+                 struct mthca_ucontext *ctx, u32 pdn,
                  struct mthca_cq *cq);
 void mthca_free_cq(struct mthca_dev *dev,
                   struct mthca_cq *cq);
index bbdfcbe6bade6e461e1e5198af18638431aed32f..9feb7618ba412f3a22bac19e12f8c4053d78ca3b 100644 (file)
@@ -497,28 +497,85 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
                                     struct ib_ucontext *context,
                                     struct ib_udata *udata)
 {
+       struct mthca_create_cq ucmd;
        struct mthca_cq *cq;
        int nent;
        int err;
 
+       if (context) {
+               if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+                       return ERR_PTR(-EFAULT);
+
+               err = mthca_map_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
+                                       to_mucontext(context)->db_tab,
+                                       ucmd.set_db_index, ucmd.set_db_page);
+               if (err)
+                       return ERR_PTR(err);
+
+               err = mthca_map_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
+                                       to_mucontext(context)->db_tab,
+                                       ucmd.arm_db_index, ucmd.arm_db_page);
+               if (err)
+                       goto err_unmap_set;
+       }
+
        cq = kmalloc(sizeof *cq, GFP_KERNEL);
-       if (!cq)
-               return ERR_PTR(-ENOMEM);
+       if (!cq) {
+               err = -ENOMEM;
+               goto err_unmap_arm;
+       }
+
+       if (context) {
+               cq->mr.ibmr.lkey    = ucmd.lkey;
+               cq->set_ci_db_index = ucmd.set_db_index;
+               cq->arm_db_index    = ucmd.arm_db_index;
+       }
 
        for (nent = 1; nent <= entries; nent <<= 1)
                ; /* nothing */
 
-       err = mthca_init_cq(to_mdev(ibdev), nent, cq);
-       if (err) {
-               kfree(cq);
-               cq = ERR_PTR(err);
+       err = mthca_init_cq(to_mdev(ibdev), nent,
+                           context ? to_mucontext(context) : NULL,
+                           context ? ucmd.pdn : to_mdev(ibdev)->driver_pd.pd_num,
+                           cq);
+       if (err)
+               goto err_free;
+
+       if (context && ib_copy_to_udata(udata, &cq->cqn, sizeof (__u32))) {
+               mthca_free_cq(to_mdev(ibdev), cq);
+               goto err_free;
        }
 
        return &cq->ibcq;
+
+err_free:
+       kfree(cq);
+
+err_unmap_arm:
+       if (context)
+               mthca_unmap_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
+                                   to_mucontext(context)->db_tab, ucmd.arm_db_index);
+
+err_unmap_set:
+       if (context)
+               mthca_unmap_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
+                                   to_mucontext(context)->db_tab, ucmd.set_db_index);
+
+       return ERR_PTR(err);
 }
 
 static int mthca_destroy_cq(struct ib_cq *cq)
 {
+       if (cq->uobject) {
+               mthca_unmap_user_db(to_mdev(cq->device),
+                                   &to_mucontext(cq->uobject->context)->uar,
+                                   to_mucontext(cq->uobject->context)->db_tab,
+                                   to_mcq(cq)->arm_db_index);
+               mthca_unmap_user_db(to_mdev(cq->device),
+                                   &to_mucontext(cq->uobject->context)->uar,
+                                   to_mucontext(cq->uobject->context)->db_tab,
+                                   to_mcq(cq)->set_ci_db_index);
+       }
        mthca_free_cq(to_mdev(cq->device), to_mcq(cq));
        kfree(cq);
 
index 579d10cd142677bf6e25a4a3437e9409fcba3f2d..1d032791cc8b67a3ad217dc3a235ead72dab1f6b 100644 (file)
@@ -177,6 +177,7 @@ struct mthca_cq {
        int                    cqn;
        u32                    cons_index;
        int                    is_direct;
+       int                    is_kernel;
 
        /* Next fields are Arbel only */
        int                    set_ci_db_index;