diff options
author | Roland Dreier <rolandd@cisco.com> | 2005-07-07 20:57:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-07 21:23:50 -0400 |
commit | 74c2174e7be52f9d2d210511bf3b490f4b41574c (patch) | |
tree | aa7288790ba6329871c82904d46afe26bca24313 | |
parent | 24d4281be0598d2d4ab9a2ffb1b78f5af0ffaddf (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.c | 76 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_dev.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_provider.c | 69 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_provider.h | 1 |
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 | ||
744 | int mthca_init_cq(struct mthca_dev *dev, int nent, | 745 | int 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 | ||
845 | err_out_free_mr: | 855 | err_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 | ||
849 | err_out_mailbox: | 861 | err_out_mailbox: |
850 | mthca_free_mailbox(dev, mailbox); | 862 | mthca_free_mailbox(dev, mailbox); |
851 | 863 | ||
852 | err_out_arm: | 864 | err_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 | ||
856 | err_out_ci: | 868 | err_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 | ||
860 | err_out_icm: | 872 | err_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, | |||
414 | int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify); | 414 | int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify); |
415 | int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify); | 415 | int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify); |
416 | int mthca_init_cq(struct mthca_dev *dev, int nent, | 416 | int 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); |
418 | void mthca_free_cq(struct mthca_dev *dev, | 419 | void 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 | |||
551 | err_free: | ||
552 | kfree(cq); | ||
553 | |||
554 | err_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 | |||
559 | err_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 | ||
520 | static int mthca_destroy_cq(struct ib_cq *cq) | 567 | static 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; |