2 * Copyright (c) 2005 Topspin Communications. All rights reserved.
3 * Copyright (c) 2005 Cisco Systems. All rights reserved.
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:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
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.
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
33 * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $
36 #include <asm/uaccess.h>
40 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
42 (udata)->inbuf = (void __user *) (ibuf); \
43 (udata)->outbuf = (void __user *) (obuf); \
44 (udata)->inlen = (ilen); \
45 (udata)->outlen = (olen); \
48 ssize_t
ib_uverbs_query_params(struct ib_uverbs_file
*file
,
49 const char __user
*buf
,
50 int in_len
, int out_len
)
52 struct ib_uverbs_query_params cmd
;
53 struct ib_uverbs_query_params_resp resp
;
55 if (out_len
< sizeof resp
)
58 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
61 memset(&resp
, 0, sizeof resp
);
63 resp
.num_cq_events
= file
->device
->num_comp
;
65 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
, &resp
, sizeof resp
))
71 ssize_t
ib_uverbs_get_context(struct ib_uverbs_file
*file
,
72 const char __user
*buf
,
73 int in_len
, int out_len
)
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
;
82 if (out_len
< sizeof resp
)
85 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
88 INIT_UDATA(&udata
, buf
+ sizeof cmd
,
89 (unsigned long) cmd
.response
+ sizeof resp
,
90 in_len
- sizeof cmd
, out_len
- sizeof resp
);
92 file
->ucontext
= ibdev
->alloc_ucontext(ibdev
, &udata
);
93 if (IS_ERR(file
->ucontext
)) {
94 ret
= PTR_ERR(file
->ucontext
);
95 file
->ucontext
= NULL
;
99 file
->ucontext
->device
= ibdev
;
100 INIT_LIST_HEAD(&file
->ucontext
->pd_list
);
101 INIT_LIST_HEAD(&file
->ucontext
->mr_list
);
102 INIT_LIST_HEAD(&file
->ucontext
->mw_list
);
103 INIT_LIST_HEAD(&file
->ucontext
->cq_list
);
104 INIT_LIST_HEAD(&file
->ucontext
->qp_list
);
105 INIT_LIST_HEAD(&file
->ucontext
->srq_list
);
106 INIT_LIST_HEAD(&file
->ucontext
->ah_list
);
107 spin_lock_init(&file
->ucontext
->lock
);
109 resp
.async_fd
= file
->async_file
.fd
;
110 for (i
= 0; i
< file
->device
->num_comp
; ++i
)
111 if (copy_to_user((void __user
*) (unsigned long) cmd
.cq_fd_tab
+
113 &file
->comp_file
[i
].fd
, sizeof (__u32
)))
116 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
123 ibdev
->dealloc_ucontext(file
->ucontext
);
124 file
->ucontext
= NULL
;
129 ssize_t
ib_uverbs_query_device(struct ib_uverbs_file
*file
,
130 const char __user
*buf
,
131 int in_len
, int out_len
)
133 struct ib_uverbs_query_device cmd
;
134 struct ib_uverbs_query_device_resp resp
;
135 struct ib_device_attr attr
;
138 if (out_len
< sizeof resp
)
141 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
144 ret
= ib_query_device(file
->device
->ib_dev
, &attr
);
148 memset(&resp
, 0, sizeof resp
);
150 resp
.fw_ver
= attr
.fw_ver
;
151 resp
.node_guid
= attr
.node_guid
;
152 resp
.sys_image_guid
= attr
.sys_image_guid
;
153 resp
.max_mr_size
= attr
.max_mr_size
;
154 resp
.page_size_cap
= attr
.page_size_cap
;
155 resp
.vendor_id
= attr
.vendor_id
;
156 resp
.vendor_part_id
= attr
.vendor_part_id
;
157 resp
.hw_ver
= attr
.hw_ver
;
158 resp
.max_qp
= attr
.max_qp
;
159 resp
.max_qp_wr
= attr
.max_qp_wr
;
160 resp
.device_cap_flags
= attr
.device_cap_flags
;
161 resp
.max_sge
= attr
.max_sge
;
162 resp
.max_sge_rd
= attr
.max_sge_rd
;
163 resp
.max_cq
= attr
.max_cq
;
164 resp
.max_cqe
= attr
.max_cqe
;
165 resp
.max_mr
= attr
.max_mr
;
166 resp
.max_pd
= attr
.max_pd
;
167 resp
.max_qp_rd_atom
= attr
.max_qp_rd_atom
;
168 resp
.max_ee_rd_atom
= attr
.max_ee_rd_atom
;
169 resp
.max_res_rd_atom
= attr
.max_res_rd_atom
;
170 resp
.max_qp_init_rd_atom
= attr
.max_qp_init_rd_atom
;
171 resp
.max_ee_init_rd_atom
= attr
.max_ee_init_rd_atom
;
172 resp
.atomic_cap
= attr
.atomic_cap
;
173 resp
.max_ee
= attr
.max_ee
;
174 resp
.max_rdd
= attr
.max_rdd
;
175 resp
.max_mw
= attr
.max_mw
;
176 resp
.max_raw_ipv6_qp
= attr
.max_raw_ipv6_qp
;
177 resp
.max_raw_ethy_qp
= attr
.max_raw_ethy_qp
;
178 resp
.max_mcast_grp
= attr
.max_mcast_grp
;
179 resp
.max_mcast_qp_attach
= attr
.max_mcast_qp_attach
;
180 resp
.max_total_mcast_qp_attach
= attr
.max_total_mcast_qp_attach
;
181 resp
.max_ah
= attr
.max_ah
;
182 resp
.max_fmr
= attr
.max_fmr
;
183 resp
.max_map_per_fmr
= attr
.max_map_per_fmr
;
184 resp
.max_srq
= attr
.max_srq
;
185 resp
.max_srq_wr
= attr
.max_srq_wr
;
186 resp
.max_srq_sge
= attr
.max_srq_sge
;
187 resp
.max_pkeys
= attr
.max_pkeys
;
188 resp
.local_ca_ack_delay
= attr
.local_ca_ack_delay
;
189 resp
.phys_port_cnt
= file
->device
->ib_dev
->phys_port_cnt
;
191 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
198 ssize_t
ib_uverbs_query_port(struct ib_uverbs_file
*file
,
199 const char __user
*buf
,
200 int in_len
, int out_len
)
202 struct ib_uverbs_query_port cmd
;
203 struct ib_uverbs_query_port_resp resp
;
204 struct ib_port_attr attr
;
207 if (out_len
< sizeof resp
)
210 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
213 ret
= ib_query_port(file
->device
->ib_dev
, cmd
.port_num
, &attr
);
217 memset(&resp
, 0, sizeof resp
);
219 resp
.state
= attr
.state
;
220 resp
.max_mtu
= attr
.max_mtu
;
221 resp
.active_mtu
= attr
.active_mtu
;
222 resp
.gid_tbl_len
= attr
.gid_tbl_len
;
223 resp
.port_cap_flags
= attr
.port_cap_flags
;
224 resp
.max_msg_sz
= attr
.max_msg_sz
;
225 resp
.bad_pkey_cntr
= attr
.bad_pkey_cntr
;
226 resp
.qkey_viol_cntr
= attr
.qkey_viol_cntr
;
227 resp
.pkey_tbl_len
= attr
.pkey_tbl_len
;
229 resp
.sm_lid
= attr
.sm_lid
;
231 resp
.max_vl_num
= attr
.max_vl_num
;
232 resp
.sm_sl
= attr
.sm_sl
;
233 resp
.subnet_timeout
= attr
.subnet_timeout
;
234 resp
.init_type_reply
= attr
.init_type_reply
;
235 resp
.active_width
= attr
.active_width
;
236 resp
.active_speed
= attr
.active_speed
;
237 resp
.phys_state
= attr
.phys_state
;
239 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
246 ssize_t
ib_uverbs_query_gid(struct ib_uverbs_file
*file
,
247 const char __user
*buf
,
248 int in_len
, int out_len
)
250 struct ib_uverbs_query_gid cmd
;
251 struct ib_uverbs_query_gid_resp resp
;
254 if (out_len
< sizeof resp
)
257 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
260 memset(&resp
, 0, sizeof resp
);
262 ret
= ib_query_gid(file
->device
->ib_dev
, cmd
.port_num
, cmd
.index
,
263 (union ib_gid
*) resp
.gid
);
267 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
274 ssize_t
ib_uverbs_query_pkey(struct ib_uverbs_file
*file
,
275 const char __user
*buf
,
276 int in_len
, int out_len
)
278 struct ib_uverbs_query_pkey cmd
;
279 struct ib_uverbs_query_pkey_resp resp
;
282 if (out_len
< sizeof resp
)
285 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
288 memset(&resp
, 0, sizeof resp
);
290 ret
= ib_query_pkey(file
->device
->ib_dev
, cmd
.port_num
, cmd
.index
,
295 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
302 ssize_t
ib_uverbs_alloc_pd(struct ib_uverbs_file
*file
,
303 const char __user
*buf
,
304 int in_len
, int out_len
)
306 struct ib_uverbs_alloc_pd cmd
;
307 struct ib_uverbs_alloc_pd_resp resp
;
308 struct ib_udata udata
;
309 struct ib_uobject
*uobj
;
313 if (out_len
< sizeof resp
)
316 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
319 INIT_UDATA(&udata
, buf
+ sizeof cmd
,
320 (unsigned long) cmd
.response
+ sizeof resp
,
321 in_len
- sizeof cmd
, out_len
- sizeof resp
);
323 uobj
= kmalloc(sizeof *uobj
, GFP_KERNEL
);
327 uobj
->context
= file
->ucontext
;
329 pd
= file
->device
->ib_dev
->alloc_pd(file
->device
->ib_dev
,
330 file
->ucontext
, &udata
);
336 pd
->device
= file
->device
->ib_dev
;
338 atomic_set(&pd
->usecnt
, 0);
341 if (!idr_pre_get(&ib_uverbs_pd_idr
, GFP_KERNEL
)) {
346 down(&ib_uverbs_idr_mutex
);
347 ret
= idr_get_new(&ib_uverbs_pd_idr
, pd
, &uobj
->id
);
348 up(&ib_uverbs_idr_mutex
);
355 spin_lock_irq(&file
->ucontext
->lock
);
356 list_add_tail(&uobj
->list
, &file
->ucontext
->pd_list
);
357 spin_unlock_irq(&file
->ucontext
->lock
);
359 memset(&resp
, 0, sizeof resp
);
360 resp
.pd_handle
= uobj
->id
;
362 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
363 &resp
, sizeof resp
)) {
371 spin_lock_irq(&file
->ucontext
->lock
);
372 list_del(&uobj
->list
);
373 spin_unlock_irq(&file
->ucontext
->lock
);
375 down(&ib_uverbs_idr_mutex
);
376 idr_remove(&ib_uverbs_pd_idr
, uobj
->id
);
377 up(&ib_uverbs_idr_mutex
);
387 ssize_t
ib_uverbs_dealloc_pd(struct ib_uverbs_file
*file
,
388 const char __user
*buf
,
389 int in_len
, int out_len
)
391 struct ib_uverbs_dealloc_pd cmd
;
393 struct ib_uobject
*uobj
;
396 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
399 down(&ib_uverbs_idr_mutex
);
401 pd
= idr_find(&ib_uverbs_pd_idr
, cmd
.pd_handle
);
402 if (!pd
|| pd
->uobject
->context
!= file
->ucontext
)
407 ret
= ib_dealloc_pd(pd
);
411 idr_remove(&ib_uverbs_pd_idr
, cmd
.pd_handle
);
413 spin_lock_irq(&file
->ucontext
->lock
);
414 list_del(&uobj
->list
);
415 spin_unlock_irq(&file
->ucontext
->lock
);
420 up(&ib_uverbs_idr_mutex
);
422 return ret
? ret
: in_len
;
425 ssize_t
ib_uverbs_reg_mr(struct ib_uverbs_file
*file
,
426 const char __user
*buf
, int in_len
,
429 struct ib_uverbs_reg_mr cmd
;
430 struct ib_uverbs_reg_mr_resp resp
;
431 struct ib_udata udata
;
432 struct ib_umem_object
*obj
;
437 if (out_len
< sizeof resp
)
440 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
443 INIT_UDATA(&udata
, buf
+ sizeof cmd
,
444 (unsigned long) cmd
.response
+ sizeof resp
,
445 in_len
- sizeof cmd
, out_len
- sizeof resp
);
447 if ((cmd
.start
& ~PAGE_MASK
) != (cmd
.hca_va
& ~PAGE_MASK
))
450 obj
= kmalloc(sizeof *obj
, GFP_KERNEL
);
454 obj
->uobject
.context
= file
->ucontext
;
457 * We ask for writable memory if any access flags other than
458 * "remote read" are set. "Local write" and "remote write"
459 * obviously require write access. "Remote atomic" can do
460 * things like fetch and add, which will modify memory, and
461 * "MW bind" can change permissions by binding a window.
463 ret
= ib_umem_get(file
->device
->ib_dev
, &obj
->umem
,
464 (void *) (unsigned long) cmd
.start
, cmd
.length
,
465 !!(cmd
.access_flags
& ~IB_ACCESS_REMOTE_READ
));
469 obj
->umem
.virt_base
= cmd
.hca_va
;
471 down(&ib_uverbs_idr_mutex
);
473 pd
= idr_find(&ib_uverbs_pd_idr
, cmd
.pd_handle
);
474 if (!pd
|| pd
->uobject
->context
!= file
->ucontext
) {
479 if (!pd
->device
->reg_user_mr
) {
484 mr
= pd
->device
->reg_user_mr(pd
, &obj
->umem
, cmd
.access_flags
, &udata
);
490 mr
->device
= pd
->device
;
492 mr
->uobject
= &obj
->uobject
;
493 atomic_inc(&pd
->usecnt
);
494 atomic_set(&mr
->usecnt
, 0);
496 memset(&resp
, 0, sizeof resp
);
497 resp
.lkey
= mr
->lkey
;
498 resp
.rkey
= mr
->rkey
;
501 if (!idr_pre_get(&ib_uverbs_mr_idr
, GFP_KERNEL
)) {
506 ret
= idr_get_new(&ib_uverbs_mr_idr
, mr
, &obj
->uobject
.id
);
513 resp
.mr_handle
= obj
->uobject
.id
;
515 spin_lock_irq(&file
->ucontext
->lock
);
516 list_add_tail(&obj
->uobject
.list
, &file
->ucontext
->mr_list
);
517 spin_unlock_irq(&file
->ucontext
->lock
);
519 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
520 &resp
, sizeof resp
)) {
525 up(&ib_uverbs_idr_mutex
);
530 spin_lock_irq(&file
->ucontext
->lock
);
531 list_del(&obj
->uobject
.list
);
532 spin_unlock_irq(&file
->ucontext
->lock
);
538 up(&ib_uverbs_idr_mutex
);
540 ib_umem_release(file
->device
->ib_dev
, &obj
->umem
);
547 ssize_t
ib_uverbs_dereg_mr(struct ib_uverbs_file
*file
,
548 const char __user
*buf
, int in_len
,
551 struct ib_uverbs_dereg_mr cmd
;
553 struct ib_umem_object
*memobj
;
556 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
559 down(&ib_uverbs_idr_mutex
);
561 mr
= idr_find(&ib_uverbs_mr_idr
, cmd
.mr_handle
);
562 if (!mr
|| mr
->uobject
->context
!= file
->ucontext
)
565 memobj
= container_of(mr
->uobject
, struct ib_umem_object
, uobject
);
567 ret
= ib_dereg_mr(mr
);
571 idr_remove(&ib_uverbs_mr_idr
, cmd
.mr_handle
);
573 spin_lock_irq(&file
->ucontext
->lock
);
574 list_del(&memobj
->uobject
.list
);
575 spin_unlock_irq(&file
->ucontext
->lock
);
577 ib_umem_release(file
->device
->ib_dev
, &memobj
->umem
);
581 up(&ib_uverbs_idr_mutex
);
583 return ret
? ret
: in_len
;
586 ssize_t
ib_uverbs_create_cq(struct ib_uverbs_file
*file
,
587 const char __user
*buf
, int in_len
,
590 struct ib_uverbs_create_cq cmd
;
591 struct ib_uverbs_create_cq_resp resp
;
592 struct ib_udata udata
;
593 struct ib_uobject
*uobj
;
597 if (out_len
< sizeof resp
)
600 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
603 INIT_UDATA(&udata
, buf
+ sizeof cmd
,
604 (unsigned long) cmd
.response
+ sizeof resp
,
605 in_len
- sizeof cmd
, out_len
- sizeof resp
);
607 if (cmd
.event_handler
>= file
->device
->num_comp
)
610 uobj
= kmalloc(sizeof *uobj
, GFP_KERNEL
);
614 uobj
->user_handle
= cmd
.user_handle
;
615 uobj
->context
= file
->ucontext
;
617 cq
= file
->device
->ib_dev
->create_cq(file
->device
->ib_dev
, cmd
.cqe
,
618 file
->ucontext
, &udata
);
624 cq
->device
= file
->device
->ib_dev
;
626 cq
->comp_handler
= ib_uverbs_comp_handler
;
627 cq
->event_handler
= ib_uverbs_cq_event_handler
;
628 cq
->cq_context
= file
;
629 atomic_set(&cq
->usecnt
, 0);
632 if (!idr_pre_get(&ib_uverbs_cq_idr
, GFP_KERNEL
)) {
637 down(&ib_uverbs_idr_mutex
);
638 ret
= idr_get_new(&ib_uverbs_cq_idr
, cq
, &uobj
->id
);
639 up(&ib_uverbs_idr_mutex
);
646 spin_lock_irq(&file
->ucontext
->lock
);
647 list_add_tail(&uobj
->list
, &file
->ucontext
->cq_list
);
648 spin_unlock_irq(&file
->ucontext
->lock
);
650 memset(&resp
, 0, sizeof resp
);
651 resp
.cq_handle
= uobj
->id
;
654 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
655 &resp
, sizeof resp
)) {
663 spin_lock_irq(&file
->ucontext
->lock
);
664 list_del(&uobj
->list
);
665 spin_unlock_irq(&file
->ucontext
->lock
);
667 down(&ib_uverbs_idr_mutex
);
668 idr_remove(&ib_uverbs_cq_idr
, uobj
->id
);
669 up(&ib_uverbs_idr_mutex
);
679 ssize_t
ib_uverbs_destroy_cq(struct ib_uverbs_file
*file
,
680 const char __user
*buf
, int in_len
,
683 struct ib_uverbs_destroy_cq cmd
;
685 struct ib_uobject
*uobj
;
688 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
691 down(&ib_uverbs_idr_mutex
);
693 cq
= idr_find(&ib_uverbs_cq_idr
, cmd
.cq_handle
);
694 if (!cq
|| cq
->uobject
->context
!= file
->ucontext
)
699 ret
= ib_destroy_cq(cq
);
703 idr_remove(&ib_uverbs_cq_idr
, cmd
.cq_handle
);
705 spin_lock_irq(&file
->ucontext
->lock
);
706 list_del(&uobj
->list
);
707 spin_unlock_irq(&file
->ucontext
->lock
);
712 up(&ib_uverbs_idr_mutex
);
714 return ret
? ret
: in_len
;
717 ssize_t
ib_uverbs_create_qp(struct ib_uverbs_file
*file
,
718 const char __user
*buf
, int in_len
,
721 struct ib_uverbs_create_qp cmd
;
722 struct ib_uverbs_create_qp_resp resp
;
723 struct ib_udata udata
;
724 struct ib_uobject
*uobj
;
726 struct ib_cq
*scq
, *rcq
;
728 struct ib_qp_init_attr attr
;
731 if (out_len
< sizeof resp
)
734 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
737 INIT_UDATA(&udata
, buf
+ sizeof cmd
,
738 (unsigned long) cmd
.response
+ sizeof resp
,
739 in_len
- sizeof cmd
, out_len
- sizeof resp
);
741 uobj
= kmalloc(sizeof *uobj
, GFP_KERNEL
);
745 down(&ib_uverbs_idr_mutex
);
747 pd
= idr_find(&ib_uverbs_pd_idr
, cmd
.pd_handle
);
748 scq
= idr_find(&ib_uverbs_cq_idr
, cmd
.send_cq_handle
);
749 rcq
= idr_find(&ib_uverbs_cq_idr
, cmd
.recv_cq_handle
);
751 if (!pd
|| pd
->uobject
->context
!= file
->ucontext
||
752 !scq
|| scq
->uobject
->context
!= file
->ucontext
||
753 !rcq
|| rcq
->uobject
->context
!= file
->ucontext
) {
758 attr
.event_handler
= ib_uverbs_qp_event_handler
;
759 attr
.qp_context
= file
;
763 attr
.sq_sig_type
= cmd
.sq_sig_all
? IB_SIGNAL_ALL_WR
: IB_SIGNAL_REQ_WR
;
764 attr
.qp_type
= cmd
.qp_type
;
766 attr
.cap
.max_send_wr
= cmd
.max_send_wr
;
767 attr
.cap
.max_recv_wr
= cmd
.max_recv_wr
;
768 attr
.cap
.max_send_sge
= cmd
.max_send_sge
;
769 attr
.cap
.max_recv_sge
= cmd
.max_recv_sge
;
770 attr
.cap
.max_inline_data
= cmd
.max_inline_data
;
772 uobj
->user_handle
= cmd
.user_handle
;
773 uobj
->context
= file
->ucontext
;
775 qp
= pd
->device
->create_qp(pd
, &attr
, &udata
);
781 qp
->device
= pd
->device
;
783 qp
->send_cq
= attr
.send_cq
;
784 qp
->recv_cq
= attr
.recv_cq
;
787 qp
->event_handler
= attr
.event_handler
;
788 qp
->qp_context
= attr
.qp_context
;
789 qp
->qp_type
= attr
.qp_type
;
790 atomic_inc(&pd
->usecnt
);
791 atomic_inc(&attr
.send_cq
->usecnt
);
792 atomic_inc(&attr
.recv_cq
->usecnt
);
794 atomic_inc(&attr
.srq
->usecnt
);
796 memset(&resp
, 0, sizeof resp
);
797 resp
.qpn
= qp
->qp_num
;
800 if (!idr_pre_get(&ib_uverbs_qp_idr
, GFP_KERNEL
)) {
805 ret
= idr_get_new(&ib_uverbs_qp_idr
, qp
, &uobj
->id
);
812 resp
.qp_handle
= uobj
->id
;
814 spin_lock_irq(&file
->ucontext
->lock
);
815 list_add_tail(&uobj
->list
, &file
->ucontext
->qp_list
);
816 spin_unlock_irq(&file
->ucontext
->lock
);
818 if (copy_to_user((void __user
*) (unsigned long) cmd
.response
,
819 &resp
, sizeof resp
)) {
824 up(&ib_uverbs_idr_mutex
);
829 spin_lock_irq(&file
->ucontext
->lock
);
830 list_del(&uobj
->list
);
831 spin_unlock_irq(&file
->ucontext
->lock
);
837 up(&ib_uverbs_idr_mutex
);
843 ssize_t
ib_uverbs_modify_qp(struct ib_uverbs_file
*file
,
844 const char __user
*buf
, int in_len
,
847 struct ib_uverbs_modify_qp cmd
;
849 struct ib_qp_attr
*attr
;
852 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
855 attr
= kmalloc(sizeof *attr
, GFP_KERNEL
);
859 down(&ib_uverbs_idr_mutex
);
861 qp
= idr_find(&ib_uverbs_qp_idr
, cmd
.qp_handle
);
862 if (!qp
|| qp
->uobject
->context
!= file
->ucontext
) {
867 attr
->qp_state
= cmd
.qp_state
;
868 attr
->cur_qp_state
= cmd
.cur_qp_state
;
869 attr
->path_mtu
= cmd
.path_mtu
;
870 attr
->path_mig_state
= cmd
.path_mig_state
;
871 attr
->qkey
= cmd
.qkey
;
872 attr
->rq_psn
= cmd
.rq_psn
;
873 attr
->sq_psn
= cmd
.sq_psn
;
874 attr
->dest_qp_num
= cmd
.dest_qp_num
;
875 attr
->qp_access_flags
= cmd
.qp_access_flags
;
876 attr
->pkey_index
= cmd
.pkey_index
;
877 attr
->alt_pkey_index
= cmd
.pkey_index
;
878 attr
->en_sqd_async_notify
= cmd
.en_sqd_async_notify
;
879 attr
->max_rd_atomic
= cmd
.max_rd_atomic
;
880 attr
->max_dest_rd_atomic
= cmd
.max_dest_rd_atomic
;
881 attr
->min_rnr_timer
= cmd
.min_rnr_timer
;
882 attr
->port_num
= cmd
.port_num
;
883 attr
->timeout
= cmd
.timeout
;
884 attr
->retry_cnt
= cmd
.retry_cnt
;
885 attr
->rnr_retry
= cmd
.rnr_retry
;
886 attr
->alt_port_num
= cmd
.alt_port_num
;
887 attr
->alt_timeout
= cmd
.alt_timeout
;
889 memcpy(attr
->ah_attr
.grh
.dgid
.raw
, cmd
.dest
.dgid
, 16);
890 attr
->ah_attr
.grh
.flow_label
= cmd
.dest
.flow_label
;
891 attr
->ah_attr
.grh
.sgid_index
= cmd
.dest
.sgid_index
;
892 attr
->ah_attr
.grh
.hop_limit
= cmd
.dest
.hop_limit
;
893 attr
->ah_attr
.grh
.traffic_class
= cmd
.dest
.traffic_class
;
894 attr
->ah_attr
.dlid
= cmd
.dest
.dlid
;
895 attr
->ah_attr
.sl
= cmd
.dest
.sl
;
896 attr
->ah_attr
.src_path_bits
= cmd
.dest
.src_path_bits
;
897 attr
->ah_attr
.static_rate
= cmd
.dest
.static_rate
;
898 attr
->ah_attr
.ah_flags
= cmd
.dest
.is_global
? IB_AH_GRH
: 0;
899 attr
->ah_attr
.port_num
= cmd
.dest
.port_num
;
901 memcpy(attr
->alt_ah_attr
.grh
.dgid
.raw
, cmd
.alt_dest
.dgid
, 16);
902 attr
->alt_ah_attr
.grh
.flow_label
= cmd
.alt_dest
.flow_label
;
903 attr
->alt_ah_attr
.grh
.sgid_index
= cmd
.alt_dest
.sgid_index
;
904 attr
->alt_ah_attr
.grh
.hop_limit
= cmd
.alt_dest
.hop_limit
;
905 attr
->alt_ah_attr
.grh
.traffic_class
= cmd
.alt_dest
.traffic_class
;
906 attr
->alt_ah_attr
.dlid
= cmd
.alt_dest
.dlid
;
907 attr
->alt_ah_attr
.sl
= cmd
.alt_dest
.sl
;
908 attr
->alt_ah_attr
.src_path_bits
= cmd
.alt_dest
.src_path_bits
;
909 attr
->alt_ah_attr
.static_rate
= cmd
.alt_dest
.static_rate
;
910 attr
->alt_ah_attr
.ah_flags
= cmd
.alt_dest
.is_global
? IB_AH_GRH
: 0;
911 attr
->alt_ah_attr
.port_num
= cmd
.alt_dest
.port_num
;
913 ret
= ib_modify_qp(qp
, attr
, cmd
.attr_mask
);
920 up(&ib_uverbs_idr_mutex
);
926 ssize_t
ib_uverbs_destroy_qp(struct ib_uverbs_file
*file
,
927 const char __user
*buf
, int in_len
,
930 struct ib_uverbs_destroy_qp cmd
;
932 struct ib_uobject
*uobj
;
935 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
938 down(&ib_uverbs_idr_mutex
);
940 qp
= idr_find(&ib_uverbs_qp_idr
, cmd
.qp_handle
);
941 if (!qp
|| qp
->uobject
->context
!= file
->ucontext
)
946 ret
= ib_destroy_qp(qp
);
950 idr_remove(&ib_uverbs_qp_idr
, cmd
.qp_handle
);
952 spin_lock_irq(&file
->ucontext
->lock
);
953 list_del(&uobj
->list
);
954 spin_unlock_irq(&file
->ucontext
->lock
);
959 up(&ib_uverbs_idr_mutex
);
961 return ret
? ret
: in_len
;
964 ssize_t
ib_uverbs_attach_mcast(struct ib_uverbs_file
*file
,
965 const char __user
*buf
, int in_len
,
968 struct ib_uverbs_attach_mcast cmd
;
972 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
975 down(&ib_uverbs_idr_mutex
);
977 qp
= idr_find(&ib_uverbs_qp_idr
, cmd
.qp_handle
);
978 if (qp
&& qp
->uobject
->context
== file
->ucontext
)
979 ret
= ib_attach_mcast(qp
, (union ib_gid
*) cmd
.gid
, cmd
.mlid
);
981 up(&ib_uverbs_idr_mutex
);
983 return ret
? ret
: in_len
;
986 ssize_t
ib_uverbs_detach_mcast(struct ib_uverbs_file
*file
,
987 const char __user
*buf
, int in_len
,
990 struct ib_uverbs_detach_mcast cmd
;
994 if (copy_from_user(&cmd
, buf
, sizeof cmd
))
997 down(&ib_uverbs_idr_mutex
);
999 qp
= idr_find(&ib_uverbs_qp_idr
, cmd
.qp_handle
);
1000 if (qp
&& qp
->uobject
->context
== file
->ucontext
)
1001 ret
= ib_detach_mcast(qp
, (union ib_gid
*) cmd
.gid
, cmd
.mlid
);
1003 up(&ib_uverbs_idr_mutex
);
1005 return ret
? ret
: in_len
;