diff options
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 64 |
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 | ||
157 | static struct ib_uobject *idr_read_uobj(struct idr *idr, int id, | 157 | static 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 | ||
193 | static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context) | 196 | static 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 | ||
201 | static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context) | 205 | static 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 | ||
206 | static void put_pd_read(struct ib_pd *pd) | 210 | static 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 | ||
211 | static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context) | 215 | static 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 | ||
216 | static void put_cq_read(struct ib_cq *cq) | 220 | static void put_cq_read(struct ib_cq *cq) |
@@ -220,7 +224,7 @@ static void put_cq_read(struct ib_cq *cq) | |||
220 | 224 | ||
221 | static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context) | 225 | static 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 | ||
226 | static void put_ah_read(struct ib_ah *ah) | 230 | static void put_ah_read(struct ib_ah *ah) |
@@ -230,7 +234,7 @@ static void put_ah_read(struct ib_ah *ah) | |||
230 | 234 | ||
231 | static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) | 235 | static 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 | ||
236 | static void put_qp_read(struct ib_qp *qp) | 240 | static void put_qp_read(struct ib_qp *qp) |
@@ -240,7 +244,7 @@ static void put_qp_read(struct ib_qp *qp) | |||
240 | 244 | ||
241 | static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) | 245 | static 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 | ||
246 | static void put_srq_read(struct ib_srq *srq) | 250 | static void put_srq_read(struct ib_srq *srq) |
@@ -837,7 +841,6 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
837 | err_copy: | 841 | err_copy: |
838 | idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); | 842 | idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); |
839 | 843 | ||
840 | |||
841 | err_free: | 844 | err_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 | ||
885 | out: | 887 | out: |
@@ -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 | ||