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