aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/core/uverbs.h11
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c90
-rw-r--r--drivers/infiniband/core/uverbs_main.c21
3 files changed, 99 insertions, 23 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index ecb830127865..7114e3fbab00 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -105,12 +105,23 @@ struct ib_uverbs_event {
105 u32 *counter; 105 u32 *counter;
106}; 106};
107 107
108struct ib_uverbs_mcast_entry {
109 struct list_head list;
110 union ib_gid gid;
111 u16 lid;
112};
113
108struct ib_uevent_object { 114struct ib_uevent_object {
109 struct ib_uobject uobject; 115 struct ib_uobject uobject;
110 struct list_head event_list; 116 struct list_head event_list;
111 u32 events_reported; 117 u32 events_reported;
112}; 118};
113 119
120struct ib_uqp_object {
121 struct ib_uevent_object uevent;
122 struct list_head mcast_list;
123};
124
114struct ib_ucq_object { 125struct ib_ucq_object {
115 struct ib_uobject uobject; 126 struct ib_uobject uobject;
116 struct ib_uverbs_file *uverbs_file; 127 struct ib_uverbs_file *uverbs_file;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index ed45da892b1c..a57d021d435a 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -815,7 +815,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
815 struct ib_uverbs_create_qp cmd; 815 struct ib_uverbs_create_qp cmd;
816 struct ib_uverbs_create_qp_resp resp; 816 struct ib_uverbs_create_qp_resp resp;
817 struct ib_udata udata; 817 struct ib_udata udata;
818 struct ib_uevent_object *uobj; 818 struct ib_uqp_object *uobj;
819 struct ib_pd *pd; 819 struct ib_pd *pd;
820 struct ib_cq *scq, *rcq; 820 struct ib_cq *scq, *rcq;
821 struct ib_srq *srq; 821 struct ib_srq *srq;
@@ -866,10 +866,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
866 attr.cap.max_recv_sge = cmd.max_recv_sge; 866 attr.cap.max_recv_sge = cmd.max_recv_sge;
867 attr.cap.max_inline_data = cmd.max_inline_data; 867 attr.cap.max_inline_data = cmd.max_inline_data;
868 868
869 uobj->uobject.user_handle = cmd.user_handle; 869 uobj->uevent.uobject.user_handle = cmd.user_handle;
870 uobj->uobject.context = file->ucontext; 870 uobj->uevent.uobject.context = file->ucontext;
871 uobj->events_reported = 0; 871 uobj->uevent.events_reported = 0;
872 INIT_LIST_HEAD(&uobj->event_list); 872 INIT_LIST_HEAD(&uobj->uevent.event_list);
873 INIT_LIST_HEAD(&uobj->mcast_list);
873 874
874 qp = pd->device->create_qp(pd, &attr, &udata); 875 qp = pd->device->create_qp(pd, &attr, &udata);
875 if (IS_ERR(qp)) { 876 if (IS_ERR(qp)) {
@@ -882,7 +883,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
882 qp->send_cq = attr.send_cq; 883 qp->send_cq = attr.send_cq;
883 qp->recv_cq = attr.recv_cq; 884 qp->recv_cq = attr.recv_cq;
884 qp->srq = attr.srq; 885 qp->srq = attr.srq;
885 qp->uobject = &uobj->uobject; 886 qp->uobject = &uobj->uevent.uobject;
886 qp->event_handler = attr.event_handler; 887 qp->event_handler = attr.event_handler;
887 qp->qp_context = attr.qp_context; 888 qp->qp_context = attr.qp_context;
888 qp->qp_type = attr.qp_type; 889 qp->qp_type = attr.qp_type;
@@ -901,14 +902,14 @@ retry:
901 goto err_destroy; 902 goto err_destroy;
902 } 903 }
903 904
904 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id); 905 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uevent.uobject.id);
905 906
906 if (ret == -EAGAIN) 907 if (ret == -EAGAIN)
907 goto retry; 908 goto retry;
908 if (ret) 909 if (ret)
909 goto err_destroy; 910 goto err_destroy;
910 911
911 resp.qp_handle = uobj->uobject.id; 912 resp.qp_handle = uobj->uevent.uobject.id;
912 resp.max_recv_sge = attr.cap.max_recv_sge; 913 resp.max_recv_sge = attr.cap.max_recv_sge;
913 resp.max_send_sge = attr.cap.max_send_sge; 914 resp.max_send_sge = attr.cap.max_send_sge;
914 resp.max_recv_wr = attr.cap.max_recv_wr; 915 resp.max_recv_wr = attr.cap.max_recv_wr;
@@ -922,7 +923,7 @@ retry:
922 } 923 }
923 924
924 down(&file->mutex); 925 down(&file->mutex);
925 list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list); 926 list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list);
926 up(&file->mutex); 927 up(&file->mutex);
927 928
928 up(&ib_uverbs_idr_mutex); 929 up(&ib_uverbs_idr_mutex);
@@ -930,7 +931,7 @@ retry:
930 return in_len; 931 return in_len;
931 932
932err_idr: 933err_idr:
933 idr_remove(&ib_uverbs_qp_idr, uobj->uobject.id); 934 idr_remove(&ib_uverbs_qp_idr, uobj->uevent.uobject.id);
934 935
935err_destroy: 936err_destroy:
936 ib_destroy_qp(qp); 937 ib_destroy_qp(qp);
@@ -1032,7 +1033,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
1032 struct ib_uverbs_destroy_qp cmd; 1033 struct ib_uverbs_destroy_qp cmd;
1033 struct ib_uverbs_destroy_qp_resp resp; 1034 struct ib_uverbs_destroy_qp_resp resp;
1034 struct ib_qp *qp; 1035 struct ib_qp *qp;
1035 struct ib_uevent_object *uobj; 1036 struct ib_uqp_object *uobj;
1036 int ret = -EINVAL; 1037 int ret = -EINVAL;
1037 1038
1038 if (copy_from_user(&cmd, buf, sizeof cmd)) 1039 if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1046,7 +1047,12 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
1046 if (!qp || qp->uobject->context != file->ucontext) 1047 if (!qp || qp->uobject->context != file->ucontext)
1047 goto out; 1048 goto out;
1048 1049
1049 uobj = container_of(qp->uobject, struct ib_uevent_object, uobject); 1050 uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
1051
1052 if (!list_empty(&uobj->mcast_list)) {
1053 ret = -EBUSY;
1054 goto out;
1055 }
1050 1056
1051 ret = ib_destroy_qp(qp); 1057 ret = ib_destroy_qp(qp);
1052 if (ret) 1058 if (ret)
@@ -1055,12 +1061,12 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
1055 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); 1061 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
1056 1062
1057 down(&file->mutex); 1063 down(&file->mutex);
1058 list_del(&uobj->uobject.list); 1064 list_del(&uobj->uevent.uobject.list);
1059 up(&file->mutex); 1065 up(&file->mutex);
1060 1066
1061 ib_uverbs_release_uevent(file, uobj); 1067 ib_uverbs_release_uevent(file, &uobj->uevent);
1062 1068
1063 resp.events_reported = uobj->events_reported; 1069 resp.events_reported = uobj->uevent.events_reported;
1064 1070
1065 kfree(uobj); 1071 kfree(uobj);
1066 1072
@@ -1542,6 +1548,8 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
1542{ 1548{
1543 struct ib_uverbs_attach_mcast cmd; 1549 struct ib_uverbs_attach_mcast cmd;
1544 struct ib_qp *qp; 1550 struct ib_qp *qp;
1551 struct ib_uqp_object *uobj;
1552 struct ib_uverbs_mcast_entry *mcast;
1545 int ret = -EINVAL; 1553 int ret = -EINVAL;
1546 1554
1547 if (copy_from_user(&cmd, buf, sizeof cmd)) 1555 if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1550,9 +1558,36 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
1550 down(&ib_uverbs_idr_mutex); 1558 down(&ib_uverbs_idr_mutex);
1551 1559
1552 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1560 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1553 if (qp && qp->uobject->context == file->ucontext) 1561 if (!qp || qp->uobject->context != file->ucontext)
1554 ret = ib_attach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 1562 goto out;
1563
1564 uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
1565
1566 list_for_each_entry(mcast, &uobj->mcast_list, list)
1567 if (cmd.mlid == mcast->lid &&
1568 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
1569 ret = 0;
1570 goto out;
1571 }
1555 1572
1573 mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
1574 if (!mcast) {
1575 ret = -ENOMEM;
1576 goto out;
1577 }
1578
1579 mcast->lid = cmd.mlid;
1580 memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw);
1581
1582 ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid);
1583 if (!ret) {
1584 uobj = container_of(qp->uobject, struct ib_uqp_object,
1585 uevent.uobject);
1586 list_add_tail(&mcast->list, &uobj->mcast_list);
1587 } else
1588 kfree(mcast);
1589
1590out:
1556 up(&ib_uverbs_idr_mutex); 1591 up(&ib_uverbs_idr_mutex);
1557 1592
1558 return ret ? ret : in_len; 1593 return ret ? ret : in_len;
@@ -1563,7 +1598,9 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
1563 int out_len) 1598 int out_len)
1564{ 1599{
1565 struct ib_uverbs_detach_mcast cmd; 1600 struct ib_uverbs_detach_mcast cmd;
1601 struct ib_uqp_object *uobj;
1566 struct ib_qp *qp; 1602 struct ib_qp *qp;
1603 struct ib_uverbs_mcast_entry *mcast;
1567 int ret = -EINVAL; 1604 int ret = -EINVAL;
1568 1605
1569 if (copy_from_user(&cmd, buf, sizeof cmd)) 1606 if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1572,9 +1609,24 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
1572 down(&ib_uverbs_idr_mutex); 1609 down(&ib_uverbs_idr_mutex);
1573 1610
1574 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1611 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1575 if (qp && qp->uobject->context == file->ucontext) 1612 if (!qp || qp->uobject->context != file->ucontext)
1576 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 1613 goto out;
1614
1615 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
1616 if (ret)
1617 goto out;
1577 1618
1619 uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
1620
1621 list_for_each_entry(mcast, &uobj->mcast_list, list)
1622 if (cmd.mlid == mcast->lid &&
1623 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
1624 list_del(&mcast->list);
1625 kfree(mcast);
1626 break;
1627 }
1628
1629out:
1578 up(&ib_uverbs_idr_mutex); 1630 up(&ib_uverbs_idr_mutex);
1579 1631
1580 return ret ? ret : in_len; 1632 return ret ? ret : in_len;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index de6581d7cb8d..81737bd6faea 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -160,6 +160,18 @@ void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
160 spin_unlock_irq(&file->async_file->lock); 160 spin_unlock_irq(&file->async_file->lock);
161} 161}
162 162
163static void ib_uverbs_detach_umcast(struct ib_qp *qp,
164 struct ib_uqp_object *uobj)
165{
166 struct ib_uverbs_mcast_entry *mcast, *tmp;
167
168 list_for_each_entry_safe(mcast, tmp, &uobj->mcast_list, list) {
169 ib_detach_mcast(qp, &mcast->gid, mcast->lid);
170 list_del(&mcast->list);
171 kfree(mcast);
172 }
173}
174
163static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, 175static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
164 struct ib_ucontext *context) 176 struct ib_ucontext *context)
165{ 177{
@@ -180,13 +192,14 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
180 192
181 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) { 193 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
182 struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id); 194 struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
183 struct ib_uevent_object *uevent = 195 struct ib_uqp_object *uqp =
184 container_of(uobj, struct ib_uevent_object, uobject); 196 container_of(uobj, struct ib_uqp_object, uevent.uobject);
185 idr_remove(&ib_uverbs_qp_idr, uobj->id); 197 idr_remove(&ib_uverbs_qp_idr, uobj->id);
198 ib_uverbs_detach_umcast(qp, uqp);
186 ib_destroy_qp(qp); 199 ib_destroy_qp(qp);
187 list_del(&uobj->list); 200 list_del(&uobj->list);
188 ib_uverbs_release_uevent(file, uevent); 201 ib_uverbs_release_uevent(file, &uqp->uevent);
189 kfree(uevent); 202 kfree(uqp);
190 } 203 }
191 204
192 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { 205 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {