aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c64
1 files changed, 34 insertions, 30 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 30923eb68ec7..b72c7f69ca90 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -155,7 +155,7 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
155} 155}
156 156
157static struct ib_uobject *idr_read_uobj(struct idr *idr, int id, 157static struct ib_uobject *idr_read_uobj(struct idr *idr, int id,
158 struct ib_ucontext *context) 158 struct ib_ucontext *context, int nested)
159{ 159{
160 struct ib_uobject *uobj; 160 struct ib_uobject *uobj;
161 161
@@ -163,7 +163,10 @@ static struct ib_uobject *idr_read_uobj(struct idr *idr, int id,
163 if (!uobj) 163 if (!uobj)
164 return NULL; 164 return NULL;
165 165
166 down_read(&uobj->mutex); 166 if (nested)
167 down_read_nested(&uobj->mutex, SINGLE_DEPTH_NESTING);
168 else
169 down_read(&uobj->mutex);
167 if (!uobj->live) { 170 if (!uobj->live) {
168 put_uobj_read(uobj); 171 put_uobj_read(uobj);
169 return NULL; 172 return NULL;
@@ -190,17 +193,18 @@ static struct ib_uobject *idr_write_uobj(struct idr *idr, int id,
190 return uobj; 193 return uobj;
191} 194}
192 195
193static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context) 196static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context,
197 int nested)
194{ 198{
195 struct ib_uobject *uobj; 199 struct ib_uobject *uobj;
196 200
197 uobj = idr_read_uobj(idr, id, context); 201 uobj = idr_read_uobj(idr, id, context, nested);
198 return uobj ? uobj->object : NULL; 202 return uobj ? uobj->object : NULL;
199} 203}
200 204
201static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context) 205static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context)
202{ 206{
203 return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context); 207 return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context, 0);
204} 208}
205 209
206static void put_pd_read(struct ib_pd *pd) 210static void put_pd_read(struct ib_pd *pd)
@@ -208,9 +212,9 @@ static void put_pd_read(struct ib_pd *pd)
208 put_uobj_read(pd->uobject); 212 put_uobj_read(pd->uobject);
209} 213}
210 214
211static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context) 215static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context, int nested)
212{ 216{
213 return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context); 217 return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context, nested);
214} 218}
215 219
216static void put_cq_read(struct ib_cq *cq) 220static void put_cq_read(struct ib_cq *cq)
@@ -220,7 +224,7 @@ static void put_cq_read(struct ib_cq *cq)
220 224
221static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context) 225static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context)
222{ 226{
223 return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context); 227 return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context, 0);
224} 228}
225 229
226static void put_ah_read(struct ib_ah *ah) 230static void put_ah_read(struct ib_ah *ah)
@@ -230,7 +234,7 @@ static void put_ah_read(struct ib_ah *ah)
230 234
231static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) 235static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context)
232{ 236{
233 return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context); 237 return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0);
234} 238}
235 239
236static void put_qp_read(struct ib_qp *qp) 240static void put_qp_read(struct ib_qp *qp)
@@ -240,7 +244,7 @@ static void put_qp_read(struct ib_qp *qp)
240 244
241static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) 245static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
242{ 246{
243 return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context); 247 return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0);
244} 248}
245 249
246static void put_srq_read(struct ib_srq *srq) 250static void put_srq_read(struct ib_srq *srq)
@@ -837,7 +841,6 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
837err_copy: 841err_copy:
838 idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); 842 idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject);
839 843
840
841err_free: 844err_free:
842 ib_destroy_cq(cq); 845 ib_destroy_cq(cq);
843 846
@@ -867,7 +870,7 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
867 (unsigned long) cmd.response + sizeof resp, 870 (unsigned long) cmd.response + sizeof resp,
868 in_len - sizeof cmd, out_len - sizeof resp); 871 in_len - sizeof cmd, out_len - sizeof resp);
869 872
870 cq = idr_read_cq(cmd.cq_handle, file->ucontext); 873 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
871 if (!cq) 874 if (!cq)
872 return -EINVAL; 875 return -EINVAL;
873 876
@@ -875,11 +878,10 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
875 if (ret) 878 if (ret)
876 goto out; 879 goto out;
877 880
878 memset(&resp, 0, sizeof resp);
879 resp.cqe = cq->cqe; 881 resp.cqe = cq->cqe;
880 882
881 if (copy_to_user((void __user *) (unsigned long) cmd.response, 883 if (copy_to_user((void __user *) (unsigned long) cmd.response,
882 &resp, sizeof resp)) 884 &resp, sizeof resp.cqe))
883 ret = -EFAULT; 885 ret = -EFAULT;
884 886
885out: 887out:
@@ -894,7 +896,6 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
894{ 896{
895 struct ib_uverbs_poll_cq cmd; 897 struct ib_uverbs_poll_cq cmd;
896 struct ib_uverbs_poll_cq_resp *resp; 898 struct ib_uverbs_poll_cq_resp *resp;
897 struct ib_uobject *uobj;
898 struct ib_cq *cq; 899 struct ib_cq *cq;
899 struct ib_wc *wc; 900 struct ib_wc *wc;
900 int ret = 0; 901 int ret = 0;
@@ -915,16 +916,15 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
915 goto out_wc; 916 goto out_wc;
916 } 917 }
917 918
918 uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); 919 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
919 if (!uobj) { 920 if (!cq) {
920 ret = -EINVAL; 921 ret = -EINVAL;
921 goto out; 922 goto out;
922 } 923 }
923 cq = uobj->object;
924 924
925 resp->count = ib_poll_cq(cq, cmd.ne, wc); 925 resp->count = ib_poll_cq(cq, cmd.ne, wc);
926 926
927 put_uobj_read(uobj); 927 put_cq_read(cq);
928 928
929 for (i = 0; i < resp->count; i++) { 929 for (i = 0; i < resp->count; i++) {
930 resp->wc[i].wr_id = wc[i].wr_id; 930 resp->wc[i].wr_id = wc[i].wr_id;
@@ -959,21 +959,19 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
959 int out_len) 959 int out_len)
960{ 960{
961 struct ib_uverbs_req_notify_cq cmd; 961 struct ib_uverbs_req_notify_cq cmd;
962 struct ib_uobject *uobj;
963 struct ib_cq *cq; 962 struct ib_cq *cq;
964 963
965 if (copy_from_user(&cmd, buf, sizeof cmd)) 964 if (copy_from_user(&cmd, buf, sizeof cmd))
966 return -EFAULT; 965 return -EFAULT;
967 966
968 uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); 967 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
969 if (!uobj) 968 if (!cq)
970 return -EINVAL; 969 return -EINVAL;
971 cq = uobj->object;
972 970
973 ib_req_notify_cq(cq, cmd.solicited_only ? 971 ib_req_notify_cq(cq, cmd.solicited_only ?
974 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); 972 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
975 973
976 put_uobj_read(uobj); 974 put_cq_read(cq);
977 975
978 return in_len; 976 return in_len;
979} 977}
@@ -1064,9 +1062,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
1064 1062
1065 srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL; 1063 srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
1066 pd = idr_read_pd(cmd.pd_handle, file->ucontext); 1064 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
1067 scq = idr_read_cq(cmd.send_cq_handle, file->ucontext); 1065 scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
1068 rcq = cmd.recv_cq_handle == cmd.send_cq_handle ? 1066 rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
1069 scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext); 1067 scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
1070 1068
1071 if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) { 1069 if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
1072 ret = -EINVAL; 1070 ret = -EINVAL;
@@ -1274,6 +1272,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
1274 int out_len) 1272 int out_len)
1275{ 1273{
1276 struct ib_uverbs_modify_qp cmd; 1274 struct ib_uverbs_modify_qp cmd;
1275 struct ib_udata udata;
1277 struct ib_qp *qp; 1276 struct ib_qp *qp;
1278 struct ib_qp_attr *attr; 1277 struct ib_qp_attr *attr;
1279 int ret; 1278 int ret;
@@ -1281,6 +1280,9 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
1281 if (copy_from_user(&cmd, buf, sizeof cmd)) 1280 if (copy_from_user(&cmd, buf, sizeof cmd))
1282 return -EFAULT; 1281 return -EFAULT;
1283 1282
1283 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
1284 out_len);
1285
1284 attr = kmalloc(sizeof *attr, GFP_KERNEL); 1286 attr = kmalloc(sizeof *attr, GFP_KERNEL);
1285 if (!attr) 1287 if (!attr)
1286 return -ENOMEM; 1288 return -ENOMEM;
@@ -1337,7 +1339,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
1337 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0; 1339 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
1338 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; 1340 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
1339 1341
1340 ret = ib_modify_qp(qp, attr, cmd.attr_mask); 1342 ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
1341 1343
1342 put_qp_read(qp); 1344 put_qp_read(qp);
1343 1345
@@ -1674,7 +1676,6 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
1674 break; 1676 break;
1675 } 1677 }
1676 1678
1677
1678 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1679 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1679 &resp, sizeof resp)) 1680 &resp, sizeof resp))
1680 ret = -EFAULT; 1681 ret = -EFAULT;
@@ -1724,7 +1725,6 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
1724 break; 1725 break;
1725 } 1726 }
1726 1727
1727
1728 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1728 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1729 &resp, sizeof resp)) 1729 &resp, sizeof resp))
1730 ret = -EFAULT; 1730 ret = -EFAULT;
@@ -2055,6 +2055,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
2055 int out_len) 2055 int out_len)
2056{ 2056{
2057 struct ib_uverbs_modify_srq cmd; 2057 struct ib_uverbs_modify_srq cmd;
2058 struct ib_udata udata;
2058 struct ib_srq *srq; 2059 struct ib_srq *srq;
2059 struct ib_srq_attr attr; 2060 struct ib_srq_attr attr;
2060 int ret; 2061 int ret;
@@ -2062,6 +2063,9 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
2062 if (copy_from_user(&cmd, buf, sizeof cmd)) 2063 if (copy_from_user(&cmd, buf, sizeof cmd))
2063 return -EFAULT; 2064 return -EFAULT;
2064 2065
2066 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
2067 out_len);
2068
2065 srq = idr_read_srq(cmd.srq_handle, file->ucontext); 2069 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
2066 if (!srq) 2070 if (!srq)
2067 return -EINVAL; 2071 return -EINVAL;
@@ -2069,7 +2073,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
2069 attr.max_wr = cmd.max_wr; 2073 attr.max_wr = cmd.max_wr;
2070 attr.srq_limit = cmd.srq_limit; 2074 attr.srq_limit = cmd.srq_limit;
2071 2075
2072 ret = ib_modify_srq(srq, &attr, cmd.attr_mask); 2076 ret = srq->device->modify_srq(srq, &attr, cmd.attr_mask, &udata);
2073 2077
2074 put_srq_read(srq); 2078 put_srq_read(srq);
2075 2079