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