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