1c39526b7SPramod Gunjikar /*
2c39526b7SPramod Gunjikar  * CDDL HEADER START
3c39526b7SPramod Gunjikar  *
4c39526b7SPramod Gunjikar  * The contents of this file are subject to the terms of the
5c39526b7SPramod Gunjikar  * Common Development and Distribution License (the "License").
6c39526b7SPramod Gunjikar  * You may not use this file except in compliance with the License.
7c39526b7SPramod Gunjikar  *
8c39526b7SPramod Gunjikar  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c39526b7SPramod Gunjikar  * or http://www.opensolaris.org/os/licensing.
10c39526b7SPramod Gunjikar  * See the License for the specific language governing permissions
11c39526b7SPramod Gunjikar  * and limitations under the License.
12c39526b7SPramod Gunjikar  *
13c39526b7SPramod Gunjikar  * When distributing Covered Code, include this CDDL HEADER in each
14c39526b7SPramod Gunjikar  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c39526b7SPramod Gunjikar  * If applicable, add the following below this CDDL HEADER, with the
16c39526b7SPramod Gunjikar  * fields enclosed by brackets "[]" replaced with your own identifying
17c39526b7SPramod Gunjikar  * information: Portions Copyright [yyyy] [name of copyright owner]
18c39526b7SPramod Gunjikar  *
19c39526b7SPramod Gunjikar  * CDDL HEADER END
20c39526b7SPramod Gunjikar  */
21c39526b7SPramod Gunjikar 
22c39526b7SPramod Gunjikar /*
23c39526b7SPramod Gunjikar  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2480d5689fSPatrick Mooney  * Copyright 2017 Joyent, Inc.
25c39526b7SPramod Gunjikar  */
26c39526b7SPramod Gunjikar 
27c39526b7SPramod Gunjikar /*
28c39526b7SPramod Gunjikar  * The sol_ucma driver provides the API for librdmacm library for RDMACM
29c39526b7SPramod Gunjikar  * functionality.
30c39526b7SPramod Gunjikar  *
31c39526b7SPramod Gunjikar  * sol_uverbs will create a minor node with prefix ":ucma",
32c39526b7SPramod Gunjikar  * which can be opened only by the kernel (cred == kcred).
33c39526b7SPramod Gunjikar  *
34c39526b7SPramod Gunjikar  * sol_cma driver will open and close the sol_uverb minor
35c39526b7SPramod Gunjikar  * device using the Layered Driver Interfaces (See PSARC
36c39526b7SPramod Gunjikar  * 2001/769).
37c39526b7SPramod Gunjikar  */
38c39526b7SPramod Gunjikar 
39c39526b7SPramod Gunjikar /* Standard driver includes */
40c39526b7SPramod Gunjikar #include <sys/types.h>
41c39526b7SPramod Gunjikar #include <sys/modctl.h>
42c39526b7SPramod Gunjikar #include <sys/ddi.h>
43c39526b7SPramod Gunjikar #include <sys/sunddi.h>
44c39526b7SPramod Gunjikar #include <sys/file.h>
45c39526b7SPramod Gunjikar #include <sys/errno.h>
46c39526b7SPramod Gunjikar #include <sys/open.h>
47c39526b7SPramod Gunjikar #include <sys/cred.h>
48c39526b7SPramod Gunjikar #include <sys/stat.h>
49c39526b7SPramod Gunjikar #include <sys/ddi.h>
50c39526b7SPramod Gunjikar #include <sys/sunddi.h>
51c39526b7SPramod Gunjikar #include <sys/conf.h>
52c39526b7SPramod Gunjikar #include <sys/uio.h>
53c39526b7SPramod Gunjikar #include <sys/sunldi.h>
54c39526b7SPramod Gunjikar #include <sys/modctl.h>
55c39526b7SPramod Gunjikar 
56c39526b7SPramod Gunjikar /* Common header files */
57c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
58c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs2ucma.h>
59c39526b7SPramod Gunjikar #include <sys/ib/clients/of/ofed_kernel.h>
60c39526b7SPramod Gunjikar 
61c39526b7SPramod Gunjikar /* Kernel Headers for User rdma_cm API */
62c39526b7SPramod Gunjikar #include <sys/ib/clients/of/rdma/ib_addr.h>
63c39526b7SPramod Gunjikar #include <sys/ib/clients/of/rdma/rdma_user_cm.h>
64c39526b7SPramod Gunjikar 
65c39526b7SPramod Gunjikar /* Kernel rdma_cm API */
66c39526b7SPramod Gunjikar #include <sys/ib/clients/of/rdma/rdma_cm.h>
67c39526b7SPramod Gunjikar 
68c39526b7SPramod Gunjikar /* sol_ucma internal Header files */
69c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_ucma/sol_ucma.h>
70c39526b7SPramod Gunjikar 
71c39526b7SPramod Gunjikar /* entry point function prototype declarations */
72c39526b7SPramod Gunjikar static int sol_ucma_attach(dev_info_t *, ddi_attach_cmd_t);
73c39526b7SPramod Gunjikar static int sol_ucma_detach(dev_info_t *, ddi_detach_cmd_t);
74c39526b7SPramod Gunjikar static int sol_ucma_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
75c39526b7SPramod Gunjikar static int sol_ucma_open(dev_t *, int, int, cred_t *);
76c39526b7SPramod Gunjikar static int sol_ucma_close(dev_t, int, int, cred_t *);
77c39526b7SPramod Gunjikar static int sol_ucma_write(dev_t, struct uio *,  cred_t *);
78c39526b7SPramod Gunjikar static int sol_ucma_poll(dev_t, short, int, short *, struct pollhead **);
79c39526b7SPramod Gunjikar 
80c39526b7SPramod Gunjikar /* Driver entry points */
81c39526b7SPramod Gunjikar static struct cb_ops	sol_ucma_cb_ops = {
82c39526b7SPramod Gunjikar 	sol_ucma_open,		/* open */
83c39526b7SPramod Gunjikar 	sol_ucma_close,		/* close */
84c39526b7SPramod Gunjikar 	nodev,			/* strategy (block) */
85c39526b7SPramod Gunjikar 	nodev,			/* print (block) */
86c39526b7SPramod Gunjikar 	nodev,			/* dump (block) */
87c39526b7SPramod Gunjikar 	nodev,			/* read */
88c39526b7SPramod Gunjikar 	sol_ucma_write,		/* write */
89c39526b7SPramod Gunjikar 	nodev,			/* ioctl */
90c39526b7SPramod Gunjikar 	nodev,			/* devmap */
91c39526b7SPramod Gunjikar 	nodev,			/* mmap */
92c39526b7SPramod Gunjikar 	nodev,			/* segmap */
93c39526b7SPramod Gunjikar 	sol_ucma_poll,		/* chpoll */
94c39526b7SPramod Gunjikar 	ddi_prop_op,		/* prop_op */
95c39526b7SPramod Gunjikar 	NULL,			/* streams */
96c39526b7SPramod Gunjikar 	D_NEW | D_MP | D_64BIT,	/* flags */
97c39526b7SPramod Gunjikar 	CB_REV			/* rev */
98c39526b7SPramod Gunjikar };
99c39526b7SPramod Gunjikar 
100c39526b7SPramod Gunjikar /* Driver operations */
101c39526b7SPramod Gunjikar static struct dev_ops	sol_ucma_dev_ops = {
102c39526b7SPramod Gunjikar 	DEVO_REV,		/* struct rev */
103c39526b7SPramod Gunjikar 	0,			/* refcnt */
104c39526b7SPramod Gunjikar 	sol_ucma_getinfo,	/* getinfo */
105c39526b7SPramod Gunjikar 	nulldev,		/* identify */
106c39526b7SPramod Gunjikar 	nulldev,		/* probe */
107c39526b7SPramod Gunjikar 	sol_ucma_attach,	/* attach */
108c39526b7SPramod Gunjikar 	sol_ucma_detach,	/* detach */
109c39526b7SPramod Gunjikar 	nodev,			/* reset */
110c39526b7SPramod Gunjikar 	&sol_ucma_cb_ops,	/* cb_ops */
111c39526b7SPramod Gunjikar 	NULL,			/* bus_ops */
112c39526b7SPramod Gunjikar 	nodev,			/* power */
113c39526b7SPramod Gunjikar 	ddi_quiesce_not_needed	/* quiesce */
114c39526b7SPramod Gunjikar };
115c39526b7SPramod Gunjikar 
116c39526b7SPramod Gunjikar /* Module Driver Info */
117c39526b7SPramod Gunjikar static struct modldrv sol_ucma_modldrv = {
118c39526b7SPramod Gunjikar 	&mod_driverops,
119c39526b7SPramod Gunjikar 	"Solaris User RDMACM driver",
120c39526b7SPramod Gunjikar 	&sol_ucma_dev_ops
121c39526b7SPramod Gunjikar };
122c39526b7SPramod Gunjikar 
123c39526b7SPramod Gunjikar /* Module Linkage */
124c39526b7SPramod Gunjikar static struct modlinkage sol_ucma_modlinkage = {
125c39526b7SPramod Gunjikar 	MODREV_1,
126c39526b7SPramod Gunjikar 	&sol_ucma_modldrv,
127c39526b7SPramod Gunjikar 	NULL,
128c39526b7SPramod Gunjikar };
129c39526b7SPramod Gunjikar 
130c39526b7SPramod Gunjikar static char	*sol_ucma_dbg_str = "sol_ucma";
131c39526b7SPramod Gunjikar sol_ofs_uobj_table_t	ucma_file_uo_tbl;
132c39526b7SPramod Gunjikar sol_ofs_uobj_table_t	ucma_ctx_uo_tbl;
133c39526b7SPramod Gunjikar sol_ofs_uobj_table_t	ucma_mcast_uo_tbl;
134c39526b7SPramod Gunjikar 
135c39526b7SPramod Gunjikar /* Function pointers for uverbs functions */
136c39526b7SPramod Gunjikar static uverbs_get_clnt_hdl_t		uverbs_get_hdl_fp = NULL;
137c39526b7SPramod Gunjikar static uverbs_qpnum2qphdl_t		uverbs_qpnum2qphdl_fp = NULL;
138c39526b7SPramod Gunjikar static uverbs_disable_uqpn_mod_t	uverbs_disable_uqpn_modify_fp = NULL;
139c39526b7SPramod Gunjikar static uverbs_uqpn_cq_ctrl_t		uverbs_uqpn_cq_ctrl_fp = NULL;
140c39526b7SPramod Gunjikar static uverbs_set_qp_free_state_t	uverbs_set_qp_free_state_fp = NULL;
141c39526b7SPramod Gunjikar static uverbs_flush_qp_t		uverbs_flush_qp_fp = NULL;
142c39526b7SPramod Gunjikar 
143c39526b7SPramod Gunjikar /* Global Variables */
144c39526b7SPramod Gunjikar sol_ucma_t	sol_ucma;
145c39526b7SPramod Gunjikar 
146c39526b7SPramod Gunjikar /* RDMACM Functions  */
147c39526b7SPramod Gunjikar static int	sol_ucma_create_id(dev_t, void *, struct uio *);
148c39526b7SPramod Gunjikar static int	sol_ucma_destroy_id(dev_t, void *, struct uio *);
149c39526b7SPramod Gunjikar static int	sol_ucma_bind_addr(dev_t, void *, struct uio *);
150c39526b7SPramod Gunjikar static int	sol_ucma_resolve_addr(dev_t, void *, struct uio *);
151c39526b7SPramod Gunjikar static int	sol_ucma_resolve_route(dev_t, void *, struct uio *);
152c39526b7SPramod Gunjikar static int	sol_ucma_query_route(dev_t, void *, struct uio *);
153c39526b7SPramod Gunjikar static int	sol_ucma_connect(dev_t, void *, struct uio *);
154c39526b7SPramod Gunjikar static int	sol_ucma_listen(dev_t, void *, struct uio *);
155c39526b7SPramod Gunjikar static int	sol_ucma_accept(dev_t, void *, struct uio *);
156c39526b7SPramod Gunjikar static int	sol_ucma_reject(dev_t, void *, struct uio *);
157c39526b7SPramod Gunjikar static int	sol_ucma_disconnect(dev_t, void *, struct uio *);
158c39526b7SPramod Gunjikar static int	sol_ucma_init_qp_attr(dev_t, void *, struct uio *);
159c39526b7SPramod Gunjikar static int	sol_ucma_get_event(dev_t, void *, struct uio *);
160c39526b7SPramod Gunjikar static int	sol_ucma_set_option(dev_t, void *, struct uio *);
161c39526b7SPramod Gunjikar static int	sol_ucma_notify(dev_t, void *, struct uio *);
162c39526b7SPramod Gunjikar static int	sol_ucma_join_mcast(dev_t, void *, struct uio *);
163c39526b7SPramod Gunjikar static int	sol_ucma_leave_mcast(dev_t, void *, struct uio *);
164c39526b7SPramod Gunjikar 
165c39526b7SPramod Gunjikar /*
166c39526b7SPramod Gunjikar  * Event callback from sol_cma
167c39526b7SPramod Gunjikar  */
168c39526b7SPramod Gunjikar int sol_ucma_evt_hdlr(struct rdma_cm_id *, struct rdma_cm_event *);
169c39526b7SPramod Gunjikar 
170c39526b7SPramod Gunjikar /*
171c39526b7SPramod Gunjikar  * Internal functions.
172c39526b7SPramod Gunjikar  */
173c39526b7SPramod Gunjikar static sol_ucma_file_t	*
174c39526b7SPramod Gunjikar ucma_alloc_file(minor_t *);
175c39526b7SPramod Gunjikar 
176c39526b7SPramod Gunjikar static sol_ucma_chan_t *
177c39526b7SPramod Gunjikar ucma_alloc_chan(sol_ucma_file_t *, sol_ucma_create_id_t *);
178c39526b7SPramod Gunjikar 
179c39526b7SPramod Gunjikar static void
180c39526b7SPramod Gunjikar ucma_free_chan(sol_ucma_chan_t *, int);
181c39526b7SPramod Gunjikar 
182c39526b7SPramod Gunjikar static int
183c39526b7SPramod Gunjikar get_file_chan(uint32_t, sol_ucma_file_t **, sol_ucma_chan_t **, char *, int);
184c39526b7SPramod Gunjikar 
185c39526b7SPramod Gunjikar static void
186c39526b7SPramod Gunjikar rdma2usr_route(struct rdma_cm_id *, sol_ucma_query_route_resp_t *);
187c39526b7SPramod Gunjikar 
188c39526b7SPramod Gunjikar static void
189c39526b7SPramod Gunjikar usr2rdma_conn_param(struct rdma_ucm_conn_param *, struct rdma_conn_param *);
190c39526b7SPramod Gunjikar 
191c39526b7SPramod Gunjikar static void
192c39526b7SPramod Gunjikar rdma2usr_conn_param(struct rdma_conn_param *, struct rdma_ucm_conn_param *);
193c39526b7SPramod Gunjikar 
194c39526b7SPramod Gunjikar static void
195c39526b7SPramod Gunjikar rdma2usr_ud_param(struct rdma_ud_param *, sol_ucma_ud_param_t *);
196c39526b7SPramod Gunjikar 
197c39526b7SPramod Gunjikar static void	sol_ucma_user_objs_init();
198c39526b7SPramod Gunjikar static void	sol_ucma_user_objs_fini();
199c39526b7SPramod Gunjikar 
200c39526b7SPramod Gunjikar int
_init(void)201c39526b7SPramod Gunjikar _init(void)
202c39526b7SPramod Gunjikar {
203c39526b7SPramod Gunjikar 	int error;
204c39526b7SPramod Gunjikar 
205c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_init()");
206c39526b7SPramod Gunjikar 	sol_ucma_user_objs_init();
207c39526b7SPramod Gunjikar 	mutex_init(&sol_ucma.ucma_mutex, NULL, MUTEX_DRIVER, NULL);
208c39526b7SPramod Gunjikar 	cv_init(&sol_ucma.ucma_open_cv, NULL, CV_DRIVER, NULL);
209c39526b7SPramod Gunjikar 
210c39526b7SPramod Gunjikar 	if ((error = ldi_ident_from_mod(&sol_ucma_modlinkage,
211c39526b7SPramod Gunjikar 	    &sol_ucma.ucma_ldi_ident)) != 0) {
212c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
213c39526b7SPramod Gunjikar 		    "ldi_ident_from_mod() failed");
214c39526b7SPramod Gunjikar 		mutex_destroy(&sol_ucma.ucma_mutex);
215c39526b7SPramod Gunjikar 		cv_destroy(&sol_ucma.ucma_open_cv);
216c39526b7SPramod Gunjikar 		sol_ucma_user_objs_fini();
217c39526b7SPramod Gunjikar 		return (error);
218c39526b7SPramod Gunjikar 	}
219c39526b7SPramod Gunjikar 	sol_ucma.ucma_clnt_hdl_flag = SOL_UCMA_CLNT_HDL_UNINITIALIZED;
220c39526b7SPramod Gunjikar 	error = mod_install(&sol_ucma_modlinkage);
221c39526b7SPramod Gunjikar 	if (error) {
222c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "mod_install() failed");
223c39526b7SPramod Gunjikar 		ldi_ident_release(sol_ucma.ucma_ldi_ident);
224c39526b7SPramod Gunjikar 		mutex_destroy(&sol_ucma.ucma_mutex);
225c39526b7SPramod Gunjikar 		cv_destroy(&sol_ucma.ucma_open_cv);
226c39526b7SPramod Gunjikar 		sol_ucma_user_objs_fini();
227c39526b7SPramod Gunjikar 		return (error);
228c39526b7SPramod Gunjikar 	}
229c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_init(): ret");
230c39526b7SPramod Gunjikar 	return (error);
231c39526b7SPramod Gunjikar }
232c39526b7SPramod Gunjikar 
233c39526b7SPramod Gunjikar int
_info(struct modinfo * modinfop)234c39526b7SPramod Gunjikar _info(struct modinfo *modinfop)
235c39526b7SPramod Gunjikar {
236c39526b7SPramod Gunjikar 	return (mod_info(&sol_ucma_modlinkage, modinfop));
237c39526b7SPramod Gunjikar }
238c39526b7SPramod Gunjikar 
239c39526b7SPramod Gunjikar int
_fini(void)240c39526b7SPramod Gunjikar _fini(void)
241c39526b7SPramod Gunjikar {
242c39526b7SPramod Gunjikar 	int ret;
243c39526b7SPramod Gunjikar 
244c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_fini()");
245c39526b7SPramod Gunjikar 	if ((ret = mod_remove(&sol_ucma_modlinkage)) != 0) {
246c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str,
247c39526b7SPramod Gunjikar 		    "sol_ucma, _fini : mod_remove failed");
248c39526b7SPramod Gunjikar 		return (ret);
249c39526b7SPramod Gunjikar 	}
250c39526b7SPramod Gunjikar 	ldi_ident_release(sol_ucma.ucma_ldi_ident);
251c39526b7SPramod Gunjikar 	mutex_destroy(&sol_ucma.ucma_mutex);
252c39526b7SPramod Gunjikar 	cv_destroy(&sol_ucma.ucma_open_cv);
253c39526b7SPramod Gunjikar 	sol_ucma_user_objs_fini();
254c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_fini(): ret");
255c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
256c39526b7SPramod Gunjikar }
257c39526b7SPramod Gunjikar 
258c39526b7SPramod Gunjikar static int
sol_ucma_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)259c39526b7SPramod Gunjikar sol_ucma_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
260c39526b7SPramod Gunjikar {
261c39526b7SPramod Gunjikar 	int	rval;
262c39526b7SPramod Gunjikar 
263c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "attach(%p, %x)", dip, cmd);
264c39526b7SPramod Gunjikar 
265c39526b7SPramod Gunjikar 	switch (cmd) {
266c39526b7SPramod Gunjikar 	case DDI_ATTACH:
267c39526b7SPramod Gunjikar 		mutex_enter(&sol_ucma.ucma_mutex);
268c39526b7SPramod Gunjikar 		if (sol_ucma.ucma_dip != NULL) {
269c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
270c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
271c39526b7SPramod Gunjikar 			    "attach: failed, > 1 instance");
272c39526b7SPramod Gunjikar 			return (DDI_FAILURE);
273c39526b7SPramod Gunjikar 		}
274c39526b7SPramod Gunjikar 		sol_ucma.ucma_dip = dip;
275c39526b7SPramod Gunjikar 		mutex_exit(&sol_ucma.ucma_mutex);
276c39526b7SPramod Gunjikar 
277c39526b7SPramod Gunjikar 		rval = ddi_create_minor_node(dip, "sol_ucma", S_IFCHR,
278c39526b7SPramod Gunjikar 		    0, DDI_PSEUDO, 0);
279c39526b7SPramod Gunjikar 		if (rval != DDI_SUCCESS) {
280c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
281c39526b7SPramod Gunjikar 			    "attach: ddi_create_minor_node failed");
282c39526b7SPramod Gunjikar 			mutex_enter(&sol_ucma.ucma_mutex);
283c39526b7SPramod Gunjikar 			sol_ucma.ucma_dip = NULL;
284c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
285c39526b7SPramod Gunjikar 			return (DDI_FAILURE);
286c39526b7SPramod Gunjikar 		}
287c39526b7SPramod Gunjikar 
288c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str,
289c39526b7SPramod Gunjikar 		    "attach : DDI_ATTACH success");
290c39526b7SPramod Gunjikar 		return (DDI_SUCCESS);
291c39526b7SPramod Gunjikar 	case DDI_RESUME:
292c39526b7SPramod Gunjikar 		return (DDI_SUCCESS);
293c39526b7SPramod Gunjikar 	default:
294c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
295c39526b7SPramod Gunjikar 	}
296c39526b7SPramod Gunjikar }
297c39526b7SPramod Gunjikar 
298c39526b7SPramod Gunjikar static int
sol_ucma_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)299c39526b7SPramod Gunjikar sol_ucma_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
300c39526b7SPramod Gunjikar {
301c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "detach(%p, %x)", dip, cmd);
302c39526b7SPramod Gunjikar 
303c39526b7SPramod Gunjikar 	switch (cmd) {
304c39526b7SPramod Gunjikar 	case DDI_DETACH:
305c39526b7SPramod Gunjikar 		mutex_enter(&sol_ucma.ucma_mutex);
306c39526b7SPramod Gunjikar 		if (sol_ucma.ucma_num_file) {
307c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
308c39526b7SPramod Gunjikar 			    "detach : %x files not closed",
309c39526b7SPramod Gunjikar 			    sol_ucma.ucma_num_file);
310c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
311c39526b7SPramod Gunjikar 			return (DDI_FAILURE);
312c39526b7SPramod Gunjikar 		}
313c39526b7SPramod Gunjikar 		sol_ucma.ucma_dip = NULL;
314c39526b7SPramod Gunjikar 		mutex_exit(&sol_ucma.ucma_mutex);
315c39526b7SPramod Gunjikar 
316c39526b7SPramod Gunjikar 		ddi_remove_minor_node(dip, "sol_ucma");
317c39526b7SPramod Gunjikar 
318c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str,
319c39526b7SPramod Gunjikar 		    "detach : DDI_DETACH success");
320c39526b7SPramod Gunjikar 		return (DDI_SUCCESS);
321c39526b7SPramod Gunjikar 	case DDI_SUSPEND:
322c39526b7SPramod Gunjikar 		return (DDI_SUCCESS);
323c39526b7SPramod Gunjikar 	default:
324c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
325c39526b7SPramod Gunjikar 	}
326c39526b7SPramod Gunjikar }
327c39526b7SPramod Gunjikar 
328c39526b7SPramod Gunjikar /*ARGSUSED*/
329c39526b7SPramod Gunjikar static int
sol_ucma_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)330c39526b7SPramod Gunjikar sol_ucma_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
331c39526b7SPramod Gunjikar     void **resultp)
332c39526b7SPramod Gunjikar {
333c39526b7SPramod Gunjikar 	switch (cmd) {
334c39526b7SPramod Gunjikar 	case DDI_INFO_DEVT2DEVINFO:
335c39526b7SPramod Gunjikar 		*resultp = (void *)sol_ucma.ucma_dip;
336c39526b7SPramod Gunjikar 		return (DDI_SUCCESS);
337c39526b7SPramod Gunjikar 	case DDI_INFO_DEVT2INSTANCE:
338c39526b7SPramod Gunjikar 		*resultp = (void *)0;
339c39526b7SPramod Gunjikar 		return (DDI_SUCCESS);
340c39526b7SPramod Gunjikar 	default :
341c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
342c39526b7SPramod Gunjikar 	}
343c39526b7SPramod Gunjikar }
344c39526b7SPramod Gunjikar 
345c39526b7SPramod Gunjikar static int
sol_ucma_open(dev_t * devp,int flag,int otype,cred_t * credp)346c39526b7SPramod Gunjikar sol_ucma_open(dev_t *devp, int flag, int otype, cred_t *credp)
347c39526b7SPramod Gunjikar {
348c39526b7SPramod Gunjikar 	sol_ucma_file_t	*new_filep;
349c39526b7SPramod Gunjikar 	minor_t		new_minor;
350c39526b7SPramod Gunjikar 
351c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "open(%p, %x, %x, %p)",
352c39526b7SPramod Gunjikar 	    devp, flag, otype, credp);
353c39526b7SPramod Gunjikar 
354c39526b7SPramod Gunjikar 	new_filep = ucma_alloc_file(&new_minor);
355c39526b7SPramod Gunjikar 	if (new_filep == NULL)
356c39526b7SPramod Gunjikar 		return (EAGAIN);
357c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str, "sol_ucma new minor %x",
358c39526b7SPramod Gunjikar 	    new_minor);
359c39526b7SPramod Gunjikar 
360c39526b7SPramod Gunjikar 	/*
361c39526b7SPramod Gunjikar 	 * For the first open, ensure that the sol_uverbs driver is attached.
362c39526b7SPramod Gunjikar 	 * Also get the function pointers for uverbs API functions using
363c39526b7SPramod Gunjikar 	 * ddi_modopen() and ddi_modsym() for the sol_uverbs driver.
364c39526b7SPramod Gunjikar 	 *
365c39526b7SPramod Gunjikar 	 * ldi_open() is done to ensure that sol_uverbs driver is attached,
366c39526b7SPramod Gunjikar 	 * even though ddi_modopen is sufficient to get the function pointers
367c39526b7SPramod Gunjikar 	 * for the uverbs APIs
368c39526b7SPramod Gunjikar 	 */
369c39526b7SPramod Gunjikar 	mutex_enter(&sol_ucma.ucma_mutex);
370c39526b7SPramod Gunjikar 	if (sol_ucma.ucma_clnt_hdl_flag == SOL_UCMA_CLNT_HDL_UNINITIALIZED) {
371c39526b7SPramod Gunjikar 		int	rval, ret_errno;
372c39526b7SPramod Gunjikar 
373c39526b7SPramod Gunjikar 		sol_ucma.ucma_clnt_hdl_flag =
374c39526b7SPramod Gunjikar 		    SOL_UCMA_CLNT_HDL_INITIALIZING;
375c39526b7SPramod Gunjikar 		if ((rval = ldi_open_by_name(SOL_UCMA_UVERBS_PATH,
376c39526b7SPramod Gunjikar 		    FREAD | FWRITE, kcred, &sol_ucma.ucma_ldi_hdl,
377c39526b7SPramod Gunjikar 		    sol_ucma.ucma_ldi_ident)) != 0) {
378c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
379c39526b7SPramod Gunjikar 			    "ldi_open_by_name(%s, ...) failed with rval %x",
380c39526b7SPramod Gunjikar 			    SOL_UCMA_UVERBS_PATH, rval);
381c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
382c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
383c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
384c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
385c39526b7SPramod Gunjikar 			return (ENODEV);
386c39526b7SPramod Gunjikar 		}
387c39526b7SPramod Gunjikar 		if ((sol_ucma.ucma_mod_hdl = ddi_modopen("drv/sol_uverbs",
388c39526b7SPramod Gunjikar 		    KRTLD_MODE_FIRST, &ret_errno)) == NULL) {
389c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
390c39526b7SPramod Gunjikar 			    "ddi_modopen(%s, ...) failed", "drv/sol_uverbs");
391c39526b7SPramod Gunjikar 			(void) ldi_close(sol_ucma.ucma_ldi_hdl,
392c39526b7SPramod Gunjikar 			    FREAD | FWRITE, kcred);
393c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
394c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
395c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
396c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
397c39526b7SPramod Gunjikar 			return (ret_errno);
398c39526b7SPramod Gunjikar 		}
399c39526b7SPramod Gunjikar 		if ((uverbs_get_hdl_fp = (uverbs_get_clnt_hdl_t)ddi_modsym(
400c39526b7SPramod Gunjikar 		    sol_ucma.ucma_mod_hdl, SOL_UVERBS_GET_CLNT_HDL, &ret_errno))
401c39526b7SPramod Gunjikar 		    == NULL) {
402c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
403c39526b7SPramod Gunjikar 			    "ddi_modsym(%s, ...) failed",
404c39526b7SPramod Gunjikar 			    SOL_UVERBS_GET_CLNT_HDL);
405c39526b7SPramod Gunjikar 			(void) ddi_modclose(sol_ucma.ucma_mod_hdl);
406c39526b7SPramod Gunjikar 			(void) ldi_close(sol_ucma.ucma_ldi_hdl,
407c39526b7SPramod Gunjikar 			    FREAD | FWRITE, kcred);
408c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
409c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
410c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
411c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
412c39526b7SPramod Gunjikar 			return (ret_errno);
413c39526b7SPramod Gunjikar 		}
414c39526b7SPramod Gunjikar 		if ((uverbs_qpnum2qphdl_fp = (uverbs_qpnum2qphdl_t)ddi_modsym(
415c39526b7SPramod Gunjikar 		    sol_ucma.ucma_mod_hdl, SOL_UVERBS_QPNUM2QPHDL, &ret_errno))
416c39526b7SPramod Gunjikar 		    == NULL) {
417c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
418c39526b7SPramod Gunjikar 			    "ddi_modsym(%s, ...) failed",
419c39526b7SPramod Gunjikar 			    SOL_UVERBS_QPNUM2QPHDL);
420c39526b7SPramod Gunjikar 			(void) ddi_modclose(sol_ucma.ucma_mod_hdl);
421c39526b7SPramod Gunjikar 			(void) ldi_close(sol_ucma.ucma_ldi_hdl,
422c39526b7SPramod Gunjikar 			    FREAD | FWRITE, kcred);
423c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
424c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
425c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
426c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
427c39526b7SPramod Gunjikar 			return (ret_errno);
428c39526b7SPramod Gunjikar 		}
429c39526b7SPramod Gunjikar 		if ((uverbs_disable_uqpn_modify_fp =
430c39526b7SPramod Gunjikar 		    (uverbs_disable_uqpn_mod_t)ddi_modsym(
431c39526b7SPramod Gunjikar 		    sol_ucma.ucma_mod_hdl, SOL_UVERBS_DISABLE_UQPN_MODIFY,
432c39526b7SPramod Gunjikar 		    &ret_errno)) == NULL) {
433c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
434c39526b7SPramod Gunjikar 			    "ddi_modsym(%s, ...) failed",
435c39526b7SPramod Gunjikar 			    SOL_UVERBS_DISABLE_UQPN_MODIFY);
436c39526b7SPramod Gunjikar 			(void) ddi_modclose(sol_ucma.ucma_mod_hdl);
437c39526b7SPramod Gunjikar 			(void) ldi_close(sol_ucma.ucma_ldi_hdl,
438c39526b7SPramod Gunjikar 			    FREAD | FWRITE, kcred);
439c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
440c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
441c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
442c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
443c39526b7SPramod Gunjikar 			return (ret_errno);
444c39526b7SPramod Gunjikar 		}
445c39526b7SPramod Gunjikar 		if ((uverbs_uqpn_cq_ctrl_fp =
446c39526b7SPramod Gunjikar 		    (uverbs_uqpn_cq_ctrl_t)ddi_modsym(
447c39526b7SPramod Gunjikar 		    sol_ucma.ucma_mod_hdl, SOL_UVERBS_UQPN_CQ_CTRL,
448c39526b7SPramod Gunjikar 		    &ret_errno)) == NULL) {
449c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
450c39526b7SPramod Gunjikar 			    "ddi_modsym(%s, ...) failed",
451c39526b7SPramod Gunjikar 			    SOL_UVERBS_UQPN_CQ_CTRL);
452c39526b7SPramod Gunjikar 			(void) ddi_modclose(sol_ucma.ucma_mod_hdl);
453c39526b7SPramod Gunjikar 			(void) ldi_close(sol_ucma.ucma_ldi_hdl,
454c39526b7SPramod Gunjikar 			    FREAD | FWRITE, kcred);
455c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
456c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
457c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
458c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
459c39526b7SPramod Gunjikar 			return (ret_errno);
460c39526b7SPramod Gunjikar 		}
461c39526b7SPramod Gunjikar 		if ((uverbs_set_qp_free_state_fp =
462c39526b7SPramod Gunjikar 		    (uverbs_set_qp_free_state_t)ddi_modsym(
463c39526b7SPramod Gunjikar 		    sol_ucma.ucma_mod_hdl, SOL_UVERBS_SET_QPFREE_STATE,
464c39526b7SPramod Gunjikar 		    &ret_errno)) == NULL) {
465c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
466c39526b7SPramod Gunjikar 			    "ddi_modsym(%s, ...) failed",
467c39526b7SPramod Gunjikar 			    SOL_UVERBS_SET_QPFREE_STATE);
468c39526b7SPramod Gunjikar 			(void) ddi_modclose(sol_ucma.ucma_mod_hdl);
469c39526b7SPramod Gunjikar 			(void) ldi_close(sol_ucma.ucma_ldi_hdl,
470c39526b7SPramod Gunjikar 			    FREAD | FWRITE, kcred);
471c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
472c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
473c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
474c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
475c39526b7SPramod Gunjikar 			return (ret_errno);
476c39526b7SPramod Gunjikar 		}
477c39526b7SPramod Gunjikar 		if ((uverbs_flush_qp_fp =
478c39526b7SPramod Gunjikar 		    (uverbs_flush_qp_t)ddi_modsym(
479c39526b7SPramod Gunjikar 		    sol_ucma.ucma_mod_hdl, SOL_UVERBS_FLUSH_QP,
480c39526b7SPramod Gunjikar 		    &ret_errno)) == NULL) {
481c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
482c39526b7SPramod Gunjikar 			    "ddi_modsym(%s, ...) failed",
483c39526b7SPramod Gunjikar 			    SOL_UVERBS_FLUSH_QP);
484c39526b7SPramod Gunjikar 			(void) ddi_modclose(sol_ucma.ucma_mod_hdl);
485c39526b7SPramod Gunjikar 			(void) ldi_close(sol_ucma.ucma_ldi_hdl,
486c39526b7SPramod Gunjikar 			    FREAD | FWRITE, kcred);
487c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
488c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
489c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
490c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
491c39526b7SPramod Gunjikar 			return (ret_errno);
492c39526b7SPramod Gunjikar 		}
493c39526b7SPramod Gunjikar 
494c39526b7SPramod Gunjikar 		(*uverbs_get_hdl_fp) (&sol_ucma.ucma_ib_clnt_hdl,
495c39526b7SPramod Gunjikar 		    &sol_ucma.ucma_iw_clnt_hdl);
496c39526b7SPramod Gunjikar 		if (sol_ucma.ucma_ib_clnt_hdl == NULL &&
497c39526b7SPramod Gunjikar 		    sol_ucma.ucma_iw_clnt_hdl == NULL) {
498c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
499c39526b7SPramod Gunjikar 			    "uverbs_get_clnt_hdl failed");
500c39526b7SPramod Gunjikar 			(void) ddi_modclose(sol_ucma.ucma_mod_hdl);
501c39526b7SPramod Gunjikar 			(void) ldi_close(sol_ucma.ucma_ldi_hdl,
502c39526b7SPramod Gunjikar 			    FREAD | FWRITE, kcred);
503c39526b7SPramod Gunjikar 			sol_ofs_uobj_free(&new_filep->file_uobj);
504c39526b7SPramod Gunjikar 			sol_ucma.ucma_clnt_hdl_flag =
505c39526b7SPramod Gunjikar 			    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
506c39526b7SPramod Gunjikar 			mutex_exit(&sol_ucma.ucma_mutex);
507c39526b7SPramod Gunjikar 			return (ENODEV);
508c39526b7SPramod Gunjikar 		}
509c39526b7SPramod Gunjikar 		sol_ucma.ucma_clnt_hdl_flag =
510c39526b7SPramod Gunjikar 		    SOL_UCMA_CLNT_HDL_INITIALIZED;
511c39526b7SPramod Gunjikar 		cv_broadcast(&sol_ucma.ucma_open_cv);
512c39526b7SPramod Gunjikar 	} else if (sol_ucma.ucma_clnt_hdl_flag ==
513c39526b7SPramod Gunjikar 	    SOL_UCMA_CLNT_HDL_INITIALIZING) {
514c39526b7SPramod Gunjikar 		cv_wait(&sol_ucma.ucma_open_cv, &sol_ucma.ucma_mutex);
515c39526b7SPramod Gunjikar 	}
516c39526b7SPramod Gunjikar 	mutex_exit(&sol_ucma.ucma_mutex);
517c39526b7SPramod Gunjikar 	*devp = makedevice(getmajor(*devp), new_minor);
518c39526b7SPramod Gunjikar 
519c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "open Success");
520c39526b7SPramod Gunjikar 	return (0);
521c39526b7SPramod Gunjikar }
522c39526b7SPramod Gunjikar 
523c39526b7SPramod Gunjikar static int
sol_ucma_close(dev_t dev,int flag,int otype,cred_t * credp)524c39526b7SPramod Gunjikar sol_ucma_close(dev_t dev, int flag, int otype, cred_t *credp)
525c39526b7SPramod Gunjikar {
526c39526b7SPramod Gunjikar 	minor_t		minor;
527c39526b7SPramod Gunjikar 	sol_ucma_file_t	*filep;
528c39526b7SPramod Gunjikar 	genlist_entry_t	*entry;
529c39526b7SPramod Gunjikar 
530c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "close(%x, %x, %x, %p)",
531c39526b7SPramod Gunjikar 	    dev, flag, otype, credp);
532c39526b7SPramod Gunjikar 
533c39526b7SPramod Gunjikar 	minor = getminor(dev);
534c39526b7SPramod Gunjikar 	filep =  (sol_ucma_file_t *)sol_ofs_uobj_get_read(
535c39526b7SPramod Gunjikar 	    &ucma_file_uo_tbl, minor);
536c39526b7SPramod Gunjikar 	if (!filep) {
537c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str, "close, no dev_t %x",
538c39526b7SPramod Gunjikar 		    dev);
539c39526b7SPramod Gunjikar 		return (0);
540c39526b7SPramod Gunjikar 	}
541c39526b7SPramod Gunjikar 
542c39526b7SPramod Gunjikar 	/* Disable further event handling for this CM event channel */
543c39526b7SPramod Gunjikar 	mutex_enter(&filep->file_mutex);
544c39526b7SPramod Gunjikar 	if (filep->file_evt_close_flag == SOL_UCMA_EVT_PROGRESS) {
545c39526b7SPramod Gunjikar 		cv_wait(&filep->file_evt_close_cv, &filep->file_mutex);
546c39526b7SPramod Gunjikar 	}
547c39526b7SPramod Gunjikar 	filep->file_evt_close_flag = SOL_UCMA_EVT_DISABLED;
548c39526b7SPramod Gunjikar 	mutex_exit(&filep->file_mutex);
549c39526b7SPramod Gunjikar 
550c39526b7SPramod Gunjikar 	/*
551c39526b7SPramod Gunjikar 	 * Destroy CM IDs which have not been destroyed.
552c39526b7SPramod Gunjikar 	 * For CMIDs which have been connected, call
553c39526b7SPramod Gunjikar 	 * uverbs_set_qp_free_state(SOL_UVERBS2UCMA_ENABLE_QP_FREE)
554c39526b7SPramod Gunjikar 	 * so that QP free will be done when appropriate,
555c39526b7SPramod Gunjikar 	 */
556c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&filep->file_id_list);
557c39526b7SPramod Gunjikar 	while (entry) {
558c39526b7SPramod Gunjikar 		sol_ucma_chan_t	*chanp;
559c39526b7SPramod Gunjikar 		void		*qphdl;
560c39526b7SPramod Gunjikar 
561c39526b7SPramod Gunjikar 		chanp = (sol_ucma_chan_t *)entry->data;
562c39526b7SPramod Gunjikar 		mutex_enter(&chanp->chan_mutex);
563c39526b7SPramod Gunjikar 		if (chanp->chan_rdma_id)
564c39526b7SPramod Gunjikar 			(chanp->chan_rdma_id)->context = NULL;
565c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
566c39526b7SPramod Gunjikar 		rdma_destroy_id(chanp->chan_rdma_id);
567c39526b7SPramod Gunjikar 
568c39526b7SPramod Gunjikar 		mutex_enter(&chanp->chan_mutex);
569c39526b7SPramod Gunjikar 		qphdl = chanp->chan_qp_hdl;
570c39526b7SPramod Gunjikar 		chanp->chan_qp_hdl = NULL;
571c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
572c39526b7SPramod Gunjikar 		if (qphdl)
573c39526b7SPramod Gunjikar 			(*uverbs_set_qp_free_state_fp) (
574c39526b7SPramod Gunjikar 			    SOL_UVERBS2UCMA_ENABLE_QP_FREE, 0, qphdl);
575c39526b7SPramod Gunjikar 		ucma_free_chan(chanp, 1);
576c39526b7SPramod Gunjikar 
577c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&filep->file_id_list);
578c39526b7SPramod Gunjikar 	}
579c39526b7SPramod Gunjikar 
580c39526b7SPramod Gunjikar 	/* Flush out any events that have not been acknowledged. */
581c39526b7SPramod Gunjikar 	mutex_enter(&filep->file_mutex);
582c39526b7SPramod Gunjikar 	if (filep->file_pending_evt_cnt) {
583c39526b7SPramod Gunjikar 		sol_ucma_event_t	*evtp;
584c39526b7SPramod Gunjikar 
585c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str,
586c39526b7SPramod Gunjikar 		    "close : %d Events not reported to userland",
587c39526b7SPramod Gunjikar 		    filep->file_pending_evt_cnt);
588c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&filep->file_evt_list);
589c39526b7SPramod Gunjikar 		while (entry) {
590c39526b7SPramod Gunjikar 			evtp = (sol_ucma_event_t *)entry->data;
591c39526b7SPramod Gunjikar 			kmem_free(evtp, sizeof (sol_ucma_event_t));
592c39526b7SPramod Gunjikar 			kmem_free(entry, sizeof (genlist_entry_t));
593c39526b7SPramod Gunjikar 			entry = remove_genlist_head(&filep->file_evt_list);
594c39526b7SPramod Gunjikar 		};
595c39526b7SPramod Gunjikar 		mutex_exit(&filep->file_mutex);
596c39526b7SPramod Gunjikar 	}
597c39526b7SPramod Gunjikar 
598c39526b7SPramod Gunjikar 	/*
599c39526b7SPramod Gunjikar 	 * Module close for sol_uverbs when the last file is closed.
600c39526b7SPramod Gunjikar 	 * Set the function pointers to sol_uverbs API to NULL
601c39526b7SPramod Gunjikar 	 * ddi_modclose() and ldi_close() - sol_uverbs driver
602c39526b7SPramod Gunjikar 	 */
603c39526b7SPramod Gunjikar 	mutex_enter(&sol_ucma.ucma_mutex);
604c39526b7SPramod Gunjikar 	if (sol_ucma.ucma_num_file == 1) {
605c39526b7SPramod Gunjikar 		sol_ucma.ucma_clnt_hdl_flag =
606c39526b7SPramod Gunjikar 		    SOL_UCMA_CLNT_HDL_UNINITIALIZED;
607c39526b7SPramod Gunjikar 		uverbs_get_hdl_fp = NULL;
608c39526b7SPramod Gunjikar 		uverbs_qpnum2qphdl_fp = NULL;
609c39526b7SPramod Gunjikar 		uverbs_disable_uqpn_modify_fp = NULL;
610c39526b7SPramod Gunjikar 		uverbs_uqpn_cq_ctrl_fp = NULL;
611c39526b7SPramod Gunjikar 		uverbs_uqpn_cq_ctrl_fp  = NULL;
612c39526b7SPramod Gunjikar 		uverbs_set_qp_free_state_fp = NULL;
613c39526b7SPramod Gunjikar 		uverbs_flush_qp_fp = NULL;
614c39526b7SPramod Gunjikar 		sol_ucma.ucma_ib_clnt_hdl = NULL;
615c39526b7SPramod Gunjikar 		sol_ucma.ucma_iw_clnt_hdl = NULL;
616c39526b7SPramod Gunjikar 		(void) ddi_modclose(sol_ucma.ucma_mod_hdl);
617c39526b7SPramod Gunjikar 		(void) ldi_close(sol_ucma.ucma_ldi_hdl,
618c39526b7SPramod Gunjikar 		    FREAD | FWRITE, kcred);
619c39526b7SPramod Gunjikar 	}
620c39526b7SPramod Gunjikar 	sol_ucma.ucma_num_file--;
621c39526b7SPramod Gunjikar 	mutex_exit(&sol_ucma.ucma_mutex);
622c39526b7SPramod Gunjikar 
623c39526b7SPramod Gunjikar 	kmem_free(filep->file_pollhead, sizeof (struct pollhead));
624c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&filep->file_uobj);
625c39526b7SPramod Gunjikar 	mutex_destroy(&filep->file_mutex);
626c39526b7SPramod Gunjikar 	cv_destroy(&filep->file_evt_cv);
627c39526b7SPramod Gunjikar 	cv_destroy(&filep->file_evt_close_cv);
628c39526b7SPramod Gunjikar 	rw_enter(&(filep->file_uobj.uo_lock), RW_WRITER);
629c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&ucma_file_uo_tbl, &(filep->file_uobj));
630c39526b7SPramod Gunjikar 	rw_exit(&(filep->file_uobj.uo_lock));
631c39526b7SPramod Gunjikar 	sol_ofs_uobj_free(&(filep->file_uobj));
632c39526b7SPramod Gunjikar 	return (0);
633c39526b7SPramod Gunjikar }
634c39526b7SPramod Gunjikar 
635c39526b7SPramod Gunjikar typedef struct sol_ucma_cmd_table_s {
636c39526b7SPramod Gunjikar 	int	(*sol_ucma_cmd_fnc)	(dev_t, void *, struct uio *);
637c39526b7SPramod Gunjikar 	uint16_t	sol_ucma_in_len;
638c39526b7SPramod Gunjikar 	uint16_t	sol_ucma_out_len;
639c39526b7SPramod Gunjikar } sol_ucma_cmd_table_t;
640c39526b7SPramod Gunjikar 
641c39526b7SPramod Gunjikar static  sol_ucma_cmd_table_t	sol_ucma_cmd_table[] = {
642c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_CREATE_ID]	= sol_ucma_create_id,
643c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_create_id_t),
644c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_create_id_resp_t),
645c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_DESTROY_ID]	= sol_ucma_destroy_id,
646c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_destroy_id_t),
647c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_destroy_id_resp_t),
648c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_BIND_ADDR]	= sol_ucma_bind_addr,
649c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_bind_addr_t),
650c39526b7SPramod Gunjikar 	    0,
651c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_RESOLVE_ADDR]	= sol_ucma_resolve_addr,
652c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_resolve_addr_t),
653c39526b7SPramod Gunjikar 	    0,
654c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_RESOLVE_ROUTE] = sol_ucma_resolve_route,
655c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_resolve_route_t),
656c39526b7SPramod Gunjikar 	    0,
657c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_QUERY_ROUTE]	= sol_ucma_query_route,
658c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_query_route_t),
659c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_query_route_resp_t),
660c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_CONNECT]	= sol_ucma_connect,
661c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_connect_t),
662c39526b7SPramod Gunjikar 	    0,
663c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_LISTEN]	= sol_ucma_listen,
664c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_listen_t),
665c39526b7SPramod Gunjikar 	    0,
666c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_ACCEPT]	= sol_ucma_accept,
667c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_accept_t),
668c39526b7SPramod Gunjikar 	    0,
669c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_REJECT]	= sol_ucma_reject,
670c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_reject_t),
671c39526b7SPramod Gunjikar 	    0,
672c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_DISCONNECT]	= sol_ucma_disconnect,
673c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_disconnect_t),
674c39526b7SPramod Gunjikar 	    0,
675c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_INIT_QP_ATTR]	= sol_ucma_init_qp_attr,
676c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_init_qp_attr_t),
677c39526b7SPramod Gunjikar 	    sizeof (struct ib_uverbs_qp_attr),
678c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_GET_EVENT]	= sol_ucma_get_event,
679c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_get_event_t),
680c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_event_resp_t),
681c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_GET_OPTION]	= NULL,
682c39526b7SPramod Gunjikar 	    0,
683c39526b7SPramod Gunjikar 	    0,
684c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_SET_OPTION]	= sol_ucma_set_option,
685c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_set_option_t),
686c39526b7SPramod Gunjikar 	    0,
687c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_NOTIFY]	= sol_ucma_notify,
688c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_notify_t),
689c39526b7SPramod Gunjikar 	    0,
690c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_JOIN_MCAST]	= sol_ucma_join_mcast,
691c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_join_mcast_t),
692c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_create_id_resp_t),
693c39526b7SPramod Gunjikar 	[RDMA_USER_CM_CMD_LEAVE_MCAST]	= sol_ucma_leave_mcast,
694c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_destroy_id_t),
695c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_destroy_id_resp_t)
696c39526b7SPramod Gunjikar };
697c39526b7SPramod Gunjikar 
698c39526b7SPramod Gunjikar #define	SOL_UCMA_MAX_CMD_DATA    512
699c39526b7SPramod Gunjikar static int
sol_ucma_write(dev_t dev,struct uio * uio,cred_t * credp)700c39526b7SPramod Gunjikar sol_ucma_write(dev_t dev, struct uio *uio,  cred_t *credp)
701c39526b7SPramod Gunjikar {
702c39526b7SPramod Gunjikar 	sol_ucma_cmd_hdr_t	*user_hdrp;
703c39526b7SPramod Gunjikar 	int			ret;
704c39526b7SPramod Gunjikar 	void			*data_buf = NULL;
705c39526b7SPramod Gunjikar 	char			uio_data[SOL_UCMA_MAX_CMD_DATA];
706c39526b7SPramod Gunjikar 	size_t			uio_data_len = uio->uio_resid;
707c39526b7SPramod Gunjikar 
708c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "write(%x, %p, %p)",
709c39526b7SPramod Gunjikar 	    dev, uio, credp);
710c39526b7SPramod Gunjikar 
711c39526b7SPramod Gunjikar 	ret = uiomove((caddr_t)&uio_data, uio_data_len, UIO_WRITE, uio);
712c39526b7SPramod Gunjikar 	user_hdrp = (sol_ucma_cmd_hdr_t *)uio_data;
713c39526b7SPramod Gunjikar 
714c39526b7SPramod Gunjikar 	if (ret != 0) {
715c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "write: uiomove failed");
716c39526b7SPramod Gunjikar 		return (ret);
717c39526b7SPramod Gunjikar 	}
718c39526b7SPramod Gunjikar 
719c39526b7SPramod Gunjikar 	if (user_hdrp->cmd >=
720c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_cmd_table) / sizeof (sol_ucma_cmd_table_t)) {
721c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
722c39526b7SPramod Gunjikar 		    "open : cmd out of bound 0x%x", user_hdrp->cmd);
723c39526b7SPramod Gunjikar 		return (EINVAL);
724c39526b7SPramod Gunjikar 	}
725c39526b7SPramod Gunjikar 	if (!(sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_cmd_fnc)) {
726c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
727c39526b7SPramod Gunjikar 		    "open : Unsupported cmd 0x%x", user_hdrp->cmd);
728c39526b7SPramod Gunjikar 		return (EINVAL);
729c39526b7SPramod Gunjikar 	}
730c39526b7SPramod Gunjikar 
731c39526b7SPramod Gunjikar 	/*
732c39526b7SPramod Gunjikar 	 * Check the user passed IN-OUT buffer length, with expected lengths
733c39526b7SPramod Gunjikar 	 */
734c39526b7SPramod Gunjikar 	if (sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_in_len !=
735c39526b7SPramod Gunjikar 	    (user_hdrp->in)) {
736c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
737c39526b7SPramod Gunjikar 		    "write : Invalid Input length cmd %x, in %x expected %x",
738c39526b7SPramod Gunjikar 		    user_hdrp->cmd, user_hdrp->in,
739c39526b7SPramod Gunjikar 		    sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_in_len);
740c39526b7SPramod Gunjikar 		return (EINVAL);
741c39526b7SPramod Gunjikar 	}
742c39526b7SPramod Gunjikar 
743c39526b7SPramod Gunjikar 	if (sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_out_len !=
744c39526b7SPramod Gunjikar 	    (user_hdrp->out)) {
745c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
746c39526b7SPramod Gunjikar 		    "write : Invalid Output length cmd %x, in %x expected %x",
747c39526b7SPramod Gunjikar 		    user_hdrp->cmd, user_hdrp->out,
748c39526b7SPramod Gunjikar 		    sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_out_len);
749c39526b7SPramod Gunjikar 		return (EINVAL);
750c39526b7SPramod Gunjikar 	}
751c39526b7SPramod Gunjikar 
752c39526b7SPramod Gunjikar 
753c39526b7SPramod Gunjikar 	if (user_hdrp->in) {
754c39526b7SPramod Gunjikar 		data_buf = (void *)((char *)uio_data +
755c39526b7SPramod Gunjikar 		    sizeof (sol_ucma_cmd_hdr_t));
756c39526b7SPramod Gunjikar 	}
757c39526b7SPramod Gunjikar 
758c39526b7SPramod Gunjikar 	ret = (sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_cmd_fnc)
759c39526b7SPramod Gunjikar 	    (dev, data_buf, uio);
760c39526b7SPramod Gunjikar 
761c39526b7SPramod Gunjikar 	/* If the command fails, set back the uio_resid */
762c39526b7SPramod Gunjikar 	if (ret)
763c39526b7SPramod Gunjikar 		uio->uio_resid += uio_data_len;
764c39526b7SPramod Gunjikar 
765c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "write : ret %x", ret);
766c39526b7SPramod Gunjikar 	return (ret);
767c39526b7SPramod Gunjikar }
768c39526b7SPramod Gunjikar 
769c39526b7SPramod Gunjikar static int
sol_ucma_poll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)77080d5689fSPatrick Mooney sol_ucma_poll(dev_t dev, short events, int anyyet, short *reventsp,
77180d5689fSPatrick Mooney     struct pollhead **phpp)
772c39526b7SPramod Gunjikar {
773c39526b7SPramod Gunjikar 	minor_t		minor = getminor(dev);
774c39526b7SPramod Gunjikar 	sol_ucma_file_t	*filep;
775c39526b7SPramod Gunjikar 
776c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "poll(%x, %x)",
777c39526b7SPramod Gunjikar 	    dev, events);
778c39526b7SPramod Gunjikar 	if (!(events & (POLLIN | POLLRDNORM)))
779c39526b7SPramod Gunjikar 		return (EINVAL);
780c39526b7SPramod Gunjikar 
781c39526b7SPramod Gunjikar 	filep =  (sol_ucma_file_t *)sol_ofs_uobj_get_read(
782c39526b7SPramod Gunjikar 	    &ucma_file_uo_tbl, minor);
783c39526b7SPramod Gunjikar 	ASSERT(filep);
784c39526b7SPramod Gunjikar 
785c39526b7SPramod Gunjikar 	if (filep->file_pending_evt_cnt) {
786c39526b7SPramod Gunjikar 		*reventsp = POLLIN | POLLRDNORM;
787c39526b7SPramod Gunjikar 	} else {
788c39526b7SPramod Gunjikar 		*reventsp = 0;
78980d5689fSPatrick Mooney 	}
79080d5689fSPatrick Mooney 	if ((*reventsp == 0 && !anyyet) || (events && POLLET)) {
79180d5689fSPatrick Mooney 		*phpp = filep->file_pollhead;
792c39526b7SPramod Gunjikar 	}
793c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&filep->file_uobj);
794c39526b7SPramod Gunjikar 
795c39526b7SPramod Gunjikar 	return (0);
796c39526b7SPramod Gunjikar }
797c39526b7SPramod Gunjikar 
798c39526b7SPramod Gunjikar /*
799c39526b7SPramod Gunjikar  * RDMACM functions.
800c39526b7SPramod Gunjikar  */
801c39526b7SPramod Gunjikar /*ARGSUSED*/
802c39526b7SPramod Gunjikar static int
sol_ucma_create_id(dev_t dev,void * io_buf,struct uio * uio)803c39526b7SPramod Gunjikar sol_ucma_create_id(dev_t dev, void *io_buf, struct uio *uio)
804c39526b7SPramod Gunjikar {
805c39526b7SPramod Gunjikar 	minor_t		minor = getminor(dev);
806c39526b7SPramod Gunjikar 	sol_ucma_file_t	*filep;
807c39526b7SPramod Gunjikar 	sol_ucma_chan_t *chanp;
808c39526b7SPramod Gunjikar 	sol_ucma_create_id_t		*ucma_id_inp;
809c39526b7SPramod Gunjikar 	sol_ucma_create_id_resp_t	ucma_id_resp;
810c39526b7SPramod Gunjikar 
811c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "create_id(%x, %p), minor %x",
812c39526b7SPramod Gunjikar 	    dev, io_buf, minor);
813c39526b7SPramod Gunjikar 
814c39526b7SPramod Gunjikar 	ucma_id_inp = (sol_ucma_create_id_t *)io_buf;
815c39526b7SPramod Gunjikar 	ASSERT(ucma_id_inp);
816c39526b7SPramod Gunjikar 	ASSERT(ucma_id_inp->response.r_laddr);
817c39526b7SPramod Gunjikar 
818c39526b7SPramod Gunjikar 	filep =  (sol_ucma_file_t *)sol_ofs_uobj_get_read(&ucma_file_uo_tbl,
819c39526b7SPramod Gunjikar 	    minor);
820c39526b7SPramod Gunjikar 	ASSERT(filep);
821c39526b7SPramod Gunjikar 
822c39526b7SPramod Gunjikar 	chanp = ucma_alloc_chan(filep, ucma_id_inp);
823c39526b7SPramod Gunjikar 	if (chanp == NULL)  {
824c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
825c39526b7SPramod Gunjikar 		    "create_id: No free Channel");
826c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&filep->file_uobj);
827c39526b7SPramod Gunjikar 		return (ENODEV);
828c39526b7SPramod Gunjikar 	}
829c39526b7SPramod Gunjikar 	ucma_id_resp.id = chanp->chan_id;
830c39526b7SPramod Gunjikar 
831c39526b7SPramod Gunjikar #ifdef	_LP64
832c39526b7SPramod Gunjikar 	if (copyout(&ucma_id_resp, (void *)(ucma_id_inp->response.r_laddr),
833c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_create_id_resp_t))) {
834c39526b7SPramod Gunjikar #else
835c39526b7SPramod Gunjikar 	if (copyout(&ucma_id_resp, (void *)(ucma_id_inp->response.r_addr),
836c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_create_id_resp_t))) {
837c39526b7SPramod Gunjikar #endif
838c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
839c39526b7SPramod Gunjikar 		    "create_id: copyout fault");
840c39526b7SPramod Gunjikar 		ucma_free_chan(chanp, 1);
841c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&filep->file_uobj);
842c39526b7SPramod Gunjikar 		return (EFAULT);
843c39526b7SPramod Gunjikar 	}
844c39526b7SPramod Gunjikar /* */
845c39526b7SPramod Gunjikar 
846c39526b7SPramod Gunjikar 	chanp->chan_rdma_id = rdma_create_id(sol_ucma_evt_hdlr,
847c39526b7SPramod Gunjikar 	    chanp, ucma_id_inp->ps);
848c39526b7SPramod Gunjikar 	if (chanp->chan_rdma_id == NULL) {
849c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
850c39526b7SPramod Gunjikar 		    "create_id: rdma_create_id failed");
851c39526b7SPramod Gunjikar 		ucma_free_chan(chanp, 1);
852c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&filep->file_uobj);
853c39526b7SPramod Gunjikar 		return (EINVAL);
854c39526b7SPramod Gunjikar 	}
855c39526b7SPramod Gunjikar 	mutex_enter(&chanp->chan_mutex);
856c39526b7SPramod Gunjikar 	(chanp->chan_rdma_id)->context = chanp;
857c39526b7SPramod Gunjikar 	mutex_exit(&chanp->chan_mutex);
858c39526b7SPramod Gunjikar 	rdma_map_id2clnthdl(chanp->chan_rdma_id, sol_ucma.ucma_ib_clnt_hdl,
859c39526b7SPramod Gunjikar 	    sol_ucma.ucma_iw_clnt_hdl);
860c39526b7SPramod Gunjikar 
861c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "create_id: Return SUCCESS");
862c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&filep->file_uobj);
863c39526b7SPramod Gunjikar 	return (0);
864c39526b7SPramod Gunjikar }
865c39526b7SPramod Gunjikar 
866c39526b7SPramod Gunjikar /*ARGSUSED*/
867c39526b7SPramod Gunjikar static int
868c39526b7SPramod Gunjikar sol_ucma_destroy_id(dev_t dev, void *io_buf, struct uio *uio)
869c39526b7SPramod Gunjikar {
870*d2a01201SToomas Soome 	sol_ucma_chan_t		*chanp;
871c39526b7SPramod Gunjikar 	uint32_t		ucma_id;
872c39526b7SPramod Gunjikar 	sol_ucma_file_t		*filep;
873c39526b7SPramod Gunjikar 	sol_ucma_destroy_id_t	*id_inp;
874c39526b7SPramod Gunjikar 	minor_t			minor;
875c39526b7SPramod Gunjikar 	genlist_entry_t		*entry;
876c39526b7SPramod Gunjikar 	sol_ucma_destroy_id_resp_t	id_resp;
877c39526b7SPramod Gunjikar 
878c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "destroy_id(%x, %p)",
879c39526b7SPramod Gunjikar 	    dev, io_buf);
880c39526b7SPramod Gunjikar 
881c39526b7SPramod Gunjikar 	id_inp = (sol_ucma_destroy_id_t *)io_buf;
882c39526b7SPramod Gunjikar 	ucma_id = id_inp->id;
883c39526b7SPramod Gunjikar 	if (!get_file_chan(ucma_id, &filep, &chanp, "destroy_id", 0)) {
884c39526b7SPramod Gunjikar 		minor = getminor(dev);
885c39526b7SPramod Gunjikar 		filep =  (sol_ucma_file_t *)sol_ofs_uobj_get_read(
886c39526b7SPramod Gunjikar 		    &ucma_file_uo_tbl, minor);
887c39526b7SPramod Gunjikar 		if (!filep) {
888c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
889c39526b7SPramod Gunjikar 			    "destroy_id : filep NULL");
890c39526b7SPramod Gunjikar 			return (EINVAL);
891c39526b7SPramod Gunjikar 		}
892c39526b7SPramod Gunjikar 	} else {
893c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "destroy_id : "
894c39526b7SPramod Gunjikar 		    "ucma_id %x invalid", ucma_id);
895c39526b7SPramod Gunjikar 		return (0);
896c39526b7SPramod Gunjikar 	}
897c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "destroy_id: chanp %p", chanp);
898c39526b7SPramod Gunjikar 
899c39526b7SPramod Gunjikar 	/*
900c39526b7SPramod Gunjikar 	 * Event handling, Flush out events pending
901c39526b7SPramod Gunjikar 	 * return the number of events that were acked. Free events not acked.
902c39526b7SPramod Gunjikar 	 */
903c39526b7SPramod Gunjikar 	ASSERT(filep);
904c39526b7SPramod Gunjikar 	mutex_enter(&filep->file_mutex);
905c39526b7SPramod Gunjikar 	if (filep->file_pending_evt_cnt != 0) {
906c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str,
907c39526b7SPramod Gunjikar 		    "destroy_id: pending events");
908c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&filep->file_evt_list);
909c39526b7SPramod Gunjikar 		while (entry) {
910c39526b7SPramod Gunjikar 			kmem_free((void *) (entry->data),
911c39526b7SPramod Gunjikar 			    sizeof (sol_ucma_event_t));
912c39526b7SPramod Gunjikar 			kmem_free(entry, sizeof (genlist_entry_t));
913c39526b7SPramod Gunjikar 			entry = remove_genlist_head(&filep->file_evt_list);
914c39526b7SPramod Gunjikar 		};
915c39526b7SPramod Gunjikar 		filep->file_pending_evt_cnt = 0;
916c39526b7SPramod Gunjikar 	}
917c39526b7SPramod Gunjikar 	if (chanp) {
918c39526b7SPramod Gunjikar 		mutex_enter(&chanp->chan_mutex);
919c39526b7SPramod Gunjikar 		id_resp.events_reported = chanp->chan_evt_cnt;
920c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
921c39526b7SPramod Gunjikar 	} else {
922c39526b7SPramod Gunjikar 		id_resp.events_reported = 0;
923c39526b7SPramod Gunjikar 	}
924c39526b7SPramod Gunjikar 	mutex_exit(&filep->file_mutex);
925c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "destroy_id : chanp %p, "
926c39526b7SPramod Gunjikar 	    "evts %x", chanp, id_resp.events_reported);
927c39526b7SPramod Gunjikar 
928c39526b7SPramod Gunjikar #ifdef	_LP64
929c39526b7SPramod Gunjikar 	if (copyout(&id_resp, (void *) (id_inp->response.r_laddr),
930c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_destroy_id_resp_t))) {
931c39526b7SPramod Gunjikar #else
932c39526b7SPramod Gunjikar 	if (copyout(&id_resp, (void *) (id_inp->response.r_addr),
933c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_destroy_id_resp_t))) {
934c39526b7SPramod Gunjikar #endif
935c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
936c39526b7SPramod Gunjikar 		    "destroy_id: copyout fault");
937c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&filep->file_uobj);
938c39526b7SPramod Gunjikar 		return (EFAULT);
939c39526b7SPramod Gunjikar 	}
940c39526b7SPramod Gunjikar /* */
941c39526b7SPramod Gunjikar 
942c39526b7SPramod Gunjikar 	if (chanp) {
943c39526b7SPramod Gunjikar 		mutex_enter(&chanp->chan_mutex);
944c39526b7SPramod Gunjikar 		if (chanp->chan_rdma_id)
945c39526b7SPramod Gunjikar 			(chanp->chan_rdma_id)->context = NULL;
946c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
947c39526b7SPramod Gunjikar 		rdma_destroy_id(chanp->chan_rdma_id);
948c39526b7SPramod Gunjikar 		ucma_free_chan(chanp, 1);
949c39526b7SPramod Gunjikar 	}
950c39526b7SPramod Gunjikar 
951c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "destroy_id: Success");
952c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&filep->file_uobj);
953c39526b7SPramod Gunjikar 	return (0);
954c39526b7SPramod Gunjikar }
955c39526b7SPramod Gunjikar 
956c39526b7SPramod Gunjikar /*ARGSUSED*/
957c39526b7SPramod Gunjikar static int
958c39526b7SPramod Gunjikar sol_ucma_bind_addr(dev_t dev, void *io_buf, struct uio *uio)
959c39526b7SPramod Gunjikar {
960c39526b7SPramod Gunjikar 	int		ret;
961c39526b7SPramod Gunjikar 	sol_ucma_chan_t	*chanp;
962c39526b7SPramod Gunjikar 	uint32_t	ucma_id;
963c39526b7SPramod Gunjikar 	sol_ucma_bind_addr_t	*bind_addrp;
964c39526b7SPramod Gunjikar 
965c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "bind_addr(%x, %p)",
966c39526b7SPramod Gunjikar 	    dev, io_buf);
967c39526b7SPramod Gunjikar 
968c39526b7SPramod Gunjikar 	bind_addrp = (sol_ucma_bind_addr_t *)io_buf;
969c39526b7SPramod Gunjikar 	ucma_id = bind_addrp->id;
970c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "bind_addr", 1))
971c39526b7SPramod Gunjikar 		return (EINVAL);
972c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "bind_addr - chanp %p", chanp);
973c39526b7SPramod Gunjikar 
974c39526b7SPramod Gunjikar 	ret = rdma_bind_addr(chanp->chan_rdma_id,
975c39526b7SPramod Gunjikar 	    (struct sockaddr *)&bind_addrp->addr);
976c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "bind_addr: ret %x", ret);
977c39526b7SPramod Gunjikar 	return (ret);
978c39526b7SPramod Gunjikar }
979c39526b7SPramod Gunjikar 
980c39526b7SPramod Gunjikar /*ARGSUSED*/
981c39526b7SPramod Gunjikar static int
982c39526b7SPramod Gunjikar sol_ucma_resolve_addr(dev_t dev, void *io_buf, struct uio *uio)
983c39526b7SPramod Gunjikar {
984c39526b7SPramod Gunjikar 	sol_ucma_chan_t	*chanp;
985c39526b7SPramod Gunjikar 	uint32_t	ucma_id;
986c39526b7SPramod Gunjikar 	int		ret;
987c39526b7SPramod Gunjikar 	sol_ucma_resolve_addr_t	*resolve_addrp;
988c39526b7SPramod Gunjikar 
989c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_addr(%x, %p)",
990c39526b7SPramod Gunjikar 	    dev, io_buf);
991c39526b7SPramod Gunjikar 
992c39526b7SPramod Gunjikar 	resolve_addrp = (sol_ucma_resolve_addr_t *)io_buf;
993c39526b7SPramod Gunjikar 	ucma_id  = resolve_addrp->id;
994c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "resolve_addr", 1)) {
995c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
996c39526b7SPramod Gunjikar 		    "resolve_addr: ucma_id %x invalid", ucma_id);
997c39526b7SPramod Gunjikar 		return (EINVAL);
998c39526b7SPramod Gunjikar 	}
999c39526b7SPramod Gunjikar 	ASSERT(chanp);
1000c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_addr - chanp %p", chanp);
1001c39526b7SPramod Gunjikar 
1002c39526b7SPramod Gunjikar 	ret = rdma_resolve_addr(chanp->chan_rdma_id,
1003c39526b7SPramod Gunjikar 	    (struct sockaddr *)&resolve_addrp->src_addr,
1004c39526b7SPramod Gunjikar 	    (struct sockaddr *)&resolve_addrp->dst_addr,
1005c39526b7SPramod Gunjikar 	    resolve_addrp->timeout_ms);
1006c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_addr: ret %x", ret);
1007c39526b7SPramod Gunjikar 	return (ret);
1008c39526b7SPramod Gunjikar }
1009c39526b7SPramod Gunjikar 
1010c39526b7SPramod Gunjikar /*ARGSUSED*/
1011c39526b7SPramod Gunjikar static int
1012c39526b7SPramod Gunjikar sol_ucma_resolve_route(dev_t dev, void *io_buf, struct uio *uio)
1013c39526b7SPramod Gunjikar {
1014c39526b7SPramod Gunjikar 	sol_ucma_chan_t	*chanp;
1015c39526b7SPramod Gunjikar 	uint32_t	ucma_id;
1016c39526b7SPramod Gunjikar 	int		ret;
1017c39526b7SPramod Gunjikar 	sol_ucma_resolve_route_t	*resolve_routep;
1018c39526b7SPramod Gunjikar 
1019c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str,
1020c39526b7SPramod Gunjikar 	    "resolve_route(%x, %p)", dev, io_buf);
1021c39526b7SPramod Gunjikar 
1022c39526b7SPramod Gunjikar 	resolve_routep = (sol_ucma_resolve_route_t *)io_buf;
1023c39526b7SPramod Gunjikar 	ucma_id  = resolve_routep->id;
1024c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "resolve_route", 1))
1025c39526b7SPramod Gunjikar 		return (EINVAL);
1026c39526b7SPramod Gunjikar 	ASSERT(chanp);
1027c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_route - chanp %p",
1028c39526b7SPramod Gunjikar 	    chanp);
1029c39526b7SPramod Gunjikar 
1030c39526b7SPramod Gunjikar 	ret = rdma_resolve_route(chanp->chan_rdma_id,
1031c39526b7SPramod Gunjikar 	    resolve_routep->timeout_ms);
1032c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_route: ret %x", ret);
1033c39526b7SPramod Gunjikar 	return (ret);
1034c39526b7SPramod Gunjikar }
1035c39526b7SPramod Gunjikar 
1036c39526b7SPramod Gunjikar /*ARGSUSED*/
1037c39526b7SPramod Gunjikar static int
1038c39526b7SPramod Gunjikar sol_ucma_query_route(dev_t dev, void *io_buf, struct uio *uio)
1039c39526b7SPramod Gunjikar {
1040c39526b7SPramod Gunjikar 	sol_ucma_chan_t			*chanp;
1041c39526b7SPramod Gunjikar 	uint32_t			ucma_id;
1042c39526b7SPramod Gunjikar 	struct rdma_cm_id		*idp;
1043c39526b7SPramod Gunjikar 	sol_ucma_query_route_t		*query_routep;
1044c39526b7SPramod Gunjikar 	sol_ucma_query_route_resp_t	route_info;
1045c39526b7SPramod Gunjikar 
1046c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "query_route(%x, %p)",
1047c39526b7SPramod Gunjikar 	    dev, io_buf);
1048c39526b7SPramod Gunjikar 
1049c39526b7SPramod Gunjikar 	query_routep = (sol_ucma_query_route_t *)io_buf;
1050c39526b7SPramod Gunjikar 	ucma_id  = query_routep->id;
1051c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "query_route", 1))
1052c39526b7SPramod Gunjikar 		return (EINVAL);
1053c39526b7SPramod Gunjikar 	ASSERT(chanp);
1054c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "query_route - chanp %p", chanp);
1055c39526b7SPramod Gunjikar 	idp = chanp->chan_rdma_id;
1056c39526b7SPramod Gunjikar 
1057c39526b7SPramod Gunjikar 	bzero(&route_info, sizeof (route_info));
1058c39526b7SPramod Gunjikar 	rdma2usr_route(idp, &route_info);
1059c39526b7SPramod Gunjikar 
1060c39526b7SPramod Gunjikar #ifdef	_LP64
1061c39526b7SPramod Gunjikar 	if (copyout(&route_info, (void *) (query_routep->response.r_laddr),
1062c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_query_route_resp_t))) {
1063c39526b7SPramod Gunjikar #else
1064c39526b7SPramod Gunjikar 	if (copyout(&route_info, (void *) (query_routep->response.r_addr),
1065c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_query_route_resp_t))) {
1066c39526b7SPramod Gunjikar #endif
1067c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1068c39526b7SPramod Gunjikar 		    "query_route: copyout fault");
1069c39526b7SPramod Gunjikar 		return (EFAULT);
1070c39526b7SPramod Gunjikar 	}
1071c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "query_route: Succcess");
1072c39526b7SPramod Gunjikar 	return (0);
1073c39526b7SPramod Gunjikar }
1074c39526b7SPramod Gunjikar 
1075c39526b7SPramod Gunjikar /*ARGSUSED*/
1076c39526b7SPramod Gunjikar static int
1077c39526b7SPramod Gunjikar sol_ucma_connect(dev_t dev, void *io_buf, struct uio *uio)
1078c39526b7SPramod Gunjikar {
1079c39526b7SPramod Gunjikar 	sol_ucma_chan_t		*chanp;
1080c39526b7SPramod Gunjikar 	uint32_t		ucma_id;
1081c39526b7SPramod Gunjikar 	int			ret;
1082c39526b7SPramod Gunjikar 	void			*qphdl;
1083c39526b7SPramod Gunjikar 	sol_ucma_connect_t	*connectp;
1084c39526b7SPramod Gunjikar 	struct rdma_conn_param	conn_param;
1085c39526b7SPramod Gunjikar 	struct rdma_cm_id	*idp;
1086c39526b7SPramod Gunjikar 
1087c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "connect(%x, %p)",
1088c39526b7SPramod Gunjikar 	    dev, io_buf);
1089c39526b7SPramod Gunjikar 
1090c39526b7SPramod Gunjikar 	connectp = (sol_ucma_connect_t *)io_buf;
1091c39526b7SPramod Gunjikar 	ucma_id  = connectp->id;
1092c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "connect", 1))
1093c39526b7SPramod Gunjikar 		return (EINVAL);
1094c39526b7SPramod Gunjikar 	ASSERT(chanp);
1095c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "connect - chanp %p", chanp);
1096c39526b7SPramod Gunjikar 
1097c39526b7SPramod Gunjikar 	usr2rdma_conn_param(&(connectp->conn_param), &conn_param);
1098c39526b7SPramod Gunjikar 	ASSERT(uverbs_qpnum2qphdl_fp);
1099c39526b7SPramod Gunjikar 	ASSERT(uverbs_disable_uqpn_modify_fp);
1100c39526b7SPramod Gunjikar 	ASSERT(uverbs_uqpn_cq_ctrl_fp);
1101c39526b7SPramod Gunjikar 	qphdl = (*uverbs_qpnum2qphdl_fp) (conn_param.qp_num);
1102c39526b7SPramod Gunjikar 	if (qphdl == NULL) {
1103c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "connect: "
1104c39526b7SPramod Gunjikar 		    "invalid QPNum %x", conn_param.qp_num);
1105c39526b7SPramod Gunjikar 		return (EINVAL);
1106c39526b7SPramod Gunjikar 	}
1107c39526b7SPramod Gunjikar 	(*uverbs_disable_uqpn_modify_fp) (conn_param.qp_num);
1108c39526b7SPramod Gunjikar 	rdma_map_id2qphdl(chanp->chan_rdma_id, qphdl);
1109c39526b7SPramod Gunjikar 	idp = chanp->chan_rdma_id;
1110c39526b7SPramod Gunjikar 	if (idp->ps == RDMA_PS_TCP)
1111c39526b7SPramod Gunjikar 		(void) (*uverbs_uqpn_cq_ctrl_fp) (conn_param.qp_num,
1112c39526b7SPramod Gunjikar 		    SOL_UVERBS2UCMA_CQ_NOTIFY_DISABLE);
1113c39526b7SPramod Gunjikar 	chanp->chan_qp_num = conn_param.qp_num;
1114c39526b7SPramod Gunjikar 	ret = rdma_connect(chanp->chan_rdma_id, &conn_param);
1115c39526b7SPramod Gunjikar 
1116c39526b7SPramod Gunjikar 	/*
1117c39526b7SPramod Gunjikar 	 * rdma_connect() initiated for this CMID, disable sol_uverbs to
1118c39526b7SPramod Gunjikar 	 * free the QP assosiated with this CM ID.
1119c39526b7SPramod Gunjikar 	 */
1120c39526b7SPramod Gunjikar 	if (ret == 0 && idp->ps == RDMA_PS_TCP) {
1121c39526b7SPramod Gunjikar 		mutex_enter(&chanp->chan_mutex);
1122c39526b7SPramod Gunjikar 		chanp->chan_qp_hdl = qphdl;
1123c39526b7SPramod Gunjikar 		chanp->chan_flags |= SOL_UCMA_CHAN_CONNECT_FLAG;
1124c39526b7SPramod Gunjikar 		mutex_exit(&chanp->chan_mutex);
1125c39526b7SPramod Gunjikar 		(*uverbs_set_qp_free_state_fp) (
1126c39526b7SPramod Gunjikar 		    SOL_UVERBS2UCMA_DISABLE_QP_FREE, conn_param.qp_num,
1127c39526b7SPramod Gunjikar 		    NULL);
1128c39526b7SPramod Gunjikar 	}
1129c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "connect: ret %x", ret);
1130c39526b7SPramod Gunjikar 	return (ret);
1131c39526b7SPramod Gunjikar }
1132c39526b7SPramod Gunjikar 
1133c39526b7SPramod Gunjikar /*ARGSUSED*/
1134c39526b7SPramod Gunjikar static int
1135c39526b7SPramod Gunjikar sol_ucma_listen(dev_t dev, void *io_buf, struct uio *uio)
1136c39526b7SPramod Gunjikar {
1137c39526b7SPramod Gunjikar 	sol_ucma_chan_t		*chanp;
1138c39526b7SPramod Gunjikar 	uint32_t		ucma_id;
1139c39526b7SPramod Gunjikar 	int			ret;
1140c39526b7SPramod Gunjikar 	sol_ucma_listen_t	*listenp;
1141c39526b7SPramod Gunjikar 
1142c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "listen(%x, %p)",
1143c39526b7SPramod Gunjikar 	    dev, io_buf);
1144c39526b7SPramod Gunjikar 
1145c39526b7SPramod Gunjikar 	listenp = (sol_ucma_listen_t *)io_buf;
1146c39526b7SPramod Gunjikar 	ucma_id  = listenp->id;
1147c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "listen", 1))
1148c39526b7SPramod Gunjikar 		return (EINVAL);
1149c39526b7SPramod Gunjikar 	ASSERT(chanp);
1150c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "listen - chanp %p", chanp);
1151c39526b7SPramod Gunjikar 
1152c39526b7SPramod Gunjikar 	listenp->backlog = (listenp->backlog == 0 ||
1153c39526b7SPramod Gunjikar 	    listenp->backlog > SOL_UCMA_MAX_LISTEN) ?
1154c39526b7SPramod Gunjikar 	    SOL_UCMA_MAX_LISTEN : listenp->backlog;
1155c39526b7SPramod Gunjikar 	chanp->chan_backlog = listenp->backlog;
1156c39526b7SPramod Gunjikar 
1157c39526b7SPramod Gunjikar 	ret = rdma_listen(chanp->chan_rdma_id, listenp->backlog);
1158c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "listen: ret %x", ret);
1159c39526b7SPramod Gunjikar 	return (ret);
1160c39526b7SPramod Gunjikar }
1161c39526b7SPramod Gunjikar 
1162c39526b7SPramod Gunjikar /*ARGSUSED*/
1163c39526b7SPramod Gunjikar static int
1164c39526b7SPramod Gunjikar sol_ucma_accept(dev_t dev, void *io_buf, struct uio *uio)
1165c39526b7SPramod Gunjikar {
1166c39526b7SPramod Gunjikar 	int				ret;
1167c39526b7SPramod Gunjikar 	uint32_t		ucma_id;
1168c39526b7SPramod Gunjikar 	sol_ucma_chan_t	*chanp;
1169c39526b7SPramod Gunjikar 	void			*qphdl;
1170c39526b7SPramod Gunjikar 	sol_ucma_accept_t		*acpt;
1171c39526b7SPramod Gunjikar 	struct rdma_conn_param	conn_param;
1172c39526b7SPramod Gunjikar 
1173c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "accept(%x, %p)",
1174c39526b7SPramod Gunjikar 	    dev, io_buf);
1175c39526b7SPramod Gunjikar 
1176c39526b7SPramod Gunjikar 	acpt = (sol_ucma_accept_t *)io_buf;
1177c39526b7SPramod Gunjikar 	ucma_id = acpt->id;
1178c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "accept", 1))
1179c39526b7SPramod Gunjikar 		return (EINVAL);
1180c39526b7SPramod Gunjikar 	ASSERT(chanp);
1181c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "accept - chanp %p", chanp);
1182c39526b7SPramod Gunjikar 
1183c39526b7SPramod Gunjikar 	if ((acpt->conn_param).valid) {
1184c39526b7SPramod Gunjikar 		struct rdma_cm_id	*idp;
1185c39526b7SPramod Gunjikar 
1186c39526b7SPramod Gunjikar 		chanp->chan_user_id = acpt->uid;
1187c39526b7SPramod Gunjikar 		usr2rdma_conn_param(&acpt->conn_param, &conn_param);
1188c39526b7SPramod Gunjikar 
1189c39526b7SPramod Gunjikar 		ASSERT(uverbs_qpnum2qphdl_fp);
1190c39526b7SPramod Gunjikar 		qphdl = (*uverbs_qpnum2qphdl_fp) (conn_param.qp_num);
1191c39526b7SPramod Gunjikar 		if (qphdl == NULL) {
1192c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "accept: "
1193c39526b7SPramod Gunjikar 			    "invalid QPNum %x", conn_param.qp_num);
1194c39526b7SPramod Gunjikar 			return (EINVAL);
1195c39526b7SPramod Gunjikar 		}
1196c39526b7SPramod Gunjikar 		(*uverbs_disable_uqpn_modify_fp) (conn_param.qp_num);
1197c39526b7SPramod Gunjikar 		rdma_map_id2qphdl(chanp->chan_rdma_id, qphdl);
1198c39526b7SPramod Gunjikar 		idp = chanp->chan_rdma_id;
1199c39526b7SPramod Gunjikar 		if (idp->ps == RDMA_PS_TCP)
1200c39526b7SPramod Gunjikar 			(void) (*uverbs_uqpn_cq_ctrl_fp) (conn_param.qp_num,
1201c39526b7SPramod Gunjikar 			    SOL_UVERBS2UCMA_CQ_NOTIFY_DISABLE);
1202c39526b7SPramod Gunjikar 		chanp->chan_qp_num = conn_param.qp_num;
1203c39526b7SPramod Gunjikar 		ret = rdma_accept(chanp->chan_rdma_id, &conn_param);
1204c39526b7SPramod Gunjikar 	} else
1205c39526b7SPramod Gunjikar 		ret = rdma_accept(chanp->chan_rdma_id, NULL);
1206c39526b7SPramod Gunjikar 
1207c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "accept: ret %x", ret);
1208c39526b7SPramod Gunjikar 	return (ret);
1209c39526b7SPramod Gunjikar }
1210c39526b7SPramod Gunjikar 
1211c39526b7SPramod Gunjikar /*ARGSUSED*/
1212c39526b7SPramod Gunjikar static int
1213c39526b7SPramod Gunjikar sol_ucma_reject(dev_t dev, void *io_buf, struct uio *uio)
1214c39526b7SPramod Gunjikar {
1215c39526b7SPramod Gunjikar 	int		ret;
1216c39526b7SPramod Gunjikar 	uint32_t	ucma_id;
1217c39526b7SPramod Gunjikar 	sol_ucma_chan_t	*chanp;
1218c39526b7SPramod Gunjikar 	sol_ucma_reject_t	*rjct;
1219c39526b7SPramod Gunjikar 
1220c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "reject(%x, %p)", dev, io_buf);
1221c39526b7SPramod Gunjikar 
1222c39526b7SPramod Gunjikar 	rjct = (sol_ucma_reject_t *)io_buf;
1223c39526b7SPramod Gunjikar 	ucma_id = rjct->id;
1224c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "reject", 1))
1225c39526b7SPramod Gunjikar 		return (EINVAL);
1226c39526b7SPramod Gunjikar 	ASSERT(chanp);
1227c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "reject - chanp %p", chanp);
1228c39526b7SPramod Gunjikar 
1229c39526b7SPramod Gunjikar 	ret = rdma_reject(chanp->chan_rdma_id, rjct->private_data,
1230c39526b7SPramod Gunjikar 	    rjct->private_data_len);
1231c39526b7SPramod Gunjikar 
1232c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "reject: ret %x", ret);
1233c39526b7SPramod Gunjikar 	return (ret);
1234c39526b7SPramod Gunjikar }
1235c39526b7SPramod Gunjikar 
1236c39526b7SPramod Gunjikar /*ARGSUSED*/
1237c39526b7SPramod Gunjikar static int
1238c39526b7SPramod Gunjikar sol_ucma_init_qp_attr(dev_t dev, void *io_buf, struct uio *uio)
1239c39526b7SPramod Gunjikar {
1240c39526b7SPramod Gunjikar 	int				ret;
1241c39526b7SPramod Gunjikar 	uint32_t			ucma_id;
1242c39526b7SPramod Gunjikar 	uint32_t			qp_attr_mask;
1243c39526b7SPramod Gunjikar 	sol_ucma_chan_t			*chanp;
1244c39526b7SPramod Gunjikar 	sol_ucma_init_qp_attr_t		*qp_attr_inp;
1245c39526b7SPramod Gunjikar 	struct ib_uverbs_qp_attr	uverbs_qp_attr;
1246c39526b7SPramod Gunjikar 	struct ib_qp_attr		qp_attr;
1247c39526b7SPramod Gunjikar 
1248c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "init_qp_attr(%x, %p)",
1249c39526b7SPramod Gunjikar 	    dev, io_buf);
1250c39526b7SPramod Gunjikar 
1251c39526b7SPramod Gunjikar 	qp_attr_inp = (sol_ucma_init_qp_attr_t *)io_buf;
1252c39526b7SPramod Gunjikar 	ucma_id = qp_attr_inp->id;
1253c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "init_qp_attr", 1))
1254c39526b7SPramod Gunjikar 		return (EINVAL);
1255c39526b7SPramod Gunjikar 	ASSERT(chanp);
1256c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "init_qp_attr - chanp %p", chanp);
1257c39526b7SPramod Gunjikar 
1258c39526b7SPramod Gunjikar 	qp_attr.qp_state = qp_attr_inp->qp_state;
1259c39526b7SPramod Gunjikar 	if ((ret = rdma_init_qp_attr(chanp->chan_rdma_id, &qp_attr,
1260c39526b7SPramod Gunjikar 	    (int *)&qp_attr_mask)) != 0) {
1261c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "init_qp_attr: ret %x, "
1262c39526b7SPramod Gunjikar 		    "mask %x", ret, qp_attr_mask);
1263c39526b7SPramod Gunjikar 		return (EINVAL);
1264c39526b7SPramod Gunjikar 	}
1265c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "init_qp_attr: ret %x, mask %x",
1266c39526b7SPramod Gunjikar 	    ret, qp_attr_mask);
1267c39526b7SPramod Gunjikar 
1268c39526b7SPramod Gunjikar 	bzero(&uverbs_qp_attr, sizeof (uverbs_qp_attr));
1269c39526b7SPramod Gunjikar 	uverbs_qp_attr.qp_attr_mask = qp_attr_mask;
1270c39526b7SPramod Gunjikar 	uverbs_qp_attr.qp_state = qp_attr.qp_state;
1271c39526b7SPramod Gunjikar 	uverbs_qp_attr.pkey_index = qp_attr.pkey_index;
1272c39526b7SPramod Gunjikar 	uverbs_qp_attr.port_num = qp_attr.port_num;
1273c39526b7SPramod Gunjikar 	uverbs_qp_attr.qp_access_flags = qp_attr.qp_access_flags;
1274c39526b7SPramod Gunjikar 	uverbs_qp_attr.qkey = qp_attr.qkey;
1275c39526b7SPramod Gunjikar 	uverbs_qp_attr.path_mtu = qp_attr.path_mtu;
1276c39526b7SPramod Gunjikar 	uverbs_qp_attr.dest_qp_num = qp_attr.dest_qp_num;
1277c39526b7SPramod Gunjikar 	uverbs_qp_attr.rq_psn = qp_attr.rq_psn;
1278c39526b7SPramod Gunjikar 	uverbs_qp_attr.max_dest_rd_atomic = qp_attr.max_dest_rd_atomic;
1279c39526b7SPramod Gunjikar 	uverbs_qp_attr.min_rnr_timer = qp_attr.min_rnr_timer;
1280c39526b7SPramod Gunjikar 	uverbs_qp_attr.ah_attr.dlid = qp_attr.ah_attr.dlid;
1281c39526b7SPramod Gunjikar 	if (qp_attr.ah_attr.ah_flags) {
1282c39526b7SPramod Gunjikar 		uverbs_qp_attr.ah_attr.is_global = 1;
1283c39526b7SPramod Gunjikar 		bcopy(&(qp_attr.ah_attr.grh.dgid),
1284c39526b7SPramod Gunjikar 		    &(uverbs_qp_attr.ah_attr.grh.dgid), 16);
1285c39526b7SPramod Gunjikar 		uverbs_qp_attr.ah_attr.grh.flow_label =
1286c39526b7SPramod Gunjikar 		    qp_attr.ah_attr.grh.flow_label;
1287c39526b7SPramod Gunjikar 		uverbs_qp_attr.ah_attr.grh.sgid_index =
1288c39526b7SPramod Gunjikar 		    qp_attr.ah_attr.grh.sgid_index;
1289c39526b7SPramod Gunjikar 		uverbs_qp_attr.ah_attr.grh.hop_limit =
1290c39526b7SPramod Gunjikar 		    qp_attr.ah_attr.grh.hop_limit;
1291c39526b7SPramod Gunjikar 		uverbs_qp_attr.ah_attr.grh.traffic_class =
1292c39526b7SPramod Gunjikar 		    qp_attr.ah_attr.grh.traffic_class;
1293c39526b7SPramod Gunjikar 	}
1294c39526b7SPramod Gunjikar 	uverbs_qp_attr.ah_attr.sl = qp_attr.ah_attr.sl;
1295c39526b7SPramod Gunjikar 	uverbs_qp_attr.ah_attr.src_path_bits = qp_attr.ah_attr.src_path_bits;
1296c39526b7SPramod Gunjikar 	uverbs_qp_attr.ah_attr.static_rate = qp_attr.ah_attr.static_rate;
1297c39526b7SPramod Gunjikar 	uverbs_qp_attr.ah_attr.port_num = qp_attr.ah_attr.port_num;
1298c39526b7SPramod Gunjikar 
1299c39526b7SPramod Gunjikar #ifdef	_LP64
1300c39526b7SPramod Gunjikar 	if (copyout(&uverbs_qp_attr, (void *) (qp_attr_inp->response.r_laddr),
1301c39526b7SPramod Gunjikar 	    sizeof (uverbs_qp_attr))) {
1302c39526b7SPramod Gunjikar #else
1303c39526b7SPramod Gunjikar 	if (copyout(&uverbs_qp_attr, (void *) (qp_attr_inp->response.r_addr),
1304c39526b7SPramod Gunjikar 	    sizeof (uverbs_qp_attr))) {
1305c39526b7SPramod Gunjikar #endif
1306c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "init_qp_attr : copyout "
1307c39526b7SPramod Gunjikar 		    "failed");
1308c39526b7SPramod Gunjikar 		return (EFAULT);
1309c39526b7SPramod Gunjikar 	}
1310c39526b7SPramod Gunjikar 	return (0);
1311c39526b7SPramod Gunjikar }
1312c39526b7SPramod Gunjikar 
1313c39526b7SPramod Gunjikar static int
1314c39526b7SPramod Gunjikar sol_ucma_get_event(dev_t dev, void *io_buf, struct uio *uio)
1315c39526b7SPramod Gunjikar {
1316c39526b7SPramod Gunjikar 	minor_t			minor;
1317c39526b7SPramod Gunjikar 	sol_ucma_file_t		*filep;
1318c39526b7SPramod Gunjikar 	sol_ucma_chan_t		*evt_chanp;
1319c39526b7SPramod Gunjikar 	genlist_entry_t		*entry;
1320c39526b7SPramod Gunjikar 	struct rdma_ucm_get_event	*user_evt_inp;
1321c39526b7SPramod Gunjikar 	sol_ucma_event_t		*queued_evt;
1322c39526b7SPramod Gunjikar 	struct rdma_ucm_event_resp	*user_evt_resp;
1323c39526b7SPramod Gunjikar 
1324c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event(%x, %p)", dev, io_buf);
1325c39526b7SPramod Gunjikar 	user_evt_inp = (struct rdma_ucm_get_event *)io_buf;
1326c39526b7SPramod Gunjikar 
1327c39526b7SPramod Gunjikar 	minor = getminor(dev);
1328c39526b7SPramod Gunjikar 	filep =  (sol_ucma_file_t *)sol_ofs_uobj_get_read(&ucma_file_uo_tbl,
1329c39526b7SPramod Gunjikar 	    minor);
1330c39526b7SPramod Gunjikar 	ASSERT(filep);
1331c39526b7SPramod Gunjikar 
1332c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event fmode %x",
1333c39526b7SPramod Gunjikar 	    uio->uio_fmode);
1334c39526b7SPramod Gunjikar 
1335c39526b7SPramod Gunjikar 	mutex_enter(&filep->file_mutex);
1336c39526b7SPramod Gunjikar 	while (filep->file_pending_evt_cnt == 0) {
1337c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str, "get_event: No events");
1338c39526b7SPramod Gunjikar 		if (uio->uio_fmode & (FNONBLOCK | FNDELAY)) {
1339c39526b7SPramod Gunjikar 			mutex_exit(&filep->file_mutex);
1340c39526b7SPramod Gunjikar 			sol_ofs_uobj_put(&filep->file_uobj);
1341c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str,
1342c39526b7SPramod Gunjikar 			    "get_event: No events, nonblocking");
1343c39526b7SPramod Gunjikar 			return (EAGAIN);
1344c39526b7SPramod Gunjikar 		}
1345c39526b7SPramod Gunjikar 		if (!cv_wait_sig(&filep->file_evt_cv, &filep->file_mutex)) {
1346c39526b7SPramod Gunjikar 			mutex_exit(&filep->file_mutex);
1347c39526b7SPramod Gunjikar 			sol_ofs_uobj_put(&filep->file_uobj);
1348c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str,
1349c39526b7SPramod Gunjikar 			    "get_event: Got Sig");
1350c39526b7SPramod Gunjikar 			return (EINTR);
1351c39526b7SPramod Gunjikar 		}
1352c39526b7SPramod Gunjikar 	}
1353c39526b7SPramod Gunjikar 
1354c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&filep->file_evt_list);
1355c39526b7SPramod Gunjikar 	mutex_exit(&filep->file_mutex);
1356c39526b7SPramod Gunjikar 	ASSERT(entry);
1357c39526b7SPramod Gunjikar 	queued_evt = (sol_ucma_event_t *)entry->data;
1358c39526b7SPramod Gunjikar 	ASSERT(queued_evt);
1359c39526b7SPramod Gunjikar 	user_evt_resp = &queued_evt->event_resp;
1360c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "event2usr "
1361c39526b7SPramod Gunjikar 	    "uid %llx, id %x, event %x, status %x", user_evt_resp->uid,
1362c39526b7SPramod Gunjikar 	    user_evt_resp->id, user_evt_resp->event, user_evt_resp->status);
1363c39526b7SPramod Gunjikar #ifdef	_LP64
1364c39526b7SPramod Gunjikar 	if (copyout((void *)user_evt_resp,
1365c39526b7SPramod Gunjikar 	    (void *)(user_evt_inp->response.r_laddr),
1366c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_event_resp_t))) {
1367c39526b7SPramod Gunjikar #else
1368c39526b7SPramod Gunjikar 	if (copyout((void *)user_evt_resp,
1369c39526b7SPramod Gunjikar 	    (void *)(user_evt_inp->response.r_addr),
1370c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_event_resp_t))) {
1371c39526b7SPramod Gunjikar #endif
1372c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event: copyout "
1373c39526b7SPramod Gunjikar 		    "failed");
1374c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&filep->file_uobj);
1375c39526b7SPramod Gunjikar 		kmem_free(entry, sizeof (genlist_entry_t));
1376c39526b7SPramod Gunjikar 		return (EFAULT);
1377c39526b7SPramod Gunjikar 	}
1378c39526b7SPramod Gunjikar 	mutex_enter(&filep->file_mutex);
1379c39526b7SPramod Gunjikar 	filep->file_pending_evt_cnt--;
1380c39526b7SPramod Gunjikar 	if (queued_evt->event_mcast)
1381c39526b7SPramod Gunjikar 		(queued_evt->event_mcast)->mcast_events++;
1382c39526b7SPramod Gunjikar 	evt_chanp = queued_evt->event_chan;
1383c39526b7SPramod Gunjikar 	if (evt_chanp) {
1384c39526b7SPramod Gunjikar 		/*
1385c39526b7SPramod Gunjikar 		 * If the event is RDMA_CM_EVENT_CONNECT_RESPONSE or
1386c39526b7SPramod Gunjikar 		 * RDMA_CM_EVENT_ESTABLISHED and the CM ID is for RC,
1387c39526b7SPramod Gunjikar 		 * enable completion notifications for the QP.
1388c39526b7SPramod Gunjikar 		 */
1389c39526b7SPramod Gunjikar 		if (user_evt_resp->event == RDMA_CM_EVENT_CONNECT_RESPONSE ||
1390c39526b7SPramod Gunjikar 		    user_evt_resp->event == RDMA_CM_EVENT_ESTABLISHED) {
1391c39526b7SPramod Gunjikar 			struct rdma_cm_id	*idp;
1392c39526b7SPramod Gunjikar 			int	rc;
1393c39526b7SPramod Gunjikar 
1394c39526b7SPramod Gunjikar 			idp = evt_chanp->chan_rdma_id;
1395c39526b7SPramod Gunjikar 			if (idp->ps == RDMA_PS_TCP) {
1396c39526b7SPramod Gunjikar 				ASSERT(uverbs_uqpn_cq_ctrl_fp);
1397c39526b7SPramod Gunjikar 				rc = (*uverbs_uqpn_cq_ctrl_fp)(
1398c39526b7SPramod Gunjikar 				    evt_chanp->chan_qp_num,
1399c39526b7SPramod Gunjikar 				    SOL_UVERBS2UCMA_CQ_NOTIFY_ENABLE);
1400c39526b7SPramod Gunjikar 				if (rc) {
1401c39526b7SPramod Gunjikar 					SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1402c39526b7SPramod Gunjikar 					    "uverbs_uqpn_cq_ctrl_fp(%X) "
1403c39526b7SPramod Gunjikar 					    "failed!!",
1404c39526b7SPramod Gunjikar 					    evt_chanp->chan_qp_num);
1405c39526b7SPramod Gunjikar 					mutex_exit(&filep->file_mutex);
1406c39526b7SPramod Gunjikar 					filep->file_pending_evt_cnt++;
1407c39526b7SPramod Gunjikar 					return (EIO);
1408c39526b7SPramod Gunjikar 				}
1409c39526b7SPramod Gunjikar 			}
1410c39526b7SPramod Gunjikar 		}
1411c39526b7SPramod Gunjikar 
1412c39526b7SPramod Gunjikar 		/* Bump up backlog for CONNECT_REQUEST events */
1413c39526b7SPramod Gunjikar 		mutex_enter(&evt_chanp->chan_mutex);
1414c39526b7SPramod Gunjikar 		if (user_evt_resp->event == RDMA_CM_EVENT_CONNECT_REQUEST)
1415c39526b7SPramod Gunjikar 			evt_chanp->chan_backlog++;
1416c39526b7SPramod Gunjikar 
1417c39526b7SPramod Gunjikar 		evt_chanp->chan_evt_cnt++;
1418c39526b7SPramod Gunjikar 		mutex_exit(&evt_chanp->chan_mutex);
1419c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event : "
1420c39526b7SPramod Gunjikar 		    "chan %p, cnt %x", evt_chanp, evt_chanp->chan_evt_cnt);
1421c39526b7SPramod Gunjikar 	}
1422c39526b7SPramod Gunjikar 	mutex_exit(&filep->file_mutex);
1423c39526b7SPramod Gunjikar 	kmem_free(entry, sizeof (genlist_entry_t));
1424c39526b7SPramod Gunjikar 	kmem_free(queued_evt, sizeof (sol_ucma_event_t));
1425c39526b7SPramod Gunjikar 
1426c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event: Success");
1427c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&filep->file_uobj);
1428c39526b7SPramod Gunjikar 	return (0);
1429c39526b7SPramod Gunjikar }
1430c39526b7SPramod Gunjikar 
1431c39526b7SPramod Gunjikar /*
1432c39526b7SPramod Gunjikar  * This is used when ULP wants to set the QOS option. This is *not*
1433c39526b7SPramod Gunjikar  * supported by Solaris IB stack, return failure.
1434c39526b7SPramod Gunjikar  */
1435c39526b7SPramod Gunjikar /*ARGSUSED*/
1436c39526b7SPramod Gunjikar static int
1437c39526b7SPramod Gunjikar sol_ucma_set_option(dev_t dev, void *io_buf, struct uio *uio)
1438c39526b7SPramod Gunjikar {
1439c39526b7SPramod Gunjikar 		return (EINVAL);
1440c39526b7SPramod Gunjikar }
1441c39526b7SPramod Gunjikar 
1442c39526b7SPramod Gunjikar /*
1443c39526b7SPramod Gunjikar  * This is used when ULP uses librdmacm but uses out of band connection for CM.
1444c39526b7SPramod Gunjikar  */
1445c39526b7SPramod Gunjikar /*ARGSUSED*/
1446c39526b7SPramod Gunjikar static int
1447c39526b7SPramod Gunjikar sol_ucma_notify(dev_t dev, void *io_buf, struct uio *uio)
1448c39526b7SPramod Gunjikar {
1449c39526b7SPramod Gunjikar 	sol_ucma_notify_t	*notifyp;
1450c39526b7SPramod Gunjikar 	uint32_t			ucma_id;
1451c39526b7SPramod Gunjikar 	sol_ucma_chan_t		*chan;
1452c39526b7SPramod Gunjikar 	int					ret;
1453c39526b7SPramod Gunjikar 
1454c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "notify(%x, %p)", dev, io_buf);
1455c39526b7SPramod Gunjikar 	notifyp = (sol_ucma_notify_t *)io_buf;
1456c39526b7SPramod Gunjikar 	ucma_id = notifyp->id;
1457c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chan, "notify", 1))
1458c39526b7SPramod Gunjikar 		return (EINVAL);
1459c39526b7SPramod Gunjikar 	ASSERT(chan);
1460c39526b7SPramod Gunjikar 
1461c39526b7SPramod Gunjikar 	ret = rdma_notify(chan->chan_rdma_id, notifyp->event);
1462c39526b7SPramod Gunjikar 	if (ret)
1463c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "notify failed %x", ret);
1464c39526b7SPramod Gunjikar 	else
1465c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "notify Success");
1466c39526b7SPramod Gunjikar 	return (ret);
1467c39526b7SPramod Gunjikar }
1468c39526b7SPramod Gunjikar 
1469c39526b7SPramod Gunjikar /*ARGSUSED*/
1470c39526b7SPramod Gunjikar static int
1471c39526b7SPramod Gunjikar sol_ucma_join_mcast(dev_t dev, void *io_buf, struct uio *uio)
1472c39526b7SPramod Gunjikar {
1473c39526b7SPramod Gunjikar 	sol_ucma_join_mcast_t		*join_buf;
1474c39526b7SPramod Gunjikar 	sol_ucma_create_id_resp_t	join_resp;
1475c39526b7SPramod Gunjikar 	sol_ucma_chan_t			*chanp;
1476c39526b7SPramod Gunjikar 	sol_ucma_mcast_t		*mcastp;
1477c39526b7SPramod Gunjikar 	int		rc;
1478c39526b7SPramod Gunjikar 	uint32_t	ucma_id;
1479c39526b7SPramod Gunjikar 
1480c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "join_mcast(%x, %p)",
1481c39526b7SPramod Gunjikar 	    dev, io_buf);
1482c39526b7SPramod Gunjikar 	join_buf = (sol_ucma_join_mcast_t *)io_buf;
1483c39526b7SPramod Gunjikar 	ucma_id = join_buf->id;
1484c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chanp, "join_mcast", 1))
1485c39526b7SPramod Gunjikar 		return (EINVAL);
1486c39526b7SPramod Gunjikar 
1487c39526b7SPramod Gunjikar 	mcastp = kmem_zalloc(sizeof (sol_ucma_mcast_t), KM_SLEEP);
1488c39526b7SPramod Gunjikar 	bcopy((void *)(&(join_buf->addr)), (void *)(&(mcastp->mcast_addr)),
1489c39526b7SPramod Gunjikar 	    sizeof (struct sockaddr));
1490c39526b7SPramod Gunjikar 	mcastp->mcast_chan = chanp;
1491*d2a01201SToomas Soome 	sol_ofs_uobj_init(&mcastp->mcast_uobj, 0, SOL_UCMA_MCAST_TYPE);
1492c39526b7SPramod Gunjikar 	if (sol_ofs_uobj_add(&ucma_mcast_uo_tbl, &mcastp->mcast_uobj) != 0) {
1493c39526b7SPramod Gunjikar 		sol_ofs_uobj_free(&mcastp->mcast_uobj);
1494c39526b7SPramod Gunjikar 		return (ENOMEM);
1495c39526b7SPramod Gunjikar 	}
1496c39526b7SPramod Gunjikar 	mcastp->mcast_uobj.uo_live = 1;
1497c39526b7SPramod Gunjikar 	mcastp->mcast_id = join_resp.id = mcastp->mcast_uobj.uo_id;
1498c39526b7SPramod Gunjikar 	mcastp->mcast_uid = join_buf->uid;
1499c39526b7SPramod Gunjikar 
1500c39526b7SPramod Gunjikar 	rc = rdma_join_multicast(chanp->chan_rdma_id,
1501c39526b7SPramod Gunjikar 	    (struct sockaddr *)(&(join_buf->addr)), mcastp);
1502c39526b7SPramod Gunjikar 	if (rc) {
1503c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1504c39526b7SPramod Gunjikar 		    "join_mcast: rdma_join_multicast ret %x", rc);
1505c39526b7SPramod Gunjikar 		rw_enter(&(mcastp->mcast_uobj.uo_lock), RW_WRITER);
1506c39526b7SPramod Gunjikar 		(void) sol_ofs_uobj_remove(&ucma_mcast_uo_tbl,
1507c39526b7SPramod Gunjikar 		    &mcastp->mcast_uobj);
1508c39526b7SPramod Gunjikar 		rw_exit(&(mcastp->mcast_uobj.uo_lock));
1509c39526b7SPramod Gunjikar 		sol_ofs_uobj_free(&mcastp->mcast_uobj);
1510c39526b7SPramod Gunjikar 		return (rc);
1511c39526b7SPramod Gunjikar 	}
1512c39526b7SPramod Gunjikar 
1513c39526b7SPramod Gunjikar #ifdef	_LP64
1514c39526b7SPramod Gunjikar 	if (copyout(&join_resp, (void *) (join_buf->response.r_laddr),
1515c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_create_id_resp_t))) {
1516c39526b7SPramod Gunjikar #else
1517c39526b7SPramod Gunjikar 	if (copyout(&join_resp, (void *) (join_buf->response.r_addr),
1518c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_create_id_resp_t))) {
1519c39526b7SPramod Gunjikar #endif
1520c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "join_mcast: copyout "
1521c39526b7SPramod Gunjikar 		    "failed");
1522c39526b7SPramod Gunjikar 		rdma_leave_multicast(chanp->chan_rdma_id,
1523c39526b7SPramod Gunjikar 		    (struct sockaddr *)(&(join_buf->addr)));
1524c39526b7SPramod Gunjikar 		rw_enter(&(mcastp->mcast_uobj.uo_lock), RW_WRITER);
1525c39526b7SPramod Gunjikar 		(void) sol_ofs_uobj_remove(&ucma_mcast_uo_tbl,
1526c39526b7SPramod Gunjikar 		    &mcastp->mcast_uobj);
1527c39526b7SPramod Gunjikar 		rw_exit(&(mcastp->mcast_uobj.uo_lock));
1528c39526b7SPramod Gunjikar 		sol_ofs_uobj_free(&mcastp->mcast_uobj);
1529c39526b7SPramod Gunjikar 		return (EFAULT);
1530c39526b7SPramod Gunjikar 	}
1531c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "join_mcast: Return Success");
1532c39526b7SPramod Gunjikar 	return (0);
1533c39526b7SPramod Gunjikar }
1534c39526b7SPramod Gunjikar 
1535c39526b7SPramod Gunjikar /*ARGSUSED*/
1536c39526b7SPramod Gunjikar static int
1537c39526b7SPramod Gunjikar sol_ucma_leave_mcast(dev_t dev, void *io_buf, struct uio *uio)
1538c39526b7SPramod Gunjikar {
1539c39526b7SPramod Gunjikar 	sol_ucma_destroy_id_t		*id_inp;
1540c39526b7SPramod Gunjikar 	sol_ucma_destroy_id_resp_t	id_resp;
1541c39526b7SPramod Gunjikar 	sol_ucma_mcast_t		*mcastp;
1542c39526b7SPramod Gunjikar 	sol_ucma_chan_t			*chanp;
1543c39526b7SPramod Gunjikar 	uint32_t			ucma_id;
1544c39526b7SPramod Gunjikar 
1545c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "leave_mcast(%x, %p)",
1546c39526b7SPramod Gunjikar 	    dev, io_buf);
1547c39526b7SPramod Gunjikar 	id_inp = (sol_ucma_destroy_id_t *)io_buf;
1548c39526b7SPramod Gunjikar 	ucma_id = id_inp->id;
1549c39526b7SPramod Gunjikar 	mcastp = (sol_ucma_mcast_t *)sol_ofs_uobj_get_read(&ucma_mcast_uo_tbl,
1550c39526b7SPramod Gunjikar 	    ucma_id);
1551c39526b7SPramod Gunjikar 	if (mcastp == NULL) {
1552c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "leave_mcast: invalid "
1553c39526b7SPramod Gunjikar 		    "ID %x", ucma_id);
1554c39526b7SPramod Gunjikar 		return (EINVAL);
1555c39526b7SPramod Gunjikar 	}
1556c39526b7SPramod Gunjikar 	chanp = mcastp->mcast_chan;
1557c39526b7SPramod Gunjikar 
1558c39526b7SPramod Gunjikar 	rdma_leave_multicast(chanp->chan_rdma_id, &mcastp->mcast_addr);
1559c39526b7SPramod Gunjikar 	id_resp.events_reported = mcastp->mcast_events;
1560c39526b7SPramod Gunjikar 
1561c39526b7SPramod Gunjikar #ifdef	_LP64
1562c39526b7SPramod Gunjikar 	if (copyout(&id_resp, (void *) (id_inp->response.r_laddr),
1563c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_destroy_id_resp_t))) {
1564c39526b7SPramod Gunjikar #else
1565c39526b7SPramod Gunjikar 	if (copyout(&id_resp, (void *) (id_inp->response.r_addr),
1566c39526b7SPramod Gunjikar 	    sizeof (sol_ucma_destroy_id_resp_t))) {
1567c39526b7SPramod Gunjikar #endif
1568c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "leave_mcast: copyout "
1569c39526b7SPramod Gunjikar 		    "fault");
1570c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&mcastp->mcast_uobj);
1571c39526b7SPramod Gunjikar 		return (EFAULT);
1572c39526b7SPramod Gunjikar 	}
1573c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&mcastp->mcast_uobj);
1574c39526b7SPramod Gunjikar 	rw_enter(&(mcastp->mcast_uobj.uo_lock), RW_WRITER);
1575c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&ucma_mcast_uo_tbl, &mcastp->mcast_uobj);
1576c39526b7SPramod Gunjikar 	rw_exit(&(mcastp->mcast_uobj.uo_lock));
1577c39526b7SPramod Gunjikar 	sol_ofs_uobj_free(&mcastp->mcast_uobj);
1578c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "leave_mcast: ret 0");
1579c39526b7SPramod Gunjikar 	return (0);
1580c39526b7SPramod Gunjikar }
1581c39526b7SPramod Gunjikar 
1582c39526b7SPramod Gunjikar /*ARGSUSED*/
1583c39526b7SPramod Gunjikar static int
1584c39526b7SPramod Gunjikar sol_ucma_disconnect(dev_t dev, void *io_buf, struct uio *uio)
1585c39526b7SPramod Gunjikar {
1586c39526b7SPramod Gunjikar 	sol_ucma_disconnect_t	*disconnectp;
1587c39526b7SPramod Gunjikar 	uint32_t	ucma_id;
1588c39526b7SPramod Gunjikar 	sol_ucma_chan_t	*chan;
1589c39526b7SPramod Gunjikar 	int		ret;
1590c39526b7SPramod Gunjikar 
1591c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "disconnect(%x, %p)",
1592c39526b7SPramod Gunjikar 	    dev, io_buf);
1593c39526b7SPramod Gunjikar 	disconnectp = (sol_ucma_disconnect_t *)io_buf;
1594c39526b7SPramod Gunjikar 	ucma_id = disconnectp->id;
1595c39526b7SPramod Gunjikar 	if (get_file_chan(ucma_id, NULL, &chan, "disconnect", 1))
1596c39526b7SPramod Gunjikar 		return (EINVAL);
1597c39526b7SPramod Gunjikar 	ASSERT(chan);
1598c39526b7SPramod Gunjikar 
1599c39526b7SPramod Gunjikar 	/*
1600c39526b7SPramod Gunjikar 	 * For a TCP CMID, which has got the DISCONNECT event, call
1601c39526b7SPramod Gunjikar 	 * ibt_flush_qp(), to transition QP to error state.
1602c39526b7SPramod Gunjikar 	 */
1603c39526b7SPramod Gunjikar 	mutex_enter(&chan->chan_mutex);
1604c39526b7SPramod Gunjikar 	if (chan->chan_flush_qp_flag == SOL_UCMA_FLUSH_QP_PENDING) {
1605c39526b7SPramod Gunjikar 		chan->chan_flush_qp_flag = SOL_UCMA_FLUSH_QP_DONE;
1606c39526b7SPramod Gunjikar 		mutex_exit(&chan->chan_mutex);
1607c39526b7SPramod Gunjikar 		(*uverbs_flush_qp_fp)(chan->chan_qp_num);
1608c39526b7SPramod Gunjikar 	} else
1609c39526b7SPramod Gunjikar 		mutex_exit(&chan->chan_mutex);
1610c39526b7SPramod Gunjikar 
1611c39526b7SPramod Gunjikar 	ret = rdma_disconnect(chan->chan_rdma_id);
1612c39526b7SPramod Gunjikar 	mutex_enter(&chan->chan_mutex);
1613c39526b7SPramod Gunjikar 	chan->chan_flush_qp_flag = SOL_UCMA_FLUSH_QP_DONE;
1614c39526b7SPramod Gunjikar 	mutex_exit(&chan->chan_mutex);
1615c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "disconnect: ret %x", ret);
1616c39526b7SPramod Gunjikar 	return (ret);
1617c39526b7SPramod Gunjikar }
1618c39526b7SPramod Gunjikar 
1619c39526b7SPramod Gunjikar /*
1620c39526b7SPramod Gunjikar  * RDMA ID Event handler
1621c39526b7SPramod Gunjikar  */
1622c39526b7SPramod Gunjikar int
1623c39526b7SPramod Gunjikar sol_ucma_evt_hdlr(struct rdma_cm_id *idp, struct rdma_cm_event *eventp)
1624c39526b7SPramod Gunjikar {
1625c39526b7SPramod Gunjikar 	sol_ucma_chan_t		*chan, *req_chan;
1626c39526b7SPramod Gunjikar 	sol_ucma_file_t		*file;
1627c39526b7SPramod Gunjikar 	sol_ucma_event_t	*ucma_evt;
1628c39526b7SPramod Gunjikar 	sol_ucma_create_id_t	ucma_create_id;
1629c39526b7SPramod Gunjikar 
1630c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "ucma_evt_hdlr(%p, %p), "
1631c39526b7SPramod Gunjikar 	    "event %x, status %x", idp, eventp, eventp->event,
1632c39526b7SPramod Gunjikar 	    eventp->status);
1633c39526b7SPramod Gunjikar 	chan = (sol_ucma_chan_t *)idp->context;
1634c39526b7SPramod Gunjikar 	if (!chan) {
1635c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "ucma_evt_hdlr() - "
1636c39526b7SPramod Gunjikar 		    "after destroy - %p", idp);
1637c39526b7SPramod Gunjikar 		return (0);
1638c39526b7SPramod Gunjikar 	}
1639c39526b7SPramod Gunjikar 	mutex_enter(&chan->chan_mutex);
1640c39526b7SPramod Gunjikar 	file = chan->chan_file;
1641c39526b7SPramod Gunjikar 	if (!file) {
1642c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str, "ucma_evt_hdlr() - "
1643c39526b7SPramod Gunjikar 		    "after file destroy - idp %p", idp);
1644c39526b7SPramod Gunjikar 		mutex_exit(&chan->chan_mutex);
1645c39526b7SPramod Gunjikar 		return (0);
1646c39526b7SPramod Gunjikar 	}
1647c39526b7SPramod Gunjikar 	mutex_exit(&chan->chan_mutex);
1648c39526b7SPramod Gunjikar 
1649c39526b7SPramod Gunjikar 	mutex_enter(&file->file_mutex);
1650c39526b7SPramod Gunjikar 	if (file->file_evt_close_flag == SOL_UCMA_EVT_DISABLED) {
1651c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str, "ucma_evt_hdlr() - "
1652c39526b7SPramod Gunjikar 		    "after file close - idp %p", idp);
1653c39526b7SPramod Gunjikar 		mutex_exit(&file->file_mutex);
1654c39526b7SPramod Gunjikar 		return (0);
1655c39526b7SPramod Gunjikar 	}
1656c39526b7SPramod Gunjikar 	file->file_evt_close_flag = SOL_UCMA_EVT_PROGRESS;
1657c39526b7SPramod Gunjikar 	mutex_exit(&file->file_mutex);
1658c39526b7SPramod Gunjikar 
1659c39526b7SPramod Gunjikar 	/*
1660c39526b7SPramod Gunjikar 	 * If the event is RDMA_CM_EVENT_CONNECT_REQUEST, allocate a
1661c39526b7SPramod Gunjikar 	 * new chan. The rdma_cm_id for this chan has already been
1662c39526b7SPramod Gunjikar 	 * allocated by sol_ofs.
1663c39526b7SPramod Gunjikar 	 */
1664c39526b7SPramod Gunjikar 	ucma_evt = kmem_zalloc(sizeof (sol_ucma_event_t), KM_SLEEP);
1665c39526b7SPramod Gunjikar 	ucma_evt->event_chan = chan;
1666c39526b7SPramod Gunjikar 	if (eventp->event == RDMA_CM_EVENT_CONNECT_REQUEST) {
1667c39526b7SPramod Gunjikar 		mutex_enter(&chan->chan_mutex);
1668c39526b7SPramod Gunjikar 		if (!chan->chan_backlog) {
1669c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str,
1670c39526b7SPramod Gunjikar 			    "backlog exceeded");
1671c39526b7SPramod Gunjikar 			mutex_exit(&chan->chan_mutex);
1672c39526b7SPramod Gunjikar 			mutex_enter(&file->file_mutex);
1673c39526b7SPramod Gunjikar 			file->file_evt_close_flag = SOL_UCMA_EVT_NONE;
1674c39526b7SPramod Gunjikar 			cv_broadcast(&file->file_evt_close_cv);
1675c39526b7SPramod Gunjikar 			mutex_exit(&file->file_mutex);
1676c39526b7SPramod Gunjikar 			kmem_free(ucma_evt, sizeof (sol_ucma_event_t));
1677c39526b7SPramod Gunjikar 			return (-1);
1678c39526b7SPramod Gunjikar 		}
1679c39526b7SPramod Gunjikar 		chan->chan_backlog--;
1680c39526b7SPramod Gunjikar 		mutex_exit(&chan->chan_mutex);
1681c39526b7SPramod Gunjikar 		ucma_create_id.uid = chan->chan_user_id;
1682c39526b7SPramod Gunjikar 		req_chan = ucma_alloc_chan(file, &ucma_create_id);
1683c39526b7SPramod Gunjikar 		if (req_chan == NULL)  {
1684c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1685c39526b7SPramod Gunjikar 			    "evt hdlr: No free Channel");
1686c39526b7SPramod Gunjikar 			sol_ofs_uobj_put(&file->file_uobj);
1687c39526b7SPramod Gunjikar 			mutex_enter(&file->file_mutex);
1688c39526b7SPramod Gunjikar 			file->file_evt_close_flag = SOL_UCMA_EVT_NONE;
1689c39526b7SPramod Gunjikar 			cv_broadcast(&file->file_evt_close_cv);
1690c39526b7SPramod Gunjikar 			mutex_exit(&file->file_mutex);
1691c39526b7SPramod Gunjikar 			return (-1);
1692c39526b7SPramod Gunjikar 		}
1693c39526b7SPramod Gunjikar 		req_chan->chan_rdma_id = idp;
1694c39526b7SPramod Gunjikar 		mutex_enter(&req_chan->chan_mutex);
1695c39526b7SPramod Gunjikar 		idp->context = req_chan;
1696c39526b7SPramod Gunjikar 		mutex_exit(&req_chan->chan_mutex);
1697c39526b7SPramod Gunjikar 		chan = req_chan;
1698c39526b7SPramod Gunjikar 	} else if (eventp->event == RDMA_CM_EVENT_DISCONNECTED ||
1699c39526b7SPramod Gunjikar 	    eventp->event == RDMA_CM_EVENT_REJECTED) {
1700c39526b7SPramod Gunjikar 		void	*qphdl;
1701c39526b7SPramod Gunjikar 
1702c39526b7SPramod Gunjikar 		/*
1703c39526b7SPramod Gunjikar 		 * Connection has been rejected or disconnected,
1704c39526b7SPramod Gunjikar 		 * Enable uverbs to free QP, if it had been disabled
1705c39526b7SPramod Gunjikar 		 * before. sol_uverbs will free the QP appropriately.
1706c39526b7SPramod Gunjikar 		 */
1707c39526b7SPramod Gunjikar 		mutex_enter(&chan->chan_mutex);
1708c39526b7SPramod Gunjikar 		qphdl = chan->chan_qp_hdl;
1709c39526b7SPramod Gunjikar 		chan->chan_qp_hdl = NULL;
1710c39526b7SPramod Gunjikar 		if (idp->ps == RDMA_PS_TCP &&
1711c39526b7SPramod Gunjikar 		    chan->chan_flush_qp_flag != SOL_UCMA_FLUSH_QP_DONE &&
1712c39526b7SPramod Gunjikar 		    eventp->event == RDMA_CM_EVENT_DISCONNECTED) {
1713c39526b7SPramod Gunjikar 			chan->chan_flush_qp_flag =
1714c39526b7SPramod Gunjikar 			    SOL_UCMA_FLUSH_QP_PENDING;
1715c39526b7SPramod Gunjikar 		}
1716c39526b7SPramod Gunjikar 		mutex_exit(&chan->chan_mutex);
1717c39526b7SPramod Gunjikar 
1718c39526b7SPramod Gunjikar 		if (idp->ps == RDMA_PS_TCP && qphdl)
1719c39526b7SPramod Gunjikar 			(*uverbs_set_qp_free_state_fp) (
1720c39526b7SPramod Gunjikar 			    SOL_UVERBS2UCMA_ENABLE_QP_FREE, 0, qphdl);
1721c39526b7SPramod Gunjikar 	} else if (eventp->event == RDMA_CM_EVENT_ESTABLISHED &&
1722c39526b7SPramod Gunjikar 	    chan->chan_flags & SOL_UCMA_CHAN_CONNECT_FLAG)
1723c39526b7SPramod Gunjikar 		eventp->event = RDMA_CM_EVENT_CONNECT_RESPONSE;
1724c39526b7SPramod Gunjikar 
1725c39526b7SPramod Gunjikar 	ucma_evt->event_resp.event = eventp->event;
1726c39526b7SPramod Gunjikar 	ucma_evt->event_resp.status = eventp->status;
1727c39526b7SPramod Gunjikar 	if (idp->ps == RDMA_PS_UDP || idp->ps == RDMA_PS_IPOIB)
1728c39526b7SPramod Gunjikar 		rdma2usr_ud_param(&(eventp->param.ud),
1729c39526b7SPramod Gunjikar 		    &(ucma_evt->event_resp.param.ud));
1730c39526b7SPramod Gunjikar 	else
1731c39526b7SPramod Gunjikar 		rdma2usr_conn_param(&(eventp->param.conn),
1732c39526b7SPramod Gunjikar 		    &(ucma_evt->event_resp.param.conn));
1733c39526b7SPramod Gunjikar 
1734c39526b7SPramod Gunjikar 	if (eventp->event == RDMA_CM_EVENT_MULTICAST_JOIN || eventp->event ==
1735c39526b7SPramod Gunjikar 	    RDMA_CM_EVENT_MULTICAST_ERROR) {
1736c39526b7SPramod Gunjikar 		ucma_evt->event_mcast = (sol_ucma_mcast_t *)
1737c39526b7SPramod Gunjikar 		    eventp->param.ud.private_data;
1738c39526b7SPramod Gunjikar 		ucma_evt->event_resp.uid = (ucma_evt->event_mcast)->mcast_uid;
1739c39526b7SPramod Gunjikar 		ucma_evt->event_resp.id = (ucma_evt->event_mcast)->mcast_id;
1740c39526b7SPramod Gunjikar 	} else {
1741c39526b7SPramod Gunjikar 		ucma_evt->event_resp.uid = chan->chan_user_id;
1742c39526b7SPramod Gunjikar 		ucma_evt->event_resp.id = chan->chan_id;
1743c39526b7SPramod Gunjikar 	}
1744c39526b7SPramod Gunjikar 
1745c39526b7SPramod Gunjikar 	mutex_enter(&file->file_mutex);
1746c39526b7SPramod Gunjikar 	(void) add_genlist(&file->file_evt_list, (uintptr_t)ucma_evt, NULL);
1747c39526b7SPramod Gunjikar 	file->file_pending_evt_cnt++;
1748c39526b7SPramod Gunjikar 	mutex_exit(&file->file_mutex);
1749c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "ucma_evt_hdlr-pollwakeup");
1750c39526b7SPramod Gunjikar 	pollwakeup(file->file_pollhead, POLLIN | POLLRDNORM);
1751c39526b7SPramod Gunjikar 	mutex_enter(&file->file_mutex);
1752c39526b7SPramod Gunjikar 	cv_broadcast(&file->file_evt_cv);
1753c39526b7SPramod Gunjikar 	mutex_exit(&file->file_mutex);
1754c39526b7SPramod Gunjikar 
1755c39526b7SPramod Gunjikar 	mutex_enter(&file->file_mutex);
1756c39526b7SPramod Gunjikar 	file->file_evt_close_flag = SOL_UCMA_EVT_NONE;
1757c39526b7SPramod Gunjikar 	cv_broadcast(&file->file_evt_close_cv);
1758c39526b7SPramod Gunjikar 	mutex_exit(&file->file_mutex);
1759c39526b7SPramod Gunjikar 	return (0);
1760c39526b7SPramod Gunjikar }
1761c39526b7SPramod Gunjikar 
1762c39526b7SPramod Gunjikar /*
1763c39526b7SPramod Gunjikar  * Local Functions
1764c39526b7SPramod Gunjikar  */
1765c39526b7SPramod Gunjikar static sol_ucma_file_t *
1766c39526b7SPramod Gunjikar ucma_alloc_file(minor_t *new_minorp)
1767c39526b7SPramod Gunjikar {
1768c39526b7SPramod Gunjikar 	sol_ucma_file_t	*new_file;
1769c39526b7SPramod Gunjikar 
1770c39526b7SPramod Gunjikar 	new_file = kmem_zalloc(sizeof (sol_ucma_file_t), KM_SLEEP);
1771*d2a01201SToomas Soome 	sol_ofs_uobj_init(&new_file->file_uobj, 0, SOL_UCMA_EVT_FILE_TYPE);
1772c39526b7SPramod Gunjikar 	if (sol_ofs_uobj_add(&ucma_file_uo_tbl, &new_file->file_uobj) != 0) {
1773c39526b7SPramod Gunjikar 		sol_ofs_uobj_free(&new_file->file_uobj);
1774c39526b7SPramod Gunjikar 		return (NULL);
1775c39526b7SPramod Gunjikar 	}
1776c39526b7SPramod Gunjikar 	new_file->file_uobj.uo_live = 1;
1777c39526b7SPramod Gunjikar 	init_genlist(&new_file->file_id_list);
1778c39526b7SPramod Gunjikar 	init_genlist(&new_file->file_evt_list);
1779c39526b7SPramod Gunjikar 
1780c39526b7SPramod Gunjikar 	mutex_enter(&sol_ucma.ucma_mutex);
1781c39526b7SPramod Gunjikar 	sol_ucma.ucma_num_file++;
1782c39526b7SPramod Gunjikar 	mutex_exit(&sol_ucma.ucma_mutex);
1783c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "new file num %x, %p",
1784c39526b7SPramod Gunjikar 	    (new_file->file_uobj).uo_id, new_file);
1785c39526b7SPramod Gunjikar 
1786c39526b7SPramod Gunjikar 	mutex_init(&new_file->file_mutex, NULL,
1787c39526b7SPramod Gunjikar 	    MUTEX_DRIVER, NULL);
1788c39526b7SPramod Gunjikar 	cv_init(&new_file->file_evt_cv, NULL, CV_DRIVER,
1789c39526b7SPramod Gunjikar 	    NULL);
1790c39526b7SPramod Gunjikar 	cv_init(&new_file->file_evt_close_cv, NULL, CV_DRIVER,
1791c39526b7SPramod Gunjikar 	    NULL);
1792c39526b7SPramod Gunjikar 	new_file->file_pollhead = kmem_zalloc(sizeof (struct pollhead),
1793c39526b7SPramod Gunjikar 	    KM_SLEEP);
1794c39526b7SPramod Gunjikar 
1795c39526b7SPramod Gunjikar 	*new_minorp = (minor_t)((new_file->file_uobj).uo_id);
1796c39526b7SPramod Gunjikar 	return (new_file);
1797c39526b7SPramod Gunjikar }
1798c39526b7SPramod Gunjikar 
1799c39526b7SPramod Gunjikar static sol_ucma_chan_t *
1800c39526b7SPramod Gunjikar ucma_alloc_chan(sol_ucma_file_t *filep, sol_ucma_create_id_t *create_id_inp)
1801c39526b7SPramod Gunjikar {
1802c39526b7SPramod Gunjikar 	sol_ucma_chan_t		*new_chanp;
1803c39526b7SPramod Gunjikar 
1804c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_alloc_chan(%p, %p)",
1805c39526b7SPramod Gunjikar 	    filep, create_id_inp);
1806c39526b7SPramod Gunjikar 
1807c39526b7SPramod Gunjikar 	new_chanp = kmem_zalloc(sizeof (sol_ucma_chan_t), KM_SLEEP);
1808*d2a01201SToomas Soome 	sol_ofs_uobj_init(&new_chanp->chan_uobj, 0, SOL_UCMA_CM_ID_TYPE);
1809c39526b7SPramod Gunjikar 	if (sol_ofs_uobj_add(&ucma_ctx_uo_tbl, &new_chanp->chan_uobj) != 0) {
1810c39526b7SPramod Gunjikar 		sol_ofs_uobj_free(&new_chanp->chan_uobj);
1811c39526b7SPramod Gunjikar 		return (NULL);
1812c39526b7SPramod Gunjikar 	}
1813c39526b7SPramod Gunjikar 	mutex_init(&new_chanp->chan_mutex, NULL, MUTEX_DRIVER, NULL);
1814c39526b7SPramod Gunjikar 
1815c39526b7SPramod Gunjikar 	new_chanp->chan_uobj.uo_live = 1;
1816c39526b7SPramod Gunjikar 	mutex_enter(&filep->file_mutex);
1817c39526b7SPramod Gunjikar 	new_chanp->chan_list_ent = add_genlist(&filep->file_id_list,
1818c39526b7SPramod Gunjikar 	    (uintptr_t)new_chanp, NULL);
1819c39526b7SPramod Gunjikar 	mutex_exit(&filep->file_mutex);
1820c39526b7SPramod Gunjikar 
1821c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_alloc_chan - filep %p, "
1822c39526b7SPramod Gunjikar 	    "chan_num %x, new_chan %p", filep, (new_chanp->chan_uobj).uo_id,
1823c39526b7SPramod Gunjikar 	    new_chanp);
1824c39526b7SPramod Gunjikar 
1825c39526b7SPramod Gunjikar 	new_chanp->chan_file = filep;
1826c39526b7SPramod Gunjikar 	new_chanp->chan_user_id = create_id_inp->uid;
1827c39526b7SPramod Gunjikar 	new_chanp->chan_id = (new_chanp->chan_uobj).uo_id;
1828c39526b7SPramod Gunjikar 
1829c39526b7SPramod Gunjikar 	return (new_chanp);
1830c39526b7SPramod Gunjikar }
1831c39526b7SPramod Gunjikar 
1832c39526b7SPramod Gunjikar static void
1833c39526b7SPramod Gunjikar ucma_free_chan(sol_ucma_chan_t *chanp, int delete_list)
1834c39526b7SPramod Gunjikar {
1835c39526b7SPramod Gunjikar 	sol_ucma_file_t	*filep;
1836c39526b7SPramod Gunjikar 
1837c39526b7SPramod Gunjikar 	ASSERT(chanp);
1838c39526b7SPramod Gunjikar 	if (delete_list) {
1839c39526b7SPramod Gunjikar 		filep = chanp->chan_file;
1840c39526b7SPramod Gunjikar 		ASSERT(filep);
1841c39526b7SPramod Gunjikar 		mutex_enter(&filep->file_mutex);
1842c39526b7SPramod Gunjikar 		delete_genlist(&filep->file_id_list, chanp->chan_list_ent);
1843c39526b7SPramod Gunjikar 		mutex_exit(&filep->file_mutex);
1844c39526b7SPramod Gunjikar 	}
1845c39526b7SPramod Gunjikar 
1846c39526b7SPramod Gunjikar 	mutex_destroy(&chanp->chan_mutex);
1847c39526b7SPramod Gunjikar 	rw_enter(&(chanp->chan_uobj.uo_lock), RW_WRITER);
1848c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&ucma_ctx_uo_tbl, &(chanp->chan_uobj));
1849c39526b7SPramod Gunjikar 	rw_exit(&(chanp->chan_uobj.uo_lock));
1850c39526b7SPramod Gunjikar 	sol_ofs_uobj_free(&(chanp->chan_uobj));
1851c39526b7SPramod Gunjikar }
1852c39526b7SPramod Gunjikar 
1853c39526b7SPramod Gunjikar static int
1854c39526b7SPramod Gunjikar get_file_chan(uint32_t ucma_id, sol_ucma_file_t **filep,
1855c39526b7SPramod Gunjikar     sol_ucma_chan_t **chanp, char *caller, int flag_err)
1856c39526b7SPramod Gunjikar {
1857c39526b7SPramod Gunjikar 	sol_ucma_chan_t	*chan;
1858c39526b7SPramod Gunjikar 
1859c39526b7SPramod Gunjikar 	if (filep)
1860c39526b7SPramod Gunjikar 		*filep = NULL;
1861c39526b7SPramod Gunjikar 	if (chanp)
1862c39526b7SPramod Gunjikar 		*chanp = NULL;
1863c39526b7SPramod Gunjikar 
1864c39526b7SPramod Gunjikar 	chan = (sol_ucma_chan_t *)sol_ofs_uobj_get_read(&ucma_ctx_uo_tbl,
1865c39526b7SPramod Gunjikar 	    ucma_id);
1866c39526b7SPramod Gunjikar 	if (chan == NULL) {
1867c39526b7SPramod Gunjikar 		if (flag_err)
1868c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1869c39526b7SPramod Gunjikar 			    "%s, ucma_id %x invalid", caller, ucma_id);
1870c39526b7SPramod Gunjikar 		else
1871c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str,
1872c39526b7SPramod Gunjikar 			    "%s, ucma_id %x invalid", caller, ucma_id);
1873c39526b7SPramod Gunjikar 		return (-1);
1874c39526b7SPramod Gunjikar 	}
1875c39526b7SPramod Gunjikar 
1876c39526b7SPramod Gunjikar 	if (filep)
1877c39526b7SPramod Gunjikar 		*filep = chan->chan_file;
1878c39526b7SPramod Gunjikar 	if (chanp)
1879c39526b7SPramod Gunjikar 		*chanp = chan;
1880c39526b7SPramod Gunjikar 
1881c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&chan->chan_uobj);
1882c39526b7SPramod Gunjikar 	return (0);
1883c39526b7SPramod Gunjikar }
1884c39526b7SPramod Gunjikar 
1885c39526b7SPramod Gunjikar static void
1886c39526b7SPramod Gunjikar rdma2usr_pathrec(struct ib_sa_path_rec *kern_path,
1887c39526b7SPramod Gunjikar     struct ib_user_path_rec *usr_path)
1888c39526b7SPramod Gunjikar {
1889c39526b7SPramod Gunjikar 	bcopy(&kern_path->dgid, &usr_path->dgid, 16);
1890c39526b7SPramod Gunjikar 	bcopy(&kern_path->sgid, &usr_path->sgid, 16);
1891c39526b7SPramod Gunjikar 	usr_path->dlid = kern_path->dlid;
1892c39526b7SPramod Gunjikar 	usr_path->slid = kern_path->slid;
1893c39526b7SPramod Gunjikar 	usr_path->raw_traffic = kern_path->raw_traffic;
1894c39526b7SPramod Gunjikar 	usr_path->flow_label = kern_path->flow_label;
1895c39526b7SPramod Gunjikar 	usr_path->reversible = kern_path->reversible;
1896c39526b7SPramod Gunjikar 	usr_path->mtu = kern_path->mtu;
1897c39526b7SPramod Gunjikar 	usr_path->pkey = kern_path->pkey;
1898c39526b7SPramod Gunjikar 	usr_path->hop_limit = kern_path->hop_limit;
1899c39526b7SPramod Gunjikar 	usr_path->traffic_class = kern_path->traffic_class;
1900c39526b7SPramod Gunjikar 	usr_path->sl = kern_path->sl;
1901c39526b7SPramod Gunjikar 	usr_path->mtu_selector = kern_path->mtu_selector;
1902c39526b7SPramod Gunjikar 	usr_path->rate_selector = kern_path->rate_selector;
1903c39526b7SPramod Gunjikar 	usr_path->rate = kern_path->rate;
1904c39526b7SPramod Gunjikar 	usr_path->packet_life_time_selector =
1905c39526b7SPramod Gunjikar 	    kern_path->packet_life_time_selector;
1906c39526b7SPramod Gunjikar 	usr_path->packet_life_time = kern_path->packet_life_time;
1907c39526b7SPramod Gunjikar 	usr_path->preference = kern_path->preference;
1908fffafeb2SJohnny Cheung 	usr_path->numb_path = kern_path->numb_path;
1909c39526b7SPramod Gunjikar }
1910c39526b7SPramod Gunjikar 
1911c39526b7SPramod Gunjikar static void
1912c39526b7SPramod Gunjikar rdma2usr_route(struct rdma_cm_id *idp, sol_ucma_query_route_resp_t *resp)
1913c39526b7SPramod Gunjikar {
1914c39526b7SPramod Gunjikar 	struct rdma_route	*routep;
1915c39526b7SPramod Gunjikar 	int	i;
1916c39526b7SPramod Gunjikar 
1917c39526b7SPramod Gunjikar 	routep = &(idp->route);
1918c39526b7SPramod Gunjikar 	if (idp->device) {
1919c39526b7SPramod Gunjikar 		resp->node_guid = idp->device->node_guid;
1920c39526b7SPramod Gunjikar 		resp->port_num = idp->port_num;
1921c39526b7SPramod Gunjikar 	}
1922c39526b7SPramod Gunjikar 	bcopy(&(routep->addr.src_addr), &resp->src_addr,
1923c39526b7SPramod Gunjikar 	    sizeof (struct sockaddr_in6));
1924c39526b7SPramod Gunjikar 	bcopy(&(routep->addr.dst_addr), &resp->dst_addr,
1925c39526b7SPramod Gunjikar 	    sizeof (struct sockaddr_in6));
1926c39526b7SPramod Gunjikar 	resp->num_paths = routep->num_paths;
1927c39526b7SPramod Gunjikar 	for (i = 0; i < resp->num_paths; i++) {
1928c39526b7SPramod Gunjikar 		rdma2usr_pathrec(&(routep->path_rec[i]),
1929c39526b7SPramod Gunjikar 		    &(resp->ib_route[i]));
1930c39526b7SPramod Gunjikar 	}
1931c39526b7SPramod Gunjikar }
1932c39526b7SPramod Gunjikar 
1933c39526b7SPramod Gunjikar static void
1934c39526b7SPramod Gunjikar usr2rdma_conn_param(struct rdma_ucm_conn_param *usr_conn_paramp,
1935c39526b7SPramod Gunjikar     struct rdma_conn_param *conn_paramp)
1936c39526b7SPramod Gunjikar {
1937c39526b7SPramod Gunjikar 	conn_paramp->private_data = usr_conn_paramp->private_data;
1938c39526b7SPramod Gunjikar 	conn_paramp->private_data_len = usr_conn_paramp->private_data_len;
1939c39526b7SPramod Gunjikar 	conn_paramp->responder_resources = usr_conn_paramp->responder_resources;
1940c39526b7SPramod Gunjikar 	conn_paramp->initiator_depth = usr_conn_paramp->initiator_depth;
1941c39526b7SPramod Gunjikar 	conn_paramp->flow_control = usr_conn_paramp->flow_control;
1942c39526b7SPramod Gunjikar 	conn_paramp->retry_count = usr_conn_paramp->retry_count;
1943c39526b7SPramod Gunjikar 	conn_paramp->rnr_retry_count = usr_conn_paramp->rnr_retry_count;
1944c39526b7SPramod Gunjikar 	conn_paramp->srq = usr_conn_paramp->srq;
1945c39526b7SPramod Gunjikar 	conn_paramp->qp_num = usr_conn_paramp->qp_num;
1946c39526b7SPramod Gunjikar }
1947c39526b7SPramod Gunjikar 
1948c39526b7SPramod Gunjikar static void
1949c39526b7SPramod Gunjikar rdma2usr_conn_param(struct rdma_conn_param *conn_paramp,
1950c39526b7SPramod Gunjikar     struct rdma_ucm_conn_param *usr_conn_paramp)
1951c39526b7SPramod Gunjikar {
1952c39526b7SPramod Gunjikar 	usr_conn_paramp->private_data_len = conn_paramp->private_data_len;
1953c39526b7SPramod Gunjikar 
1954c39526b7SPramod Gunjikar 	bzero(usr_conn_paramp->private_data, RDMA_MAX_PRIVATE_DATA);
1955c39526b7SPramod Gunjikar 	if (conn_paramp->private_data)
1956c39526b7SPramod Gunjikar 		bcopy(conn_paramp->private_data,
1957c39526b7SPramod Gunjikar 		    usr_conn_paramp->private_data,
1958c39526b7SPramod Gunjikar 		    usr_conn_paramp->private_data_len);
1959c39526b7SPramod Gunjikar 	usr_conn_paramp->responder_resources = conn_paramp->responder_resources;
1960c39526b7SPramod Gunjikar 	usr_conn_paramp->initiator_depth = conn_paramp->initiator_depth;
1961c39526b7SPramod Gunjikar 	usr_conn_paramp->flow_control = conn_paramp->flow_control;
1962c39526b7SPramod Gunjikar 	usr_conn_paramp->retry_count = conn_paramp->retry_count;
1963c39526b7SPramod Gunjikar 	usr_conn_paramp->rnr_retry_count = conn_paramp->rnr_retry_count;
1964c39526b7SPramod Gunjikar 	usr_conn_paramp->srq = conn_paramp->srq;
1965c39526b7SPramod Gunjikar 	usr_conn_paramp->qp_num = conn_paramp->qp_num;
1966c39526b7SPramod Gunjikar }
1967c39526b7SPramod Gunjikar 
1968c39526b7SPramod Gunjikar static void
1969c39526b7SPramod Gunjikar rdma2usr_ud_param(struct rdma_ud_param *ud_paramp,
1970c39526b7SPramod Gunjikar     sol_ucma_ud_param_t *usr_ud_paramp)
1971c39526b7SPramod Gunjikar {
1972c39526b7SPramod Gunjikar 	struct ib_ah_attr		*ah_attrp;
1973c39526b7SPramod Gunjikar 	struct ib_uverbs_ah_attr	*usr_ah_attrp;
1974c39526b7SPramod Gunjikar 
1975c39526b7SPramod Gunjikar 	usr_ud_paramp->private_data_len = ud_paramp->private_data_len;
1976c39526b7SPramod Gunjikar 
1977c39526b7SPramod Gunjikar 	bzero(usr_ud_paramp->private_data, RDMA_MAX_PRIVATE_DATA);
1978c39526b7SPramod Gunjikar 	if (ud_paramp->private_data)
1979c39526b7SPramod Gunjikar 		bcopy(ud_paramp->private_data,
1980c39526b7SPramod Gunjikar 		    usr_ud_paramp->private_data,
1981c39526b7SPramod Gunjikar 		    usr_ud_paramp->private_data_len);
1982c39526b7SPramod Gunjikar 	usr_ud_paramp->qp_num = ud_paramp->qp_num;
1983c39526b7SPramod Gunjikar 	usr_ud_paramp->qkey = ud_paramp->qkey;
1984c39526b7SPramod Gunjikar 
1985c39526b7SPramod Gunjikar 	ah_attrp = &(ud_paramp->ah_attr);
1986c39526b7SPramod Gunjikar 	usr_ah_attrp = &(usr_ud_paramp->ah_attr);
1987c39526b7SPramod Gunjikar 	bcopy(&(ah_attrp->grh.dgid), &(usr_ah_attrp->grh.dgid[0]), 16);
1988c39526b7SPramod Gunjikar 	usr_ah_attrp->grh.flow_label = ah_attrp->grh.flow_label;
1989c39526b7SPramod Gunjikar 	usr_ah_attrp->grh.sgid_index = ah_attrp->grh.sgid_index;
1990c39526b7SPramod Gunjikar 	usr_ah_attrp->grh.hop_limit = ah_attrp->grh.hop_limit;
1991c39526b7SPramod Gunjikar 	usr_ah_attrp->grh.traffic_class = ah_attrp->grh.traffic_class;
1992c39526b7SPramod Gunjikar 	usr_ah_attrp->dlid = ah_attrp->dlid;
1993c39526b7SPramod Gunjikar 	usr_ah_attrp->sl = ah_attrp->sl;
1994c39526b7SPramod Gunjikar 	usr_ah_attrp->src_path_bits = ah_attrp->src_path_bits;
1995c39526b7SPramod Gunjikar 	usr_ah_attrp->static_rate = ah_attrp->static_rate;
1996c39526b7SPramod Gunjikar 	usr_ah_attrp->is_global = ah_attrp->ah_flags;
1997c39526b7SPramod Gunjikar 	usr_ah_attrp->port_num = ah_attrp->port_num;
1998c39526b7SPramod Gunjikar }
1999c39526b7SPramod Gunjikar 
2000c39526b7SPramod Gunjikar static void
2001c39526b7SPramod Gunjikar sol_ucma_user_objs_init()
2002c39526b7SPramod Gunjikar {
2003c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&ucma_file_uo_tbl, sizeof (sol_ucma_file_t));
2004c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&ucma_ctx_uo_tbl, sizeof (sol_ucma_chan_t));
2005c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&ucma_mcast_uo_tbl, sizeof (sol_ucma_mcast_t));
2006c39526b7SPramod Gunjikar }
2007c39526b7SPramod Gunjikar 
2008c39526b7SPramod Gunjikar static void
2009c39526b7SPramod Gunjikar sol_ucma_user_objs_fini()
2010c39526b7SPramod Gunjikar {
2011c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&ucma_file_uo_tbl);
2012c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&ucma_ctx_uo_tbl);
2013c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&ucma_mcast_uo_tbl);
2014c39526b7SPramod Gunjikar }
2015