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