1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include <linux/file.h>
37#include <linux/fs.h>
38#include <linux/slab.h>
39
40#include <asm/uaccess.h>
41
42#include "uverbs.h"
43
44static struct lock_class_key pd_lock_key;
45static struct lock_class_key mr_lock_key;
46static struct lock_class_key cq_lock_key;
47static struct lock_class_key qp_lock_key;
48static struct lock_class_key ah_lock_key;
49static struct lock_class_key srq_lock_key;
50
51#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
52 do { \
53 (udata)->inbuf = (void __user *) (ibuf); \
54 (udata)->outbuf = (void __user *) (obuf); \
55 (udata)->inlen = (ilen); \
56 (udata)->outlen = (olen); \
57 } while (0)
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
85 struct ib_ucontext *context, struct lock_class_key *key)
86{
87 uobj->user_handle = user_handle;
88 uobj->context = context;
89 kref_init(&uobj->ref);
90 init_rwsem(&uobj->mutex);
91 lockdep_set_class(&uobj->mutex, key);
92 uobj->live = 0;
93}
94
95static void release_uobj(struct kref *kref)
96{
97 kfree(container_of(kref, struct ib_uobject, ref));
98}
99
100static void put_uobj(struct ib_uobject *uobj)
101{
102 kref_put(&uobj->ref, release_uobj);
103}
104
105static void put_uobj_read(struct ib_uobject *uobj)
106{
107 up_read(&uobj->mutex);
108 put_uobj(uobj);
109}
110
111static void put_uobj_write(struct ib_uobject *uobj)
112{
113 up_write(&uobj->mutex);
114 put_uobj(uobj);
115}
116
117static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj)
118{
119 int ret;
120
121retry:
122 if (!idr_pre_get(idr, GFP_KERNEL))
123 return -ENOMEM;
124
125 spin_lock(&ib_uverbs_idr_lock);
126 ret = idr_get_new(idr, uobj, &uobj->id);
127 spin_unlock(&ib_uverbs_idr_lock);
128
129 if (ret == -EAGAIN)
130 goto retry;
131
132 return ret;
133}
134
135void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj)
136{
137 spin_lock(&ib_uverbs_idr_lock);
138 idr_remove(idr, uobj->id);
139 spin_unlock(&ib_uverbs_idr_lock);
140}
141
142static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
143 struct ib_ucontext *context)
144{
145 struct ib_uobject *uobj;
146
147 spin_lock(&ib_uverbs_idr_lock);
148 uobj = idr_find(idr, id);
149 if (uobj) {
150 if (uobj->context == context)
151 kref_get(&uobj->ref);
152 else
153 uobj = NULL;
154 }
155 spin_unlock(&ib_uverbs_idr_lock);
156
157 return uobj;
158}
159
160static struct ib_uobject *idr_read_uobj(struct idr *idr, int id,
161 struct ib_ucontext *context, int nested)
162{
163 struct ib_uobject *uobj;
164
165 uobj = __idr_get_uobj(idr, id, context);
166 if (!uobj)
167 return NULL;
168
169 if (nested)
170 down_read_nested(&uobj->mutex, SINGLE_DEPTH_NESTING);
171 else
172 down_read(&uobj->mutex);
173 if (!uobj->live) {
174 put_uobj_read(uobj);
175 return NULL;
176 }
177
178 return uobj;
179}
180
181static struct ib_uobject *idr_write_uobj(struct idr *idr, int id,
182 struct ib_ucontext *context)
183{
184 struct ib_uobject *uobj;
185
186 uobj = __idr_get_uobj(idr, id, context);
187 if (!uobj)
188 return NULL;
189
190 down_write(&uobj->mutex);
191 if (!uobj->live) {
192 put_uobj_write(uobj);
193 return NULL;
194 }
195
196 return uobj;
197}
198
199static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context,
200 int nested)
201{
202 struct ib_uobject *uobj;
203
204 uobj = idr_read_uobj(idr, id, context, nested);
205 return uobj ? uobj->object : NULL;
206}
207
208static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context)
209{
210 return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context, 0);
211}
212
213static void put_pd_read(struct ib_pd *pd)
214{
215 put_uobj_read(pd->uobject);
216}
217
218static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context, int nested)
219{
220 return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context, nested);
221}
222
223static void put_cq_read(struct ib_cq *cq)
224{
225 put_uobj_read(cq->uobject);
226}
227
228static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context)
229{
230 return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context, 0);
231}
232
233static void put_ah_read(struct ib_ah *ah)
234{
235 put_uobj_read(ah->uobject);
236}
237
238static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context)
239{
240 return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0);
241}
242
243static void put_qp_read(struct ib_qp *qp)
244{
245 put_uobj_read(qp->uobject);
246}
247
248static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
249{
250 return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0);
251}
252
253static void put_srq_read(struct ib_srq *srq)
254{
255 put_uobj_read(srq->uobject);
256}
257
258ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
259 const char __user *buf,
260 int in_len, int out_len)
261{
262 struct ib_uverbs_get_context cmd;
263 struct ib_uverbs_get_context_resp resp;
264 struct ib_udata udata;
265 struct ib_device *ibdev = file->device->ib_dev;
266 struct ib_ucontext *ucontext;
267 struct file *filp;
268 int ret;
269
270 if (out_len < sizeof resp)
271 return -ENOSPC;
272
273 if (copy_from_user(&cmd, buf, sizeof cmd))
274 return -EFAULT;
275
276 mutex_lock(&file->mutex);
277
278 if (file->ucontext) {
279 ret = -EINVAL;
280 goto err;
281 }
282
283 INIT_UDATA(&udata, buf + sizeof cmd,
284 (unsigned long) cmd.response + sizeof resp,
285 in_len - sizeof cmd, out_len - sizeof resp);
286
287 ucontext = ibdev->alloc_ucontext(ibdev, &udata);
288 if (IS_ERR(ucontext)) {
289 ret = PTR_ERR(ucontext);
290 goto err;
291 }
292
293 ucontext->device = ibdev;
294 INIT_LIST_HEAD(&ucontext->pd_list);
295 INIT_LIST_HEAD(&ucontext->mr_list);
296 INIT_LIST_HEAD(&ucontext->mw_list);
297 INIT_LIST_HEAD(&ucontext->cq_list);
298 INIT_LIST_HEAD(&ucontext->qp_list);
299 INIT_LIST_HEAD(&ucontext->srq_list);
300 INIT_LIST_HEAD(&ucontext->ah_list);
301 ucontext->closing = 0;
302
303 resp.num_comp_vectors = file->device->num_comp_vectors;
304
305 ret = get_unused_fd();
306 if (ret < 0)
307 goto err_free;
308 resp.async_fd = ret;
309
310 filp = ib_uverbs_alloc_event_file(file, 1);
311 if (IS_ERR(filp)) {
312 ret = PTR_ERR(filp);
313 goto err_fd;
314 }
315
316 if (copy_to_user((void __user *) (unsigned long) cmd.response,
317 &resp, sizeof resp)) {
318 ret = -EFAULT;
319 goto err_file;
320 }
321
322 file->async_file = filp->private_data;
323
324 INIT_IB_EVENT_HANDLER(&file->event_handler, file->device->ib_dev,
325 ib_uverbs_event_handler);
326 ret = ib_register_event_handler(&file->event_handler);
327 if (ret)
328 goto err_file;
329
330 kref_get(&file->async_file->ref);
331 kref_get(&file->ref);
332 file->ucontext = ucontext;
333
334 fd_install(resp.async_fd, filp);
335
336 mutex_unlock(&file->mutex);
337
338 return in_len;
339
340err_file:
341 fput(filp);
342
343err_fd:
344 put_unused_fd(resp.async_fd);
345
346err_free:
347 ibdev->dealloc_ucontext(ucontext);
348
349err:
350 mutex_unlock(&file->mutex);
351 return ret;
352}
353
354ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
355 const char __user *buf,
356 int in_len, int out_len)
357{
358 struct ib_uverbs_query_device cmd;
359 struct ib_uverbs_query_device_resp resp;
360 struct ib_device_attr attr;
361 int ret;
362
363 if (out_len < sizeof resp)
364 return -ENOSPC;
365
366 if (copy_from_user(&cmd, buf, sizeof cmd))
367 return -EFAULT;
368
369 ret = ib_query_device(file->device->ib_dev, &attr);
370 if (ret)
371 return ret;
372
373 memset(&resp, 0, sizeof resp);
374
375 resp.fw_ver = attr.fw_ver;
376 resp.node_guid = file->device->ib_dev->node_guid;
377 resp.sys_image_guid = attr.sys_image_guid;
378 resp.max_mr_size = attr.max_mr_size;
379 resp.page_size_cap = attr.page_size_cap;
380 resp.vendor_id = attr.vendor_id;
381 resp.vendor_part_id = attr.vendor_part_id;
382 resp.hw_ver = attr.hw_ver;
383 resp.max_qp = attr.max_qp;
384 resp.max_qp_wr = attr.max_qp_wr;
385 resp.device_cap_flags = attr.device_cap_flags;
386 resp.max_sge = attr.max_sge;
387 resp.max_sge_rd = attr.max_sge_rd;
388 resp.max_cq = attr.max_cq;
389 resp.max_cqe = attr.max_cqe;
390 resp.max_mr = attr.max_mr;
391 resp.max_pd = attr.max_pd;
392 resp.max_qp_rd_atom = attr.max_qp_rd_atom;
393 resp.max_ee_rd_atom = attr.max_ee_rd_atom;
394 resp.max_res_rd_atom = attr.max_res_rd_atom;
395 resp.max_qp_init_rd_atom = attr.max_qp_init_rd_atom;
396 resp.max_ee_init_rd_atom = attr.max_ee_init_rd_atom;
397 resp.atomic_cap = attr.atomic_cap;
398 resp.max_ee = attr.max_ee;
399 resp.max_rdd = attr.max_rdd;
400 resp.max_mw = attr.max_mw;
401 resp.max_raw_ipv6_qp = attr.max_raw_ipv6_qp;
402 resp.max_raw_ethy_qp = attr.max_raw_ethy_qp;
403 resp.max_mcast_grp = attr.max_mcast_grp;
404 resp.max_mcast_qp_attach = attr.max_mcast_qp_attach;
405 resp.max_total_mcast_qp_attach = attr.max_total_mcast_qp_attach;
406 resp.max_ah = attr.max_ah;
407 resp.max_fmr = attr.max_fmr;
408 resp.max_map_per_fmr = attr.max_map_per_fmr;
409 resp.max_srq = attr.max_srq;
410 resp.max_srq_wr = attr.max_srq_wr;
411 resp.max_srq_sge = attr.max_srq_sge;
412 resp.max_pkeys = attr.max_pkeys;
413 resp.local_ca_ack_delay = attr.local_ca_ack_delay;
414 resp.phys_port_cnt = file->device->ib_dev->phys_port_cnt;
415
416 if (copy_to_user((void __user *) (unsigned long) cmd.response,
417 &resp, sizeof resp))
418 return -EFAULT;
419
420 return in_len;
421}
422
423ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file,
424 const char __user *buf,
425 int in_len, int out_len)
426{
427 struct ib_uverbs_query_port cmd;
428 struct ib_uverbs_query_port_resp resp;
429 struct ib_port_attr attr;
430 int ret;
431
432 if (out_len < sizeof resp)
433 return -ENOSPC;
434
435 if (copy_from_user(&cmd, buf, sizeof cmd))
436 return -EFAULT;
437
438 ret = ib_query_port(file->device->ib_dev, cmd.port_num, &attr);
439 if (ret)
440 return ret;
441
442 memset(&resp, 0, sizeof resp);
443
444 resp.state = attr.state;
445 resp.max_mtu = attr.max_mtu;
446 resp.active_mtu = attr.active_mtu;
447 resp.gid_tbl_len = attr.gid_tbl_len;
448 resp.port_cap_flags = attr.port_cap_flags;
449 resp.max_msg_sz = attr.max_msg_sz;
450 resp.bad_pkey_cntr = attr.bad_pkey_cntr;
451 resp.qkey_viol_cntr = attr.qkey_viol_cntr;
452 resp.pkey_tbl_len = attr.pkey_tbl_len;
453 resp.lid = attr.lid;
454 resp.sm_lid = attr.sm_lid;
455 resp.lmc = attr.lmc;
456 resp.max_vl_num = attr.max_vl_num;
457 resp.sm_sl = attr.sm_sl;
458 resp.subnet_timeout = attr.subnet_timeout;
459 resp.init_type_reply = attr.init_type_reply;
460 resp.active_width = attr.active_width;
461 resp.active_speed = attr.active_speed;
462 resp.phys_state = attr.phys_state;
463 resp.link_layer = rdma_port_get_link_layer(file->device->ib_dev,
464 cmd.port_num);
465
466 if (copy_to_user((void __user *) (unsigned long) cmd.response,
467 &resp, sizeof resp))
468 return -EFAULT;
469
470 return in_len;
471}
472
473ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
474 const char __user *buf,
475 int in_len, int out_len)
476{
477 struct ib_uverbs_alloc_pd cmd;
478 struct ib_uverbs_alloc_pd_resp resp;
479 struct ib_udata udata;
480 struct ib_uobject *uobj;
481 struct ib_pd *pd;
482 int ret;
483
484 if (out_len < sizeof resp)
485 return -ENOSPC;
486
487 if (copy_from_user(&cmd, buf, sizeof cmd))
488 return -EFAULT;
489
490 INIT_UDATA(&udata, buf + sizeof cmd,
491 (unsigned long) cmd.response + sizeof resp,
492 in_len - sizeof cmd, out_len - sizeof resp);
493
494 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
495 if (!uobj)
496 return -ENOMEM;
497
498 init_uobj(uobj, 0, file->ucontext, &pd_lock_key);
499 down_write(&uobj->mutex);
500
501 pd = file->device->ib_dev->alloc_pd(file->device->ib_dev,
502 file->ucontext, &udata);
503 if (IS_ERR(pd)) {
504 ret = PTR_ERR(pd);
505 goto err;
506 }
507
508 pd->device = file->device->ib_dev;
509 pd->uobject = uobj;
510 atomic_set(&pd->usecnt, 0);
511
512 uobj->object = pd;
513 ret = idr_add_uobj(&ib_uverbs_pd_idr, uobj);
514 if (ret)
515 goto err_idr;
516
517 memset(&resp, 0, sizeof resp);
518 resp.pd_handle = uobj->id;
519
520 if (copy_to_user((void __user *) (unsigned long) cmd.response,
521 &resp, sizeof resp)) {
522 ret = -EFAULT;
523 goto err_copy;
524 }
525
526 mutex_lock(&file->mutex);
527 list_add_tail(&uobj->list, &file->ucontext->pd_list);
528 mutex_unlock(&file->mutex);
529
530 uobj->live = 1;
531
532 up_write(&uobj->mutex);
533
534 return in_len;
535
536err_copy:
537 idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
538
539err_idr:
540 ib_dealloc_pd(pd);
541
542err:
543 put_uobj_write(uobj);
544 return ret;
545}
546
547ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
548 const char __user *buf,
549 int in_len, int out_len)
550{
551 struct ib_uverbs_dealloc_pd cmd;
552 struct ib_uobject *uobj;
553 int ret;
554
555 if (copy_from_user(&cmd, buf, sizeof cmd))
556 return -EFAULT;
557
558 uobj = idr_write_uobj(&ib_uverbs_pd_idr, cmd.pd_handle, file->ucontext);
559 if (!uobj)
560 return -EINVAL;
561
562 ret = ib_dealloc_pd(uobj->object);
563 if (!ret)
564 uobj->live = 0;
565
566 put_uobj_write(uobj);
567
568 if (ret)
569 return ret;
570
571 idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
572
573 mutex_lock(&file->mutex);
574 list_del(&uobj->list);
575 mutex_unlock(&file->mutex);
576
577 put_uobj(uobj);
578
579 return in_len;
580}
581
582ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
583 const char __user *buf, int in_len,
584 int out_len)
585{
586 struct ib_uverbs_reg_mr cmd;
587 struct ib_uverbs_reg_mr_resp resp;
588 struct ib_udata udata;
589 struct ib_uobject *uobj;
590 struct ib_pd *pd;
591 struct ib_mr *mr;
592 int ret;
593
594 if (out_len < sizeof resp)
595 return -ENOSPC;
596
597 if (copy_from_user(&cmd, buf, sizeof cmd))
598 return -EFAULT;
599
600 INIT_UDATA(&udata, buf + sizeof cmd,
601 (unsigned long) cmd.response + sizeof resp,
602 in_len - sizeof cmd, out_len - sizeof resp);
603
604 if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
605 return -EINVAL;
606
607
608
609
610
611 if (cmd.access_flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) &&
612 !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE))
613 return -EINVAL;
614
615 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
616 if (!uobj)
617 return -ENOMEM;
618
619 init_uobj(uobj, 0, file->ucontext, &mr_lock_key);
620 down_write(&uobj->mutex);
621
622 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
623 if (!pd) {
624 ret = -EINVAL;
625 goto err_free;
626 }
627
628 mr = pd->device->reg_user_mr(pd, cmd.start, cmd.length, cmd.hca_va,
629 cmd.access_flags, &udata);
630 if (IS_ERR(mr)) {
631 ret = PTR_ERR(mr);
632 goto err_put;
633 }
634
635 mr->device = pd->device;
636 mr->pd = pd;
637 mr->uobject = uobj;
638 atomic_inc(&pd->usecnt);
639 atomic_set(&mr->usecnt, 0);
640
641 uobj->object = mr;
642 ret = idr_add_uobj(&ib_uverbs_mr_idr, uobj);
643 if (ret)
644 goto err_unreg;
645
646 memset(&resp, 0, sizeof resp);
647 resp.lkey = mr->lkey;
648 resp.rkey = mr->rkey;
649 resp.mr_handle = uobj->id;
650
651 if (copy_to_user((void __user *) (unsigned long) cmd.response,
652 &resp, sizeof resp)) {
653 ret = -EFAULT;
654 goto err_copy;
655 }
656
657 put_pd_read(pd);
658
659 mutex_lock(&file->mutex);
660 list_add_tail(&uobj->list, &file->ucontext->mr_list);
661 mutex_unlock(&file->mutex);
662
663 uobj->live = 1;
664
665 up_write(&uobj->mutex);
666
667 return in_len;
668
669err_copy:
670 idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
671
672err_unreg:
673 ib_dereg_mr(mr);
674
675err_put:
676 put_pd_read(pd);
677
678err_free:
679 put_uobj_write(uobj);
680 return ret;
681}
682
683ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
684 const char __user *buf, int in_len,
685 int out_len)
686{
687 struct ib_uverbs_dereg_mr cmd;
688 struct ib_mr *mr;
689 struct ib_uobject *uobj;
690 int ret = -EINVAL;
691
692 if (copy_from_user(&cmd, buf, sizeof cmd))
693 return -EFAULT;
694
695 uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle, file->ucontext);
696 if (!uobj)
697 return -EINVAL;
698
699 mr = uobj->object;
700
701 ret = ib_dereg_mr(mr);
702 if (!ret)
703 uobj->live = 0;
704
705 put_uobj_write(uobj);
706
707 if (ret)
708 return ret;
709
710 idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
711
712 mutex_lock(&file->mutex);
713 list_del(&uobj->list);
714 mutex_unlock(&file->mutex);
715
716 put_uobj(uobj);
717
718 return in_len;
719}
720
721ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
722 const char __user *buf, int in_len,
723 int out_len)
724{
725 struct ib_uverbs_create_comp_channel cmd;
726 struct ib_uverbs_create_comp_channel_resp resp;
727 struct file *filp;
728 int ret;
729
730 if (out_len < sizeof resp)
731 return -ENOSPC;
732
733 if (copy_from_user(&cmd, buf, sizeof cmd))
734 return -EFAULT;
735
736 ret = get_unused_fd();
737 if (ret < 0)
738 return ret;
739 resp.fd = ret;
740
741 filp = ib_uverbs_alloc_event_file(file, 0);
742 if (IS_ERR(filp)) {
743 put_unused_fd(resp.fd);
744 return PTR_ERR(filp);
745 }
746
747 if (copy_to_user((void __user *) (unsigned long) cmd.response,
748 &resp, sizeof resp)) {
749 put_unused_fd(resp.fd);
750 fput(filp);
751 return -EFAULT;
752 }
753
754 fd_install(resp.fd, filp);
755 return in_len;
756}
757
758ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
759 const char __user *buf, int in_len,
760 int out_len)
761{
762 struct ib_uverbs_create_cq cmd;
763 struct ib_uverbs_create_cq_resp resp;
764 struct ib_udata udata;
765 struct ib_ucq_object *obj;
766 struct ib_uverbs_event_file *ev_file = NULL;
767 struct ib_cq *cq;
768 int ret;
769
770 if (out_len < sizeof resp)
771 return -ENOSPC;
772
773 if (copy_from_user(&cmd, buf, sizeof cmd))
774 return -EFAULT;
775
776 INIT_UDATA(&udata, buf + sizeof cmd,
777 (unsigned long) cmd.response + sizeof resp,
778 in_len - sizeof cmd, out_len - sizeof resp);
779
780 if (cmd.comp_vector >= file->device->num_comp_vectors)
781 return -EINVAL;
782
783 obj = kmalloc(sizeof *obj, GFP_KERNEL);
784 if (!obj)
785 return -ENOMEM;
786
787 init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_key);
788 down_write(&obj->uobject.mutex);
789
790 if (cmd.comp_channel >= 0) {
791 ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
792 if (!ev_file) {
793 ret = -EINVAL;
794 goto err;
795 }
796 }
797
798 obj->uverbs_file = file;
799 obj->comp_events_reported = 0;
800 obj->async_events_reported = 0;
801 INIT_LIST_HEAD(&obj->comp_list);
802 INIT_LIST_HEAD(&obj->async_list);
803
804 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
805 cmd.comp_vector,
806 file->ucontext, &udata);
807 if (IS_ERR(cq)) {
808 ret = PTR_ERR(cq);
809 goto err_file;
810 }
811
812 cq->device = file->device->ib_dev;
813 cq->uobject = &obj->uobject;
814 cq->comp_handler = ib_uverbs_comp_handler;
815 cq->event_handler = ib_uverbs_cq_event_handler;
816 cq->cq_context = ev_file;
817 atomic_set(&cq->usecnt, 0);
818
819 obj->uobject.object = cq;
820 ret = idr_add_uobj(&ib_uverbs_cq_idr, &obj->uobject);
821 if (ret)
822 goto err_free;
823
824 memset(&resp, 0, sizeof resp);
825 resp.cq_handle = obj->uobject.id;
826 resp.cqe = cq->cqe;
827
828 if (copy_to_user((void __user *) (unsigned long) cmd.response,
829 &resp, sizeof resp)) {
830 ret = -EFAULT;
831 goto err_copy;
832 }
833
834 mutex_lock(&file->mutex);
835 list_add_tail(&obj->uobject.list, &file->ucontext->cq_list);
836 mutex_unlock(&file->mutex);
837
838 obj->uobject.live = 1;
839
840 up_write(&obj->uobject.mutex);
841
842 return in_len;
843
844err_copy:
845 idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject);
846
847err_free:
848 ib_destroy_cq(cq);
849
850err_file:
851 if (ev_file)
852 ib_uverbs_release_ucq(file, ev_file, obj);
853
854err:
855 put_uobj_write(&obj->uobject);
856 return ret;
857}
858
859ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
860 const char __user *buf, int in_len,
861 int out_len)
862{
863 struct ib_uverbs_resize_cq cmd;
864 struct ib_uverbs_resize_cq_resp resp;
865 struct ib_udata udata;
866 struct ib_cq *cq;
867 int ret = -EINVAL;
868
869 if (copy_from_user(&cmd, buf, sizeof cmd))
870 return -EFAULT;
871
872 INIT_UDATA(&udata, buf + sizeof cmd,
873 (unsigned long) cmd.response + sizeof resp,
874 in_len - sizeof cmd, out_len - sizeof resp);
875
876 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
877 if (!cq)
878 return -EINVAL;
879
880 ret = cq->device->resize_cq(cq, cmd.cqe, &udata);
881 if (ret)
882 goto out;
883
884 resp.cqe = cq->cqe;
885
886 if (copy_to_user((void __user *) (unsigned long) cmd.response,
887 &resp, sizeof resp.cqe))
888 ret = -EFAULT;
889
890out:
891 put_cq_read(cq);
892
893 return ret ? ret : in_len;
894}
895
896static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
897{
898 struct ib_uverbs_wc tmp;
899
900 tmp.wr_id = wc->wr_id;
901 tmp.status = wc->status;
902 tmp.opcode = wc->opcode;
903 tmp.vendor_err = wc->vendor_err;
904 tmp.byte_len = wc->byte_len;
905 tmp.ex.imm_data = (__u32 __force) wc->ex.imm_data;
906 tmp.qp_num = wc->qp->qp_num;
907 tmp.src_qp = wc->src_qp;
908 tmp.wc_flags = wc->wc_flags;
909 tmp.pkey_index = wc->pkey_index;
910 tmp.slid = wc->slid;
911 tmp.sl = wc->sl;
912 tmp.dlid_path_bits = wc->dlid_path_bits;
913 tmp.port_num = wc->port_num;
914 tmp.reserved = 0;
915
916 if (copy_to_user(dest, &tmp, sizeof tmp))
917 return -EFAULT;
918
919 return 0;
920}
921
922ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
923 const char __user *buf, int in_len,
924 int out_len)
925{
926 struct ib_uverbs_poll_cq cmd;
927 struct ib_uverbs_poll_cq_resp resp;
928 u8 __user *header_ptr;
929 u8 __user *data_ptr;
930 struct ib_cq *cq;
931 struct ib_wc wc;
932 int ret;
933
934 if (copy_from_user(&cmd, buf, sizeof cmd))
935 return -EFAULT;
936
937 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
938 if (!cq)
939 return -EINVAL;
940
941
942 header_ptr = (void __user *)(unsigned long) cmd.response;
943 data_ptr = header_ptr + sizeof resp;
944
945 memset(&resp, 0, sizeof resp);
946 while (resp.count < cmd.ne) {
947 ret = ib_poll_cq(cq, 1, &wc);
948 if (ret < 0)
949 goto out_put;
950 if (!ret)
951 break;
952
953 ret = copy_wc_to_user(data_ptr, &wc);
954 if (ret)
955 goto out_put;
956
957 data_ptr += sizeof(struct ib_uverbs_wc);
958 ++resp.count;
959 }
960
961 if (copy_to_user(header_ptr, &resp, sizeof resp)) {
962 ret = -EFAULT;
963 goto out_put;
964 }
965
966 ret = in_len;
967
968out_put:
969 put_cq_read(cq);
970 return ret;
971}
972
973ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
974 const char __user *buf, int in_len,
975 int out_len)
976{
977 struct ib_uverbs_req_notify_cq cmd;
978 struct ib_cq *cq;
979
980 if (copy_from_user(&cmd, buf, sizeof cmd))
981 return -EFAULT;
982
983 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
984 if (!cq)
985 return -EINVAL;
986
987 ib_req_notify_cq(cq, cmd.solicited_only ?
988 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
989
990 put_cq_read(cq);
991
992 return in_len;
993}
994
995ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
996 const char __user *buf, int in_len,
997 int out_len)
998{
999 struct ib_uverbs_destroy_cq cmd;
1000 struct ib_uverbs_destroy_cq_resp resp;
1001 struct ib_uobject *uobj;
1002 struct ib_cq *cq;
1003 struct ib_ucq_object *obj;
1004 struct ib_uverbs_event_file *ev_file;
1005 int ret = -EINVAL;
1006
1007 if (copy_from_user(&cmd, buf, sizeof cmd))
1008 return -EFAULT;
1009
1010 uobj = idr_write_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
1011 if (!uobj)
1012 return -EINVAL;
1013 cq = uobj->object;
1014 ev_file = cq->cq_context;
1015 obj = container_of(cq->uobject, struct ib_ucq_object, uobject);
1016
1017 ret = ib_destroy_cq(cq);
1018 if (!ret)
1019 uobj->live = 0;
1020
1021 put_uobj_write(uobj);
1022
1023 if (ret)
1024 return ret;
1025
1026 idr_remove_uobj(&ib_uverbs_cq_idr, uobj);
1027
1028 mutex_lock(&file->mutex);
1029 list_del(&uobj->list);
1030 mutex_unlock(&file->mutex);
1031
1032 ib_uverbs_release_ucq(file, ev_file, obj);
1033
1034 memset(&resp, 0, sizeof resp);
1035 resp.comp_events_reported = obj->comp_events_reported;
1036 resp.async_events_reported = obj->async_events_reported;
1037
1038 put_uobj(uobj);
1039
1040 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1041 &resp, sizeof resp))
1042 return -EFAULT;
1043
1044 return in_len;
1045}
1046
1047ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
1048 const char __user *buf, int in_len,
1049 int out_len)
1050{
1051 struct ib_uverbs_create_qp cmd;
1052 struct ib_uverbs_create_qp_resp resp;
1053 struct ib_udata udata;
1054 struct ib_uqp_object *obj;
1055 struct ib_pd *pd;
1056 struct ib_cq *scq, *rcq;
1057 struct ib_srq *srq;
1058 struct ib_qp *qp;
1059 struct ib_qp_init_attr attr;
1060 int ret;
1061
1062 if (out_len < sizeof resp)
1063 return -ENOSPC;
1064
1065 if (copy_from_user(&cmd, buf, sizeof cmd))
1066 return -EFAULT;
1067
1068 INIT_UDATA(&udata, buf + sizeof cmd,
1069 (unsigned long) cmd.response + sizeof resp,
1070 in_len - sizeof cmd, out_len - sizeof resp);
1071
1072 obj = kmalloc(sizeof *obj, GFP_KERNEL);
1073 if (!obj)
1074 return -ENOMEM;
1075
1076 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
1077 down_write(&obj->uevent.uobject.mutex);
1078
1079 srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
1080 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
1081 scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
1082 rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
1083 scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
1084
1085 if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
1086 ret = -EINVAL;
1087 goto err_put;
1088 }
1089
1090 attr.event_handler = ib_uverbs_qp_event_handler;
1091 attr.qp_context = file;
1092 attr.send_cq = scq;
1093 attr.recv_cq = rcq;
1094 attr.srq = srq;
1095 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
1096 attr.qp_type = cmd.qp_type;
1097 attr.create_flags = 0;
1098
1099 attr.cap.max_send_wr = cmd.max_send_wr;
1100 attr.cap.max_recv_wr = cmd.max_recv_wr;
1101 attr.cap.max_send_sge = cmd.max_send_sge;
1102 attr.cap.max_recv_sge = cmd.max_recv_sge;
1103 attr.cap.max_inline_data = cmd.max_inline_data;
1104
1105 obj->uevent.events_reported = 0;
1106 INIT_LIST_HEAD(&obj->uevent.event_list);
1107 INIT_LIST_HEAD(&obj->mcast_list);
1108
1109 qp = pd->device->create_qp(pd, &attr, &udata);
1110 if (IS_ERR(qp)) {
1111 ret = PTR_ERR(qp);
1112 goto err_put;
1113 }
1114
1115 qp->device = pd->device;
1116 qp->pd = pd;
1117 qp->send_cq = attr.send_cq;
1118 qp->recv_cq = attr.recv_cq;
1119 qp->srq = attr.srq;
1120 qp->uobject = &obj->uevent.uobject;
1121 qp->event_handler = attr.event_handler;
1122 qp->qp_context = attr.qp_context;
1123 qp->qp_type = attr.qp_type;
1124 atomic_inc(&pd->usecnt);
1125 atomic_inc(&attr.send_cq->usecnt);
1126 atomic_inc(&attr.recv_cq->usecnt);
1127 if (attr.srq)
1128 atomic_inc(&attr.srq->usecnt);
1129
1130 obj->uevent.uobject.object = qp;
1131 ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
1132 if (ret)
1133 goto err_destroy;
1134
1135 memset(&resp, 0, sizeof resp);
1136 resp.qpn = qp->qp_num;
1137 resp.qp_handle = obj->uevent.uobject.id;
1138 resp.max_recv_sge = attr.cap.max_recv_sge;
1139 resp.max_send_sge = attr.cap.max_send_sge;
1140 resp.max_recv_wr = attr.cap.max_recv_wr;
1141 resp.max_send_wr = attr.cap.max_send_wr;
1142 resp.max_inline_data = attr.cap.max_inline_data;
1143
1144 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1145 &resp, sizeof resp)) {
1146 ret = -EFAULT;
1147 goto err_copy;
1148 }
1149
1150 put_pd_read(pd);
1151 put_cq_read(scq);
1152 if (rcq != scq)
1153 put_cq_read(rcq);
1154 if (srq)
1155 put_srq_read(srq);
1156
1157 mutex_lock(&file->mutex);
1158 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
1159 mutex_unlock(&file->mutex);
1160
1161 obj->uevent.uobject.live = 1;
1162
1163 up_write(&obj->uevent.uobject.mutex);
1164
1165 return in_len;
1166
1167err_copy:
1168 idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
1169
1170err_destroy:
1171 ib_destroy_qp(qp);
1172
1173err_put:
1174 if (pd)
1175 put_pd_read(pd);
1176 if (scq)
1177 put_cq_read(scq);
1178 if (rcq && rcq != scq)
1179 put_cq_read(rcq);
1180 if (srq)
1181 put_srq_read(srq);
1182
1183 put_uobj_write(&obj->uevent.uobject);
1184 return ret;
1185}
1186
1187ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
1188 const char __user *buf, int in_len,
1189 int out_len)
1190{
1191 struct ib_uverbs_query_qp cmd;
1192 struct ib_uverbs_query_qp_resp resp;
1193 struct ib_qp *qp;
1194 struct ib_qp_attr *attr;
1195 struct ib_qp_init_attr *init_attr;
1196 int ret;
1197
1198 if (copy_from_user(&cmd, buf, sizeof cmd))
1199 return -EFAULT;
1200
1201 attr = kmalloc(sizeof *attr, GFP_KERNEL);
1202 init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL);
1203 if (!attr || !init_attr) {
1204 ret = -ENOMEM;
1205 goto out;
1206 }
1207
1208 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
1209 if (!qp) {
1210 ret = -EINVAL;
1211 goto out;
1212 }
1213
1214 ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr);
1215
1216 put_qp_read(qp);
1217
1218 if (ret)
1219 goto out;
1220
1221 memset(&resp, 0, sizeof resp);
1222
1223 resp.qp_state = attr->qp_state;
1224 resp.cur_qp_state = attr->cur_qp_state;
1225 resp.path_mtu = attr->path_mtu;
1226 resp.path_mig_state = attr->path_mig_state;
1227 resp.qkey = attr->qkey;
1228 resp.rq_psn = attr->rq_psn;
1229 resp.sq_psn = attr->sq_psn;
1230 resp.dest_qp_num = attr->dest_qp_num;
1231 resp.qp_access_flags = attr->qp_access_flags;
1232 resp.pkey_index = attr->pkey_index;
1233 resp.alt_pkey_index = attr->alt_pkey_index;
1234 resp.sq_draining = attr->sq_draining;
1235 resp.max_rd_atomic = attr->max_rd_atomic;
1236 resp.max_dest_rd_atomic = attr->max_dest_rd_atomic;
1237 resp.min_rnr_timer = attr->min_rnr_timer;
1238 resp.port_num = attr->port_num;
1239 resp.timeout = attr->timeout;
1240 resp.retry_cnt = attr->retry_cnt;
1241 resp.rnr_retry = attr->rnr_retry;
1242 resp.alt_port_num = attr->alt_port_num;
1243 resp.alt_timeout = attr->alt_timeout;
1244
1245 memcpy(resp.dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
1246 resp.dest.flow_label = attr->ah_attr.grh.flow_label;
1247 resp.dest.sgid_index = attr->ah_attr.grh.sgid_index;
1248 resp.dest.hop_limit = attr->ah_attr.grh.hop_limit;
1249 resp.dest.traffic_class = attr->ah_attr.grh.traffic_class;
1250 resp.dest.dlid = attr->ah_attr.dlid;
1251 resp.dest.sl = attr->ah_attr.sl;
1252 resp.dest.src_path_bits = attr->ah_attr.src_path_bits;
1253 resp.dest.static_rate = attr->ah_attr.static_rate;
1254 resp.dest.is_global = !!(attr->ah_attr.ah_flags & IB_AH_GRH);
1255 resp.dest.port_num = attr->ah_attr.port_num;
1256
1257 memcpy(resp.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
1258 resp.alt_dest.flow_label = attr->alt_ah_attr.grh.flow_label;
1259 resp.alt_dest.sgid_index = attr->alt_ah_attr.grh.sgid_index;
1260 resp.alt_dest.hop_limit = attr->alt_ah_attr.grh.hop_limit;
1261 resp.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
1262 resp.alt_dest.dlid = attr->alt_ah_attr.dlid;
1263 resp.alt_dest.sl = attr->alt_ah_attr.sl;
1264 resp.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
1265 resp.alt_dest.static_rate = attr->alt_ah_attr.static_rate;
1266 resp.alt_dest.is_global = !!(attr->alt_ah_attr.ah_flags & IB_AH_GRH);
1267 resp.alt_dest.port_num = attr->alt_ah_attr.port_num;
1268
1269 resp.max_send_wr = init_attr->cap.max_send_wr;
1270 resp.max_recv_wr = init_attr->cap.max_recv_wr;
1271 resp.max_send_sge = init_attr->cap.max_send_sge;
1272 resp.max_recv_sge = init_attr->cap.max_recv_sge;
1273 resp.max_inline_data = init_attr->cap.max_inline_data;
1274 resp.sq_sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
1275
1276 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1277 &resp, sizeof resp))
1278 ret = -EFAULT;
1279
1280out:
1281 kfree(attr);
1282 kfree(init_attr);
1283
1284 return ret ? ret : in_len;
1285}
1286
1287ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
1288 const char __user *buf, int in_len,
1289 int out_len)
1290{
1291 struct ib_uverbs_modify_qp cmd;
1292 struct ib_udata udata;
1293 struct ib_qp *qp;
1294 struct ib_qp_attr *attr;
1295 int ret;
1296
1297 if (copy_from_user(&cmd, buf, sizeof cmd))
1298 return -EFAULT;
1299
1300 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
1301 out_len);
1302
1303 attr = kmalloc(sizeof *attr, GFP_KERNEL);
1304 if (!attr)
1305 return -ENOMEM;
1306
1307 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
1308 if (!qp) {
1309 ret = -EINVAL;
1310 goto out;
1311 }
1312
1313 attr->qp_state = cmd.qp_state;
1314 attr->cur_qp_state = cmd.cur_qp_state;
1315 attr->path_mtu = cmd.path_mtu;
1316 attr->path_mig_state = cmd.path_mig_state;
1317 attr->qkey = cmd.qkey;
1318 attr->rq_psn = cmd.rq_psn;
1319 attr->sq_psn = cmd.sq_psn;
1320 attr->dest_qp_num = cmd.dest_qp_num;
1321 attr->qp_access_flags = cmd.qp_access_flags;
1322 attr->pkey_index = cmd.pkey_index;
1323 attr->alt_pkey_index = cmd.alt_pkey_index;
1324 attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
1325 attr->max_rd_atomic = cmd.max_rd_atomic;
1326 attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic;
1327 attr->min_rnr_timer = cmd.min_rnr_timer;
1328 attr->port_num = cmd.port_num;
1329 attr->timeout = cmd.timeout;
1330 attr->retry_cnt = cmd.retry_cnt;
1331 attr->rnr_retry = cmd.rnr_retry;
1332 attr->alt_port_num = cmd.alt_port_num;
1333 attr->alt_timeout = cmd.alt_timeout;
1334
1335 memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16);
1336 attr->ah_attr.grh.flow_label = cmd.dest.flow_label;
1337 attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index;
1338 attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit;
1339 attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class;
1340 attr->ah_attr.dlid = cmd.dest.dlid;
1341 attr->ah_attr.sl = cmd.dest.sl;
1342 attr->ah_attr.src_path_bits = cmd.dest.src_path_bits;
1343 attr->ah_attr.static_rate = cmd.dest.static_rate;
1344 attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0;
1345 attr->ah_attr.port_num = cmd.dest.port_num;
1346
1347 memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16);
1348 attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label;
1349 attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index;
1350 attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit;
1351 attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class;
1352 attr->alt_ah_attr.dlid = cmd.alt_dest.dlid;
1353 attr->alt_ah_attr.sl = cmd.alt_dest.sl;
1354 attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits;
1355 attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate;
1356 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
1357 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
1358
1359 ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
1360
1361 put_qp_read(qp);
1362
1363 if (ret)
1364 goto out;
1365
1366 ret = in_len;
1367
1368out:
1369 kfree(attr);
1370
1371 return ret;
1372}
1373
1374ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
1375 const char __user *buf, int in_len,
1376 int out_len)
1377{
1378 struct ib_uverbs_destroy_qp cmd;
1379 struct ib_uverbs_destroy_qp_resp resp;
1380 struct ib_uobject *uobj;
1381 struct ib_qp *qp;
1382 struct ib_uqp_object *obj;
1383 int ret = -EINVAL;
1384
1385 if (copy_from_user(&cmd, buf, sizeof cmd))
1386 return -EFAULT;
1387
1388 memset(&resp, 0, sizeof resp);
1389
1390 uobj = idr_write_uobj(&ib_uverbs_qp_idr, cmd.qp_handle, file->ucontext);
1391 if (!uobj)
1392 return -EINVAL;
1393 qp = uobj->object;
1394 obj = container_of(uobj, struct ib_uqp_object, uevent.uobject);
1395
1396 if (!list_empty(&obj->mcast_list)) {
1397 put_uobj_write(uobj);
1398 return -EBUSY;
1399 }
1400
1401 ret = ib_destroy_qp(qp);
1402 if (!ret)
1403 uobj->live = 0;
1404
1405 put_uobj_write(uobj);
1406
1407 if (ret)
1408 return ret;
1409
1410 idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
1411
1412 mutex_lock(&file->mutex);
1413 list_del(&uobj->list);
1414 mutex_unlock(&file->mutex);
1415
1416 ib_uverbs_release_uevent(file, &obj->uevent);
1417
1418 resp.events_reported = obj->uevent.events_reported;
1419
1420 put_uobj(uobj);
1421
1422 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1423 &resp, sizeof resp))
1424 return -EFAULT;
1425
1426 return in_len;
1427}
1428
1429ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
1430 const char __user *buf, int in_len,
1431 int out_len)
1432{
1433 struct ib_uverbs_post_send cmd;
1434 struct ib_uverbs_post_send_resp resp;
1435 struct ib_uverbs_send_wr *user_wr;
1436 struct ib_send_wr *wr = NULL, *last, *next, *bad_wr;
1437 struct ib_qp *qp;
1438 int i, sg_ind;
1439 int is_ud;
1440 ssize_t ret = -EINVAL;
1441
1442 if (copy_from_user(&cmd, buf, sizeof cmd))
1443 return -EFAULT;
1444
1445 if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count +
1446 cmd.sge_count * sizeof (struct ib_uverbs_sge))
1447 return -EINVAL;
1448
1449 if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr))
1450 return -EINVAL;
1451
1452 user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL);
1453 if (!user_wr)
1454 return -ENOMEM;
1455
1456 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
1457 if (!qp)
1458 goto out;
1459
1460 is_ud = qp->qp_type == IB_QPT_UD;
1461 sg_ind = 0;
1462 last = NULL;
1463 for (i = 0; i < cmd.wr_count; ++i) {
1464 if (copy_from_user(user_wr,
1465 buf + sizeof cmd + i * cmd.wqe_size,
1466 cmd.wqe_size)) {
1467 ret = -EFAULT;
1468 goto out_put;
1469 }
1470
1471 if (user_wr->num_sge + sg_ind > cmd.sge_count) {
1472 ret = -EINVAL;
1473 goto out_put;
1474 }
1475
1476 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
1477 user_wr->num_sge * sizeof (struct ib_sge),
1478 GFP_KERNEL);
1479 if (!next) {
1480 ret = -ENOMEM;
1481 goto out_put;
1482 }
1483
1484 if (!last)
1485 wr = next;
1486 else
1487 last->next = next;
1488 last = next;
1489
1490 next->next = NULL;
1491 next->wr_id = user_wr->wr_id;
1492 next->num_sge = user_wr->num_sge;
1493 next->opcode = user_wr->opcode;
1494 next->send_flags = user_wr->send_flags;
1495
1496 if (is_ud) {
1497 next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
1498 file->ucontext);
1499 if (!next->wr.ud.ah) {
1500 ret = -EINVAL;
1501 goto out_put;
1502 }
1503 next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn;
1504 next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
1505 } else {
1506 switch (next->opcode) {
1507 case IB_WR_RDMA_WRITE_WITH_IMM:
1508 next->ex.imm_data =
1509 (__be32 __force) user_wr->ex.imm_data;
1510 case IB_WR_RDMA_WRITE:
1511 case IB_WR_RDMA_READ:
1512 next->wr.rdma.remote_addr =
1513 user_wr->wr.rdma.remote_addr;
1514 next->wr.rdma.rkey =
1515 user_wr->wr.rdma.rkey;
1516 break;
1517 case IB_WR_SEND_WITH_IMM:
1518 next->ex.imm_data =
1519 (__be32 __force) user_wr->ex.imm_data;
1520 break;
1521 case IB_WR_SEND_WITH_INV:
1522 next->ex.invalidate_rkey =
1523 user_wr->ex.invalidate_rkey;
1524 break;
1525 case IB_WR_ATOMIC_CMP_AND_SWP:
1526 case IB_WR_ATOMIC_FETCH_AND_ADD:
1527 next->wr.atomic.remote_addr =
1528 user_wr->wr.atomic.remote_addr;
1529 next->wr.atomic.compare_add =
1530 user_wr->wr.atomic.compare_add;
1531 next->wr.atomic.swap = user_wr->wr.atomic.swap;
1532 next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
1533 break;
1534 default:
1535 break;
1536 }
1537 }
1538
1539 if (next->num_sge) {
1540 next->sg_list = (void *) next +
1541 ALIGN(sizeof *next, sizeof (struct ib_sge));
1542 if (copy_from_user(next->sg_list,
1543 buf + sizeof cmd +
1544 cmd.wr_count * cmd.wqe_size +
1545 sg_ind * sizeof (struct ib_sge),
1546 next->num_sge * sizeof (struct ib_sge))) {
1547 ret = -EFAULT;
1548 goto out_put;
1549 }
1550 sg_ind += next->num_sge;
1551 } else
1552 next->sg_list = NULL;
1553 }
1554
1555 resp.bad_wr = 0;
1556 ret = qp->device->post_send(qp, wr, &bad_wr);
1557 if (ret)
1558 for (next = wr; next; next = next->next) {
1559 ++resp.bad_wr;
1560 if (next == bad_wr)
1561 break;
1562 }
1563
1564 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1565 &resp, sizeof resp))
1566 ret = -EFAULT;
1567
1568out_put:
1569 put_qp_read(qp);
1570
1571 while (wr) {
1572 if (is_ud && wr->wr.ud.ah)
1573 put_ah_read(wr->wr.ud.ah);
1574 next = wr->next;
1575 kfree(wr);
1576 wr = next;
1577 }
1578
1579out:
1580 kfree(user_wr);
1581
1582 return ret ? ret : in_len;
1583}
1584
1585static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf,
1586 int in_len,
1587 u32 wr_count,
1588 u32 sge_count,
1589 u32 wqe_size)
1590{
1591 struct ib_uverbs_recv_wr *user_wr;
1592 struct ib_recv_wr *wr = NULL, *last, *next;
1593 int sg_ind;
1594 int i;
1595 int ret;
1596
1597 if (in_len < wqe_size * wr_count +
1598 sge_count * sizeof (struct ib_uverbs_sge))
1599 return ERR_PTR(-EINVAL);
1600
1601 if (wqe_size < sizeof (struct ib_uverbs_recv_wr))
1602 return ERR_PTR(-EINVAL);
1603
1604 user_wr = kmalloc(wqe_size, GFP_KERNEL);
1605 if (!user_wr)
1606 return ERR_PTR(-ENOMEM);
1607
1608 sg_ind = 0;
1609 last = NULL;
1610 for (i = 0; i < wr_count; ++i) {
1611 if (copy_from_user(user_wr, buf + i * wqe_size,
1612 wqe_size)) {
1613 ret = -EFAULT;
1614 goto err;
1615 }
1616
1617 if (user_wr->num_sge + sg_ind > sge_count) {
1618 ret = -EINVAL;
1619 goto err;
1620 }
1621
1622 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
1623 user_wr->num_sge * sizeof (struct ib_sge),
1624 GFP_KERNEL);
1625 if (!next) {
1626 ret = -ENOMEM;
1627 goto err;
1628 }
1629
1630 if (!last)
1631 wr = next;
1632 else
1633 last->next = next;
1634 last = next;
1635
1636 next->next = NULL;
1637 next->wr_id = user_wr->wr_id;
1638 next->num_sge = user_wr->num_sge;
1639
1640 if (next->num_sge) {
1641 next->sg_list = (void *) next +
1642 ALIGN(sizeof *next, sizeof (struct ib_sge));
1643 if (copy_from_user(next->sg_list,
1644 buf + wr_count * wqe_size +
1645 sg_ind * sizeof (struct ib_sge),
1646 next->num_sge * sizeof (struct ib_sge))) {
1647 ret = -EFAULT;
1648 goto err;
1649 }
1650 sg_ind += next->num_sge;
1651 } else
1652 next->sg_list = NULL;
1653 }
1654
1655 kfree(user_wr);
1656 return wr;
1657
1658err:
1659 kfree(user_wr);
1660
1661 while (wr) {
1662 next = wr->next;
1663 kfree(wr);
1664 wr = next;
1665 }
1666
1667 return ERR_PTR(ret);
1668}
1669
1670ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
1671 const char __user *buf, int in_len,
1672 int out_len)
1673{
1674 struct ib_uverbs_post_recv cmd;
1675 struct ib_uverbs_post_recv_resp resp;
1676 struct ib_recv_wr *wr, *next, *bad_wr;
1677 struct ib_qp *qp;
1678 ssize_t ret = -EINVAL;
1679
1680 if (copy_from_user(&cmd, buf, sizeof cmd))
1681 return -EFAULT;
1682
1683 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
1684 in_len - sizeof cmd, cmd.wr_count,
1685 cmd.sge_count, cmd.wqe_size);
1686 if (IS_ERR(wr))
1687 return PTR_ERR(wr);
1688
1689 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
1690 if (!qp)
1691 goto out;
1692
1693 resp.bad_wr = 0;
1694 ret = qp->device->post_recv(qp, wr, &bad_wr);
1695
1696 put_qp_read(qp);
1697
1698 if (ret)
1699 for (next = wr; next; next = next->next) {
1700 ++resp.bad_wr;
1701 if (next == bad_wr)
1702 break;
1703 }
1704
1705 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1706 &resp, sizeof resp))
1707 ret = -EFAULT;
1708
1709out:
1710 while (wr) {
1711 next = wr->next;
1712 kfree(wr);
1713 wr = next;
1714 }
1715
1716 return ret ? ret : in_len;
1717}
1718
1719ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
1720 const char __user *buf, int in_len,
1721 int out_len)
1722{
1723 struct ib_uverbs_post_srq_recv cmd;
1724 struct ib_uverbs_post_srq_recv_resp resp;
1725 struct ib_recv_wr *wr, *next, *bad_wr;
1726 struct ib_srq *srq;
1727 ssize_t ret = -EINVAL;
1728
1729 if (copy_from_user(&cmd, buf, sizeof cmd))
1730 return -EFAULT;
1731
1732 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
1733 in_len - sizeof cmd, cmd.wr_count,
1734 cmd.sge_count, cmd.wqe_size);
1735 if (IS_ERR(wr))
1736 return PTR_ERR(wr);
1737
1738 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
1739 if (!srq)
1740 goto out;
1741
1742 resp.bad_wr = 0;
1743 ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
1744
1745 put_srq_read(srq);
1746
1747 if (ret)
1748 for (next = wr; next; next = next->next) {
1749 ++resp.bad_wr;
1750 if (next == bad_wr)
1751 break;
1752 }
1753
1754 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1755 &resp, sizeof resp))
1756 ret = -EFAULT;
1757
1758out:
1759 while (wr) {
1760 next = wr->next;
1761 kfree(wr);
1762 wr = next;
1763 }
1764
1765 return ret ? ret : in_len;
1766}
1767
1768ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
1769 const char __user *buf, int in_len,
1770 int out_len)
1771{
1772 struct ib_uverbs_create_ah cmd;
1773 struct ib_uverbs_create_ah_resp resp;
1774 struct ib_uobject *uobj;
1775 struct ib_pd *pd;
1776 struct ib_ah *ah;
1777 struct ib_ah_attr attr;
1778 int ret;
1779
1780 if (out_len < sizeof resp)
1781 return -ENOSPC;
1782
1783 if (copy_from_user(&cmd, buf, sizeof cmd))
1784 return -EFAULT;
1785
1786 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
1787 if (!uobj)
1788 return -ENOMEM;
1789
1790 init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_key);
1791 down_write(&uobj->mutex);
1792
1793 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
1794 if (!pd) {
1795 ret = -EINVAL;
1796 goto err;
1797 }
1798
1799 attr.dlid = cmd.attr.dlid;
1800 attr.sl = cmd.attr.sl;
1801 attr.src_path_bits = cmd.attr.src_path_bits;
1802 attr.static_rate = cmd.attr.static_rate;
1803 attr.ah_flags = cmd.attr.is_global ? IB_AH_GRH : 0;
1804 attr.port_num = cmd.attr.port_num;
1805 attr.grh.flow_label = cmd.attr.grh.flow_label;
1806 attr.grh.sgid_index = cmd.attr.grh.sgid_index;
1807 attr.grh.hop_limit = cmd.attr.grh.hop_limit;
1808 attr.grh.traffic_class = cmd.attr.grh.traffic_class;
1809 memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
1810
1811 ah = ib_create_ah(pd, &attr);
1812 if (IS_ERR(ah)) {
1813 ret = PTR_ERR(ah);
1814 goto err_put;
1815 }
1816
1817 ah->uobject = uobj;
1818 uobj->object = ah;
1819
1820 ret = idr_add_uobj(&ib_uverbs_ah_idr, uobj);
1821 if (ret)
1822 goto err_destroy;
1823
1824 resp.ah_handle = uobj->id;
1825
1826 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1827 &resp, sizeof resp)) {
1828 ret = -EFAULT;
1829 goto err_copy;
1830 }
1831
1832 put_pd_read(pd);
1833
1834 mutex_lock(&file->mutex);
1835 list_add_tail(&uobj->list, &file->ucontext->ah_list);
1836 mutex_unlock(&file->mutex);
1837
1838 uobj->live = 1;
1839
1840 up_write(&uobj->mutex);
1841
1842 return in_len;
1843
1844err_copy:
1845 idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
1846
1847err_destroy:
1848 ib_destroy_ah(ah);
1849
1850err_put:
1851 put_pd_read(pd);
1852
1853err:
1854 put_uobj_write(uobj);
1855 return ret;
1856}
1857
1858ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
1859 const char __user *buf, int in_len, int out_len)
1860{
1861 struct ib_uverbs_destroy_ah cmd;
1862 struct ib_ah *ah;
1863 struct ib_uobject *uobj;
1864 int ret;
1865
1866 if (copy_from_user(&cmd, buf, sizeof cmd))
1867 return -EFAULT;
1868
1869 uobj = idr_write_uobj(&ib_uverbs_ah_idr, cmd.ah_handle, file->ucontext);
1870 if (!uobj)
1871 return -EINVAL;
1872 ah = uobj->object;
1873
1874 ret = ib_destroy_ah(ah);
1875 if (!ret)
1876 uobj->live = 0;
1877
1878 put_uobj_write(uobj);
1879
1880 if (ret)
1881 return ret;
1882
1883 idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
1884
1885 mutex_lock(&file->mutex);
1886 list_del(&uobj->list);
1887 mutex_unlock(&file->mutex);
1888
1889 put_uobj(uobj);
1890
1891 return in_len;
1892}
1893
1894ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
1895 const char __user *buf, int in_len,
1896 int out_len)
1897{
1898 struct ib_uverbs_attach_mcast cmd;
1899 struct ib_qp *qp;
1900 struct ib_uqp_object *obj;
1901 struct ib_uverbs_mcast_entry *mcast;
1902 int ret;
1903
1904 if (copy_from_user(&cmd, buf, sizeof cmd))
1905 return -EFAULT;
1906
1907 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
1908 if (!qp)
1909 return -EINVAL;
1910
1911 obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
1912
1913 list_for_each_entry(mcast, &obj->mcast_list, list)
1914 if (cmd.mlid == mcast->lid &&
1915 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
1916 ret = 0;
1917 goto out_put;
1918 }
1919
1920 mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
1921 if (!mcast) {
1922 ret = -ENOMEM;
1923 goto out_put;
1924 }
1925
1926 mcast->lid = cmd.mlid;
1927 memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw);
1928
1929 ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid);
1930 if (!ret)
1931 list_add_tail(&mcast->list, &obj->mcast_list);
1932 else
1933 kfree(mcast);
1934
1935out_put:
1936 put_qp_read(qp);
1937
1938 return ret ? ret : in_len;
1939}
1940
1941ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
1942 const char __user *buf, int in_len,
1943 int out_len)
1944{
1945 struct ib_uverbs_detach_mcast cmd;
1946 struct ib_uqp_object *obj;
1947 struct ib_qp *qp;
1948 struct ib_uverbs_mcast_entry *mcast;
1949 int ret = -EINVAL;
1950
1951 if (copy_from_user(&cmd, buf, sizeof cmd))
1952 return -EFAULT;
1953
1954 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
1955 if (!qp)
1956 return -EINVAL;
1957
1958 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
1959 if (ret)
1960 goto out_put;
1961
1962 obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
1963
1964 list_for_each_entry(mcast, &obj->mcast_list, list)
1965 if (cmd.mlid == mcast->lid &&
1966 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
1967 list_del(&mcast->list);
1968 kfree(mcast);
1969 break;
1970 }
1971
1972out_put:
1973 put_qp_read(qp);
1974
1975 return ret ? ret : in_len;
1976}
1977
1978ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1979 const char __user *buf, int in_len,
1980 int out_len)
1981{
1982 struct ib_uverbs_create_srq cmd;
1983 struct ib_uverbs_create_srq_resp resp;
1984 struct ib_udata udata;
1985 struct ib_uevent_object *obj;
1986 struct ib_pd *pd;
1987 struct ib_srq *srq;
1988 struct ib_srq_init_attr attr;
1989 int ret;
1990
1991 if (out_len < sizeof resp)
1992 return -ENOSPC;
1993
1994 if (copy_from_user(&cmd, buf, sizeof cmd))
1995 return -EFAULT;
1996
1997 INIT_UDATA(&udata, buf + sizeof cmd,
1998 (unsigned long) cmd.response + sizeof resp,
1999 in_len - sizeof cmd, out_len - sizeof resp);
2000
2001 obj = kmalloc(sizeof *obj, GFP_KERNEL);
2002 if (!obj)
2003 return -ENOMEM;
2004
2005 init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
2006 down_write(&obj->uobject.mutex);
2007
2008 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
2009 if (!pd) {
2010 ret = -EINVAL;
2011 goto err;
2012 }
2013
2014 attr.event_handler = ib_uverbs_srq_event_handler;
2015 attr.srq_context = file;
2016 attr.attr.max_wr = cmd.max_wr;
2017 attr.attr.max_sge = cmd.max_sge;
2018 attr.attr.srq_limit = cmd.srq_limit;
2019
2020 obj->events_reported = 0;
2021 INIT_LIST_HEAD(&obj->event_list);
2022
2023 srq = pd->device->create_srq(pd, &attr, &udata);
2024 if (IS_ERR(srq)) {
2025 ret = PTR_ERR(srq);
2026 goto err_put;
2027 }
2028
2029 srq->device = pd->device;
2030 srq->pd = pd;
2031 srq->uobject = &obj->uobject;
2032 srq->event_handler = attr.event_handler;
2033 srq->srq_context = attr.srq_context;
2034 atomic_inc(&pd->usecnt);
2035 atomic_set(&srq->usecnt, 0);
2036
2037 obj->uobject.object = srq;
2038 ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
2039 if (ret)
2040 goto err_destroy;
2041
2042 memset(&resp, 0, sizeof resp);
2043 resp.srq_handle = obj->uobject.id;
2044 resp.max_wr = attr.attr.max_wr;
2045 resp.max_sge = attr.attr.max_sge;
2046
2047 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2048 &resp, sizeof resp)) {
2049 ret = -EFAULT;
2050 goto err_copy;
2051 }
2052
2053 put_pd_read(pd);
2054
2055 mutex_lock(&file->mutex);
2056 list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
2057 mutex_unlock(&file->mutex);
2058
2059 obj->uobject.live = 1;
2060
2061 up_write(&obj->uobject.mutex);
2062
2063 return in_len;
2064
2065err_copy:
2066 idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
2067
2068err_destroy:
2069 ib_destroy_srq(srq);
2070
2071err_put:
2072 put_pd_read(pd);
2073
2074err:
2075 put_uobj_write(&obj->uobject);
2076 return ret;
2077}
2078
2079ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
2080 const char __user *buf, int in_len,
2081 int out_len)
2082{
2083 struct ib_uverbs_modify_srq cmd;
2084 struct ib_udata udata;
2085 struct ib_srq *srq;
2086 struct ib_srq_attr attr;
2087 int ret;
2088
2089 if (copy_from_user(&cmd, buf, sizeof cmd))
2090 return -EFAULT;
2091
2092 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
2093 out_len);
2094
2095 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
2096 if (!srq)
2097 return -EINVAL;
2098
2099 attr.max_wr = cmd.max_wr;
2100 attr.srq_limit = cmd.srq_limit;
2101
2102 ret = srq->device->modify_srq(srq, &attr, cmd.attr_mask, &udata);
2103
2104 put_srq_read(srq);
2105
2106 return ret ? ret : in_len;
2107}
2108
2109ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file,
2110 const char __user *buf,
2111 int in_len, int out_len)
2112{
2113 struct ib_uverbs_query_srq cmd;
2114 struct ib_uverbs_query_srq_resp resp;
2115 struct ib_srq_attr attr;
2116 struct ib_srq *srq;
2117 int ret;
2118
2119 if (out_len < sizeof resp)
2120 return -ENOSPC;
2121
2122 if (copy_from_user(&cmd, buf, sizeof cmd))
2123 return -EFAULT;
2124
2125 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
2126 if (!srq)
2127 return -EINVAL;
2128
2129 ret = ib_query_srq(srq, &attr);
2130
2131 put_srq_read(srq);
2132
2133 if (ret)
2134 return ret;
2135
2136 memset(&resp, 0, sizeof resp);
2137
2138 resp.max_wr = attr.max_wr;
2139 resp.max_sge = attr.max_sge;
2140 resp.srq_limit = attr.srq_limit;
2141
2142 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2143 &resp, sizeof resp))
2144 return -EFAULT;
2145
2146 return in_len;
2147}
2148
2149ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
2150 const char __user *buf, int in_len,
2151 int out_len)
2152{
2153 struct ib_uverbs_destroy_srq cmd;
2154 struct ib_uverbs_destroy_srq_resp resp;
2155 struct ib_uobject *uobj;
2156 struct ib_srq *srq;
2157 struct ib_uevent_object *obj;
2158 int ret = -EINVAL;
2159
2160 if (copy_from_user(&cmd, buf, sizeof cmd))
2161 return -EFAULT;
2162
2163 uobj = idr_write_uobj(&ib_uverbs_srq_idr, cmd.srq_handle, file->ucontext);
2164 if (!uobj)
2165 return -EINVAL;
2166 srq = uobj->object;
2167 obj = container_of(uobj, struct ib_uevent_object, uobject);
2168
2169 ret = ib_destroy_srq(srq);
2170 if (!ret)
2171 uobj->live = 0;
2172
2173 put_uobj_write(uobj);
2174
2175 if (ret)
2176 return ret;
2177
2178 idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
2179
2180 mutex_lock(&file->mutex);
2181 list_del(&uobj->list);
2182 mutex_unlock(&file->mutex);
2183
2184 ib_uverbs_release_uevent(file, obj);
2185
2186 memset(&resp, 0, sizeof resp);
2187 resp.events_reported = obj->events_reported;
2188
2189 put_uobj(uobj);
2190
2191 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2192 &resp, sizeof resp))
2193 ret = -EFAULT;
2194
2195 return ret ? ret : in_len;
2196}
2197