aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2005-07-07 20:57:19 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-07 21:23:50 -0400
commit74c2174e7be52f9d2d210511bf3b490f4b41574c (patch)
treeaa7288790ba6329871c82904d46afe26bca24313
parent24d4281be0598d2d4ab9a2ffb1b78f5af0ffaddf (diff)
[PATCH] IB uverbs: add mthca user CQ support
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>
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c76
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c69
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.h1
4 files changed, 110 insertions, 37 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 766e9031ec45..b5aea7b869f6 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 2 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
3 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 3 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
4 * Copyright (c) 2005 Cisco Systems, Inc. All rights reserved.
4 * 5 *
5 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
@@ -742,6 +743,7 @@ err_out:
742} 743}
743 744
744int mthca_init_cq(struct mthca_dev *dev, int nent, 745int mthca_init_cq(struct mthca_dev *dev, int nent,
746 struct mthca_ucontext *ctx, u32 pdn,
745 struct mthca_cq *cq) 747 struct mthca_cq *cq)
746{ 748{
747 int size = nent * MTHCA_CQ_ENTRY_SIZE; 749 int size = nent * MTHCA_CQ_ENTRY_SIZE;
@@ -753,30 +755,33 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
753 755
754 might_sleep(); 756 might_sleep();
755 757
756 cq->ibcq.cqe = nent - 1; 758 cq->ibcq.cqe = nent - 1;
759 cq->is_kernel = !ctx;
757 760
758 cq->cqn = mthca_alloc(&dev->cq_table.alloc); 761 cq->cqn = mthca_alloc(&dev->cq_table.alloc);
759 if (cq->cqn == -1) 762 if (cq->cqn == -1)
760 return -ENOMEM; 763 return -ENOMEM;
761 764
762 if (mthca_is_memfree(dev)) { 765 if (mthca_is_memfree(dev)) {
763 cq->arm_sn = 1;
764
765 err = mthca_table_get(dev, dev->cq_table.table, cq->cqn); 766 err = mthca_table_get(dev, dev->cq_table.table, cq->cqn);
766 if (err) 767 if (err)
767 goto err_out; 768 goto err_out;
768 769
769 err = -ENOMEM; 770 if (cq->is_kernel) {
771 cq->arm_sn = 1;
772
773 err = -ENOMEM;
770 774
771 cq->set_ci_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, 775 cq->set_ci_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_SET_CI,
772 cq->cqn, &cq->set_ci_db); 776 cq->cqn, &cq->set_ci_db);
773 if (cq->set_ci_db_index < 0) 777 if (cq->set_ci_db_index < 0)
774 goto err_out_icm; 778 goto err_out_icm;
775 779
776 cq->arm_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_ARM, 780 cq->arm_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_ARM,
777 cq->cqn, &cq->arm_db); 781 cq->cqn, &cq->arm_db);
778 if (cq->arm_db_index < 0) 782 if (cq->arm_db_index < 0)
779 goto err_out_ci; 783 goto err_out_ci;
784 }
780 } 785 }
781 786
782 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 787 mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -785,12 +790,14 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
785 790
786 cq_context = mailbox->buf; 791 cq_context = mailbox->buf;
787 792
788 err = mthca_alloc_cq_buf(dev, size, cq); 793 if (cq->is_kernel) {
789 if (err) 794 err = mthca_alloc_cq_buf(dev, size, cq);
790 goto err_out_mailbox; 795 if (err)
796 goto err_out_mailbox;
791 797
792 for (i = 0; i < nent; ++i) 798 for (i = 0; i < nent; ++i)
793 set_cqe_hw(get_cqe(cq, i)); 799 set_cqe_hw(get_cqe(cq, i));
800 }
794 801
795 spin_lock_init(&cq->lock); 802 spin_lock_init(&cq->lock);
796 atomic_set(&cq->refcount, 1); 803 atomic_set(&cq->refcount, 1);
@@ -801,11 +808,14 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
801 MTHCA_CQ_STATE_DISARMED | 808 MTHCA_CQ_STATE_DISARMED |
802 MTHCA_CQ_FLAG_TR); 809 MTHCA_CQ_FLAG_TR);
803 cq_context->start = cpu_to_be64(0); 810 cq_context->start = cpu_to_be64(0);
804 cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24 | 811 cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
805 dev->driver_uar.index); 812 if (ctx)
813 cq_context->logsize_usrpage |= cpu_to_be32(ctx->uar.index);
814 else
815 cq_context->logsize_usrpage |= cpu_to_be32(dev->driver_uar.index);
806 cq_context->error_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn); 816 cq_context->error_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
807 cq_context->comp_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn); 817 cq_context->comp_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn);
808 cq_context->pd = cpu_to_be32(dev->driver_pd.pd_num); 818 cq_context->pd = cpu_to_be32(pdn);
809 cq_context->lkey = cpu_to_be32(cq->mr.ibmr.lkey); 819 cq_context->lkey = cpu_to_be32(cq->mr.ibmr.lkey);
810 cq_context->cqn = cpu_to_be32(cq->cqn); 820 cq_context->cqn = cpu_to_be32(cq->cqn);
811 821
@@ -843,18 +853,20 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
843 return 0; 853 return 0;
844 854
845err_out_free_mr: 855err_out_free_mr:
846 mthca_free_mr(dev, &cq->mr); 856 if (cq->is_kernel) {
847 mthca_free_cq_buf(dev, cq); 857 mthca_free_mr(dev, &cq->mr);
858 mthca_free_cq_buf(dev, cq);
859 }
848 860
849err_out_mailbox: 861err_out_mailbox:
850 mthca_free_mailbox(dev, mailbox); 862 mthca_free_mailbox(dev, mailbox);
851 863
852err_out_arm: 864err_out_arm:
853 if (mthca_is_memfree(dev)) 865 if (cq->is_kernel && mthca_is_memfree(dev))
854 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index); 866 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
855 867
856err_out_ci: 868err_out_ci:
857 if (mthca_is_memfree(dev)) 869 if (cq->is_kernel && mthca_is_memfree(dev))
858 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index); 870 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
859 871
860err_out_icm: 872err_out_icm:
@@ -892,7 +904,8 @@ void mthca_free_cq(struct mthca_dev *dev,
892 int j; 904 int j;
893 905
894 printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n", 906 printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
895 cq->cqn, cq->cons_index, !!next_cqe_sw(cq)); 907 cq->cqn, cq->cons_index,
908 cq->is_kernel ? !!next_cqe_sw(cq) : 0);
896 for (j = 0; j < 16; ++j) 909 for (j = 0; j < 16; ++j)
897 printk(KERN_ERR "[%2x] %08x\n", j * 4, be32_to_cpu(ctx[j])); 910 printk(KERN_ERR "[%2x] %08x\n", j * 4, be32_to_cpu(ctx[j]));
898 } 911 }
@@ -910,12 +923,13 @@ void mthca_free_cq(struct mthca_dev *dev,
910 atomic_dec(&cq->refcount); 923 atomic_dec(&cq->refcount);
911 wait_event(cq->wait, !atomic_read(&cq->refcount)); 924 wait_event(cq->wait, !atomic_read(&cq->refcount));
912 925
913 mthca_free_mr(dev, &cq->mr); 926 if (cq->is_kernel) {
914 mthca_free_cq_buf(dev, cq); 927 mthca_free_mr(dev, &cq->mr);
915 928 mthca_free_cq_buf(dev, cq);
916 if (mthca_is_memfree(dev)) { 929 if (mthca_is_memfree(dev)) {
917 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index); 930 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
918 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index); 931 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
932 }
919 } 933 }
920 934
921 mthca_table_put(dev, dev->cq_table.table, cq->cqn); 935 mthca_table_put(dev, dev->cq_table.table, cq->cqn);
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 3801facf6f1f..751f69479a78 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -414,6 +414,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
414int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify); 414int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
415int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify); 415int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
416int mthca_init_cq(struct mthca_dev *dev, int nent, 416int mthca_init_cq(struct mthca_dev *dev, int nent,
417 struct mthca_ucontext *ctx, u32 pdn,
417 struct mthca_cq *cq); 418 struct mthca_cq *cq);
418void mthca_free_cq(struct mthca_dev *dev, 419void mthca_free_cq(struct mthca_dev *dev,
419 struct mthca_cq *cq); 420 struct mthca_cq *cq);
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index bbdfcbe6bade..9feb7618ba41 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -497,28 +497,85 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
497 struct ib_ucontext *context, 497 struct ib_ucontext *context,
498 struct ib_udata *udata) 498 struct ib_udata *udata)
499{ 499{
500 struct mthca_create_cq ucmd;
500 struct mthca_cq *cq; 501 struct mthca_cq *cq;
501 int nent; 502 int nent;
502 int err; 503 int err;
503 504
505 if (context) {
506 if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
507 return ERR_PTR(-EFAULT);
508
509 err = mthca_map_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
510 to_mucontext(context)->db_tab,
511 ucmd.set_db_index, ucmd.set_db_page);
512 if (err)
513 return ERR_PTR(err);
514
515 err = mthca_map_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
516 to_mucontext(context)->db_tab,
517 ucmd.arm_db_index, ucmd.arm_db_page);
518 if (err)
519 goto err_unmap_set;
520 }
521
504 cq = kmalloc(sizeof *cq, GFP_KERNEL); 522 cq = kmalloc(sizeof *cq, GFP_KERNEL);
505 if (!cq) 523 if (!cq) {
506 return ERR_PTR(-ENOMEM); 524 err = -ENOMEM;
525 goto err_unmap_arm;
526 }
527
528 if (context) {
529 cq->mr.ibmr.lkey = ucmd.lkey;
530 cq->set_ci_db_index = ucmd.set_db_index;
531 cq->arm_db_index = ucmd.arm_db_index;
532 }
507 533
508 for (nent = 1; nent <= entries; nent <<= 1) 534 for (nent = 1; nent <= entries; nent <<= 1)
509 ; /* nothing */ 535 ; /* nothing */
510 536
511 err = mthca_init_cq(to_mdev(ibdev), nent, cq); 537 err = mthca_init_cq(to_mdev(ibdev), nent,
512 if (err) { 538 context ? to_mucontext(context) : NULL,
513 kfree(cq); 539 context ? ucmd.pdn : to_mdev(ibdev)->driver_pd.pd_num,
514 cq = ERR_PTR(err); 540 cq);
541 if (err)
542 goto err_free;
543
544 if (context && ib_copy_to_udata(udata, &cq->cqn, sizeof (__u32))) {
545 mthca_free_cq(to_mdev(ibdev), cq);
546 goto err_free;
515 } 547 }
516 548
517 return &cq->ibcq; 549 return &cq->ibcq;
550
551err_free:
552 kfree(cq);
553
554err_unmap_arm:
555 if (context)
556 mthca_unmap_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
557 to_mucontext(context)->db_tab, ucmd.arm_db_index);
558
559err_unmap_set:
560 if (context)
561 mthca_unmap_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
562 to_mucontext(context)->db_tab, ucmd.set_db_index);
563
564 return ERR_PTR(err);
518} 565}
519 566
520static int mthca_destroy_cq(struct ib_cq *cq) 567static int mthca_destroy_cq(struct ib_cq *cq)
521{ 568{
569 if (cq->uobject) {
570 mthca_unmap_user_db(to_mdev(cq->device),
571 &to_mucontext(cq->uobject->context)->uar,
572 to_mucontext(cq->uobject->context)->db_tab,
573 to_mcq(cq)->arm_db_index);
574 mthca_unmap_user_db(to_mdev(cq->device),
575 &to_mucontext(cq->uobject->context)->uar,
576 to_mucontext(cq->uobject->context)->db_tab,
577 to_mcq(cq)->set_ci_db_index);
578 }
522 mthca_free_cq(to_mdev(cq->device), to_mcq(cq)); 579 mthca_free_cq(to_mdev(cq->device), to_mcq(cq));
523 kfree(cq); 580 kfree(cq);
524 581
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 579d10cd1426..1d032791cc8b 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -177,6 +177,7 @@ struct mthca_cq {
177 int cqn; 177 int cqn;
178 u32 cons_index; 178 u32 cons_index;
179 int is_direct; 179 int is_direct;
180 int is_kernel;
180 181
181 /* Next fields are Arbel only */ 182 /* Next fields are Arbel only */
182 int set_ci_db_index; 183 int set_ci_db_index;