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