aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/uverbs.h26
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c155
-rw-r--r--drivers/infiniband/core/uverbs_main.c98
-rw-r--r--include/rdma/ib_user_verbs.h21
4 files changed, 211 insertions, 89 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 180b3d4765e4..b1897bed14ad 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -76,20 +76,28 @@ struct ib_uverbs_file {
76 struct ib_uverbs_event_file comp_file[1]; 76 struct ib_uverbs_event_file comp_file[1];
77}; 77};
78 78
79struct ib_uverbs_async_event { 79struct ib_uverbs_event {
80 struct ib_uverbs_async_event_desc desc; 80 union {
81 struct ib_uverbs_async_event_desc async;
82 struct ib_uverbs_comp_event_desc comp;
83 } desc;
81 struct list_head list; 84 struct list_head list;
85 struct list_head obj_list;
86 u32 *counter;
82}; 87};
83 88
84struct ib_uverbs_comp_event { 89struct ib_uevent_object {
85 struct ib_uverbs_comp_event_desc desc; 90 struct ib_uobject uobject;
86 struct list_head list; 91 struct list_head event_list;
92 u32 events_reported;
87}; 93};
88 94
89struct ib_uobject_mr { 95struct ib_ucq_object {
90 struct ib_uobject uobj; 96 struct ib_uobject uobject;
91 struct page *page_list; 97 struct list_head comp_list;
92 struct scatterlist *sg_list; 98 struct list_head async_list;
99 u32 comp_events_reported;
100 u32 async_events_reported;
93}; 101};
94 102
95extern struct semaphore ib_uverbs_idr_mutex; 103extern struct semaphore ib_uverbs_idr_mutex;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index ebccf9f38af9..e91ebde46481 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -590,7 +590,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
590 struct ib_uverbs_create_cq cmd; 590 struct ib_uverbs_create_cq cmd;
591 struct ib_uverbs_create_cq_resp resp; 591 struct ib_uverbs_create_cq_resp resp;
592 struct ib_udata udata; 592 struct ib_udata udata;
593 struct ib_uobject *uobj; 593 struct ib_ucq_object *uobj;
594 struct ib_cq *cq; 594 struct ib_cq *cq;
595 int ret; 595 int ret;
596 596
@@ -611,8 +611,12 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
611 if (!uobj) 611 if (!uobj)
612 return -ENOMEM; 612 return -ENOMEM;
613 613
614 uobj->user_handle = cmd.user_handle; 614 uobj->uobject.user_handle = cmd.user_handle;
615 uobj->context = file->ucontext; 615 uobj->uobject.context = file->ucontext;
616 uobj->comp_events_reported = 0;
617 uobj->async_events_reported = 0;
618 INIT_LIST_HEAD(&uobj->comp_list);
619 INIT_LIST_HEAD(&uobj->async_list);
616 620
617 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, 621 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
618 file->ucontext, &udata); 622 file->ucontext, &udata);
@@ -622,7 +626,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
622 } 626 }
623 627
624 cq->device = file->device->ib_dev; 628 cq->device = file->device->ib_dev;
625 cq->uobject = uobj; 629 cq->uobject = &uobj->uobject;
626 cq->comp_handler = ib_uverbs_comp_handler; 630 cq->comp_handler = ib_uverbs_comp_handler;
627 cq->event_handler = ib_uverbs_cq_event_handler; 631 cq->event_handler = ib_uverbs_cq_event_handler;
628 cq->cq_context = file; 632 cq->cq_context = file;
@@ -635,7 +639,7 @@ retry:
635 } 639 }
636 640
637 down(&ib_uverbs_idr_mutex); 641 down(&ib_uverbs_idr_mutex);
638 ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->id); 642 ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
639 up(&ib_uverbs_idr_mutex); 643 up(&ib_uverbs_idr_mutex);
640 644
641 if (ret == -EAGAIN) 645 if (ret == -EAGAIN)
@@ -644,11 +648,11 @@ retry:
644 goto err_cq; 648 goto err_cq;
645 649
646 spin_lock_irq(&file->ucontext->lock); 650 spin_lock_irq(&file->ucontext->lock);
647 list_add_tail(&uobj->list, &file->ucontext->cq_list); 651 list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
648 spin_unlock_irq(&file->ucontext->lock); 652 spin_unlock_irq(&file->ucontext->lock);
649 653
650 memset(&resp, 0, sizeof resp); 654 memset(&resp, 0, sizeof resp);
651 resp.cq_handle = uobj->id; 655 resp.cq_handle = uobj->uobject.id;
652 resp.cqe = cq->cqe; 656 resp.cqe = cq->cqe;
653 657
654 if (copy_to_user((void __user *) (unsigned long) cmd.response, 658 if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -661,11 +665,11 @@ retry:
661 665
662err_list: 666err_list:
663 spin_lock_irq(&file->ucontext->lock); 667 spin_lock_irq(&file->ucontext->lock);
664 list_del(&uobj->list); 668 list_del(&uobj->uobject.list);
665 spin_unlock_irq(&file->ucontext->lock); 669 spin_unlock_irq(&file->ucontext->lock);
666 670
667 down(&ib_uverbs_idr_mutex); 671 down(&ib_uverbs_idr_mutex);
668 idr_remove(&ib_uverbs_cq_idr, uobj->id); 672 idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
669 up(&ib_uverbs_idr_mutex); 673 up(&ib_uverbs_idr_mutex);
670 674
671err_cq: 675err_cq:
@@ -680,21 +684,27 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
680 const char __user *buf, int in_len, 684 const char __user *buf, int in_len,
681 int out_len) 685 int out_len)
682{ 686{
683 struct ib_uverbs_destroy_cq cmd; 687 struct ib_uverbs_destroy_cq cmd;
684 struct ib_cq *cq; 688 struct ib_uverbs_destroy_cq_resp resp;
685 struct ib_uobject *uobj; 689 struct ib_cq *cq;
686 int ret = -EINVAL; 690 struct ib_ucq_object *uobj;
691 struct ib_uverbs_event *evt, *tmp;
692 u64 user_handle;
693 int ret = -EINVAL;
687 694
688 if (copy_from_user(&cmd, buf, sizeof cmd)) 695 if (copy_from_user(&cmd, buf, sizeof cmd))
689 return -EFAULT; 696 return -EFAULT;
690 697
698 memset(&resp, 0, sizeof resp);
699
691 down(&ib_uverbs_idr_mutex); 700 down(&ib_uverbs_idr_mutex);
692 701
693 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 702 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
694 if (!cq || cq->uobject->context != file->ucontext) 703 if (!cq || cq->uobject->context != file->ucontext)
695 goto out; 704 goto out;
696 705
697 uobj = cq->uobject; 706 user_handle = cq->uobject->user_handle;
707 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
698 708
699 ret = ib_destroy_cq(cq); 709 ret = ib_destroy_cq(cq);
700 if (ret) 710 if (ret)
@@ -703,11 +713,32 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
703 idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); 713 idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
704 714
705 spin_lock_irq(&file->ucontext->lock); 715 spin_lock_irq(&file->ucontext->lock);
706 list_del(&uobj->list); 716 list_del(&uobj->uobject.list);
707 spin_unlock_irq(&file->ucontext->lock); 717 spin_unlock_irq(&file->ucontext->lock);
708 718
719 spin_lock_irq(&file->comp_file[0].lock);
720 list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
721 list_del(&evt->list);
722 kfree(evt);
723 }
724 spin_unlock_irq(&file->comp_file[0].lock);
725
726 spin_lock_irq(&file->async_file.lock);
727 list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
728 list_del(&evt->list);
729 kfree(evt);
730 }
731 spin_unlock_irq(&file->async_file.lock);
732
733 resp.comp_events_reported = uobj->comp_events_reported;
734 resp.async_events_reported = uobj->async_events_reported;
735
709 kfree(uobj); 736 kfree(uobj);
710 737
738 if (copy_to_user((void __user *) (unsigned long) cmd.response,
739 &resp, sizeof resp))
740 ret = -EFAULT;
741
711out: 742out:
712 up(&ib_uverbs_idr_mutex); 743 up(&ib_uverbs_idr_mutex);
713 744
@@ -721,7 +752,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
721 struct ib_uverbs_create_qp cmd; 752 struct ib_uverbs_create_qp cmd;
722 struct ib_uverbs_create_qp_resp resp; 753 struct ib_uverbs_create_qp_resp resp;
723 struct ib_udata udata; 754 struct ib_udata udata;
724 struct ib_uobject *uobj; 755 struct ib_uevent_object *uobj;
725 struct ib_pd *pd; 756 struct ib_pd *pd;
726 struct ib_cq *scq, *rcq; 757 struct ib_cq *scq, *rcq;
727 struct ib_srq *srq; 758 struct ib_srq *srq;
@@ -772,8 +803,10 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
772 attr.cap.max_recv_sge = cmd.max_recv_sge; 803 attr.cap.max_recv_sge = cmd.max_recv_sge;
773 attr.cap.max_inline_data = cmd.max_inline_data; 804 attr.cap.max_inline_data = cmd.max_inline_data;
774 805
775 uobj->user_handle = cmd.user_handle; 806 uobj->uobject.user_handle = cmd.user_handle;
776 uobj->context = file->ucontext; 807 uobj->uobject.context = file->ucontext;
808 uobj->events_reported = 0;
809 INIT_LIST_HEAD(&uobj->event_list);
777 810
778 qp = pd->device->create_qp(pd, &attr, &udata); 811 qp = pd->device->create_qp(pd, &attr, &udata);
779 if (IS_ERR(qp)) { 812 if (IS_ERR(qp)) {
@@ -786,7 +819,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
786 qp->send_cq = attr.send_cq; 819 qp->send_cq = attr.send_cq;
787 qp->recv_cq = attr.recv_cq; 820 qp->recv_cq = attr.recv_cq;
788 qp->srq = attr.srq; 821 qp->srq = attr.srq;
789 qp->uobject = uobj; 822 qp->uobject = &uobj->uobject;
790 qp->event_handler = attr.event_handler; 823 qp->event_handler = attr.event_handler;
791 qp->qp_context = attr.qp_context; 824 qp->qp_context = attr.qp_context;
792 qp->qp_type = attr.qp_type; 825 qp->qp_type = attr.qp_type;
@@ -805,17 +838,17 @@ retry:
805 goto err_destroy; 838 goto err_destroy;
806 } 839 }
807 840
808 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id); 841 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id);
809 842
810 if (ret == -EAGAIN) 843 if (ret == -EAGAIN)
811 goto retry; 844 goto retry;
812 if (ret) 845 if (ret)
813 goto err_destroy; 846 goto err_destroy;
814 847
815 resp.qp_handle = uobj->id; 848 resp.qp_handle = uobj->uobject.id;
816 849
817 spin_lock_irq(&file->ucontext->lock); 850 spin_lock_irq(&file->ucontext->lock);
818 list_add_tail(&uobj->list, &file->ucontext->qp_list); 851 list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
819 spin_unlock_irq(&file->ucontext->lock); 852 spin_unlock_irq(&file->ucontext->lock);
820 853
821 if (copy_to_user((void __user *) (unsigned long) cmd.response, 854 if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -830,7 +863,7 @@ retry:
830 863
831err_list: 864err_list:
832 spin_lock_irq(&file->ucontext->lock); 865 spin_lock_irq(&file->ucontext->lock);
833 list_del(&uobj->list); 866 list_del(&uobj->uobject.list);
834 spin_unlock_irq(&file->ucontext->lock); 867 spin_unlock_irq(&file->ucontext->lock);
835 868
836err_destroy: 869err_destroy:
@@ -930,21 +963,25 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
930 const char __user *buf, int in_len, 963 const char __user *buf, int in_len,
931 int out_len) 964 int out_len)
932{ 965{
933 struct ib_uverbs_destroy_qp cmd; 966 struct ib_uverbs_destroy_qp cmd;
934 struct ib_qp *qp; 967 struct ib_uverbs_destroy_qp_resp resp;
935 struct ib_uobject *uobj; 968 struct ib_qp *qp;
936 int ret = -EINVAL; 969 struct ib_uevent_object *uobj;
970 struct ib_uverbs_event *evt, *tmp;
971 int ret = -EINVAL;
937 972
938 if (copy_from_user(&cmd, buf, sizeof cmd)) 973 if (copy_from_user(&cmd, buf, sizeof cmd))
939 return -EFAULT; 974 return -EFAULT;
940 975
976 memset(&resp, 0, sizeof resp);
977
941 down(&ib_uverbs_idr_mutex); 978 down(&ib_uverbs_idr_mutex);
942 979
943 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 980 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
944 if (!qp || qp->uobject->context != file->ucontext) 981 if (!qp || qp->uobject->context != file->ucontext)
945 goto out; 982 goto out;
946 983
947 uobj = qp->uobject; 984 uobj = container_of(qp->uobject, struct ib_uevent_object, uobject);
948 985
949 ret = ib_destroy_qp(qp); 986 ret = ib_destroy_qp(qp);
950 if (ret) 987 if (ret)
@@ -953,11 +990,24 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
953 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); 990 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
954 991
955 spin_lock_irq(&file->ucontext->lock); 992 spin_lock_irq(&file->ucontext->lock);
956 list_del(&uobj->list); 993 list_del(&uobj->uobject.list);
957 spin_unlock_irq(&file->ucontext->lock); 994 spin_unlock_irq(&file->ucontext->lock);
958 995
996 spin_lock_irq(&file->async_file.lock);
997 list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
998 list_del(&evt->list);
999 kfree(evt);
1000 }
1001 spin_unlock_irq(&file->async_file.lock);
1002
1003 resp.events_reported = uobj->events_reported;
1004
959 kfree(uobj); 1005 kfree(uobj);
960 1006
1007 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1008 &resp, sizeof resp))
1009 ret = -EFAULT;
1010
961out: 1011out:
962 up(&ib_uverbs_idr_mutex); 1012 up(&ib_uverbs_idr_mutex);
963 1013
@@ -1015,7 +1065,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1015 struct ib_uverbs_create_srq cmd; 1065 struct ib_uverbs_create_srq cmd;
1016 struct ib_uverbs_create_srq_resp resp; 1066 struct ib_uverbs_create_srq_resp resp;
1017 struct ib_udata udata; 1067 struct ib_udata udata;
1018 struct ib_uobject *uobj; 1068 struct ib_uevent_object *uobj;
1019 struct ib_pd *pd; 1069 struct ib_pd *pd;
1020 struct ib_srq *srq; 1070 struct ib_srq *srq;
1021 struct ib_srq_init_attr attr; 1071 struct ib_srq_init_attr attr;
@@ -1050,8 +1100,10 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1050 attr.attr.max_sge = cmd.max_sge; 1100 attr.attr.max_sge = cmd.max_sge;
1051 attr.attr.srq_limit = cmd.srq_limit; 1101 attr.attr.srq_limit = cmd.srq_limit;
1052 1102
1053 uobj->user_handle = cmd.user_handle; 1103 uobj->uobject.user_handle = cmd.user_handle;
1054 uobj->context = file->ucontext; 1104 uobj->uobject.context = file->ucontext;
1105 uobj->events_reported = 0;
1106 INIT_LIST_HEAD(&uobj->event_list);
1055 1107
1056 srq = pd->device->create_srq(pd, &attr, &udata); 1108 srq = pd->device->create_srq(pd, &attr, &udata);
1057 if (IS_ERR(srq)) { 1109 if (IS_ERR(srq)) {
@@ -1061,7 +1113,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1061 1113
1062 srq->device = pd->device; 1114 srq->device = pd->device;
1063 srq->pd = pd; 1115 srq->pd = pd;
1064 srq->uobject = uobj; 1116 srq->uobject = &uobj->uobject;
1065 srq->event_handler = attr.event_handler; 1117 srq->event_handler = attr.event_handler;
1066 srq->srq_context = attr.srq_context; 1118 srq->srq_context = attr.srq_context;
1067 atomic_inc(&pd->usecnt); 1119 atomic_inc(&pd->usecnt);
@@ -1075,17 +1127,17 @@ retry:
1075 goto err_destroy; 1127 goto err_destroy;
1076 } 1128 }
1077 1129
1078 ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->id); 1130 ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
1079 1131
1080 if (ret == -EAGAIN) 1132 if (ret == -EAGAIN)
1081 goto retry; 1133 goto retry;
1082 if (ret) 1134 if (ret)
1083 goto err_destroy; 1135 goto err_destroy;
1084 1136
1085 resp.srq_handle = uobj->id; 1137 resp.srq_handle = uobj->uobject.id;
1086 1138
1087 spin_lock_irq(&file->ucontext->lock); 1139 spin_lock_irq(&file->ucontext->lock);
1088 list_add_tail(&uobj->list, &file->ucontext->srq_list); 1140 list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
1089 spin_unlock_irq(&file->ucontext->lock); 1141 spin_unlock_irq(&file->ucontext->lock);
1090 1142
1091 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1143 if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -1100,7 +1152,7 @@ retry:
1100 1152
1101err_list: 1153err_list:
1102 spin_lock_irq(&file->ucontext->lock); 1154 spin_lock_irq(&file->ucontext->lock);
1103 list_del(&uobj->list); 1155 list_del(&uobj->uobject.list);
1104 spin_unlock_irq(&file->ucontext->lock); 1156 spin_unlock_irq(&file->ucontext->lock);
1105 1157
1106err_destroy: 1158err_destroy:
@@ -1149,21 +1201,25 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1149 const char __user *buf, int in_len, 1201 const char __user *buf, int in_len,
1150 int out_len) 1202 int out_len)
1151{ 1203{
1152 struct ib_uverbs_destroy_srq cmd; 1204 struct ib_uverbs_destroy_srq cmd;
1153 struct ib_srq *srq; 1205 struct ib_uverbs_destroy_srq_resp resp;
1154 struct ib_uobject *uobj; 1206 struct ib_srq *srq;
1155 int ret = -EINVAL; 1207 struct ib_uevent_object *uobj;
1208 struct ib_uverbs_event *evt, *tmp;
1209 int ret = -EINVAL;
1156 1210
1157 if (copy_from_user(&cmd, buf, sizeof cmd)) 1211 if (copy_from_user(&cmd, buf, sizeof cmd))
1158 return -EFAULT; 1212 return -EFAULT;
1159 1213
1160 down(&ib_uverbs_idr_mutex); 1214 down(&ib_uverbs_idr_mutex);
1161 1215
1216 memset(&resp, 0, sizeof resp);
1217
1162 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1218 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
1163 if (!srq || srq->uobject->context != file->ucontext) 1219 if (!srq || srq->uobject->context != file->ucontext)
1164 goto out; 1220 goto out;
1165 1221
1166 uobj = srq->uobject; 1222 uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
1167 1223
1168 ret = ib_destroy_srq(srq); 1224 ret = ib_destroy_srq(srq);
1169 if (ret) 1225 if (ret)
@@ -1172,11 +1228,24 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1172 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); 1228 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
1173 1229
1174 spin_lock_irq(&file->ucontext->lock); 1230 spin_lock_irq(&file->ucontext->lock);
1175 list_del(&uobj->list); 1231 list_del(&uobj->uobject.list);
1176 spin_unlock_irq(&file->ucontext->lock); 1232 spin_unlock_irq(&file->ucontext->lock);
1177 1233
1234 spin_lock_irq(&file->async_file.lock);
1235 list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
1236 list_del(&evt->list);
1237 kfree(evt);
1238 }
1239 spin_unlock_irq(&file->async_file.lock);
1240
1241 resp.events_reported = uobj->events_reported;
1242
1178 kfree(uobj); 1243 kfree(uobj);
1179 1244
1245 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1246 &resp, sizeof resp))
1247 ret = -EFAULT;
1248
1180out: 1249out:
1181 up(&ib_uverbs_idr_mutex); 1250 up(&ib_uverbs_idr_mutex);
1182 1251
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 09caf5b1ef36..ce5bdb7af306 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -120,7 +120,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
120 idr_remove(&ib_uverbs_qp_idr, uobj->id); 120 idr_remove(&ib_uverbs_qp_idr, uobj->id);
121 ib_destroy_qp(qp); 121 ib_destroy_qp(qp);
122 list_del(&uobj->list); 122 list_del(&uobj->list);
123 kfree(uobj); 123 kfree(container_of(uobj, struct ib_uevent_object, uobject));
124 } 124 }
125 125
126 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { 126 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
@@ -128,7 +128,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
128 idr_remove(&ib_uverbs_cq_idr, uobj->id); 128 idr_remove(&ib_uverbs_cq_idr, uobj->id);
129 ib_destroy_cq(cq); 129 ib_destroy_cq(cq);
130 list_del(&uobj->list); 130 list_del(&uobj->list);
131 kfree(uobj); 131 kfree(container_of(uobj, struct ib_ucq_object, uobject));
132 } 132 }
133 133
134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { 134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
@@ -136,7 +136,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
136 idr_remove(&ib_uverbs_srq_idr, uobj->id); 136 idr_remove(&ib_uverbs_srq_idr, uobj->id);
137 ib_destroy_srq(srq); 137 ib_destroy_srq(srq);
138 list_del(&uobj->list); 138 list_del(&uobj->list);
139 kfree(uobj); 139 kfree(container_of(uobj, struct ib_uevent_object, uobject));
140 } 140 }
141 141
142 /* XXX Free MWs */ 142 /* XXX Free MWs */
@@ -182,7 +182,7 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
182 size_t count, loff_t *pos) 182 size_t count, loff_t *pos)
183{ 183{
184 struct ib_uverbs_event_file *file = filp->private_data; 184 struct ib_uverbs_event_file *file = filp->private_data;
185 void *event; 185 struct ib_uverbs_event *event;
186 int eventsz; 186 int eventsz;
187 int ret = 0; 187 int ret = 0;
188 188
@@ -207,21 +207,23 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
207 return -ENODEV; 207 return -ENODEV;
208 } 208 }
209 209
210 if (file->is_async) { 210 event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
211 event = list_entry(file->event_list.next, 211
212 struct ib_uverbs_async_event, list); 212 if (file->is_async)
213 eventsz = sizeof (struct ib_uverbs_async_event_desc); 213 eventsz = sizeof (struct ib_uverbs_async_event_desc);
214 } else { 214 else
215 event = list_entry(file->event_list.next,
216 struct ib_uverbs_comp_event, list);
217 eventsz = sizeof (struct ib_uverbs_comp_event_desc); 215 eventsz = sizeof (struct ib_uverbs_comp_event_desc);
218 }
219 216
220 if (eventsz > count) { 217 if (eventsz > count) {
221 ret = -EINVAL; 218 ret = -EINVAL;
222 event = NULL; 219 event = NULL;
223 } else 220 } else {
224 list_del(file->event_list.next); 221 list_del(file->event_list.next);
222 if (event->counter) {
223 ++(*event->counter);
224 list_del(&event->obj_list);
225 }
226 }
225 227
226 spin_unlock_irq(&file->lock); 228 spin_unlock_irq(&file->lock);
227 229
@@ -257,16 +259,13 @@ static unsigned int ib_uverbs_event_poll(struct file *filp,
257 259
258static void ib_uverbs_event_release(struct ib_uverbs_event_file *file) 260static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
259{ 261{
260 struct list_head *entry, *tmp; 262 struct ib_uverbs_event *entry, *tmp;
261 263
262 spin_lock_irq(&file->lock); 264 spin_lock_irq(&file->lock);
263 if (file->fd != -1) { 265 if (file->fd != -1) {
264 file->fd = -1; 266 file->fd = -1;
265 list_for_each_safe(entry, tmp, &file->event_list) 267 list_for_each_entry_safe(entry, tmp, &file->event_list, list)
266 if (file->is_async) 268 kfree(entry);
267 kfree(list_entry(entry, struct ib_uverbs_async_event, list));
268 else
269 kfree(list_entry(entry, struct ib_uverbs_comp_event, list));
270 } 269 }
271 spin_unlock_irq(&file->lock); 270 spin_unlock_irq(&file->lock);
272} 271}
@@ -304,18 +303,23 @@ static struct file_operations uverbs_event_fops = {
304 303
305void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context) 304void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
306{ 305{
307 struct ib_uverbs_file *file = cq_context; 306 struct ib_uverbs_file *file = cq_context;
308 struct ib_uverbs_comp_event *entry; 307 struct ib_ucq_object *uobj;
309 unsigned long flags; 308 struct ib_uverbs_event *entry;
309 unsigned long flags;
310 310
311 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 311 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
312 if (!entry) 312 if (!entry)
313 return; 313 return;
314 314
315 entry->desc.cq_handle = cq->uobject->user_handle; 315 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
316
317 entry->desc.comp.cq_handle = cq->uobject->user_handle;
318 entry->counter = &uobj->comp_events_reported;
316 319
317 spin_lock_irqsave(&file->comp_file[0].lock, flags); 320 spin_lock_irqsave(&file->comp_file[0].lock, flags);
318 list_add_tail(&entry->list, &file->comp_file[0].event_list); 321 list_add_tail(&entry->list, &file->comp_file[0].event_list);
322 list_add_tail(&entry->obj_list, &uobj->comp_list);
319 spin_unlock_irqrestore(&file->comp_file[0].lock, flags); 323 spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
320 324
321 wake_up_interruptible(&file->comp_file[0].poll_wait); 325 wake_up_interruptible(&file->comp_file[0].poll_wait);
@@ -323,20 +327,25 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
323} 327}
324 328
325static void ib_uverbs_async_handler(struct ib_uverbs_file *file, 329static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
326 __u64 element, __u64 event) 330 __u64 element, __u64 event,
331 struct list_head *obj_list,
332 u32 *counter)
327{ 333{
328 struct ib_uverbs_async_event *entry; 334 struct ib_uverbs_event *entry;
329 unsigned long flags; 335 unsigned long flags;
330 336
331 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 337 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
332 if (!entry) 338 if (!entry)
333 return; 339 return;
334 340
335 entry->desc.element = element; 341 entry->desc.async.element = element;
336 entry->desc.event_type = event; 342 entry->desc.async.event_type = event;
343 entry->counter = counter;
337 344
338 spin_lock_irqsave(&file->async_file.lock, flags); 345 spin_lock_irqsave(&file->async_file.lock, flags);
339 list_add_tail(&entry->list, &file->async_file.event_list); 346 list_add_tail(&entry->list, &file->async_file.event_list);
347 if (obj_list)
348 list_add_tail(&entry->obj_list, obj_list);
340 spin_unlock_irqrestore(&file->async_file.lock, flags); 349 spin_unlock_irqrestore(&file->async_file.lock, flags);
341 350
342 wake_up_interruptible(&file->async_file.poll_wait); 351 wake_up_interruptible(&file->async_file.poll_wait);
@@ -345,23 +354,39 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
345 354
346void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr) 355void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
347{ 356{
348 ib_uverbs_async_handler(context_ptr, 357 struct ib_ucq_object *uobj;
349 event->element.cq->uobject->user_handle, 358
350 event->event); 359 uobj = container_of(event->element.cq->uobject,
360 struct ib_ucq_object, uobject);
361
362 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
363 event->event, &uobj->async_list,
364 &uobj->async_events_reported);
365
351} 366}
352 367
353void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr) 368void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
354{ 369{
355 ib_uverbs_async_handler(context_ptr, 370 struct ib_uevent_object *uobj;
356 event->element.qp->uobject->user_handle, 371
357 event->event); 372 uobj = container_of(event->element.qp->uobject,
373 struct ib_uevent_object, uobject);
374
375 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
376 event->event, &uobj->event_list,
377 &uobj->events_reported);
358} 378}
359 379
360void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr) 380void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
361{ 381{
362 ib_uverbs_async_handler(context_ptr, 382 struct ib_uevent_object *uobj;
363 event->element.srq->uobject->user_handle, 383
364 event->event); 384 uobj = container_of(event->element.srq->uobject,
385 struct ib_uevent_object, uobject);
386
387 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
388 event->event, &uobj->event_list,
389 &uobj->events_reported);
365} 390}
366 391
367static void ib_uverbs_event_handler(struct ib_event_handler *handler, 392static void ib_uverbs_event_handler(struct ib_event_handler *handler,
@@ -370,7 +395,8 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler,
370 struct ib_uverbs_file *file = 395 struct ib_uverbs_file *file =
371 container_of(handler, struct ib_uverbs_file, event_handler); 396 container_of(handler, struct ib_uverbs_file, event_handler);
372 397
373 ib_uverbs_async_handler(file, event->element.port_num, event->event); 398 ib_uverbs_async_handler(file, event->element.port_num, event->event,
399 NULL, NULL);
374} 400}
375 401
376static int ib_uverbs_event_init(struct ib_uverbs_event_file *file, 402static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index 7ebb01c8f996..fd85725391a4 100644
--- a/include/rdma/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -42,7 +42,7 @@
42 * Increment this value if any changes that break userspace ABI 42 * Increment this value if any changes that break userspace ABI
43 * compatibility are made. 43 * compatibility are made.
44 */ 44 */
45#define IB_USER_VERBS_ABI_VERSION 1 45#define IB_USER_VERBS_ABI_VERSION 2
46 46
47enum { 47enum {
48 IB_USER_VERBS_CMD_QUERY_PARAMS, 48 IB_USER_VERBS_CMD_QUERY_PARAMS,
@@ -292,7 +292,14 @@ struct ib_uverbs_create_cq_resp {
292}; 292};
293 293
294struct ib_uverbs_destroy_cq { 294struct ib_uverbs_destroy_cq {
295 __u64 response;
295 __u32 cq_handle; 296 __u32 cq_handle;
297 __u32 reserved;
298};
299
300struct ib_uverbs_destroy_cq_resp {
301 __u32 comp_events_reported;
302 __u32 async_events_reported;
296}; 303};
297 304
298struct ib_uverbs_create_qp { 305struct ib_uverbs_create_qp {
@@ -372,7 +379,13 @@ struct ib_uverbs_modify_qp_resp {
372}; 379};
373 380
374struct ib_uverbs_destroy_qp { 381struct ib_uverbs_destroy_qp {
382 __u64 response;
375 __u32 qp_handle; 383 __u32 qp_handle;
384 __u32 reserved;
385};
386
387struct ib_uverbs_destroy_qp_resp {
388 __u32 events_reported;
376}; 389};
377 390
378struct ib_uverbs_attach_mcast { 391struct ib_uverbs_attach_mcast {
@@ -416,7 +429,13 @@ struct ib_uverbs_modify_srq {
416}; 429};
417 430
418struct ib_uverbs_destroy_srq { 431struct ib_uverbs_destroy_srq {
432 __u64 response;
419 __u32 srq_handle; 433 __u32 srq_handle;
434 __u32 reserved;
435};
436
437struct ib_uverbs_destroy_srq_resp {
438 __u32 events_reported;
420}; 439};
421 440
422#endif /* IB_USER_VERBS_H */ 441#endif /* IB_USER_VERBS_H */