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  * sol_uverbs_qp.c
27c39526b7SPramod Gunjikar  *
28c39526b7SPramod Gunjikar  * OFED User Verbs kernel agent QP implementation.
29c39526b7SPramod Gunjikar  *
30c39526b7SPramod Gunjikar  */
31c39526b7SPramod Gunjikar #include <sys/vfs.h>
32c39526b7SPramod Gunjikar #include <sys/vnode.h>
33c39526b7SPramod Gunjikar #include <sys/errno.h>
34c39526b7SPramod Gunjikar #include <sys/cred.h>
35c39526b7SPramod Gunjikar #include <sys/uio.h>
36c39526b7SPramod Gunjikar #include <sys/semaphore.h>
37c39526b7SPramod Gunjikar #include <sys/ddi.h>
38c39526b7SPramod Gunjikar #include <sys/sunddi.h>
39c39526b7SPramod Gunjikar 
40c39526b7SPramod Gunjikar #include <sys/ib/ibtl/ibvti.h>
41c39526b7SPramod Gunjikar #include <sys/ib/clients/of/ofa_solaris.h>
42c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
43c39526b7SPramod Gunjikar #include <sys/ib/clients/of/ofed_kernel.h>
44c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs.h>
45c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_qp.h>
46c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_event.h>
47c39526b7SPramod Gunjikar 
48c39526b7SPramod Gunjikar 
49c39526b7SPramod Gunjikar static uint32_t	ibt_cep_flags2ibv(ibt_cep_flags_t);
50c39526b7SPramod Gunjikar static void	uverbs_cq_ctrl(uverbs_ucq_uobj_t *, sol_uverbs_cq_ctrl_t);
51c39526b7SPramod Gunjikar 
52c39526b7SPramod Gunjikar extern char	*sol_uverbs_dbg_str;
53c39526b7SPramod Gunjikar 
54c39526b7SPramod Gunjikar /*
55c39526b7SPramod Gunjikar  * Multicast Element
56c39526b7SPramod Gunjikar  */
57c39526b7SPramod Gunjikar typedef struct uverbs_mcast_entry {
58c39526b7SPramod Gunjikar 	llist_head_t	list;
59c39526b7SPramod Gunjikar 	ibt_mcg_info_t	mcg;
60c39526b7SPramod Gunjikar } uverbs_mcast_entry_t;
61c39526b7SPramod Gunjikar 
62c39526b7SPramod Gunjikar /*
63c39526b7SPramod Gunjikar  * uverbs_qp_state_table
64c39526b7SPramod Gunjikar  *
65c39526b7SPramod Gunjikar  * Determine if the requested QP modify operation is valid.  To maintain/ensure
66c39526b7SPramod Gunjikar  * consistency with the semantics expected by OFED user verbs operaton, this
67c39526b7SPramod Gunjikar  * table is used to verify a QP transition.  A valid transition is one that is
68c39526b7SPramod Gunjikar  * a legal state transition and meets the required/optional attributes
69c39526b7SPramod Gunjikar  * associated with that transition for that QP type.
70c39526b7SPramod Gunjikar  *
71c39526b7SPramod Gunjikar  * Note: The OFED kern-abi (See ib_user_verbs.h) does not provide any
72c39526b7SPramod Gunjikar  * mechanism to support queue resize, consequently the IBTA spec defined
73c39526b7SPramod Gunjikar  * valid optional parameter to modify QP size (IB_QP_CAP) is not included
74c39526b7SPramod Gunjikar  * in the state table.
75c39526b7SPramod Gunjikar  */
76c39526b7SPramod Gunjikar typedef struct {
77c39526b7SPramod Gunjikar 	int			valid;
78c39526b7SPramod Gunjikar 	enum ib_qp_attr_mask	req_param[IB_QPT_RAW_ETY + 1];
79c39526b7SPramod Gunjikar 	enum ib_qp_attr_mask	opt_param[IB_QPT_RAW_ETY + 1];
80c39526b7SPramod Gunjikar } uverbs_qp_state_tbl_t;
81c39526b7SPramod Gunjikar 
82c39526b7SPramod Gunjikar static uverbs_qp_state_tbl_t
83c39526b7SPramod Gunjikar uverbs_qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
84c39526b7SPramod Gunjikar 	[IB_QPS_RESET] = {
85c39526b7SPramod Gunjikar 		[IB_QPS_RESET] = { .valid = 1 },
86c39526b7SPramod Gunjikar 		[IB_QPS_ERR]   = { .valid = 1 },
87c39526b7SPramod Gunjikar 		[IB_QPS_INIT]  = { .valid = 1,
88c39526b7SPramod Gunjikar 			.req_param = {
89c39526b7SPramod Gunjikar 				[IB_QPT_UD] = (IB_QP_PKEY_INDEX |
90c39526b7SPramod Gunjikar 						IB_QP_PORT | IB_QP_QKEY),
91c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
92c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS),
93c39526b7SPramod Gunjikar 				[IB_QPT_RC] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
94c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS),
95c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
96c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
97c39526b7SPramod Gunjikar 			}
98c39526b7SPramod Gunjikar 		},
99c39526b7SPramod Gunjikar 	},
100c39526b7SPramod Gunjikar 	[IB_QPS_INIT]  = {
101c39526b7SPramod Gunjikar 		[IB_QPS_RESET] = { .valid = 1 },
102c39526b7SPramod Gunjikar 		[IB_QPS_ERR] =   { .valid = 1 },
103c39526b7SPramod Gunjikar 		[IB_QPS_INIT]  = { .valid = 1,
104c39526b7SPramod Gunjikar 			.opt_param = {
105c39526b7SPramod Gunjikar 				[IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
106c39526b7SPramod Gunjikar 						IB_QP_QKEY),
107c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
108c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS),
109c39526b7SPramod Gunjikar 				[IB_QPT_RC] = (IB_QP_PKEY_INDEX | IB_QP_PORT |
110c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS),
111c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
112c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
113c39526b7SPramod Gunjikar 			}
114c39526b7SPramod Gunjikar 		},
115c39526b7SPramod Gunjikar 		[IB_QPS_RTR] = { .valid = 1,
116c39526b7SPramod Gunjikar 			.req_param = {
117c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_AV | IB_QP_PATH_MTU |
118c39526b7SPramod Gunjikar 						IB_QP_DEST_QPN | IB_QP_RQ_PSN),
119c39526b7SPramod Gunjikar 				[IB_QPT_RC] = (IB_QP_AV | IB_QP_PATH_MTU |
120c39526b7SPramod Gunjikar 						IB_QP_DEST_QPN | IB_QP_RQ_PSN |
121c39526b7SPramod Gunjikar 						IB_QP_MAX_DEST_RD_ATOMIC |
122c39526b7SPramod Gunjikar 						IB_QP_MIN_RNR_TIMER),
123c39526b7SPramod Gunjikar 			},
124c39526b7SPramod Gunjikar 			.opt_param = {
125c39526b7SPramod Gunjikar 				[IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
126c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_ALT_PATH |
127c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
128c39526b7SPramod Gunjikar 						IB_QP_PKEY_INDEX),
129c39526b7SPramod Gunjikar 				[IB_QPT_RC] = (IB_QP_ALT_PATH |
130c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
131c39526b7SPramod Gunjikar 						IB_QP_PKEY_INDEX),
132c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
133c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
134c39526b7SPramod Gunjikar 			}
135c39526b7SPramod Gunjikar 		}
136c39526b7SPramod Gunjikar 	},
137c39526b7SPramod Gunjikar 	[IB_QPS_RTR] = {
138c39526b7SPramod Gunjikar 		[IB_QPS_RESET] = { .valid = 1 },
139c39526b7SPramod Gunjikar 		[IB_QPS_ERR] = { .valid = 1 },
140c39526b7SPramod Gunjikar 		[IB_QPS_RTS] = { .valid = 1,
141c39526b7SPramod Gunjikar 			.req_param = {
142c39526b7SPramod Gunjikar 				[IB_QPT_UD] = IB_QP_SQ_PSN,
143c39526b7SPramod Gunjikar 				[IB_QPT_UC] = IB_QP_SQ_PSN,
144c39526b7SPramod Gunjikar 				[IB_QPT_RC] = (IB_QP_TIMEOUT |
145c39526b7SPramod Gunjikar 						IB_QP_RETRY_CNT |
146c39526b7SPramod Gunjikar 						IB_QP_RNR_RETRY |
147c39526b7SPramod Gunjikar 						IB_QP_SQ_PSN |
148c39526b7SPramod Gunjikar 						IB_QP_MAX_QP_RD_ATOMIC),
149c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = IB_QP_SQ_PSN,
150c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = IB_QP_SQ_PSN,
151c39526b7SPramod Gunjikar 			},
152c39526b7SPramod Gunjikar 			.opt_param = {
153c39526b7SPramod Gunjikar 				[IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY),
154c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_CUR_STATE |
155c39526b7SPramod Gunjikar 						IB_QP_ALT_PATH |
156c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
157c39526b7SPramod Gunjikar 						IB_QP_PATH_MIG_STATE),
158c39526b7SPramod Gunjikar 				[IB_QPT_RC] = (IB_QP_CUR_STATE |
159c39526b7SPramod Gunjikar 						IB_QP_ALT_PATH |
160c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
161c39526b7SPramod Gunjikar 						IB_QP_MIN_RNR_TIMER |
162c39526b7SPramod Gunjikar 						IB_QP_PATH_MIG_STATE),
163c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
164c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
165c39526b7SPramod Gunjikar 			}
166c39526b7SPramod Gunjikar 		}
167c39526b7SPramod Gunjikar 	},
168c39526b7SPramod Gunjikar 	[IB_QPS_RTS] = {
169c39526b7SPramod Gunjikar 		[IB_QPS_RESET] = { .valid = 1 },
170c39526b7SPramod Gunjikar 		[IB_QPS_ERR] = { .valid = 1 },
171c39526b7SPramod Gunjikar 		[IB_QPS_RTS] = { .valid = 1,
172c39526b7SPramod Gunjikar 			.opt_param = {
173c39526b7SPramod Gunjikar 				[IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY),
174c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_CUR_STATE |
175c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
176c39526b7SPramod Gunjikar 						IB_QP_ALT_PATH |
177c39526b7SPramod Gunjikar 						IB_QP_PATH_MIG_STATE),
178c39526b7SPramod Gunjikar 				[IB_QPT_RC] = (IB_QP_CUR_STATE |
179c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
180c39526b7SPramod Gunjikar 						IB_QP_ALT_PATH |
181c39526b7SPramod Gunjikar 						IB_QP_PATH_MIG_STATE |
182c39526b7SPramod Gunjikar 						IB_QP_MIN_RNR_TIMER),
183c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
184c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
185c39526b7SPramod Gunjikar 			}
186c39526b7SPramod Gunjikar 		},
187c39526b7SPramod Gunjikar 		[IB_QPS_SQD] = { .valid = 1,
188c39526b7SPramod Gunjikar 			.opt_param = {
189c39526b7SPramod Gunjikar 				[IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY,
190c39526b7SPramod Gunjikar 				[IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
191c39526b7SPramod Gunjikar 				[IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
192c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
193c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
194c39526b7SPramod Gunjikar 			}
195c39526b7SPramod Gunjikar 		},
196c39526b7SPramod Gunjikar 	},
197c39526b7SPramod Gunjikar 	[IB_QPS_SQD] = {
198c39526b7SPramod Gunjikar 		[IB_QPS_RESET] = { .valid = 1 },
199c39526b7SPramod Gunjikar 		[IB_QPS_ERR] =  { .valid = 1 },
200c39526b7SPramod Gunjikar 		[IB_QPS_RTS] = { .valid = 1,
201c39526b7SPramod Gunjikar 			.opt_param = {
202c39526b7SPramod Gunjikar 				[IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY),
203c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_CUR_STATE |
204c39526b7SPramod Gunjikar 						IB_QP_ALT_PATH |
205c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
206c39526b7SPramod Gunjikar 						IB_QP_PATH_MIG_STATE),
207c39526b7SPramod Gunjikar 				[IB_QPT_RC] = (IB_QP_CUR_STATE |
208c39526b7SPramod Gunjikar 						IB_QP_ALT_PATH  |
209c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
210c39526b7SPramod Gunjikar 						IB_QP_MIN_RNR_TIMER |
211c39526b7SPramod Gunjikar 						IB_QP_PATH_MIG_STATE),
212c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
213c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
214c39526b7SPramod Gunjikar 			}
215c39526b7SPramod Gunjikar 		},
216c39526b7SPramod Gunjikar 		[IB_QPS_SQD] = { .valid = 1,
217c39526b7SPramod Gunjikar 			.opt_param = {
218c39526b7SPramod Gunjikar 				[IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
219c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_AV | IB_QP_ALT_PATH |
220c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
221c39526b7SPramod Gunjikar 						IB_QP_PKEY_INDEX |
222c39526b7SPramod Gunjikar 						IB_QP_PATH_MIG_STATE),
223c39526b7SPramod Gunjikar 				[IB_QPT_RC]  = (IB_QP_PORT | IB_QP_AV |
224c39526b7SPramod Gunjikar 						IB_QP_TIMEOUT |
225c39526b7SPramod Gunjikar 						IB_QP_RETRY_CNT |
226c39526b7SPramod Gunjikar 						IB_QP_RNR_RETRY |
227c39526b7SPramod Gunjikar 						IB_QP_MAX_QP_RD_ATOMIC |
228c39526b7SPramod Gunjikar 						IB_QP_MAX_DEST_RD_ATOMIC |
229c39526b7SPramod Gunjikar 						IB_QP_ALT_PATH |
230c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS |
231c39526b7SPramod Gunjikar 						IB_QP_PKEY_INDEX |
232c39526b7SPramod Gunjikar 						IB_QP_MIN_RNR_TIMER |
233c39526b7SPramod Gunjikar 						IB_QP_PATH_MIG_STATE),
234c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
235c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY),
236c39526b7SPramod Gunjikar 			}
237c39526b7SPramod Gunjikar 		}
238c39526b7SPramod Gunjikar 	},
239c39526b7SPramod Gunjikar 	[IB_QPS_SQE] = {
240c39526b7SPramod Gunjikar 		[IB_QPS_RESET] = { .valid = 1 },
241c39526b7SPramod Gunjikar 		[IB_QPS_ERR] = { .valid = 1 },
242c39526b7SPramod Gunjikar 		[IB_QPS_RTS] = { .valid = 1,
243c39526b7SPramod Gunjikar 			.opt_param = {
244c39526b7SPramod Gunjikar 				[IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY),
245c39526b7SPramod Gunjikar 				[IB_QPT_UC] = (IB_QP_CUR_STATE |
246c39526b7SPramod Gunjikar 						IB_QP_ACCESS_FLAGS),
247c39526b7SPramod Gunjikar 				[IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
248c39526b7SPramod Gunjikar 				[IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY),
249c39526b7SPramod Gunjikar 			}
250c39526b7SPramod Gunjikar 		}
251c39526b7SPramod Gunjikar 	},
252c39526b7SPramod Gunjikar 	[IB_QPS_ERR] = {
253c39526b7SPramod Gunjikar 		[IB_QPS_RESET] = { .valid = 1 },
254c39526b7SPramod Gunjikar 		[IB_QPS_ERR] = { .valid = 1 }
255c39526b7SPramod Gunjikar 	}
256c39526b7SPramod Gunjikar };
257c39526b7SPramod Gunjikar 
258c39526b7SPramod Gunjikar /*
259c39526b7SPramod Gunjikar  * Function:
260c39526b7SPramod Gunjikar  *      uverbs_modify_qp_is_ok
261c39526b7SPramod Gunjikar  * Input:
262c39526b7SPramod Gunjikar  *      cur_state	- The current OFED QP state.
263c39526b7SPramod Gunjikar  *	next_state	- The OFED QP state to transition to.
264c39526b7SPramod Gunjikar  *	type		- The OFED QP transport type.
265c39526b7SPramod Gunjikar  *      mask		- The OFED QP attribute mask for the QP transition.
266c39526b7SPramod Gunjikar  * Output:
267c39526b7SPramod Gunjikar  *      None
268c39526b7SPramod Gunjikar  * Returns:
269c39526b7SPramod Gunjikar  *      Returns 1 if the operation is valid; otherwise 0 for invalid
270c39526b7SPramod Gunjikar  *	operations.
271c39526b7SPramod Gunjikar  * Description:
272c39526b7SPramod Gunjikar  *      Indicate whether the desired QP modify operation is a valid operation.
273c39526b7SPramod Gunjikar  *	To be valid, the state transition must be legal and the required and
274c39526b7SPramod Gunjikar  *	optional parameters must be valid for the transition and QP type.
275c39526b7SPramod Gunjikar  */
276c39526b7SPramod Gunjikar static int
uverbs_modify_qp_is_ok(enum ib_qp_state cur_state,enum ib_qp_state next_state,enum ib_qp_type type,enum ib_qp_attr_mask * maskp)277c39526b7SPramod Gunjikar uverbs_modify_qp_is_ok(enum ib_qp_state cur_state,
278c39526b7SPramod Gunjikar     enum ib_qp_state next_state, enum ib_qp_type type,
279c39526b7SPramod Gunjikar     enum ib_qp_attr_mask *maskp)
280c39526b7SPramod Gunjikar {
281c39526b7SPramod Gunjikar 	enum ib_qp_attr_mask 	req_param, opt_param;
282c39526b7SPramod Gunjikar 	uverbs_qp_state_tbl_t	*state_tblp;
283c39526b7SPramod Gunjikar 	enum ib_qp_attr_mask	mask = *maskp;
284c39526b7SPramod Gunjikar 
285c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp_is_ok"
286c39526b7SPramod Gunjikar 	    "(%x, %x, %x, %x)", cur_state, next_state, type, mask);
287c39526b7SPramod Gunjikar 
288c39526b7SPramod Gunjikar 	if (cur_state  < 0 || cur_state  > IB_QPS_ERR ||
289c39526b7SPramod Gunjikar 	    next_state < 0 || next_state > IB_QPS_ERR) {
290c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
291c39526b7SPramod Gunjikar 		    "modify_qp_is_ok: bad state, cur %d, next %d",
292c39526b7SPramod Gunjikar 		    cur_state, next_state);
293c39526b7SPramod Gunjikar 		return (0);
294c39526b7SPramod Gunjikar 	}
295c39526b7SPramod Gunjikar 
296c39526b7SPramod Gunjikar 	if (mask & IB_QP_CUR_STATE &&
297c39526b7SPramod Gunjikar 	    cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS &&
298c39526b7SPramod Gunjikar 	    cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) {
299c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
300c39526b7SPramod Gunjikar 		    "modify_qp_is_ok: cur_state %d is a bad state",
301c39526b7SPramod Gunjikar 		    cur_state);
302c39526b7SPramod Gunjikar 		return (0);
303c39526b7SPramod Gunjikar 	}
304c39526b7SPramod Gunjikar 
305c39526b7SPramod Gunjikar 	state_tblp = &uverbs_qp_state_table[cur_state][next_state];
306c39526b7SPramod Gunjikar 	if (!state_tblp->valid) {
307c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "modify_qp: "
308c39526b7SPramod Gunjikar 		    "bad transition, cur = %d, next = %d", cur_state,
309c39526b7SPramod Gunjikar 		    next_state);
310c39526b7SPramod Gunjikar 		return (0);
311c39526b7SPramod Gunjikar 	}
312c39526b7SPramod Gunjikar 
313c39526b7SPramod Gunjikar 	req_param = state_tblp->req_param[type];
314c39526b7SPramod Gunjikar 	opt_param = state_tblp->opt_param[type];
315c39526b7SPramod Gunjikar 
316c39526b7SPramod Gunjikar 	if ((mask & req_param) != req_param) {
317c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
318c39526b7SPramod Gunjikar 		    "modify_qp_is_ok: cur %d, next %d, "
319c39526b7SPramod Gunjikar 		    "missing required parms, spec = 0x%08X, "
320c39526b7SPramod Gunjikar 		    "req = 0%08X", cur_state, next_state,
321c39526b7SPramod Gunjikar 		    mask, req_param);
322c39526b7SPramod Gunjikar 		return (0);
323c39526b7SPramod Gunjikar 	}
324c39526b7SPramod Gunjikar 
325c39526b7SPramod Gunjikar 	if (mask & ~(req_param | opt_param | IB_QP_STATE)) {
326c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str,
327c39526b7SPramod Gunjikar 		    "modify_qp_is_ok: cur %d, next %d, "
328c39526b7SPramod Gunjikar 		    "illegal optional parms, parms = 0x%08X, "
329c39526b7SPramod Gunjikar 		    "illegal = 0x%08X", cur_state, next_state,
330c39526b7SPramod Gunjikar 		    mask, mask & ~(req_param | opt_param | IB_QP_STATE));
331c39526b7SPramod Gunjikar 		*maskp = mask & (req_param | opt_param | IB_QP_STATE);
332c39526b7SPramod Gunjikar 		return (0);
333c39526b7SPramod Gunjikar 	}
334c39526b7SPramod Gunjikar 
335c39526b7SPramod Gunjikar 	return (1);
336c39526b7SPramod Gunjikar }
337c39526b7SPramod Gunjikar 
338c39526b7SPramod Gunjikar 
339c39526b7SPramod Gunjikar /*
340c39526b7SPramod Gunjikar  * Function:
341c39526b7SPramod Gunjikar  *      sol_uverbs_create_qp
342c39526b7SPramod Gunjikar  * Input:
343c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
344c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing the create command.
345c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
346c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
347c39526b7SPramod Gunjikar  * Output:
348c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
349c39526b7SPramod Gunjikar  * Returns:
350c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
351c39526b7SPramod Gunjikar  * Description:
352c39526b7SPramod Gunjikar  *      User verbs entry point to create a new device QP.
353c39526b7SPramod Gunjikar  */
354c39526b7SPramod Gunjikar /* ARGSUSED */
355c39526b7SPramod Gunjikar int
sol_uverbs_create_qp(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)356c39526b7SPramod Gunjikar sol_uverbs_create_qp(uverbs_uctxt_uobj_t *uctxt, char *buf,
357c39526b7SPramod Gunjikar     int in_len, int out_len)
358c39526b7SPramod Gunjikar {
359c39526b7SPramod Gunjikar 	struct ib_uverbs_create_qp	cmd;
360c39526b7SPramod Gunjikar 	struct ib_uverbs_create_qp_resp	resp;
361c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t		*uqp;
362c39526b7SPramod Gunjikar 	ibt_qp_type_t			qp_type;
363c39526b7SPramod Gunjikar 	ibt_qp_alloc_attr_t		qp_attr;
364c39526b7SPramod Gunjikar 	ibt_chan_sizes_t		qp_sizes;
365c39526b7SPramod Gunjikar 	int				rc = 0;
366c39526b7SPramod Gunjikar 	uverbs_upd_uobj_t		*upd;
367c39526b7SPramod Gunjikar 	uverbs_ucq_uobj_t		*uscq;
368c39526b7SPramod Gunjikar 	uverbs_ucq_uobj_t		*urcq;
369c39526b7SPramod Gunjikar 	uverbs_usrq_uobj_t		*usrq = NULL;
370c39526b7SPramod Gunjikar 
371c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
372c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
373c39526b7SPramod Gunjikar 	(void) memset(&qp_attr, 0, sizeof (qp_attr));
374c39526b7SPramod Gunjikar 	(void) memset(&qp_sizes, 0, sizeof (qp_sizes));
375c39526b7SPramod Gunjikar 
376c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "create_qp(): entry");
377c39526b7SPramod Gunjikar 
378c39526b7SPramod Gunjikar 	switch (cmd.qp_type) {
379c39526b7SPramod Gunjikar 		case IB_QPT_UC:
380c39526b7SPramod Gunjikar 			qp_type 		= IBT_UC_RQP;
381c39526b7SPramod Gunjikar 			break;
382c39526b7SPramod Gunjikar 		case IB_QPT_UD:
383c39526b7SPramod Gunjikar 			qp_type 		= IBT_UD_RQP;
384c39526b7SPramod Gunjikar 			break;
385c39526b7SPramod Gunjikar 		case IB_QPT_RC:
386c39526b7SPramod Gunjikar 			qp_type 		= IBT_RC_RQP;
387c39526b7SPramod Gunjikar 			break;
388c39526b7SPramod Gunjikar 		default:
389c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
390c39526b7SPramod Gunjikar 			    "create_qp(): Invalid qp type");
391c39526b7SPramod Gunjikar 			rc = EINVAL;
392c39526b7SPramod Gunjikar 			goto err_out;
393c39526b7SPramod Gunjikar 	}
394c39526b7SPramod Gunjikar 
395c39526b7SPramod Gunjikar 	qp_attr.qp_alloc_flags = IBT_QP_USER_MAP;
396c39526b7SPramod Gunjikar 
397c39526b7SPramod Gunjikar 	if (cmd.is_srq) {
398c39526b7SPramod Gunjikar 		qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ;
399c39526b7SPramod Gunjikar 	}
400c39526b7SPramod Gunjikar 
401c39526b7SPramod Gunjikar 	qp_attr.qp_flags = IBT_WR_SIGNALED;
402c39526b7SPramod Gunjikar 	if (cmd.sq_sig_all) {
403c39526b7SPramod Gunjikar 		qp_attr.qp_flags = IBT_ALL_SIGNALED;
404c39526b7SPramod Gunjikar 	}
405c39526b7SPramod Gunjikar 
406c39526b7SPramod Gunjikar 	uqp = kmem_zalloc(sizeof (*uqp), KM_NOSLEEP);
407c39526b7SPramod Gunjikar 	if (uqp == NULL) {
408c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
409c39526b7SPramod Gunjikar 		    "create_qp(): User object allocation failed");
410c39526b7SPramod Gunjikar 		rc = ENOMEM;
411c39526b7SPramod Gunjikar 		goto err_out;
412c39526b7SPramod Gunjikar 	}
413c39526b7SPramod Gunjikar 	sol_ofs_uobj_init(&uqp->uobj, cmd.user_handle,
414c39526b7SPramod Gunjikar 	    SOL_UVERBS_UQP_UOBJ_TYPE);
415c39526b7SPramod Gunjikar 	rw_enter(&uqp->uobj.uo_lock, RW_WRITER);
416c39526b7SPramod Gunjikar 	llist_head_init(&uqp->mcast_list, NULL);
417c39526b7SPramod Gunjikar 	llist_head_init(&uqp->async_list, NULL);
418c39526b7SPramod Gunjikar 
419c39526b7SPramod Gunjikar 	uqp->async_events_reported	= 0;
420c39526b7SPramod Gunjikar 	uqp->uctxt			= uctxt;
421c39526b7SPramod Gunjikar 	uqp->disable_qp_mod		= FALSE;
422c39526b7SPramod Gunjikar 
423c39526b7SPramod Gunjikar 	if (cmd.is_srq) {
424c39526b7SPramod Gunjikar 		usrq = uverbs_uobj_get_usrq_read(cmd.srq_handle);
425c39526b7SPramod Gunjikar 		uqp->uqp_rcq_srq_valid |= SOL_UVERBS_UQP_SRQ_VALID;
426c39526b7SPramod Gunjikar 		uqp->uqp_srq_hdl = cmd.srq_handle;
427c39526b7SPramod Gunjikar 	}
428c39526b7SPramod Gunjikar 	upd  = uverbs_uobj_get_upd_read(cmd.pd_handle);
429c39526b7SPramod Gunjikar 	uqp->uqp_pd_hdl = cmd.pd_handle;
430c39526b7SPramod Gunjikar 	uscq = uverbs_uobj_get_ucq_read(cmd.send_cq_handle);
431c39526b7SPramod Gunjikar 	uqp->uqp_scq_hdl = cmd.send_cq_handle;
432c39526b7SPramod Gunjikar 	uqp->uqp_rcq_hdl = cmd.recv_cq_handle;
433c39526b7SPramod Gunjikar 	if (cmd.recv_cq_handle != cmd.send_cq_handle) {
434c39526b7SPramod Gunjikar 		urcq = uverbs_uobj_get_ucq_read(cmd.recv_cq_handle);
435c39526b7SPramod Gunjikar 		uqp->uqp_rcq_srq_valid |= SOL_UVERBS_UQP_RCQ_VALID;
436c39526b7SPramod Gunjikar 	} else
437c39526b7SPramod Gunjikar 		urcq = uscq;
438c39526b7SPramod Gunjikar 
439c39526b7SPramod Gunjikar 	if (!upd || !uscq || !urcq || (cmd.is_srq && !usrq)) {
440c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
441c39526b7SPramod Gunjikar 		    "create_qp(): Invalid resource handle");
442c39526b7SPramod Gunjikar 		rc = EINVAL;
443c39526b7SPramod Gunjikar 		goto err_put;
444c39526b7SPramod Gunjikar 	}
445c39526b7SPramod Gunjikar 	uqp->uqp_rcq = urcq;
446c39526b7SPramod Gunjikar 	uqp->uqp_scq = uscq;
447c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
448c39526b7SPramod Gunjikar 	    "uqp %p, rcq %p. scq %p", uqp, urcq, uscq);
449c39526b7SPramod Gunjikar 
450c39526b7SPramod Gunjikar 	qp_attr.qp_pd_hdl	= upd->pd;
451c39526b7SPramod Gunjikar 	if (usrq) {
452c39526b7SPramod Gunjikar 		qp_attr.qp_srq_hdl = usrq->srq;
453c39526b7SPramod Gunjikar 	}
454c39526b7SPramod Gunjikar 	qp_attr.qp_scq_hdl		= uscq->cq;
455c39526b7SPramod Gunjikar 	qp_attr.qp_rcq_hdl		= urcq->cq;
456c39526b7SPramod Gunjikar 	qp_attr.qp_sizes.cs_sq		= cmd.max_send_wr;
457c39526b7SPramod Gunjikar 	qp_attr.qp_sizes.cs_rq		= cmd.max_recv_wr;
458c39526b7SPramod Gunjikar 	qp_attr.qp_sizes.cs_sq_sgl	= cmd.max_send_sge;
459c39526b7SPramod Gunjikar 	qp_attr.qp_sizes.cs_rq_sgl	= cmd.max_recv_sge;
460c39526b7SPramod Gunjikar 
461c39526b7SPramod Gunjikar 	uqp->max_inline_data	= cmd.max_inline_data;
462c39526b7SPramod Gunjikar 	uqp->ofa_qp_type	= cmd.qp_type;
463c39526b7SPramod Gunjikar 
464c39526b7SPramod Gunjikar 	/*
465c39526b7SPramod Gunjikar 	 * NOTE: We allocate the QP and leave it in the RESET state to follow
466c39526b7SPramod Gunjikar 	 * usage semantics consistent with OFA verbs.
467c39526b7SPramod Gunjikar 	 */
468c39526b7SPramod Gunjikar 	rc = ibt_alloc_qp(uctxt->hca->hdl, qp_type, &qp_attr, &qp_sizes,
469c39526b7SPramod Gunjikar 	    &uqp->qp_num, &uqp->qp);
470c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
471c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
472c39526b7SPramod Gunjikar 		    "create_qp(): Error in ibt_alloc_qp() (rc=%d)", rc);
473c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
474c39526b7SPramod Gunjikar 		uqp->uobj.uo_uobj_sz = sizeof (uverbs_uqp_uobj_t);
475c39526b7SPramod Gunjikar 		goto err_put;
476c39526b7SPramod Gunjikar 	}
477c39526b7SPramod Gunjikar 
478c39526b7SPramod Gunjikar 	ibt_set_qp_private(uqp->qp, uqp);
479c39526b7SPramod Gunjikar 
480c39526b7SPramod Gunjikar 	/* Bump up the active_qp_cnt for CQ, SRQ & PD resources it is using */
481c39526b7SPramod Gunjikar 	upd->active_qp_cnt++;
482c39526b7SPramod Gunjikar 	uscq->active_qp_cnt++;
483c39526b7SPramod Gunjikar 	if (cmd.recv_cq_handle != cmd.send_cq_handle)
484c39526b7SPramod Gunjikar 		urcq->active_qp_cnt++;
485c39526b7SPramod Gunjikar 	if (usrq)
486c39526b7SPramod Gunjikar 		usrq->active_qp_cnt++;
487c39526b7SPramod Gunjikar 
488c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
489c39526b7SPramod Gunjikar 	    "\treq cs_sq=%d, actual cs_sq=%d",
490c39526b7SPramod Gunjikar 	    qp_attr.qp_sizes.cs_sq, qp_sizes.cs_sq);
491c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
492c39526b7SPramod Gunjikar 	    "\treq cs_sq_sgl=%d, actual cs_sg_sgl=%d",
493c39526b7SPramod Gunjikar 	    qp_attr.qp_sizes.cs_sq_sgl, qp_sizes.cs_sq_sgl);
494c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
495c39526b7SPramod Gunjikar 	    "\treq cs_rq=%d, actual cs_rq=%d",
496c39526b7SPramod Gunjikar 	    qp_attr.qp_sizes.cs_rq, qp_sizes.cs_rq);
497c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
498c39526b7SPramod Gunjikar 	    "\treq cs_rq_sgl=%d, actual cs_rq_sgl=%d",
499c39526b7SPramod Gunjikar 	    qp_attr.qp_sizes.cs_rq_sgl, qp_sizes.cs_rq_sgl);
500c39526b7SPramod Gunjikar 
501c39526b7SPramod Gunjikar 	/*
502c39526b7SPramod Gunjikar 	 * Query underlying hardware for data used in mapping QP work
503c39526b7SPramod Gunjikar 	 * queues back to user space, we will return this information
504c39526b7SPramod Gunjikar 	 * in the user verbs command response.
505c39526b7SPramod Gunjikar 	 */
506c39526b7SPramod Gunjikar 	rc = ibt_ci_data_out(uctxt->hca->hdl, IBT_CI_NO_FLAGS, IBT_HDL_CHANNEL,
507c39526b7SPramod Gunjikar 	    (void *)uqp->qp, &resp.drv_out, sizeof (resp.drv_out));
508c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
509c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
510c39526b7SPramod Gunjikar 		    "create_qp(): Error in ibt_ci_data_out() (rc=%d)", rc);
511c39526b7SPramod Gunjikar 		rc = EFAULT;
512c39526b7SPramod Gunjikar 		uqp->uobj.uo_uobj_sz = sizeof (uverbs_uqp_uobj_t);
513c39526b7SPramod Gunjikar 		goto err_qp_destroy;
514c39526b7SPramod Gunjikar 	}
515c39526b7SPramod Gunjikar 
516c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
517c39526b7SPramod Gunjikar 	    "create_qp QP: ibt_ci_data_out:0x%016llx 0x%016llx",
518c39526b7SPramod Gunjikar 	    resp.drv_out[0], resp.drv_out[1]);
519c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
520c39526b7SPramod Gunjikar 	    "                          :0x%016llx 0x%016llx",
521c39526b7SPramod Gunjikar 	    resp.drv_out[2], resp.drv_out[3]);
522c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
523c39526b7SPramod Gunjikar 	    "                          :0x%016llx 0x%016llx",
524c39526b7SPramod Gunjikar 	    resp.drv_out[4], resp.drv_out[5]);
525c39526b7SPramod Gunjikar 
526c39526b7SPramod Gunjikar 	if (sol_ofs_uobj_add(&uverbs_uqp_uo_tbl, &uqp->uobj) != 0) {
527c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
528c39526b7SPramod Gunjikar 		    "create_qp(): User object add failed (rc=%d)", rc);
529c39526b7SPramod Gunjikar 		rc = ENOMEM;
530c39526b7SPramod Gunjikar 		goto err_qp_destroy;
531c39526b7SPramod Gunjikar 	}
532c39526b7SPramod Gunjikar 
533c39526b7SPramod Gunjikar 	resp.qp_handle		= uqp->uobj.uo_id;
534c39526b7SPramod Gunjikar 	resp.qpn		= uqp->qp_num;
535c39526b7SPramod Gunjikar 	resp.max_send_wr	= qp_sizes.cs_sq;
536c39526b7SPramod Gunjikar 	resp.max_send_sge	= qp_sizes.cs_sq_sgl;
537c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "create_qp() : "
538c39526b7SPramod Gunjikar 	    "resp.qp_handle=0x%08x, resp.qpn=0x%08x", resp.qp_handle, resp.qpn);
539c39526b7SPramod Gunjikar 
540c39526b7SPramod Gunjikar 	/*
541c39526b7SPramod Gunjikar 	 * In Solaris the receive work requests and sg entries are cleared
542c39526b7SPramod Gunjikar 	 * when a SRQ is used since these values are ignored.  To maintain
543c39526b7SPramod Gunjikar 	 * consistency with OFED we return the requested values as is done
544c39526b7SPramod Gunjikar 	 * in OFED, but these values will be ignored and SRQ valuves are
545c39526b7SPramod Gunjikar 	 * used.  MTHCA lib will extract the zeroed out value from the
546c39526b7SPramod Gunjikar 	 * driver out data.
547c39526b7SPramod Gunjikar 	 */
548c39526b7SPramod Gunjikar 	if (usrq) {
549c39526b7SPramod Gunjikar 		resp.max_recv_wr    = cmd.max_recv_wr;
550c39526b7SPramod Gunjikar 		resp.max_recv_sge   = cmd.max_recv_sge;
551c39526b7SPramod Gunjikar 	} else {
552c39526b7SPramod Gunjikar 		resp.max_recv_wr    = qp_sizes.cs_rq;
553c39526b7SPramod Gunjikar 		resp.max_recv_sge   = qp_sizes.cs_rq_sgl;
554c39526b7SPramod Gunjikar 	}
555c39526b7SPramod Gunjikar 	resp.max_inline_data = cmd.max_inline_data;
556c39526b7SPramod Gunjikar 
557c39526b7SPramod Gunjikar #ifdef	_LP64
558c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
559c39526b7SPramod Gunjikar #else
560c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
561c39526b7SPramod Gunjikar #endif
562c39526b7SPramod Gunjikar 	if (rc != 0) {
563c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
564c39526b7SPramod Gunjikar 		    "create_qp(): Error writing resp data (rc=%d)", rc);
565c39526b7SPramod Gunjikar 		rc = EFAULT;
566c39526b7SPramod Gunjikar 		goto err_uo_delete;
567c39526b7SPramod Gunjikar 	}
568c39526b7SPramod Gunjikar 
569c39526b7SPramod Gunjikar 	mutex_enter(&uctxt->lock);
570c39526b7SPramod Gunjikar 	uqp->list_entry = add_genlist(&uctxt->qp_list, (uintptr_t)uqp,
571c39526b7SPramod Gunjikar 	    (void*)uctxt);
572c39526b7SPramod Gunjikar 	mutex_exit(&uctxt->lock);
573c39526b7SPramod Gunjikar 
574c39526b7SPramod Gunjikar 	if (!uqp->list_entry) {
575c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
576c39526b7SPramod Gunjikar 		    "create_qp(): Error adding uqp to qp_list\n");
577c39526b7SPramod Gunjikar 		rc = ENOMEM;
578c39526b7SPramod Gunjikar 		goto err_uo_delete;
579c39526b7SPramod Gunjikar 	}
580c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
581c39526b7SPramod Gunjikar 	    "create_qp() - uqp %p", uqp);
582c39526b7SPramod Gunjikar 
583c39526b7SPramod Gunjikar 	uqp->uobj.uo_live = 1;
584c39526b7SPramod Gunjikar 
585c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&upd->uobj);
586c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uscq->uobj);
587c39526b7SPramod Gunjikar 
588c39526b7SPramod Gunjikar 	if (urcq != uscq) {
589c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&urcq->uobj);
590c39526b7SPramod Gunjikar 	}
591c39526b7SPramod Gunjikar 	if (usrq) {
592c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&usrq->uobj);
593c39526b7SPramod Gunjikar 	}
594c39526b7SPramod Gunjikar 	rw_exit(&uqp->uobj.uo_lock);
595c39526b7SPramod Gunjikar 
596c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
597c39526b7SPramod Gunjikar 
598c39526b7SPramod Gunjikar err_uo_delete:
599c39526b7SPramod Gunjikar 	/*
600c39526b7SPramod Gunjikar 	 * Need to set uo_live, so sol_ofs_uobj_remove() will
601c39526b7SPramod Gunjikar 	 * remove the object from the object table.
602c39526b7SPramod Gunjikar 	 */
603c39526b7SPramod Gunjikar 	uqp->uobj.uo_live = 1;
604c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&uverbs_uqp_uo_tbl, &uqp->uobj);
605c39526b7SPramod Gunjikar 
606c39526b7SPramod Gunjikar err_qp_destroy:
607c39526b7SPramod Gunjikar 	(void) ibt_free_qp(uqp->qp);
608c39526b7SPramod Gunjikar 
609c39526b7SPramod Gunjikar 	upd->active_qp_cnt--;
610c39526b7SPramod Gunjikar 	uscq->active_qp_cnt--;
611c39526b7SPramod Gunjikar 	if (cmd.recv_cq_handle != cmd.send_cq_handle)
612c39526b7SPramod Gunjikar 		urcq->active_qp_cnt--;
613c39526b7SPramod Gunjikar 	if (usrq)
614c39526b7SPramod Gunjikar 		usrq->active_qp_cnt--;
615c39526b7SPramod Gunjikar 
616c39526b7SPramod Gunjikar err_put:
617c39526b7SPramod Gunjikar 	if (upd) {
618c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&upd->uobj);
619c39526b7SPramod Gunjikar 	}
620c39526b7SPramod Gunjikar 	if (uscq) {
621c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uscq->uobj);
622c39526b7SPramod Gunjikar 	}
623c39526b7SPramod Gunjikar 	if (urcq && urcq != uscq) {
624c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&urcq->uobj);
625c39526b7SPramod Gunjikar 	}
626c39526b7SPramod Gunjikar 	if (usrq) {
627c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&usrq->uobj);
628c39526b7SPramod Gunjikar 	}
629c39526b7SPramod Gunjikar 
630c39526b7SPramod Gunjikar 	rw_exit(&uqp->uobj.uo_lock);
631c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&uqp->uobj, sol_ofs_uobj_free);
632c39526b7SPramod Gunjikar 
633c39526b7SPramod Gunjikar err_out:
634c39526b7SPramod Gunjikar 	return (rc);
635c39526b7SPramod Gunjikar }
636c39526b7SPramod Gunjikar 
637c39526b7SPramod Gunjikar /*
638c39526b7SPramod Gunjikar  * Free the resources used by uqp. Return 0, if the free of all
639c39526b7SPramod Gunjikar  * resources where succesful, return non-zero, if not.
640c39526b7SPramod Gunjikar  *
641c39526b7SPramod Gunjikar  * If other uQPs are holding the resources (PD, CQ, SRQ), do not
642c39526b7SPramod Gunjikar  * free the resource, but return 0, so the free of uqp can be
643c39526b7SPramod Gunjikar  * done. Return failure only if active_cnt cannot be decremented
644c39526b7SPramod Gunjikar  * resource_free() fails.
645c39526b7SPramod Gunjikar  */
646c39526b7SPramod Gunjikar static int
uverbs_uqp_rsrc_free(uverbs_uqp_uobj_t * uqp,uverbs_uctxt_uobj_t * uctxt)647c39526b7SPramod Gunjikar uverbs_uqp_rsrc_free(uverbs_uqp_uobj_t *uqp, uverbs_uctxt_uobj_t *uctxt)
648c39526b7SPramod Gunjikar {
649c39526b7SPramod Gunjikar 	uverbs_ucq_uobj_t	*uscq = NULL, *urcq = NULL;
650c39526b7SPramod Gunjikar 	uverbs_usrq_uobj_t	*usrq = NULL;
651c39526b7SPramod Gunjikar 	uverbs_upd_uobj_t	*upd = NULL;
652c39526b7SPramod Gunjikar 	int			ret, rc = -1;
653c39526b7SPramod Gunjikar 
654c39526b7SPramod Gunjikar 	/* Get uobj for PD, CQ & SRQ resources used. */
655c39526b7SPramod Gunjikar 	upd = uverbs_uobj_get_upd_write(uqp->uqp_pd_hdl);
656c39526b7SPramod Gunjikar 	if (upd == NULL) {
657c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
658c39526b7SPramod Gunjikar 		    "uqp_rsrc_free: get_upd %d failed", uqp->uqp_pd_hdl);
659c39526b7SPramod Gunjikar 		goto err_free;
660c39526b7SPramod Gunjikar 	}
661c39526b7SPramod Gunjikar 	uscq = uverbs_uobj_get_ucq_write(uqp->uqp_scq_hdl);
662c39526b7SPramod Gunjikar 	if (uscq == NULL) {
663c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
664c39526b7SPramod Gunjikar 		    "uqp_rsrc_free: get_ucq %x failed", uqp->uqp_scq_hdl);
665c39526b7SPramod Gunjikar 		goto err_free;
666c39526b7SPramod Gunjikar 	}
667c39526b7SPramod Gunjikar 	if (uqp->uqp_rcq_srq_valid & SOL_UVERBS_UQP_RCQ_VALID) {
668c39526b7SPramod Gunjikar 		urcq = uverbs_uobj_get_ucq_write(uqp->uqp_rcq_hdl);
669c39526b7SPramod Gunjikar 		if (urcq == NULL) {
670c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
671c39526b7SPramod Gunjikar 			    "uqp_rsrc_free: get_ucq %x failed",
672c39526b7SPramod Gunjikar 			    uqp->uqp_rcq_hdl);
673c39526b7SPramod Gunjikar 			goto err_free;
674c39526b7SPramod Gunjikar 		}
675c39526b7SPramod Gunjikar 	}
676c39526b7SPramod Gunjikar 	if (uqp->uqp_rcq_srq_valid & SOL_UVERBS_UQP_SRQ_VALID) {
677c39526b7SPramod Gunjikar 		usrq = uverbs_uobj_get_usrq_write(uqp->uqp_srq_hdl);
678c39526b7SPramod Gunjikar 		if (usrq == NULL) {
679c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
680c39526b7SPramod Gunjikar 			    "uqp_rsrc_free: get_srq %x failed",
681c39526b7SPramod Gunjikar 			    uqp->uqp_srq_hdl);
682c39526b7SPramod Gunjikar 			goto err_free;
683c39526b7SPramod Gunjikar 		}
684c39526b7SPramod Gunjikar 	}
685c39526b7SPramod Gunjikar 	rc = 0;
686c39526b7SPramod Gunjikar 
687c39526b7SPramod Gunjikar 	/* Decrement active_qp_cnt for resources used */
688c39526b7SPramod Gunjikar 	upd->active_qp_cnt--;
689c39526b7SPramod Gunjikar 	uscq->active_qp_cnt--;
690c39526b7SPramod Gunjikar 	if (urcq)
691c39526b7SPramod Gunjikar 		urcq->active_qp_cnt--;
692c39526b7SPramod Gunjikar 	if (usrq)
693c39526b7SPramod Gunjikar 		usrq->active_qp_cnt--;
694c39526b7SPramod Gunjikar 
695c39526b7SPramod Gunjikar 	/*
696c39526b7SPramod Gunjikar 	 * Free the resources, if active_qp_cnt is 0 and userland free
697c39526b7SPramod Gunjikar 	 * already been pending for the resource.
698c39526b7SPramod Gunjikar 	 */
699c39526b7SPramod Gunjikar 	if (upd->active_qp_cnt == 0 && upd->free_pending) {
700c39526b7SPramod Gunjikar 		ret = uverbs_upd_free(upd, uctxt);
701c39526b7SPramod Gunjikar 		if (ret && rc == 0) {
702c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
703c39526b7SPramod Gunjikar 			    "uqp_rsrc_free: upd_free failed");
704c39526b7SPramod Gunjikar 			rc = ret;
705c39526b7SPramod Gunjikar 		}
706c39526b7SPramod Gunjikar 	} else if (upd)
707c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&upd->uobj);
708c39526b7SPramod Gunjikar 	if (uscq && uscq->active_qp_cnt == 0 && uscq->free_pending) {
709c39526b7SPramod Gunjikar 		ret = uverbs_ucq_free(uscq, uctxt);
710c39526b7SPramod Gunjikar 		if (ret && rc == 0) {
711c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
712c39526b7SPramod Gunjikar 			    "uqp_rsrc_free: ucq_free failed");
713c39526b7SPramod Gunjikar 			rc = ret;
714c39526b7SPramod Gunjikar 		}
715c39526b7SPramod Gunjikar 	} else if (uscq)
716c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uscq->uobj);
717c39526b7SPramod Gunjikar 	if (urcq && urcq->active_qp_cnt == 0 && urcq->free_pending) {
718*fffafeb2SJohnny Cheung 		ret = uverbs_ucq_free(urcq, uctxt);
719c39526b7SPramod Gunjikar 		if (ret && rc == 0) {
720c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
721c39526b7SPramod Gunjikar 			    "uqp_rsrc_free: ucq_free failed");
722c39526b7SPramod Gunjikar 			rc = ret;
723c39526b7SPramod Gunjikar 		}
724c39526b7SPramod Gunjikar 	} else if (urcq)
725c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&urcq->uobj);
726c39526b7SPramod Gunjikar 	if (usrq && usrq->active_qp_cnt == 0 && usrq->free_pending) {
727*fffafeb2SJohnny Cheung 		ret = uverbs_usrq_free(usrq, uctxt);
728c39526b7SPramod Gunjikar 		if (ret && rc == 0) {
729c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
730c39526b7SPramod Gunjikar 			    "uqp_rsrc_free: usrq_free failed");
731c39526b7SPramod Gunjikar 			rc = ret;
732c39526b7SPramod Gunjikar 		}
733c39526b7SPramod Gunjikar 	} else if (usrq)
734c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&usrq->uobj);
735c39526b7SPramod Gunjikar 	return (rc);
736c39526b7SPramod Gunjikar 
737c39526b7SPramod Gunjikar err_free:
738c39526b7SPramod Gunjikar 	if (upd)
739c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&upd->uobj);
740c39526b7SPramod Gunjikar 	if (uscq)
741c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uscq->uobj);
742c39526b7SPramod Gunjikar 	if (urcq)
743c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&urcq->uobj);
744c39526b7SPramod Gunjikar 
745c39526b7SPramod Gunjikar 	return (rc);
746c39526b7SPramod Gunjikar }
747c39526b7SPramod Gunjikar 
748c39526b7SPramod Gunjikar /*
749c39526b7SPramod Gunjikar  * Free the resources held by the uqp.
750c39526b7SPramod Gunjikar  * Call ibt_free_qp() to free the IBTF QP.
751c39526b7SPramod Gunjikar  * Free uqp.
752c39526b7SPramod Gunjikar  */
753c39526b7SPramod Gunjikar int
uverbs_uqp_free(uverbs_uqp_uobj_t * uqp,uverbs_uctxt_uobj_t * uctxt)754c39526b7SPramod Gunjikar uverbs_uqp_free(uverbs_uqp_uobj_t *uqp, uverbs_uctxt_uobj_t *uctxt)
755c39526b7SPramod Gunjikar {
756c39526b7SPramod Gunjikar 	int		rc;
757c39526b7SPramod Gunjikar 	ibt_status_t	status;
758c39526b7SPramod Gunjikar 
759c39526b7SPramod Gunjikar 	/* Detach  Mcast entries, if any. */
760c39526b7SPramod Gunjikar 	uverbs_detach_uqp_mcast_entries(uqp);
761c39526b7SPramod Gunjikar 
762c39526b7SPramod Gunjikar 	if (!uqp->qp)
763c39526b7SPramod Gunjikar 		goto skip_ibt_free_qp;
764c39526b7SPramod Gunjikar 
765c39526b7SPramod Gunjikar 	status = ibt_free_qp(uqp->qp);
766c39526b7SPramod Gunjikar 	if (status != IBT_SUCCESS) {
767c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
768c39526b7SPramod Gunjikar 		    "uqp_free: ibt_free_qp failed %d", status);
769c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uqp->uobj);
770c39526b7SPramod Gunjikar 		return (status);
771c39526b7SPramod Gunjikar 	}
772c39526b7SPramod Gunjikar 	uqp->qp = NULL;
773c39526b7SPramod Gunjikar 
774c39526b7SPramod Gunjikar skip_ibt_free_qp :
775c39526b7SPramod Gunjikar 	rc = uverbs_uqp_rsrc_free(uqp, uctxt);
776c39526b7SPramod Gunjikar 	if (rc) {
777c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
778c39526b7SPramod Gunjikar 		    "uqp_free: uqp_rcrc_free failed  %d", rc);
779c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uqp->uobj);
780c39526b7SPramod Gunjikar 		return (rc);
781c39526b7SPramod Gunjikar 	}
782c39526b7SPramod Gunjikar 
783c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&uverbs_uqp_uo_tbl, &uqp->uobj);
784c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
785c39526b7SPramod Gunjikar 
786c39526b7SPramod Gunjikar 	if (uqp->list_entry) {
787c39526b7SPramod Gunjikar 		mutex_enter(&uctxt->lock);
788c39526b7SPramod Gunjikar 		delete_genlist(&uctxt->qp_list, uqp->list_entry);
789c39526b7SPramod Gunjikar 		uqp->list_entry = NULL;
790c39526b7SPramod Gunjikar 		mutex_exit(&uctxt->lock);
791c39526b7SPramod Gunjikar 	}
792c39526b7SPramod Gunjikar 
793c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&uqp->uobj, sol_ofs_uobj_free);
794c39526b7SPramod Gunjikar 
795c39526b7SPramod Gunjikar 	if (uctxt->uctxt_free_pending && (uctxt->qp_list).count == 0) {
796c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str,
797c39526b7SPramod Gunjikar 		    "uqp_free: freeing uctxt %p", uctxt);
798c39526b7SPramod Gunjikar 		sol_ofs_uobj_deref(&uctxt->uobj, sol_ofs_uobj_free);
799c39526b7SPramod Gunjikar 	}
800c39526b7SPramod Gunjikar 	return (0);
801c39526b7SPramod Gunjikar }
802c39526b7SPramod Gunjikar 
803c39526b7SPramod Gunjikar /*
804c39526b7SPramod Gunjikar  * Function:
805c39526b7SPramod Gunjikar  *      sol_uverbs_destroy_qp
806c39526b7SPramod Gunjikar  * Input:
807c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
808c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing the destroy command.
809c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
810c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
811c39526b7SPramod Gunjikar  * Output:
812c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
813c39526b7SPramod Gunjikar  * Returns:
814c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
815c39526b7SPramod Gunjikar  * Description:
816c39526b7SPramod Gunjikar  *      User verbs  entry point to destroy a device QP.
817c39526b7SPramod Gunjikar  */
818c39526b7SPramod Gunjikar /* ARGSUSED */
819c39526b7SPramod Gunjikar int
sol_uverbs_destroy_qp(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)820c39526b7SPramod Gunjikar sol_uverbs_destroy_qp(uverbs_uctxt_uobj_t *uctxt, char *buf,
821c39526b7SPramod Gunjikar     int in_len, int out_len)
822c39526b7SPramod Gunjikar {
823c39526b7SPramod Gunjikar 	struct ib_uverbs_destroy_qp		cmd;
824c39526b7SPramod Gunjikar 	struct ib_uverbs_destroy_qp_resp	resp;
825c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t			*uqp;
826c39526b7SPramod Gunjikar 	int					rc;
827c39526b7SPramod Gunjikar 
828c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
829c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
830c39526b7SPramod Gunjikar 
831c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "DESTROY QP: entry "
832c39526b7SPramod Gunjikar 	    "(qp_handle=%d)", cmd.qp_handle);
833c39526b7SPramod Gunjikar 
834c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_write(cmd.qp_handle);
835c39526b7SPramod Gunjikar 	if (uqp == NULL) {
836c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
837c39526b7SPramod Gunjikar 		    "destroy_qp() : List lookup failure");
838c39526b7SPramod Gunjikar 		rc = EINVAL;
839c39526b7SPramod Gunjikar 		goto err_out;
840c39526b7SPramod Gunjikar 	}
841c39526b7SPramod Gunjikar 
842c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "DESTROY QP: qp_handle=%d, "
843c39526b7SPramod Gunjikar 	    "uqp %p, qp_ptr %p", cmd.qp_handle, uqp, uqp->qp);
844c39526b7SPramod Gunjikar 
845c39526b7SPramod Gunjikar 	if (!llist_empty(&uqp->mcast_list)) {
846c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
847c39526b7SPramod Gunjikar 		    "destroy_qp() called with attached MC group(s)");
848c39526b7SPramod Gunjikar 		rc = EBUSY;
849c39526b7SPramod Gunjikar 		goto err_busy;
850c39526b7SPramod Gunjikar 	}
851c39526b7SPramod Gunjikar 
852c39526b7SPramod Gunjikar 	uverbs_release_uqp_uevents(uctxt->async_evfile, uqp);
853c39526b7SPramod Gunjikar 	resp.events_reported = uqp->async_events_reported;
854c39526b7SPramod Gunjikar 
855c39526b7SPramod Gunjikar 	/*
856c39526b7SPramod Gunjikar 	 * If ucma has disabled QP free for this QP, set FREE_PENDING
857c39526b7SPramod Gunjikar 	 * flag so that the QP can be freed when UCMA enables QP_FREE.
858c39526b7SPramod Gunjikar 	 * Call ibt_free_qp() is ucma has not disabled QP free.
859c39526b7SPramod Gunjikar 	 */
860c39526b7SPramod Gunjikar 	if (uqp->uqp_free_state == SOL_UVERBS2UCMA_DISABLE_QP_FREE) {
861c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
862c39526b7SPramod Gunjikar 		    "destroy_qp() - UCMA disabled");
863c39526b7SPramod Gunjikar 		uqp->uqp_free_state = SOL_UVERBS2UCMA_FREE_PENDING;
864c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uqp->uobj);
865c39526b7SPramod Gunjikar 		rc = 0;
866c39526b7SPramod Gunjikar 		goto report_qp_evts;
867c39526b7SPramod Gunjikar 	} else {
868c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
869c39526b7SPramod Gunjikar 		    "destroy_qp() - freeing QP : %p", uqp);
870c39526b7SPramod Gunjikar 		rc = uverbs_uqp_free(uqp, uctxt);
871c39526b7SPramod Gunjikar 	}
872c39526b7SPramod Gunjikar 
873c39526b7SPramod Gunjikar 	if (rc) {
874c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
875c39526b7SPramod Gunjikar 		    "destroy_qp() - ibt_free_qp() fail %d", rc);
876c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
877*fffafeb2SJohnny Cheung 		goto err_out;
878c39526b7SPramod Gunjikar 	}
879c39526b7SPramod Gunjikar 
880c39526b7SPramod Gunjikar report_qp_evts:
881c39526b7SPramod Gunjikar #ifdef	_LP64
882c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
883c39526b7SPramod Gunjikar #else
884c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
885c39526b7SPramod Gunjikar #endif
886c39526b7SPramod Gunjikar 	if (rc != 0) {
887c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
888c39526b7SPramod Gunjikar 		    "destroy_qp() : copyout failure %x", rc);
889c39526b7SPramod Gunjikar 		rc = EFAULT;
890c39526b7SPramod Gunjikar 		goto err_out;
891c39526b7SPramod Gunjikar 	}
892c39526b7SPramod Gunjikar 
893c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
894c39526b7SPramod Gunjikar 
895c39526b7SPramod Gunjikar err_busy:
896c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
897c39526b7SPramod Gunjikar 
898c39526b7SPramod Gunjikar err_out:
899c39526b7SPramod Gunjikar 	return (rc);
900c39526b7SPramod Gunjikar }
901c39526b7SPramod Gunjikar 
902c39526b7SPramod Gunjikar /*
903c39526b7SPramod Gunjikar  * Function:
904c39526b7SPramod Gunjikar  *      uverbs_copy_path_info_from_ibv
905c39526b7SPramod Gunjikar  * Input:
906c39526b7SPramod Gunjikar  *      src_path	- IB OFED path.
907c39526b7SPramod Gunjikar  * Output:
908c39526b7SPramod Gunjikar  *      dest_path	- IBT path.
909c39526b7SPramod Gunjikar  * Returns:
910c39526b7SPramod Gunjikar  *      None
911c39526b7SPramod Gunjikar  * Description:
912c39526b7SPramod Gunjikar  *      Helper to copy from the OFED path format to IBT path format.
913c39526b7SPramod Gunjikar  */
914c39526b7SPramod Gunjikar static void
uverbs_copy_path_info_from_ibv(struct ib_uverbs_qp_dest * src_path,ibt_cep_path_t * dest_path)915c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibv(struct ib_uverbs_qp_dest *src_path,
916c39526b7SPramod Gunjikar     ibt_cep_path_t *dest_path)
917c39526b7SPramod Gunjikar {
918c39526b7SPramod Gunjikar 	ASSERT(src_path != NULL);
919c39526b7SPramod Gunjikar 	ASSERT(dest_path != NULL);
920c39526b7SPramod Gunjikar 
921c39526b7SPramod Gunjikar 	(void) memcpy(&dest_path->cep_adds_vect.av_dgid,
922c39526b7SPramod Gunjikar 	    &src_path->dgid[0], sizeof (src_path->dgid));
923c39526b7SPramod Gunjikar 
924c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_flow	= src_path->flow_label;
925c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_dlid	= src_path->dlid;
926c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_hop		= src_path->hop_limit;
927c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_tclass	= src_path->traffic_class;
928c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_srvl	= src_path->sl & 0x0f;
929c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_port_num	= src_path->port_num;
930c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_src_path	= src_path->src_path_bits;
931c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_send_grh	= src_path->is_global;
932c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_sgid_ix	= src_path->sgid_index;
933c39526b7SPramod Gunjikar 	dest_path->cep_adds_vect.av_srate 	= src_path->static_rate;
934c39526b7SPramod Gunjikar }
935c39526b7SPramod Gunjikar 
936c39526b7SPramod Gunjikar /*
937c39526b7SPramod Gunjikar  * Function:
938c39526b7SPramod Gunjikar  *      uverbs_modify_update
939c39526b7SPramod Gunjikar  * Input:
940c39526b7SPramod Gunjikar  *      cmd		- The user verbs modify command to be translated.
941c39526b7SPramod Gunjikar  *	cur_state	- The current QP state
942c39526b7SPramod Gunjikar  *	new_state	- The new QP state
943c39526b7SPramod Gunjikar  * Output:
944c39526b7SPramod Gunjikar  *      qp_query_attr	- The IBT QP attributes.
945c39526b7SPramod Gunjikar  *	flags		- The IBT flags.
946c39526b7SPramod Gunjikar  * Returns:
947c39526b7SPramod Gunjikar  *      None
948c39526b7SPramod Gunjikar  * Description:
949c39526b7SPramod Gunjikar  *      Helper to convert OFED user verbs QP modify attributes to IBT
950c39526b7SPramod Gunjikar  *	QP modify attributes.  Note that on required parameters, the
951c39526b7SPramod Gunjikar  *	individual IBT modify flags are not set (there is a global
952c39526b7SPramod Gunjikar  *	flag for the transition), only optional flags are set.
953c39526b7SPramod Gunjikar  */
954c39526b7SPramod Gunjikar static void
uverbs_modify_update(struct ib_uverbs_modify_qp * cmd,enum ib_qp_state cur_state,enum ib_qp_state new_state,ibt_qp_query_attr_t * qp_query_attr,ibt_cep_modify_flags_t * flags)955c39526b7SPramod Gunjikar uverbs_modify_update(struct ib_uverbs_modify_qp *cmd,
956c39526b7SPramod Gunjikar     enum ib_qp_state cur_state, enum ib_qp_state new_state,
957c39526b7SPramod Gunjikar     ibt_qp_query_attr_t *qp_query_attr, ibt_cep_modify_flags_t *flags)
958c39526b7SPramod Gunjikar {
959c39526b7SPramod Gunjikar 	ibt_qp_info_t		*qp_infop;
960c39526b7SPramod Gunjikar 	ibt_qp_rc_attr_t	*rcp;
961c39526b7SPramod Gunjikar 	ibt_qp_uc_attr_t	*ucp;
962c39526b7SPramod Gunjikar 	ibt_qp_ud_attr_t	*udp;
963c39526b7SPramod Gunjikar 
964c39526b7SPramod Gunjikar 	*flags = IBT_CEP_SET_NOTHING;
965c39526b7SPramod Gunjikar 	qp_infop = &(qp_query_attr->qp_info);
966c39526b7SPramod Gunjikar 	rcp = &(qp_infop->qp_transport.rc);
967c39526b7SPramod Gunjikar 	ucp = &(qp_infop->qp_transport.uc);
968c39526b7SPramod Gunjikar 	udp = &(qp_infop->qp_transport.ud);
969c39526b7SPramod Gunjikar 
970c39526b7SPramod Gunjikar 	switch (cur_state) {
971c39526b7SPramod Gunjikar 	case IB_QPS_RESET:
972c39526b7SPramod Gunjikar 		qp_infop->qp_current_state = IBT_STATE_RESET;
973c39526b7SPramod Gunjikar 		break;
974c39526b7SPramod Gunjikar 	case IB_QPS_INIT:
975c39526b7SPramod Gunjikar 		qp_infop->qp_current_state = IBT_STATE_INIT;
976c39526b7SPramod Gunjikar 		break;
977c39526b7SPramod Gunjikar 	case IB_QPS_RTR:
978c39526b7SPramod Gunjikar 		qp_infop->qp_current_state = IBT_STATE_RTR;
979c39526b7SPramod Gunjikar 		break;
980c39526b7SPramod Gunjikar 	case IB_QPS_RTS:
981c39526b7SPramod Gunjikar 		qp_infop->qp_current_state = IBT_STATE_RTS;
982c39526b7SPramod Gunjikar 		break;
983c39526b7SPramod Gunjikar 	case IB_QPS_SQD:
984c39526b7SPramod Gunjikar 		qp_infop->qp_current_state = IBT_STATE_SQD;
985c39526b7SPramod Gunjikar 		break;
986c39526b7SPramod Gunjikar 	case IB_QPS_SQE:
987c39526b7SPramod Gunjikar 		qp_infop->qp_current_state = IBT_STATE_SQE;
988c39526b7SPramod Gunjikar 		break;
989c39526b7SPramod Gunjikar 	case IB_QPS_ERR:
990c39526b7SPramod Gunjikar 		qp_infop->qp_current_state = IBT_STATE_ERROR;
991c39526b7SPramod Gunjikar 		break;
992c39526b7SPramod Gunjikar 	}
993c39526b7SPramod Gunjikar 
994c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_STATE) {
995c39526b7SPramod Gunjikar 		switch (new_state) {
996c39526b7SPramod Gunjikar 		case IB_QPS_RESET:
997c39526b7SPramod Gunjikar 			qp_infop->qp_state = IBT_STATE_RESET;
998c39526b7SPramod Gunjikar 			*flags |= IBT_CEP_SET_STATE;
999c39526b7SPramod Gunjikar 			break;
1000c39526b7SPramod Gunjikar 
1001c39526b7SPramod Gunjikar 		case IB_QPS_INIT:
1002c39526b7SPramod Gunjikar 			qp_infop->qp_state = IBT_STATE_INIT;
1003c39526b7SPramod Gunjikar 			if (cur_state == IB_QPS_RESET) {
1004c39526b7SPramod Gunjikar 				*flags |= IBT_CEP_SET_RESET_INIT;
1005c39526b7SPramod Gunjikar 			} else {
1006c39526b7SPramod Gunjikar 				*flags |= IBT_CEP_SET_STATE;
1007c39526b7SPramod Gunjikar 			}
1008c39526b7SPramod Gunjikar 			break;
1009c39526b7SPramod Gunjikar 
1010c39526b7SPramod Gunjikar 		case IB_QPS_RTR:
1011c39526b7SPramod Gunjikar 			qp_infop->qp_state = IBT_STATE_RTR;
1012c39526b7SPramod Gunjikar 			if (cur_state == IB_QPS_INIT) {
1013c39526b7SPramod Gunjikar 				*flags |= IBT_CEP_SET_INIT_RTR;
1014c39526b7SPramod Gunjikar 			} else {
1015c39526b7SPramod Gunjikar 				*flags |= IBT_CEP_SET_STATE;
1016c39526b7SPramod Gunjikar 			}
1017c39526b7SPramod Gunjikar 			break;
1018c39526b7SPramod Gunjikar 
1019c39526b7SPramod Gunjikar 		case IB_QPS_RTS:
1020c39526b7SPramod Gunjikar 			qp_infop->qp_state = IBT_STATE_RTS;
1021c39526b7SPramod Gunjikar 
1022c39526b7SPramod Gunjikar 			/*
1023c39526b7SPramod Gunjikar 			 * For RTS transitions other than RTR we must
1024c39526b7SPramod Gunjikar 			 * specify the assumption for the qp state.
1025c39526b7SPramod Gunjikar 			 */
1026c39526b7SPramod Gunjikar 			if (cur_state == IB_QPS_RTR) {
1027c39526b7SPramod Gunjikar 				*flags |= IBT_CEP_SET_RTR_RTS;
1028c39526b7SPramod Gunjikar 			} else {
1029c39526b7SPramod Gunjikar 				ibt_cep_state_t *ibt_curr =
1030c39526b7SPramod Gunjikar 				    &qp_infop->qp_current_state;
1031c39526b7SPramod Gunjikar 
1032c39526b7SPramod Gunjikar 				switch (cur_state) {
1033c39526b7SPramod Gunjikar 				case IB_QPS_RTS:
1034c39526b7SPramod Gunjikar 					*ibt_curr = IBT_STATE_RTS;
1035c39526b7SPramod Gunjikar 					break;
1036c39526b7SPramod Gunjikar 
1037c39526b7SPramod Gunjikar 				case IB_QPS_SQD:
1038c39526b7SPramod Gunjikar 					*ibt_curr = IBT_STATE_SQD;
1039c39526b7SPramod Gunjikar 					break;
1040c39526b7SPramod Gunjikar 
1041c39526b7SPramod Gunjikar 				case IB_QPS_SQE:
1042c39526b7SPramod Gunjikar 					*ibt_curr = IBT_STATE_SQE;
1043c39526b7SPramod Gunjikar 					break;
1044c39526b7SPramod Gunjikar 				}
1045c39526b7SPramod Gunjikar 				*flags |= IBT_CEP_SET_STATE;
1046c39526b7SPramod Gunjikar 			}
1047c39526b7SPramod Gunjikar 			break;
1048c39526b7SPramod Gunjikar 
1049c39526b7SPramod Gunjikar 		case IB_QPS_SQD:
1050c39526b7SPramod Gunjikar 			qp_infop->qp_state = IBT_STATE_SQD;
1051c39526b7SPramod Gunjikar 			*flags |= IBT_CEP_SET_STATE;
1052c39526b7SPramod Gunjikar 			break;
1053c39526b7SPramod Gunjikar 
1054c39526b7SPramod Gunjikar 		case IB_QPS_SQE:
1055c39526b7SPramod Gunjikar 			qp_infop->qp_state = IBT_STATE_SQE;
1056c39526b7SPramod Gunjikar 			*flags |= IBT_CEP_SET_STATE;
1057c39526b7SPramod Gunjikar 			break;
1058c39526b7SPramod Gunjikar 
1059c39526b7SPramod Gunjikar 		case IB_QPS_ERR:
1060c39526b7SPramod Gunjikar 			qp_infop->qp_state = IBT_STATE_ERROR;
1061c39526b7SPramod Gunjikar 			*flags |= IBT_CEP_SET_STATE;
1062c39526b7SPramod Gunjikar 			break;
1063c39526b7SPramod Gunjikar 		}
1064c39526b7SPramod Gunjikar 	}
1065c39526b7SPramod Gunjikar 
1066c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_PKEY_INDEX) {
1067c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UD_SRV) {
1068c39526b7SPramod Gunjikar 			udp->ud_pkey_ix = cmd->pkey_index;
1069c39526b7SPramod Gunjikar 		} else if (qp_infop->qp_trans == IBT_RC_SRV) {
1070c39526b7SPramod Gunjikar 			rcp->rc_path.cep_pkey_ix = cmd->pkey_index;
1071c39526b7SPramod Gunjikar 		}
1072c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_PKEY_IX;
1073c39526b7SPramod Gunjikar 	}
1074c39526b7SPramod Gunjikar 
1075c39526b7SPramod Gunjikar 
1076c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_AV) {
1077c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1078c39526b7SPramod Gunjikar 			uverbs_copy_path_info_from_ibv(&cmd->dest,
1079c39526b7SPramod Gunjikar 			    &rcp->rc_path);
1080c39526b7SPramod Gunjikar 		}
1081c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_ADDS_VECT;
1082c39526b7SPramod Gunjikar 	}
1083c39526b7SPramod Gunjikar 
1084c39526b7SPramod Gunjikar 	if (qp_infop->qp_trans == IBT_RC_SRV) {
1085c39526b7SPramod Gunjikar 		if (cmd->attr_mask & IB_QP_TIMEOUT) {
1086c39526b7SPramod Gunjikar 			rcp->rc_path.cep_timeout = cmd->timeout;
1087c39526b7SPramod Gunjikar 			*flags |= IBT_CEP_SET_TIMEOUT;
1088c39526b7SPramod Gunjikar 		}
1089c39526b7SPramod Gunjikar 	}
1090c39526b7SPramod Gunjikar 
1091c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_PORT) {
1092c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UD_SRV) {
1093c39526b7SPramod Gunjikar 			udp->ud_port = cmd->port_num;
1094c39526b7SPramod Gunjikar 		} else if (qp_infop->qp_trans == IBT_RC_SRV) {
1095c39526b7SPramod Gunjikar 			rcp->rc_path.cep_hca_port_num = cmd->port_num;
1096c39526b7SPramod Gunjikar 		}
1097c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_PORT;
1098c39526b7SPramod Gunjikar 	}
1099c39526b7SPramod Gunjikar 
1100c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_QKEY) {
1101c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UD_SRV) {
1102c39526b7SPramod Gunjikar 			udp->ud_qkey = cmd->qkey;
1103c39526b7SPramod Gunjikar 		}
1104c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RD_SRV) {
1105c39526b7SPramod Gunjikar 			qp_infop->qp_transport.rd.rd_qkey = cmd->qkey;
1106c39526b7SPramod Gunjikar 		}
1107c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_QKEY;
1108c39526b7SPramod Gunjikar 	}
1109c39526b7SPramod Gunjikar 
1110c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_PATH_MTU) {
1111c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UC_SRV) {
1112c39526b7SPramod Gunjikar 			ucp->uc_path_mtu = cmd->path_mtu;
1113c39526b7SPramod Gunjikar 		}
1114c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1115c39526b7SPramod Gunjikar 			rcp->rc_path_mtu = cmd->path_mtu;
1116c39526b7SPramod Gunjikar 		}
1117c39526b7SPramod Gunjikar 	}
1118c39526b7SPramod Gunjikar 
1119c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_RETRY_CNT) {
1120c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1121c39526b7SPramod Gunjikar 			rcp->rc_retry_cnt = cmd->retry_cnt & 0x7;
1122c39526b7SPramod Gunjikar 		}
1123c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_RETRY;
1124c39526b7SPramod Gunjikar 	}
1125c39526b7SPramod Gunjikar 
1126c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_RNR_RETRY) {
1127c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1128c39526b7SPramod Gunjikar 			rcp->rc_rnr_retry_cnt = cmd->rnr_retry;
1129c39526b7SPramod Gunjikar 		}
1130c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_RNR_NAK_RETRY;
1131c39526b7SPramod Gunjikar 	}
1132c39526b7SPramod Gunjikar 
1133c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_MIN_RNR_TIMER) {
1134c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1135c39526b7SPramod Gunjikar 			rcp->rc_min_rnr_nak = cmd->min_rnr_timer;
1136c39526b7SPramod Gunjikar 		}
1137c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_MIN_RNR_NAK;
1138c39526b7SPramod Gunjikar 	}
1139c39526b7SPramod Gunjikar 
1140c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_RQ_PSN) {
1141c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1142c39526b7SPramod Gunjikar 			rcp->rc_rq_psn = cmd->rq_psn;
1143c39526b7SPramod Gunjikar 		}
1144c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UC_SRV) {
1145c39526b7SPramod Gunjikar 			ucp->uc_rq_psn = cmd->rq_psn;
1146c39526b7SPramod Gunjikar 		}
1147c39526b7SPramod Gunjikar 	}
1148c39526b7SPramod Gunjikar 
1149c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_ALT_PATH) {
1150c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1151c39526b7SPramod Gunjikar 			uverbs_copy_path_info_from_ibv(&cmd->alt_dest,
1152c39526b7SPramod Gunjikar 			    &rcp->rc_alt_path);
1153c39526b7SPramod Gunjikar 
1154c39526b7SPramod Gunjikar 			rcp->rc_alt_path.cep_hca_port_num = cmd->alt_port_num;
1155c39526b7SPramod Gunjikar 			rcp->rc_alt_path.cep_timeout = cmd->alt_timeout;
1156c39526b7SPramod Gunjikar 		}
1157c39526b7SPramod Gunjikar 
1158c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UC_SRV) {
1159c39526b7SPramod Gunjikar 			uverbs_copy_path_info_from_ibv(&cmd->alt_dest,
1160c39526b7SPramod Gunjikar 			    &ucp->uc_alt_path);
1161c39526b7SPramod Gunjikar 
1162c39526b7SPramod Gunjikar 			ucp->uc_alt_path.cep_hca_port_num = cmd->alt_port_num;
1163c39526b7SPramod Gunjikar 			ucp->uc_alt_path.cep_timeout = cmd->alt_timeout;
1164c39526b7SPramod Gunjikar 		}
1165c39526b7SPramod Gunjikar 
1166c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_ALT_PATH;
1167c39526b7SPramod Gunjikar 	}
1168c39526b7SPramod Gunjikar 
1169c39526b7SPramod Gunjikar 
1170c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_SQ_PSN) {
1171c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UD_SRV) {
1172c39526b7SPramod Gunjikar 			udp->ud_sq_psn = cmd->sq_psn;
1173c39526b7SPramod Gunjikar 		}
1174c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UC_SRV) {
1175c39526b7SPramod Gunjikar 			ucp->uc_sq_psn = cmd->sq_psn;
1176c39526b7SPramod Gunjikar 		}
1177c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1178c39526b7SPramod Gunjikar 			rcp->rc_sq_psn = cmd->sq_psn;
1179c39526b7SPramod Gunjikar 		}
1180c39526b7SPramod Gunjikar 	}
1181c39526b7SPramod Gunjikar 
1182c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
1183c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1184c39526b7SPramod Gunjikar 			rcp->rc_rdma_ra_out = cmd->max_rd_atomic;
1185c39526b7SPramod Gunjikar 		}
1186c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_STATE;
1187c39526b7SPramod Gunjikar 	}
1188c39526b7SPramod Gunjikar 
1189c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
1190c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1191c39526b7SPramod Gunjikar 			rcp->rc_rdma_ra_in = cmd->max_dest_rd_atomic;
1192c39526b7SPramod Gunjikar 		}
1193c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_RDMARA_IN | IBT_CEP_SET_STATE;
1194c39526b7SPramod Gunjikar 	}
1195c39526b7SPramod Gunjikar 
1196c39526b7SPramod Gunjikar 	if (cmd->attr_mask & (IB_QP_ACCESS_FLAGS |
1197c39526b7SPramod Gunjikar 	    IB_QP_MAX_DEST_RD_ATOMIC)) {
1198c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1199c39526b7SPramod Gunjikar 			uint32_t	access_flags = IBT_CEP_NO_FLAGS;
1200c39526b7SPramod Gunjikar 
1201c39526b7SPramod Gunjikar 			if (rcp->rc_rdma_ra_in) {
1202c39526b7SPramod Gunjikar 				access_flags	|= IBT_CEP_RDMA_WR;
1203c39526b7SPramod Gunjikar 				*flags		|= IBT_CEP_SET_RDMA_W;
1204c39526b7SPramod Gunjikar 			}
1205c39526b7SPramod Gunjikar 
1206c39526b7SPramod Gunjikar 			if (cmd->attr_mask & IB_QP_ACCESS_FLAGS) {
1207c39526b7SPramod Gunjikar 				if (cmd->qp_access_flags &
1208c39526b7SPramod Gunjikar 				    IB_ACCESS_REMOTE_WRITE) {
1209c39526b7SPramod Gunjikar 					access_flags	|= IBT_CEP_RDMA_WR;
1210c39526b7SPramod Gunjikar 					*flags		|= IBT_CEP_SET_RDMA_W;
1211c39526b7SPramod Gunjikar 				}
1212c39526b7SPramod Gunjikar 				if (cmd->qp_access_flags &
1213c39526b7SPramod Gunjikar 				    IB_ACCESS_REMOTE_READ) {
1214c39526b7SPramod Gunjikar 					access_flags	|= IBT_CEP_RDMA_RD;
1215c39526b7SPramod Gunjikar 					*flags		|= IBT_CEP_SET_RDMA_R;
1216c39526b7SPramod Gunjikar 				}
1217c39526b7SPramod Gunjikar 				if (cmd->qp_access_flags &
1218c39526b7SPramod Gunjikar 				    IB_ACCESS_REMOTE_ATOMIC) {
1219c39526b7SPramod Gunjikar 					access_flags	|= IBT_CEP_ATOMIC;
1220c39526b7SPramod Gunjikar 					*flags		|= IBT_CEP_SET_ATOMIC;
1221c39526b7SPramod Gunjikar 				}
1222c39526b7SPramod Gunjikar 			}
1223c39526b7SPramod Gunjikar 			qp_infop->qp_flags &= ~(IBT_CEP_RDMA_WR |
1224c39526b7SPramod Gunjikar 			    IBT_CEP_RDMA_RD | IBT_CEP_ATOMIC);
1225c39526b7SPramod Gunjikar 			qp_infop->qp_flags |= access_flags;
1226c39526b7SPramod Gunjikar 		}
1227c39526b7SPramod Gunjikar 	}
1228c39526b7SPramod Gunjikar 
1229c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_PATH_MIG_STATE) {
1230c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1231c39526b7SPramod Gunjikar 			if (cmd->path_mig_state == IB_MIG_MIGRATED) {
1232c39526b7SPramod Gunjikar 				rcp->rc_mig_state = IBT_STATE_MIGRATED;
1233c39526b7SPramod Gunjikar 			}
1234c39526b7SPramod Gunjikar 			if (cmd->path_mig_state == IB_MIG_REARM) {
1235c39526b7SPramod Gunjikar 				rcp->rc_mig_state = IBT_STATE_REARMED;
1236c39526b7SPramod Gunjikar 			}
1237c39526b7SPramod Gunjikar 			if (cmd->path_mig_state == IB_MIG_ARMED) {
1238c39526b7SPramod Gunjikar 				rcp->rc_mig_state = IBT_STATE_ARMED;
1239c39526b7SPramod Gunjikar 			}
1240c39526b7SPramod Gunjikar 		}
1241c39526b7SPramod Gunjikar 
1242c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UC_SRV) {
1243c39526b7SPramod Gunjikar 			if (cmd->path_mig_state == IB_MIG_MIGRATED) {
1244c39526b7SPramod Gunjikar 				ucp->uc_mig_state = IBT_STATE_MIGRATED;
1245c39526b7SPramod Gunjikar 			}
1246c39526b7SPramod Gunjikar 			if (cmd->path_mig_state == IB_MIG_REARM) {
1247c39526b7SPramod Gunjikar 				ucp->uc_mig_state = IBT_STATE_REARMED;
1248c39526b7SPramod Gunjikar 			}
1249c39526b7SPramod Gunjikar 			if (cmd->path_mig_state == IB_MIG_ARMED) {
1250c39526b7SPramod Gunjikar 				ucp->uc_mig_state = IBT_STATE_ARMED;
1251c39526b7SPramod Gunjikar 			}
1252c39526b7SPramod Gunjikar 		}
1253c39526b7SPramod Gunjikar 		*flags |= IBT_CEP_SET_MIG;
1254c39526b7SPramod Gunjikar 	}
1255c39526b7SPramod Gunjikar 
1256c39526b7SPramod Gunjikar 	if (cmd->attr_mask & IB_QP_DEST_QPN) {
1257c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_RC_SRV) {
1258c39526b7SPramod Gunjikar 			rcp->rc_dst_qpn = cmd->dest_qp_num;
1259c39526b7SPramod Gunjikar 		}
1260c39526b7SPramod Gunjikar 		if (qp_infop->qp_trans == IBT_UC_SRV) {
1261c39526b7SPramod Gunjikar 			ucp->uc_dst_qpn = cmd->dest_qp_num;
1262c39526b7SPramod Gunjikar 		}
1263c39526b7SPramod Gunjikar 	}
1264c39526b7SPramod Gunjikar }
1265c39526b7SPramod Gunjikar 
1266c39526b7SPramod Gunjikar 
1267c39526b7SPramod Gunjikar static void
uverbs_qp_print_path(ibt_cep_path_t * pathp)1268c39526b7SPramod Gunjikar uverbs_qp_print_path(ibt_cep_path_t *pathp)
1269c39526b7SPramod Gunjikar {
1270c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qp_print_pathp %p", pathp);
1271c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "cep_pkey_ix %x, "
1272c39526b7SPramod Gunjikar 	    "cep_hca_port_num %x", pathp->cep_pkey_ix, pathp->cep_hca_port_num);
1273c39526b7SPramod Gunjikar }
1274c39526b7SPramod Gunjikar 
1275c39526b7SPramod Gunjikar static void
uverbs_print_query_qp(ibt_qp_hdl_t qp_hdlp)1276c39526b7SPramod Gunjikar uverbs_print_query_qp(ibt_qp_hdl_t qp_hdlp)
1277c39526b7SPramod Gunjikar {
1278c39526b7SPramod Gunjikar 	ibt_qp_query_attr_t	qp_query_attr;
1279c39526b7SPramod Gunjikar 	ibt_qp_info_t		*qp_infop = &qp_query_attr.qp_info;
1280c39526b7SPramod Gunjikar 	ibt_qp_rc_attr_t	*rcp = &((qp_infop->qp_transport).rc);
1281c39526b7SPramod Gunjikar 	ibt_status_t		rc;
1282c39526b7SPramod Gunjikar 
1283c39526b7SPramod Gunjikar 	bzero(&qp_query_attr, sizeof (qp_query_attr));
1284c39526b7SPramod Gunjikar 	rc =  ibt_query_qp(qp_hdlp, &qp_query_attr);
1285c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1286c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "print_query_qp -"
1287c39526b7SPramod Gunjikar 		    "ibt_query_qp() failed - rc=%d", rc);
1288c39526b7SPramod Gunjikar 		return;
1289c39526b7SPramod Gunjikar 	}
1290c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qp_print %p", qp_hdlp);
1291c39526b7SPramod Gunjikar 
1292c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qp_sq_cq %p, qp_rq_cq %p, "
1293c39526b7SPramod Gunjikar 	    "qp_qpn %x, qp_sq_sgl %x, qp_rq_sgl %x, qp_srq %p, qp_flags %x",
1294c39526b7SPramod Gunjikar 	    qp_query_attr.qp_sq_cq, qp_query_attr.qp_rq_cq,
1295c39526b7SPramod Gunjikar 	    qp_query_attr.qp_qpn, qp_query_attr.qp_sq_sgl,
1296c39526b7SPramod Gunjikar 	    qp_query_attr.qp_rq_sgl, qp_query_attr.qp_srq,
1297c39526b7SPramod Gunjikar 	    qp_query_attr.qp_flags);
1298c39526b7SPramod Gunjikar 
1299c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qp_sq_sz %x, qp_rq_sz %x, "
1300c39526b7SPramod Gunjikar 	    "qp_state %x, qp_current_state %x, qp_flags %x, qp_trans %x",
1301c39526b7SPramod Gunjikar 	    qp_infop->qp_sq_sz, qp_infop->qp_rq_sz, qp_infop->qp_state,
1302c39526b7SPramod Gunjikar 	    qp_infop->qp_current_state,  qp_infop->qp_flags,
1303c39526b7SPramod Gunjikar 	    qp_infop->qp_trans);
1304c39526b7SPramod Gunjikar 
1305c39526b7SPramod Gunjikar 	if (qp_infop->qp_trans == IBT_RC_SRV) {
1306c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "rc_sq_psn %x, rc_rq_psn %x, "
1307c39526b7SPramod Gunjikar 	    "rc_dst_qpn %x, rc_mig_state %x, rc_rnr_retry_cnt %x,"
1308c39526b7SPramod Gunjikar 	    "rc_retry_cnt %x rc_rdma_ra_out %x, rc_rdma_ra_in %x,"
1309c39526b7SPramod Gunjikar 	    "rc_min_rnr_nak %x, rc_path_mtu %x",
1310c39526b7SPramod Gunjikar 	    rcp->rc_sq_psn, rcp->rc_rq_psn, rcp->rc_dst_qpn, rcp->rc_mig_state,
1311c39526b7SPramod Gunjikar 	    rcp->rc_rnr_retry_cnt, rcp->rc_retry_cnt, rcp->rc_rdma_ra_out,
1312c39526b7SPramod Gunjikar 	    rcp->rc_rdma_ra_in, rcp->rc_min_rnr_nak, rcp->rc_path_mtu);
1313c39526b7SPramod Gunjikar 	uverbs_qp_print_path(&rcp->rc_path);
1314c39526b7SPramod Gunjikar 	uverbs_qp_print_path(&rcp->rc_alt_path);
1315c39526b7SPramod Gunjikar 	}
1316c39526b7SPramod Gunjikar }
1317c39526b7SPramod Gunjikar 
1318c39526b7SPramod Gunjikar 
1319c39526b7SPramod Gunjikar /*
1320c39526b7SPramod Gunjikar  * Function:
1321c39526b7SPramod Gunjikar  *      sol_uverbs_modify_qp
1322c39526b7SPramod Gunjikar  * Input:
1323c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
1324c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing QP modify command.
1325c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
1326c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
1327c39526b7SPramod Gunjikar  * Output:
1328c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
1329c39526b7SPramod Gunjikar  * Returns:
1330c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
1331c39526b7SPramod Gunjikar  * Description:
1332c39526b7SPramod Gunjikar  *      User verbs entry point to modify a device QP.
1333c39526b7SPramod Gunjikar  */
1334c39526b7SPramod Gunjikar /* ARGSUSED */
1335c39526b7SPramod Gunjikar int
sol_uverbs_modify_qp(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1336c39526b7SPramod Gunjikar sol_uverbs_modify_qp(uverbs_uctxt_uobj_t *uctxt, char *buf,
1337c39526b7SPramod Gunjikar     int in_len, int out_len)
1338c39526b7SPramod Gunjikar {
1339c39526b7SPramod Gunjikar 	struct ib_uverbs_modify_qp	cmd;
1340c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t		*uqp;
1341c39526b7SPramod Gunjikar 	ibt_qp_query_attr_t		qp_query_attr;
1342c39526b7SPramod Gunjikar 	ibt_cep_modify_flags_t		flags;
1343c39526b7SPramod Gunjikar 	ibt_queue_sizes_t		size;
1344c39526b7SPramod Gunjikar 	int				rc;
1345c39526b7SPramod Gunjikar 	enum ib_qp_state		cur_state, new_state;
1346c39526b7SPramod Gunjikar 
1347c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1348c39526b7SPramod Gunjikar 
1349c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp - qp_hdl %d, "
1350c39526b7SPramod Gunjikar 	    "attr_mask %x", cmd.qp_handle, cmd.attr_mask);
1351c39526b7SPramod Gunjikar 
1352c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_write(cmd.qp_handle);
1353c39526b7SPramod Gunjikar 	if (uqp == NULL) {
1354c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "modify_qp -"
1355c39526b7SPramod Gunjikar 		    "List lookup failure");
1356c39526b7SPramod Gunjikar 		rc = EINVAL;
1357c39526b7SPramod Gunjikar 		goto err_out;
1358c39526b7SPramod Gunjikar 	}
1359c39526b7SPramod Gunjikar 
1360c39526b7SPramod Gunjikar 	/*
1361c39526b7SPramod Gunjikar 	 * Has the UCMA asked us to ignore QP modify operations?
1362c39526b7SPramod Gunjikar 	 * This is required because of differences in the level of
1363c39526b7SPramod Gunjikar 	 * abstraction fo CM processing between IBT and OFED.
1364c39526b7SPramod Gunjikar 	 */
1365c39526b7SPramod Gunjikar 	if (uqp->disable_qp_mod == TRUE) {
1366c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str, "modify_qp -"
1367c39526b7SPramod Gunjikar 		    "qp_mod disabled");
1368c39526b7SPramod Gunjikar 		goto done;
1369c39526b7SPramod Gunjikar 	}
1370c39526b7SPramod Gunjikar 
1371c39526b7SPramod Gunjikar 	/*
1372c39526b7SPramod Gunjikar 	 * Load the current QP attributes and then do a validation
1373c39526b7SPramod Gunjikar 	 * based on OFA verbs expectations to see if the modify
1374c39526b7SPramod Gunjikar 	 * should be performed.
1375c39526b7SPramod Gunjikar 	 */
1376c39526b7SPramod Gunjikar 	bzero(&qp_query_attr, sizeof (qp_query_attr));
1377c39526b7SPramod Gunjikar 	rc =  ibt_query_qp(uqp->qp, &qp_query_attr);
1378c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1379c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "modify_qp -"
1380c39526b7SPramod Gunjikar 		    "ibt_query_qp() failed - rc=%d", rc);
1381c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1382c39526b7SPramod Gunjikar 		goto err_deref;
1383c39526b7SPramod Gunjikar 	}
1384c39526b7SPramod Gunjikar 
1385c39526b7SPramod Gunjikar 	if (cmd.attr_mask & IB_QP_CUR_STATE) {
1386c39526b7SPramod Gunjikar 		cur_state = cmd.cur_qp_state;
1387c39526b7SPramod Gunjikar 	} else {
1388c39526b7SPramod Gunjikar 		cur_state = IBT_TO_OFA_QP_STATE(qp_query_attr.qp_info.qp_state);
1389c39526b7SPramod Gunjikar 	}
1390c39526b7SPramod Gunjikar 
1391c39526b7SPramod Gunjikar 	new_state = cmd.attr_mask & IB_QP_STATE ? cmd.qp_state : cur_state;
1392c39526b7SPramod Gunjikar 
1393c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp: ibt qp %p, handle "
1394c39526b7SPramod Gunjikar 	    "%x, cur_state %x, new_state %x, qp_type %x, attr_mask %x", uqp->qp,
1395c39526b7SPramod Gunjikar 	    cmd.qp_handle, cur_state, new_state, uqp->ofa_qp_type,
1396c39526b7SPramod Gunjikar 	    cmd.attr_mask);
1397c39526b7SPramod Gunjikar 
1398c39526b7SPramod Gunjikar 	if (!uverbs_modify_qp_is_ok(cur_state, new_state, uqp->ofa_qp_type,
1399c39526b7SPramod Gunjikar 	    (enum ib_qp_attr_mask *)&cmd.attr_mask)) {
1400c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "modify_qp() -"
1401c39526b7SPramod Gunjikar 		    "Failed modify OK test");
1402c39526b7SPramod Gunjikar 		rc = EINVAL;
1403c39526b7SPramod Gunjikar 		goto err_deref;
1404c39526b7SPramod Gunjikar 	}
1405c39526b7SPramod Gunjikar 
1406c39526b7SPramod Gunjikar 	if (!cmd.attr_mask) {
1407c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str, "modify_qp() -"
1408c39526b7SPramod Gunjikar 		    "attr_mask after modify OK test is 0");
1409c39526b7SPramod Gunjikar 		rc = 0;
1410c39526b7SPramod Gunjikar 		goto done;
1411c39526b7SPramod Gunjikar 	}
1412c39526b7SPramod Gunjikar 
1413c39526b7SPramod Gunjikar 	flags = 0;
1414c39526b7SPramod Gunjikar 
1415c39526b7SPramod Gunjikar 	switch (uqp->ofa_qp_type) {
1416c39526b7SPramod Gunjikar 		case IB_QPT_UC:
1417c39526b7SPramod Gunjikar 			qp_query_attr.qp_info.qp_trans = IBT_UC_SRV;
1418c39526b7SPramod Gunjikar 			break;
1419c39526b7SPramod Gunjikar 		case IB_QPT_UD:
1420c39526b7SPramod Gunjikar 			qp_query_attr.qp_info.qp_trans = IBT_UD_SRV;
1421c39526b7SPramod Gunjikar 			break;
1422c39526b7SPramod Gunjikar 		case IB_QPT_RC:
1423c39526b7SPramod Gunjikar 			qp_query_attr.qp_info.qp_trans = IBT_RC_SRV;
1424c39526b7SPramod Gunjikar 			break;
1425c39526b7SPramod Gunjikar 		default:
1426c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1427c39526b7SPramod Gunjikar 			    "modify_qp: Invalid QP type");
1428c39526b7SPramod Gunjikar 			rc = EINVAL;
1429c39526b7SPramod Gunjikar 			goto err_deref;
1430c39526b7SPramod Gunjikar 	}
1431c39526b7SPramod Gunjikar 
1432c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp(): qp_info.qp_flags "
1433c39526b7SPramod Gunjikar 	    "before modify update = 0%08x", qp_query_attr.qp_info.qp_flags);
1434c39526b7SPramod Gunjikar 
1435c39526b7SPramod Gunjikar 	uverbs_modify_update(&cmd, cur_state, new_state, &qp_query_attr,
1436c39526b7SPramod Gunjikar 	    &flags);
1437c39526b7SPramod Gunjikar 
1438c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp(): after "
1439c39526b7SPramod Gunjikar 	    "modify_update hdl flags = 0x%08x, qp_info.qp_flags = 0%08x",
1440c39526b7SPramod Gunjikar 	    flags, qp_query_attr.qp_info.qp_flags);
1441c39526b7SPramod Gunjikar 
1442c39526b7SPramod Gunjikar 	rc = ibt_modify_qp(uqp->qp, flags, &qp_query_attr.qp_info, &size);
1443c39526b7SPramod Gunjikar 
1444c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1445c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1446c39526b7SPramod Gunjikar 		    "modify_qp: Error in ibt_modify_qp() (rc=%d)", rc);
1447c39526b7SPramod Gunjikar 		uverbs_print_query_qp(uqp->qp);
1448c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1449c39526b7SPramod Gunjikar 		goto err_deref;
1450c39526b7SPramod Gunjikar 	}
1451c39526b7SPramod Gunjikar 
1452c39526b7SPramod Gunjikar done:
1453c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
1454c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
1455c39526b7SPramod Gunjikar 
1456c39526b7SPramod Gunjikar err_deref:
1457c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
1458c39526b7SPramod Gunjikar 
1459c39526b7SPramod Gunjikar err_out:
1460c39526b7SPramod Gunjikar 	return (rc);
1461c39526b7SPramod Gunjikar }
1462c39526b7SPramod Gunjikar 
1463c39526b7SPramod Gunjikar /*
1464c39526b7SPramod Gunjikar  * Function:
1465c39526b7SPramod Gunjikar  *      uverbs_copy_path_info_from_ibt
1466c39526b7SPramod Gunjikar  * Input:
1467c39526b7SPramod Gunjikar  *      src_path	- The IBT path.
1468c39526b7SPramod Gunjikar  * Output:
1469c39526b7SPramod Gunjikar  *      dest_path	- The OFED user verbs path.
1470c39526b7SPramod Gunjikar  * Returns:
1471c39526b7SPramod Gunjikar  *      None
1472c39526b7SPramod Gunjikar  * Description:
1473c39526b7SPramod Gunjikar  *      Helper to convert IBT path to OFED  user verbs path.
1474c39526b7SPramod Gunjikar  */
1475c39526b7SPramod Gunjikar static void
uverbs_copy_path_info_from_ibt(ibt_cep_path_t * src_path,struct ib_uverbs_qp_dest * dest_path)1476c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibt(ibt_cep_path_t *src_path,
1477c39526b7SPramod Gunjikar     struct ib_uverbs_qp_dest *dest_path)
1478c39526b7SPramod Gunjikar {
1479c39526b7SPramod Gunjikar 	ASSERT(src_path != NULL);
1480c39526b7SPramod Gunjikar 	ASSERT(dest_path != NULL);
1481c39526b7SPramod Gunjikar 
1482c39526b7SPramod Gunjikar 	(void) memcpy(&dest_path->dgid[0],
1483c39526b7SPramod Gunjikar 	    &src_path->cep_adds_vect.av_dgid, sizeof (dest_path->dgid));
1484c39526b7SPramod Gunjikar 
1485c39526b7SPramod Gunjikar 	dest_path->flow_label = src_path->cep_adds_vect.av_flow;
1486c39526b7SPramod Gunjikar 	dest_path->dlid = src_path->cep_adds_vect.av_dlid;
1487c39526b7SPramod Gunjikar 	dest_path->hop_limit = src_path->cep_adds_vect.av_hop;
1488c39526b7SPramod Gunjikar 	dest_path->traffic_class = src_path->cep_adds_vect.av_tclass;
1489c39526b7SPramod Gunjikar 	dest_path->sl = src_path->cep_adds_vect.av_srvl;
1490c39526b7SPramod Gunjikar 	dest_path->port_num = src_path->cep_adds_vect.av_port_num;
1491c39526b7SPramod Gunjikar 	dest_path->src_path_bits = src_path->cep_adds_vect.av_src_path;
1492c39526b7SPramod Gunjikar 	dest_path->is_global = src_path->cep_adds_vect.av_send_grh;
1493c39526b7SPramod Gunjikar 	dest_path->sgid_index = src_path->cep_adds_vect.av_sgid_ix;
1494c39526b7SPramod Gunjikar 	dest_path->static_rate =  src_path->cep_adds_vect.av_srate;
1495c39526b7SPramod Gunjikar }
1496c39526b7SPramod Gunjikar 
1497c39526b7SPramod Gunjikar /*
1498c39526b7SPramod Gunjikar  * Function:
1499c39526b7SPramod Gunjikar  *      uverbs_query_copy_rc
1500c39526b7SPramod Gunjikar  * Input:
1501c39526b7SPramod Gunjikar  *      src	- The IBT RC QP attributes.
1502c39526b7SPramod Gunjikar  * Output:
1503c39526b7SPramod Gunjikar  *      dest	- The OFED user verbs QP attributes.
1504c39526b7SPramod Gunjikar  * Returns:
1505c39526b7SPramod Gunjikar  *      None
1506c39526b7SPramod Gunjikar  * Description:
1507c39526b7SPramod Gunjikar  *      Helper to copy IBT RC QP attributes to OFED QP attributes.
1508c39526b7SPramod Gunjikar  */
1509c39526b7SPramod Gunjikar static void
uverbs_query_copy_rc(struct ib_uverbs_query_qp_resp * dest,ibt_qp_rc_attr_t * src)1510c39526b7SPramod Gunjikar uverbs_query_copy_rc(struct ib_uverbs_query_qp_resp *dest,
1511c39526b7SPramod Gunjikar     ibt_qp_rc_attr_t *src)
1512c39526b7SPramod Gunjikar {
1513c39526b7SPramod Gunjikar 	dest->sq_psn = src->rc_sq_psn;
1514c39526b7SPramod Gunjikar 	dest->rq_psn = src->rc_rq_psn;
1515c39526b7SPramod Gunjikar 	dest->dest_qp_num = src->rc_dst_qpn;
1516c39526b7SPramod Gunjikar 	dest->rnr_retry = src->rc_rnr_retry_cnt;
1517c39526b7SPramod Gunjikar 	dest->retry_cnt = src->rc_retry_cnt;
1518c39526b7SPramod Gunjikar 	dest->max_dest_rd_atomic = src->rc_rdma_ra_in;
1519c39526b7SPramod Gunjikar 	dest->max_rd_atomic = src->rc_rdma_ra_out;
1520c39526b7SPramod Gunjikar 	dest->min_rnr_timer = src->rc_min_rnr_nak;
1521c39526b7SPramod Gunjikar 	dest->path_mtu = src->rc_path_mtu;
1522c39526b7SPramod Gunjikar 	dest->timeout = src->rc_path.cep_timeout;
1523c39526b7SPramod Gunjikar 	dest->alt_timeout = src->rc_alt_path.cep_timeout;
1524c39526b7SPramod Gunjikar 	dest->port_num = src->rc_path.cep_hca_port_num;
1525c39526b7SPramod Gunjikar 	dest->alt_port_num = src->rc_alt_path.cep_hca_port_num;
1526c39526b7SPramod Gunjikar 
1527c39526b7SPramod Gunjikar 	if (src->rc_mig_state == IBT_STATE_MIGRATED) {
1528c39526b7SPramod Gunjikar 		dest->path_mig_state = IB_MIG_MIGRATED;
1529c39526b7SPramod Gunjikar 	}
1530c39526b7SPramod Gunjikar 	if (src->rc_mig_state == IBT_STATE_REARMED) {
1531c39526b7SPramod Gunjikar 		dest->path_mig_state = IB_MIG_REARM;
1532c39526b7SPramod Gunjikar 	}
1533c39526b7SPramod Gunjikar 	if (src->rc_mig_state == IBT_STATE_ARMED) {
1534c39526b7SPramod Gunjikar 		dest->path_mig_state = IB_MIG_ARMED;
1535c39526b7SPramod Gunjikar 	}
1536c39526b7SPramod Gunjikar 
1537c39526b7SPramod Gunjikar 	uverbs_copy_path_info_from_ibt(&src->rc_path, &dest->dest);
1538c39526b7SPramod Gunjikar 	uverbs_copy_path_info_from_ibt(&src->rc_alt_path, &dest->alt_dest);
1539c39526b7SPramod Gunjikar }
1540c39526b7SPramod Gunjikar 
1541c39526b7SPramod Gunjikar /*
1542c39526b7SPramod Gunjikar  * Function:
1543c39526b7SPramod Gunjikar  *      uverbs_query_copy_uc
1544c39526b7SPramod Gunjikar  * Input:
1545c39526b7SPramod Gunjikar  *      src	- The IBT UC QP attributes.
1546c39526b7SPramod Gunjikar  * Output:
1547c39526b7SPramod Gunjikar  *      dest	- The OFED user verbs QP attributes.
1548c39526b7SPramod Gunjikar  * Returns:
1549c39526b7SPramod Gunjikar  *      None
1550c39526b7SPramod Gunjikar  * Description:
1551c39526b7SPramod Gunjikar  *      Helper to copy IBT UC QP attributes to OFED user verbs
1552c39526b7SPramod Gunjikar  *	QP attributes.
1553c39526b7SPramod Gunjikar  */
1554c39526b7SPramod Gunjikar static void
uverbs_query_copy_uc(struct ib_uverbs_query_qp_resp * dest,ibt_qp_uc_attr_t * src)1555c39526b7SPramod Gunjikar uverbs_query_copy_uc(struct ib_uverbs_query_qp_resp *dest,
1556c39526b7SPramod Gunjikar     ibt_qp_uc_attr_t *src)
1557c39526b7SPramod Gunjikar {
1558c39526b7SPramod Gunjikar 	dest->sq_psn	  = src->uc_sq_psn;
1559c39526b7SPramod Gunjikar 	dest->rq_psn	  = src->uc_rq_psn;
1560c39526b7SPramod Gunjikar 	dest->dest_qp_num = src->uc_dst_qpn;
1561c39526b7SPramod Gunjikar 	dest->path_mtu	  = src->uc_path_mtu;
1562c39526b7SPramod Gunjikar 
1563c39526b7SPramod Gunjikar 	if (src->uc_mig_state == IBT_STATE_MIGRATED) {
1564c39526b7SPramod Gunjikar 		dest->path_mig_state = IB_MIG_MIGRATED;
1565c39526b7SPramod Gunjikar 	}
1566c39526b7SPramod Gunjikar 	if (src->uc_mig_state == IBT_STATE_REARMED) {
1567c39526b7SPramod Gunjikar 		dest->path_mig_state = IB_MIG_REARM;
1568c39526b7SPramod Gunjikar 	}
1569c39526b7SPramod Gunjikar 	if (src->uc_mig_state == IBT_STATE_ARMED) {
1570c39526b7SPramod Gunjikar 		dest->path_mig_state = IB_MIG_ARMED;
1571c39526b7SPramod Gunjikar 	}
1572c39526b7SPramod Gunjikar 
1573c39526b7SPramod Gunjikar 	uverbs_copy_path_info_from_ibt(&src->uc_path, &dest->dest);
1574c39526b7SPramod Gunjikar 	uverbs_copy_path_info_from_ibt(&src->uc_alt_path, &dest->alt_dest);
1575c39526b7SPramod Gunjikar }
1576c39526b7SPramod Gunjikar 
1577c39526b7SPramod Gunjikar /*
1578c39526b7SPramod Gunjikar  * Function:
1579c39526b7SPramod Gunjikar  *      uverbs_query_copy_rd
1580c39526b7SPramod Gunjikar  * Input:
1581c39526b7SPramod Gunjikar  *      src	- The IBT RD QP attributes.
1582c39526b7SPramod Gunjikar  * Output:
1583c39526b7SPramod Gunjikar  *      dest	- The OFED user verbs QP attributes.
1584c39526b7SPramod Gunjikar  * Returns:
1585c39526b7SPramod Gunjikar  *      None
1586c39526b7SPramod Gunjikar  * Description:
1587c39526b7SPramod Gunjikar  *      Helper to copy IBT RD QP attributes to OFED user verb QP attributes.
1588c39526b7SPramod Gunjikar  */
1589c39526b7SPramod Gunjikar static void
uverbs_query_copy_rd(struct ib_uverbs_query_qp_resp * dest,ibt_qp_rd_attr_t * src)1590c39526b7SPramod Gunjikar uverbs_query_copy_rd(struct ib_uverbs_query_qp_resp *dest,
1591c39526b7SPramod Gunjikar     ibt_qp_rd_attr_t *src)
1592c39526b7SPramod Gunjikar {
1593c39526b7SPramod Gunjikar 	dest->qkey	    = src->rd_qkey;
1594c39526b7SPramod Gunjikar 	dest->min_rnr_timer = src->rd_min_rnr_nak;
1595c39526b7SPramod Gunjikar }
1596c39526b7SPramod Gunjikar 
1597c39526b7SPramod Gunjikar /*
1598c39526b7SPramod Gunjikar  * Function:
1599c39526b7SPramod Gunjikar  *      uverbs_query_copy_ud
1600c39526b7SPramod Gunjikar  * Input:
1601c39526b7SPramod Gunjikar  *      src	- The IBT UD QP attributes.
1602c39526b7SPramod Gunjikar  * Output:
1603c39526b7SPramod Gunjikar  *      dest	- The OFED user verbs QP attributes.
1604c39526b7SPramod Gunjikar  * Returns:
1605c39526b7SPramod Gunjikar  *      None
1606c39526b7SPramod Gunjikar  * Description:
1607c39526b7SPramod Gunjikar  *      Helper to copy IBT UD QP attributes to OFED user verbs QP attributes.
1608c39526b7SPramod Gunjikar  */
1609c39526b7SPramod Gunjikar static void
uverbs_query_copy_ud(struct ib_uverbs_query_qp_resp * dest,ibt_qp_ud_attr_t * src)1610c39526b7SPramod Gunjikar uverbs_query_copy_ud(struct ib_uverbs_query_qp_resp *dest,
1611c39526b7SPramod Gunjikar     ibt_qp_ud_attr_t *src)
1612c39526b7SPramod Gunjikar {
1613c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1614c39526b7SPramod Gunjikar 	    "query_copy_ud:entry - return UD info: qkey:%08X, "
1615c39526b7SPramod Gunjikar 	    "psn:%d, pkey_idx:%d, port:%d", src->ud_qkey, src->ud_sq_psn,
1616c39526b7SPramod Gunjikar 	    src->ud_pkey_ix, src->ud_port);
1617c39526b7SPramod Gunjikar 
1618c39526b7SPramod Gunjikar 	dest->qkey	 = src->ud_qkey;
1619c39526b7SPramod Gunjikar 	dest->sq_psn	 = src->ud_sq_psn;
1620c39526b7SPramod Gunjikar 	dest->pkey_index = src->ud_pkey_ix;
1621c39526b7SPramod Gunjikar 	dest->port_num	 = src->ud_port;
1622c39526b7SPramod Gunjikar }
1623c39526b7SPramod Gunjikar 
1624c39526b7SPramod Gunjikar /*
1625c39526b7SPramod Gunjikar  * Function:
1626c39526b7SPramod Gunjikar  *      uverbs_query_copy_info
1627c39526b7SPramod Gunjikar  * Input:
1628c39526b7SPramod Gunjikar  *      src	- The IBT QP information.
1629c39526b7SPramod Gunjikar  * Output:
1630c39526b7SPramod Gunjikar  *      dest	- The OFED user verbs QP attributes.
1631c39526b7SPramod Gunjikar  * Returns:
1632c39526b7SPramod Gunjikar  *      None
1633c39526b7SPramod Gunjikar  * Description:
1634c39526b7SPramod Gunjikar  *      Helper to copy IBT QP info to OFED user verbs QP attributes.
1635c39526b7SPramod Gunjikar  */
1636c39526b7SPramod Gunjikar static void
uverbs_query_copy_info(struct ib_uverbs_query_qp_resp * dest,ibt_qp_info_t * src)1637c39526b7SPramod Gunjikar uverbs_query_copy_info(struct ib_uverbs_query_qp_resp *dest,
1638c39526b7SPramod Gunjikar     ibt_qp_info_t *src)
1639c39526b7SPramod Gunjikar {
1640c39526b7SPramod Gunjikar 
1641c39526b7SPramod Gunjikar 	dest->max_send_wr = src->qp_sq_sz;
1642c39526b7SPramod Gunjikar 	dest->max_recv_wr = src->qp_rq_sz;
1643c39526b7SPramod Gunjikar 	dest->qp_access_flags = ibt_cep_flags2ibv(src->qp_flags);
1644c39526b7SPramod Gunjikar 
1645c39526b7SPramod Gunjikar 	switch (src->qp_state) {
1646c39526b7SPramod Gunjikar 		case IBT_STATE_RESET:
1647c39526b7SPramod Gunjikar 			dest->qp_state = IB_QPS_RESET;
1648c39526b7SPramod Gunjikar 			break;
1649c39526b7SPramod Gunjikar 		case IBT_STATE_INIT:
1650c39526b7SPramod Gunjikar 			dest->qp_state = IB_QPS_INIT;
1651c39526b7SPramod Gunjikar 			break;
1652c39526b7SPramod Gunjikar 		case IBT_STATE_RTR:
1653c39526b7SPramod Gunjikar 			dest->qp_state = IB_QPS_RTR;
1654c39526b7SPramod Gunjikar 			break;
1655c39526b7SPramod Gunjikar 		case IBT_STATE_RTS:
1656c39526b7SPramod Gunjikar 			dest->qp_state = IB_QPS_RTS;
1657c39526b7SPramod Gunjikar 			break;
1658c39526b7SPramod Gunjikar 		case IBT_STATE_SQD:
1659c39526b7SPramod Gunjikar 			dest->qp_state = IB_QPS_SQD;
1660c39526b7SPramod Gunjikar 			break;
1661c39526b7SPramod Gunjikar 		case IBT_STATE_SQE:
1662c39526b7SPramod Gunjikar 			dest->qp_state = IB_QPS_SQE;
1663c39526b7SPramod Gunjikar 			break;
1664c39526b7SPramod Gunjikar 		case IBT_STATE_ERROR:
1665c39526b7SPramod Gunjikar 		default:
1666c39526b7SPramod Gunjikar 			dest->qp_state = IB_QPS_ERR;
1667c39526b7SPramod Gunjikar 			break;
1668c39526b7SPramod Gunjikar 	}
1669c39526b7SPramod Gunjikar 
1670c39526b7SPramod Gunjikar 	switch (src->qp_current_state) {
1671c39526b7SPramod Gunjikar 		case IBT_STATE_RESET:
1672c39526b7SPramod Gunjikar 			dest->cur_qp_state = IB_QPS_RESET;
1673c39526b7SPramod Gunjikar 			break;
1674c39526b7SPramod Gunjikar 		case IBT_STATE_INIT:
1675c39526b7SPramod Gunjikar 			dest->cur_qp_state = IB_QPS_INIT;
1676c39526b7SPramod Gunjikar 			break;
1677c39526b7SPramod Gunjikar 		case IBT_STATE_RTR:
1678c39526b7SPramod Gunjikar 			dest->cur_qp_state = IB_QPS_RTR;
1679c39526b7SPramod Gunjikar 			break;
1680c39526b7SPramod Gunjikar 		case IBT_STATE_RTS:
1681c39526b7SPramod Gunjikar 			dest->cur_qp_state = IB_QPS_RTS;
1682c39526b7SPramod Gunjikar 			break;
1683c39526b7SPramod Gunjikar 		case IBT_STATE_SQD:
1684c39526b7SPramod Gunjikar 			dest->cur_qp_state = IB_QPS_SQD;
1685c39526b7SPramod Gunjikar 			break;
1686c39526b7SPramod Gunjikar 		case IBT_STATE_SQE:
1687c39526b7SPramod Gunjikar 			dest->cur_qp_state = IB_QPS_SQE;
1688c39526b7SPramod Gunjikar 			break;
1689c39526b7SPramod Gunjikar 		case IBT_STATE_ERROR:
1690c39526b7SPramod Gunjikar 		default:
1691c39526b7SPramod Gunjikar 			dest->cur_qp_state = IB_QPS_ERR;
1692c39526b7SPramod Gunjikar 			break;
1693c39526b7SPramod Gunjikar 	}
1694c39526b7SPramod Gunjikar 
1695c39526b7SPramod Gunjikar 	if ((src->qp_flags & IBT_ALL_SIGNALED) == IBT_ALL_SIGNALED) {
1696c39526b7SPramod Gunjikar 		dest->sq_sig_all = 1;
1697c39526b7SPramod Gunjikar 	}
1698c39526b7SPramod Gunjikar }
1699c39526b7SPramod Gunjikar 
1700c39526b7SPramod Gunjikar /*
1701c39526b7SPramod Gunjikar  * Function:
1702c39526b7SPramod Gunjikar  *      uverbs_query_copy_attr
1703c39526b7SPramod Gunjikar  * Input:
1704c39526b7SPramod Gunjikar  *      src	- The IBT QP information.
1705c39526b7SPramod Gunjikar  * Output:
1706c39526b7SPramod Gunjikar  *      dest	- The OFED user verbs QP attributes.
1707c39526b7SPramod Gunjikar  * Returns:
1708c39526b7SPramod Gunjikar  *      None
1709c39526b7SPramod Gunjikar  * Description:
1710c39526b7SPramod Gunjikar  *      Helper to copy IBT QP attributes to OFED user verbs QP attributes.
1711c39526b7SPramod Gunjikar  */
1712c39526b7SPramod Gunjikar static void
uverbs_query_copy_attr(struct ib_uverbs_query_qp_resp * dest,ibt_qp_query_attr_t * src)1713c39526b7SPramod Gunjikar uverbs_query_copy_attr(struct ib_uverbs_query_qp_resp *dest,
1714c39526b7SPramod Gunjikar     ibt_qp_query_attr_t *src)
1715c39526b7SPramod Gunjikar {
1716c39526b7SPramod Gunjikar 	dest->max_send_sge = src->qp_sq_sgl;
1717c39526b7SPramod Gunjikar 	dest->max_recv_sge = src->qp_rq_sgl;
1718c39526b7SPramod Gunjikar }
1719c39526b7SPramod Gunjikar 
1720c39526b7SPramod Gunjikar /*
1721c39526b7SPramod Gunjikar  * Function:
1722c39526b7SPramod Gunjikar  *      sol_uverbs_query_qp
1723c39526b7SPramod Gunjikar  * Input:
1724c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
1725c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing query QP command.
1726c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
1727c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
1728c39526b7SPramod Gunjikar  * Output:
1729c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
1730c39526b7SPramod Gunjikar  * Returns:
1731c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
1732c39526b7SPramod Gunjikar  * Description:
1733c39526b7SPramod Gunjikar  *      User verbs entry point to query a device QP properties.
1734c39526b7SPramod Gunjikar  */
1735c39526b7SPramod Gunjikar /* ARGSUSED */
1736c39526b7SPramod Gunjikar int
sol_uverbs_query_qp(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1737c39526b7SPramod Gunjikar sol_uverbs_query_qp(uverbs_uctxt_uobj_t *uctxt, char *buf,
1738c39526b7SPramod Gunjikar     int in_len, int out_len)
1739c39526b7SPramod Gunjikar {
1740c39526b7SPramod Gunjikar 	struct ib_uverbs_query_qp	cmd;
1741c39526b7SPramod Gunjikar 	struct ib_uverbs_query_qp_resp	resp;
1742c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t		*uqp;
1743c39526b7SPramod Gunjikar 	ibt_qp_query_attr_t		qp_query_attr;
1744c39526b7SPramod Gunjikar 	int				rc;
1745c39526b7SPramod Gunjikar 
1746c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
1747c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1748c39526b7SPramod Gunjikar 
1749c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1750c39526b7SPramod Gunjikar 	    "query_qp: entry (qp_handle=%d)", cmd.qp_handle);
1751c39526b7SPramod Gunjikar 
1752c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_read(cmd.qp_handle);
1753c39526b7SPramod Gunjikar 	if (uqp == NULL) {
1754c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1755c39526b7SPramod Gunjikar 		    "query_qp(): List lookup failure");
1756c39526b7SPramod Gunjikar 		rc = EINVAL;
1757c39526b7SPramod Gunjikar 		goto err_out;
1758c39526b7SPramod Gunjikar 	}
1759c39526b7SPramod Gunjikar 
1760c39526b7SPramod Gunjikar 	bzero(&qp_query_attr, sizeof (qp_query_attr));
1761c39526b7SPramod Gunjikar 	rc =  ibt_query_qp(uqp->qp, &qp_query_attr);
1762c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
1763c39526b7SPramod Gunjikar 
1764c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1765c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1766c39526b7SPramod Gunjikar 		    "query_qp: Error in ibt_query_qp() (rc=%d)", rc);
1767c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1768c39526b7SPramod Gunjikar 		goto err_out;
1769c39526b7SPramod Gunjikar 	}
1770c39526b7SPramod Gunjikar 
1771c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1772c39526b7SPramod Gunjikar 	    "query_qp(): qp_query_attr.qp_info.qp_trans = %d",
1773c39526b7SPramod Gunjikar 	    qp_query_attr.qp_info.qp_trans);
1774c39526b7SPramod Gunjikar 
1775c39526b7SPramod Gunjikar 	uverbs_query_copy_attr(&resp, &qp_query_attr);
1776c39526b7SPramod Gunjikar 	uverbs_query_copy_info(&resp, &qp_query_attr.qp_info);
1777c39526b7SPramod Gunjikar 
1778c39526b7SPramod Gunjikar 	if (qp_query_attr.qp_info.qp_trans == IBT_RC_SRV) {
1779c39526b7SPramod Gunjikar 		uverbs_query_copy_rc(&resp,
1780c39526b7SPramod Gunjikar 		    &qp_query_attr.qp_info.qp_transport.rc);
1781c39526b7SPramod Gunjikar 	}
1782c39526b7SPramod Gunjikar 
1783c39526b7SPramod Gunjikar 	if (qp_query_attr.qp_info.qp_trans == IBT_UC_SRV) {
1784c39526b7SPramod Gunjikar 		uverbs_query_copy_uc(&resp,
1785c39526b7SPramod Gunjikar 		    &qp_query_attr.qp_info.qp_transport.uc);
1786c39526b7SPramod Gunjikar 	}
1787c39526b7SPramod Gunjikar 
1788c39526b7SPramod Gunjikar 	if (qp_query_attr.qp_info.qp_trans == IBT_RD_SRV) {
1789c39526b7SPramod Gunjikar 		uverbs_query_copy_rd(&resp,
1790c39526b7SPramod Gunjikar 		    &qp_query_attr.qp_info.qp_transport.rd);
1791c39526b7SPramod Gunjikar 	}
1792c39526b7SPramod Gunjikar 
1793c39526b7SPramod Gunjikar 
1794c39526b7SPramod Gunjikar 	if (qp_query_attr.qp_info.qp_trans == IBT_UD_SRV) {
1795c39526b7SPramod Gunjikar 		uverbs_query_copy_ud(&resp,
1796c39526b7SPramod Gunjikar 		    &qp_query_attr.qp_info.qp_transport.ud);
1797c39526b7SPramod Gunjikar 	}
1798c39526b7SPramod Gunjikar 
1799c39526b7SPramod Gunjikar 	resp.max_inline_data = uqp->max_inline_data;
1800c39526b7SPramod Gunjikar 
1801c39526b7SPramod Gunjikar #ifdef	_LP64
1802c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
1803c39526b7SPramod Gunjikar #else
1804c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
1805c39526b7SPramod Gunjikar #endif
1806c39526b7SPramod Gunjikar 	if (rc != 0) {
1807c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1808c39526b7SPramod Gunjikar 		    "query_qp(): Error writing resp data (rc=%d)", rc);
1809c39526b7SPramod Gunjikar 		rc = EFAULT;
1810c39526b7SPramod Gunjikar 		goto err_out;
1811c39526b7SPramod Gunjikar 	}
1812c39526b7SPramod Gunjikar 
1813c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
1814c39526b7SPramod Gunjikar 
1815c39526b7SPramod Gunjikar err_out:
1816c39526b7SPramod Gunjikar 	return (rc);
1817c39526b7SPramod Gunjikar }
1818c39526b7SPramod Gunjikar 
1819c39526b7SPramod Gunjikar /*
1820c39526b7SPramod Gunjikar  * Function:
1821c39526b7SPramod Gunjikar  *      sol_uverbs_create_srq
1822c39526b7SPramod Gunjikar  * Input:
1823c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
1824c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing command.
1825c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
1826c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
1827c39526b7SPramod Gunjikar  * Output:
1828c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
1829c39526b7SPramod Gunjikar  * Returns:
1830c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
1831c39526b7SPramod Gunjikar  * Description:
1832c39526b7SPramod Gunjikar  *      User verbs entry point to create a device shared receive queue.
1833c39526b7SPramod Gunjikar  */
1834c39526b7SPramod Gunjikar /* ARGSUSED */
1835c39526b7SPramod Gunjikar int
sol_uverbs_create_srq(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)1836c39526b7SPramod Gunjikar sol_uverbs_create_srq(uverbs_uctxt_uobj_t *uctxt, char *buf,
1837c39526b7SPramod Gunjikar     int in_len, int out_len)
1838c39526b7SPramod Gunjikar {
1839c39526b7SPramod Gunjikar 	struct ib_uverbs_create_srq		cmd;
1840c39526b7SPramod Gunjikar 	struct ib_uverbs_create_srq_resp	resp;
1841c39526b7SPramod Gunjikar 	uverbs_usrq_uobj_t			*usrq;
1842c39526b7SPramod Gunjikar 	uverbs_upd_uobj_t			*upd;
1843c39526b7SPramod Gunjikar 	ibt_srq_flags_t				flags = IBT_SRQ_USER_MAP;
1844c39526b7SPramod Gunjikar 	ibt_srq_sizes_t				attr;
1845c39526b7SPramod Gunjikar 	ibt_srq_sizes_t				real_attr;
1846c39526b7SPramod Gunjikar 	int					rc;
1847c39526b7SPramod Gunjikar 
1848c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
1849c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
1850c39526b7SPramod Gunjikar 	(void) memset(&attr, 0, sizeof (attr));
1851c39526b7SPramod Gunjikar 
1852c39526b7SPramod Gunjikar 	attr.srq_wr_sz   = cmd.max_wr;
1853c39526b7SPramod Gunjikar 	attr.srq_sgl_sz  = cmd.max_sge;
1854c39526b7SPramod Gunjikar 
1855c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "create_srq: "
1856c39526b7SPramod Gunjikar 	    "max_wr=%d, max_sge=%d, srq_limit=%d",
1857c39526b7SPramod Gunjikar 	    cmd.max_wr, cmd.max_sge, cmd.srq_limit);
1858c39526b7SPramod Gunjikar 
1859c39526b7SPramod Gunjikar 	if (!attr.srq_wr_sz) {
1860c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1861c39526b7SPramod Gunjikar 		    "create_srq(): Invalid args, invalid work "
1862c39526b7SPramod Gunjikar 		    "request size");
1863c39526b7SPramod Gunjikar 
1864c39526b7SPramod Gunjikar 		rc = EINVAL;
1865c39526b7SPramod Gunjikar 		goto err_out;
1866c39526b7SPramod Gunjikar 	}
1867c39526b7SPramod Gunjikar 
1868c39526b7SPramod Gunjikar 	if (attr.srq_wr_sz > uctxt->hca->attr.hca_max_srqs_sz ||
1869c39526b7SPramod Gunjikar 	    attr.srq_sgl_sz > uctxt->hca->attr.hca_max_srq_sgl) {
1870c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1871c39526b7SPramod Gunjikar 		    "create_srq(): Invalid args, too large");
1872c39526b7SPramod Gunjikar 		rc = EINVAL;
1873c39526b7SPramod Gunjikar 		goto err_out;
1874c39526b7SPramod Gunjikar 	}
1875c39526b7SPramod Gunjikar 
1876c39526b7SPramod Gunjikar 	usrq = kmem_zalloc(sizeof (*usrq), KM_NOSLEEP);
1877c39526b7SPramod Gunjikar 	if (usrq == NULL) {
1878c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1879c39526b7SPramod Gunjikar 		    "create_srq(): User object alloc failed");
1880c39526b7SPramod Gunjikar 		rc = ENOMEM;
1881c39526b7SPramod Gunjikar 		goto err_out;
1882c39526b7SPramod Gunjikar 	}
1883c39526b7SPramod Gunjikar 	sol_ofs_uobj_init(&usrq->uobj, cmd.user_handle,
1884c39526b7SPramod Gunjikar 	    SOL_UVERBS_USRQ_UOBJ_TYPE);
1885c39526b7SPramod Gunjikar 	rw_enter(&usrq->uobj.uo_lock, RW_WRITER);
1886c39526b7SPramod Gunjikar 	llist_head_init(&usrq->async_list, NULL);
1887c39526b7SPramod Gunjikar 	usrq->async_events_reported = 0;
1888c39526b7SPramod Gunjikar 	usrq->uctxt = uctxt;
1889c39526b7SPramod Gunjikar 
1890c39526b7SPramod Gunjikar 	upd = uverbs_uobj_get_upd_read(cmd.pd_handle);
1891c39526b7SPramod Gunjikar 	if (upd == NULL) {
1892c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1893c39526b7SPramod Gunjikar 		    "create_srq(): PD Invalid");
1894c39526b7SPramod Gunjikar 		rc = EINVAL;
1895c39526b7SPramod Gunjikar 		goto err_dealloc;
1896c39526b7SPramod Gunjikar 	}
1897c39526b7SPramod Gunjikar 
1898c39526b7SPramod Gunjikar 	rc = ibt_alloc_srq(uctxt->hca->hdl, flags, upd->pd, &attr, &usrq->srq,
1899c39526b7SPramod Gunjikar 	    &real_attr);
1900c39526b7SPramod Gunjikar 
1901c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1902c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1903c39526b7SPramod Gunjikar 		    "create_srq(): Error in ibt_alloc_srq() (rc=%d)", rc);
1904c39526b7SPramod Gunjikar 		usrq->srq = NULL;
1905c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
1906c39526b7SPramod Gunjikar 		usrq->uobj.uo_uobj_sz = sizeof (uverbs_usrq_uobj_t);
1907c39526b7SPramod Gunjikar 		goto err_release_pd;
1908c39526b7SPramod Gunjikar 	}
1909c39526b7SPramod Gunjikar 
1910c39526b7SPramod Gunjikar 	ibt_set_srq_private(usrq->srq, usrq);
1911c39526b7SPramod Gunjikar 
1912c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1913c39526b7SPramod Gunjikar 	    "create_srq(): ib_alloc_srq()real wqe_sz=%d, real_sg_sz=%d",
1914c39526b7SPramod Gunjikar 	    real_attr.srq_wr_sz, real_attr.srq_sgl_sz);
1915c39526b7SPramod Gunjikar 
1916c39526b7SPramod Gunjikar 	/*
1917c39526b7SPramod Gunjikar 	 * Query underlying hardware for data used in mapping CQ back to user
1918c39526b7SPramod Gunjikar 	 * space, we will return this information in the user verbs command
1919c39526b7SPramod Gunjikar 	 * response.
1920c39526b7SPramod Gunjikar 	 */
1921c39526b7SPramod Gunjikar 	rc = ibt_ci_data_out(uctxt->hca->hdl, IBT_CI_NO_FLAGS, IBT_HDL_SRQ,
1922c39526b7SPramod Gunjikar 	    (void *)usrq->srq,  &resp.drv_out, sizeof (resp.drv_out));
1923c39526b7SPramod Gunjikar 
1924c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
1925c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1926c39526b7SPramod Gunjikar 		    "create_srq(): Error in ibt_ci_data_out() (rc=%d)", rc);
1927c39526b7SPramod Gunjikar 		rc = EFAULT;
1928c39526b7SPramod Gunjikar 		usrq->uobj.uo_uobj_sz = sizeof (uverbs_usrq_uobj_t);
1929c39526b7SPramod Gunjikar 		goto err_srq_destroy;
1930c39526b7SPramod Gunjikar 	}
1931c39526b7SPramod Gunjikar 
1932c39526b7SPramod Gunjikar 	if (sol_ofs_uobj_add(&uverbs_usrq_uo_tbl, &usrq->uobj) != 0) {
1933c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1934c39526b7SPramod Gunjikar 		    "create_srq(): uobj add failed");
1935c39526b7SPramod Gunjikar 		rc = ENOMEM;
1936c39526b7SPramod Gunjikar 		goto err_srq_destroy;
1937c39526b7SPramod Gunjikar 	}
1938c39526b7SPramod Gunjikar 
1939c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
1940c39526b7SPramod Gunjikar 	    "create_srq(): ibt_ci_data_out: 0x%16llx 0x%16llx 0x%16llx "
1941c39526b7SPramod Gunjikar 	    "0x%16llx", resp.drv_out[0], resp.drv_out[1], resp.drv_out[2],
1942c39526b7SPramod Gunjikar 	    resp.drv_out[3]);
1943c39526b7SPramod Gunjikar 
1944c39526b7SPramod Gunjikar 	resp.srq_handle	= usrq->uobj.uo_id;
1945c39526b7SPramod Gunjikar 	resp.max_wr	= real_attr.srq_wr_sz;
1946c39526b7SPramod Gunjikar 	resp.max_sge	= real_attr.srq_sgl_sz;
1947c39526b7SPramod Gunjikar 
1948c39526b7SPramod Gunjikar #ifdef	_LP64
1949c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
1950c39526b7SPramod Gunjikar #else
1951c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
1952c39526b7SPramod Gunjikar #endif
1953c39526b7SPramod Gunjikar 	if (rc != 0) {
1954c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1955c39526b7SPramod Gunjikar 		    "create_srq(): Error writing resp data (rc=%d)", rc);
1956c39526b7SPramod Gunjikar 		rc = EFAULT;
1957c39526b7SPramod Gunjikar 		goto err_uo_delete;
1958c39526b7SPramod Gunjikar 	}
1959c39526b7SPramod Gunjikar 
1960c39526b7SPramod Gunjikar 	mutex_enter(&uctxt->lock);
1961c39526b7SPramod Gunjikar 	usrq->list_entry = add_genlist(&uctxt->srq_list, (uintptr_t)usrq,
1962c39526b7SPramod Gunjikar 	    uctxt);
1963c39526b7SPramod Gunjikar 	mutex_exit(&uctxt->lock);
1964c39526b7SPramod Gunjikar 
1965c39526b7SPramod Gunjikar 	if (!usrq->list_entry) {
1966c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
1967c39526b7SPramod Gunjikar 		    "create_srq() : Error adding usrq to srq_list failed");
1968c39526b7SPramod Gunjikar 		rc = ENOMEM;
1969c39526b7SPramod Gunjikar 		goto err_uo_delete;
1970c39526b7SPramod Gunjikar 	}
1971c39526b7SPramod Gunjikar 
1972c39526b7SPramod Gunjikar 	usrq->uobj.uo_live = 1;
1973c39526b7SPramod Gunjikar 	rw_exit(&usrq->uobj.uo_lock);
1974c39526b7SPramod Gunjikar 
1975c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&upd->uobj);
1976c39526b7SPramod Gunjikar 
1977c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
1978c39526b7SPramod Gunjikar 
1979c39526b7SPramod Gunjikar err_uo_delete:
1980c39526b7SPramod Gunjikar 	/*
1981c39526b7SPramod Gunjikar 	 * Need to set uo_live, so sol_ofs_uobj_remove() will
1982c39526b7SPramod Gunjikar 	 * remove the object from the object table.
1983c39526b7SPramod Gunjikar 	 */
1984c39526b7SPramod Gunjikar 	usrq->uobj.uo_live = 1;
1985c39526b7SPramod Gunjikar 	(void) sol_ofs_uobj_remove(&uverbs_usrq_uo_tbl, &usrq->uobj);
1986c39526b7SPramod Gunjikar 
1987c39526b7SPramod Gunjikar err_srq_destroy:
1988c39526b7SPramod Gunjikar 	(void) ibt_free_srq(usrq->srq);
1989c39526b7SPramod Gunjikar 
1990c39526b7SPramod Gunjikar err_release_pd:
1991c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&upd->uobj);
1992c39526b7SPramod Gunjikar 
1993c39526b7SPramod Gunjikar err_dealloc:
1994c39526b7SPramod Gunjikar 	rw_exit(&usrq->uobj.uo_lock);
1995c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&usrq->uobj, sol_ofs_uobj_free);
1996c39526b7SPramod Gunjikar 
1997c39526b7SPramod Gunjikar err_out:
1998c39526b7SPramod Gunjikar 	return (rc);
1999c39526b7SPramod Gunjikar }
2000c39526b7SPramod Gunjikar 
2001c39526b7SPramod Gunjikar /*
2002c39526b7SPramod Gunjikar  * Function:
2003c39526b7SPramod Gunjikar  *      sol_uverbs_modify_srq
2004c39526b7SPramod Gunjikar  * Input:
2005c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
2006c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing SRQ modify command.
2007c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
2008c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
2009c39526b7SPramod Gunjikar  * Output:
2010c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
2011c39526b7SPramod Gunjikar  * Returns:
2012c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
2013c39526b7SPramod Gunjikar  * Description:
2014c39526b7SPramod Gunjikar  *      User verbs entry point to modify a device shared receive queue.
2015c39526b7SPramod Gunjikar  */
2016c39526b7SPramod Gunjikar /* ARGSUSED */
2017c39526b7SPramod Gunjikar int
sol_uverbs_modify_srq(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2018c39526b7SPramod Gunjikar sol_uverbs_modify_srq(uverbs_uctxt_uobj_t *uctxt, char *buf,
2019c39526b7SPramod Gunjikar     int in_len, int out_len)
2020c39526b7SPramod Gunjikar {
2021c39526b7SPramod Gunjikar 	struct ib_uverbs_modify_srq	cmd;
2022c39526b7SPramod Gunjikar 	uverbs_usrq_uobj_t		*usrq;
2023c39526b7SPramod Gunjikar 	uint_t				limit = 0;
2024c39526b7SPramod Gunjikar 	uint_t				size = 0;
2025c39526b7SPramod Gunjikar 	uint_t				real_size = 0;
2026c39526b7SPramod Gunjikar 	ibt_srq_modify_flags_t 		flags = 0;
2027c39526b7SPramod Gunjikar 	int				rc;
2028c39526b7SPramod Gunjikar 
2029c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
2030c39526b7SPramod Gunjikar 
2031c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2032c39526b7SPramod Gunjikar 	    "modify_srq(): entry (srq_handle=%d)", cmd.srq_handle);
2033c39526b7SPramod Gunjikar 
2034c39526b7SPramod Gunjikar 	usrq = uverbs_uobj_get_usrq_read(cmd.srq_handle);
2035c39526b7SPramod Gunjikar 	if (usrq == NULL) {
2036c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2037c39526b7SPramod Gunjikar 		    "modify_srq(): List lookup failure");
2038c39526b7SPramod Gunjikar 		rc = EINVAL;
2039c39526b7SPramod Gunjikar 		goto err_out;
2040c39526b7SPramod Gunjikar 	}
2041c39526b7SPramod Gunjikar 
2042c39526b7SPramod Gunjikar 	if (cmd.attr_mask & IB_SRQ_MAX_WR) {
2043c39526b7SPramod Gunjikar 		flags = IBT_SRQ_SET_SIZE;
2044c39526b7SPramod Gunjikar 		size = cmd.max_wr;
2045c39526b7SPramod Gunjikar 	}
2046c39526b7SPramod Gunjikar 
2047c39526b7SPramod Gunjikar 	if (cmd.attr_mask & IB_SRQ_LIMIT) {
2048c39526b7SPramod Gunjikar 		flags |= IBT_SRQ_SET_LIMIT;
2049c39526b7SPramod Gunjikar 		limit = cmd.srq_limit;
2050c39526b7SPramod Gunjikar 	}
2051c39526b7SPramod Gunjikar 
2052c39526b7SPramod Gunjikar 	rc = ibt_modify_srq(usrq->srq, flags, size, limit, &real_size);
2053c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
2054c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2055c39526b7SPramod Gunjikar 		    "modify_srq(): Error in ibt_modify_srq() (rc=%d)", rc);
2056c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
2057c39526b7SPramod Gunjikar 		goto err_deref;
2058c39526b7SPramod Gunjikar 	}
2059c39526b7SPramod Gunjikar 
2060c39526b7SPramod Gunjikar done:
2061c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&usrq->uobj);
2062c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
2063c39526b7SPramod Gunjikar 
2064c39526b7SPramod Gunjikar err_deref:
2065c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&usrq->uobj);
2066c39526b7SPramod Gunjikar 
2067c39526b7SPramod Gunjikar err_out:
2068c39526b7SPramod Gunjikar 	return (rc);
2069c39526b7SPramod Gunjikar }
2070c39526b7SPramod Gunjikar 
2071c39526b7SPramod Gunjikar /*
2072c39526b7SPramod Gunjikar  * Function:
2073c39526b7SPramod Gunjikar  *      sol_uverbs_query_srq
2074c39526b7SPramod Gunjikar  * Input:
2075c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
2076c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing command.
2077c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
2078c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
2079c39526b7SPramod Gunjikar  * Output:
2080c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
2081c39526b7SPramod Gunjikar  * Returns:
2082c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
2083c39526b7SPramod Gunjikar  * Description:
2084c39526b7SPramod Gunjikar  *      User verbs entry point to query a device shared receive queue
2085c39526b7SPramod Gunjikar  *	properties.
2086c39526b7SPramod Gunjikar  */
2087c39526b7SPramod Gunjikar /* ARGSUSED */
2088c39526b7SPramod Gunjikar int
sol_uverbs_query_srq(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2089c39526b7SPramod Gunjikar sol_uverbs_query_srq(uverbs_uctxt_uobj_t *uctxt, char *buf,
2090c39526b7SPramod Gunjikar     int in_len, int out_len)
2091c39526b7SPramod Gunjikar {
2092c39526b7SPramod Gunjikar 	struct ib_uverbs_query_srq	cmd;
2093c39526b7SPramod Gunjikar 	struct ib_uverbs_query_srq_resp	resp;
2094c39526b7SPramod Gunjikar 	uverbs_usrq_uobj_t		*usrq;
2095c39526b7SPramod Gunjikar 	ibt_pd_hdl_t			pd;
2096c39526b7SPramod Gunjikar 	int				rc;
2097c39526b7SPramod Gunjikar 	ibt_srq_sizes_t			attr;
2098c39526b7SPramod Gunjikar 	uint_t				limit;
2099c39526b7SPramod Gunjikar 
2100c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
2101c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
2102c39526b7SPramod Gunjikar 
2103c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2104c39526b7SPramod Gunjikar 	    "query_srq(): entry (srq_handle=%d)", cmd.srq_handle);
2105c39526b7SPramod Gunjikar 
2106c39526b7SPramod Gunjikar 	usrq = uverbs_uobj_get_usrq_read(cmd.srq_handle);
2107c39526b7SPramod Gunjikar 	if (usrq == NULL) {
2108c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2109c39526b7SPramod Gunjikar 		    "query_srq(): Invalid handle: %d", cmd.srq_handle);
2110c39526b7SPramod Gunjikar 		rc = EINVAL;
2111c39526b7SPramod Gunjikar 		goto err_out;
2112c39526b7SPramod Gunjikar 	}
2113c39526b7SPramod Gunjikar 
2114c39526b7SPramod Gunjikar 	rc = ibt_query_srq(usrq->srq, &pd, &attr, &limit);
2115c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&usrq->uobj);
2116c39526b7SPramod Gunjikar 
2117c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
2118c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2119c39526b7SPramod Gunjikar 		    "query_srq(): Error in ibt_query_srq() (rc=%d)", rc);
2120c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
2121c39526b7SPramod Gunjikar 		goto err_out;
2122c39526b7SPramod Gunjikar 	}
2123c39526b7SPramod Gunjikar 
2124c39526b7SPramod Gunjikar 	resp.max_wr    = attr.srq_wr_sz;
2125c39526b7SPramod Gunjikar 	resp.max_sge   = attr.srq_sgl_sz;
2126c39526b7SPramod Gunjikar 	resp.srq_limit = limit;
2127c39526b7SPramod Gunjikar 
2128c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "query_srq() - "
2129c39526b7SPramod Gunjikar 	    "max_wr=%d, max_sge=%d, limit=%d", resp.max_wr,
2130c39526b7SPramod Gunjikar 	    resp.max_sge, resp.srq_limit);
2131c39526b7SPramod Gunjikar 
2132c39526b7SPramod Gunjikar 	/*
2133c39526b7SPramod Gunjikar 	 * Release the reference from the find above, we leave the initial
2134c39526b7SPramod Gunjikar 	 * reference placed at SRQ creation time.
2135c39526b7SPramod Gunjikar 	 */
2136c39526b7SPramod Gunjikar 
2137c39526b7SPramod Gunjikar #ifdef	_LP64
2138c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
2139c39526b7SPramod Gunjikar #else
2140c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
2141c39526b7SPramod Gunjikar #endif
2142c39526b7SPramod Gunjikar 	if (rc != 0) {
2143c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "query_srq() - "
2144c39526b7SPramod Gunjikar 		    "copyout failure %x", rc);
2145c39526b7SPramod Gunjikar 		rc = EFAULT;
2146c39526b7SPramod Gunjikar 		goto err_out;
2147c39526b7SPramod Gunjikar 	}
2148c39526b7SPramod Gunjikar 
2149c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
2150c39526b7SPramod Gunjikar 
2151c39526b7SPramod Gunjikar err_out:
2152c39526b7SPramod Gunjikar 	return (rc);
2153c39526b7SPramod Gunjikar }
2154c39526b7SPramod Gunjikar 
2155c39526b7SPramod Gunjikar int
uverbs_usrq_free(uverbs_usrq_uobj_t * usrq,uverbs_uctxt_uobj_t * uctxt)2156c39526b7SPramod Gunjikar uverbs_usrq_free(uverbs_usrq_uobj_t *usrq, uverbs_uctxt_uobj_t *uctxt)
2157c39526b7SPramod Gunjikar {
2158c39526b7SPramod Gunjikar 	int	rc;
2159c39526b7SPramod Gunjikar 
2160c39526b7SPramod Gunjikar 	if (!usrq->srq)
2161c39526b7SPramod Gunjikar 		goto skip_ibt_free_srq;
2162c39526b7SPramod Gunjikar 
2163c39526b7SPramod Gunjikar 	rc = ibt_free_srq(usrq->srq);
2164c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
2165c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "usrq_free() - "
2166c39526b7SPramod Gunjikar 		    "Error in ibt_free_srq() (rc=%d)", rc);
2167c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
2168c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&usrq->uobj);
2169c39526b7SPramod Gunjikar 		return (rc);
2170c39526b7SPramod Gunjikar 	}
2171c39526b7SPramod Gunjikar 	usrq->srq = NULL;
2172c39526b7SPramod Gunjikar 
2173c39526b7SPramod Gunjikar skip_ibt_free_srq :
2174c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&usrq->uobj);
2175c39526b7SPramod Gunjikar 	if (usrq->list_entry) {
2176c39526b7SPramod Gunjikar 		mutex_enter(&uctxt->lock);
2177c39526b7SPramod Gunjikar 		delete_genlist(&uctxt->srq_list,  usrq->list_entry);
2178c39526b7SPramod Gunjikar 		mutex_exit(&uctxt->lock);
2179c39526b7SPramod Gunjikar 		(void) sol_ofs_uobj_remove(&uverbs_usrq_uo_tbl, &usrq->uobj);
2180c39526b7SPramod Gunjikar 	}
2181c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(&usrq->uobj, sol_ofs_uobj_free);
2182c39526b7SPramod Gunjikar 
2183c39526b7SPramod Gunjikar 	return (0);
2184c39526b7SPramod Gunjikar }
2185c39526b7SPramod Gunjikar 
2186c39526b7SPramod Gunjikar /*
2187c39526b7SPramod Gunjikar  * Function:
2188c39526b7SPramod Gunjikar  *      sol_uverbs_destroy_srq
2189c39526b7SPramod Gunjikar  * Input:
2190c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
2191c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing command.
2192c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
2193c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
2194c39526b7SPramod Gunjikar  * Output:
2195c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
2196c39526b7SPramod Gunjikar  * Returns:
2197c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
2198c39526b7SPramod Gunjikar  * Description:
2199c39526b7SPramod Gunjikar  *      User verbs entry point to destroy a device shared receive queue.
2200c39526b7SPramod Gunjikar  */
2201c39526b7SPramod Gunjikar /* ARGSUSED */
2202c39526b7SPramod Gunjikar int
sol_uverbs_destroy_srq(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2203c39526b7SPramod Gunjikar sol_uverbs_destroy_srq(uverbs_uctxt_uobj_t *uctxt, char *buf,
2204c39526b7SPramod Gunjikar     int in_len, int out_len)
2205c39526b7SPramod Gunjikar {
2206c39526b7SPramod Gunjikar 	struct ib_uverbs_destroy_srq		cmd;
2207c39526b7SPramod Gunjikar 	struct ib_uverbs_destroy_srq_resp	resp;
2208c39526b7SPramod Gunjikar 	uverbs_usrq_uobj_t			*usrq;
2209c39526b7SPramod Gunjikar 	int					rc;
2210c39526b7SPramod Gunjikar 
2211c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
2212c39526b7SPramod Gunjikar 	(void) memset(&resp, 0, sizeof (resp));
2213c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "destroy_srq() - "
2214c39526b7SPramod Gunjikar 	    "srq_handle %d", cmd.srq_handle);
2215c39526b7SPramod Gunjikar 
2216c39526b7SPramod Gunjikar 	usrq = uverbs_uobj_get_usrq_write(cmd.srq_handle);
2217c39526b7SPramod Gunjikar 	if (usrq == NULL) {
2218c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2219c39526b7SPramod Gunjikar 		    "destroy_srq() : inavlid hdl %d", cmd.srq_handle);
2220c39526b7SPramod Gunjikar 		rc = EINVAL;
2221c39526b7SPramod Gunjikar 		goto err_out;
2222c39526b7SPramod Gunjikar 	}
2223c39526b7SPramod Gunjikar 
2224c39526b7SPramod Gunjikar 	uverbs_release_usrq_uevents(uctxt->async_evfile, usrq);
2225c39526b7SPramod Gunjikar 	resp.events_reported = usrq->async_events_reported;
2226c39526b7SPramod Gunjikar 	if (usrq->active_qp_cnt) {
2227c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&usrq->uobj);
2228c39526b7SPramod Gunjikar 		return (EBUSY);
2229c39526b7SPramod Gunjikar 	} else {
2230c39526b7SPramod Gunjikar 		rc = uverbs_usrq_free(usrq, uctxt);
2231c39526b7SPramod Gunjikar 		if (rc)
2232c39526b7SPramod Gunjikar 			goto err_out;
2233c39526b7SPramod Gunjikar 	}
2234c39526b7SPramod Gunjikar 
2235c39526b7SPramod Gunjikar #ifdef	_LP64
2236c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp));
2237c39526b7SPramod Gunjikar #else
2238c39526b7SPramod Gunjikar 	rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp));
2239c39526b7SPramod Gunjikar #endif
2240c39526b7SPramod Gunjikar 	if (rc != 0) {
2241c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2242c39526b7SPramod Gunjikar 		    "destroy_srq() : copyout failure %x", rc);
2243c39526b7SPramod Gunjikar 		rc = EFAULT;
2244c39526b7SPramod Gunjikar 		goto err_out;
2245c39526b7SPramod Gunjikar 	}
2246c39526b7SPramod Gunjikar 
2247c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
2248c39526b7SPramod Gunjikar 
2249c39526b7SPramod Gunjikar err_out:
2250c39526b7SPramod Gunjikar 	return (rc);
2251c39526b7SPramod Gunjikar }
2252c39526b7SPramod Gunjikar 
2253c39526b7SPramod Gunjikar /*
2254c39526b7SPramod Gunjikar  * Function:
2255c39526b7SPramod Gunjikar  *      sol_uverbs_attach_mcast
2256c39526b7SPramod Gunjikar  * Input:
2257c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
2258c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing command.
2259c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
2260c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
2261c39526b7SPramod Gunjikar  * Output:
2262c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
2263c39526b7SPramod Gunjikar  * Returns:
2264c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
2265c39526b7SPramod Gunjikar  * Description:
2266c39526b7SPramod Gunjikar  *      User verbs entry point to attach a QP to a multicast group
2267c39526b7SPramod Gunjikar  */
2268c39526b7SPramod Gunjikar /* ARGSUSED */
2269c39526b7SPramod Gunjikar int
sol_uverbs_attach_mcast(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2270c39526b7SPramod Gunjikar sol_uverbs_attach_mcast(uverbs_uctxt_uobj_t *uctxt, char *buf,
2271c39526b7SPramod Gunjikar     int in_len, int out_len)
2272c39526b7SPramod Gunjikar {
2273c39526b7SPramod Gunjikar 	struct ib_uverbs_attach_mcast	cmd;
2274c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t		*uqp;
2275c39526b7SPramod Gunjikar 	uverbs_mcast_entry_t		*mc;
2276c39526b7SPramod Gunjikar 	llist_head_t			*entry;
2277c39526b7SPramod Gunjikar 	int				rc;
2278c39526b7SPramod Gunjikar 	ib_gid_t			mc_gid;
2279c39526b7SPramod Gunjikar 
2280c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
2281c39526b7SPramod Gunjikar 
2282c39526b7SPramod Gunjikar 	/*
2283c39526b7SPramod Gunjikar 	 * API specifies gid in network order, Solaris expects the gid
2284c39526b7SPramod Gunjikar 	 * in host order, do the conversion if required.
2285c39526b7SPramod Gunjikar 	 */
2286c39526b7SPramod Gunjikar 	mc_gid.gid_prefix = b2h64(*((uint64_t *)&cmd.gid[0]));
2287c39526b7SPramod Gunjikar 	mc_gid.gid_guid   = b2h64(*((uint64_t *)&cmd.gid[8]));
2288c39526b7SPramod Gunjikar 
2289c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "attach_mcast(qp_handle=%d, "
2290c39526b7SPramod Gunjikar 	    "mlid=0x%04x, gid=%016llx:%016llx", cmd.qp_handle, cmd.mlid,
2291c39526b7SPramod Gunjikar 	    mc_gid.gid_prefix, mc_gid.gid_guid);
2292c39526b7SPramod Gunjikar 
2293c39526b7SPramod Gunjikar 	/*
2294c39526b7SPramod Gunjikar 	 * Take object write to protect MC list.
2295c39526b7SPramod Gunjikar 	 */
2296c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_write(cmd.qp_handle);
2297c39526b7SPramod Gunjikar 	if (uqp == NULL) {
2298c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2299c39526b7SPramod Gunjikar 		    "attach_mcast QP not found");
2300c39526b7SPramod Gunjikar 		rc = EINVAL;
2301c39526b7SPramod Gunjikar 		goto err_out;
2302c39526b7SPramod Gunjikar 	}
2303c39526b7SPramod Gunjikar 
2304c39526b7SPramod Gunjikar 	/*
2305c39526b7SPramod Gunjikar 	 * Look to see if we are already attached and if so no need to attach
2306c39526b7SPramod Gunjikar 	 * again, just return good status.
2307c39526b7SPramod Gunjikar 	 */
2308c39526b7SPramod Gunjikar 	list_for_each(entry, &uqp->mcast_list) {
2309c39526b7SPramod Gunjikar 		mc = (uverbs_mcast_entry_t *)entry->ptr;
2310c39526b7SPramod Gunjikar 
2311c39526b7SPramod Gunjikar 		if (cmd.mlid == mc->mcg.mc_adds_vect.av_dlid &&
2312c39526b7SPramod Gunjikar 		    !memcmp(&mc_gid.gid, &mc->mcg.mc_adds_vect.av_dgid,
2313c39526b7SPramod Gunjikar 		    sizeof (mc_gid.gid))) {
2314c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L4(sol_uverbs_dbg_str,
2315c39526b7SPramod Gunjikar 			    "attach_mcast: match entry found");
2316c39526b7SPramod Gunjikar 			rc = DDI_SUCCESS;
2317c39526b7SPramod Gunjikar 			goto out_put;
2318c39526b7SPramod Gunjikar 		}
2319c39526b7SPramod Gunjikar 	}
2320c39526b7SPramod Gunjikar 
2321c39526b7SPramod Gunjikar 	mc = kmem_zalloc(sizeof (*mc), KM_NOSLEEP);
2322c39526b7SPramod Gunjikar 	if (mc == NULL) {
2323c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2324c39526b7SPramod Gunjikar 		    "attach_mcast: kmem_zalloc fail");
2325c39526b7SPramod Gunjikar 		rc = ENOMEM;
2326c39526b7SPramod Gunjikar 		goto out_put;
2327c39526b7SPramod Gunjikar 	}
2328c39526b7SPramod Gunjikar 
2329c39526b7SPramod Gunjikar 	llist_head_init(&mc->list, mc);
2330c39526b7SPramod Gunjikar 	mc->mcg.mc_adds_vect.av_dlid  = cmd.mlid;
2331c39526b7SPramod Gunjikar 	bcopy(&mc_gid, &(mc->mcg.mc_adds_vect.av_dgid), sizeof (mc_gid));
2332c39526b7SPramod Gunjikar 
2333c39526b7SPramod Gunjikar 	rc = ibt_attach_mcg(uqp->qp, &mc->mcg);
2334c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
2335c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2336c39526b7SPramod Gunjikar 		    "attach_mcast: ibt_attach_mcq failed (r=%d)", rc);
2337c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
2338c39526b7SPramod Gunjikar 		goto err_free;
2339c39526b7SPramod Gunjikar 	}
2340c39526b7SPramod Gunjikar 
2341c39526b7SPramod Gunjikar 	llist_add_tail(&mc->list, &uqp->mcast_list);
2342c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
2343c39526b7SPramod Gunjikar 
2344c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
2345c39526b7SPramod Gunjikar 
2346c39526b7SPramod Gunjikar err_free:
2347c39526b7SPramod Gunjikar 	kmem_free(mc, sizeof (*mc));
2348c39526b7SPramod Gunjikar out_put:
2349c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
2350c39526b7SPramod Gunjikar err_out:
2351c39526b7SPramod Gunjikar 	return (rc);
2352c39526b7SPramod Gunjikar }
2353c39526b7SPramod Gunjikar 
2354c39526b7SPramod Gunjikar /*
2355c39526b7SPramod Gunjikar  * Function:
2356c39526b7SPramod Gunjikar  *      sol_uverbs_detach_mcast
2357c39526b7SPramod Gunjikar  * Input:
2358c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
2359c39526b7SPramod Gunjikar  *      buf     - Pointer to kernel buffer containing command.
2360c39526b7SPramod Gunjikar  *      in_len  - Length in bytes of input command buffer.
2361c39526b7SPramod Gunjikar  *      out_len - Length in bytes of output response buffer.
2362c39526b7SPramod Gunjikar  * Output:
2363c39526b7SPramod Gunjikar  *      The command output buffer is updated with command results.
2364c39526b7SPramod Gunjikar  * Returns:
2365c39526b7SPramod Gunjikar  *      DDI_SUCCESS on success, else error code.
2366c39526b7SPramod Gunjikar  * Description:
2367c39526b7SPramod Gunjikar  *      User verbs entry point to detach a QP from a multicast group
2368c39526b7SPramod Gunjikar  */
2369c39526b7SPramod Gunjikar /* ARGSUSED */
2370c39526b7SPramod Gunjikar int
sol_uverbs_detach_mcast(uverbs_uctxt_uobj_t * uctxt,char * buf,int in_len,int out_len)2371c39526b7SPramod Gunjikar sol_uverbs_detach_mcast(uverbs_uctxt_uobj_t *uctxt, char *buf,
2372c39526b7SPramod Gunjikar     int in_len, int out_len)
2373c39526b7SPramod Gunjikar {
2374c39526b7SPramod Gunjikar 	struct ib_uverbs_detach_mcast	cmd;
2375c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t		*uqp;
2376c39526b7SPramod Gunjikar 	ibt_mcg_info_t			mcg;
2377c39526b7SPramod Gunjikar 	int				rc;
2378c39526b7SPramod Gunjikar 	uverbs_mcast_entry_t		*mc;
2379c39526b7SPramod Gunjikar 	llist_head_t			*entry;
2380c39526b7SPramod Gunjikar 	llist_head_t			*temp;
2381c39526b7SPramod Gunjikar 	ib_gid_t			mc_gid;
2382c39526b7SPramod Gunjikar 
2383c39526b7SPramod Gunjikar 	(void) memcpy(&cmd, buf, sizeof (cmd));
2384c39526b7SPramod Gunjikar 
2385c39526b7SPramod Gunjikar 	/*
2386c39526b7SPramod Gunjikar 	 * API specifies gid in network order, Solaris expects the gid
2387c39526b7SPramod Gunjikar 	 * in host order, do the conversion if required.
2388c39526b7SPramod Gunjikar 	 */
2389c39526b7SPramod Gunjikar 	mc_gid.gid_prefix = b2h64(*((uint64_t *)&cmd.gid[0]));
2390c39526b7SPramod Gunjikar 	mc_gid.gid_guid   = b2h64(*((uint64_t *)&cmd.gid[8]));
2391c39526b7SPramod Gunjikar 
2392c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2393c39526b7SPramod Gunjikar 	    "detach_mcast: entry (qp_handle=%d, mlid=0x%04x,"
2394c39526b7SPramod Gunjikar 	    "gid=%016llx:%016llx", cmd.qp_handle, cmd.mlid, mc_gid.gid_prefix,
2395c39526b7SPramod Gunjikar 	    mc_gid.gid_guid);
2396c39526b7SPramod Gunjikar 
2397c39526b7SPramod Gunjikar 	(void) memset(&mcg, 0, sizeof (mcg));
2398c39526b7SPramod Gunjikar 
2399c39526b7SPramod Gunjikar 	/*
2400c39526b7SPramod Gunjikar 	 * Get object write to protect mcast list.
2401c39526b7SPramod Gunjikar 	 */
2402c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_write(cmd.qp_handle);
2403c39526b7SPramod Gunjikar 	if (uqp == NULL) {
2404c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2405c39526b7SPramod Gunjikar 		    "detach_mcast(): QP hdl %x not found", cmd.qp_handle);
2406c39526b7SPramod Gunjikar 		rc = EINVAL;
2407c39526b7SPramod Gunjikar 		goto err_out;
2408c39526b7SPramod Gunjikar 	}
2409c39526b7SPramod Gunjikar 
2410c39526b7SPramod Gunjikar 	mcg.mc_adds_vect.av_dlid = cmd.mlid;
2411c39526b7SPramod Gunjikar 	mcg.mc_adds_vect.av_dgid = mc_gid;
2412c39526b7SPramod Gunjikar 
2413c39526b7SPramod Gunjikar 	rc = ibt_detach_mcg(uqp->qp, &mcg);
2414c39526b7SPramod Gunjikar 	if (rc != IBT_SUCCESS) {
2415c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2416c39526b7SPramod Gunjikar 		    "deatch_mcast(): ibt_attach_mcq failed (r=%d)", rc);
2417c39526b7SPramod Gunjikar 		rc = sol_uverbs_ibt_to_kernel_status(rc);
2418c39526b7SPramod Gunjikar 		goto err_put;
2419c39526b7SPramod Gunjikar 	}
2420c39526b7SPramod Gunjikar 
2421c39526b7SPramod Gunjikar 	/*
2422c39526b7SPramod Gunjikar 	 * Find and delete MC group from the QP multicast list.
2423c39526b7SPramod Gunjikar 	 */
2424c39526b7SPramod Gunjikar 	entry = uqp->mcast_list.nxt;
2425c39526b7SPramod Gunjikar 	temp = entry->nxt;
2426c39526b7SPramod Gunjikar 	while (entry != &uqp->mcast_list) {
2427c39526b7SPramod Gunjikar 		ASSERT(entry);
2428c39526b7SPramod Gunjikar 		mc    = (uverbs_mcast_entry_t *)entry->ptr;
2429c39526b7SPramod Gunjikar 		ASSERT(mc);
2430c39526b7SPramod Gunjikar 
2431c39526b7SPramod Gunjikar 		if (cmd.mlid == mc->mcg.mc_adds_vect.av_dlid &&
2432c39526b7SPramod Gunjikar 		    !memcmp(&mc_gid.gid, &mc->mcg.mc_adds_vect.av_dgid,
2433c39526b7SPramod Gunjikar 		    sizeof (mc_gid.gid))) {
2434c39526b7SPramod Gunjikar 			llist_del(&mc->list);
2435c39526b7SPramod Gunjikar 			kmem_free(mc, sizeof (*mc));
2436c39526b7SPramod Gunjikar 			break;
2437c39526b7SPramod Gunjikar 		}
2438c39526b7SPramod Gunjikar 		entry = temp;
2439c39526b7SPramod Gunjikar 		temp = entry->nxt;
2440c39526b7SPramod Gunjikar 	}
2441c39526b7SPramod Gunjikar 
2442c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
2443c39526b7SPramod Gunjikar 
2444c39526b7SPramod Gunjikar 	return (DDI_SUCCESS);
2445c39526b7SPramod Gunjikar 
2446c39526b7SPramod Gunjikar err_put:
2447c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
2448c39526b7SPramod Gunjikar 
2449c39526b7SPramod Gunjikar err_out:
2450c39526b7SPramod Gunjikar 	return (rc);
2451c39526b7SPramod Gunjikar }
2452c39526b7SPramod Gunjikar 
2453c39526b7SPramod Gunjikar /*
2454c39526b7SPramod Gunjikar  * Function:
2455c39526b7SPramod Gunjikar  *      uverbs_release_uqp_mcast_entries
2456c39526b7SPramod Gunjikar  * Input:
2457c39526b7SPramod Gunjikar  *      uctxt   - Pointer to the callers user context.
2458c39526b7SPramod Gunjikar  *      uqp     - Pointer to the user QP object for which the multicast
2459c39526b7SPramod Gunjikar  *                list should be flushed.
2460c39526b7SPramod Gunjikar  * Output:
2461c39526b7SPramod Gunjikar  *      None
2462c39526b7SPramod Gunjikar  * Returns:
2463c39526b7SPramod Gunjikar  *      None
2464c39526b7SPramod Gunjikar  * Description:
2465c39526b7SPramod Gunjikar  *      Release any multicast resources held by this QP.  The
2466c39526b7SPramod Gunjikar  *	user context associated with the QP should be locked
2467c39526b7SPramod Gunjikar  *	externally to this routine to protect the updates to the
2468c39526b7SPramod Gunjikar  *	multicast list.
2469c39526b7SPramod Gunjikar  */
2470c39526b7SPramod Gunjikar void
uverbs_detach_uqp_mcast_entries(uverbs_uqp_uobj_t * uqp)2471c39526b7SPramod Gunjikar uverbs_detach_uqp_mcast_entries(uverbs_uqp_uobj_t *uqp)
2472c39526b7SPramod Gunjikar {
2473c39526b7SPramod Gunjikar 	int			rc;
2474c39526b7SPramod Gunjikar 	uverbs_mcast_entry_t	*mc;
2475c39526b7SPramod Gunjikar 	llist_head_t		*entry;
2476c39526b7SPramod Gunjikar 	llist_head_t		*temp;
2477c39526b7SPramod Gunjikar 
2478c39526b7SPramod Gunjikar 	/*
2479c39526b7SPramod Gunjikar 	 * Find and delete MC group from the QP multicast list.
2480c39526b7SPramod Gunjikar 	 */
2481c39526b7SPramod Gunjikar 	entry = uqp->mcast_list.nxt;
2482c39526b7SPramod Gunjikar 	temp = entry->nxt;
2483c39526b7SPramod Gunjikar 	while (entry != &uqp->mcast_list) {
2484c39526b7SPramod Gunjikar 		ASSERT(entry);
2485c39526b7SPramod Gunjikar 		mc    = (uverbs_mcast_entry_t *)entry->ptr;
2486c39526b7SPramod Gunjikar 		ASSERT(mc);
2487c39526b7SPramod Gunjikar 
2488c39526b7SPramod Gunjikar 		rc = ibt_detach_mcg(uqp->qp, &mc->mcg);
2489c39526b7SPramod Gunjikar 		if (rc != IBT_SUCCESS) {
2490c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2491c39526b7SPramod Gunjikar 			    "detach_mcast() : "
2492c39526b7SPramod Gunjikar 			    "ibt_detach_mcq failed (r=%d)", rc);
2493c39526b7SPramod Gunjikar 		}
2494c39526b7SPramod Gunjikar 		llist_del(&mc->list);
2495c39526b7SPramod Gunjikar 		entry = temp;
2496c39526b7SPramod Gunjikar 		temp = entry->nxt;
2497c39526b7SPramod Gunjikar 	}
2498c39526b7SPramod Gunjikar }
2499c39526b7SPramod Gunjikar 
2500c39526b7SPramod Gunjikar /*
2501c39526b7SPramod Gunjikar  * Function:
2502c39526b7SPramod Gunjikar  *      sol_uverbs_uqpid_to_ibt_handle
2503c39526b7SPramod Gunjikar  * Input:
2504c39526b7SPramod Gunjikar  *      uqpid   - A user verbs QP id, i.e. a QP handle that was
2505c39526b7SPramod Gunjikar  *	          created via libibverbs and sol_uverbs.
2506c39526b7SPramod Gunjikar  * Output:
2507c39526b7SPramod Gunjikar  *      None
2508c39526b7SPramod Gunjikar  * Returns:
2509c39526b7SPramod Gunjikar  *      The ibt_qp_hdl_t associated with the user space QP handle.
2510c39526b7SPramod Gunjikar  *	-1 is returned if the id is not found.
2511c39526b7SPramod Gunjikar  * Description:
2512c39526b7SPramod Gunjikar  *      Map the user verbs QP id to the associated IBT QP handle.
2513c39526b7SPramod Gunjikar  */
2514c39526b7SPramod Gunjikar ibt_qp_hdl_t
sol_uverbs_uqpid_to_ibt_handle(uint32_t uqpid)2515c39526b7SPramod Gunjikar sol_uverbs_uqpid_to_ibt_handle(uint32_t uqpid)
2516c39526b7SPramod Gunjikar {
2517c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t	*uqp;
2518c39526b7SPramod Gunjikar 	void			*qphdl;
2519c39526b7SPramod Gunjikar 
2520c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_read(uqpid);
2521c39526b7SPramod Gunjikar 	if (uqp == NULL) {
2522c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2523c39526b7SPramod Gunjikar 		    "uqpid2ibthdl: QP lookup failure: id %d", uqpid);
2524c39526b7SPramod Gunjikar 		return (NULL);
2525c39526b7SPramod Gunjikar 	}
2526c39526b7SPramod Gunjikar 	qphdl = (void *)uqp->qp;
2527c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
2528c39526b7SPramod Gunjikar 	return (qphdl);
2529c39526b7SPramod Gunjikar }
2530c39526b7SPramod Gunjikar 
2531c39526b7SPramod Gunjikar /*
2532c39526b7SPramod Gunjikar  * Function:
2533c39526b7SPramod Gunjikar  *      sol_uverbs_disable_user_qp_modify
2534c39526b7SPramod Gunjikar  * Input:
2535c39526b7SPramod Gunjikar  *      uqpid   - A user verbs QP id, i.e. a QP handle that was
2536c39526b7SPramod Gunjikar  *	          created via libibverbs and sol_uverbs.
2537c39526b7SPramod Gunjikar  * Output:
2538c39526b7SPramod Gunjikar  *      None
2539c39526b7SPramod Gunjikar  * Returns:
2540c39526b7SPramod Gunjikar  *      0 on success, EINVAL if associated QP is not found.
2541c39526b7SPramod Gunjikar  * Description:
2542c39526b7SPramod Gunjikar  *      Inform sol_uverbs driver to ignore user qp modify
2543c39526b7SPramod Gunjikar  *	operations it receives for the specified qp.  To re-enable
2544c39526b7SPramod Gunjikar  *	this capability see the function sol_uverbs_enable_user_qp_modify.
2545c39526b7SPramod Gunjikar  */
2546c39526b7SPramod Gunjikar int
sol_uverbs_disable_user_qp_modify(uint32_t uqpid)2547c39526b7SPramod Gunjikar sol_uverbs_disable_user_qp_modify(uint32_t uqpid)
2548c39526b7SPramod Gunjikar {
2549c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t	*uqp;
2550c39526b7SPramod Gunjikar 
2551c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_write(uqpid);
2552c39526b7SPramod Gunjikar 	if (uqp == NULL) {
2553c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2554c39526b7SPramod Gunjikar 		    "disable_uqp_modify(%d) -lookup failure", uqpid);
2555c39526b7SPramod Gunjikar 		return (EINVAL);
2556c39526b7SPramod Gunjikar 	}
2557c39526b7SPramod Gunjikar 	uqp->disable_qp_mod = TRUE;
2558c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
2559c39526b7SPramod Gunjikar 	return (0);
2560c39526b7SPramod Gunjikar }
2561c39526b7SPramod Gunjikar 
2562c39526b7SPramod Gunjikar /*
2563c39526b7SPramod Gunjikar  * Function:
2564c39526b7SPramod Gunjikar  *      sol_uverbs_enable_user_qp_modify
2565c39526b7SPramod Gunjikar  * Input:
2566c39526b7SPramod Gunjikar  *      uqpid   - A user verbs QP id, i.e. a QP handle that was
2567c39526b7SPramod Gunjikar  *	          created via libibverbs and sol_uverbs.
2568c39526b7SPramod Gunjikar  * Output:
2569c39526b7SPramod Gunjikar  *      None
2570c39526b7SPramod Gunjikar  * Returns:
2571c39526b7SPramod Gunjikar  *      0 on success, EINVAL if associated QP is not found.
2572c39526b7SPramod Gunjikar  * Description:
2573c39526b7SPramod Gunjikar  *      Inform sol_uverbs driver to process user qp modify
2574c39526b7SPramod Gunjikar  *	operations it receives for the specified qp.  This is
2575c39526b7SPramod Gunjikar  *	the default and this routine need only be invoked if
2576c39526b7SPramod Gunjikar  *	user QP modify operations have explicitly been disabled
2577c39526b7SPramod Gunjikar  *	with sol_uverbs_disable_user_qp_modify.
2578c39526b7SPramod Gunjikar  */
2579c39526b7SPramod Gunjikar int
sol_uverbs_enable_user_qp_modify(uint32_t uqpid)2580c39526b7SPramod Gunjikar sol_uverbs_enable_user_qp_modify(uint32_t uqpid)
2581c39526b7SPramod Gunjikar {
2582c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t    *uqp;
2583c39526b7SPramod Gunjikar 
2584c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_write(uqpid);
2585c39526b7SPramod Gunjikar 	if (uqp == NULL) {
2586c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2587c39526b7SPramod Gunjikar 		    "enable_uqp_modify(%d) -lookup failure", uqpid);
2588c39526b7SPramod Gunjikar 		return (EINVAL);
2589c39526b7SPramod Gunjikar 	}
2590c39526b7SPramod Gunjikar 	uqp->disable_qp_mod = FALSE;
2591c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
2592c39526b7SPramod Gunjikar 	return (0);
2593c39526b7SPramod Gunjikar }
2594c39526b7SPramod Gunjikar 
2595c39526b7SPramod Gunjikar int
uverbs_uqpn_cq_ctrl(uint32_t uqpid,sol_uverbs_cq_ctrl_t ctrl)2596c39526b7SPramod Gunjikar uverbs_uqpn_cq_ctrl(uint32_t uqpid, sol_uverbs_cq_ctrl_t ctrl)
2597c39526b7SPramod Gunjikar {
2598c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t	*uqp;
2599c39526b7SPramod Gunjikar 	uverbs_ucq_uobj_t	*uscq;
2600c39526b7SPramod Gunjikar 	uverbs_ucq_uobj_t	*urcq;
2601c39526b7SPramod Gunjikar 
2602c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_write(uqpid);
2603c39526b7SPramod Gunjikar 	if (uqp == NULL) {
2604c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2605c39526b7SPramod Gunjikar 		    "uqpn_cq_ctrl(%d) -lookup failure", uqpid);
2606c39526b7SPramod Gunjikar 		return (EINVAL);
2607c39526b7SPramod Gunjikar 	}
2608c39526b7SPramod Gunjikar 	uscq = uqp->uqp_scq;
2609c39526b7SPramod Gunjikar 	urcq = uqp->uqp_rcq;
2610c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str,
2611c39526b7SPramod Gunjikar 	    "ctrl - uqp %p, rcq %p. scq %p", uqp, urcq, uscq);
2612c39526b7SPramod Gunjikar 
2613c39526b7SPramod Gunjikar 	ASSERT(uscq);
2614c39526b7SPramod Gunjikar 	ASSERT(urcq);
2615c39526b7SPramod Gunjikar 	uverbs_cq_ctrl(uscq, ctrl);
2616c39526b7SPramod Gunjikar 	if (uscq != urcq)
2617c39526b7SPramod Gunjikar 		uverbs_cq_ctrl(urcq, ctrl);
2618c39526b7SPramod Gunjikar 	sol_ofs_uobj_put(&uqp->uobj);
2619c39526b7SPramod Gunjikar 	return (0);
2620c39526b7SPramod Gunjikar }
2621c39526b7SPramod Gunjikar 
2622c39526b7SPramod Gunjikar extern uint32_t	sol_uverbs_qpnum2uqpid(uint32_t);
2623c39526b7SPramod Gunjikar 
2624c39526b7SPramod Gunjikar void
sol_uverbs_flush_qp(uint32_t qpnum)2625c39526b7SPramod Gunjikar sol_uverbs_flush_qp(uint32_t qpnum)
2626c39526b7SPramod Gunjikar {
2627c39526b7SPramod Gunjikar 	int32_t			uqpid;
2628c39526b7SPramod Gunjikar 	ibt_status_t		status;
2629c39526b7SPramod Gunjikar 	uverbs_uqp_uobj_t	*uqp;
2630c39526b7SPramod Gunjikar 
2631c39526b7SPramod Gunjikar 	uqpid = sol_uverbs_qpnum2uqpid(qpnum);
2632c39526b7SPramod Gunjikar 	if (uqpid == DDI_FAILURE) {
2633c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2634c39526b7SPramod Gunjikar 		    "sol_uverbs_flush_qp(%x) - Invalid qpnum",
2635c39526b7SPramod Gunjikar 		    qpnum);
2636c39526b7SPramod Gunjikar 		return;
2637c39526b7SPramod Gunjikar 	}
2638c39526b7SPramod Gunjikar 	uqp = uverbs_uobj_get_uqp_write(uqpid);
2639c39526b7SPramod Gunjikar 	if (uqp == NULL) {
2640c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2641c39526b7SPramod Gunjikar 		    "sol_uverbs_flush_qp(%x) - Invalid "
2642c39526b7SPramod Gunjikar 		    "uqpid %x", qpnum, uqpid);
2643c39526b7SPramod Gunjikar 		return;
2644c39526b7SPramod Gunjikar 	}
2645c39526b7SPramod Gunjikar 
2646c39526b7SPramod Gunjikar 	if (uqp->qp) {
2647c39526b7SPramod Gunjikar 		status = ibt_flush_qp(uqp->qp);
2648c39526b7SPramod Gunjikar 		if (status != IBT_SUCCESS)
2649c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2650c39526b7SPramod Gunjikar 			    "sol_uverbs_flush_qp(%x) - "
2651c39526b7SPramod Gunjikar 			    "ibt_flush_qp(%p) failed - status %d",
2652c39526b7SPramod Gunjikar 			    qpnum, uqp->qp, status);
2653c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uqp->uobj);
2654c39526b7SPramod Gunjikar 		return;
2655c39526b7SPramod Gunjikar 	} else {
2656c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str,
2657c39526b7SPramod Gunjikar 		    "sol_uverbs_flush_qp(%x), uqpid %x -"
2658c39526b7SPramod Gunjikar 		    "uqp->qp is NULL!!", qpnum, uqpid);
2659c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(&uqp->uobj);
2660c39526b7SPramod Gunjikar 		return;
2661c39526b7SPramod Gunjikar 	}
2662c39526b7SPramod Gunjikar }
2663c39526b7SPramod Gunjikar static uint32_t
ibt_cep_flags2ibv(ibt_cep_flags_t ibt_flags)2664c39526b7SPramod Gunjikar ibt_cep_flags2ibv(ibt_cep_flags_t ibt_flags)
2665c39526b7SPramod Gunjikar {
2666c39526b7SPramod Gunjikar 	uint32_t	ib_flags = 0;
2667c39526b7SPramod Gunjikar 
2668c39526b7SPramod Gunjikar 	if (ibt_flags & IBT_CEP_RDMA_WR)
2669c39526b7SPramod Gunjikar 		ib_flags |= IB_ACCESS_REMOTE_WRITE;
2670c39526b7SPramod Gunjikar 	if (ibt_flags & IBT_CEP_RDMA_RD)
2671c39526b7SPramod Gunjikar 		ib_flags |= IB_ACCESS_REMOTE_READ;
2672c39526b7SPramod Gunjikar 	if (ibt_flags & IBT_CEP_ATOMIC)
2673c39526b7SPramod Gunjikar 		ib_flags |= IB_ACCESS_REMOTE_ATOMIC;
2674c39526b7SPramod Gunjikar 
2675c39526b7SPramod Gunjikar 	return (ib_flags);
2676c39526b7SPramod Gunjikar }
2677c39526b7SPramod Gunjikar 
2678c39526b7SPramod Gunjikar static void
uverbs_cq_ctrl(uverbs_ucq_uobj_t * ucq,sol_uverbs_cq_ctrl_t ctrl)2679c39526b7SPramod Gunjikar uverbs_cq_ctrl(uverbs_ucq_uobj_t *ucq, sol_uverbs_cq_ctrl_t ctrl)
2680c39526b7SPramod Gunjikar {
2681c39526b7SPramod Gunjikar 	uverbs_ufile_uobj_t	*ufile;
2682c39526b7SPramod Gunjikar 
2683c39526b7SPramod Gunjikar 	ufile = ucq->comp_chan;
2684c39526b7SPramod Gunjikar 	if (!ufile) {
2685c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str,
2686c39526b7SPramod Gunjikar 		    "cq_ctrl(%p), ufile NULL", ucq, ufile);
2687c39526b7SPramod Gunjikar 		return;
2688c39526b7SPramod Gunjikar 	}
2689c39526b7SPramod Gunjikar 
2690c39526b7SPramod Gunjikar 	mutex_enter(&ufile->lock);
2691c39526b7SPramod Gunjikar 	ufile->ufile_notify_enabled = ctrl;
2692c39526b7SPramod Gunjikar 
2693c39526b7SPramod Gunjikar 	if (ctrl == SOL_UVERBS2UCMA_CQ_NOTIFY_ENABLE) {
2694c39526b7SPramod Gunjikar 		if (!llist_empty(&ufile->event_list)) {
2695c39526b7SPramod Gunjikar 			cv_signal(&ufile->poll_wait);
2696c39526b7SPramod Gunjikar 			pollwakeup(&ufile->poll_head,
2697c39526b7SPramod Gunjikar 			    POLLIN | POLLRDNORM);
2698c39526b7SPramod Gunjikar 		}
2699c39526b7SPramod Gunjikar 	}
2700c39526b7SPramod Gunjikar 	mutex_exit(&ufile->lock);
2701c39526b7SPramod Gunjikar }
2702