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.
24c39526b7SPramod Gunjikar  */
25c39526b7SPramod Gunjikar 
26c39526b7SPramod Gunjikar /*
27c39526b7SPramod Gunjikar  * sol_uverbs.c
28c39526b7SPramod Gunjikar  *
29c39526b7SPramod Gunjikar  * Solaris OFED User Verbs kernel agent module
30c39526b7SPramod Gunjikar  *
31c39526b7SPramod Gunjikar  */
32c39526b7SPramod Gunjikar #include <sys/devops.h>
33c39526b7SPramod Gunjikar #include <sys/conf.h>
34c39526b7SPramod Gunjikar #include <sys/modctl.h>
35c39526b7SPramod Gunjikar #include <sys/types.h>
36c39526b7SPramod Gunjikar #include <sys/file.h>
37c39526b7SPramod Gunjikar #include <sys/errno.h>
38c39526b7SPramod Gunjikar #include <sys/open.h>
39c39526b7SPramod Gunjikar #include <sys/cred.h>
40c39526b7SPramod Gunjikar #include <sys/uio.h>
41c39526b7SPramod Gunjikar #include <sys/semaphore.h>
42c39526b7SPramod Gunjikar #include <sys/stat.h>
43c39526b7SPramod Gunjikar #include <sys/ddi.h>
44c39526b7SPramod Gunjikar #include <sys/sunddi.h>
45c39526b7SPramod Gunjikar #include <sys/ib/clients/of/ofa_solaris.h>
46c39526b7SPramod Gunjikar 
47c39526b7SPramod Gunjikar #include <sys/ib/ibtl/ibvti.h>
48c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
49c39526b7SPramod Gunjikar #include <sys/ib/clients/of/ofed_kernel.h>
50c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs.h>
51c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_event.h>
52c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_comp.h>
53c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_qp.h>
54c39526b7SPramod Gunjikar 
55c39526b7SPramod Gunjikar static void *statep;
56c39526b7SPramod Gunjikar static ibt_clnt_hdl_t	sol_uverbs_ib_clntp = NULL;
57c39526b7SPramod Gunjikar 
58c39526b7SPramod Gunjikar char	*sol_uverbs_dbg_str = "sol_uverbs";
59c39526b7SPramod Gunjikar 
60c39526b7SPramod Gunjikar static int sol_uverbs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
61c39526b7SPramod Gunjikar static int sol_uverbs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
62c39526b7SPramod Gunjikar static int sol_uverbs_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
63c39526b7SPramod Gunjikar     void **resultp);
64c39526b7SPramod Gunjikar static int sol_uverbs_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
65c39526b7SPramod Gunjikar     int flags, char *name, caddr_t valuep, int *lengthp);
66c39526b7SPramod Gunjikar static int sol_uverbs_open(dev_t *devp, int flag, int otyp, cred_t *cred);
67c39526b7SPramod Gunjikar static int sol_uverbs_close(dev_t dev, int flag, int otyp, cred_t *cred);
68c39526b7SPramod Gunjikar static int sol_uverbs_poll(dev_t, short, int, short *, struct pollhead **);
69c39526b7SPramod Gunjikar static int sol_uverbs_read(dev_t dev, struct uio *uiop, cred_t *credp);
70c39526b7SPramod Gunjikar static int sol_uverbs_mmap(dev_t dev, off_t sol_uverbs_mmap, int prot);
71c39526b7SPramod Gunjikar static int sol_uverbs_write(dev_t dev, struct uio *uiop, cred_t *credp);
72c39526b7SPramod Gunjikar 
73c39526b7SPramod Gunjikar static struct cb_ops sol_uverbs_cb_ops = {
74c39526b7SPramod Gunjikar 	.cb_open	= sol_uverbs_open,
75c39526b7SPramod Gunjikar 	.cb_close	= sol_uverbs_close,
76c39526b7SPramod Gunjikar 	.cb_strategy	= nodev,
77c39526b7SPramod Gunjikar 	.cb_print	= nodev,
78c39526b7SPramod Gunjikar 	.cb_dump	= nodev,
79c39526b7SPramod Gunjikar 	.cb_read	= sol_uverbs_read,
80c39526b7SPramod Gunjikar 	.cb_write	= sol_uverbs_write,
81c39526b7SPramod Gunjikar 	.cb_ioctl	= nodev,
82c39526b7SPramod Gunjikar 	.cb_devmap	= nodev,
83c39526b7SPramod Gunjikar 	.cb_mmap	= sol_uverbs_mmap,
84c39526b7SPramod Gunjikar 	.cb_segmap	= nodev,
85c39526b7SPramod Gunjikar 	.cb_chpoll	= sol_uverbs_poll,
86c39526b7SPramod Gunjikar 	.cb_prop_op	= sol_uverbs_prop_op,
87c39526b7SPramod Gunjikar 	.cb_str		= NULL,
88c39526b7SPramod Gunjikar 	.cb_flag	= D_NEW | D_MP,
89c39526b7SPramod Gunjikar 	.cb_rev		= CB_REV,
90c39526b7SPramod Gunjikar 	.cb_aread	= nodev,
91c39526b7SPramod Gunjikar 	.cb_awrite	= nodev
92c39526b7SPramod Gunjikar };
93c39526b7SPramod Gunjikar 
94c39526b7SPramod Gunjikar static struct dev_ops sol_uverbs_dev_ops = {
95c39526b7SPramod Gunjikar 	.devo_rev	= DEVO_REV,
96c39526b7SPramod Gunjikar 	.devo_refcnt	= 0,
97c39526b7SPramod Gunjikar 	.devo_getinfo	= sol_uverbs_getinfo,
98c39526b7SPramod Gunjikar 	.devo_identify	= nulldev,
99c39526b7SPramod Gunjikar 	.devo_probe	= nulldev,
100c39526b7SPramod Gunjikar 	.devo_attach	= sol_uverbs_attach,
101c39526b7SPramod Gunjikar 	.devo_detach	= sol_uverbs_detach,
102c39526b7SPramod Gunjikar 	.devo_reset	= nodev,
103c39526b7SPramod Gunjikar 	.devo_cb_ops	= &sol_uverbs_cb_ops,
104c39526b7SPramod Gunjikar 	.devo_bus_ops	= NULL,
105c39526b7SPramod Gunjikar 	.devo_power	= nodev,
106c39526b7SPramod Gunjikar 	.devo_quiesce	= ddi_quiesce_not_needed
107c39526b7SPramod Gunjikar };
108c39526b7SPramod Gunjikar 
109c39526b7SPramod Gunjikar static struct modldrv modldrv = {
110c39526b7SPramod Gunjikar 	.drv_modops	= &mod_driverops,
111c39526b7SPramod Gunjikar 	.drv_linkinfo	= "Solaris User Verbs driver",
112c39526b7SPramod Gunjikar 	.drv_dev_ops	= &sol_uverbs_dev_ops
113c39526b7SPramod Gunjikar };
114c39526b7SPramod Gunjikar 
115c39526b7SPramod Gunjikar static struct modlinkage modlinkage = {
116c39526b7SPramod Gunjikar 	.ml_rev			= MODREV_1,
117c39526b7SPramod Gunjikar 	.ml_linkage = {
118c39526b7SPramod Gunjikar 		[0]		= &modldrv,
119c39526b7SPramod Gunjikar 		[1]		= NULL,
120c39526b7SPramod Gunjikar 	}
121c39526b7SPramod Gunjikar };
122c39526b7SPramod Gunjikar 
123c39526b7SPramod Gunjikar /*
124c39526b7SPramod Gunjikar  * User Object Tables for management of user resources. The tables are driver
125c39526b7SPramod Gunjikar  * wide, but each user context maintains a list of the objects it has created
126c39526b7SPramod Gunjikar  * that is used in cleanup.
127c39526b7SPramod Gunjikar  */
128c39526b7SPramod Gunjikar sol_ofs_uobj_table_t uverbs_uctxt_uo_tbl;
129c39526b7SPramod Gunjikar sol_ofs_uobj_table_t uverbs_upd_uo_tbl;
130c39526b7SPramod Gunjikar sol_ofs_uobj_table_t uverbs_uah_uo_tbl;
131c39526b7SPramod Gunjikar sol_ofs_uobj_table_t uverbs_umr_uo_tbl;
132c39526b7SPramod Gunjikar sol_ofs_uobj_table_t uverbs_ucq_uo_tbl;
133c39526b7SPramod Gunjikar sol_ofs_uobj_table_t uverbs_usrq_uo_tbl;
134c39526b7SPramod Gunjikar sol_ofs_uobj_table_t uverbs_uqp_uo_tbl;
135c39526b7SPramod Gunjikar sol_ofs_uobj_table_t uverbs_ufile_uo_tbl;
136c39526b7SPramod Gunjikar 
137c39526b7SPramod Gunjikar static void sol_uverbs_user_objects_init(void);
138c39526b7SPramod Gunjikar static void sol_uverbs_user_objects_fini(void);
139c39526b7SPramod Gunjikar 
140c39526b7SPramod Gunjikar /*
141c39526b7SPramod Gunjikar  * Open Fabric User Verbs API, command table. See ib_user_verbs.h for
142c39526b7SPramod Gunjikar  * definitions.
143c39526b7SPramod Gunjikar  */
144c39526b7SPramod Gunjikar static int (*uverbs_cmd_table[])(uverbs_uctxt_uobj_t *uctxt, char *buf,
145c39526b7SPramod Gunjikar 	int in_len, int out_len) = {
146c39526b7SPramod Gunjikar 
147c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_GET_CONTEXT]   	= sol_uverbs_get_context,
148c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_QUERY_DEVICE]  	= sol_uverbs_query_device,
149c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_QUERY_PORT]    	= sol_uverbs_query_port,
150c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_ALLOC_PD]		= sol_uverbs_alloc_pd,
151c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_DEALLOC_PD]		= sol_uverbs_dealloc_pd,
152c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_REG_MR]		= sol_uverbs_reg_mr,
153c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_DEREG_MR]		= sol_uverbs_dereg_mr,
154c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] =
155c39526b7SPramod Gunjikar 					sol_uverbs_create_comp_channel,
156c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_CREATE_CQ]		= sol_uverbs_create_cq,
157c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_RESIZE_CQ]		= sol_uverbs_resize_cq,
158c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_POLL_CQ]		= sol_uverbs_poll_cq,
159c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_REQ_NOTIFY_CQ]	= sol_uverbs_req_notify_cq,
160c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_DESTROY_CQ]    	= sol_uverbs_destroy_cq,
161c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_CREATE_QP]		= sol_uverbs_create_qp,
162c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_QUERY_QP]		= sol_uverbs_query_qp,
163c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_MODIFY_QP]		= sol_uverbs_modify_qp,
164c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_DESTROY_QP]    	= sol_uverbs_destroy_qp,
165c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_POST_SEND]    	= sol_uverbs_dummy_command,
166c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_POST_RECV]    	= sol_uverbs_dummy_command,
167c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_POST_SRQ_RECV]    	= sol_uverbs_dummy_command,
168c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_CREATE_AH]    	= sol_uverbs_create_ah,
169c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_DESTROY_AH]    	= sol_uverbs_destroy_ah,
170c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_ATTACH_MCAST]  	= sol_uverbs_attach_mcast,
171c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_DETACH_MCAST]  	= sol_uverbs_detach_mcast,
172c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_CREATE_SRQ]    	= sol_uverbs_create_srq,
173c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_MODIFY_SRQ]		= sol_uverbs_modify_srq,
174c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_QUERY_SRQ]		= sol_uverbs_query_srq,
175c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_DESTROY_SRQ]   	= sol_uverbs_destroy_srq,
176c39526b7SPramod Gunjikar 
177c39526b7SPramod Gunjikar 		/* TODO - XRC */
178c39526b7SPramod Gunjikar 
179c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_CREATE_XRC_SRQ]   	= sol_uverbs_dummy_command,
180c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_OPEN_XRC_DOMAIN]   	= sol_uverbs_dummy_command,
181c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN]   	= sol_uverbs_dummy_command,
182c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_CREATE_XRC_RCV_QP]  	= sol_uverbs_dummy_command,
183c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_MODIFY_XRC_RCV_QP]  	= sol_uverbs_dummy_command,
184c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_QUERY_XRC_RCV_QP]   	= sol_uverbs_dummy_command,
185c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_REG_XRC_RCV_QP]   	= sol_uverbs_dummy_command,
186c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_UNREG_XRC_RCV_QP]   	= sol_uverbs_dummy_command,
187c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_QUERY_GID]		= sol_uverbs_query_gid,
188c39526b7SPramod Gunjikar 	[IB_USER_VERBS_CMD_QUERY_PKEY]		= sol_uverbs_query_pkey,
189c39526b7SPramod Gunjikar };
190c39526b7SPramod Gunjikar 
191c39526b7SPramod Gunjikar /*
192c39526b7SPramod Gunjikar  * Function:
193c39526b7SPramod Gunjikar  *	sol_uverbs_hca_open
194c39526b7SPramod Gunjikar  * Input:
195c39526b7SPramod Gunjikar  *	mod_ctxt	- Pointer to the user verbs module context.
196c39526b7SPramod Gunjikar  * Output:
197c39526b7SPramod Gunjikar  *	None
198c39526b7SPramod Gunjikar  * Returns:
199c39526b7SPramod Gunjikar  *	Zero on success, else error code.
200c39526b7SPramod Gunjikar  * Description:
201c39526b7SPramod Gunjikar  *	Register as a client with the IBT framework and open all of the
202c39526b7SPramod Gunjikar  *	HCA's present.
203c39526b7SPramod Gunjikar  */
204c39526b7SPramod Gunjikar static int
sol_uverbs_hca_open(uverbs_module_context_t * mod_ctxt)205c39526b7SPramod Gunjikar sol_uverbs_hca_open(uverbs_module_context_t *mod_ctxt)
206c39526b7SPramod Gunjikar {
207c39526b7SPramod Gunjikar 	int			status;
208c39526b7SPramod Gunjikar 	int			hca_ndx;
209c39526b7SPramod Gunjikar #ifdef DEBUG
210c39526b7SPramod Gunjikar 	llist_head_t		*entry;
211c39526b7SPramod Gunjikar 	sol_uverbs_hca_t	*temp;
212c39526b7SPramod Gunjikar #endif
213c39526b7SPramod Gunjikar 
214c39526b7SPramod Gunjikar 	mod_ctxt->hca_count	= 0;
215c39526b7SPramod Gunjikar 	mod_ctxt->hca_guid_list	= NULL;
216c39526b7SPramod Gunjikar 	mod_ctxt->hcas		= NULL;
217c39526b7SPramod Gunjikar 	mod_ctxt->clnt_hdl	= NULL;
218c39526b7SPramod Gunjikar 
219c39526b7SPramod Gunjikar 	mod_ctxt->clnt_modinfo.mi_ibt_version   = IBTI_V_CURR;
220c39526b7SPramod Gunjikar 	mod_ctxt->clnt_modinfo.mi_clnt_class    = IBT_USER;
221c39526b7SPramod Gunjikar 	mod_ctxt->clnt_modinfo.mi_async_handler = uverbs_async_event_handler;
222c39526b7SPramod Gunjikar 	mod_ctxt->clnt_modinfo.mi_reserved	= NULL;
223c39526b7SPramod Gunjikar 	mod_ctxt->clnt_modinfo.mi_clnt_name	= "sol_uverbs";
224c39526b7SPramod Gunjikar 
225c39526b7SPramod Gunjikar 	status = ibt_attach(&mod_ctxt->clnt_modinfo, mod_ctxt->dip,
226c39526b7SPramod Gunjikar 	    mod_ctxt, &mod_ctxt->clnt_hdl);
227c39526b7SPramod Gunjikar 
228c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
229c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
230c39526b7SPramod Gunjikar 		    "hca_open:ibt_attach fail %d", status);
231c39526b7SPramod Gunjikar 		status = ENODEV;
232c39526b7SPramod Gunjikar 		goto out_err;
233c39526b7SPramod Gunjikar 	}
234c39526b7SPramod Gunjikar 	if (sol_uverbs_ib_clntp == NULL)
235c39526b7SPramod Gunjikar 		sol_uverbs_ib_clntp  = mod_ctxt->clnt_hdl;
236c39526b7SPramod Gunjikar 
237c39526b7SPramod Gunjikar 	mod_ctxt->hca_count = ibt_get_hca_list(&mod_ctxt->hca_guid_list);
238c39526b7SPramod Gunjikar 
239c39526b7SPramod Gunjikar 	if (mod_ctxt->hca_count == 0) {
240c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
241c39526b7SPramod Gunjikar 		    "hca_open: Zero HCAs on this system!");
242c39526b7SPramod Gunjikar 		status = ENODEV;
243c39526b7SPramod Gunjikar 		goto out_err;
244c39526b7SPramod Gunjikar 	}
245c39526b7SPramod Gunjikar 
246c39526b7SPramod Gunjikar 	if (mod_ctxt->hca_count > SOL_UVERBS_DRIVER_MAX_HCA_MINOR) {
247c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
248c39526b7SPramod Gunjikar 		    "hca_open: HCA count %d exceeds max %d",
249c39526b7SPramod Gunjikar 		    mod_ctxt->hca_count, SOL_UVERBS_DRIVER_MAX_HCA_MINOR);
250c39526b7SPramod Gunjikar 		status =  ENODEV;
251c39526b7SPramod Gunjikar 		goto out_err;
252c39526b7SPramod Gunjikar 	}
253c39526b7SPramod Gunjikar 
254c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
255c39526b7SPramod Gunjikar 	    "hca_open: No. of HCAs present %d", mod_ctxt->hca_count);
256c39526b7SPramod Gunjikar 
257c39526b7SPramod Gunjikar 	mod_ctxt->hcas = kmem_zalloc(mod_ctxt->hca_count *
258c39526b7SPramod Gunjikar 	    sizeof (sol_uverbs_hca_t), KM_SLEEP);
259c39526b7SPramod Gunjikar 	ASSERT(mod_ctxt->hcas != NULL);
260c39526b7SPramod Gunjikar 
261c39526b7SPramod Gunjikar 	/*
262c39526b7SPramod Gunjikar 	 * Note: we open these in the reverse order of the guid list, although
263c39526b7SPramod Gunjikar 	 * this is technically not required it is done this way so that the
264c39526b7SPramod Gunjikar 	 * mapping will be in same order as the interfaces. Also note, that we
265c39526b7SPramod Gunjikar 	 * provide a guid property, and the guid should be used to map a verbs
266c39526b7SPramod Gunjikar 	 * device to an interface (i.e. don't depend on the order).
267c39526b7SPramod Gunjikar 	 */
268c39526b7SPramod Gunjikar 	for (hca_ndx = 0; hca_ndx < mod_ctxt->hca_count; hca_ndx++) {
269c39526b7SPramod Gunjikar 		status = ibt_open_hca(mod_ctxt->clnt_hdl,
270c39526b7SPramod Gunjikar 		    mod_ctxt->hca_guid_list[mod_ctxt->hca_count - hca_ndx -1],
271c39526b7SPramod Gunjikar 		    &mod_ctxt->hcas[hca_ndx].hdl);
272c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS) {
273c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
274c39526b7SPramod Gunjikar 			    "hca_open: ibt_open_hca() returned %d",
275c39526b7SPramod Gunjikar 			    status);
276c39526b7SPramod Gunjikar 			goto out_err;
277c39526b7SPramod Gunjikar 		}
278c39526b7SPramod Gunjikar 
279c39526b7SPramod Gunjikar 		mod_ctxt->hcas[hca_ndx].clnt_hdl = mod_ctxt->clnt_hdl;
280c39526b7SPramod Gunjikar 		llist_head_init(&mod_ctxt->hcas[hca_ndx].list,
281c39526b7SPramod Gunjikar 		    &mod_ctxt->hcas[hca_ndx]);
282c39526b7SPramod Gunjikar 		mutex_init(&mod_ctxt->hcas[hca_ndx].event_handler_lock, NULL,
283c39526b7SPramod Gunjikar 		    MUTEX_DRIVER, NULL);
284c39526b7SPramod Gunjikar 		llist_head_init(&mod_ctxt->hcas[hca_ndx].event_handler_list,
285c39526b7SPramod Gunjikar 		    NULL);
286c39526b7SPramod Gunjikar 		mutex_init(&mod_ctxt->hcas[hca_ndx].client_data_lock, NULL,
287c39526b7SPramod Gunjikar 		    MUTEX_DRIVER, NULL);
288c39526b7SPramod Gunjikar 		llist_head_init(&mod_ctxt->hcas[hca_ndx].client_data_list,
289c39526b7SPramod Gunjikar 		    NULL);
290c39526b7SPramod Gunjikar 
291c39526b7SPramod Gunjikar 		mutex_enter(&sol_uverbs_hca_lock);
292c39526b7SPramod Gunjikar 		llist_add_tail(&mod_ctxt->hcas[hca_ndx].list,
293c39526b7SPramod Gunjikar 		    &sol_uverbs_hca_list);
294c39526b7SPramod Gunjikar 		mutex_exit(&sol_uverbs_hca_lock);
295c39526b7SPramod Gunjikar 
296c39526b7SPramod Gunjikar 		mod_ctxt->hcas[hca_ndx].guid =
297c39526b7SPramod Gunjikar 		    mod_ctxt->hca_guid_list[mod_ctxt->hca_count - hca_ndx -1];
298c39526b7SPramod Gunjikar 
299c39526b7SPramod Gunjikar 		/*
300c39526b7SPramod Gunjikar 		 * Get a cached copy of the HCA's attributes for easy access.
301c39526b7SPramod Gunjikar 		 */
302c39526b7SPramod Gunjikar 		status = ibt_query_hca(mod_ctxt->hcas[hca_ndx].hdl,
303c39526b7SPramod Gunjikar 		    &mod_ctxt->hcas[hca_ndx].attr);
304c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS) {
305c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
306c39526b7SPramod Gunjikar 			    "hca_open: ibt_query_hca() failed "
307c39526b7SPramod Gunjikar 			    "(status=%d)", status);
308c39526b7SPramod Gunjikar 			goto out_err;
309c39526b7SPramod Gunjikar 		}
310c39526b7SPramod Gunjikar 
311c39526b7SPramod Gunjikar 		/* Note : GUID is in host order here */
312c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
313c39526b7SPramod Gunjikar 		    "hca_open: HCA index %d, HCA GUID: 0x%016llX",
314c39526b7SPramod Gunjikar 		    hca_ndx, (u_longlong_t)mod_ctxt->hcas[hca_ndx].guid);
315c39526b7SPramod Gunjikar 	}
316c39526b7SPramod Gunjikar 
317c39526b7SPramod Gunjikar #ifdef DEBUG
318c39526b7SPramod Gunjikar 	mutex_enter(&sol_uverbs_hca_lock);
319c39526b7SPramod Gunjikar 	list_for_each(entry, &sol_uverbs_hca_list) {
320c39526b7SPramod Gunjikar 		temp = (sol_uverbs_hca_t *)entry->ptr;
321c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
322c39526b7SPramod Gunjikar 		    "HCA list: entry: %p, handle: %p, "
323c39526b7SPramod Gunjikar 		    "GUID: 0x%016llX", (void *)entry, (void *)temp->hdl,
324c39526b7SPramod Gunjikar 		    (u_longlong_t)temp->guid);
325c39526b7SPramod Gunjikar 	}
326c39526b7SPramod Gunjikar 	mutex_exit(&sol_uverbs_hca_lock);
327c39526b7SPramod Gunjikar #endif
328c39526b7SPramod Gunjikar 	return (0);
329c39526b7SPramod Gunjikar 
330c39526b7SPramod Gunjikar out_err:
331c39526b7SPramod Gunjikar 	/*
332c39526b7SPramod Gunjikar 	 * Note, cleanup of hca list and associated resources is done via
333c39526b7SPramod Gunjikar 	 * uverbs_hca_close called outside this routine in the case of bad
334c39526b7SPramod Gunjikar 	 * status.
335c39526b7SPramod Gunjikar 	 */
336c39526b7SPramod Gunjikar 	return (status);
337c39526b7SPramod Gunjikar }
338c39526b7SPramod Gunjikar 
339c39526b7SPramod Gunjikar /*
340c39526b7SPramod Gunjikar  * Function:
341c39526b7SPramod Gunjikar  *	sol_uverbs_hca_close
342c39526b7SPramod Gunjikar  * Input:
343c39526b7SPramod Gunjikar  *	mod_ctxt	- Pointer to the module context.
344c39526b7SPramod Gunjikar  * Output:
345c39526b7SPramod Gunjikar  *	None
346c39526b7SPramod Gunjikar  * Returns:
347c39526b7SPramod Gunjikar  *	None
348c39526b7SPramod Gunjikar  * Description:
349c39526b7SPramod Gunjikar  * 	Close all of the IBT HCAs opened by the driver and detach from
350c39526b7SPramod Gunjikar  *	the IBT framework.
351c39526b7SPramod Gunjikar  */
352c39526b7SPramod Gunjikar static void
sol_uverbs_hca_close(uverbs_module_context_t * mod_ctxt)353c39526b7SPramod Gunjikar sol_uverbs_hca_close(uverbs_module_context_t *mod_ctxt)
354c39526b7SPramod Gunjikar {
355c39526b7SPramod Gunjikar 	int    hca_ndx;
356c39526b7SPramod Gunjikar 
357c39526b7SPramod Gunjikar 	if (mod_ctxt->hcas != NULL) {
358c39526b7SPramod Gunjikar 		mutex_enter(&sol_uverbs_hca_lock);
359c39526b7SPramod Gunjikar 		llist_head_init(&sol_uverbs_hca_list, NULL);
360c39526b7SPramod Gunjikar 		mutex_exit(&sol_uverbs_hca_lock);
361c39526b7SPramod Gunjikar 		for (hca_ndx = 0; hca_ndx < mod_ctxt->hca_count; hca_ndx++) {
362c39526b7SPramod Gunjikar 			if (mod_ctxt->hcas[hca_ndx].hdl != NULL) {
363c39526b7SPramod Gunjikar 				mutex_destroy(&mod_ctxt->hcas[hca_ndx].
364c39526b7SPramod Gunjikar 				    event_handler_lock);
365c39526b7SPramod Gunjikar 				mutex_destroy(&mod_ctxt->hcas[hca_ndx].
366c39526b7SPramod Gunjikar 				    client_data_lock);
367c39526b7SPramod Gunjikar 				(void) ibt_close_hca(mod_ctxt->
368c39526b7SPramod Gunjikar 				    hcas[hca_ndx].hdl);
369c39526b7SPramod Gunjikar 			}
370c39526b7SPramod Gunjikar 		}
371c39526b7SPramod Gunjikar 		kmem_free(mod_ctxt->hcas,
372c39526b7SPramod Gunjikar 		    mod_ctxt->hca_count * sizeof (sol_uverbs_hca_t));
373c39526b7SPramod Gunjikar 		mod_ctxt->hcas = NULL;
374c39526b7SPramod Gunjikar 	}
375c39526b7SPramod Gunjikar 
376c39526b7SPramod Gunjikar 	if ((mod_ctxt->hca_guid_list != NULL) && (mod_ctxt->hca_count > 0)) {
377c39526b7SPramod Gunjikar 		ibt_free_hca_list(mod_ctxt->hca_guid_list, mod_ctxt->hca_count);
378c39526b7SPramod Gunjikar 		mod_ctxt->hca_count	= 0;
379c39526b7SPramod Gunjikar 		mod_ctxt->hca_guid_list = NULL;
380c39526b7SPramod Gunjikar 	}
381c39526b7SPramod Gunjikar 
382c39526b7SPramod Gunjikar 	if (mod_ctxt->clnt_hdl != NULL) {
383c39526b7SPramod Gunjikar 		(void) ibt_detach(mod_ctxt->clnt_hdl);
384c39526b7SPramod Gunjikar 		mod_ctxt->clnt_hdl = NULL;
385c39526b7SPramod Gunjikar 	}
386c39526b7SPramod Gunjikar }
387c39526b7SPramod Gunjikar 
388c39526b7SPramod Gunjikar /*
389c39526b7SPramod Gunjikar  * Function:
390c39526b7SPramod Gunjikar  *	_init
391c39526b7SPramod Gunjikar  * Input:
392c39526b7SPramod Gunjikar  *	None
393c39526b7SPramod Gunjikar  * Output:
394c39526b7SPramod Gunjikar  *	None
395c39526b7SPramod Gunjikar  * Returns:
396c39526b7SPramod Gunjikar  *	DDI_SUCCESS  on success, else error code.
397c39526b7SPramod Gunjikar  * Description:
398c39526b7SPramod Gunjikar  * 	Perform Solaris OFED user verbs kernel agent driver initialization.
399c39526b7SPramod Gunjikar  */
400c39526b7SPramod Gunjikar int
_init(void)401c39526b7SPramod Gunjikar _init(void)
402c39526b7SPramod Gunjikar {
403c39526b7SPramod Gunjikar 	int	error;
404c39526b7SPramod Gunjikar 
405c39526b7SPramod Gunjikar 	error = ddi_soft_state_init(&statep,
406c39526b7SPramod Gunjikar 	    sizeof (uverbs_module_context_t), 0);
407c39526b7SPramod Gunjikar 
408c39526b7SPramod Gunjikar 	if (error != 0) {
409c39526b7SPramod Gunjikar 		return (error);
410c39526b7SPramod Gunjikar 	}
411c39526b7SPramod Gunjikar 
412c39526b7SPramod Gunjikar 	sol_uverbs_user_objects_init();
413c39526b7SPramod Gunjikar 	if (sol_uverbs_common_hca_init()) {
414c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
415c39526b7SPramod Gunjikar 		    "uverbs_hca_init() failed");
416c39526b7SPramod Gunjikar 		ddi_soft_state_fini(&statep);
417c39526b7SPramod Gunjikar 		return (ENODEV);
418c39526b7SPramod Gunjikar 	}
419c39526b7SPramod Gunjikar 
420c39526b7SPramod Gunjikar 	error = mod_install(&modlinkage);
421c39526b7SPramod Gunjikar 	if (error != 0) {
422c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
423c39526b7SPramod Gunjikar 		    "uverbs: mod_install failed!!");
424c39526b7SPramod Gunjikar 		sol_uverbs_common_hca_fini();
425c39526b7SPramod Gunjikar 		sol_uverbs_user_objects_fini();
426c39526b7SPramod Gunjikar 		ddi_soft_state_fini(&statep);
427c39526b7SPramod Gunjikar 	}
428c39526b7SPramod Gunjikar 	return (error);
429c39526b7SPramod Gunjikar }
430c39526b7SPramod Gunjikar 
431c39526b7SPramod Gunjikar /*
432c39526b7SPramod Gunjikar  * Function:
433c39526b7SPramod Gunjikar  *	_info
434c39526b7SPramod Gunjikar  * Input:
435c39526b7SPramod Gunjikar  *	modinfop	- Pointer to an opqque modinfo structure.
436c39526b7SPramod Gunjikar  * Output:
437c39526b7SPramod Gunjikar  *	modinfop	- Updated structure.
438c39526b7SPramod Gunjikar  * Returns:
439c39526b7SPramod Gunjikar  *	The mod_info() return code.
440c39526b7SPramod Gunjikar  * Description:
441c39526b7SPramod Gunjikar  * 	Return information about the loadable module via the mod_info()
442c39526b7SPramod Gunjikar  *	kernel function call.
443c39526b7SPramod Gunjikar  */
444c39526b7SPramod Gunjikar int
_info(struct modinfo * modinfop)445c39526b7SPramod Gunjikar _info(struct modinfo *modinfop)
446c39526b7SPramod Gunjikar {
447c39526b7SPramod Gunjikar 	return (mod_info(&modlinkage, modinfop));
448c39526b7SPramod Gunjikar }
449c39526b7SPramod Gunjikar 
450c39526b7SPramod Gunjikar /*
451c39526b7SPramod Gunjikar  * Function:
452c39526b7SPramod Gunjikar  *	_fini
453c39526b7SPramod Gunjikar  * Input:
454c39526b7SPramod Gunjikar  *	None
455c39526b7SPramod Gunjikar  * Output:
456c39526b7SPramod Gunjikar  *	None
457c39526b7SPramod Gunjikar  * Returns:
458c39526b7SPramod Gunjikar  *	DDI_SUCCESS  on success, else error code returned by
459c39526b7SPramod Gunjikar  *	mod_remove kernel function.
460c39526b7SPramod Gunjikar  * Description:
461c39526b7SPramod Gunjikar  * 	Perform Solaris OFED user verbs kernel agent driver cleanup.
462c39526b7SPramod Gunjikar  */
463c39526b7SPramod Gunjikar int
_fini(void)464c39526b7SPramod Gunjikar _fini(void)
465c39526b7SPramod Gunjikar {
466c39526b7SPramod Gunjikar 	int    rc;
467c39526b7SPramod Gunjikar 
468c39526b7SPramod Gunjikar 	rc = mod_remove(&modlinkage);
469c39526b7SPramod Gunjikar 	if (!rc) {
470c39526b7SPramod Gunjikar 		sol_uverbs_common_hca_fini();
471c39526b7SPramod Gunjikar 		sol_uverbs_user_objects_fini();
472c39526b7SPramod Gunjikar 	}
473c39526b7SPramod Gunjikar 	return (rc);
474c39526b7SPramod Gunjikar }
475c39526b7SPramod Gunjikar 
476c39526b7SPramod Gunjikar int
sol_uverbs_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)477c39526b7SPramod Gunjikar sol_uverbs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
478c39526b7SPramod Gunjikar {
479c39526b7SPramod Gunjikar 	uverbs_module_context_t	*mod_ctxt;
480c39526b7SPramod Gunjikar 	int			rc, instance, hca_ndx;
481c39526b7SPramod Gunjikar 
482c39526b7SPramod Gunjikar 	switch (cmd) {
483c39526b7SPramod Gunjikar 		case DDI_ATTACH:
484c39526b7SPramod Gunjikar 			break;
485c39526b7SPramod Gunjikar 		case DDI_RESUME:
486c39526b7SPramod Gunjikar 			return (DDI_SUCCESS);
487c39526b7SPramod Gunjikar 		default:
488c39526b7SPramod Gunjikar 			return (DDI_FAILURE);
489c39526b7SPramod Gunjikar 	}
490c39526b7SPramod Gunjikar 
491c39526b7SPramod Gunjikar 	/*
492c39526b7SPramod Gunjikar 	 * Allocate a soft data structure based on this dev info
493c39526b7SPramod Gunjikar 	 */
494c39526b7SPramod Gunjikar 	instance = ddi_get_instance(dip);
495c39526b7SPramod Gunjikar 	if (instance != 0) {
496c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
497c39526b7SPramod Gunjikar 		    "attach: bad instance number %d", instance);
498c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
499c39526b7SPramod Gunjikar 	}
500c39526b7SPramod Gunjikar 
501c39526b7SPramod Gunjikar 	if (ddi_soft_state_zalloc(statep, instance) != DDI_SUCCESS) {
502c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
503c39526b7SPramod Gunjikar 		    "attach: bad state zalloc");
504c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
505c39526b7SPramod Gunjikar 	}
506c39526b7SPramod Gunjikar 
507c39526b7SPramod Gunjikar 	mod_ctxt = ddi_get_soft_state(statep, instance);
508c39526b7SPramod Gunjikar 	if (mod_ctxt == NULL) {
509c39526b7SPramod Gunjikar 		ddi_soft_state_free(statep, instance);
510c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
511c39526b7SPramod Gunjikar 		    "attach: cannot get soft state");
512c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
513c39526b7SPramod Gunjikar 	}
514c39526b7SPramod Gunjikar 
515c39526b7SPramod Gunjikar 	/*
516c39526b7SPramod Gunjikar 	 * Save off our private context in the dev_info
517c39526b7SPramod Gunjikar 	 */
518c39526b7SPramod Gunjikar 	mod_ctxt->dip = dip;
519c39526b7SPramod Gunjikar 	ddi_set_driver_private(dip, mod_ctxt);
520c39526b7SPramod Gunjikar 
521c39526b7SPramod Gunjikar 	/*
522c39526b7SPramod Gunjikar 	 * Opening of the hca will perform the ibt_attach and build a list of
523c39526b7SPramod Gunjikar 	 * devices.
524c39526b7SPramod Gunjikar 	 */
525c39526b7SPramod Gunjikar 	rc = sol_uverbs_hca_open(mod_ctxt);
526c39526b7SPramod Gunjikar 	if (rc) {
527c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
528c39526b7SPramod Gunjikar 		    "attach: sol_uverbs_hca_open() (rc=%d)", rc);
529c39526b7SPramod Gunjikar 		goto error;
530c39526b7SPramod Gunjikar 	}
531c39526b7SPramod Gunjikar 
532c39526b7SPramod Gunjikar 	/*
533c39526b7SPramod Gunjikar 	 * Export our ABI revision as a property.
534c39526b7SPramod Gunjikar 	 */
535c39526b7SPramod Gunjikar 	rc = ddi_prop_update_int(makedevice(ddi_driver_major(dip), 0),
536c39526b7SPramod Gunjikar 	    dip, "abi-version", IB_USER_VERBS_ABI_VERSION);
537c39526b7SPramod Gunjikar 	if (rc != DDI_SUCCESS) {
538c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
539c39526b7SPramod Gunjikar 		    "attach: could not add abi-version property");
540c39526b7SPramod Gunjikar 	}
541c39526b7SPramod Gunjikar 
542c39526b7SPramod Gunjikar 	/*
543c39526b7SPramod Gunjikar 	 * Create the filesystem device node for each HCA.
544c39526b7SPramod Gunjikar 	 */
545c39526b7SPramod Gunjikar 	for (hca_ndx = 0; hca_ndx < mod_ctxt->hca_count; hca_ndx++) {
546c39526b7SPramod Gunjikar 		char name[20];
547c39526b7SPramod Gunjikar 
548c39526b7SPramod Gunjikar 		(void) snprintf(name, 20, "uverbs%d", hca_ndx);
549c39526b7SPramod Gunjikar 		rc = ddi_create_minor_node(dip, name, S_IFCHR, hca_ndx,
550c39526b7SPramod Gunjikar 		    DDI_PSEUDO, 0);
551c39526b7SPramod Gunjikar 		if (rc != DDI_SUCCESS) {
552c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
553c39526b7SPramod Gunjikar 			    "attach: could not add character node");
554c39526b7SPramod Gunjikar 			goto error;
555c39526b7SPramod Gunjikar 		}
556c39526b7SPramod Gunjikar 
557c39526b7SPramod Gunjikar 		rc = ddi_prop_update_int64(makedevice(ddi_driver_major(dip),
558c39526b7SPramod Gunjikar 		    hca_ndx), dip, "guid", mod_ctxt->hcas[hca_ndx].guid);
559c39526b7SPramod Gunjikar 		if (rc != DDI_SUCCESS) {
560c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
561c39526b7SPramod Gunjikar 			    "attach: could not add GUID property");
562c39526b7SPramod Gunjikar 		}
563c39526b7SPramod Gunjikar 
564c39526b7SPramod Gunjikar 		rc = ddi_prop_update_int(makedevice(ddi_driver_major(dip),
565c39526b7SPramod Gunjikar 		    hca_ndx), dip, "vendor-id",
566c39526b7SPramod Gunjikar 		    mod_ctxt->hcas[hca_ndx].attr.hca_vendor_id);
567c39526b7SPramod Gunjikar 		if (rc != DDI_SUCCESS) {
568c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
569c39526b7SPramod Gunjikar 			    "attach: could not add vendor-id property");
570c39526b7SPramod Gunjikar 		}
571c39526b7SPramod Gunjikar 
572c39526b7SPramod Gunjikar 		rc = ddi_prop_update_int(makedevice(ddi_driver_major(dip),
573c39526b7SPramod Gunjikar 		    hca_ndx), dip, "device-id", mod_ctxt->
574c39526b7SPramod Gunjikar 		    hcas[hca_ndx].attr.hca_device_id);
575c39526b7SPramod Gunjikar 		if (rc != DDI_SUCCESS) {
576c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
577c39526b7SPramod Gunjikar 			    "attach: could not add device-id property");
578c39526b7SPramod Gunjikar 		}
579c39526b7SPramod Gunjikar 	}
580c39526b7SPramod Gunjikar 
581c39526b7SPramod Gunjikar 	rc = ddi_create_minor_node(dip, "ucma",  S_IFCHR,
582c39526b7SPramod Gunjikar 	    SOL_UVERBS_DRIVER_MAX_HCA_MINOR, DDI_PSEUDO, 0);
583c39526b7SPramod Gunjikar 
584c39526b7SPramod Gunjikar 	if (rc != DDI_SUCCESS) {
585c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
586c39526b7SPramod Gunjikar 		    "attach: could not add minor for ucma");
587c39526b7SPramod Gunjikar 		goto error;
588c39526b7SPramod Gunjikar 	}
589c39526b7SPramod Gunjikar 
590c39526b7SPramod Gunjikar 	rc = ddi_create_minor_node(dip, "event",  S_IFCHR,
591c39526b7SPramod Gunjikar 	    SOL_UVERBS_DRIVER_EVENT_MINOR, DDI_PSEUDO, 0);
592c39526b7SPramod Gunjikar 
593c39526b7SPramod Gunjikar 	if (rc != DDI_SUCCESS) {
594c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
595c39526b7SPramod Gunjikar 		    "attach: could not add minor for events");
596c39526b7SPramod Gunjikar 		goto error;
597c39526b7SPramod Gunjikar 	}
598c39526b7SPramod Gunjikar 
599c39526b7SPramod Gunjikar 	ddi_report_dev(dip);
600c39526b7SPramod Gunjikar 
601c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
602c39526b7SPramod Gunjikar 
603c39526b7SPramod Gunjikar error:
604c39526b7SPramod Gunjikar 	/*
605c39526b7SPramod Gunjikar 	 * Cleanup any resources and dettach.
606c39526b7SPramod Gunjikar 	 */
607c39526b7SPramod Gunjikar 	sol_uverbs_hca_close(mod_ctxt);
608c39526b7SPramod Gunjikar 	ddi_soft_state_free(statep, instance);
609c39526b7SPramod Gunjikar 
610c39526b7SPramod Gunjikar 	return (rc);
611c39526b7SPramod Gunjikar }
612c39526b7SPramod Gunjikar 
613c39526b7SPramod Gunjikar /*
614c39526b7SPramod Gunjikar  * Function:
615c39526b7SPramod Gunjikar  *	sol_uverbs_detach
616c39526b7SPramod Gunjikar  * Input:
617c39526b7SPramod Gunjikar  *	dip	- A pointer to the devices dev_info_t structure.
618c39526b7SPramod Gunjikar  *	cmd	- Type of detach (DDI_DETACH or DDI_SUSPEND).
619c39526b7SPramod Gunjikar  * Output:
620c39526b7SPramod Gunjikar  *	None
621c39526b7SPramod Gunjikar  * Returns:
622c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
623c39526b7SPramod Gunjikar  * Description:
624c39526b7SPramod Gunjikar  * 	Detaches thea driver module and will cause the driver to close
625c39526b7SPramod Gunjikar  *	the underlying IBT HCA and detach from the IBT driver.  Note
626c39526b7SPramod Gunjikar  *	that this call will fail if user verb consumers or ucma have a
627c39526b7SPramod Gunjikar  *	sol_uverbs device open.
628c39526b7SPramod Gunjikar  */
629c39526b7SPramod Gunjikar static int
sol_uverbs_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)630c39526b7SPramod Gunjikar sol_uverbs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
631c39526b7SPramod Gunjikar {
632c39526b7SPramod Gunjikar 	int			instance;
633c39526b7SPramod Gunjikar 	uverbs_module_context_t	*mod_ctxt;
634c39526b7SPramod Gunjikar 
635c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "detach()");
636c39526b7SPramod Gunjikar 
637c39526b7SPramod Gunjikar 	if (cmd != DDI_DETACH) {
638c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
639c39526b7SPramod Gunjikar 	}
640c39526b7SPramod Gunjikar 
641c39526b7SPramod Gunjikar 	instance = ddi_get_instance(dip);
642c39526b7SPramod Gunjikar 	if (instance != 0) {
643c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
644c39526b7SPramod Gunjikar 		    "detach: bad instance number 0x%x", instance);
645c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
646c39526b7SPramod Gunjikar 	}
647c39526b7SPramod Gunjikar 
648c39526b7SPramod Gunjikar 	rw_enter(&uverbs_uctxt_uo_tbl.uobj_tbl_lock, RW_WRITER);
649c39526b7SPramod Gunjikar 	if (uverbs_uctxt_uo_tbl.uobj_tbl_uo_cnt > 0) {
650c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
651c39526b7SPramod Gunjikar 		    "detach(): device in use");
652c39526b7SPramod Gunjikar 		rw_exit(&uverbs_uctxt_uo_tbl.uobj_tbl_lock);
653c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
654c39526b7SPramod Gunjikar 	}
655c39526b7SPramod Gunjikar 	rw_exit(&uverbs_uctxt_uo_tbl.uobj_tbl_lock);
656c39526b7SPramod Gunjikar 
657c39526b7SPramod Gunjikar 	mod_ctxt = ddi_get_soft_state(statep, instance);
658c39526b7SPramod Gunjikar 
659c39526b7SPramod Gunjikar 	/*
660c39526b7SPramod Gunjikar 	 * Sanity check, do not detach if other kernel agents
661c39526b7SPramod Gunjikar 	 * are still using sol_uverbs IBT handles.
662c39526b7SPramod Gunjikar 	 */
663c39526b7SPramod Gunjikar 	mutex_enter(&sol_uverbs_hca_lock);
664c39526b7SPramod Gunjikar 	if (!llist_empty(&sol_uverbs_client_list)) {
665c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
666c39526b7SPramod Gunjikar 		    "detach: agents still registered");
667c39526b7SPramod Gunjikar 		mutex_exit(&sol_uverbs_hca_lock);
668c39526b7SPramod Gunjikar 		return (DDI_FAILURE);
669c39526b7SPramod Gunjikar 	}
670c39526b7SPramod Gunjikar 	mutex_exit(&sol_uverbs_hca_lock);
671c39526b7SPramod Gunjikar 
672c39526b7SPramod Gunjikar 	/*
673c39526b7SPramod Gunjikar 	 * Hca close will perform the detach from IBTF.
674c39526b7SPramod Gunjikar 	 */
675c39526b7SPramod Gunjikar 	sol_uverbs_hca_close(mod_ctxt);
676c39526b7SPramod Gunjikar 
677c39526b7SPramod Gunjikar 	ddi_soft_state_free(statep, instance);
678c39526b7SPramod Gunjikar 	ddi_remove_minor_node(dip, NULL);
679c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
680c39526b7SPramod Gunjikar }
681c39526b7SPramod Gunjikar 
682c39526b7SPramod Gunjikar /*
683c39526b7SPramod Gunjikar  * Function:
684c39526b7SPramod Gunjikar  *	sol_uverbs_getinfo
685c39526b7SPramod Gunjikar  * Input:
686c39526b7SPramod Gunjikar  *	dip     - Deprecated, do not use.
687c39526b7SPramod Gunjikar  *	cmd     - Command argument (DDI_INFO_DEVT2DEVINFO or
688c39526b7SPramod Gunjikar  *	          DDI_INFO_DEVT2INSTANCE).
689c39526b7SPramod Gunjikar  *	arg     - Command specific argument.
690c39526b7SPramod Gunjikar  *	resultp - Pointer to place results.
691c39526b7SPramod Gunjikar  * Output:
692c39526b7SPramod Gunjikar  *	resultp	- Location is updated with command results.
693c39526b7SPramod Gunjikar  * Returns:
694c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
695c39526b7SPramod Gunjikar  * Description:
696c39526b7SPramod Gunjikar  *	Depending on the request (cmd) return either the dev_info_t pointer
697c39526b7SPramod Gunjikar  *	associated with the dev_info_t specified, or the instance.  Note
698c39526b7SPramod Gunjikar  *	that we have only a single instance.
699c39526b7SPramod Gunjikar  */
700c39526b7SPramod Gunjikar /* ARGSUSED */
701c39526b7SPramod Gunjikar static int
sol_uverbs_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)702c39526b7SPramod Gunjikar sol_uverbs_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
703c39526b7SPramod Gunjikar     void **resultp)
704c39526b7SPramod Gunjikar {
705c39526b7SPramod Gunjikar 	uverbs_module_context_t	*mod_ctxt;
706c39526b7SPramod Gunjikar 
707c39526b7SPramod Gunjikar 	switch (cmd) {
708c39526b7SPramod Gunjikar 		case DDI_INFO_DEVT2DEVINFO:
709c39526b7SPramod Gunjikar 			mod_ctxt = ddi_get_soft_state(statep, 0);
710c39526b7SPramod Gunjikar 			if (!mod_ctxt) {
711c39526b7SPramod Gunjikar 				return (DDI_FAILURE);
712c39526b7SPramod Gunjikar 			}
713c39526b7SPramod Gunjikar 			*resultp = (void *)mod_ctxt->dip;
714c39526b7SPramod Gunjikar 			return (DDI_SUCCESS);
715c39526b7SPramod Gunjikar 
716c39526b7SPramod Gunjikar 		case DDI_INFO_DEVT2INSTANCE:
717c39526b7SPramod Gunjikar 			*resultp = 0;
718c39526b7SPramod Gunjikar 			return (DDI_SUCCESS);
719c39526b7SPramod Gunjikar 
720c39526b7SPramod Gunjikar 		default:
721c39526b7SPramod Gunjikar 			return (DDI_FAILURE);
722c39526b7SPramod Gunjikar 	}
723c39526b7SPramod Gunjikar }
724c39526b7SPramod Gunjikar 
725c39526b7SPramod Gunjikar /*
726c39526b7SPramod Gunjikar  * Function:
727c39526b7SPramod Gunjikar  *	sol_uverbs_prop_op
728c39526b7SPramod Gunjikar  * Input:
729c39526b7SPramod Gunjikar  *	dev	- The device number associated with this device.
730c39526b7SPramod Gunjikar  *	dip	- A pointer to the device information structure for this device.
731c39526b7SPramod Gunjikar  *	prop_op - Property operator (PROP_LEN, PROP_LEN_AND_VAL_BUF, or
732c39526b7SPramod Gunjikar  *	          PROP_LEN_AND_VAL_ALLOC).
733c39526b7SPramod Gunjikar  *	flags	- Only possible flag value is DDI_PROP_DONTPASS.
734c39526b7SPramod Gunjikar  *	name    - Pointer to the property to be interrogated.
735c39526b7SPramod Gunjikar  *	valuep	- Address of pointer if ALLOC, otherwise a pointer to the
736c39526b7SPramod Gunjikar  *	          users buffer.
737c39526b7SPramod Gunjikar  *	lengthp	- Pointer to update with property length.
738c39526b7SPramod Gunjikar  * Output:
739c39526b7SPramod Gunjikar  *	valuep	- Updated with the property value.
740c39526b7SPramod Gunjikar  *	lenghtp	- Updated with the property length.
741c39526b7SPramod Gunjikar  * Returns:
742c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
743c39526b7SPramod Gunjikar  * Description:
744c39526b7SPramod Gunjikar  *	Driver entry point to report the values of certain properties of the
745c39526b7SPramod Gunjikar  *	driver or  device.
746c39526b7SPramod Gunjikar  */
747c39526b7SPramod Gunjikar static int
sol_uverbs_prop_op(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int flags,char * name,caddr_t valuep,int * lengthp)748c39526b7SPramod Gunjikar sol_uverbs_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int flags,
749c39526b7SPramod Gunjikar     char *name, caddr_t valuep, int *lengthp)
750c39526b7SPramod Gunjikar {
751c39526b7SPramod Gunjikar 	return (ddi_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp));
752c39526b7SPramod Gunjikar 
753c39526b7SPramod Gunjikar }
754c39526b7SPramod Gunjikar 
755c39526b7SPramod Gunjikar static uverbs_uctxt_uobj_t *sol_uverbs_alloc_uctxt(dev_t *,
756c39526b7SPramod Gunjikar     uverbs_module_context_t *, minor_t);
757c39526b7SPramod Gunjikar 
758c39526b7SPramod Gunjikar /*
759c39526b7SPramod Gunjikar  * Function:
760c39526b7SPramod Gunjikar  *	sol_uverbs_open
761c39526b7SPramod Gunjikar  * Input:
762c39526b7SPramod Gunjikar  *	devp	- A pointer to the device number.
763c39526b7SPramod Gunjikar  *	flag	- Flags specified by caller (FEXCL, FNDELAY, FREAD, FWRITE).
764c39526b7SPramod Gunjikar  *	otyp	- Open type (OTYP_BLK, OTYP_CHR, OTYP_LYR).
765c39526b7SPramod Gunjikar  *	cred	- Pointer to the callers credentials.
766c39526b7SPramod Gunjikar  * Output:
767c39526b7SPramod Gunjikar  *	devp	- On success devp has been cloned to point to a unique minor
768c39526b7SPramod Gunjikar  *		  device.
769c39526b7SPramod Gunjikar  * Returns:
770c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
771c39526b7SPramod Gunjikar  * Description:
772c39526b7SPramod Gunjikar  * 	Handles a user process open of a specific user verbs minor device by
773c39526b7SPramod Gunjikar  *	allocating a user context user object and creating a unique device
774c39526b7SPramod Gunjikar  *	to identify the user.  Note: The first SOL_UVERBS_DRIVER_MAX_MINOR
775c39526b7SPramod Gunjikar  *	minor numbers are reserved for :
776c39526b7SPramod Gunjikar  *		0 to SOL_UVERBS_DRIVER_MAX_HCA_MINOR - 1 : actual HCA devices
777c39526b7SPramod Gunjikar  *		SOL_UVERBS_DRIVER_MAX_HCA_MINOR		 : UCMA node
778c39526b7SPramod Gunjikar  *		SOL_UVERBS_DRIVER_EVENT_MINOR		 :
779c39526b7SPramod Gunjikar  *			Event file for opening an event file for completion
780c39526b7SPramod Gunjikar  *			or async notifications.
781c39526b7SPramod Gunjikar  */
782c39526b7SPramod Gunjikar /* ARGSUSED */
783c39526b7SPramod Gunjikar static int
sol_uverbs_open(dev_t * devp,int flag,int otyp,cred_t * cred)784c39526b7SPramod Gunjikar sol_uverbs_open(dev_t *devp, int flag, int otyp, cred_t *cred)
785c39526b7SPramod Gunjikar {
786c39526b7SPramod Gunjikar 	uverbs_module_context_t	*mod_ctxt;
787c39526b7SPramod Gunjikar 	uverbs_uctxt_uobj_t	*uctxt;
788c39526b7SPramod Gunjikar 	int			minor;
789c39526b7SPramod Gunjikar 
790c39526b7SPramod Gunjikar 	/* Char only */
791c39526b7SPramod Gunjikar 	if (otyp != OTYP_CHR) {
792c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
793c39526b7SPramod Gunjikar 		    "open: not CHR");
794c39526b7SPramod Gunjikar 		return (EINVAL);
795c39526b7SPramod Gunjikar 	}
796c39526b7SPramod Gunjikar 
797c39526b7SPramod Gunjikar 	mod_ctxt = ddi_get_soft_state(statep, 0);
798c39526b7SPramod Gunjikar 	if (mod_ctxt == NULL) {
799c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
800c39526b7SPramod Gunjikar 		    "open: get soft state failed");
801c39526b7SPramod Gunjikar 		return (ENXIO);
802c39526b7SPramod Gunjikar 	}
803c39526b7SPramod Gunjikar 
804c39526b7SPramod Gunjikar 	minor = getminor(*devp);
805c39526b7SPramod Gunjikar 
806c39526b7SPramod Gunjikar 	/*
807c39526b7SPramod Gunjikar 	 * Special case of ucma module.
808c39526b7SPramod Gunjikar 	 */
809c39526b7SPramod Gunjikar 	if (minor == SOL_UVERBS_DRIVER_MAX_HCA_MINOR) {
810c39526b7SPramod Gunjikar 		extern cred_t	*kcred;
811c39526b7SPramod Gunjikar 
812c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
813c39526b7SPramod Gunjikar 		    "open: ucma_open");
814c39526b7SPramod Gunjikar 		if (cred != kcred) {
815c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
816c39526b7SPramod Gunjikar 			    "open: ucma_open non-kernel context");
817c39526b7SPramod Gunjikar 			return (ENOTSUP);
818c39526b7SPramod Gunjikar 		}
819c39526b7SPramod Gunjikar 
820c39526b7SPramod Gunjikar 		return (DDI_SUCCESS);
821c39526b7SPramod Gunjikar 	}
822c39526b7SPramod Gunjikar 
823c39526b7SPramod Gunjikar 	/*
824c39526b7SPramod Gunjikar 	 * If this is not an open for sol_uverbs event file,
825c39526b7SPramod Gunjikar 	 * A device minor number must be less than the user verb max
826c39526b7SPramod Gunjikar 	 * minor device number and the HCA count.
827c39526b7SPramod Gunjikar 	 */
828c39526b7SPramod Gunjikar 	if (minor != SOL_UVERBS_DRIVER_EVENT_MINOR &&
829c39526b7SPramod Gunjikar 	    (minor >= SOL_UVERBS_DRIVER_MAX_HCA_MINOR ||
830c39526b7SPramod Gunjikar 	    minor >= mod_ctxt->hca_count)) {
831c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
832c39526b7SPramod Gunjikar 		    "open: bad minor %d", minor);
833c39526b7SPramod Gunjikar 		return (ENODEV);
834c39526b7SPramod Gunjikar 	}
835c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "open() - minor %d", minor);
836c39526b7SPramod Gunjikar 
837c39526b7SPramod Gunjikar 	/*
838c39526b7SPramod Gunjikar 	 * Allocate a user context and return a unique ID that can be used
839c39526b7SPramod Gunjikar 	 * in identify the new user context object.  Create a clone device
840c39526b7SPramod Gunjikar 	 * that uses this unique ID as the minor number.  Allocation of the
841c39526b7SPramod Gunjikar 	 * user context object places one reference against it; which will
842c39526b7SPramod Gunjikar 	 * be held until the device is closed.
843c39526b7SPramod Gunjikar 	 *
844c39526b7SPramod Gunjikar 	 * sol_uverbs_alloc_uctxt() returns a sucessful allocation of uctx
845c39526b7SPramod Gunjikar 	 * with the uobj uo_lock held for WRITTER.
846c39526b7SPramod Gunjikar 	 */
847c39526b7SPramod Gunjikar 	uctxt = sol_uverbs_alloc_uctxt(devp, mod_ctxt, minor);
848c39526b7SPramod Gunjikar 	if (!uctxt)  {
849c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
850c39526b7SPramod Gunjikar 		    "open: user context alloc failed");
851c39526b7SPramod Gunjikar 		return (ENODEV);
852c39526b7SPramod Gunjikar 	}
853c39526b7SPramod Gunjikar 
854c39526b7SPramod Gunjikar 	/*
855c39526b7SPramod Gunjikar 	 * Indicate the object is alive and release the user object write lock
856c39526b7SPramod Gunjikar 	 * which was placed on the user context at allocation.
857c39526b7SPramod Gunjikar 	 */
858c39526b7SPramod Gunjikar 	uctxt->uobj.uo_live = 1;
859c39526b7SPramod Gunjikar 	rw_exit(&uctxt->uobj.uo_lock);
860c39526b7SPramod Gunjikar 
861c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
862c39526b7SPramod Gunjikar }
863c39526b7SPramod Gunjikar 
864c39526b7SPramod Gunjikar /*
865c39526b7SPramod Gunjikar  * Function:
866c39526b7SPramod Gunjikar  *	sol_uverbs_close
867c39526b7SPramod Gunjikar  * Input:
868c39526b7SPramod Gunjikar  *	dev	- Device number.
869c39526b7SPramod Gunjikar  *	flag	- File status flag.
870c39526b7SPramod Gunjikar  *	otyp	- Open type.
871c39526b7SPramod Gunjikar  *	cred	- A pointer to the callers credientials.
872c39526b7SPramod Gunjikar  * Output:
873c39526b7SPramod Gunjikar  *	None
874c39526b7SPramod Gunjikar  * Returns:
875c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
876c39526b7SPramod Gunjikar  * Description:
877c39526b7SPramod Gunjikar  * 	Handles a user process close of a specific user verbs minor device by
878c39526b7SPramod Gunjikar  *	freeing any user objects this process may still have allocated and
879c39526b7SPramod Gunjikar  * 	deleting the associated user context object.
880c39526b7SPramod Gunjikar  */
881c39526b7SPramod Gunjikar /* ARGSUSED */
882c39526b7SPramod Gunjikar static int
sol_uverbs_close(dev_t dev,int flag,int otyp,cred_t * cred)883c39526b7SPramod Gunjikar sol_uverbs_close(dev_t dev, int flag, int otyp, cred_t *cred)
884c39526b7SPramod Gunjikar {
885c39526b7SPramod Gunjikar 	minor_t			id = getminor(dev);
886c39526b7SPramod Gunjikar 	genlist_entry_t		*entry, *new_entry;
887c39526b7SPramod Gunjikar 	uverbs_uctxt_uobj_t	*uctxt;
888c39526b7SPramod Gunjikar 	int			rc;
889c39526b7SPramod Gunjikar 	genlist_t		tmp_genlist;
890c39526b7SPramod Gunjikar 
891c39526b7SPramod Gunjikar 	/*
892c39526b7SPramod Gunjikar 	 * HCA specific device nodes created during attach are been
893c39526b7SPramod Gunjikar 	 * closed. Return SUCCESS.
894c39526b7SPramod Gunjikar 	 */
895c39526b7SPramod Gunjikar 	if (id < SOL_UVERBS_DRIVER_MAX_MINOR) {
896c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
897c39526b7SPramod Gunjikar 		    "uverbs_close: dev_t %x, minor %x < %x",
898c39526b7SPramod Gunjikar 		    dev, id, SOL_UVERBS_DRIVER_MAX_MINOR);
899c39526b7SPramod Gunjikar 		return (0);
900c39526b7SPramod Gunjikar 	}
901c39526b7SPramod Gunjikar 
902c39526b7SPramod Gunjikar 	/*
903c39526b7SPramod Gunjikar 	 * Must be a user or kernel open, i.e. not a minor node that
904c39526b7SPramod Gunjikar 	 * that represents a user verbs device.  If it is the UCMA
905c39526b7SPramod Gunjikar 	 * nothing needs to be done.
906c39526b7SPramod Gunjikar 	 */
907c39526b7SPramod Gunjikar 	if (id == SOL_UVERBS_DRIVER_MAX_HCA_MINOR) {
908c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
909c39526b7SPramod Gunjikar 		    "uverbs_close: ucma close");
910c39526b7SPramod Gunjikar 		return (DDI_SUCCESS);
911c39526b7SPramod Gunjikar 	}
912c39526b7SPramod Gunjikar 
913c39526b7SPramod Gunjikar 	uctxt = uverbs_uobj_get_uctxt_write(id - SOL_UVERBS_DRIVER_MAX_MINOR);
914c39526b7SPramod Gunjikar 	if (uctxt == NULL) {
915c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
916c39526b7SPramod Gunjikar 		    "uverbs_close: Unknown user context");
917c39526b7SPramod Gunjikar 		return (ENXIO);
918c39526b7SPramod Gunjikar 	}
919c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "uverbs_close- "
920c39526b7SPramod Gunjikar 	    "uctxt %p", uctxt);
921c39526b7SPramod Gunjikar 
922c39526b7SPramod Gunjikar 	/*
923c39526b7SPramod Gunjikar 	 * Remove from the user context resource table, cleanup all
924c39526b7SPramod Gunjikar 	 * user resources that may still be hanging around.
925c39526b7SPramod Gunjikar 	 */
926c39526b7SPramod Gunjikar 	if (!sol_ofs_uobj_remove(&uverbs_uctxt_uo_tbl, &uctxt->uobj)) {
927c39526b7SPramod Gunjikar 		/*
928c39526b7SPramod Gunjikar 		 * It was already removed, drop the lock held from
929c39526b7SPramod Gunjikar 		 * get above and exit.
930c39526b7SPramod Gunjikar 		 */
931c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uctxt->uobj);
932c39526b7SPramod Gunjikar 		return (ENXIO);
933c39526b7SPramod Gunjikar 	}
934c39526b7SPramod Gunjikar 
935c39526b7SPramod Gunjikar 	if (uctxt->uctxt_type == SOL_UVERBS_UCTXT_ASYNC ||
936c39526b7SPramod Gunjikar 	    uctxt->uctxt_type == SOL_UVERBS_UCTXT_COMPL) {
937c39526b7SPramod Gunjikar 		uverbs_uctxt_uobj_t	*verbs_uctxt;
938c39526b7SPramod Gunjikar 
939c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L4(sol_uverbs_dbg_str,
940c39526b7SPramod Gunjikar 		    "uverbs_close: Async or Compl user context");
941c39526b7SPramod Gunjikar 
942c39526b7SPramod Gunjikar 		/*
943c39526b7SPramod Gunjikar 		 * Verbs uctxt has already been freed, just return.
944c39526b7SPramod Gunjikar 		 */
945c39526b7SPramod Gunjikar 		if (!uctxt->uctxt_verbs_id) {
946c39526b7SPramod Gunjikar 			sol_ofs_uobj_put(&uctxt->uobj);
947c39526b7SPramod Gunjikar 			sol_ofs_uobj_deref(&uctxt->uobj, sol_ofs_uobj_free);
948c39526b7SPramod Gunjikar 			return (0);
949c39526b7SPramod Gunjikar 		}
950c39526b7SPramod Gunjikar 
951c39526b7SPramod Gunjikar 		/*
952c39526b7SPramod Gunjikar 		 * Verbs uctxt has not been freed. Close the ufile. This
953c39526b7SPramod Gunjikar 		 * also frees the ufile if reference count is 0.
954c39526b7SPramod Gunjikar 		 */
955c39526b7SPramod Gunjikar 		verbs_uctxt = uverbs_uobj_get_uctxt_write(
956c39526b7SPramod Gunjikar 		    uctxt->uctxt_verbs_id - SOL_UVERBS_DRIVER_MAX_MINOR);
957c39526b7SPramod Gunjikar 
958c39526b7SPramod Gunjikar 		if (verbs_uctxt &&
959c39526b7SPramod Gunjikar 		    uctxt->uctxt_type == SOL_UVERBS_UCTXT_ASYNC) {
960c39526b7SPramod Gunjikar 			sol_uverbs_event_file_close(verbs_uctxt->async_evfile);
961c39526b7SPramod Gunjikar 			verbs_uctxt->async_evfile = NULL;
962c39526b7SPramod Gunjikar 		} else if (uctxt->comp_evfile) {
963c39526b7SPramod Gunjikar 			uctxt->comp_evfile = NULL;
964c39526b7SPramod Gunjikar 		}
965c39526b7SPramod Gunjikar 		if (verbs_uctxt)
966c39526b7SPramod Gunjikar 			sol_ofs_uobj_put(&verbs_uctxt->uobj);
967c39526b7SPramod Gunjikar 
968c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uctxt->uobj);
969c39526b7SPramod Gunjikar 		sol_ofs_uobj_deref(&uctxt->uobj, sol_ofs_uobj_free);
970c39526b7SPramod Gunjikar 		return (0);
971c39526b7SPramod Gunjikar 	} else if (uctxt->uctxt_type == SOL_UVERBS_UCTXT_EVENT) {
972c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uctxt->uobj);
973c39526b7SPramod Gunjikar 		sol_ofs_uobj_deref(&uctxt->uobj, sol_ofs_uobj_free);
974c39526b7SPramod Gunjikar 		return (0);
975c39526b7SPramod Gunjikar 	}
976c39526b7SPramod Gunjikar 
977c39526b7SPramod Gunjikar 	ASSERT(uctxt->hca != NULL);
978c39526b7SPramod Gunjikar 
979c39526b7SPramod Gunjikar 	/*
980c39526b7SPramod Gunjikar 	 * Release resources that may still be held by this user context.
981c39526b7SPramod Gunjikar 	 * Remove the resources from the associated resource managment
982c39526b7SPramod Gunjikar 	 * table and free it.
983c39526b7SPramod Gunjikar 	 */
984c39526b7SPramod Gunjikar 	mutex_enter(&uctxt->lock);
985c39526b7SPramod Gunjikar 
986c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&uctxt->ah_list);
987c39526b7SPramod Gunjikar 	while (entry) {
988c39526b7SPramod Gunjikar 		uverbs_uah_uobj_t *uah = (uverbs_uah_uobj_t *)entry->data;
989c39526b7SPramod Gunjikar 
990c39526b7SPramod Gunjikar 		rw_enter(&(uah->uobj.uo_lock), RW_WRITER);
991c39526b7SPramod Gunjikar 		(void) sol_ofs_uobj_remove(&uverbs_uah_uo_tbl, &uah->uobj);
992c39526b7SPramod Gunjikar 		rw_exit(&(uah->uobj.uo_lock));
993c39526b7SPramod Gunjikar 		(void) ibt_free_ah(uctxt->hca->hdl, uah->ah);
994c39526b7SPramod Gunjikar 		sol_ofs_uobj_free(&uah->uobj);
995c39526b7SPramod Gunjikar 
996c39526b7SPramod Gunjikar 		kmem_free((void *)entry, sizeof (genlist_entry_t));
997c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&uctxt->ah_list);
998c39526b7SPramod Gunjikar 	}
999c39526b7SPramod Gunjikar 
1000c39526b7SPramod Gunjikar 	init_genlist(&tmp_genlist);
1001c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&uctxt->qp_list);
1002c39526b7SPramod Gunjikar 	while (entry) {
1003c39526b7SPramod Gunjikar 		uverbs_uqp_uobj_t *uqp = (uverbs_uqp_uobj_t *)entry->data;
1004c39526b7SPramod Gunjikar 
1005c39526b7SPramod Gunjikar 		/* Free unreaped asynchronous events.  */
1006c39526b7SPramod Gunjikar 		uverbs_release_uqp_uevents(uctxt->async_evfile, uqp);
1007c39526b7SPramod Gunjikar 
1008c39526b7SPramod Gunjikar 		/*
1009c39526b7SPramod Gunjikar 		 * If ucma has disabled QP free for this QP, set the
1010c39526b7SPramod Gunjikar 		 * uqp_free_state to FREE_PENDING. Free QP if not.
1011c39526b7SPramod Gunjikar 		 */
1012c39526b7SPramod Gunjikar 		rw_enter(&(uqp->uobj.uo_lock), RW_WRITER);
1013c39526b7SPramod Gunjikar 		if (uqp->uqp_free_state != SOL_UVERBS2UCMA_ENABLE_QP_FREE) {
1014c39526b7SPramod Gunjikar 			new_entry = add_genlist(&tmp_genlist, entry->data,
1015c39526b7SPramod Gunjikar 			    entry->data_context);
1016c39526b7SPramod Gunjikar 			uqp->list_entry = new_entry;
1017c39526b7SPramod Gunjikar 			uqp->uqp_free_state = SOL_UVERBS2UCMA_FREE_PENDING;
1018c39526b7SPramod Gunjikar 			rw_exit(&(uqp->uobj.uo_lock));
1019c39526b7SPramod Gunjikar 		} else {
1020c39526b7SPramod Gunjikar 			uqp->list_entry = NULL;
1021c39526b7SPramod Gunjikar 			mutex_exit(&uctxt->lock);
1022c39526b7SPramod Gunjikar 			sol_ofs_uobj_ref(&uqp->uobj);
1023c39526b7SPramod Gunjikar 			rc = uverbs_uqp_free(uqp, uctxt);
1024c39526b7SPramod Gunjikar 			mutex_enter(&uctxt->lock);
1025c39526b7SPramod Gunjikar 			if (rc)
1026c39526b7SPramod Gunjikar 				SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1027c39526b7SPramod Gunjikar 				    "uqp_free(%p) failed", uqp);
1028c39526b7SPramod Gunjikar 		}
1029c39526b7SPramod Gunjikar 		kmem_free(entry, sizeof (genlist_entry_t));
1030c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&uctxt->qp_list);
1031c39526b7SPramod Gunjikar 	}
1032c39526b7SPramod Gunjikar 	(uctxt->qp_list).count = tmp_genlist.count;
1033c39526b7SPramod Gunjikar 	(uctxt->qp_list).head = tmp_genlist.head;
1034c39526b7SPramod Gunjikar 	(uctxt->qp_list).tail = tmp_genlist.tail;
1035c39526b7SPramod Gunjikar 
1036c39526b7SPramod Gunjikar 	init_genlist(&tmp_genlist);
1037c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&uctxt->cq_list);
1038c39526b7SPramod Gunjikar 	while (entry) {
1039c39526b7SPramod Gunjikar 		uverbs_ucq_uobj_t *ucq = (uverbs_ucq_uobj_t *)entry->data;
1040c39526b7SPramod Gunjikar 
1041c39526b7SPramod Gunjikar 		rw_enter(&(ucq->uobj.uo_lock), RW_WRITER);
1042c39526b7SPramod Gunjikar 
1043c39526b7SPramod Gunjikar 		/* Free events associated with the CQ.  */
1044c39526b7SPramod Gunjikar 		uverbs_release_ucq_channel(uctxt, ucq->comp_chan, ucq);
1045c39526b7SPramod Gunjikar 
1046c39526b7SPramod Gunjikar 		if (ucq->active_qp_cnt) {
1047c39526b7SPramod Gunjikar 			new_entry = add_genlist(&tmp_genlist, entry->data,
1048c39526b7SPramod Gunjikar 			    entry->data_context);
1049c39526b7SPramod Gunjikar 			ucq->list_entry = new_entry;
1050c39526b7SPramod Gunjikar 			ucq->free_pending = 1;
1051c39526b7SPramod Gunjikar 			rw_exit(&(ucq->uobj.uo_lock));
1052c39526b7SPramod Gunjikar 		} else {
1053c39526b7SPramod Gunjikar 			ucq->list_entry = NULL;
1054c39526b7SPramod Gunjikar 			sol_ofs_uobj_ref(&ucq->uobj);
1055c39526b7SPramod Gunjikar 			mutex_exit(&uctxt->lock);
1056c39526b7SPramod Gunjikar 			rc = uverbs_ucq_free(ucq, uctxt);
1057c39526b7SPramod Gunjikar 			mutex_enter(&uctxt->lock);
1058c39526b7SPramod Gunjikar 			if (rc)
1059c39526b7SPramod Gunjikar 				SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1060c39526b7SPramod Gunjikar 				    "ucq_free(%p) failed", ucq);
1061c39526b7SPramod Gunjikar 		}
1062c39526b7SPramod Gunjikar 
1063c39526b7SPramod Gunjikar 		kmem_free((void *)entry, sizeof (genlist_entry_t));
1064c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&uctxt->cq_list);
1065c39526b7SPramod Gunjikar 	}
1066c39526b7SPramod Gunjikar 	(uctxt->cq_list).count = tmp_genlist.count;
1067c39526b7SPramod Gunjikar 	(uctxt->cq_list).head = tmp_genlist.head;
1068c39526b7SPramod Gunjikar 	(uctxt->cq_list).tail = tmp_genlist.tail;
1069c39526b7SPramod Gunjikar 
1070c39526b7SPramod Gunjikar 	init_genlist(&tmp_genlist);
1071c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&uctxt->srq_list);
1072c39526b7SPramod Gunjikar 	while (entry) {
1073c39526b7SPramod Gunjikar 		uverbs_usrq_uobj_t *usrq = (uverbs_usrq_uobj_t *)entry->data;
1074c39526b7SPramod Gunjikar 
1075c39526b7SPramod Gunjikar 		rw_enter(&(usrq->uobj.uo_lock), RW_WRITER);
1076c39526b7SPramod Gunjikar 
1077c39526b7SPramod Gunjikar 		/* Free unreaped asynchronous events.  */
1078c39526b7SPramod Gunjikar 		uverbs_release_usrq_uevents(uctxt->async_evfile, usrq);
1079c39526b7SPramod Gunjikar 
1080c39526b7SPramod Gunjikar 		if (usrq->active_qp_cnt) {
1081c39526b7SPramod Gunjikar 			new_entry = add_genlist(&tmp_genlist, entry->data,
1082c39526b7SPramod Gunjikar 			    entry->data_context);
1083c39526b7SPramod Gunjikar 			usrq->list_entry = new_entry;
1084c39526b7SPramod Gunjikar 			usrq->free_pending = 1;
1085c39526b7SPramod Gunjikar 			rw_exit(&(usrq->uobj.uo_lock));
1086c39526b7SPramod Gunjikar 		} else {
1087c39526b7SPramod Gunjikar 			usrq->list_entry = NULL;
1088c39526b7SPramod Gunjikar 			sol_ofs_uobj_ref(&usrq->uobj);
1089c39526b7SPramod Gunjikar 			mutex_exit(&uctxt->lock);
1090c39526b7SPramod Gunjikar 			rc = uverbs_usrq_free(usrq, uctxt);
1091c39526b7SPramod Gunjikar 			mutex_enter(&uctxt->lock);
1092c39526b7SPramod Gunjikar 			if (rc)
1093c39526b7SPramod Gunjikar 				SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1094c39526b7SPramod Gunjikar 				    "usrq_free(%p) failed", usrq);
1095c39526b7SPramod Gunjikar 		}
1096c39526b7SPramod Gunjikar 
1097c39526b7SPramod Gunjikar 		kmem_free((void *)entry, sizeof (genlist_entry_t));
1098c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&uctxt->srq_list);
1099c39526b7SPramod Gunjikar 	}
1100c39526b7SPramod Gunjikar 	(uctxt->srq_list).count = tmp_genlist.count;
1101c39526b7SPramod Gunjikar 	(uctxt->srq_list).head = tmp_genlist.head;
1102c39526b7SPramod Gunjikar 	(uctxt->srq_list).tail = tmp_genlist.tail;
1103c39526b7SPramod Gunjikar 
1104c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&uctxt->mr_list);
1105c39526b7SPramod Gunjikar 	while (entry) {
1106c39526b7SPramod Gunjikar 		uverbs_umr_uobj_t *umr = (uverbs_umr_uobj_t *)entry->data;
1107c39526b7SPramod Gunjikar 
1108c39526b7SPramod Gunjikar 		rw_enter(&(umr->uobj.uo_lock), RW_WRITER);
1109c39526b7SPramod Gunjikar 		(void) sol_ofs_uobj_remove(&uverbs_umr_uo_tbl, &umr->uobj);
1110c39526b7SPramod Gunjikar 		rw_exit(&(umr->uobj.uo_lock));
1111c39526b7SPramod Gunjikar 
1112c39526b7SPramod Gunjikar 		(void) ibt_deregister_mr(uctxt->hca->hdl, umr->mr);
1113c39526b7SPramod Gunjikar 		sol_ofs_uobj_free(&umr->uobj);
1114c39526b7SPramod Gunjikar 
1115c39526b7SPramod Gunjikar 		kmem_free((void *)entry, sizeof (genlist_entry_t));
1116c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&uctxt->mr_list);
1117c39526b7SPramod Gunjikar 	}
1118c39526b7SPramod Gunjikar 
1119c39526b7SPramod Gunjikar 	entry = remove_genlist_head(&uctxt->pd_list);
1120c39526b7SPramod Gunjikar 	while (entry) {
1121c39526b7SPramod Gunjikar 		uverbs_upd_uobj_t *upd = (uverbs_upd_uobj_t *)entry->data;
1122c39526b7SPramod Gunjikar 
1123c39526b7SPramod Gunjikar 		rw_enter(&(upd->uobj.uo_lock), RW_WRITER);
1124c39526b7SPramod Gunjikar 		if (upd->active_qp_cnt) {
1125c39526b7SPramod Gunjikar 			new_entry = add_genlist(&tmp_genlist, entry->data,
1126c39526b7SPramod Gunjikar 			    entry->data_context);
1127c39526b7SPramod Gunjikar 			upd->list_entry = new_entry;
1128c39526b7SPramod Gunjikar 			upd->free_pending = 1;
1129c39526b7SPramod Gunjikar 			rw_exit(&(upd->uobj.uo_lock));
1130c39526b7SPramod Gunjikar 		} else {
1131c39526b7SPramod Gunjikar 			upd->list_entry = NULL;
1132c39526b7SPramod Gunjikar 			sol_ofs_uobj_ref(&upd->uobj);
1133c39526b7SPramod Gunjikar 			mutex_exit(&uctxt->lock);
1134c39526b7SPramod Gunjikar 			rc = uverbs_upd_free(upd, uctxt);
1135c39526b7SPramod Gunjikar 			mutex_enter(&uctxt->lock);
1136c39526b7SPramod Gunjikar 			if (rc)
1137c39526b7SPramod Gunjikar 				SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1138c39526b7SPramod Gunjikar 				    "upd_free(%p) failed", upd);
1139c39526b7SPramod Gunjikar 		}
1140c39526b7SPramod Gunjikar 
1141c39526b7SPramod Gunjikar 		kmem_free((void *)entry, sizeof (genlist_entry_t));
1142c39526b7SPramod Gunjikar 		entry = remove_genlist_head(&uctxt->pd_list);
1143c39526b7SPramod Gunjikar 	}
1144c39526b7SPramod Gunjikar 	(uctxt->pd_list).count = tmp_genlist.count;
1145c39526b7SPramod Gunjikar 	(uctxt->pd_list).head = tmp_genlist.head;
1146c39526b7SPramod Gunjikar 	(uctxt->pd_list).tail = tmp_genlist.tail;
1147c39526b7SPramod Gunjikar 
1148c39526b7SPramod Gunjikar 	mutex_exit(&uctxt->lock);
1149c39526b7SPramod Gunjikar 
1150c39526b7SPramod Gunjikar 	/*
1151c39526b7SPramod Gunjikar 	 * Release the user file structure to the async file if it
1152c39526b7SPramod Gunjikar 	 * has not be released yet. The uctxt for async file will
1153c39526b7SPramod Gunjikar 	 * be closed when the async file is closed.
1154c39526b7SPramod Gunjikar 	 */
1155c39526b7SPramod Gunjikar 	if (uctxt->async_evfile) {
1156c39526b7SPramod Gunjikar 		uverbs_uctxt_uobj_t	*async_uctxt;
1157c39526b7SPramod Gunjikar 
1158c39526b7SPramod Gunjikar 		async_uctxt = uverbs_uobj_get_uctxt_write(
1159c39526b7SPramod Gunjikar 		    uctxt->uctxt_async_id -
1160c39526b7SPramod Gunjikar 		    SOL_UVERBS_DRIVER_MAX_MINOR);
1161c39526b7SPramod Gunjikar 		if (!async_uctxt) {
1162c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1163c39526b7SPramod Gunjikar 			    "uverbs_close: Invalid async_id %x",
1164c39526b7SPramod Gunjikar 			    uctxt->uctxt_async_id);
1165c39526b7SPramod Gunjikar 			sol_ofs_uobj_put(&uctxt->uobj);
1166c39526b7SPramod Gunjikar 			return (ENXIO);
1167c39526b7SPramod Gunjikar 		}
1168c39526b7SPramod Gunjikar 
1169c39526b7SPramod Gunjikar 		async_uctxt->uctxt_verbs_id = 0;
1170c39526b7SPramod Gunjikar 		sol_uverbs_event_file_close(uctxt->async_evfile);
1171c39526b7SPramod Gunjikar 		uctxt->async_evfile = NULL;
1172c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&async_uctxt->uobj);
1173c39526b7SPramod Gunjikar 	}
1174c39526b7SPramod Gunjikar 
1175c39526b7SPramod Gunjikar 	/*
1176c39526b7SPramod Gunjikar 	 * Release the write lock and the reference from the get above, and
1177c39526b7SPramod Gunjikar 	 * release the reference placed on the user context as process open
1178c39526b7SPramod Gunjikar 	 * to release context.
1179c39526b7SPramod Gunjikar 	 */
1180c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uctxt->uobj);
1181c39526b7SPramod Gunjikar 
1182c39526b7SPramod Gunjikar 	/*
1183c39526b7SPramod Gunjikar 	 * If some QPs have not been freed, donot free the uctxt.
1184c39526b7SPramod Gunjikar 	 * Set uctxt_free_pending flag. This will be freed when
1185c39526b7SPramod Gunjikar 	 * the QP will be freed.
1186c39526b7SPramod Gunjikar 	 */
1187c39526b7SPramod Gunjikar 	if ((uctxt->qp_list).count) {
1188c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str,
1189c39526b7SPramod Gunjikar 		    "close: uctxt %p, has pending uqp", uctxt);
1190c39526b7SPramod Gunjikar 		uctxt->uctxt_free_pending = 1;
1191c39526b7SPramod Gunjikar 		return (0);
1192c39526b7SPramod Gunjikar 	}
1193c39526b7SPramod Gunjikar 
1194c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1195c39526b7SPramod Gunjikar 	    "close: deallocated user context: %p, ref = %d",
1196c39526b7SPramod Gunjikar 	    (void *)uctxt, uctxt->uobj.uo_refcnt);
1197c39526b7SPramod Gunjikar 
1198c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&uctxt->uobj, sol_ofs_uobj_free);
1199c39526b7SPramod Gunjikar 
1200c39526b7SPramod Gunjikar 	return (0);
1201c39526b7SPramod Gunjikar }
1202c39526b7SPramod Gunjikar 
1203c39526b7SPramod Gunjikar /*
1204c39526b7SPramod Gunjikar  * Function:
1205c39526b7SPramod Gunjikar  *	sol_uverbs_read
1206c39526b7SPramod Gunjikar  * Input:
1207c39526b7SPramod Gunjikar  *	dev	- Device number.
1208c39526b7SPramod Gunjikar  *	uiop	- Pointer to the uio structgure where data is to be stored.
1209c39526b7SPramod Gunjikar  *	credp	- A pointer to the credentials for the I/O transaction.
1210c39526b7SPramod Gunjikar  * Output:
1211c39526b7SPramod Gunjikar  *	None
1212c39526b7SPramod Gunjikar  * Returns:
1213c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1214c39526b7SPramod Gunjikar  * Description:
1215c39526b7SPramod Gunjikar  * 	User process read stub.
1216c39526b7SPramod Gunjikar  */
1217c39526b7SPramod Gunjikar static int
sol_uverbs_read(dev_t dev,struct uio * uiop,cred_t * credp)1218c39526b7SPramod Gunjikar sol_uverbs_read(dev_t dev, struct uio *uiop, cred_t *credp)
1219c39526b7SPramod Gunjikar {
1220c39526b7SPramod Gunjikar 	minor_t			id = getminor(dev);
1221c39526b7SPramod Gunjikar 	uverbs_uctxt_uobj_t	*uctxt, *verbs_uctxt;
1222c39526b7SPramod Gunjikar 	int			rc;
1223c39526b7SPramod Gunjikar 
1224c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "uverbs_read(%x, %p, %p)",
1225c39526b7SPramod Gunjikar 	    dev, uiop, credp);
1226c39526b7SPramod Gunjikar 
1227c39526b7SPramod Gunjikar 	ASSERT(id >= SOL_UVERBS_DRIVER_MAX_MINOR);
1228c39526b7SPramod Gunjikar 	uctxt = uverbs_uobj_get_uctxt_read(id - SOL_UVERBS_DRIVER_MAX_MINOR);
1229c39526b7SPramod Gunjikar 	if (uctxt == NULL) {
1230c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1231c39526b7SPramod Gunjikar 		    "uverbs_read: Failed get user context");
1232c39526b7SPramod Gunjikar 		return (ENXIO);
1233c39526b7SPramod Gunjikar 	}
1234c39526b7SPramod Gunjikar 
1235c39526b7SPramod Gunjikar 	if (uctxt->uctxt_verbs_id < SOL_UVERBS_DRIVER_MAX_MINOR) {
1236c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1237c39526b7SPramod Gunjikar 		    "uverbs_read: Invalid Verbs user context id, %x",
1238c39526b7SPramod Gunjikar 		    uctxt->uctxt_verbs_id);
1239c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uctxt->uobj);
1240c39526b7SPramod Gunjikar 		return (ENXIO);
1241c39526b7SPramod Gunjikar 	}
1242c39526b7SPramod Gunjikar 	verbs_uctxt = uverbs_uobj_get_uctxt_read(uctxt->uctxt_verbs_id
1243c39526b7SPramod Gunjikar 	    - SOL_UVERBS_DRIVER_MAX_MINOR);
1244c39526b7SPramod Gunjikar 	if (verbs_uctxt == NULL) {
1245c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1246c39526b7SPramod Gunjikar 		    "uverbs_read: Failed get verbs user context");
1247c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uctxt->uobj);
1248c39526b7SPramod Gunjikar 		return (ENXIO);
1249c39526b7SPramod Gunjikar 	}
1250c39526b7SPramod Gunjikar 	if (uctxt->uctxt_type == SOL_UVERBS_UCTXT_ASYNC) {
1251c39526b7SPramod Gunjikar 		ASSERT(verbs_uctxt->async_evfile);
1252c39526b7SPramod Gunjikar 		rc = sol_uverbs_event_file_read(verbs_uctxt->async_evfile,
1253c39526b7SPramod Gunjikar 		    uiop, credp);
1254c39526b7SPramod Gunjikar 	} else if (uctxt->uctxt_type == SOL_UVERBS_UCTXT_COMPL) {
1255c39526b7SPramod Gunjikar 		rc = sol_uverbs_event_file_read(uctxt->comp_evfile,
1256c39526b7SPramod Gunjikar 		    uiop, credp);
1257c39526b7SPramod Gunjikar 	} else {
1258c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1259c39526b7SPramod Gunjikar 		    "uverbs_read: invalid user context type %x",
1260c39526b7SPramod Gunjikar 		    uctxt->uctxt_type);
1261c39526b7SPramod Gunjikar 		rc = ENXIO;
1262c39526b7SPramod Gunjikar 	}
1263c39526b7SPramod Gunjikar 
1264c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&verbs_uctxt->uobj);
1265c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uctxt->uobj);
1266c39526b7SPramod Gunjikar 	return (rc);
1267c39526b7SPramod Gunjikar }
1268c39526b7SPramod Gunjikar 
1269c39526b7SPramod Gunjikar /*
1270c39526b7SPramod Gunjikar  * Function:
1271c39526b7SPramod Gunjikar  *	sol_uverbs_mmap
1272c39526b7SPramod Gunjikar  * Input:
1273c39526b7SPramod Gunjikar  *	dev		- Device whose memory is to be mapped.
1274c39526b7SPramod Gunjikar  *	sol_uverbs_mmap	- Offset within the device memory at which mapping
1275c39526b7SPramod Gunjikar  *			  begins.
1276c39526b7SPramod Gunjikar  *	prot		- Bitmask specifying protection.
1277c39526b7SPramod Gunjikar  * Output:
1278c39526b7SPramod Gunjikar  *	None
1279c39526b7SPramod Gunjikar  * Returns:
1280c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1281c39526b7SPramod Gunjikar  * Description:
1282c39526b7SPramod Gunjikar  * 	User process mmap stub.  Mmap operations are performed directly
1283c39526b7SPramod Gunjikar  *	by the underlying IB HCA driver, bypassing the user verbs.
1284c39526b7SPramod Gunjikar  */
1285c39526b7SPramod Gunjikar /* ARGSUSED */
1286c39526b7SPramod Gunjikar static int
sol_uverbs_mmap(dev_t dev,off_t mmap_offset,int prot)1287c39526b7SPramod Gunjikar sol_uverbs_mmap(dev_t dev, off_t mmap_offset, int prot)
1288c39526b7SPramod Gunjikar {
1289c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1290c39526b7SPramod Gunjikar 	    "sol_uverbs_mmap(%d)-  not yet used", mmap_offset);
1291c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
1292c39526b7SPramod Gunjikar }
1293c39526b7SPramod Gunjikar 
1294c39526b7SPramod Gunjikar /*
1295c39526b7SPramod Gunjikar  * Function:
1296c39526b7SPramod Gunjikar  *	sol_uverbs_get_context
1297c39526b7SPramod Gunjikar  * Input:
1298c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
1299c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing command.
1300c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
1301c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
1302c39526b7SPramod Gunjikar  * Output:
1303c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
1304c39526b7SPramod Gunjikar  * Returns:
1305c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1306c39526b7SPramod Gunjikar  * Description:
1307c39526b7SPramod Gunjikar  * 	User verb entry point to return the unique user context to the process
1308c39526b7SPramod Gunjikar  *	that opened the associated user verb driver instance.  Note that upon
1309c39526b7SPramod Gunjikar  *	entry a reference will have already been placed on the user
1310c39526b7SPramod Gunjikar  *	context user space object, so an additional reference is not
1311c39526b7SPramod Gunjikar  *	required here.
1312c39526b7SPramod Gunjikar  */
1313c39526b7SPramod Gunjikar int
sol_uverbs_get_context(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1314c39526b7SPramod Gunjikar sol_uverbs_get_context(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
1315c39526b7SPramod Gunjikar     int out_len)
1316c39526b7SPramod Gunjikar {
1317c39526b7SPramod Gunjikar 	struct mthca_alloc_ucontext_resp	uresp;
1318c39526b7SPramod Gunjikar 	struct ib_uverbs_get_context		cmd;
1319c39526b7SPramod Gunjikar 	struct ib_uverbs_get_context_resp	resp;
1320c39526b7SPramod Gunjikar 	struct ib_udata				udata;
1321c39526b7SPramod Gunjikar 	int					rc;
1322c39526b7SPramod Gunjikar 	minor_t					async_id;
1323c39526b7SPramod Gunjikar 	uverbs_uctxt_uobj_t			*async_uctxt;
1324c39526b7SPramod Gunjikar 
1325c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1326c39526b7SPramod Gunjikar 	    "uverbs_get_context() - buf %p, sizeof (cmd) %d",
1327c39526b7SPramod Gunjikar 	    buf, sizeof (cmd));
1328c39526b7SPramod Gunjikar 
1329c39526b7SPramod Gunjikar 	ASSERT(uctxt->hca);
1330c39526b7SPramod Gunjikar 
1331c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1332c39526b7SPramod Gunjikar 
1333c39526b7SPramod Gunjikar 	udata.inbuf  = (void *)(buf + sizeof (cmd));
1334c39526b7SPramod Gunjikar #ifdef	_LP64
1335c39526b7SPramod Gunjikar 	udata.outbuf = (void *)(cmd.response.r_laddr + sizeof (resp));
1336c39526b7SPramod Gunjikar #else
1337c39526b7SPramod Gunjikar 	udata.outbuf = (void *)(cmd.response.r_addr + sizeof (resp));
1338c39526b7SPramod Gunjikar #endif
1339c39526b7SPramod Gunjikar 	udata.inlen  = in_len - sizeof (cmd);
1340c39526b7SPramod Gunjikar 	udata.outlen = out_len - sizeof (resp);
1341c39526b7SPramod Gunjikar 
1342c39526b7SPramod Gunjikar 	/*
1343c39526b7SPramod Gunjikar 	 * libibverbs will have passed minor of the async file in
1344c39526b7SPramod Gunjikar 	 * resp.fd. Use this to determine the uctxt created for
1345c39526b7SPramod Gunjikar 	 * asyncs.
1346c39526b7SPramod Gunjikar 	 */
1347c39526b7SPramod Gunjikar #ifdef	_LP64
1348c39526b7SPramod Gunjikar 	rc = copyin((void*)cmd.response.r_laddr, (void*)&resp, sizeof (resp));
1349c39526b7SPramod Gunjikar #else
1350c39526b7SPramod Gunjikar 	rc = copyin((void*)cmd.response.r_addr, (void*)&resp, sizeof (resp));
1351c39526b7SPramod Gunjikar #endif
1352c39526b7SPramod Gunjikar 	if (rc != 0) {
1353c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1354c39526b7SPramod Gunjikar 		    "get_context: copyin (rc=%d)", rc);
1355c39526b7SPramod Gunjikar 		rc = EFAULT;
1356c39526b7SPramod Gunjikar 		goto out;
1357c39526b7SPramod Gunjikar 	}
1358c39526b7SPramod Gunjikar 	async_id = resp.async_fd;
1359c39526b7SPramod Gunjikar 	if (async_id < SOL_UVERBS_DRIVER_MAX_MINOR) {
1360c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1361c39526b7SPramod Gunjikar 		    "get_context: Invalid async user context "
1362c39526b7SPramod Gunjikar 		    "id %x", async_id);
1363c39526b7SPramod Gunjikar 		return (ENXIO);
1364c39526b7SPramod Gunjikar 	}
1365c39526b7SPramod Gunjikar 
1366c39526b7SPramod Gunjikar 	async_uctxt = uverbs_uobj_get_uctxt_read(async_id -
1367c39526b7SPramod Gunjikar 	    SOL_UVERBS_DRIVER_MAX_MINOR);
1368c39526b7SPramod Gunjikar 	if (async_uctxt == NULL) {
1369c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1370c39526b7SPramod Gunjikar 		    "get_context: Failed get async user context");
1371c39526b7SPramod Gunjikar 		return (ENXIO);
1372c39526b7SPramod Gunjikar 	}
1373c39526b7SPramod Gunjikar 	if (async_uctxt->uctxt_type != SOL_UVERBS_UCTXT_EVENT ||
1374c39526b7SPramod Gunjikar 	    async_uctxt->uctxt_verbs_id != 0) {
1375c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1376c39526b7SPramod Gunjikar 		    "get_context: Invalid user context - "
1377c39526b7SPramod Gunjikar 		    "possibly reused");
1378c39526b7SPramod Gunjikar 		return (ENXIO);
1379c39526b7SPramod Gunjikar 	}
1380c39526b7SPramod Gunjikar 	async_uctxt->uctxt_type = SOL_UVERBS_UCTXT_ASYNC;
1381c39526b7SPramod Gunjikar 	async_uctxt->uctxt_verbs_id = uctxt->uobj.uo_id +
1382c39526b7SPramod Gunjikar 	    SOL_UVERBS_DRIVER_MAX_MINOR;
1383c39526b7SPramod Gunjikar 	uctxt->uctxt_async_id = async_id;
1384c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1385c39526b7SPramod Gunjikar 	    "get_context: uctxt %p, async_uctxt %p, async_id %x",
1386c39526b7SPramod Gunjikar 	    uctxt, async_uctxt, async_id);
1387c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&async_uctxt->uobj);
1388c39526b7SPramod Gunjikar 
1389c39526b7SPramod Gunjikar 	uctxt->async_evfile = uverbs_alloc_event_file(uctxt, 1);
1390c39526b7SPramod Gunjikar 	if (!uctxt->async_evfile) {
1391c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1392c39526b7SPramod Gunjikar 		    "get_context: async event file allocation failed");
1393c39526b7SPramod Gunjikar 		goto out;
1394c39526b7SPramod Gunjikar 	}
1395c39526b7SPramod Gunjikar 
1396c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
1397c39526b7SPramod Gunjikar 	resp.num_comp_vectors 	= 1;
1398c39526b7SPramod Gunjikar 
1399c39526b7SPramod Gunjikar #ifdef	_LP64
1400c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
1401c39526b7SPramod Gunjikar #else
1402c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
1403c39526b7SPramod Gunjikar #endif
1404c39526b7SPramod Gunjikar 	if (rc != 0) {
1405c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1406c39526b7SPramod Gunjikar 		    "get_context: copyout (rc=%d)", rc);
1407c39526b7SPramod Gunjikar 		rc = EFAULT;
1408c39526b7SPramod Gunjikar 		goto out;
1409c39526b7SPramod Gunjikar 	}
1410c39526b7SPramod Gunjikar 
1411c39526b7SPramod Gunjikar 	/*
1412c39526b7SPramod Gunjikar 	 * This unfortunately is Mellanox specific, we need to consider moving
1413c39526b7SPramod Gunjikar 	 * this directly into the command response as opaque data, instead of
1414c39526b7SPramod Gunjikar 	 * using this method.
1415c39526b7SPramod Gunjikar 	 */
1416c39526b7SPramod Gunjikar 	(void) memset(&uresp, 0, sizeof (uresp));
1417c39526b7SPramod Gunjikar 	uresp.uarc_size   = 0;
1418c39526b7SPramod Gunjikar 	uresp.qp_tab_size = uctxt->hca->attr.hca_max_chans;
1419c39526b7SPramod Gunjikar 
1420c39526b7SPramod Gunjikar 	rc = copyout((void*)&uresp, (void*)udata.outbuf, sizeof (uresp));
1421c39526b7SPramod Gunjikar 	if (rc != 0) {
1422c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1423c39526b7SPramod Gunjikar 		    "get_context: copyout outbuf (rc=%d)", rc);
1424c39526b7SPramod Gunjikar 		rc = EFAULT;
1425c39526b7SPramod Gunjikar 		goto out;
1426c39526b7SPramod Gunjikar 	}
1427c39526b7SPramod Gunjikar 	rc = DDI_SUCCESS;
1428c39526b7SPramod Gunjikar 
1429c39526b7SPramod Gunjikar out:
1430c39526b7SPramod Gunjikar 	return (rc);
1431c39526b7SPramod Gunjikar }
1432c39526b7SPramod Gunjikar 
1433c39526b7SPramod Gunjikar /*
1434c39526b7SPramod Gunjikar  * Function:
1435c39526b7SPramod Gunjikar  *	sol_uverbs_alloc_pd
1436c39526b7SPramod Gunjikar  * Input:
1437c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
1438c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing a alloc PD command.
1439c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
1440c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
1441c39526b7SPramod Gunjikar  * Output:
1442c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
1443c39526b7SPramod Gunjikar  * Returns:
1444c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1445c39526b7SPramod Gunjikar  * Description:
1446c39526b7SPramod Gunjikar  * 	User verb entry point to allocate a device protection domain.
1447c39526b7SPramod Gunjikar  */
1448c39526b7SPramod Gunjikar /* ARGSUSED */
1449c39526b7SPramod Gunjikar int
sol_uverbs_alloc_pd(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1450c39526b7SPramod Gunjikar sol_uverbs_alloc_pd(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
1451c39526b7SPramod Gunjikar     int out_len)
1452c39526b7SPramod Gunjikar {
1453c39526b7SPramod Gunjikar 	struct ib_uverbs_alloc_pd	cmd;
1454c39526b7SPramod Gunjikar 	struct ib_uverbs_alloc_pd_resp	resp;
1455c39526b7SPramod Gunjikar 	uverbs_upd_uobj_t		*upd;
1456c39526b7SPramod Gunjikar 	int				rc;
1457c39526b7SPramod Gunjikar 
1458c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "alloc_pd()");
1459c39526b7SPramod Gunjikar 
1460c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1461c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
1462c39526b7SPramod Gunjikar 
1463c39526b7SPramod Gunjikar 	upd = kmem_zalloc(sizeof (*upd), KM_NOSLEEP);
1464c39526b7SPramod Gunjikar 	if (upd == NULL) {
1465c39526b7SPramod Gunjikar 		rc = ENOMEM;
1466c39526b7SPramod Gunjikar 		goto out;
1467c39526b7SPramod Gunjikar 	}
1468c39526b7SPramod Gunjikar 	sol_ofs_uobj_init(&upd->uobj, 0, SOL_UVERBS_UPD_UOBJ_TYPE);
1469c39526b7SPramod Gunjikar 	rw_enter(&upd->uobj.uo_lock, RW_WRITER);
1470c39526b7SPramod Gunjikar 
1471c39526b7SPramod Gunjikar 	rc = ibt_alloc_pd(uctxt->hca->hdl, IBT_PD_NO_FLAGS, &upd->pd);
1472c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1473c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1474c39526b7SPramod Gunjikar 		    "alloc_pd: ibt_alloc_pd() (rc=%d)", rc);
1475c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1476c39526b7SPramod Gunjikar 		upd->uobj.uo_uobj_sz = sizeof (uverbs_upd_uobj_t);
1477c39526b7SPramod Gunjikar 		goto alloc_err;
1478c39526b7SPramod Gunjikar 	}
1479c39526b7SPramod Gunjikar 
1480c39526b7SPramod Gunjikar 	if (sol_ofs_uobj_add(&uverbs_upd_uo_tbl, &upd->uobj) != 0) {
1481c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1482c39526b7SPramod Gunjikar 		    "alloc_pd: User object add failed");
1483c39526b7SPramod Gunjikar 		rc = ENOMEM;
1484c39526b7SPramod Gunjikar 		goto err_add_uobj;
1485c39526b7SPramod Gunjikar 	}
1486c39526b7SPramod Gunjikar 	resp.pd_handle = upd->uobj.uo_id;
1487c39526b7SPramod Gunjikar 
1488c39526b7SPramod Gunjikar 	/*
1489c39526b7SPramod Gunjikar 	 * Query underlying hardware driver for data that may be required
1490c39526b7SPramod Gunjikar 	 * when using the PD in an OS Bypass creation of UD address vectors.
1491c39526b7SPramod Gunjikar 	 */
1492c39526b7SPramod Gunjikar 	rc = ibt_ci_data_out(uctxt->hca->hdl, IBT_CI_NO_FLAGS, IBT_HDL_PD,
1493c39526b7SPramod Gunjikar 	    (void *)upd->pd, &resp.drv_out, sizeof (resp.drv_out));
1494c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1495c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1496c39526b7SPramod Gunjikar 		    "alloc_pd: ibt_ci_data_out() (rc=%d)", rc);
1497c39526b7SPramod Gunjikar 		rc = EFAULT;
1498c39526b7SPramod Gunjikar 		goto err_response;
1499c39526b7SPramod Gunjikar 	}
1500c39526b7SPramod Gunjikar 
1501c39526b7SPramod Gunjikar #ifdef	_LP64
1502c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
1503c39526b7SPramod Gunjikar #else
1504c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
1505c39526b7SPramod Gunjikar #endif
1506c39526b7SPramod Gunjikar 	if (rc != 0) {
1507c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1508c39526b7SPramod Gunjikar 		    "alloc_pd: copyout fail (rc=%d)", rc);
1509c39526b7SPramod Gunjikar 		rc = EFAULT;
1510c39526b7SPramod Gunjikar 		goto err_response;
1511c39526b7SPramod Gunjikar 	}
1512c39526b7SPramod Gunjikar 
1513c39526b7SPramod Gunjikar 	mutex_enter(&uctxt->lock);
1514c39526b7SPramod Gunjikar 	upd->list_entry = add_genlist(&uctxt->pd_list, (uintptr_t)upd, uctxt);
1515c39526b7SPramod Gunjikar 	mutex_exit(&uctxt->lock);
1516c39526b7SPramod Gunjikar 
1517c39526b7SPramod Gunjikar 	if (!upd->list_entry) {
1518c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1519c39526b7SPramod Gunjikar 		    "alloc_pd: Error adding upd to pd_list\n");
1520c39526b7SPramod Gunjikar 		rc = ENOMEM;
1521c39526b7SPramod Gunjikar 		goto err_response;
1522c39526b7SPramod Gunjikar 	}
1523c39526b7SPramod Gunjikar 
1524c39526b7SPramod Gunjikar 	upd->uobj.uo_live = 1;
1525c39526b7SPramod Gunjikar 	rw_exit(&upd->uobj.uo_lock);
1526c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
1527c39526b7SPramod Gunjikar 
1528c39526b7SPramod Gunjikar err_response:
1529c39526b7SPramod Gunjikar 	/*
1530c39526b7SPramod Gunjikar 	 * Need to set uo_live, so sol_ofs_uobj_remove() will
1531c39526b7SPramod Gunjikar 	 * remove the object from the object table.
1532c39526b7SPramod Gunjikar 	 */
1533c39526b7SPramod Gunjikar 	upd->uobj.uo_live = 1;
1534c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&uverbs_upd_uo_tbl, &upd->uobj);
1535c39526b7SPramod Gunjikar 
1536c39526b7SPramod Gunjikar err_add_uobj:
1537c39526b7SPramod Gunjikar 	(void) ibt_free_pd(uctxt->hca->hdl, upd->pd);
1538c39526b7SPramod Gunjikar 
1539c39526b7SPramod Gunjikar alloc_err:
1540c39526b7SPramod Gunjikar 	rw_exit(&upd->uobj.uo_lock);
1541c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&upd->uobj, sol_ofs_uobj_free);
1542c39526b7SPramod Gunjikar out:
1543c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1544c39526b7SPramod Gunjikar 	    "alloc_pd:error (rc=%d)", rc);
1545c39526b7SPramod Gunjikar 	return (rc);
1546c39526b7SPramod Gunjikar }
1547c39526b7SPramod Gunjikar 
1548c39526b7SPramod Gunjikar int
uverbs_upd_free(uverbs_upd_uobj_t * upd,uverbs_uctxt_uobj_t * uctxt)1549c39526b7SPramod Gunjikar uverbs_upd_free(uverbs_upd_uobj_t *upd, uverbs_uctxt_uobj_t *uctxt)
1550c39526b7SPramod Gunjikar {
1551c39526b7SPramod Gunjikar 	int	rc;
1552c39526b7SPramod Gunjikar 
1553c39526b7SPramod Gunjikar 	rc = ibt_free_pd(uctxt->hca->hdl, upd->pd);
1554c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1555c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1556c39526b7SPramod Gunjikar 		    "uverbs_upd_free: ibt_free_pd() failed %d", rc);
1557c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1558c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&upd->uobj);
1559c39526b7SPramod Gunjikar 		return (rc);
1560c39526b7SPramod Gunjikar 	}
1561c39526b7SPramod Gunjikar 
1562c39526b7SPramod Gunjikar 	/*
1563c39526b7SPramod Gunjikar 	 * Remove from the list of this contexts PD resources, then remove from
1564c39526b7SPramod Gunjikar 	 * the resource managment table and the reference placed on the user
1565c39526b7SPramod Gunjikar 	 * object at PD allocation.
1566c39526b7SPramod Gunjikar 	 */
1567c39526b7SPramod Gunjikar 	upd->pd = NULL;
1568c39526b7SPramod Gunjikar 	if (upd->list_entry) {
1569c39526b7SPramod Gunjikar 		mutex_enter(&uctxt->lock);
1570c39526b7SPramod Gunjikar 		delete_genlist(&uctxt->pd_list, upd->list_entry);
1571c39526b7SPramod Gunjikar 		mutex_exit(&uctxt->lock);
1572c39526b7SPramod Gunjikar 	}
1573c39526b7SPramod Gunjikar 
1574c39526b7SPramod Gunjikar 	/*
1575c39526b7SPramod Gunjikar 	 * list_entry is NULL when called from sol_uverbs_close. Remove
1576c39526b7SPramod Gunjikar 	 * from upd_uo_tbl and free upd, when called from close also.
1577c39526b7SPramod Gunjikar 	 */
1578c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&upd->uobj);
1579c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&uverbs_upd_uo_tbl, &upd->uobj);
1580c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&upd->uobj, sol_ofs_uobj_free);
1581c39526b7SPramod Gunjikar 	return (0);
1582c39526b7SPramod Gunjikar }
1583c39526b7SPramod Gunjikar 
1584c39526b7SPramod Gunjikar /*
1585c39526b7SPramod Gunjikar  * Function:
1586c39526b7SPramod Gunjikar  *	sol_uverbs_dealloc_pd
1587c39526b7SPramod Gunjikar  * Input:
1588c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
1589c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing dealloc PD command.
1590c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
1591c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
1592c39526b7SPramod Gunjikar  * Output:
1593c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
1594c39526b7SPramod Gunjikar  * Returns:
1595c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1596c39526b7SPramod Gunjikar  * Description:
1597c39526b7SPramod Gunjikar  * 	User verb entry point to de-allocate a device protection domain.
1598c39526b7SPramod Gunjikar  */
1599c39526b7SPramod Gunjikar /* ARGSUSED */
1600c39526b7SPramod Gunjikar int
sol_uverbs_dealloc_pd(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1601c39526b7SPramod Gunjikar sol_uverbs_dealloc_pd(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
1602c39526b7SPramod Gunjikar     int out_len)
1603c39526b7SPramod Gunjikar {
1604c39526b7SPramod Gunjikar 	struct ib_uverbs_dealloc_pd	cmd;
1605c39526b7SPramod Gunjikar 	uverbs_upd_uobj_t		*upd;
1606c39526b7SPramod Gunjikar 	int				rc = 0;
1607c39526b7SPramod Gunjikar 
1608c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1609c39526b7SPramod Gunjikar 
1610c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1611c39526b7SPramod Gunjikar 	    "dealloc_pd(%d)", cmd.pd_handle);
1612c39526b7SPramod Gunjikar 
1613c39526b7SPramod Gunjikar 	upd = uverbs_uobj_get_upd_write(cmd.pd_handle);
1614c39526b7SPramod Gunjikar 	if (upd == NULL) {
1615c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1616c39526b7SPramod Gunjikar 		    "dealloc_pd(%d) : invalid hdl", cmd.pd_handle);
1617c39526b7SPramod Gunjikar 		rc = EINVAL;
1618c39526b7SPramod Gunjikar 		goto err_out1;
1619c39526b7SPramod Gunjikar 	}
1620c39526b7SPramod Gunjikar 
1621c39526b7SPramod Gunjikar 	if (upd->active_qp_cnt) {
1622c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&upd->uobj);
1623c39526b7SPramod Gunjikar 		rc = EBUSY;
1624c39526b7SPramod Gunjikar 	} else {
1625c39526b7SPramod Gunjikar 		rc = uverbs_upd_free(upd, uctxt);
1626c39526b7SPramod Gunjikar 	}
1627c39526b7SPramod Gunjikar 	cmd.pd_handle = 0;
1628c39526b7SPramod Gunjikar 	return (rc);
1629c39526b7SPramod Gunjikar 
1630c39526b7SPramod Gunjikar err_out1:
1631c39526b7SPramod Gunjikar 	return (rc);
1632c39526b7SPramod Gunjikar }
1633c39526b7SPramod Gunjikar 
1634c39526b7SPramod Gunjikar /*
1635c39526b7SPramod Gunjikar  * Function:
1636c39526b7SPramod Gunjikar  *	sol_uverbs_query_device
1637c39526b7SPramod Gunjikar  * Input:
1638c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
1639c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing query device command.
1640c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
1641c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
1642c39526b7SPramod Gunjikar  * Output:
1643c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
1644c39526b7SPramod Gunjikar  * Returns:
1645c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1646c39526b7SPramod Gunjikar  * Description:
1647c39526b7SPramod Gunjikar  * 	User verb entry point to query device attributes.
1648c39526b7SPramod Gunjikar  */
1649c39526b7SPramod Gunjikar /* ARGSUSED */
1650c39526b7SPramod Gunjikar int
sol_uverbs_query_device(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1651c39526b7SPramod Gunjikar sol_uverbs_query_device(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
1652c39526b7SPramod Gunjikar 	int out_len)
1653c39526b7SPramod Gunjikar {
1654c39526b7SPramod Gunjikar 	struct ib_uverbs_query_device		cmd;
1655c39526b7SPramod Gunjikar 	struct ib_uverbs_query_device_resp	resp;
1656c39526b7SPramod Gunjikar 	ibt_hca_attr_t				hca_attr;
1657c39526b7SPramod Gunjikar 	int					rc;
1658c39526b7SPramod Gunjikar 
1659c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "query_device()");
1660c39526b7SPramod Gunjikar 
1661c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1662c39526b7SPramod Gunjikar 	rc = ibt_query_hca(uctxt->hca->hdl, &hca_attr);
1663c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1664c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1665c39526b7SPramod Gunjikar 		    "query_device: ibt_query_hca() (rc=%d)", rc);
1666c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1667c39526b7SPramod Gunjikar 		goto out;
1668c39526b7SPramod Gunjikar 	}
1669c39526b7SPramod Gunjikar 
1670c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
1671c39526b7SPramod Gunjikar 
1672c39526b7SPramod Gunjikar 	resp.fw_ver = ((uint64_t)hca_attr.hca_fw_major_version << 32) |
1673c39526b7SPramod Gunjikar 	    ((uint64_t)hca_attr.hca_fw_minor_version << 16) |
1674c39526b7SPramod Gunjikar 	    ((uint64_t)hca_attr.hca_fw_micro_version);
1675c39526b7SPramod Gunjikar 
1676c39526b7SPramod Gunjikar 	/*
1677c39526b7SPramod Gunjikar 	 * NOTE: node guid and system image guid must be returned in big
1678c39526b7SPramod Gunjikar 	 * endian (network order).  On solaris these are in host
1679c39526b7SPramod Gunjikar 	 * order, so we swap it back here.
1680c39526b7SPramod Gunjikar 	 */
1681c39526b7SPramod Gunjikar 	resp.node_guid			= htonll(hca_attr.hca_node_guid);
1682c39526b7SPramod Gunjikar 	resp.sys_image_guid		= htonll(hca_attr.hca_si_guid);
1683c39526b7SPramod Gunjikar 
1684c39526b7SPramod Gunjikar 	resp.max_mr_size		= hca_attr.hca_max_memr_len;
1685c39526b7SPramod Gunjikar 
1686c39526b7SPramod Gunjikar 	resp.page_size_cap =
1687c39526b7SPramod Gunjikar 	    sol_uverbs_ibt_to_of_page_sz(hca_attr.hca_page_sz);
1688c39526b7SPramod Gunjikar 
1689c39526b7SPramod Gunjikar 	resp.vendor_id			= hca_attr.hca_vendor_id;
1690c39526b7SPramod Gunjikar 	resp.vendor_part_id		= hca_attr.hca_device_id;
1691c39526b7SPramod Gunjikar 	resp.hw_ver			= hca_attr.hca_version_id;
1692c39526b7SPramod Gunjikar 	resp.max_qp			= hca_attr.hca_max_chans;
1693c39526b7SPramod Gunjikar 	resp.max_qp_wr			= hca_attr.hca_max_chan_sz;
1694c39526b7SPramod Gunjikar 
1695c39526b7SPramod Gunjikar 	resp.device_cap_flags		=
1696c39526b7SPramod Gunjikar 	    sol_uverbs_ibt_to_of_device_cap_flags(hca_attr.hca_flags,
1697c39526b7SPramod Gunjikar 	    hca_attr.hca_flags2);
1698c39526b7SPramod Gunjikar 
1699c39526b7SPramod Gunjikar 	resp.max_sge			= hca_attr.hca_max_sgl;
1700c39526b7SPramod Gunjikar 	resp.max_sge_rd			= hca_attr.hca_max_sgl;
1701c39526b7SPramod Gunjikar 	resp.max_cq			= hca_attr.hca_max_cq;
1702c39526b7SPramod Gunjikar 	resp.max_cqe			= hca_attr.hca_max_cq_sz;
1703c39526b7SPramod Gunjikar 	resp.max_mr			= hca_attr.hca_max_memr;
1704c39526b7SPramod Gunjikar 	resp.max_pd			= hca_attr.hca_max_pd;
1705c39526b7SPramod Gunjikar 	resp.max_qp_rd_atom		= hca_attr.hca_max_rdma_in_chan;
1706c39526b7SPramod Gunjikar 	resp.max_ee_rd_atom		= 0;
1707c39526b7SPramod Gunjikar 	resp.max_res_rd_atom		= hca_attr.hca_max_rsc;
1708c39526b7SPramod Gunjikar 	resp.max_qp_init_rd_atom	= hca_attr.hca_max_rdma_out_chan;
1709c39526b7SPramod Gunjikar 	resp.max_ee_init_rd_atom	= 0;
1710c39526b7SPramod Gunjikar 	if (hca_attr.hca_flags & IBT_HCA_ATOMICS_GLOBAL) {
1711c39526b7SPramod Gunjikar 		resp.atomic_cap = IB_ATOMIC_GLOB;
1712c39526b7SPramod Gunjikar 	} else if (hca_attr.hca_flags & IBT_HCA_ATOMICS_HCA) {
1713c39526b7SPramod Gunjikar 		resp.atomic_cap = IB_ATOMIC_HCA;
1714c39526b7SPramod Gunjikar 	} else {
1715c39526b7SPramod Gunjikar 		resp.atomic_cap = IB_ATOMIC_NONE;
1716c39526b7SPramod Gunjikar 	}
1717c39526b7SPramod Gunjikar 	resp.max_ee			= 0;
1718c39526b7SPramod Gunjikar 	resp.max_rdd			= 0;
1719c39526b7SPramod Gunjikar 	resp.max_mw			= hca_attr.hca_max_mem_win;
1720c39526b7SPramod Gunjikar 	resp.max_raw_ipv6_qp		= hca_attr.hca_max_ipv6_chan;
1721c39526b7SPramod Gunjikar 	resp.max_raw_ethy_qp		= hca_attr.hca_max_ether_chan;
1722c39526b7SPramod Gunjikar 	resp.max_mcast_grp		= hca_attr.hca_max_mcg;
1723c39526b7SPramod Gunjikar 	resp.max_mcast_qp_attach	= hca_attr.hca_max_chan_per_mcg;
1724c39526b7SPramod Gunjikar 	resp.max_total_mcast_qp_attach	= hca_attr.hca_max_mcg_chans;
1725c39526b7SPramod Gunjikar 	resp.max_ah			= hca_attr.hca_max_ud_dest;
1726c39526b7SPramod Gunjikar 	resp.max_fmr			= hca_attr.hca_max_fmrs;
1727c39526b7SPramod Gunjikar 	resp.max_map_per_fmr		= 0;
1728c39526b7SPramod Gunjikar 	resp.max_srq			= hca_attr.hca_max_srqs;
1729c39526b7SPramod Gunjikar 	resp.max_srq_wr			= hca_attr.hca_max_srqs_sz;
1730c39526b7SPramod Gunjikar 	resp.max_srq_sge		= hca_attr.hca_max_srq_sgl;
1731c39526b7SPramod Gunjikar 	resp.max_pkeys			= hca_attr.hca_max_port_pkey_tbl_sz;
1732c39526b7SPramod Gunjikar 	resp.local_ca_ack_delay		= hca_attr.hca_local_ack_delay;
1733c39526b7SPramod Gunjikar 	resp.phys_port_cnt		= hca_attr.hca_nports;
1734c39526b7SPramod Gunjikar 
1735c39526b7SPramod Gunjikar #ifdef	_LP64
1736c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
1737c39526b7SPramod Gunjikar #else
1738c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
1739c39526b7SPramod Gunjikar #endif
1740c39526b7SPramod Gunjikar 	if (rc != 0) {
1741c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1742c39526b7SPramod Gunjikar 		    "query_device: Error writing resp data (rc=%d)", rc);
1743c39526b7SPramod Gunjikar 		rc = EFAULT;
1744c39526b7SPramod Gunjikar 		goto out;
1745c39526b7SPramod Gunjikar 	}
1746c39526b7SPramod Gunjikar 
1747c39526b7SPramod Gunjikar 	rc = DDI_SUCCESS;
1748c39526b7SPramod Gunjikar 
1749c39526b7SPramod Gunjikar out:
1750c39526b7SPramod Gunjikar 	return (rc);
1751c39526b7SPramod Gunjikar }
1752c39526b7SPramod Gunjikar 
1753c39526b7SPramod Gunjikar /*
1754c39526b7SPramod Gunjikar  * Function:
1755c39526b7SPramod Gunjikar  *	sol_uverbs_query_port
1756c39526b7SPramod Gunjikar  * Input:
1757c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
1758c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing query port command.
1759c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
1760c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
1761c39526b7SPramod Gunjikar  * Output:
1762c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
1763c39526b7SPramod Gunjikar  * Returns:
1764c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1765c39526b7SPramod Gunjikar  * Description:
1766c39526b7SPramod Gunjikar  * 	User verb entry point to query a device port attributes.
1767c39526b7SPramod Gunjikar  */
1768c39526b7SPramod Gunjikar /* ARGSUSED */
1769c39526b7SPramod Gunjikar int
sol_uverbs_query_port(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1770c39526b7SPramod Gunjikar sol_uverbs_query_port(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
1771c39526b7SPramod Gunjikar     int out_len)
1772c39526b7SPramod Gunjikar {
1773c39526b7SPramod Gunjikar 	struct ib_uverbs_query_port		cmd;
1774c39526b7SPramod Gunjikar 	struct ib_uverbs_query_port_resp	resp;
1775c39526b7SPramod Gunjikar 	ibt_hca_portinfo_t			*port_info;
1776c39526b7SPramod Gunjikar 	uint_t					port_info_n;
1777c39526b7SPramod Gunjikar 	uint_t					port_info_size;
1778c39526b7SPramod Gunjikar 	int					rc;
1779c39526b7SPramod Gunjikar 
1780c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1781c39526b7SPramod Gunjikar 
1782c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "sol_uverbs_query_port: %d",
1783c39526b7SPramod Gunjikar 	    cmd.port_num);
1784c39526b7SPramod Gunjikar 
1785c39526b7SPramod Gunjikar 	if (!cmd.port_num || cmd.port_num > uctxt->hca->attr.hca_nports) {
1786c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1787c39526b7SPramod Gunjikar 		    "query_port: Invalid port specified");
1788c39526b7SPramod Gunjikar 
1789c39526b7SPramod Gunjikar 		rc = EINVAL;
1790c39526b7SPramod Gunjikar 		goto out;
1791c39526b7SPramod Gunjikar 	}
1792c39526b7SPramod Gunjikar 
1793c39526b7SPramod Gunjikar 	rc = ibt_query_hca_ports(uctxt->hca->hdl, cmd.port_num, &port_info,
1794c39526b7SPramod Gunjikar 	    &port_info_n, &port_info_size);
1795c39526b7SPramod Gunjikar 
1796c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1797c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1798c39526b7SPramod Gunjikar 		    "query_port: ibt_query_hca_ports() (rc=%d)", rc);
1799c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1800c39526b7SPramod Gunjikar 		goto out;
1801c39526b7SPramod Gunjikar 	}
1802c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "query_port: "
1803c39526b7SPramod Gunjikar 	    "port_num %d, port_info %x, lid %x, sm_lid %x",
1804c39526b7SPramod Gunjikar 	    cmd.port_num, port_info, port_info->p_opaque1,
1805c39526b7SPramod Gunjikar 	    port_info->p_sm_lid);
1806c39526b7SPramod Gunjikar 
1807c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
1808c39526b7SPramod Gunjikar 
1809c39526b7SPramod Gunjikar 	resp.state			= port_info->p_linkstate;
1810c39526b7SPramod Gunjikar 	resp.max_mtu			= port_info->p_mtu;
1811c39526b7SPramod Gunjikar 	resp.active_mtu			= port_info->p_mtu;
1812c39526b7SPramod Gunjikar 	resp.gid_tbl_len		= port_info->p_sgid_tbl_sz;
1813c39526b7SPramod Gunjikar 	resp.port_cap_flags  		= port_info->p_capabilities;
1814c39526b7SPramod Gunjikar 	resp.max_msg_sz			= port_info->p_msg_sz;
1815c39526b7SPramod Gunjikar 	resp.bad_pkey_cntr   		= port_info->p_pkey_violations;
1816c39526b7SPramod Gunjikar 	resp.qkey_viol_cntr  		= port_info->p_qkey_violations;
1817c39526b7SPramod Gunjikar 	resp.pkey_tbl_len    		= port_info->p_pkey_tbl_sz;
1818c39526b7SPramod Gunjikar 	resp.lid			= port_info->p_opaque1;
1819c39526b7SPramod Gunjikar 	resp.sm_lid			= port_info->p_sm_lid;
1820c39526b7SPramod Gunjikar 	resp.lmc			= port_info->p_lmc;
1821c39526b7SPramod Gunjikar 	resp.max_vl_num			= port_info->p_max_vl;
1822c39526b7SPramod Gunjikar 	resp.sm_sl			= port_info->p_sm_sl;
1823c39526b7SPramod Gunjikar 	resp.subnet_timeout  		= port_info->p_subnet_timeout;
1824c39526b7SPramod Gunjikar 	resp.init_type_reply 		= port_info->p_init_type_reply;
1825c39526b7SPramod Gunjikar 	resp.active_width    		= port_info->p_width_active;
1826c39526b7SPramod Gunjikar 	resp.active_speed    		= port_info->p_speed_active;
1827c39526b7SPramod Gunjikar 	resp.phys_state			= port_info->p_phys_state;
1828c39526b7SPramod Gunjikar 
1829c39526b7SPramod Gunjikar 	ibt_free_portinfo(port_info, port_info_size);
1830c39526b7SPramod Gunjikar 
1831c39526b7SPramod Gunjikar #ifdef	_LP64
1832c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
1833c39526b7SPramod Gunjikar #else
1834c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
1835c39526b7SPramod Gunjikar #endif
1836c39526b7SPramod Gunjikar 	if (rc != 0) {
1837c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1838c39526b7SPramod Gunjikar 		    "query_port : copyout fail %x", rc);
1839c39526b7SPramod Gunjikar 		rc = EFAULT;
1840c39526b7SPramod Gunjikar 		goto out;
1841c39526b7SPramod Gunjikar 	}
1842c39526b7SPramod Gunjikar 
1843c39526b7SPramod Gunjikar 	rc = DDI_SUCCESS;
1844c39526b7SPramod Gunjikar 
1845c39526b7SPramod Gunjikar out:
1846c39526b7SPramod Gunjikar 	return (rc);
1847c39526b7SPramod Gunjikar }
1848c39526b7SPramod Gunjikar 
1849c39526b7SPramod Gunjikar /*
1850c39526b7SPramod Gunjikar  * Function:
1851c39526b7SPramod Gunjikar  *	sol_uverbs_query_gid
1852c39526b7SPramod Gunjikar  * Input:
1853c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
1854c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing query gid command.
1855c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
1856c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
1857c39526b7SPramod Gunjikar  * Output:
1858c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
1859c39526b7SPramod Gunjikar  * Returns:
1860c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1861c39526b7SPramod Gunjikar  * Description:
1862c39526b7SPramod Gunjikar  * 	User verb entry point to query the device gid for the specified
1863c39526b7SPramod Gunjikar  *	port and gid index.
1864c39526b7SPramod Gunjikar  */
1865c39526b7SPramod Gunjikar /* ARGSUSED */
1866c39526b7SPramod Gunjikar int
sol_uverbs_query_gid(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1867c39526b7SPramod Gunjikar sol_uverbs_query_gid(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
1868c39526b7SPramod Gunjikar     int out_len)
1869c39526b7SPramod Gunjikar {
1870c39526b7SPramod Gunjikar 	struct ib_uverbs_query_gid	cmd;
1871c39526b7SPramod Gunjikar 	struct ib_uverbs_query_gid_resp	resp;
1872c39526b7SPramod Gunjikar 	ibt_hca_portinfo_t		*port_info;
1873c39526b7SPramod Gunjikar 	uint_t				port_info_n;
1874c39526b7SPramod Gunjikar 	uint_t				port_info_size;
1875c39526b7SPramod Gunjikar 	int				rc;
1876c39526b7SPramod Gunjikar 	uint64_t			temp;
1877c39526b7SPramod Gunjikar 
1878c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1879c39526b7SPramod Gunjikar 
1880c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1881c39526b7SPramod Gunjikar 	    "query_gid() : port_num %x, gid_index %x",
1882c39526b7SPramod Gunjikar 	    cmd.port_num, cmd.gid_index);
1883c39526b7SPramod Gunjikar 
1884c39526b7SPramod Gunjikar 	if (!cmd.port_num || cmd.port_num > uctxt->hca->attr.hca_nports) {
1885c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1886c39526b7SPramod Gunjikar 		    "query_gid: Invalid port specified");
1887c39526b7SPramod Gunjikar 
1888c39526b7SPramod Gunjikar 		rc = EINVAL;
1889c39526b7SPramod Gunjikar 		goto out;
1890c39526b7SPramod Gunjikar 	}
1891c39526b7SPramod Gunjikar 
1892c39526b7SPramod Gunjikar 	rc = ibt_query_hca_ports(uctxt->hca->hdl, cmd.port_num, &port_info,
1893c39526b7SPramod Gunjikar 	    &port_info_n, &port_info_size);
1894c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1895c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1896c39526b7SPramod Gunjikar 		    "query_gid: ibt_query_hca_ports() (rc=%d)", rc);
1897c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1898c39526b7SPramod Gunjikar 		goto out;
1899c39526b7SPramod Gunjikar 	}
1900c39526b7SPramod Gunjikar 
1901c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "number of "
1902c39526b7SPramod Gunjikar 	    "gid entries %d", cmd.port_num, cmd.gid_index,
1903c39526b7SPramod Gunjikar 	    port_info->p_sgid_tbl_sz);
1904c39526b7SPramod Gunjikar 
1905c39526b7SPramod Gunjikar 
1906c39526b7SPramod Gunjikar 	if (cmd.gid_index >= port_info->p_sgid_tbl_sz) {
1907c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1908c39526b7SPramod Gunjikar 		    "query_gid: cmd gid_index %x > port_info sz %x",
1909c39526b7SPramod Gunjikar 		    cmd.gid_index, port_info->p_sgid_tbl_sz);
1910c39526b7SPramod Gunjikar 		rc = EINVAL;
1911c39526b7SPramod Gunjikar 		ibt_free_portinfo(port_info, port_info_size);
1912c39526b7SPramod Gunjikar 		goto out;
1913c39526b7SPramod Gunjikar 	}
1914c39526b7SPramod Gunjikar 
1915c39526b7SPramod Gunjikar 	/*
1916c39526b7SPramod Gunjikar 	 * The gid must be returned as a network ordered byte array, on solaris
1917c39526b7SPramod Gunjikar 	 * it is a structure in host order so we swap the components as needed.
1918c39526b7SPramod Gunjikar 	 */
1919c39526b7SPramod Gunjikar 	temp = htonll(port_info->p_sgid_tbl[cmd.gid_index].gid.ucast_gid.
1920c39526b7SPramod Gunjikar 	    ugid_prefix);
1921c39526b7SPramod Gunjikar 	(void) memcpy(&resp.gid[0], &temp, sizeof (temp));
1922c39526b7SPramod Gunjikar 	temp = htonll(port_info->p_sgid_tbl[cmd.gid_index].gid.ucast_gid.
1923c39526b7SPramod Gunjikar 	    ugid_guid);
1924c39526b7SPramod Gunjikar 	(void) memcpy(&resp.gid[8], &temp, sizeof (temp));
1925c39526b7SPramod Gunjikar 
1926c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "query_gid: gid = "
1927c39526b7SPramod Gunjikar 	    "0x%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
1928c39526b7SPramod Gunjikar 	    "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:",
1929c39526b7SPramod Gunjikar 	    resp.gid[0], resp.gid[1], resp.gid[2], resp.gid[3],
1930c39526b7SPramod Gunjikar 	    resp.gid[4], resp.gid[5], resp.gid[6], resp.gid[7],
1931c39526b7SPramod Gunjikar 	    resp.gid[8], resp.gid[9], resp.gid[10], resp.gid[11],
1932c39526b7SPramod Gunjikar 	    resp.gid[12], resp.gid[13], resp.gid[14], resp.gid[15]);
1933c39526b7SPramod Gunjikar 
1934c39526b7SPramod Gunjikar 	ibt_free_portinfo(port_info, port_info_size);
1935c39526b7SPramod Gunjikar 
1936c39526b7SPramod Gunjikar #ifdef	_LP64
1937c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
1938c39526b7SPramod Gunjikar #else
1939c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
1940c39526b7SPramod Gunjikar #endif
1941c39526b7SPramod Gunjikar 	if (rc != 0) {
1942c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1943c39526b7SPramod Gunjikar 		    "query_gid: copyout %d", rc);
1944c39526b7SPramod Gunjikar 		rc = EFAULT;
1945c39526b7SPramod Gunjikar 		goto out;
1946c39526b7SPramod Gunjikar 	}
1947c39526b7SPramod Gunjikar 
1948c39526b7SPramod Gunjikar 	rc = DDI_SUCCESS;
1949c39526b7SPramod Gunjikar out:
1950c39526b7SPramod Gunjikar 	return (rc);
1951c39526b7SPramod Gunjikar }
1952c39526b7SPramod Gunjikar 
1953c39526b7SPramod Gunjikar /*
1954c39526b7SPramod Gunjikar  * Function:
1955c39526b7SPramod Gunjikar  *	sol_uverbs_query_pkey
1956c39526b7SPramod Gunjikar  * Input:
1957c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
1958c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing a query pkey command.
1959c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
1960c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
1961c39526b7SPramod Gunjikar  * Output:
1962c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
1963c39526b7SPramod Gunjikar  * Returns:
1964c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
1965c39526b7SPramod Gunjikar  * Description:
1966c39526b7SPramod Gunjikar  * 	User verb entry point to query a device for the pkey at the specified
1967c39526b7SPramod Gunjikar  *	port and pkey index.
1968c39526b7SPramod Gunjikar  */
1969c39526b7SPramod Gunjikar /* ARGSUSED */
1970c39526b7SPramod Gunjikar int
sol_uverbs_query_pkey(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1971c39526b7SPramod Gunjikar sol_uverbs_query_pkey(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
1972c39526b7SPramod Gunjikar     int out_len)
1973c39526b7SPramod Gunjikar {
1974c39526b7SPramod Gunjikar 	struct ib_uverbs_query_pkey		cmd;
1975c39526b7SPramod Gunjikar 	struct ib_uverbs_query_pkey_resp	resp;
1976c39526b7SPramod Gunjikar 	ibt_hca_portinfo_t			*port_info;
1977c39526b7SPramod Gunjikar 	uint_t					port_info_n;
1978c39526b7SPramod Gunjikar 	uint_t					port_info_size;
1979c39526b7SPramod Gunjikar 	int					rc;
1980c39526b7SPramod Gunjikar 
1981c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1982c39526b7SPramod Gunjikar 
1983c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1984c39526b7SPramod Gunjikar 	    "query_pkey: entry, port = %d, pkey index = %d",
1985c39526b7SPramod Gunjikar 	    cmd.port_num, cmd.pkey_index);
1986c39526b7SPramod Gunjikar 
1987c39526b7SPramod Gunjikar 	if (!cmd.port_num || cmd.port_num > uctxt->hca->attr.hca_nports) {
1988c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1989c39526b7SPramod Gunjikar 		    "query_pkey: Invalid port specified");
1990c39526b7SPramod Gunjikar 
1991c39526b7SPramod Gunjikar 		rc = EINVAL;
1992c39526b7SPramod Gunjikar 		goto out;
1993c39526b7SPramod Gunjikar 	}
1994c39526b7SPramod Gunjikar 
1995c39526b7SPramod Gunjikar 	rc = ibt_query_hca_ports(uctxt->hca->hdl, cmd.port_num, &port_info,
1996c39526b7SPramod Gunjikar 	    &port_info_n, &port_info_size);
1997c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1998c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1999c39526b7SPramod Gunjikar 		    "query_pkey: ibt_query_hca_ports() %d", rc);
2000c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
2001c39526b7SPramod Gunjikar 		goto out;
2002c39526b7SPramod Gunjikar 	}
2003c39526b7SPramod Gunjikar 
2004c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2005c39526b7SPramod Gunjikar 	    "query_pkey: port %d, requested index %d, number of pkey entries "
2006c39526b7SPramod Gunjikar 	    "%d", cmd.port_num, cmd.pkey_index, port_info->p_pkey_tbl_sz);
2007c39526b7SPramod Gunjikar 
2008c39526b7SPramod Gunjikar 
2009c39526b7SPramod Gunjikar 	if (cmd.pkey_index >= port_info->p_pkey_tbl_sz) {
2010c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2011c39526b7SPramod Gunjikar 		    "query_pkey: Invalid index %d, table size = %d",
2012c39526b7SPramod Gunjikar 		    cmd.pkey_index, port_info->p_pkey_tbl_sz);
2013c39526b7SPramod Gunjikar 
2014c39526b7SPramod Gunjikar 		ibt_free_portinfo(port_info, port_info_size);
2015c39526b7SPramod Gunjikar 		rc = EINVAL;
2016c39526b7SPramod Gunjikar 		goto out;
2017c39526b7SPramod Gunjikar 	}
2018c39526b7SPramod Gunjikar 
2019c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
2020c39526b7SPramod Gunjikar 	resp.pkey = port_info->p_pkey_tbl[cmd.pkey_index];
2021c39526b7SPramod Gunjikar 
2022c39526b7SPramod Gunjikar 	ibt_free_portinfo(port_info, port_info_size);
2023c39526b7SPramod Gunjikar 
2024c39526b7SPramod Gunjikar #ifdef	_LP64
2025c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
2026c39526b7SPramod Gunjikar #else
2027c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
2028c39526b7SPramod Gunjikar #endif
2029c39526b7SPramod Gunjikar 	if (rc != 0) {
2030c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2031c39526b7SPramod Gunjikar 		    "query_pkey: copyout %d", rc);
2032c39526b7SPramod Gunjikar 		rc = EFAULT;
2033c39526b7SPramod Gunjikar 		goto out;
2034c39526b7SPramod Gunjikar 	}
2035c39526b7SPramod Gunjikar 
2036c39526b7SPramod Gunjikar 	rc = DDI_SUCCESS;
2037c39526b7SPramod Gunjikar out:
2038c39526b7SPramod Gunjikar 	return (rc);
2039c39526b7SPramod Gunjikar }
2040c39526b7SPramod Gunjikar 
2041c39526b7SPramod Gunjikar /*
2042c39526b7SPramod Gunjikar  * Function:
2043c39526b7SPramod Gunjikar  *	sol_uverbs_reg_mr
2044c39526b7SPramod Gunjikar  * Input:
2045c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
2046c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing command.
2047c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
2048c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
2049c39526b7SPramod Gunjikar  * Output:
2050c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
2051c39526b7SPramod Gunjikar  * Returns:
2052c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
2053c39526b7SPramod Gunjikar  * Description:
2054c39526b7SPramod Gunjikar  * 	User verb entry point to register a memory region.
2055c39526b7SPramod Gunjikar  */
2056c39526b7SPramod Gunjikar /* ARGSUSED */
2057c39526b7SPramod Gunjikar int
sol_uverbs_reg_mr(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2058c39526b7SPramod Gunjikar sol_uverbs_reg_mr(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
2059c39526b7SPramod Gunjikar     int out_len)
2060c39526b7SPramod Gunjikar {
2061c39526b7SPramod Gunjikar 	struct ib_uverbs_reg_mr		cmd;
2062c39526b7SPramod Gunjikar 	struct ib_uverbs_reg_mr_resp	resp;
2063c39526b7SPramod Gunjikar 	uverbs_upd_uobj_t		*upd;
2064c39526b7SPramod Gunjikar 	uverbs_umr_uobj_t		*umr;
2065c39526b7SPramod Gunjikar 	ibt_mr_attr_t			new_mem_attr;
2066c39526b7SPramod Gunjikar 	ibt_mr_desc_t			new_mr_desc;
2067c39526b7SPramod Gunjikar 	int				rc;
2068c39526b7SPramod Gunjikar 
2069c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
2070c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
2071c39526b7SPramod Gunjikar 	(void) memset(&new_mem_attr, 0, sizeof (new_mem_attr));
2072c39526b7SPramod Gunjikar 	(void) memset(&new_mr_desc, 0, sizeof (new_mr_desc));
2073c39526b7SPramod Gunjikar 
2074c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "reg_mr()");
2075c39526b7SPramod Gunjikar 
2076c39526b7SPramod Gunjikar 	new_mem_attr.mr_vaddr	= cmd.start;
2077c39526b7SPramod Gunjikar 	new_mem_attr.mr_len	= cmd.length;
2078c39526b7SPramod Gunjikar 	new_mem_attr.mr_as	= curproc->p_as;
2079c39526b7SPramod Gunjikar 	new_mem_attr.mr_flags	= IBT_MR_NOSLEEP;
2080c39526b7SPramod Gunjikar 
2081c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "reg_mr : "
2082c39526b7SPramod Gunjikar 	    "mr_vaddr 0x%0lX, mr_len %d, mr_as %d, mr_flags %d",
2083c39526b7SPramod Gunjikar 	    new_mem_attr.mr_vaddr, new_mem_attr.mr_len,
2084c39526b7SPramod Gunjikar 	    new_mem_attr.mr_as, new_mem_attr.mr_flags);
2085c39526b7SPramod Gunjikar 
2086c39526b7SPramod Gunjikar 	if ((cmd.access_flags & IB_ACCESS_LOCAL_WRITE) ==
2087c39526b7SPramod Gunjikar 	    IB_ACCESS_LOCAL_WRITE) {
2088c39526b7SPramod Gunjikar 		new_mem_attr.mr_flags |= IBT_MR_ENABLE_LOCAL_WRITE;
2089c39526b7SPramod Gunjikar 	}
2090c39526b7SPramod Gunjikar 	if ((cmd.access_flags & IB_ACCESS_REMOTE_WRITE) ==
2091c39526b7SPramod Gunjikar 	    IB_ACCESS_REMOTE_WRITE) {
2092c39526b7SPramod Gunjikar 		new_mem_attr.mr_flags |= IBT_MR_ENABLE_REMOTE_WRITE;
2093c39526b7SPramod Gunjikar 	}
2094c39526b7SPramod Gunjikar 	if ((cmd.access_flags & IB_ACCESS_REMOTE_READ) ==
2095c39526b7SPramod Gunjikar 	    IB_ACCESS_REMOTE_READ) {
2096c39526b7SPramod Gunjikar 		new_mem_attr.mr_flags |= IBT_MR_ENABLE_REMOTE_READ;
2097c39526b7SPramod Gunjikar 	}
2098c39526b7SPramod Gunjikar 	if ((cmd.access_flags & IB_ACCESS_REMOTE_ATOMIC) ==
2099c39526b7SPramod Gunjikar 	    IB_ACCESS_REMOTE_ATOMIC) {
2100c39526b7SPramod Gunjikar 		new_mem_attr.mr_flags |= IBT_MR_ENABLE_REMOTE_ATOMIC;
2101c39526b7SPramod Gunjikar 	}
2102c39526b7SPramod Gunjikar 	if ((cmd.access_flags & IB_ACCESS_MW_BIND) == IB_ACCESS_MW_BIND) {
2103c39526b7SPramod Gunjikar 		new_mem_attr.mr_flags |= IBT_MR_ENABLE_WINDOW_BIND;
2104c39526b7SPramod Gunjikar 	}
2105*fffafeb2SJohnny Cheung 	if ((cmd.access_flags & IB_ACCESS_SO) == IB_ACCESS_SO) {
2106*fffafeb2SJohnny Cheung 		new_mem_attr.mr_flags |= IBT_MR_DISABLE_RO;
2107*fffafeb2SJohnny Cheung 	}
2108c39526b7SPramod Gunjikar 
2109c39526b7SPramod Gunjikar 	umr = kmem_zalloc(sizeof (*umr), KM_NOSLEEP);
2110c39526b7SPramod Gunjikar 	if (umr == NULL) {
2111c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2112c39526b7SPramod Gunjikar 		    "reg_mr: User object mem allocation error");
2113c39526b7SPramod Gunjikar 		rc = ENOMEM;
2114c39526b7SPramod Gunjikar 		goto out;
2115c39526b7SPramod Gunjikar 	}
2116c39526b7SPramod Gunjikar 	sol_ofs_uobj_init(&umr->uobj, 0, SOL_UVERBS_UMR_UOBJ_TYPE);
2117c39526b7SPramod Gunjikar 	rw_enter(&umr->uobj.uo_lock, RW_WRITER);
2118c39526b7SPramod Gunjikar 
2119c39526b7SPramod Gunjikar 	upd = uverbs_uobj_get_upd_read(cmd.pd_handle);
2120c39526b7SPramod Gunjikar 	if (upd == NULL) {
2121c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2122c39526b7SPramod Gunjikar 		    "reg_mr: PD invalid");
2123c39526b7SPramod Gunjikar 		rc = EINVAL;
2124c39526b7SPramod Gunjikar 		goto bad_pd;
2125c39526b7SPramod Gunjikar 	}
2126c39526b7SPramod Gunjikar 
2127c39526b7SPramod Gunjikar 	rc = ibt_register_mr(uctxt->hca->hdl, upd->pd, &new_mem_attr, &umr->mr,
2128c39526b7SPramod Gunjikar 	    &new_mr_desc);
2129c39526b7SPramod Gunjikar 
2130c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
2131c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2132c39526b7SPramod Gunjikar 		    "reg_mr: ibt_register_mr() (rc=%d)", rc);
2133c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
2134c39526b7SPramod Gunjikar 		umr->uobj.uo_uobj_sz = sizeof (uverbs_umr_uobj_t);
2135c39526b7SPramod Gunjikar 		goto err_register;
2136c39526b7SPramod Gunjikar 	}
2137c39526b7SPramod Gunjikar 
2138c39526b7SPramod Gunjikar 	if (sol_ofs_uobj_add(&uverbs_umr_uo_tbl, &umr->uobj) != 0) {
2139c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2140c39526b7SPramod Gunjikar 		    "reg_mr: User object add failed");
2141c39526b7SPramod Gunjikar 		rc = ENOMEM;
2142c39526b7SPramod Gunjikar 		goto err_add_uobj;
2143c39526b7SPramod Gunjikar 	}
2144c39526b7SPramod Gunjikar 
2145c39526b7SPramod Gunjikar 	resp.mr_handle  = umr->uobj.uo_id;
2146c39526b7SPramod Gunjikar 	resp.lkey	= new_mr_desc.md_lkey;
2147c39526b7SPramod Gunjikar 	resp.rkey	= new_mr_desc.md_rkey;
2148c39526b7SPramod Gunjikar 
2149c39526b7SPramod Gunjikar #ifdef	_LP64
2150c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
2151c39526b7SPramod Gunjikar #else
2152c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
2153c39526b7SPramod Gunjikar #endif
2154c39526b7SPramod Gunjikar 	if (rc != 0) {
2155c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2156c39526b7SPramod Gunjikar 		    "reg_mr: Error writing resp data (rc=%d)", rc);
2157c39526b7SPramod Gunjikar 		rc = EFAULT;
2158c39526b7SPramod Gunjikar 		goto err_response;
2159c39526b7SPramod Gunjikar 	}
2160c39526b7SPramod Gunjikar 
2161c39526b7SPramod Gunjikar 	mutex_enter(&uctxt->lock);
2162c39526b7SPramod Gunjikar 	umr->list_entry  = add_genlist(&uctxt->mr_list, (uintptr_t)umr, uctxt);
2163c39526b7SPramod Gunjikar 	mutex_exit(&uctxt->lock);
2164c39526b7SPramod Gunjikar 
2165c39526b7SPramod Gunjikar 	if (!umr->list_entry) {
2166c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2167c39526b7SPramod Gunjikar 		    "reg_mr: Error adding umr to mr_list\n");
2168c39526b7SPramod Gunjikar 		rc = ENOMEM;
2169c39526b7SPramod Gunjikar 		goto err_response;
2170c39526b7SPramod Gunjikar 	}
2171c39526b7SPramod Gunjikar 
2172c39526b7SPramod Gunjikar 	umr->uobj.uo_live = 1;
2173c39526b7SPramod Gunjikar 	rw_exit(&umr->uobj.uo_lock);
2174c39526b7SPramod Gunjikar 
2175c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&upd->uobj);
2176c39526b7SPramod Gunjikar 
2177c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
2178c39526b7SPramod Gunjikar 
2179c39526b7SPramod Gunjikar err_response:
2180c39526b7SPramod Gunjikar 	/*
2181c39526b7SPramod Gunjikar 	 * Need to set uo_live, so sol_ofs_uobj_remove() will
2182c39526b7SPramod Gunjikar 	 * remove the object from the object table.
2183c39526b7SPramod Gunjikar 	 */
2184c39526b7SPramod Gunjikar 	umr->uobj.uo_live = 1;
2185c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&uverbs_umr_uo_tbl, &umr->uobj);
2186c39526b7SPramod Gunjikar 
2187c39526b7SPramod Gunjikar err_add_uobj:
2188c39526b7SPramod Gunjikar 	(void) ibt_deregister_mr(uctxt->hca->hdl, umr->mr);
2189c39526b7SPramod Gunjikar 
2190c39526b7SPramod Gunjikar err_register:
2191c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&upd->uobj);
2192c39526b7SPramod Gunjikar 
2193c39526b7SPramod Gunjikar bad_pd:
2194c39526b7SPramod Gunjikar 	rw_exit(&umr->uobj.uo_lock);
2195c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&umr->uobj, sol_ofs_uobj_free);
2196c39526b7SPramod Gunjikar 
2197c39526b7SPramod Gunjikar out:
2198c39526b7SPramod Gunjikar 	return (rc);
2199c39526b7SPramod Gunjikar }
2200c39526b7SPramod Gunjikar 
2201c39526b7SPramod Gunjikar /*
2202c39526b7SPramod Gunjikar  * Function:
2203c39526b7SPramod Gunjikar  *	sol_uverbs_dereg_mr
2204c39526b7SPramod Gunjikar  * Input:
2205c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
2206c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing command.
2207c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
2208c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
2209c39526b7SPramod Gunjikar  * Output:
2210c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
2211c39526b7SPramod Gunjikar  * Returns:
2212c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
2213c39526b7SPramod Gunjikar  * Description:
2214c39526b7SPramod Gunjikar  * 	User verb entry point to de-register a memory region.
2215c39526b7SPramod Gunjikar  */
2216c39526b7SPramod Gunjikar /* ARGSUSED */
2217c39526b7SPramod Gunjikar int
sol_uverbs_dereg_mr(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2218c39526b7SPramod Gunjikar sol_uverbs_dereg_mr(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
2219c39526b7SPramod Gunjikar     int out_len)
2220c39526b7SPramod Gunjikar {
2221c39526b7SPramod Gunjikar 	struct ib_uverbs_dereg_mr	cmd;
2222c39526b7SPramod Gunjikar 	uverbs_umr_uobj_t		*umr;
2223c39526b7SPramod Gunjikar 	int				rc;
2224c39526b7SPramod Gunjikar 
2225c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
2226c39526b7SPramod Gunjikar 
2227c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2228c39526b7SPramod Gunjikar 	    "dereg_mr(mr_handle=%d)", cmd.mr_handle);
2229c39526b7SPramod Gunjikar 
2230c39526b7SPramod Gunjikar 	umr = uverbs_uobj_get_umr_write(cmd.mr_handle);
2231c39526b7SPramod Gunjikar 	if (umr == NULL) {
2232c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2233c39526b7SPramod Gunjikar 		    "dereg_mr: Invalid handle");
2234c39526b7SPramod Gunjikar 		rc = EINVAL;
2235c39526b7SPramod Gunjikar 		goto err_out;
2236c39526b7SPramod Gunjikar 	}
2237c39526b7SPramod Gunjikar 
2238c39526b7SPramod Gunjikar 	rc = ibt_deregister_mr(uctxt->hca->hdl, umr->mr);
2239c39526b7SPramod Gunjikar 
2240c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
2241c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2242c39526b7SPramod Gunjikar 		    "dereg_mr: ibt_deregister_mr() (rc=%d)", rc);
2243c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
2244c39526b7SPramod Gunjikar 		goto err_deregister;
2245c39526b7SPramod Gunjikar 	}
2246c39526b7SPramod Gunjikar 
2247c39526b7SPramod Gunjikar 	/*
2248c39526b7SPramod Gunjikar 	 * Remove from the list of this contexts MR resources, then remove from
2249c39526b7SPramod Gunjikar 	 * the resource management table and the reference placed on the user
2250c39526b7SPramod Gunjikar 	 * object at MR creation.
2251c39526b7SPramod Gunjikar 	 */
2252c39526b7SPramod Gunjikar 	mutex_enter(&uctxt->lock);
2253c39526b7SPramod Gunjikar 	delete_genlist(&uctxt->mr_list, umr->list_entry);
2254c39526b7SPramod Gunjikar 	mutex_exit(&uctxt->lock);
2255c39526b7SPramod Gunjikar 
2256c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&uverbs_umr_uo_tbl, &umr->uobj);
2257c39526b7SPramod Gunjikar 
2258c39526b7SPramod Gunjikar 	/*
2259c39526b7SPramod Gunjikar 	 * Drop the lock and ref held by get_umr_write.
2260c39526b7SPramod Gunjikar 	 */
2261c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&umr->uobj);
2262c39526b7SPramod Gunjikar 
2263c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&umr->uobj, sol_ofs_uobj_free);
2264c39526b7SPramod Gunjikar 
2265c39526b7SPramod Gunjikar 	cmd.mr_handle = 0;
2266c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
2267c39526b7SPramod Gunjikar 
2268c39526b7SPramod Gunjikar err_deregister:
2269c39526b7SPramod Gunjikar 	/*
2270c39526b7SPramod Gunjikar 	 * Drop the lock and ref held by get_umr_write.
2271c39526b7SPramod Gunjikar 	 */
2272c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&umr->uobj);
2273c39526b7SPramod Gunjikar 
2274c39526b7SPramod Gunjikar err_out:
2275c39526b7SPramod Gunjikar 	return (rc);
2276c39526b7SPramod Gunjikar }
2277c39526b7SPramod Gunjikar 
2278c39526b7SPramod Gunjikar /*
2279c39526b7SPramod Gunjikar  * Function:
2280c39526b7SPramod Gunjikar  *	sol_uverbs_create_ah
2281c39526b7SPramod Gunjikar  * Input:
2282c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
2283c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing command.
2284c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
2285c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
2286c39526b7SPramod Gunjikar  * Output:
2287c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
2288c39526b7SPramod Gunjikar  * Returns:
2289c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
2290c39526b7SPramod Gunjikar  * Description:
2291c39526b7SPramod Gunjikar  * 	User verb entry point to for devices that require kernel AH creation.
2292c39526b7SPramod Gunjikar  */
2293c39526b7SPramod Gunjikar /* ARGSUSED */
2294c39526b7SPramod Gunjikar int
sol_uverbs_create_ah(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2295c39526b7SPramod Gunjikar sol_uverbs_create_ah(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
2296c39526b7SPramod Gunjikar     int out_len)
2297c39526b7SPramod Gunjikar {
2298c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str,
2299c39526b7SPramod Gunjikar 	    "create_ah: kernel user verb not implemented");
2300c39526b7SPramod Gunjikar 	return (ENOTSUP);
2301c39526b7SPramod Gunjikar }
2302c39526b7SPramod Gunjikar 
2303c39526b7SPramod Gunjikar /*
2304c39526b7SPramod Gunjikar  * Function:
2305c39526b7SPramod Gunjikar  *	sol_uverbs_destroy_ah
2306c39526b7SPramod Gunjikar  * Input:
2307c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
2308c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing command.
2309c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
2310c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
2311c39526b7SPramod Gunjikar  * Output:
2312c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
2313c39526b7SPramod Gunjikar  * Returns:
2314c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
2315c39526b7SPramod Gunjikar  * Description:
2316c39526b7SPramod Gunjikar  * 	User verb entry point to for devices that require kernel AH deletion.
2317c39526b7SPramod Gunjikar  */
2318c39526b7SPramod Gunjikar /* ARGSUSED */
2319c39526b7SPramod Gunjikar int
sol_uverbs_destroy_ah(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2320c39526b7SPramod Gunjikar sol_uverbs_destroy_ah(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
2321c39526b7SPramod Gunjikar     int out_len)
2322c39526b7SPramod Gunjikar {
2323c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str,
2324c39526b7SPramod Gunjikar 	    "destroy_ah: kernel user verb not implemented");
2325c39526b7SPramod Gunjikar 	return (ENOTSUP);
2326c39526b7SPramod Gunjikar }
2327c39526b7SPramod Gunjikar 
2328c39526b7SPramod Gunjikar /*
2329c39526b7SPramod Gunjikar  * Function:
2330c39526b7SPramod Gunjikar  *	sol_uverbs_create_comp_chan
2331c39526b7SPramod Gunjikar  * Input:
2332c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
2333c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing command.
2334c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
2335c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
2336c39526b7SPramod Gunjikar  * Output:
2337c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
2338c39526b7SPramod Gunjikar  * Returns:
2339c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
2340c39526b7SPramod Gunjikar  * Description:
2341c39526b7SPramod Gunjikar  * 	User verb entry point to create a completion event channel.
2342c39526b7SPramod Gunjikar  */
2343c39526b7SPramod Gunjikar int
sol_uverbs_create_comp_channel(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2344c39526b7SPramod Gunjikar sol_uverbs_create_comp_channel(uverbs_uctxt_uobj_t *uctxt, char *buf,
2345c39526b7SPramod Gunjikar     int in_len, int out_len)
2346c39526b7SPramod Gunjikar {
2347c39526b7SPramod Gunjikar 	struct ib_uverbs_create_comp_channel		cmd;
2348c39526b7SPramod Gunjikar 	struct ib_uverbs_create_comp_channel_resp	resp;
2349c39526b7SPramod Gunjikar 	int						rc;
2350c39526b7SPramod Gunjikar 	minor_t						compl_id;
2351c39526b7SPramod Gunjikar 	uverbs_uctxt_uobj_t				*compl_uctxt;
2352c39526b7SPramod Gunjikar 
2353c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
2354c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
2355c39526b7SPramod Gunjikar 
2356c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2357c39526b7SPramod Gunjikar 	    "create_comp_chan: entry, in_len=%d, out_len=%d",
2358c39526b7SPramod Gunjikar 	    in_len, out_len);
2359c39526b7SPramod Gunjikar 
2360c39526b7SPramod Gunjikar 	/*
2361c39526b7SPramod Gunjikar 	 * libibverbs will have passed minor of the compl file in
2362c39526b7SPramod Gunjikar 	 * resp.fd. Use this to determine the uctxt created for
2363c39526b7SPramod Gunjikar 	 * completions.
2364c39526b7SPramod Gunjikar 	 */
2365c39526b7SPramod Gunjikar #ifdef	_LP64
2366c39526b7SPramod Gunjikar 	rc = copyin((void*)cmd.response.r_laddr, (void*)&resp, sizeof (resp));
2367c39526b7SPramod Gunjikar #else
2368c39526b7SPramod Gunjikar 	rc = copyin((void*)cmd.response.r_addr, (void*)&resp, sizeof (resp));
2369c39526b7SPramod Gunjikar #endif
2370c39526b7SPramod Gunjikar 	if (rc != 0) {
2371c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2372c39526b7SPramod Gunjikar 		    "create_comp: copyin (rc=%d)", rc);
2373c39526b7SPramod Gunjikar 		rc = EFAULT;
2374c39526b7SPramod Gunjikar 		return (rc);
2375c39526b7SPramod Gunjikar 	}
2376c39526b7SPramod Gunjikar 	compl_id = resp.fd;
2377c39526b7SPramod Gunjikar 	if (compl_id < SOL_UVERBS_DRIVER_MAX_MINOR) {
2378c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2379c39526b7SPramod Gunjikar 		    "create_comp: Invalid compl user context id %x",
2380c39526b7SPramod Gunjikar 		    compl_id);
2381c39526b7SPramod Gunjikar 		return (ENXIO);
2382c39526b7SPramod Gunjikar 	}
2383c39526b7SPramod Gunjikar 
2384c39526b7SPramod Gunjikar 	compl_uctxt = uverbs_uobj_get_uctxt_read(compl_id -
2385c39526b7SPramod Gunjikar 	    SOL_UVERBS_DRIVER_MAX_MINOR);
2386c39526b7SPramod Gunjikar 	if (compl_uctxt == NULL) {
2387c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2388c39526b7SPramod Gunjikar 		    "create_comp: Failed get compl user context");
2389c39526b7SPramod Gunjikar 		return (ENXIO);
2390c39526b7SPramod Gunjikar 	}
2391c39526b7SPramod Gunjikar 	if (compl_uctxt->uctxt_type != SOL_UVERBS_UCTXT_EVENT ||
2392c39526b7SPramod Gunjikar 	    compl_uctxt->uctxt_verbs_id != 0) {
2393c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2394c39526b7SPramod Gunjikar 		    "create_comp_chan: Invalid user context - "
2395c39526b7SPramod Gunjikar 		    "possibly reused");
2396c39526b7SPramod Gunjikar 		return (ENXIO);
2397c39526b7SPramod Gunjikar 	}
2398c39526b7SPramod Gunjikar 	compl_uctxt->uctxt_type = SOL_UVERBS_UCTXT_COMPL;
2399c39526b7SPramod Gunjikar 	compl_uctxt->uctxt_verbs_id = uctxt->uobj.uo_id +
2400c39526b7SPramod Gunjikar 	    SOL_UVERBS_DRIVER_MAX_MINOR;
2401c39526b7SPramod Gunjikar 	uctxt->uctxt_comp_id = compl_id;
2402c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "create_comp_chan: "
2403c39526b7SPramod Gunjikar 	    "uctxt %p, compl_uctxt %p, compl_id %x", uctxt,
2404c39526b7SPramod Gunjikar 	    compl_uctxt, compl_id);
2405c39526b7SPramod Gunjikar 
2406c39526b7SPramod Gunjikar 	/*
2407c39526b7SPramod Gunjikar 	 * Allocate an event file to be used for completion
2408c39526b7SPramod Gunjikar 	 * event notification.
2409c39526b7SPramod Gunjikar 	 */
2410c39526b7SPramod Gunjikar 	compl_uctxt->comp_evfile = uverbs_alloc_event_file(uctxt, 0);
2411c39526b7SPramod Gunjikar 	if (compl_uctxt->comp_evfile == NULL) {
2412c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2413c39526b7SPramod Gunjikar 		    "create_comp_chan: Event file alloc error");
2414c39526b7SPramod Gunjikar 		rc = EINVAL;
2415c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&compl_uctxt->uobj);
2416c39526b7SPramod Gunjikar 		return (rc);
2417c39526b7SPramod Gunjikar 	}
2418c39526b7SPramod Gunjikar 
2419c39526b7SPramod Gunjikar 	/*
2420c39526b7SPramod Gunjikar 	 * Place an extra reference on the compl event file.  These will
2421c39526b7SPramod Gunjikar 	 * be used to handle the natural race of between the closing of
2422c39526b7SPramod Gunjikar 	 * the compl event file and uverbs device file that can occur.
2423c39526b7SPramod Gunjikar 	 */
2424c39526b7SPramod Gunjikar 	sol_ofs_uobj_ref(&compl_uctxt->comp_evfile->uobj);
2425c39526b7SPramod Gunjikar 
2426c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&compl_uctxt->uobj);
2427c39526b7SPramod Gunjikar 
2428c39526b7SPramod Gunjikar #ifdef	_LP64
2429c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
2430c39526b7SPramod Gunjikar #else
2431c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
2432c39526b7SPramod Gunjikar #endif
2433c39526b7SPramod Gunjikar 	if (rc != 0) {
2434c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2435c39526b7SPramod Gunjikar 		    "create_comp_chan: copyout %d", rc);
2436c39526b7SPramod Gunjikar 		rc = EFAULT;
2437c39526b7SPramod Gunjikar 		return (rc);
2438c39526b7SPramod Gunjikar 	}
2439c39526b7SPramod Gunjikar 
2440c39526b7SPramod Gunjikar 	return (0);
2441c39526b7SPramod Gunjikar }
2442c39526b7SPramod Gunjikar 
2443c39526b7SPramod Gunjikar /*
2444c39526b7SPramod Gunjikar  * Function:
2445c39526b7SPramod Gunjikar  *	sol_uverbs_dummy_command
2446c39526b7SPramod Gunjikar  * Input:
2447c39526b7SPramod Gunjikar  *	uctxt   - Pointer to the callers user context.
2448c39526b7SPramod Gunjikar  *	buf     - Pointer to kernel buffer containing command.
2449c39526b7SPramod Gunjikar  *	in_len  - Length in bytes of input command buffer.
2450c39526b7SPramod Gunjikar  *	out_len - Length in bytes of output response buffer.
2451c39526b7SPramod Gunjikar  * Output:
2452c39526b7SPramod Gunjikar  *	The command output buffer is updated with command results.
2453c39526b7SPramod Gunjikar  * Returns:
2454c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
2455c39526b7SPramod Gunjikar  * Description:
2456c39526b7SPramod Gunjikar  * 	User verb generic place holder stub.
2457c39526b7SPramod Gunjikar  */
2458c39526b7SPramod Gunjikar /* ARGSUSED */
2459c39526b7SPramod Gunjikar int
sol_uverbs_dummy_command(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2460c39526b7SPramod Gunjikar sol_uverbs_dummy_command(uverbs_uctxt_uobj_t *uctxt, char *buf, int in_len,
2461c39526b7SPramod Gunjikar     int out_len)
2462c39526b7SPramod Gunjikar {
2463c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L4(sol_uverbs_dbg_str,
2464c39526b7SPramod Gunjikar 	    "sol_uverbs_dummy_command invoked");
2465c39526b7SPramod Gunjikar 
2466c39526b7SPramod Gunjikar 	return (0);
2467c39526b7SPramod Gunjikar }
2468c39526b7SPramod Gunjikar 
2469c39526b7SPramod Gunjikar /*
2470c39526b7SPramod Gunjikar  * Function:
2471c39526b7SPramod Gunjikar  *	sol_uverbs_write
2472c39526b7SPramod Gunjikar  * Input:
2473c39526b7SPramod Gunjikar  *	dev	- Device number.
2474c39526b7SPramod Gunjikar  *	uiop	- Pointer to the uio structure that describes the data (i.e.
2475c39526b7SPramod Gunjikar  *                Solaris User Verbs command).
2476c39526b7SPramod Gunjikar  *	credp	- A pointer to the user credentials for the I/O transaction.
2477c39526b7SPramod Gunjikar  * Output:
2478c39526b7SPramod Gunjikar  *	uiop	-
2479c39526b7SPramod Gunjikar  * Returns:
2480c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
2481c39526b7SPramod Gunjikar  * Description:
2482c39526b7SPramod Gunjikar  * 	User verb write entry point.  A user deivce libraries use this
2483c39526b7SPramod Gunjikar  *	entry point to execute a kernel agent user verbs call.  During
2484c39526b7SPramod Gunjikar  *	the course of the call the user process will hold a read reference
2485c39526b7SPramod Gunjikar  *	to the associated user context.
2486c39526b7SPramod Gunjikar  */
2487c39526b7SPramod Gunjikar #define	SOL_UVERBS_MAX_CMD_PAYLOAD    512
2488c39526b7SPramod Gunjikar /* ARGSUSED */
2489c39526b7SPramod Gunjikar static int
sol_uverbs_write(dev_t dev,struct uio * uiop,cred_t * credp)2490c39526b7SPramod Gunjikar sol_uverbs_write(dev_t dev, struct uio *uiop, cred_t *credp)
2491c39526b7SPramod Gunjikar {
2492c39526b7SPramod Gunjikar 	uverbs_uctxt_uobj_t		*uctxt;
2493c39526b7SPramod Gunjikar 	size_t				len = uiop->uio_resid;
2494c39526b7SPramod Gunjikar 	int				rc;
2495c39526b7SPramod Gunjikar 	struct ib_uverbs_cmd_hdr	hdr;
2496c39526b7SPramod Gunjikar 	char				payload[SOL_UVERBS_MAX_CMD_PAYLOAD];
2497c39526b7SPramod Gunjikar 	minor_t				id = getminor(dev);
2498c39526b7SPramod Gunjikar 
2499c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2500c39526b7SPramod Gunjikar 	    "uverbs_write: entry (len=%d)", len);
2501c39526b7SPramod Gunjikar 
2502c39526b7SPramod Gunjikar 	ASSERT(id >= SOL_UVERBS_DRIVER_MAX_MINOR);
2503c39526b7SPramod Gunjikar 
2504c39526b7SPramod Gunjikar 	uctxt = uverbs_uobj_get_uctxt_read(id - SOL_UVERBS_DRIVER_MAX_MINOR);
2505c39526b7SPramod Gunjikar 	if (uctxt == NULL) {
2506c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2507c39526b7SPramod Gunjikar 		    "uverbs_write: Failed get user context");
2508c39526b7SPramod Gunjikar 		return (ENXIO);
2509c39526b7SPramod Gunjikar 	}
2510c39526b7SPramod Gunjikar 
2511c39526b7SPramod Gunjikar 	if (uctxt->uctxt_type != SOL_UVERBS_UCTXT_VERBS) {
2512c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2513c39526b7SPramod Gunjikar 		    "uverbs_write: write() on invalid uctxt type %x",
2514c39526b7SPramod Gunjikar 		    uctxt->uctxt_type);
2515c39526b7SPramod Gunjikar 		rc = ENXIO;
2516c39526b7SPramod Gunjikar 		goto out;
2517c39526b7SPramod Gunjikar 	}
2518c39526b7SPramod Gunjikar 
2519c39526b7SPramod Gunjikar 	if (len < sizeof (hdr)) {
2520c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2521c39526b7SPramod Gunjikar 		    "uverbs_write: Header too small");
2522c39526b7SPramod Gunjikar 		rc =  EINVAL;
2523c39526b7SPramod Gunjikar 		goto out;
2524c39526b7SPramod Gunjikar 	}
2525c39526b7SPramod Gunjikar 
2526c39526b7SPramod Gunjikar 	hdr.command	= -1;
2527c39526b7SPramod Gunjikar 	hdr.in_words	= 0;
2528c39526b7SPramod Gunjikar 	hdr.out_words	= 0;
2529c39526b7SPramod Gunjikar 
2530c39526b7SPramod Gunjikar 	if (uiomove(&hdr, sizeof (hdr), UIO_WRITE, uiop) != 0) {
2531c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2532c39526b7SPramod Gunjikar 		    "uverbs_write: Error reading header");
2533c39526b7SPramod Gunjikar 		rc = EFAULT;
2534c39526b7SPramod Gunjikar 		goto out;
2535c39526b7SPramod Gunjikar 	}
2536c39526b7SPramod Gunjikar 
2537c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2538c39526b7SPramod Gunjikar 	    "uverbs_write:  hdr.command   = %d", hdr.command);
2539c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2540c39526b7SPramod Gunjikar 	    "uverbs_write:  hdr.command   = %d", hdr.command);
2541c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2542c39526b7SPramod Gunjikar 	    "uverbs_write:  hdr.in_words  = %d", hdr.in_words);
2543c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2544c39526b7SPramod Gunjikar 	    "uverbs_write:  hdr.out_words = %d", hdr.out_words);
2545c39526b7SPramod Gunjikar 
2546c39526b7SPramod Gunjikar 	if (hdr.in_words * 4 != len) {
2547c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2548c39526b7SPramod Gunjikar 		    "uverbs_write: Invalid header size");
2549c39526b7SPramod Gunjikar 		rc = EINVAL;
2550c39526b7SPramod Gunjikar 		goto out;
2551c39526b7SPramod Gunjikar 	}
2552c39526b7SPramod Gunjikar 
2553c39526b7SPramod Gunjikar 	if (hdr.command >=
2554c39526b7SPramod Gunjikar 	    sizeof (uverbs_cmd_table)/sizeof (uverbs_cmd_table[0]) ||
2555c39526b7SPramod Gunjikar 	    !uverbs_cmd_table[hdr.command]) {
2556c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2557c39526b7SPramod Gunjikar 		    "uverbs_write: Invalid command (%d)", hdr.command);
2558c39526b7SPramod Gunjikar 		rc = EINVAL;
2559c39526b7SPramod Gunjikar 		goto out;
2560c39526b7SPramod Gunjikar 	}
2561c39526b7SPramod Gunjikar 
2562c39526b7SPramod Gunjikar 	ASSERT(len <= SOL_UVERBS_MAX_CMD_PAYLOAD);
2563c39526b7SPramod Gunjikar 
2564c39526b7SPramod Gunjikar 	if (uiomove(&payload, len, UIO_WRITE, uiop) != 0) {
2565c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2566c39526b7SPramod Gunjikar 		    "uverbs_write: Error reading payload");
2567c39526b7SPramod Gunjikar 		rc = EFAULT;
2568c39526b7SPramod Gunjikar 		goto out;
2569c39526b7SPramod Gunjikar 	}
2570c39526b7SPramod Gunjikar 
2571c39526b7SPramod Gunjikar #ifdef DEBUG
2572c39526b7SPramod Gunjikar 	unsigned int	*payload_int = (unsigned int *)payload;
2573c39526b7SPramod Gunjikar 
2574c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2575c39526b7SPramod Gunjikar 	    "payload:   %08x,    %08x,    %08x,    %08x",
2576c39526b7SPramod Gunjikar 	    payload_int[0], payload_int[1],
2577c39526b7SPramod Gunjikar 	    payload_int[2], payload_int[3]);
2578c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2579c39526b7SPramod Gunjikar 	    "payload:   %08x,    %08x,    %08x,    %08x",
2580c39526b7SPramod Gunjikar 	    payload_int[4], payload_int[5],
2581c39526b7SPramod Gunjikar 	    payload_int[6], payload_int[7]);
2582c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2583c39526b7SPramod Gunjikar 	    "payload:   %08x,    %08x,    %08x,    %08x",
2584c39526b7SPramod Gunjikar 	    payload_int[8], payload_int[9],
2585c39526b7SPramod Gunjikar 	    payload_int[10], payload_int[11]);
2586c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2587c39526b7SPramod Gunjikar 	    "payload:   %08x,    %08x,    %08x",
2588c39526b7SPramod Gunjikar 	    payload_int[12], payload_int[13], payload_int[14]);
2589c39526b7SPramod Gunjikar #endif
2590c39526b7SPramod Gunjikar 
2591c39526b7SPramod Gunjikar 	rc = uverbs_cmd_table[hdr.command](uctxt, &payload[0], hdr.in_words * 4,
2592c39526b7SPramod Gunjikar 	    hdr.out_words * 4);
2593c39526b7SPramod Gunjikar 
2594c39526b7SPramod Gunjikar out:
2595c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uctxt->uobj);
2596c39526b7SPramod Gunjikar 
2597c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2598c39526b7SPramod Gunjikar 	    "uverbs_write: rc = %d", rc);
2599c39526b7SPramod Gunjikar 
2600c39526b7SPramod Gunjikar 	return (rc);
2601c39526b7SPramod Gunjikar }
2602c39526b7SPramod Gunjikar 
2603c39526b7SPramod Gunjikar static int
sol_uverbs_poll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)2604c39526b7SPramod Gunjikar sol_uverbs_poll(dev_t dev, short events, int anyyet,
2605c39526b7SPramod Gunjikar     short *reventsp, struct pollhead **phpp)
2606c39526b7SPramod Gunjikar {
2607c39526b7SPramod Gunjikar 	minor_t			id = getminor(dev);
2608c39526b7SPramod Gunjikar 	uverbs_uctxt_uobj_t	*uctxt, *verbs_uctxt;
2609c39526b7SPramod Gunjikar 	int			rc;
2610c39526b7SPramod Gunjikar 
2611c39526b7SPramod Gunjikar #ifdef DEBUG
2612c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "uverbs_poll(%p, %x, %x, "
2613c39526b7SPramod Gunjikar 	    "%p, %p)", dev, events, anyyet, reventsp, phpp);
2614c39526b7SPramod Gunjikar #endif
2615c39526b7SPramod Gunjikar 
2616c39526b7SPramod Gunjikar 	ASSERT(id >= SOL_UVERBS_DRIVER_MAX_MINOR);
2617c39526b7SPramod Gunjikar 
2618c39526b7SPramod Gunjikar 	uctxt = uverbs_uobj_get_uctxt_read(id - SOL_UVERBS_DRIVER_MAX_MINOR);
2619c39526b7SPramod Gunjikar 	if (uctxt == NULL) {
2620c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2621c39526b7SPramod Gunjikar 		    "uverbs_poll: Failed get user context");
2622c39526b7SPramod Gunjikar 		return (ENXIO);
2623c39526b7SPramod Gunjikar 	}
2624c39526b7SPramod Gunjikar 
2625c39526b7SPramod Gunjikar 	if (uctxt->uctxt_verbs_id < SOL_UVERBS_DRIVER_MAX_MINOR) {
2626c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2627c39526b7SPramod Gunjikar 		    "uverbs_poll: Invalid Verbs user context id, %x",
2628c39526b7SPramod Gunjikar 		    uctxt->uctxt_verbs_id);
2629c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uctxt->uobj);
2630c39526b7SPramod Gunjikar 		return (ENXIO);
2631c39526b7SPramod Gunjikar 	}
2632c39526b7SPramod Gunjikar 	verbs_uctxt = uverbs_uobj_get_uctxt_read(uctxt->uctxt_verbs_id
2633c39526b7SPramod Gunjikar 	    - SOL_UVERBS_DRIVER_MAX_MINOR);
2634c39526b7SPramod Gunjikar 	if (verbs_uctxt == NULL) {
2635c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2636c39526b7SPramod Gunjikar 		    "uverbs_poll: Failed get verbs user context");
2637c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uctxt->uobj);
2638c39526b7SPramod Gunjikar 		return (ENXIO);
2639c39526b7SPramod Gunjikar 	}
2640c39526b7SPramod Gunjikar 	if (uctxt->uctxt_type == SOL_UVERBS_UCTXT_ASYNC) {
2641c39526b7SPramod Gunjikar 		ASSERT(verbs_uctxt->async_evfile);
2642c39526b7SPramod Gunjikar 		rc = sol_uverbs_event_file_poll(verbs_uctxt->async_evfile,
2643c39526b7SPramod Gunjikar 		    events, anyyet, reventsp, phpp);
2644c39526b7SPramod Gunjikar 	} else if (uctxt->uctxt_type == SOL_UVERBS_UCTXT_COMPL) {
2645c39526b7SPramod Gunjikar 		ASSERT(uctxt->comp_evfile);
2646c39526b7SPramod Gunjikar 		rc = sol_uverbs_event_file_poll(uctxt->comp_evfile,
2647c39526b7SPramod Gunjikar 		    events, anyyet, reventsp, phpp);
2648c39526b7SPramod Gunjikar 	} else {
2649c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2650c39526b7SPramod Gunjikar 		    "uverbs_poll: poll user context type %d",
2651c39526b7SPramod Gunjikar 		    uctxt->uctxt_type);
2652c39526b7SPramod Gunjikar 		rc = ENXIO;
2653c39526b7SPramod Gunjikar 	}
2654c39526b7SPramod Gunjikar 
2655c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&verbs_uctxt->uobj);
2656c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uctxt->uobj);
2657c39526b7SPramod Gunjikar 	return (rc);
2658c39526b7SPramod Gunjikar }
2659c39526b7SPramod Gunjikar 
2660c39526b7SPramod Gunjikar /*
2661c39526b7SPramod Gunjikar  * Function:
2662c39526b7SPramod Gunjikar  *	sol_uverbs_alloc_uctxt
2663c39526b7SPramod Gunjikar  * Input:
2664c39526b7SPramod Gunjikar  *	devp	 - A pointer to the device number associated with the open.
2665c39526b7SPramod Gunjikar  *	mod_ctxt - A pointer to the drivers module context.
2666c39526b7SPramod Gunjikar  *	minor    - The minor device number.
2667c39526b7SPramod Gunjikar  * Output:
2668c39526b7SPramod Gunjikar  *	None.
2669c39526b7SPramod Gunjikar  * Returns:
2670c39526b7SPramod Gunjikar  *	On success a new user context user resource object associated with
2671c39526b7SPramod Gunjikar  *	the device passed via devp. NULL on error.
2672c39526b7SPramod Gunjikar  * Description:
2673c39526b7SPramod Gunjikar  * 	Allocate a new user context user resource object and initialize it.
2674c39526b7SPramod Gunjikar  *	The users asynchronous event file is created as part of this. On
2675c39526b7SPramod Gunjikar  *	successful allocation, the user context is returned with the
2676c39526b7SPramod Gunjikar  *	associated write lock enabled.
2677c39526b7SPramod Gunjikar  */
2678c39526b7SPramod Gunjikar static uverbs_uctxt_uobj_t *
sol_uverbs_alloc_uctxt(dev_t * devp,uverbs_module_context_t * mod_ctxt,minor_t minor)2679c39526b7SPramod Gunjikar sol_uverbs_alloc_uctxt(dev_t *devp, uverbs_module_context_t *mod_ctxt,
2680c39526b7SPramod Gunjikar     minor_t minor)
2681c39526b7SPramod Gunjikar {
2682c39526b7SPramod Gunjikar 	uverbs_uctxt_uobj_t *uctxt = NULL;
2683c39526b7SPramod Gunjikar 
2684c39526b7SPramod Gunjikar 	uctxt = kmem_zalloc(sizeof (uverbs_uctxt_uobj_t), KM_SLEEP);
2685c39526b7SPramod Gunjikar 	ASSERT(uctxt != NULL);
2686c39526b7SPramod Gunjikar 	sol_ofs_uobj_init(&uctxt->uobj, 0, SOL_UVERBS_UCTXT_UOBJ_TYPE);
2687c39526b7SPramod Gunjikar 	rw_enter(&uctxt->uobj.uo_lock, RW_WRITER);
2688c39526b7SPramod Gunjikar 	if (sol_ofs_uobj_add(&uverbs_uctxt_uo_tbl, &uctxt->uobj) != 0) {
2689c39526b7SPramod Gunjikar 		/*
2690c39526b7SPramod Gunjikar 		 * The initialization routine set's the initial reference,
2691c39526b7SPramod Gunjikar 		 * we dereference the object here to clean it up.
2692c39526b7SPramod Gunjikar 		 */
2693c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2694c39526b7SPramod Gunjikar 		    "alloc_uctxt: Object add failed");
2695c39526b7SPramod Gunjikar 		rw_exit(&uctxt->uobj.uo_lock);
2696c39526b7SPramod Gunjikar 		sol_ofs_uobj_free(&uctxt->uobj);
2697c39526b7SPramod Gunjikar 		return (NULL);
2698c39526b7SPramod Gunjikar 	}
2699c39526b7SPramod Gunjikar 
2700c39526b7SPramod Gunjikar 	/*
2701c39526b7SPramod Gunjikar 	 * Create the new clone for this user context using the
2702c39526b7SPramod Gunjikar 	 * object id as the minor number.   Note we offset beyond all
2703c39526b7SPramod Gunjikar 	 * real minor device numbers.
2704c39526b7SPramod Gunjikar 	 */
2705c39526b7SPramod Gunjikar 	*devp = makedevice(getmajor(*devp),
2706c39526b7SPramod Gunjikar 	    uctxt->uobj.uo_id + SOL_UVERBS_DRIVER_MAX_MINOR);
2707c39526b7SPramod Gunjikar 
2708c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "uverbs_open : "
2709c39526b7SPramod Gunjikar 	    "uctxt %p, minor %x- alloced", uctxt,
2710c39526b7SPramod Gunjikar 	    uctxt->uobj.uo_id + SOL_UVERBS_DRIVER_MAX_MINOR);
2711c39526b7SPramod Gunjikar 
2712c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2713c39526b7SPramod Gunjikar 	    "alloc_uctxt: user context allocated: %p, ref = %d",
2714c39526b7SPramod Gunjikar 	    (void *)uctxt, uctxt->uobj.uo_refcnt);
2715c39526b7SPramod Gunjikar 
2716c39526b7SPramod Gunjikar 	mutex_init(&uctxt->lock, NULL, MUTEX_DRIVER, NULL);
2717c39526b7SPramod Gunjikar 	uctxt->mod_ctxt	= mod_ctxt;
2718c39526b7SPramod Gunjikar 	if (minor == SOL_UVERBS_DRIVER_EVENT_MINOR) {
2719c39526b7SPramod Gunjikar 		uctxt->uctxt_type = SOL_UVERBS_UCTXT_EVENT;
2720c39526b7SPramod Gunjikar 	} else {
2721c39526b7SPramod Gunjikar 		uctxt->uctxt_type = SOL_UVERBS_UCTXT_VERBS;
2722c39526b7SPramod Gunjikar 		uctxt->hca = &mod_ctxt->hcas[minor];
2723c39526b7SPramod Gunjikar 	}
2724c39526b7SPramod Gunjikar 
2725c39526b7SPramod Gunjikar 	init_genlist(&uctxt->pd_list);
2726c39526b7SPramod Gunjikar 	init_genlist(&uctxt->mr_list);
2727c39526b7SPramod Gunjikar 	init_genlist(&uctxt->cq_list);
2728c39526b7SPramod Gunjikar 	init_genlist(&uctxt->srq_list);
2729c39526b7SPramod Gunjikar 	init_genlist(&uctxt->qp_list);
2730c39526b7SPramod Gunjikar 	init_genlist(&uctxt->ah_list);
2731c39526b7SPramod Gunjikar 
2732c39526b7SPramod Gunjikar 	/* Return with uobj uo_lock held for WRITTER. */
2733c39526b7SPramod Gunjikar 	return (uctxt);
2734c39526b7SPramod Gunjikar }
2735c39526b7SPramod Gunjikar 
2736c39526b7SPramod Gunjikar /*
2737c39526b7SPramod Gunjikar  * Function:
2738c39526b7SPramod Gunjikar  *	sol_uverbs_qpnum2uqpid
2739c39526b7SPramod Gunjikar  * Input:
2740c39526b7SPramod Gunjikar  *	qp_num	- used to find the user object that mapped to this qp_num
2741c39526b7SPramod Gunjikar  * Output:
2742c39526b7SPramod Gunjikar  *	None
2743c39526b7SPramod Gunjikar  * Returns:
2744c39526b7SPramod Gunjikar  *	DDI_FAILURE if not found else
2745c39526b7SPramod Gunjikar  *	the uo_id in the user object that matches the qp_num
2746c39526b7SPramod Gunjikar  * Description:
2747c39526b7SPramod Gunjikar  * 	Find the uo_id of the user object which mapped to the input qp_num
2748c39526b7SPramod Gunjikar  */
2749c39526b7SPramod Gunjikar uint32_t
sol_uverbs_qpnum2uqpid(uint32_t qp_num)2750c39526b7SPramod Gunjikar sol_uverbs_qpnum2uqpid(uint32_t qp_num)
2751c39526b7SPramod Gunjikar {
2752c39526b7SPramod Gunjikar 	sol_ofs_uobj_table_t	*uo_tbl;
2753c39526b7SPramod Gunjikar 	sol_ofs_uobj_t		*uobj;
2754c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t	*uqp;
2755c39526b7SPramod Gunjikar 	int			i, j;
2756c39526b7SPramod Gunjikar 	sol_ofs_uobj_blk_t	*blk;
2757c39526b7SPramod Gunjikar 
2758c39526b7SPramod Gunjikar 	uo_tbl = &uverbs_uqp_uo_tbl;
2759c39526b7SPramod Gunjikar 	rw_enter(&uo_tbl->uobj_tbl_lock, RW_READER);
2760c39526b7SPramod Gunjikar 
2761c39526b7SPramod Gunjikar 	/*
2762c39526b7SPramod Gunjikar 	 * Try to find an empty slot for the new user object.
2763c39526b7SPramod Gunjikar 	 */
2764c39526b7SPramod Gunjikar 	for (i = 0; i < uo_tbl->uobj_tbl_used_blks; i++) {
2765c39526b7SPramod Gunjikar 		blk = uo_tbl->uobj_tbl_uo_root[i];
2766c39526b7SPramod Gunjikar 		if (blk != NULL) {
2767c39526b7SPramod Gunjikar 			for (j = 0; j < SOL_OFS_UO_BLKSZ; j++) {
2768c39526b7SPramod Gunjikar 				if ((uobj = blk->ofs_uoblk_blks[j]) != NULL) {
2769c39526b7SPramod Gunjikar 					uqp = (uverbs_uqp_uobj_t *)uobj;
2770c39526b7SPramod Gunjikar 					if (uqp->qp_num == qp_num) {
2771c39526b7SPramod Gunjikar 						rw_exit(&uo_tbl->uobj_tbl_lock);
2772c39526b7SPramod Gunjikar 						SOL_OFS_DPRINTF_L5(
2773c39526b7SPramod Gunjikar 						    sol_uverbs_dbg_str,
2774c39526b7SPramod Gunjikar 						    "qpnum2uqpid(%x) ret %x",
2775c39526b7SPramod Gunjikar 						    qp_num, uobj->uo_id);
2776c39526b7SPramod Gunjikar 						return (uobj->uo_id);
2777c39526b7SPramod Gunjikar 					}
2778c39526b7SPramod Gunjikar 				}
2779c39526b7SPramod Gunjikar 			}
2780c39526b7SPramod Gunjikar 		}
2781c39526b7SPramod Gunjikar 	}
2782c39526b7SPramod Gunjikar 
2783c39526b7SPramod Gunjikar 	rw_exit(&uo_tbl->uobj_tbl_lock);
2784c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qpnum2uqpid(%x) ret %x",
2785c39526b7SPramod Gunjikar 	    qp_num, DDI_FAILURE);
2786c39526b7SPramod Gunjikar 	return (DDI_FAILURE);
2787c39526b7SPramod Gunjikar }
2788c39526b7SPramod Gunjikar 
2789c39526b7SPramod Gunjikar void
sol_uverbs_get_clnt_hdl(void ** ibclnt_hdl,void ** iwclnt_hdl)2790c39526b7SPramod Gunjikar sol_uverbs_get_clnt_hdl(void **ibclnt_hdl, void **iwclnt_hdl)
2791c39526b7SPramod Gunjikar {
2792c39526b7SPramod Gunjikar 	*ibclnt_hdl = sol_uverbs_ib_clntp;
2793c39526b7SPramod Gunjikar 	*iwclnt_hdl = NULL;
2794c39526b7SPramod Gunjikar }
2795c39526b7SPramod Gunjikar 
2796c39526b7SPramod Gunjikar void *
sol_uverbs_qpnum2qphdl(uint32_t qpnum)2797c39526b7SPramod Gunjikar sol_uverbs_qpnum2qphdl(uint32_t qpnum)
2798c39526b7SPramod Gunjikar {
2799c39526b7SPramod Gunjikar 	int32_t	uqpid;
2800c39526b7SPramod Gunjikar 
2801c39526b7SPramod Gunjikar 	uqpid = sol_uverbs_qpnum2uqpid(qpnum);
2802c39526b7SPramod Gunjikar 	if (uqpid == DDI_FAILURE)
2803c39526b7SPramod Gunjikar 		return (NULL);
2804c39526b7SPramod Gunjikar 	return (sol_uverbs_uqpid_to_ibt_handle(uqpid));
2805c39526b7SPramod Gunjikar }
2806c39526b7SPramod Gunjikar 
2807c39526b7SPramod Gunjikar int
sol_uverbs_disable_uqpn_modify(uint32_t qpnum)2808c39526b7SPramod Gunjikar sol_uverbs_disable_uqpn_modify(uint32_t qpnum)
2809c39526b7SPramod Gunjikar {
2810c39526b7SPramod Gunjikar 	int32_t	uqpid;
2811c39526b7SPramod Gunjikar 
2812c39526b7SPramod Gunjikar 	uqpid = sol_uverbs_qpnum2uqpid(qpnum);
2813c39526b7SPramod Gunjikar 	if (uqpid == DDI_FAILURE)
2814c39526b7SPramod Gunjikar 		return (-1);
2815c39526b7SPramod Gunjikar 
2816c39526b7SPramod Gunjikar 	return (sol_uverbs_disable_user_qp_modify(uqpid));
2817c39526b7SPramod Gunjikar }
2818c39526b7SPramod Gunjikar 
2819c39526b7SPramod Gunjikar extern int uverbs_uqpn_cq_ctrl(uint32_t, sol_uverbs_cq_ctrl_t);
2820c39526b7SPramod Gunjikar 
2821c39526b7SPramod Gunjikar int
sol_uverbs_uqpn_cq_ctrl(uint32_t qpnum,sol_uverbs_cq_ctrl_t ctrl)2822c39526b7SPramod Gunjikar sol_uverbs_uqpn_cq_ctrl(uint32_t qpnum, sol_uverbs_cq_ctrl_t ctrl)
2823c39526b7SPramod Gunjikar {
2824c39526b7SPramod Gunjikar 	int32_t	uqpid;
2825c39526b7SPramod Gunjikar 
2826c39526b7SPramod Gunjikar 	uqpid = sol_uverbs_qpnum2uqpid(qpnum);
2827c39526b7SPramod Gunjikar 	if (uqpid == DDI_FAILURE)
2828c39526b7SPramod Gunjikar 		return (-1);
2829c39526b7SPramod Gunjikar 
2830c39526b7SPramod Gunjikar 	return (uverbs_uqpn_cq_ctrl(uqpid, ctrl));
2831c39526b7SPramod Gunjikar }
2832c39526b7SPramod Gunjikar 
2833c39526b7SPramod Gunjikar void
sol_uverbs_set_qp_free_state(sol_uverbs_qp_free_state_t qp_free_state,uint32_t qpnum,void * qphdl)2834c39526b7SPramod Gunjikar sol_uverbs_set_qp_free_state(sol_uverbs_qp_free_state_t qp_free_state,
2835c39526b7SPramod Gunjikar     uint32_t qpnum, void *qphdl)
2836c39526b7SPramod Gunjikar {
2837c39526b7SPramod Gunjikar 	int32_t			uqpid;
2838c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t	*uqp;
2839c39526b7SPramod Gunjikar 
2840c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2841c39526b7SPramod Gunjikar 	    "sol_uverbs_set_qp_free_state(%x, %x, %p)",
2842c39526b7SPramod Gunjikar 	    qp_free_state, qpnum, qphdl);
2843c39526b7SPramod Gunjikar 	if (qp_free_state == SOL_UVERBS2UCMA_DISABLE_QP_FREE) {
2844c39526b7SPramod Gunjikar 		uqpid = sol_uverbs_qpnum2uqpid(qpnum);
2845c39526b7SPramod Gunjikar 		if (uqpid == DDI_FAILURE) {
2846c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2847c39526b7SPramod Gunjikar 			    "set_qp_free_state(%d)-invalid qpnum",
2848c39526b7SPramod Gunjikar 			    qpnum);
2849c39526b7SPramod Gunjikar 			return;
2850c39526b7SPramod Gunjikar 		}
2851c39526b7SPramod Gunjikar 
2852c39526b7SPramod Gunjikar 		uqp = uverbs_uobj_get_uqp_write(uqpid);
2853c39526b7SPramod Gunjikar 		if (uqp == NULL) {
2854c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2855c39526b7SPramod Gunjikar 			    "set_qp_free_state(%d)-uqp lookup failure", qpnum);
2856c39526b7SPramod Gunjikar 			return;
2857c39526b7SPramod Gunjikar 		}
2858c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2859c39526b7SPramod Gunjikar 		    "set_qp_free_state : uqp %p, setting Disable QP Free", uqp);
2860c39526b7SPramod Gunjikar 		uqp->uqp_free_state  = SOL_UVERBS2UCMA_DISABLE_QP_FREE;
2861c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uqp->uobj);
2862c39526b7SPramod Gunjikar 		return;
2863c39526b7SPramod Gunjikar 	}
2864c39526b7SPramod Gunjikar 
2865c39526b7SPramod Gunjikar 	ASSERT(qphdl);
2866c39526b7SPramod Gunjikar 	uqp = (uverbs_uqp_uobj_t *)ibt_get_qp_private((ibt_qp_hdl_t)qphdl);
2867c39526b7SPramod Gunjikar 	ASSERT(uqp);
2868c39526b7SPramod Gunjikar 	if (uqp->uqp_free_state != SOL_UVERBS2UCMA_FREE_PENDING) {
2869c39526b7SPramod Gunjikar 		/*
2870c39526b7SPramod Gunjikar 		 * Enable free flag, so that close or userland free_qp
2871c39526b7SPramod Gunjikar 		 * call can free this in the future.
2872c39526b7SPramod Gunjikar 		 */
2873c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2874c39526b7SPramod Gunjikar 		    "set_qp_free_state : uqp %p, setting Enable QP Free",
2875c39526b7SPramod Gunjikar 		    uqp);
2876c39526b7SPramod Gunjikar 		rw_enter(&(uqp->uobj.uo_lock), RW_WRITER);
2877c39526b7SPramod Gunjikar 		uqp->uqp_free_state = SOL_UVERBS2UCMA_ENABLE_QP_FREE;
2878c39526b7SPramod Gunjikar 		rw_exit(&(uqp->uobj.uo_lock));
2879c39526b7SPramod Gunjikar 	} else {
2880c39526b7SPramod Gunjikar 		/*
2881c39526b7SPramod Gunjikar 		 * uqp_free_state is set to FREE_PENDING, QP has been freed
2882c39526b7SPramod Gunjikar 		 * by userland. Call uverbs_uqp_free() to free this.
2883c39526b7SPramod Gunjikar 		 */
2884c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2885c39526b7SPramod Gunjikar 		    "set_qp_free_state : uqp %p calling uverbs_uqp_free()",
2886c39526b7SPramod Gunjikar 		    uqp);
2887c39526b7SPramod Gunjikar 		rw_enter(&(uqp->uobj.uo_lock), RW_WRITER);
2888c39526b7SPramod Gunjikar 		sol_ofs_uobj_ref(&uqp->uobj);
2889c39526b7SPramod Gunjikar 		if (uverbs_uqp_free(uqp, uqp->uctxt))
2890c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2891c39526b7SPramod Gunjikar 			    "set_qp_free_state : uverbs_uqp_free(%p) failed",
2892c39526b7SPramod Gunjikar 			    uqp);
2893c39526b7SPramod Gunjikar 	}
2894c39526b7SPramod Gunjikar }
2895c39526b7SPramod Gunjikar 
2896c39526b7SPramod Gunjikar /*
2897c39526b7SPramod Gunjikar  * Function:
2898c39526b7SPramod Gunjikar  *	sol_uverbs_user_objects_init
2899c39526b7SPramod Gunjikar  * Input:
2900c39526b7SPramod Gunjikar  *	None
2901c39526b7SPramod Gunjikar  * Output:
2902c39526b7SPramod Gunjikar  *	None
2903c39526b7SPramod Gunjikar  * Returns:
2904c39526b7SPramod Gunjikar  *	None
2905c39526b7SPramod Gunjikar  * Description:
2906c39526b7SPramod Gunjikar  * 	Initializes all of the user object resource managment tables.
2907c39526b7SPramod Gunjikar  */
sol_uverbs_user_objects_init()2908c39526b7SPramod Gunjikar static void sol_uverbs_user_objects_init()
2909c39526b7SPramod Gunjikar {
2910c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&uverbs_uctxt_uo_tbl,
2911c39526b7SPramod Gunjikar 	    sizeof (uverbs_uctxt_uobj_t));
2912c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&uverbs_upd_uo_tbl,
2913c39526b7SPramod Gunjikar 	    sizeof (uverbs_upd_uobj_t));
2914c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&uverbs_umr_uo_tbl,
2915c39526b7SPramod Gunjikar 	    sizeof (uverbs_umr_uobj_t));
2916c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&uverbs_ucq_uo_tbl,
2917c39526b7SPramod Gunjikar 	    sizeof (uverbs_ucq_uobj_t));
2918c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&uverbs_usrq_uo_tbl,
2919c39526b7SPramod Gunjikar 	    sizeof (uverbs_usrq_uobj_t));
2920c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&uverbs_uqp_uo_tbl,
2921c39526b7SPramod Gunjikar 	    sizeof (uverbs_uqp_uobj_t));
2922c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&uverbs_uah_uo_tbl,
2923c39526b7SPramod Gunjikar 	    sizeof (uverbs_uah_uobj_t));
2924c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_init(&uverbs_ufile_uo_tbl,
2925c39526b7SPramod Gunjikar 	    sizeof (uverbs_ufile_uobj_t));
2926c39526b7SPramod Gunjikar }
2927c39526b7SPramod Gunjikar 
2928c39526b7SPramod Gunjikar /*
2929c39526b7SPramod Gunjikar  * Function:
2930c39526b7SPramod Gunjikar  *	sol_uverbs_user_objects_fini
2931c39526b7SPramod Gunjikar  * Input:
2932c39526b7SPramod Gunjikar  *	None
2933c39526b7SPramod Gunjikar  * Output:
2934c39526b7SPramod Gunjikar  *	None
2935c39526b7SPramod Gunjikar  * Returns:
2936c39526b7SPramod Gunjikar  *	None
2937c39526b7SPramod Gunjikar  * Description:
2938c39526b7SPramod Gunjikar  * 	Releases all of the user object resource managment tables.
2939c39526b7SPramod Gunjikar  */
sol_uverbs_user_objects_fini()2940c39526b7SPramod Gunjikar static void sol_uverbs_user_objects_fini()
2941c39526b7SPramod Gunjikar {
2942c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&uverbs_ufile_uo_tbl);
2943c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&uverbs_uah_uo_tbl);
2944c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&uverbs_uqp_uo_tbl);
2945c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&uverbs_usrq_uo_tbl);
2946c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&uverbs_ucq_uo_tbl);
2947c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&uverbs_umr_uo_tbl);
2948c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&uverbs_upd_uo_tbl);
2949c39526b7SPramod Gunjikar 	sol_ofs_uobj_tbl_fini(&uverbs_uctxt_uo_tbl);
2950c39526b7SPramod Gunjikar }
2951c39526b7SPramod Gunjikar 
2952c39526b7SPramod Gunjikar /*
2953c39526b7SPramod Gunjikar  * Function:
2954c39526b7SPramod Gunjikar  *	sol_uverbs_ibt_to_kernel_status
2955c39526b7SPramod Gunjikar  * Input:
2956c39526b7SPramod Gunjikar  *	status	- An IBT status code.
2957c39526b7SPramod Gunjikar  * Output:
2958c39526b7SPramod Gunjikar  *	None
2959c39526b7SPramod Gunjikar  * Returns:
2960c39526b7SPramod Gunjikar  *	The "errno" based kernel error code the IBT status maps to.
2961c39526b7SPramod Gunjikar  * Description:
2962c39526b7SPramod Gunjikar  * 	Map an IBT status to the "errno" code that should be returned.
2963c39526b7SPramod Gunjikar  */
2964c39526b7SPramod Gunjikar int
sol_uverbs_ibt_to_kernel_status(ibt_status_t status)2965c39526b7SPramod Gunjikar sol_uverbs_ibt_to_kernel_status(ibt_status_t status)
2966c39526b7SPramod Gunjikar {
2967c39526b7SPramod Gunjikar 	int err;
2968c39526b7SPramod Gunjikar 
2969c39526b7SPramod Gunjikar 	switch (status) {
2970c39526b7SPramod Gunjikar 		case IBT_NOT_SUPPORTED:
2971c39526b7SPramod Gunjikar 			err = ENOTSUP;
2972c39526b7SPramod Gunjikar 			break;
2973c39526b7SPramod Gunjikar 
2974c39526b7SPramod Gunjikar 		case IBT_ILLEGAL_OP:
2975c39526b7SPramod Gunjikar 		case IBT_INVALID_PARAM:
2976c39526b7SPramod Gunjikar 			err = EINVAL;
2977c39526b7SPramod Gunjikar 			break;
2978c39526b7SPramod Gunjikar 
2979c39526b7SPramod Gunjikar 		case IBT_HCA_IN_USE:
2980c39526b7SPramod Gunjikar 		case IBT_HCA_BUSY_DETACHING:
2981c39526b7SPramod Gunjikar 		case IBT_HCA_BUSY_CLOSING:
2982c39526b7SPramod Gunjikar 		case IBT_CHAN_IN_USE:
2983c39526b7SPramod Gunjikar 		case IBT_CQ_BUSY:
2984c39526b7SPramod Gunjikar 		case IBT_MR_IN_USE:
2985c39526b7SPramod Gunjikar 		case IBT_PD_IN_USE:
2986c39526b7SPramod Gunjikar 		case IBT_SRQ_IN_USE:
2987c39526b7SPramod Gunjikar 			err = EBUSY;
2988c39526b7SPramod Gunjikar 			break;
2989c39526b7SPramod Gunjikar 		case	IBT_INSUFF_RESOURCE:
2990c39526b7SPramod Gunjikar 		case	IBT_INSUFF_KERNEL_RESOURCE:
2991c39526b7SPramod Gunjikar 		case	IBT_HCA_WR_EXCEEDED:
2992c39526b7SPramod Gunjikar 		case	IBT_HCA_SGL_EXCEEDED:
2993c39526b7SPramod Gunjikar 			err = ENOMEM;
2994c39526b7SPramod Gunjikar 			break;
2995c39526b7SPramod Gunjikar 
2996c39526b7SPramod Gunjikar 		default:
2997c39526b7SPramod Gunjikar 			err = EINVAL;
2998c39526b7SPramod Gunjikar 	}
2999c39526b7SPramod Gunjikar 	return (err);
3000c39526b7SPramod Gunjikar }
3001c39526b7SPramod Gunjikar 
3002c39526b7SPramod Gunjikar /* ARGSUSED */
3003c39526b7SPramod Gunjikar uint32_t
sol_uverbs_ibt_to_of_device_cap_flags(ibt_hca_flags_t flags,ibt_hca_flags2_t flags2)3004c39526b7SPramod Gunjikar sol_uverbs_ibt_to_of_device_cap_flags(ibt_hca_flags_t flags,
3005c39526b7SPramod Gunjikar     ibt_hca_flags2_t flags2) {
3006c39526b7SPramod Gunjikar 
3007c39526b7SPramod Gunjikar 	uint32_t of_flags = 0;
3008c39526b7SPramod Gunjikar 
3009c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_RESIZE_CHAN)
3010c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_RESIZE_MAX_WR;
3011c39526b7SPramod Gunjikar 
3012c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_PKEY_CNTR)
3013c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_BAD_PKEY_CNTR;
3014c39526b7SPramod Gunjikar 
3015c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_QKEY_CNTR)
3016c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_BAD_QKEY_CNTR;
3017c39526b7SPramod Gunjikar 
3018c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_RAW_MULTICAST)
3019c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_RAW_MULTI;
3020c39526b7SPramod Gunjikar 
3021c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_AUTO_PATH_MIG)
3022c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_AUTO_PATH_MIG;
3023c39526b7SPramod Gunjikar 
3024c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_SQD_SQD_PORT)
3025c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_CHANGE_PHY_PORT;
3026c39526b7SPramod Gunjikar 
3027c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_AH_PORT_CHECK)
3028c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
3029c39526b7SPramod Gunjikar 
3030c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_CURRENT_QP_STATE)
3031c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_CURR_QP_STATE_MOD;
3032c39526b7SPramod Gunjikar 
3033c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_SHUTDOWN_PORT)
3034c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_SHUTDOWN_PORT;
3035c39526b7SPramod Gunjikar 
3036c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_INIT_TYPE)
3037c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_INIT_TYPE;
3038c39526b7SPramod Gunjikar 
3039c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_PORT_UP)
3040c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_PORT_ACTIVE_EVENT;
3041c39526b7SPramod Gunjikar 
3042c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_SI_GUID)
3043c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_SYS_IMAGE_GUID;
3044c39526b7SPramod Gunjikar 
3045c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_RNR_NAK)
3046c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_RC_RNR_NAK_GEN;
3047c39526b7SPramod Gunjikar 
3048c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_RESIZE_SRQ)
3049c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_SRQ_RESIZE;
3050c39526b7SPramod Gunjikar 
3051c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_BASE_QUEUE_MGT)
3052c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_N_NOTIFY_CQ;
3053c39526b7SPramod Gunjikar 
3054c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_ZERO_BASED_VA)
3055c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_ZERO_STAG;
3056c39526b7SPramod Gunjikar 
3057c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_LOCAL_INVAL_FENCE)
3058c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_SEND_W_INV;
3059c39526b7SPramod Gunjikar 
3060c39526b7SPramod Gunjikar 	if (flags && IBT_HCA_MEM_WIN_TYPE_2B)
3061c39526b7SPramod Gunjikar 		of_flags |= IB_DEVICE_MEM_WINDOW;
3062c39526b7SPramod Gunjikar 
3063c39526b7SPramod Gunjikar 	return (of_flags);
3064c39526b7SPramod Gunjikar }
3065c39526b7SPramod Gunjikar 
3066c39526b7SPramod Gunjikar uint64_t
sol_uverbs_ibt_to_of_page_sz(ibt_page_sizes_t page_szs)3067c39526b7SPramod Gunjikar sol_uverbs_ibt_to_of_page_sz(ibt_page_sizes_t page_szs)
3068c39526b7SPramod Gunjikar {
3069c39526b7SPramod Gunjikar 
3070c39526b7SPramod Gunjikar 	uint64_t of_page_sz = 0;
3071c39526b7SPramod Gunjikar 
3072c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_4K)
3073c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 12;
3074c39526b7SPramod Gunjikar 
3075c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_8K)
3076c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 13;
3077c39526b7SPramod Gunjikar 
3078c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_16K)
3079c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 14;
3080c39526b7SPramod Gunjikar 
3081c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_32K)
3082c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 15;
3083c39526b7SPramod Gunjikar 
3084c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_64K)
3085c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 16;
3086c39526b7SPramod Gunjikar 
3087c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_128K)
3088c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 17;
3089c39526b7SPramod Gunjikar 
3090c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_256K)
3091c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 18;
3092c39526b7SPramod Gunjikar 
3093c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_512K)
3094c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 19;
3095c39526b7SPramod Gunjikar 
3096c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_1M)
3097c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 20;
3098c39526b7SPramod Gunjikar 
3099c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_2M)
3100c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 21;
3101c39526b7SPramod Gunjikar 
3102c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_4M)
3103c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 22;
3104c39526b7SPramod Gunjikar 
3105c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_8M)
3106c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 23;
3107c39526b7SPramod Gunjikar 
3108c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_16M)
3109c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 24;
3110c39526b7SPramod Gunjikar 
3111c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_32M)
3112c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 25;
3113c39526b7SPramod Gunjikar 
3114c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_64M)
3115c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 26;
3116c39526b7SPramod Gunjikar 
3117c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_128M)
3118c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 27;
3119c39526b7SPramod Gunjikar 
3120c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_256M)
3121c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 28;
3122c39526b7SPramod Gunjikar 
3123c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_512M)
3124c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 29;
3125c39526b7SPramod Gunjikar 
3126c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_1G)
3127c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 30;
3128c39526b7SPramod Gunjikar 
3129c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_2G)
3130c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 31;
3131c39526b7SPramod Gunjikar 
3132c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_4G)
3133c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 32;
3134c39526b7SPramod Gunjikar 
3135c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_8G)
3136c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 33;
3137c39526b7SPramod Gunjikar 
3138c39526b7SPramod Gunjikar 	if (page_szs && IBT_PAGE_16G)
3139c39526b7SPramod Gunjikar 		of_page_sz |= 1LL << 34;
3140c39526b7SPramod Gunjikar 
3141c39526b7SPramod Gunjikar 	return (of_page_sz);
3142c39526b7SPramod Gunjikar }
3143