[IB] uverbs: ABI-breaking fixes for userspace verbs
[powerpc.git] / drivers / infiniband / core / uverbs_cmd.c
1 /*
2  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
3  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $
34  */
35
36 #include <linux/file.h>
37
38 #include <asm/uaccess.h>
39
40 #include "uverbs.h"
41
42 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)                       \
43         do {                                                            \
44                 (udata)->inbuf  = (void __user *) (ibuf);               \
45                 (udata)->outbuf = (void __user *) (obuf);               \
46                 (udata)->inlen  = (ilen);                               \
47                 (udata)->outlen = (olen);                               \
48         } while (0)
49
50 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
51                               const char __user *buf,
52                               int in_len, int out_len)
53 {
54         struct ib_uverbs_get_context      cmd;
55         struct ib_uverbs_get_context_resp resp;
56         struct ib_udata                   udata;
57         struct ib_device                 *ibdev = file->device->ib_dev;
58         struct ib_ucontext               *ucontext;
59         struct file                      *filp;
60         int ret;
61
62         if (out_len < sizeof resp)
63                 return -ENOSPC;
64
65         if (copy_from_user(&cmd, buf, sizeof cmd))
66                 return -EFAULT;
67
68         down(&file->mutex);
69
70         if (file->ucontext) {
71                 ret = -EINVAL;
72                 goto err;
73         }
74
75         INIT_UDATA(&udata, buf + sizeof cmd,
76                    (unsigned long) cmd.response + sizeof resp,
77                    in_len - sizeof cmd, out_len - sizeof resp);
78
79         ucontext = ibdev->alloc_ucontext(ibdev, &udata);
80         if (IS_ERR(ucontext))
81                 return PTR_ERR(file->ucontext);
82
83         ucontext->device = ibdev;
84         INIT_LIST_HEAD(&ucontext->pd_list);
85         INIT_LIST_HEAD(&ucontext->mr_list);
86         INIT_LIST_HEAD(&ucontext->mw_list);
87         INIT_LIST_HEAD(&ucontext->cq_list);
88         INIT_LIST_HEAD(&ucontext->qp_list);
89         INIT_LIST_HEAD(&ucontext->srq_list);
90         INIT_LIST_HEAD(&ucontext->ah_list);
91
92         resp.num_comp_vectors = file->device->num_comp_vectors;
93
94         filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd);
95         if (IS_ERR(filp)) {
96                 ret = PTR_ERR(filp);
97                 goto err_free;
98         }
99
100         if (copy_to_user((void __user *) (unsigned long) cmd.response,
101                          &resp, sizeof resp)) {
102                 ret = -EFAULT;
103                 goto err_file;
104         }
105
106         file->async_file = filp->private_data;
107
108         INIT_IB_EVENT_HANDLER(&file->event_handler, file->device->ib_dev,
109                               ib_uverbs_event_handler);
110         ret = ib_register_event_handler(&file->event_handler);
111         if (ret)
112                 goto err_file;
113
114         kref_get(&file->async_file->ref);
115         kref_get(&file->ref);
116         file->ucontext   = ucontext;
117
118         fd_install(resp.async_fd, filp);
119
120         up(&file->mutex);
121
122         return in_len;
123
124 err_file:
125         put_unused_fd(resp.async_fd);
126         fput(filp);
127
128 err_free:
129         ibdev->dealloc_ucontext(ucontext);
130
131 err:
132         up(&file->mutex);
133         return ret;
134 }
135
136 ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
137                                const char __user *buf,
138                                int in_len, int out_len)
139 {
140         struct ib_uverbs_query_device      cmd;
141         struct ib_uverbs_query_device_resp resp;
142         struct ib_device_attr              attr;
143         int                                ret;
144
145         if (out_len < sizeof resp)
146                 return -ENOSPC;
147
148         if (copy_from_user(&cmd, buf, sizeof cmd))
149                 return -EFAULT;
150
151         ret = ib_query_device(file->device->ib_dev, &attr);
152         if (ret)
153                 return ret;
154
155         memset(&resp, 0, sizeof resp);
156
157         resp.fw_ver                    = attr.fw_ver;
158         resp.node_guid                 = attr.node_guid;
159         resp.sys_image_guid            = attr.sys_image_guid;
160         resp.max_mr_size               = attr.max_mr_size;
161         resp.page_size_cap             = attr.page_size_cap;
162         resp.vendor_id                 = attr.vendor_id;
163         resp.vendor_part_id            = attr.vendor_part_id;
164         resp.hw_ver                    = attr.hw_ver;
165         resp.max_qp                    = attr.max_qp;
166         resp.max_qp_wr                 = attr.max_qp_wr;
167         resp.device_cap_flags          = attr.device_cap_flags;
168         resp.max_sge                   = attr.max_sge;
169         resp.max_sge_rd                = attr.max_sge_rd;
170         resp.max_cq                    = attr.max_cq;
171         resp.max_cqe                   = attr.max_cqe;
172         resp.max_mr                    = attr.max_mr;
173         resp.max_pd                    = attr.max_pd;
174         resp.max_qp_rd_atom            = attr.max_qp_rd_atom;
175         resp.max_ee_rd_atom            = attr.max_ee_rd_atom;
176         resp.max_res_rd_atom           = attr.max_res_rd_atom;
177         resp.max_qp_init_rd_atom       = attr.max_qp_init_rd_atom;
178         resp.max_ee_init_rd_atom       = attr.max_ee_init_rd_atom;
179         resp.atomic_cap                = attr.atomic_cap;
180         resp.max_ee                    = attr.max_ee;
181         resp.max_rdd                   = attr.max_rdd;
182         resp.max_mw                    = attr.max_mw;
183         resp.max_raw_ipv6_qp           = attr.max_raw_ipv6_qp;
184         resp.max_raw_ethy_qp           = attr.max_raw_ethy_qp;
185         resp.max_mcast_grp             = attr.max_mcast_grp;
186         resp.max_mcast_qp_attach       = attr.max_mcast_qp_attach;
187         resp.max_total_mcast_qp_attach = attr.max_total_mcast_qp_attach;
188         resp.max_ah                    = attr.max_ah;
189         resp.max_fmr                   = attr.max_fmr;
190         resp.max_map_per_fmr           = attr.max_map_per_fmr;
191         resp.max_srq                   = attr.max_srq;
192         resp.max_srq_wr                = attr.max_srq_wr;
193         resp.max_srq_sge               = attr.max_srq_sge;
194         resp.max_pkeys                 = attr.max_pkeys;
195         resp.local_ca_ack_delay        = attr.local_ca_ack_delay;
196         resp.phys_port_cnt             = file->device->ib_dev->phys_port_cnt;
197
198         if (copy_to_user((void __user *) (unsigned long) cmd.response,
199                          &resp, sizeof resp))
200                 return -EFAULT;
201
202         return in_len;
203 }
204
205 ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file,
206                              const char __user *buf,
207                              int in_len, int out_len)
208 {
209         struct ib_uverbs_query_port      cmd;
210         struct ib_uverbs_query_port_resp resp;
211         struct ib_port_attr              attr;
212         int                              ret;
213
214         if (out_len < sizeof resp)
215                 return -ENOSPC;
216
217         if (copy_from_user(&cmd, buf, sizeof cmd))
218                 return -EFAULT;
219
220         ret = ib_query_port(file->device->ib_dev, cmd.port_num, &attr);
221         if (ret)
222                 return ret;
223
224         memset(&resp, 0, sizeof resp);
225
226         resp.state           = attr.state;
227         resp.max_mtu         = attr.max_mtu;
228         resp.active_mtu      = attr.active_mtu;
229         resp.gid_tbl_len     = attr.gid_tbl_len;
230         resp.port_cap_flags  = attr.port_cap_flags;
231         resp.max_msg_sz      = attr.max_msg_sz;
232         resp.bad_pkey_cntr   = attr.bad_pkey_cntr;
233         resp.qkey_viol_cntr  = attr.qkey_viol_cntr;
234         resp.pkey_tbl_len    = attr.pkey_tbl_len;
235         resp.lid             = attr.lid;
236         resp.sm_lid          = attr.sm_lid;
237         resp.lmc             = attr.lmc;
238         resp.max_vl_num      = attr.max_vl_num;
239         resp.sm_sl           = attr.sm_sl;
240         resp.subnet_timeout  = attr.subnet_timeout;
241         resp.init_type_reply = attr.init_type_reply;
242         resp.active_width    = attr.active_width;
243         resp.active_speed    = attr.active_speed;
244         resp.phys_state      = attr.phys_state;
245
246         if (copy_to_user((void __user *) (unsigned long) cmd.response,
247                          &resp, sizeof resp))
248                 return -EFAULT;
249
250         return in_len;
251 }
252
253 ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
254                            const char __user *buf,
255                            int in_len, int out_len)
256 {
257         struct ib_uverbs_alloc_pd      cmd;
258         struct ib_uverbs_alloc_pd_resp resp;
259         struct ib_udata                udata;
260         struct ib_uobject             *uobj;
261         struct ib_pd                  *pd;
262         int                            ret;
263
264         if (out_len < sizeof resp)
265                 return -ENOSPC;
266
267         if (copy_from_user(&cmd, buf, sizeof cmd))
268                 return -EFAULT;
269
270         INIT_UDATA(&udata, buf + sizeof cmd,
271                    (unsigned long) cmd.response + sizeof resp,
272                    in_len - sizeof cmd, out_len - sizeof resp);
273
274         uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
275         if (!uobj)
276                 return -ENOMEM;
277
278         uobj->context = file->ucontext;
279
280         pd = file->device->ib_dev->alloc_pd(file->device->ib_dev,
281                                             file->ucontext, &udata);
282         if (IS_ERR(pd)) {
283                 ret = PTR_ERR(pd);
284                 goto err;
285         }
286
287         pd->device  = file->device->ib_dev;
288         pd->uobject = uobj;
289         atomic_set(&pd->usecnt, 0);
290
291 retry:
292         if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
293                 ret = -ENOMEM;
294                 goto err_pd;
295         }
296
297         down(&ib_uverbs_idr_mutex);
298         ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);
299         up(&ib_uverbs_idr_mutex);
300
301         if (ret == -EAGAIN)
302                 goto retry;
303         if (ret)
304                 goto err_pd;
305
306         down(&file->mutex);
307         list_add_tail(&uobj->list, &file->ucontext->pd_list);
308         up(&file->mutex);
309
310         memset(&resp, 0, sizeof resp);
311         resp.pd_handle = uobj->id;
312
313         if (copy_to_user((void __user *) (unsigned long) cmd.response,
314                          &resp, sizeof resp)) {
315                 ret = -EFAULT;
316                 goto err_list;
317         }
318
319         return in_len;
320
321 err_list:
322         down(&file->mutex);
323         list_del(&uobj->list);
324         up(&file->mutex);
325
326         down(&ib_uverbs_idr_mutex);
327         idr_remove(&ib_uverbs_pd_idr, uobj->id);
328         up(&ib_uverbs_idr_mutex);
329
330 err_pd:
331         ib_dealloc_pd(pd);
332
333 err:
334         kfree(uobj);
335         return ret;
336 }
337
338 ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
339                              const char __user *buf,
340                              int in_len, int out_len)
341 {
342         struct ib_uverbs_dealloc_pd cmd;
343         struct ib_pd               *pd;
344         struct ib_uobject          *uobj;
345         int                         ret = -EINVAL;
346
347         if (copy_from_user(&cmd, buf, sizeof cmd))
348                 return -EFAULT;
349
350         down(&ib_uverbs_idr_mutex);
351
352         pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
353         if (!pd || pd->uobject->context != file->ucontext)
354                 goto out;
355
356         uobj = pd->uobject;
357
358         ret = ib_dealloc_pd(pd);
359         if (ret)
360                 goto out;
361
362         idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
363
364         down(&file->mutex);
365         list_del(&uobj->list);
366         up(&file->mutex);
367
368         kfree(uobj);
369
370 out:
371         up(&ib_uverbs_idr_mutex);
372
373         return ret ? ret : in_len;
374 }
375
376 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
377                          const char __user *buf, int in_len,
378                          int out_len)
379 {
380         struct ib_uverbs_reg_mr      cmd;
381         struct ib_uverbs_reg_mr_resp resp;
382         struct ib_udata              udata;
383         struct ib_umem_object       *obj;
384         struct ib_pd                *pd;
385         struct ib_mr                *mr;
386         int                          ret;
387
388         if (out_len < sizeof resp)
389                 return -ENOSPC;
390
391         if (copy_from_user(&cmd, buf, sizeof cmd))
392                 return -EFAULT;
393
394         INIT_UDATA(&udata, buf + sizeof cmd,
395                    (unsigned long) cmd.response + sizeof resp,
396                    in_len - sizeof cmd, out_len - sizeof resp);
397
398         if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
399                 return -EINVAL;
400
401         obj = kmalloc(sizeof *obj, GFP_KERNEL);
402         if (!obj)
403                 return -ENOMEM;
404
405         obj->uobject.context = file->ucontext;
406
407         /*
408          * We ask for writable memory if any access flags other than
409          * "remote read" are set.  "Local write" and "remote write"
410          * obviously require write access.  "Remote atomic" can do
411          * things like fetch and add, which will modify memory, and
412          * "MW bind" can change permissions by binding a window.
413          */
414         ret = ib_umem_get(file->device->ib_dev, &obj->umem,
415                           (void *) (unsigned long) cmd.start, cmd.length,
416                           !!(cmd.access_flags & ~IB_ACCESS_REMOTE_READ));
417         if (ret)
418                 goto err_free;
419
420         obj->umem.virt_base = cmd.hca_va;
421
422         down(&ib_uverbs_idr_mutex);
423
424         pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
425         if (!pd || pd->uobject->context != file->ucontext) {
426                 ret = -EINVAL;
427                 goto err_up;
428         }
429
430         if (!pd->device->reg_user_mr) {
431                 ret = -ENOSYS;
432                 goto err_up;
433         }
434
435         mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata);
436         if (IS_ERR(mr)) {
437                 ret = PTR_ERR(mr);
438                 goto err_up;
439         }
440
441         mr->device  = pd->device;
442         mr->pd      = pd;
443         mr->uobject = &obj->uobject;
444         atomic_inc(&pd->usecnt);
445         atomic_set(&mr->usecnt, 0);
446
447         memset(&resp, 0, sizeof resp);
448         resp.lkey = mr->lkey;
449         resp.rkey = mr->rkey;
450
451 retry:
452         if (!idr_pre_get(&ib_uverbs_mr_idr, GFP_KERNEL)) {
453                 ret = -ENOMEM;
454                 goto err_unreg;
455         }
456
457         ret = idr_get_new(&ib_uverbs_mr_idr, mr, &obj->uobject.id);
458
459         if (ret == -EAGAIN)
460                 goto retry;
461         if (ret)
462                 goto err_unreg;
463
464         resp.mr_handle = obj->uobject.id;
465
466         down(&file->mutex);
467         list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
468         up(&file->mutex);
469
470         if (copy_to_user((void __user *) (unsigned long) cmd.response,
471                          &resp, sizeof resp)) {
472                 ret = -EFAULT;
473                 goto err_list;
474         }
475
476         up(&ib_uverbs_idr_mutex);
477
478         return in_len;
479
480 err_list:
481         down(&file->mutex);
482         list_del(&obj->uobject.list);
483         up(&file->mutex);
484
485 err_unreg:
486         ib_dereg_mr(mr);
487
488 err_up:
489         up(&ib_uverbs_idr_mutex);
490
491         ib_umem_release(file->device->ib_dev, &obj->umem);
492
493 err_free:
494         kfree(obj);
495         return ret;
496 }
497
498 ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
499                            const char __user *buf, int in_len,
500                            int out_len)
501 {
502         struct ib_uverbs_dereg_mr cmd;
503         struct ib_mr             *mr;
504         struct ib_umem_object    *memobj;
505         int                       ret = -EINVAL;
506
507         if (copy_from_user(&cmd, buf, sizeof cmd))
508                 return -EFAULT;
509
510         down(&ib_uverbs_idr_mutex);
511
512         mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle);
513         if (!mr || mr->uobject->context != file->ucontext)
514                 goto out;
515
516         memobj = container_of(mr->uobject, struct ib_umem_object, uobject);
517
518         ret = ib_dereg_mr(mr);
519         if (ret)
520                 goto out;
521
522         idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
523
524         down(&file->mutex);
525         list_del(&memobj->uobject.list);
526         up(&file->mutex);
527
528         ib_umem_release(file->device->ib_dev, &memobj->umem);
529         kfree(memobj);
530
531 out:
532         up(&ib_uverbs_idr_mutex);
533
534         return ret ? ret : in_len;
535 }
536
537 ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
538                                       const char __user *buf, int in_len,
539                                       int out_len)
540 {
541         struct ib_uverbs_create_comp_channel       cmd;
542         struct ib_uverbs_create_comp_channel_resp  resp;
543         struct file                               *filp;
544
545         if (out_len < sizeof resp)
546                 return -ENOSPC;
547
548         if (copy_from_user(&cmd, buf, sizeof cmd))
549                 return -EFAULT;
550
551         filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd);
552         if (IS_ERR(filp))
553                 return PTR_ERR(filp);
554
555         if (copy_to_user((void __user *) (unsigned long) cmd.response,
556                          &resp, sizeof resp)) {
557                 put_unused_fd(resp.fd);
558                 fput(filp);
559                 return -EFAULT;
560         }
561
562         fd_install(resp.fd, filp);
563         return in_len;
564 }
565
566 ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
567                             const char __user *buf, int in_len,
568                             int out_len)
569 {
570         struct ib_uverbs_create_cq      cmd;
571         struct ib_uverbs_create_cq_resp resp;
572         struct ib_udata                 udata;
573         struct ib_ucq_object           *uobj;
574         struct ib_uverbs_event_file    *ev_file = NULL;
575         struct ib_cq                   *cq;
576         int                             ret;
577
578         if (out_len < sizeof resp)
579                 return -ENOSPC;
580
581         if (copy_from_user(&cmd, buf, sizeof cmd))
582                 return -EFAULT;
583
584         INIT_UDATA(&udata, buf + sizeof cmd,
585                    (unsigned long) cmd.response + sizeof resp,
586                    in_len - sizeof cmd, out_len - sizeof resp);
587
588         if (cmd.comp_vector >= file->device->num_comp_vectors)
589                 return -EINVAL;
590
591         if (cmd.comp_channel >= 0)
592                 ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
593
594         uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
595         if (!uobj)
596                 return -ENOMEM;
597
598         uobj->uobject.user_handle   = cmd.user_handle;
599         uobj->uobject.context       = file->ucontext;
600         uobj->comp_events_reported  = 0;
601         uobj->async_events_reported = 0;
602         INIT_LIST_HEAD(&uobj->comp_list);
603         INIT_LIST_HEAD(&uobj->async_list);
604
605         cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
606                                              file->ucontext, &udata);
607         if (IS_ERR(cq)) {
608                 ret = PTR_ERR(cq);
609                 goto err;
610         }
611
612         cq->device        = file->device->ib_dev;
613         cq->uobject       = &uobj->uobject;
614         cq->comp_handler  = ib_uverbs_comp_handler;
615         cq->event_handler = ib_uverbs_cq_event_handler;
616         cq->cq_context    = ev_file;
617         atomic_set(&cq->usecnt, 0);
618
619 retry:
620         if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
621                 ret = -ENOMEM;
622                 goto err_cq;
623         }
624
625         down(&ib_uverbs_idr_mutex);
626         ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
627         up(&ib_uverbs_idr_mutex);
628
629         if (ret == -EAGAIN)
630                 goto retry;
631         if (ret)
632                 goto err_cq;
633
634         down(&file->mutex);
635         list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
636         up(&file->mutex);
637
638         memset(&resp, 0, sizeof resp);
639         resp.cq_handle = uobj->uobject.id;
640         resp.cqe       = cq->cqe;
641
642         if (copy_to_user((void __user *) (unsigned long) cmd.response,
643                          &resp, sizeof resp)) {
644                 ret = -EFAULT;
645                 goto err_list;
646         }
647
648         return in_len;
649
650 err_list:
651         down(&file->mutex);
652         list_del(&uobj->uobject.list);
653         up(&file->mutex);
654
655         down(&ib_uverbs_idr_mutex);
656         idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
657         up(&ib_uverbs_idr_mutex);
658
659 err_cq:
660         ib_destroy_cq(cq);
661
662 err:
663         kfree(uobj);
664         return ret;
665 }
666
667 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
668                              const char __user *buf, int in_len,
669                              int out_len)
670 {
671         struct ib_uverbs_destroy_cq      cmd;
672         struct ib_uverbs_destroy_cq_resp resp;
673         struct ib_cq                    *cq;
674         struct ib_ucq_object            *uobj;
675         struct ib_uverbs_event_file     *ev_file;
676         struct ib_uverbs_event          *evt, *tmp;
677         u64                              user_handle;
678         int                              ret = -EINVAL;
679
680         if (copy_from_user(&cmd, buf, sizeof cmd))
681                 return -EFAULT;
682
683         memset(&resp, 0, sizeof resp);
684
685         down(&ib_uverbs_idr_mutex);
686
687         cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
688         if (!cq || cq->uobject->context != file->ucontext)
689                 goto out;
690
691         user_handle = cq->uobject->user_handle;
692         uobj        = container_of(cq->uobject, struct ib_ucq_object, uobject);
693         ev_file     = cq->cq_context;
694
695         ret = ib_destroy_cq(cq);
696         if (ret)
697                 goto out;
698
699         idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
700
701         down(&file->mutex);
702         list_del(&uobj->uobject.list);
703         up(&file->mutex);
704
705         if (ev_file) {
706                 spin_lock_irq(&ev_file->lock);
707                 list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
708                         list_del(&evt->list);
709                         kfree(evt);
710                 }
711                 spin_unlock_irq(&ev_file->lock);
712
713                 kref_put(&ev_file->ref, ib_uverbs_release_event_file);
714         }
715
716         spin_lock_irq(&file->async_file->lock);
717         list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
718                 list_del(&evt->list);
719                 kfree(evt);
720         }
721         spin_unlock_irq(&file->async_file->lock);
722
723         resp.comp_events_reported  = uobj->comp_events_reported;
724         resp.async_events_reported = uobj->async_events_reported;
725
726         kfree(uobj);
727
728         if (copy_to_user((void __user *) (unsigned long) cmd.response,
729                          &resp, sizeof resp))
730                 ret = -EFAULT;
731
732 out:
733         up(&ib_uverbs_idr_mutex);
734
735         return ret ? ret : in_len;
736 }
737
738 ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
739                             const char __user *buf, int in_len,
740                             int out_len)
741 {
742         struct ib_uverbs_create_qp      cmd;
743         struct ib_uverbs_create_qp_resp resp;
744         struct ib_udata                 udata;
745         struct ib_uevent_object        *uobj;
746         struct ib_pd                   *pd;
747         struct ib_cq                   *scq, *rcq;
748         struct ib_srq                  *srq;
749         struct ib_qp                   *qp;
750         struct ib_qp_init_attr          attr;
751         int ret;
752
753         if (out_len < sizeof resp)
754                 return -ENOSPC;
755
756         if (copy_from_user(&cmd, buf, sizeof cmd))
757                 return -EFAULT;
758
759         INIT_UDATA(&udata, buf + sizeof cmd,
760                    (unsigned long) cmd.response + sizeof resp,
761                    in_len - sizeof cmd, out_len - sizeof resp);
762
763         uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
764         if (!uobj)
765                 return -ENOMEM;
766
767         down(&ib_uverbs_idr_mutex);
768
769         pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
770         scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
771         rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
772         srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL;
773
774         if (!pd  || pd->uobject->context  != file->ucontext ||
775             !scq || scq->uobject->context != file->ucontext ||
776             !rcq || rcq->uobject->context != file->ucontext ||
777             (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
778                 ret = -EINVAL;
779                 goto err_up;
780         }
781
782         attr.event_handler = ib_uverbs_qp_event_handler;
783         attr.qp_context    = file;
784         attr.send_cq       = scq;
785         attr.recv_cq       = rcq;
786         attr.srq           = srq;
787         attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
788         attr.qp_type       = cmd.qp_type;
789
790         attr.cap.max_send_wr     = cmd.max_send_wr;
791         attr.cap.max_recv_wr     = cmd.max_recv_wr;
792         attr.cap.max_send_sge    = cmd.max_send_sge;
793         attr.cap.max_recv_sge    = cmd.max_recv_sge;
794         attr.cap.max_inline_data = cmd.max_inline_data;
795
796         uobj->uobject.user_handle = cmd.user_handle;
797         uobj->uobject.context     = file->ucontext;
798         uobj->events_reported     = 0;
799         INIT_LIST_HEAD(&uobj->event_list);
800
801         qp = pd->device->create_qp(pd, &attr, &udata);
802         if (IS_ERR(qp)) {
803                 ret = PTR_ERR(qp);
804                 goto err_up;
805         }
806
807         qp->device        = pd->device;
808         qp->pd            = pd;
809         qp->send_cq       = attr.send_cq;
810         qp->recv_cq       = attr.recv_cq;
811         qp->srq           = attr.srq;
812         qp->uobject       = &uobj->uobject;
813         qp->event_handler = attr.event_handler;
814         qp->qp_context    = attr.qp_context;
815         qp->qp_type       = attr.qp_type;
816         atomic_inc(&pd->usecnt);
817         atomic_inc(&attr.send_cq->usecnt);
818         atomic_inc(&attr.recv_cq->usecnt);
819         if (attr.srq)
820                 atomic_inc(&attr.srq->usecnt);
821
822         memset(&resp, 0, sizeof resp);
823         resp.qpn = qp->qp_num;
824
825 retry:
826         if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) {
827                 ret = -ENOMEM;
828                 goto err_destroy;
829         }
830
831         ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id);
832
833         if (ret == -EAGAIN)
834                 goto retry;
835         if (ret)
836                 goto err_destroy;
837
838         resp.qp_handle = uobj->uobject.id;
839
840         down(&file->mutex);
841         list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
842         up(&file->mutex);
843
844         if (copy_to_user((void __user *) (unsigned long) cmd.response,
845                          &resp, sizeof resp)) {
846                 ret = -EFAULT;
847                 goto err_list;
848         }
849
850         up(&ib_uverbs_idr_mutex);
851
852         return in_len;
853
854 err_list:
855         down(&file->mutex);
856         list_del(&uobj->uobject.list);
857         up(&file->mutex);
858
859 err_destroy:
860         ib_destroy_qp(qp);
861
862 err_up:
863         up(&ib_uverbs_idr_mutex);
864
865         kfree(uobj);
866         return ret;
867 }
868
869 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
870                             const char __user *buf, int in_len,
871                             int out_len)
872 {
873         struct ib_uverbs_modify_qp cmd;
874         struct ib_qp              *qp;
875         struct ib_qp_attr         *attr;
876         int                        ret;
877
878         if (copy_from_user(&cmd, buf, sizeof cmd))
879                 return -EFAULT;
880
881         attr = kmalloc(sizeof *attr, GFP_KERNEL);
882         if (!attr)
883                 return -ENOMEM;
884
885         down(&ib_uverbs_idr_mutex);
886
887         qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
888         if (!qp || qp->uobject->context != file->ucontext) {
889                 ret = -EINVAL;
890                 goto out;
891         }
892
893         attr->qp_state            = cmd.qp_state;
894         attr->cur_qp_state        = cmd.cur_qp_state;
895         attr->path_mtu            = cmd.path_mtu;
896         attr->path_mig_state      = cmd.path_mig_state;
897         attr->qkey                = cmd.qkey;
898         attr->rq_psn              = cmd.rq_psn;
899         attr->sq_psn              = cmd.sq_psn;
900         attr->dest_qp_num         = cmd.dest_qp_num;
901         attr->qp_access_flags     = cmd.qp_access_flags;
902         attr->pkey_index          = cmd.pkey_index;
903         attr->alt_pkey_index      = cmd.pkey_index;
904         attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
905         attr->max_rd_atomic       = cmd.max_rd_atomic;
906         attr->max_dest_rd_atomic  = cmd.max_dest_rd_atomic;
907         attr->min_rnr_timer       = cmd.min_rnr_timer;
908         attr->port_num            = cmd.port_num;
909         attr->timeout             = cmd.timeout;
910         attr->retry_cnt           = cmd.retry_cnt;
911         attr->rnr_retry           = cmd.rnr_retry;
912         attr->alt_port_num        = cmd.alt_port_num;
913         attr->alt_timeout         = cmd.alt_timeout;
914
915         memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16);
916         attr->ah_attr.grh.flow_label        = cmd.dest.flow_label;
917         attr->ah_attr.grh.sgid_index        = cmd.dest.sgid_index;
918         attr->ah_attr.grh.hop_limit         = cmd.dest.hop_limit;
919         attr->ah_attr.grh.traffic_class     = cmd.dest.traffic_class;
920         attr->ah_attr.dlid                  = cmd.dest.dlid;
921         attr->ah_attr.sl                    = cmd.dest.sl;
922         attr->ah_attr.src_path_bits         = cmd.dest.src_path_bits;
923         attr->ah_attr.static_rate           = cmd.dest.static_rate;
924         attr->ah_attr.ah_flags              = cmd.dest.is_global ? IB_AH_GRH : 0;
925         attr->ah_attr.port_num              = cmd.dest.port_num;
926
927         memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16);
928         attr->alt_ah_attr.grh.flow_label    = cmd.alt_dest.flow_label;
929         attr->alt_ah_attr.grh.sgid_index    = cmd.alt_dest.sgid_index;
930         attr->alt_ah_attr.grh.hop_limit     = cmd.alt_dest.hop_limit;
931         attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class;
932         attr->alt_ah_attr.dlid              = cmd.alt_dest.dlid;
933         attr->alt_ah_attr.sl                = cmd.alt_dest.sl;
934         attr->alt_ah_attr.src_path_bits     = cmd.alt_dest.src_path_bits;
935         attr->alt_ah_attr.static_rate       = cmd.alt_dest.static_rate;
936         attr->alt_ah_attr.ah_flags          = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
937         attr->alt_ah_attr.port_num          = cmd.alt_dest.port_num;
938
939         ret = ib_modify_qp(qp, attr, cmd.attr_mask);
940         if (ret)
941                 goto out;
942
943         ret = in_len;
944
945 out:
946         up(&ib_uverbs_idr_mutex);
947         kfree(attr);
948
949         return ret;
950 }
951
952 ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
953                              const char __user *buf, int in_len,
954                              int out_len)
955 {
956         struct ib_uverbs_destroy_qp      cmd;
957         struct ib_uverbs_destroy_qp_resp resp;
958         struct ib_qp                    *qp;
959         struct ib_uevent_object         *uobj;
960         struct ib_uverbs_event          *evt, *tmp;
961         int                              ret = -EINVAL;
962
963         if (copy_from_user(&cmd, buf, sizeof cmd))
964                 return -EFAULT;
965
966         memset(&resp, 0, sizeof resp);
967
968         down(&ib_uverbs_idr_mutex);
969
970         qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
971         if (!qp || qp->uobject->context != file->ucontext)
972                 goto out;
973
974         uobj = container_of(qp->uobject, struct ib_uevent_object, uobject);
975
976         ret = ib_destroy_qp(qp);
977         if (ret)
978                 goto out;
979
980         idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
981
982         down(&file->mutex);
983         list_del(&uobj->uobject.list);
984         up(&file->mutex);
985
986         spin_lock_irq(&file->async_file->lock);
987         list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
988                 list_del(&evt->list);
989                 kfree(evt);
990         }
991         spin_unlock_irq(&file->async_file->lock);
992
993         resp.events_reported = uobj->events_reported;
994
995         kfree(uobj);
996
997         if (copy_to_user((void __user *) (unsigned long) cmd.response,
998                          &resp, sizeof resp))
999                 ret = -EFAULT;
1000
1001 out:
1002         up(&ib_uverbs_idr_mutex);
1003
1004         return ret ? ret : in_len;
1005 }
1006
1007 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
1008                                const char __user *buf, int in_len,
1009                                int out_len)
1010 {
1011         struct ib_uverbs_attach_mcast cmd;
1012         struct ib_qp                 *qp;
1013         int                           ret = -EINVAL;
1014
1015         if (copy_from_user(&cmd, buf, sizeof cmd))
1016                 return -EFAULT;
1017
1018         down(&ib_uverbs_idr_mutex);
1019
1020         qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1021         if (qp && qp->uobject->context == file->ucontext)
1022                 ret = ib_attach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
1023
1024         up(&ib_uverbs_idr_mutex);
1025
1026         return ret ? ret : in_len;
1027 }
1028
1029 ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
1030                                const char __user *buf, int in_len,
1031                                int out_len)
1032 {
1033         struct ib_uverbs_detach_mcast cmd;
1034         struct ib_qp                 *qp;
1035         int                           ret = -EINVAL;
1036
1037         if (copy_from_user(&cmd, buf, sizeof cmd))
1038                 return -EFAULT;
1039
1040         down(&ib_uverbs_idr_mutex);
1041
1042         qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
1043         if (qp && qp->uobject->context == file->ucontext)
1044                 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
1045
1046         up(&ib_uverbs_idr_mutex);
1047
1048         return ret ? ret : in_len;
1049 }
1050
1051 ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1052                              const char __user *buf, int in_len,
1053                              int out_len)
1054 {
1055         struct ib_uverbs_create_srq      cmd;
1056         struct ib_uverbs_create_srq_resp resp;
1057         struct ib_udata                  udata;
1058         struct ib_uevent_object         *uobj;
1059         struct ib_pd                    *pd;
1060         struct ib_srq                   *srq;
1061         struct ib_srq_init_attr          attr;
1062         int ret;
1063
1064         if (out_len < sizeof resp)
1065                 return -ENOSPC;
1066
1067         if (copy_from_user(&cmd, buf, sizeof cmd))
1068                 return -EFAULT;
1069
1070         INIT_UDATA(&udata, buf + sizeof cmd,
1071                    (unsigned long) cmd.response + sizeof resp,
1072                    in_len - sizeof cmd, out_len - sizeof resp);
1073
1074         uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
1075         if (!uobj)
1076                 return -ENOMEM;
1077
1078         down(&ib_uverbs_idr_mutex);
1079
1080         pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
1081
1082         if (!pd || pd->uobject->context != file->ucontext) {
1083                 ret = -EINVAL;
1084                 goto err_up;
1085         }
1086
1087         attr.event_handler  = ib_uverbs_srq_event_handler;
1088         attr.srq_context    = file;
1089         attr.attr.max_wr    = cmd.max_wr;
1090         attr.attr.max_sge   = cmd.max_sge;
1091         attr.attr.srq_limit = cmd.srq_limit;
1092
1093         uobj->uobject.user_handle = cmd.user_handle;
1094         uobj->uobject.context     = file->ucontext;
1095         uobj->events_reported     = 0;
1096         INIT_LIST_HEAD(&uobj->event_list);
1097
1098         srq = pd->device->create_srq(pd, &attr, &udata);
1099         if (IS_ERR(srq)) {
1100                 ret = PTR_ERR(srq);
1101                 goto err_up;
1102         }
1103
1104         srq->device        = pd->device;
1105         srq->pd            = pd;
1106         srq->uobject       = &uobj->uobject;
1107         srq->event_handler = attr.event_handler;
1108         srq->srq_context   = attr.srq_context;
1109         atomic_inc(&pd->usecnt);
1110         atomic_set(&srq->usecnt, 0);
1111
1112         memset(&resp, 0, sizeof resp);
1113
1114 retry:
1115         if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) {
1116                 ret = -ENOMEM;
1117                 goto err_destroy;
1118         }
1119
1120         ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
1121
1122         if (ret == -EAGAIN)
1123                 goto retry;
1124         if (ret)
1125                 goto err_destroy;
1126
1127         resp.srq_handle = uobj->uobject.id;
1128
1129         down(&file->mutex);
1130         list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
1131         up(&file->mutex);
1132
1133         if (copy_to_user((void __user *) (unsigned long) cmd.response,
1134                          &resp, sizeof resp)) {
1135                 ret = -EFAULT;
1136                 goto err_list;
1137         }
1138
1139         up(&ib_uverbs_idr_mutex);
1140
1141         return in_len;
1142
1143 err_list:
1144         down(&file->mutex);
1145         list_del(&uobj->uobject.list);
1146         up(&file->mutex);
1147
1148 err_destroy:
1149         ib_destroy_srq(srq);
1150
1151 err_up:
1152         up(&ib_uverbs_idr_mutex);
1153
1154         kfree(uobj);
1155         return ret;
1156 }
1157
1158 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
1159                              const char __user *buf, int in_len,
1160                              int out_len)
1161 {
1162         struct ib_uverbs_modify_srq cmd;
1163         struct ib_srq              *srq;
1164         struct ib_srq_attr          attr;
1165         int                         ret;
1166
1167         if (copy_from_user(&cmd, buf, sizeof cmd))
1168                 return -EFAULT;
1169
1170         down(&ib_uverbs_idr_mutex);
1171
1172         srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
1173         if (!srq || srq->uobject->context != file->ucontext) {
1174                 ret = -EINVAL;
1175                 goto out;
1176         }
1177
1178         attr.max_wr    = cmd.max_wr;
1179         attr.max_sge   = cmd.max_sge;
1180         attr.srq_limit = cmd.srq_limit;
1181
1182         ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
1183
1184 out:
1185         up(&ib_uverbs_idr_mutex);
1186
1187         return ret ? ret : in_len;
1188 }
1189
1190 ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1191                               const char __user *buf, int in_len,
1192                               int out_len)
1193 {
1194         struct ib_uverbs_destroy_srq      cmd;
1195         struct ib_uverbs_destroy_srq_resp resp;
1196         struct ib_srq                    *srq;
1197         struct ib_uevent_object          *uobj;
1198         struct ib_uverbs_event           *evt, *tmp;
1199         int                               ret = -EINVAL;
1200
1201         if (copy_from_user(&cmd, buf, sizeof cmd))
1202                 return -EFAULT;
1203
1204         down(&ib_uverbs_idr_mutex);
1205
1206         memset(&resp, 0, sizeof resp);
1207
1208         srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
1209         if (!srq || srq->uobject->context != file->ucontext)
1210                 goto out;
1211
1212         uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
1213
1214         ret = ib_destroy_srq(srq);
1215         if (ret)
1216                 goto out;
1217
1218         idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
1219
1220         down(&file->mutex);
1221         list_del(&uobj->uobject.list);
1222         up(&file->mutex);
1223
1224         spin_lock_irq(&file->async_file->lock);
1225         list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
1226                 list_del(&evt->list);
1227                 kfree(evt);
1228         }
1229         spin_unlock_irq(&file->async_file->lock);
1230
1231         resp.events_reported = uobj->events_reported;
1232
1233         kfree(uobj);
1234
1235         if (copy_to_user((void __user *) (unsigned long) cmd.response,
1236                          &resp, sizeof resp))
1237                 ret = -EFAULT;
1238
1239 out:
1240         up(&ib_uverbs_idr_mutex);
1241
1242         return ret ? ret : in_len;
1243 }