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