xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_qp.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_cm.h>
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate  * ibtl_qp.c
34*7c478bd9Sstevel@tonic-gate  *	These routines implement (most of) the verbs related to
35*7c478bd9Sstevel@tonic-gate  *	Queue Pairs.
36*7c478bd9Sstevel@tonic-gate  */
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate /* Globals. */
39*7c478bd9Sstevel@tonic-gate static char ibtf_qp[] = "ibtl";
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate /* This table indirectly initializes the ibt_cep_next_state[] table. */
42*7c478bd9Sstevel@tonic-gate typedef struct ibt_cep_next_state_s {
43*7c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		next_state;
44*7c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
45*7c478bd9Sstevel@tonic-gate } ibt_cep_next_state_t;
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate struct	{
48*7c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		current_state;
49*7c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		next_state;
50*7c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
51*7c478bd9Sstevel@tonic-gate } ibt_cep_next_state_inits[] = {
52*7c478bd9Sstevel@tonic-gate 	{ IBT_STATE_RESET, IBT_STATE_INIT, IBT_CEP_SET_RESET_INIT},
53*7c478bd9Sstevel@tonic-gate 	{ IBT_STATE_INIT, IBT_STATE_RTR, IBT_CEP_SET_INIT_RTR},
54*7c478bd9Sstevel@tonic-gate 	{ IBT_STATE_RTR, IBT_STATE_RTS, IBT_CEP_SET_RTR_RTS}
55*7c478bd9Sstevel@tonic-gate };
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate ibt_cep_next_state_t ibt_cep_next_state[IBT_STATE_NUM];
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique", ibt_cep_next_state))
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate /* The following data and functions can increase system stability. */
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate int ibtl_qp_calls_curr;
64*7c478bd9Sstevel@tonic-gate int ibtl_qp_calls_max = 128;	/* limit on # of simultaneous QP verb calls */
65*7c478bd9Sstevel@tonic-gate kmutex_t ibtl_qp_mutex;
66*7c478bd9Sstevel@tonic-gate kcondvar_t ibtl_qp_cv;
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate void
69*7c478bd9Sstevel@tonic-gate ibtl_qp_flow_control_enter(void)
70*7c478bd9Sstevel@tonic-gate {
71*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_qp_mutex);
72*7c478bd9Sstevel@tonic-gate 	while (ibtl_qp_calls_curr >= ibtl_qp_calls_max) {
73*7c478bd9Sstevel@tonic-gate 		cv_wait(&ibtl_qp_cv, &ibtl_qp_mutex);
74*7c478bd9Sstevel@tonic-gate 	}
75*7c478bd9Sstevel@tonic-gate 	++ibtl_qp_calls_curr;
76*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_qp_mutex);
77*7c478bd9Sstevel@tonic-gate }
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate void
80*7c478bd9Sstevel@tonic-gate ibtl_qp_flow_control_exit(void)
81*7c478bd9Sstevel@tonic-gate {
82*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_qp_mutex);
83*7c478bd9Sstevel@tonic-gate 	cv_signal(&ibtl_qp_cv);
84*7c478bd9Sstevel@tonic-gate 	--ibtl_qp_calls_curr;
85*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_qp_mutex);
86*7c478bd9Sstevel@tonic-gate }
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate /*
89*7c478bd9Sstevel@tonic-gate  * Function:
90*7c478bd9Sstevel@tonic-gate  *	ibt_alloc_qp
91*7c478bd9Sstevel@tonic-gate  * Input:
92*7c478bd9Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
93*7c478bd9Sstevel@tonic-gate  *	type		Specifies the type of QP to alloc in ibt_alloc_qp()
94*7c478bd9Sstevel@tonic-gate  *	qp_attrp	Specifies the ibt_qp_alloc_attr_t that are needed to
95*7c478bd9Sstevel@tonic-gate  *			allocate a QP and transition it to the RTS state for
96*7c478bd9Sstevel@tonic-gate  *			UDs and INIT state for all other QPs.
97*7c478bd9Sstevel@tonic-gate  * Output:
98*7c478bd9Sstevel@tonic-gate  *	queue_sizes_p	Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
99*7c478bd9Sstevel@tonic-gate  *			WR SGL elements.
100*7c478bd9Sstevel@tonic-gate  *	qpn_p		Returned QP Number of the allocated QP.
101*7c478bd9Sstevel@tonic-gate  *	ibt_qp_p	The ibt_qp_hdl_t of the allocated QP.
102*7c478bd9Sstevel@tonic-gate  * Returns:
103*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
104*7c478bd9Sstevel@tonic-gate  * Description:
105*7c478bd9Sstevel@tonic-gate  *	Allocate a QP with specified attributes.
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate ibt_status_t
108*7c478bd9Sstevel@tonic-gate ibt_alloc_qp(ibt_hca_hdl_t hca_hdl, ibt_qp_type_t type,
109*7c478bd9Sstevel@tonic-gate     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
110*7c478bd9Sstevel@tonic-gate     ib_qpn_t *qpn_p, ibt_qp_hdl_t *ibt_qp_p)
111*7c478bd9Sstevel@tonic-gate {
112*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
113*7c478bd9Sstevel@tonic-gate 	ibtl_channel_t		*chanp;
114*7c478bd9Sstevel@tonic-gate 	ibt_tran_srv_t		qp_type;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_qp(%p, %d, %p, %p, %p, %p) ",
117*7c478bd9Sstevel@tonic-gate 	    hca_hdl, type, qp_attrp, queue_sizes_p, qpn_p, ibt_qp_p);
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	switch (type) {
120*7c478bd9Sstevel@tonic-gate 	case IBT_UD_RQP:
121*7c478bd9Sstevel@tonic-gate 		qp_type = IBT_UD_SRV;
122*7c478bd9Sstevel@tonic-gate 		break;
123*7c478bd9Sstevel@tonic-gate 	case IBT_RC_RQP:
124*7c478bd9Sstevel@tonic-gate 		qp_type = IBT_RC_SRV;
125*7c478bd9Sstevel@tonic-gate 		break;
126*7c478bd9Sstevel@tonic-gate 	case IBT_UC_RQP:
127*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Unreliable Connected "
128*7c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
129*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
130*7c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
131*7c478bd9Sstevel@tonic-gate 	case IBT_RD_RQP:
132*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Reliable Datagram "
133*7c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
134*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
135*7c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
136*7c478bd9Sstevel@tonic-gate 	default:
137*7c478bd9Sstevel@tonic-gate 		/* shouldn't happen ILLEGAL Type */
138*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Illegal Transport Type "
139*7c478bd9Sstevel@tonic-gate 		    "%d", type);
140*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
141*7c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
142*7c478bd9Sstevel@tonic-gate 	}
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	/* Get CI CQ handles */
145*7c478bd9Sstevel@tonic-gate 	if ((qp_attrp->qp_scq_hdl == NULL) || (qp_attrp->qp_rcq_hdl == NULL)) {
146*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Invalid CQ Handle");
147*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
148*7c478bd9Sstevel@tonic-gate 		return (IBT_CQ_HDL_INVALID);
149*7c478bd9Sstevel@tonic-gate 	}
150*7c478bd9Sstevel@tonic-gate 	qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
151*7c478bd9Sstevel@tonic-gate 	qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	if ((qp_attrp->qp_alloc_flags & IBT_QP_USES_SRQ) &&
154*7c478bd9Sstevel@tonic-gate 	    (qp_attrp->qp_srq_hdl != NULL))
155*7c478bd9Sstevel@tonic-gate 		qp_attrp->qp_ibc_srq_hdl =
156*7c478bd9Sstevel@tonic-gate 		    qp_attrp->qp_srq_hdl->srq_ibc_srq_hdl;
157*7c478bd9Sstevel@tonic-gate 	else
158*7c478bd9Sstevel@tonic-gate 		qp_attrp->qp_ibc_srq_hdl = NULL;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	/* Allocate Channel structure */
161*7c478bd9Sstevel@tonic-gate 	chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
164*7c478bd9Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp)(
165*7c478bd9Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), &chanp->ch_qp, type, qp_attrp,
166*7c478bd9Sstevel@tonic-gate 	    queue_sizes_p, qpn_p, &chanp->ch_qp.qp_ibc_qp_hdl);
167*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
168*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
169*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: "
170*7c478bd9Sstevel@tonic-gate 		    "Failed to allocate QP: %d", retval);
171*7c478bd9Sstevel@tonic-gate 		kmem_free(chanp, sizeof (*chanp));
172*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
173*7c478bd9Sstevel@tonic-gate 		return (retval);
174*7c478bd9Sstevel@tonic-gate 	}
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	/* Initialize the internal QP struct. */
177*7c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_type = qp_type;
178*7c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_hca = hca_hdl;
179*7c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
180*7c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
181*7c478bd9Sstevel@tonic-gate 	chanp->ch_current_state = IBT_STATE_RESET;
182*7c478bd9Sstevel@tonic-gate 	mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
183*7c478bd9Sstevel@tonic-gate 	cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hca_hdl->ha_mutex);
186*7c478bd9Sstevel@tonic-gate 	hca_hdl->ha_qp_cnt++;
187*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hca_hdl->ha_mutex);
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: SUCCESS: qp %p owned by '%s'",
190*7c478bd9Sstevel@tonic-gate 	    chanp, hca_hdl->ha_clnt_devp->clnt_name);
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 	*ibt_qp_p = chanp;
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	return (retval);
195*7c478bd9Sstevel@tonic-gate }
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate /*
199*7c478bd9Sstevel@tonic-gate  * Function:
200*7c478bd9Sstevel@tonic-gate  *	ibt_initialize_qp
201*7c478bd9Sstevel@tonic-gate  * Input:
202*7c478bd9Sstevel@tonic-gate  *	ibt_qp		The previously allocated IBT QP Handle.
203*7c478bd9Sstevel@tonic-gate  *	modify_attrp	Specifies the QP Modify attributes that to transition
204*7c478bd9Sstevel@tonic-gate  *			the QP to the RTS state for UDs (including special QPs)
205*7c478bd9Sstevel@tonic-gate  *			and INIT state for all other QPs.
206*7c478bd9Sstevel@tonic-gate  * Output:
207*7c478bd9Sstevel@tonic-gate  *	none.
208*7c478bd9Sstevel@tonic-gate  * Returns:
209*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
210*7c478bd9Sstevel@tonic-gate  * Description:
211*7c478bd9Sstevel@tonic-gate  *	Transition the QP to the RTS state for UDs (including special QPs)
212*7c478bd9Sstevel@tonic-gate  *	and INIT state for all other QPs.
213*7c478bd9Sstevel@tonic-gate  */
214*7c478bd9Sstevel@tonic-gate ibt_status_t
215*7c478bd9Sstevel@tonic-gate ibt_initialize_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_info_t *modify_attrp)
216*7c478bd9Sstevel@tonic-gate {
217*7c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
218*7c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		state;
219*7c478bd9Sstevel@tonic-gate 	ibc_hca_hdl_t		ibc_hca_hdl = IBTL_CHAN2CIHCA(ibt_qp);
220*7c478bd9Sstevel@tonic-gate 	ibc_qp_hdl_t		ibc_qp_hdl = IBTL_CHAN2CIQP(ibt_qp);
221*7c478bd9Sstevel@tonic-gate 	ibc_operations_t	*hca_ops_p = IBTL_CHAN2CIHCAOPS_P(ibt_qp);
222*7c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp(%p, %p)",
225*7c478bd9Sstevel@tonic-gate 	    ibt_qp, modify_attrp);
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	/*
228*7c478bd9Sstevel@tonic-gate 	 * Validate the QP Type from the channel with QP Type from the
229*7c478bd9Sstevel@tonic-gate 	 * modify attribute struct.
230*7c478bd9Sstevel@tonic-gate 	 */
231*7c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type != modify_attrp->qp_trans) {
232*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
233*7c478bd9Sstevel@tonic-gate 		    "QP Type mismatch: Chan QP Type<%d>, Modify QP Type<%d>",
234*7c478bd9Sstevel@tonic-gate 		    ibt_qp->ch_qp.qp_type, modify_attrp->qp_trans);
235*7c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
236*7c478bd9Sstevel@tonic-gate 	}
237*7c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_current_state != IBT_STATE_RESET) {
238*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
239*7c478bd9Sstevel@tonic-gate 		    "QP needs to be in RESET state: Chan QP State<%d>",
240*7c478bd9Sstevel@tonic-gate 		    ibt_qp->ch_current_state);
241*7c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
242*7c478bd9Sstevel@tonic-gate 	}
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	/*
245*7c478bd9Sstevel@tonic-gate 	 * Initialize the QP to the RTS state for UDs
246*7c478bd9Sstevel@tonic-gate 	 * and INIT state for all other QPs.
247*7c478bd9Sstevel@tonic-gate 	 */
248*7c478bd9Sstevel@tonic-gate 	switch (modify_attrp->qp_trans) {
249*7c478bd9Sstevel@tonic-gate 	case IBT_UD_SRV:
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 		/*
252*7c478bd9Sstevel@tonic-gate 		 * Bring the QP to the RTS state.
253*7c478bd9Sstevel@tonic-gate 		 */
254*7c478bd9Sstevel@tonic-gate 		state = IBT_STATE_RESET;
255*7c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
256*7c478bd9Sstevel@tonic-gate 		do {
257*7c478bd9Sstevel@tonic-gate 			modify_attrp->qp_current_state = state;
258*7c478bd9Sstevel@tonic-gate 			modify_flags = ibt_cep_next_state[state].modify_flags;
259*7c478bd9Sstevel@tonic-gate 			modify_attrp->qp_state = state =
260*7c478bd9Sstevel@tonic-gate 			    ibt_cep_next_state[state].next_state;
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp: "
263*7c478bd9Sstevel@tonic-gate 			    "modifying qp state to 0x%x", state);
264*7c478bd9Sstevel@tonic-gate 			status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl,
265*7c478bd9Sstevel@tonic-gate 			    ibc_qp_hdl, modify_flags, modify_attrp, NULL);
266*7c478bd9Sstevel@tonic-gate 		} while ((state != IBT_STATE_RTS) && (status == IBT_SUCCESS));
267*7c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_exit();
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 		if (status == IBT_SUCCESS) {
270*7c478bd9Sstevel@tonic-gate 			ibt_qp->ch_current_state = state;
271*7c478bd9Sstevel@tonic-gate 			ibt_qp->ch_transport.ud.ud_port_num =
272*7c478bd9Sstevel@tonic-gate 			    modify_attrp->qp_transport.ud.ud_port;
273*7c478bd9Sstevel@tonic-gate 			ibt_qp->ch_transport.ud.ud_qkey =
274*7c478bd9Sstevel@tonic-gate 			    modify_attrp->qp_transport.ud.ud_qkey;
275*7c478bd9Sstevel@tonic-gate 		}
276*7c478bd9Sstevel@tonic-gate 		break;
277*7c478bd9Sstevel@tonic-gate 	case IBT_UC_SRV:
278*7c478bd9Sstevel@tonic-gate 	case IBT_RD_SRV:
279*7c478bd9Sstevel@tonic-gate 	case IBT_RC_SRV:
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 		/*
282*7c478bd9Sstevel@tonic-gate 		 * Bring the QP to the INIT state.
283*7c478bd9Sstevel@tonic-gate 		 */
284*7c478bd9Sstevel@tonic-gate 		modify_attrp->qp_state = IBT_STATE_INIT;
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
287*7c478bd9Sstevel@tonic-gate 		status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl, ibc_qp_hdl,
288*7c478bd9Sstevel@tonic-gate 		    IBT_CEP_SET_RESET_INIT, modify_attrp, NULL);
289*7c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_exit();
290*7c478bd9Sstevel@tonic-gate 		if (status == IBT_SUCCESS)
291*7c478bd9Sstevel@tonic-gate 			ibt_qp->ch_current_state = IBT_STATE_INIT;
292*7c478bd9Sstevel@tonic-gate 		break;
293*7c478bd9Sstevel@tonic-gate 	default:
294*7c478bd9Sstevel@tonic-gate 		/* shouldn't happen ILLEGAL Type */
295*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: Illegal Type %d",
296*7c478bd9Sstevel@tonic-gate 		    modify_attrp->qp_trans);
297*7c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
298*7c478bd9Sstevel@tonic-gate 	} /* End switch */
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	return (status);
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate /*
305*7c478bd9Sstevel@tonic-gate  * Function:
306*7c478bd9Sstevel@tonic-gate  *	ibt_alloc_special_qp
307*7c478bd9Sstevel@tonic-gate  * Input:
308*7c478bd9Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
309*7c478bd9Sstevel@tonic-gate  *	type		Specifies the type of Special QP to be allocated.
310*7c478bd9Sstevel@tonic-gate  *	qp_attrp	Specifies the ibt_qp_alloc_attr_t that are needed to
311*7c478bd9Sstevel@tonic-gate  *			allocate a special QP.
312*7c478bd9Sstevel@tonic-gate  * Output:
313*7c478bd9Sstevel@tonic-gate  *	queue_sizes_p	Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
314*7c478bd9Sstevel@tonic-gate  *			WR SGL elements.
315*7c478bd9Sstevel@tonic-gate  *	qpn_p		Returned qpn of the allocated QP.
316*7c478bd9Sstevel@tonic-gate  *	ibt_qp_p	The ibt_qp_hdl_t of the allocated QP.
317*7c478bd9Sstevel@tonic-gate  * Returns:
318*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
319*7c478bd9Sstevel@tonic-gate  * Description:
320*7c478bd9Sstevel@tonic-gate  *	Allocate a special QP with specified attributes.
321*7c478bd9Sstevel@tonic-gate  */
322*7c478bd9Sstevel@tonic-gate ibt_status_t
323*7c478bd9Sstevel@tonic-gate ibt_alloc_special_qp(ibt_hca_hdl_t hca_hdl, uint8_t port, ibt_sqp_type_t type,
324*7c478bd9Sstevel@tonic-gate     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
325*7c478bd9Sstevel@tonic-gate     ibt_qp_hdl_t *ibt_qp_p)
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate 	ibt_qp_hdl_t	chanp;
328*7c478bd9Sstevel@tonic-gate 	ibt_status_t	retval;
329*7c478bd9Sstevel@tonic-gate 	ibt_tran_srv_t	sqp_type;
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_special_qp(%p, %d, %x, %p, %p, %p)",
332*7c478bd9Sstevel@tonic-gate 	    hca_hdl, port, type, qp_attrp, queue_sizes_p, ibt_qp_p);
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	switch (type) {
335*7c478bd9Sstevel@tonic-gate 	case IBT_SMI_SQP:
336*7c478bd9Sstevel@tonic-gate 	case IBT_GSI_SQP:
337*7c478bd9Sstevel@tonic-gate 		sqp_type = IBT_UD_SRV;
338*7c478bd9Sstevel@tonic-gate 		break;
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 	case IBT_RAWIP_SQP:
341*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw IP "
342*7c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
343*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
344*7c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	case IBT_RAWETHER_SQP:
347*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw Ethernet "
348*7c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
349*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
350*7c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	default:
353*7c478bd9Sstevel@tonic-gate 		/* Shouldn't happen */
354*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
355*7c478bd9Sstevel@tonic-gate 		    "Illegal Type 0x%x", type);
356*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
357*7c478bd9Sstevel@tonic-gate 		return (IBT_QP_SPECIAL_TYPE_INVALID);
358*7c478bd9Sstevel@tonic-gate 	}
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	/* convert the CQ handles for the CI */
361*7c478bd9Sstevel@tonic-gate 	qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
362*7c478bd9Sstevel@tonic-gate 	qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 	/* Allocate Channel structure */
365*7c478bd9Sstevel@tonic-gate 	chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
368*7c478bd9Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_special_qp)(
369*7c478bd9Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), port, &chanp->ch_qp, type, qp_attrp,
370*7c478bd9Sstevel@tonic-gate 	    queue_sizes_p, &chanp->ch_qp.qp_ibc_qp_hdl);
371*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
372*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
373*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
374*7c478bd9Sstevel@tonic-gate 		    "Failed to allocate Special QP: %d", retval);
375*7c478bd9Sstevel@tonic-gate 		kmem_free(chanp, sizeof (*chanp));
376*7c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
377*7c478bd9Sstevel@tonic-gate 		return (retval);
378*7c478bd9Sstevel@tonic-gate 	}
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	/* Initialize the internal QP struct. */
381*7c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_type = sqp_type;
382*7c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_hca = hca_hdl;
383*7c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
384*7c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
385*7c478bd9Sstevel@tonic-gate 	chanp->ch_current_state = IBT_STATE_RESET;
386*7c478bd9Sstevel@tonic-gate 	mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
387*7c478bd9Sstevel@tonic-gate 	cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hca_hdl->ha_mutex);
390*7c478bd9Sstevel@tonic-gate 	hca_hdl->ha_qp_cnt++;
391*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hca_hdl->ha_mutex);
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	*ibt_qp_p = chanp;
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate 	return (retval);
396*7c478bd9Sstevel@tonic-gate }
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate /*
400*7c478bd9Sstevel@tonic-gate  * Function:
401*7c478bd9Sstevel@tonic-gate  *	ibt_flush_qp
402*7c478bd9Sstevel@tonic-gate  * Input:
403*7c478bd9Sstevel@tonic-gate  *	ibtl_qp		Handle for QP that needs to be flushed.
404*7c478bd9Sstevel@tonic-gate  * Output:
405*7c478bd9Sstevel@tonic-gate  *	none.
406*7c478bd9Sstevel@tonic-gate  * Returns:
407*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
408*7c478bd9Sstevel@tonic-gate  *	IBT_QP_HDL_INVALID
409*7c478bd9Sstevel@tonic-gate  * Description:
410*7c478bd9Sstevel@tonic-gate  *	Put the QP into error state to flush out work requests.
411*7c478bd9Sstevel@tonic-gate  */
412*7c478bd9Sstevel@tonic-gate ibt_status_t
413*7c478bd9Sstevel@tonic-gate ibt_flush_qp(ibt_qp_hdl_t ibt_qp)
414*7c478bd9Sstevel@tonic-gate {
415*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
416*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_flush_qp(%p)", ibt_qp);
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
421*7c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
422*7c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_transport.rc.rc_free_flags &
423*7c478bd9Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
424*7c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
425*7c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp(%p): "
426*7c478bd9Sstevel@tonic-gate 			    "called with a connected RC QP", ibt_qp);
427*7c478bd9Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
428*7c478bd9Sstevel@tonic-gate 		}
429*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
430*7c478bd9Sstevel@tonic-gate 	}
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 	/*
435*7c478bd9Sstevel@tonic-gate 	 * Set the QP state to error to flush any uncompleted WRs.
436*7c478bd9Sstevel@tonic-gate 	 */
437*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_ERROR;
438*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = ibt_qp->ch_qp.qp_type;
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(ibt_qp, IBT_CEP_SET_STATE, &modify_attr, NULL);
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
443*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp: "
444*7c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 	return (retval);
447*7c478bd9Sstevel@tonic-gate }
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate /*
451*7c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_open()
452*7c478bd9Sstevel@tonic-gate  *
453*7c478bd9Sstevel@tonic-gate  *	Inform IBTL that the connection has been established on this
454*7c478bd9Sstevel@tonic-gate  *	channel so that a later call to ibtl_cm_chan_is_closed()
455*7c478bd9Sstevel@tonic-gate  *	will be required to free the QPN used by this channel.
456*7c478bd9Sstevel@tonic-gate  *
457*7c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
458*7c478bd9Sstevel@tonic-gate  */
459*7c478bd9Sstevel@tonic-gate void
460*7c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)
461*7c478bd9Sstevel@tonic-gate {
462*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_open(%p)", chan);
463*7c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
464*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
465*7c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_transport.rc.rc_free_flags == 0);
466*7c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTED;
467*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
468*7c478bd9Sstevel@tonic-gate }
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate /*
471*7c478bd9Sstevel@tonic-gate  * ibtl_cm_is_chan_closing()
472*7c478bd9Sstevel@tonic-gate  *
473*7c478bd9Sstevel@tonic-gate  *	Returns 1, if the connection that has been
474*7c478bd9Sstevel@tonic-gate  *	started for this channel has moved to TIMEWAIT
475*7c478bd9Sstevel@tonic-gate  *	If not, returns 0
476*7c478bd9Sstevel@tonic-gate  *
477*7c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
478*7c478bd9Sstevel@tonic-gate  */
479*7c478bd9Sstevel@tonic-gate int
480*7c478bd9Sstevel@tonic-gate ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)
481*7c478bd9Sstevel@tonic-gate {
482*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closing(%p)", chan);
483*7c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
484*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
485*7c478bd9Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSING) {
486*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
487*7c478bd9Sstevel@tonic-gate 		return (1);
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
490*7c478bd9Sstevel@tonic-gate 	return (0);
491*7c478bd9Sstevel@tonic-gate }
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate /*
494*7c478bd9Sstevel@tonic-gate  * ibtl_cm_is_chan_closed()
495*7c478bd9Sstevel@tonic-gate  *
496*7c478bd9Sstevel@tonic-gate  *	Returns 1, if the connection that has been
497*7c478bd9Sstevel@tonic-gate  *	started for this channel has completed TIMEWAIT
498*7c478bd9Sstevel@tonic-gate  *	If not, returns 0
499*7c478bd9Sstevel@tonic-gate  *
500*7c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
501*7c478bd9Sstevel@tonic-gate  */
502*7c478bd9Sstevel@tonic-gate int
503*7c478bd9Sstevel@tonic-gate ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)
504*7c478bd9Sstevel@tonic-gate {
505*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closed(%p)", chan);
506*7c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
507*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
508*7c478bd9Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSED) {
509*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
510*7c478bd9Sstevel@tonic-gate 		return (1);
511*7c478bd9Sstevel@tonic-gate 	}
512*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
513*7c478bd9Sstevel@tonic-gate 	return (0);
514*7c478bd9Sstevel@tonic-gate }
515*7c478bd9Sstevel@tonic-gate /*
516*7c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_closing()
517*7c478bd9Sstevel@tonic-gate  *
518*7c478bd9Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
519*7c478bd9Sstevel@tonic-gate  *	started for this channel so that the QP can be freed.
520*7c478bd9Sstevel@tonic-gate  *
521*7c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
522*7c478bd9Sstevel@tonic-gate  */
523*7c478bd9Sstevel@tonic-gate void
524*7c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)
525*7c478bd9Sstevel@tonic-gate {
526*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closing(%p)", chan);
527*7c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
528*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
529*7c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_transport.rc.rc_free_flags == IBTL_RC_QP_CONNECTED);
530*7c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSING;
531*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
532*7c478bd9Sstevel@tonic-gate }
533*7c478bd9Sstevel@tonic-gate /*
534*7c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_closed()
535*7c478bd9Sstevel@tonic-gate  *
536*7c478bd9Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
537*7c478bd9Sstevel@tonic-gate  *	reached for this channel so that the QPN can be reused.
538*7c478bd9Sstevel@tonic-gate  *
539*7c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
540*7c478bd9Sstevel@tonic-gate  */
541*7c478bd9Sstevel@tonic-gate void
542*7c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)
543*7c478bd9Sstevel@tonic-gate {
544*7c478bd9Sstevel@tonic-gate 	ibt_status_t status;
545*7c478bd9Sstevel@tonic-gate 	ibtl_hca_t *ibtl_hca = chan->ch_qp.qp_hca;
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closed(%p)", chan);
548*7c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
549*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
550*7c478bd9Sstevel@tonic-gate 	ASSERT((chan->ch_transport.rc.rc_free_flags &
551*7c478bd9Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
552*7c478bd9Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING));
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTED;
555*7c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSING;
556*7c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSED;
557*7c478bd9Sstevel@tonic-gate 
558*7c478bd9Sstevel@tonic-gate 	ibtl_cm_set_chan_private(chan, NULL);
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	if ((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_FREED) == 0) {
561*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
562*7c478bd9Sstevel@tonic-gate 		return;
563*7c478bd9Sstevel@tonic-gate 	}
564*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
565*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
566*7c478bd9Sstevel@tonic-gate 	if ((status = (IBTL_CHAN2CIHCAOPS_P(chan)->ibc_release_qpn)
567*7c478bd9Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(chan), chan->ch_transport.rc.rc_qpn_hdl)) ==
568*7c478bd9Sstevel@tonic-gate 	    IBT_SUCCESS) {
569*7c478bd9Sstevel@tonic-gate 		/* effectively, this is kmem_free(chan); */
570*7c478bd9Sstevel@tonic-gate 		ibtl_free_qp_async_check(&chan->ch_qp);
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 		/* decrement ha_qpn_cnt and check for close in progress */
573*7c478bd9Sstevel@tonic-gate 		ibtl_close_hca_check(ibtl_hca);
574*7c478bd9Sstevel@tonic-gate 	} else
575*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L1(ibtf_qp, "ibtl_cm_chan_is_closed: "
576*7c478bd9Sstevel@tonic-gate 		    "ibc_release_qpn failed: status = %d\n", status);
577*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
578*7c478bd9Sstevel@tonic-gate }
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate /*
581*7c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_reused()
582*7c478bd9Sstevel@tonic-gate  *
583*7c478bd9Sstevel@tonic-gate  *	Inform IBTL that the channel is going to be re-used
584*7c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
585*7c478bd9Sstevel@tonic-gate  */
586*7c478bd9Sstevel@tonic-gate void
587*7c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)
588*7c478bd9Sstevel@tonic-gate {
589*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_reused(%p)", chan);
590*7c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
591*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
592*7c478bd9Sstevel@tonic-gate 	ASSERT(((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CONNECTED) !=
593*7c478bd9Sstevel@tonic-gate 	    IBTL_RC_QP_CONNECTED));
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	/* channel is no longer in closed state, shall be re-used */
596*7c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSED;
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate }
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate /*
603*7c478bd9Sstevel@tonic-gate  * Function:	ibt_free_qp()
604*7c478bd9Sstevel@tonic-gate  *
605*7c478bd9Sstevel@tonic-gate  * Input:	ibt_qp		Handle for Channel(QP) that needs to be freed.
606*7c478bd9Sstevel@tonic-gate  *
607*7c478bd9Sstevel@tonic-gate  * Output:	NONE.
608*7c478bd9Sstevel@tonic-gate  *
609*7c478bd9Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
610*7c478bd9Sstevel@tonic-gate  *		IBT_QP_STATE_INVALID
611*7c478bd9Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
612*7c478bd9Sstevel@tonic-gate  *
613*7c478bd9Sstevel@tonic-gate  * Description:
614*7c478bd9Sstevel@tonic-gate  *		Free a previously allocated QP.
615*7c478bd9Sstevel@tonic-gate  */
616*7c478bd9Sstevel@tonic-gate ibt_status_t
617*7c478bd9Sstevel@tonic-gate ibt_free_qp(ibt_qp_hdl_t ibt_qp)
618*7c478bd9Sstevel@tonic-gate {
619*7c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
620*7c478bd9Sstevel@tonic-gate 	ibtl_hca_t		*ibtl_hca = ibt_qp->ch_qp.qp_hca;
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p)", ibt_qp);
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
625*7c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
626*7c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
627*7c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_transport.rc.rc_free_flags &
628*7c478bd9Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
629*7c478bd9Sstevel@tonic-gate 			if ((ibt_qp->ch_transport.rc.rc_free_flags &
630*7c478bd9Sstevel@tonic-gate 			    IBTL_RC_QP_CLOSING) == 0) {
631*7c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
632*7c478bd9Sstevel@tonic-gate 				    "need to call ibt_close_rc_channel");
633*7c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_free_qp_mutex);
634*7c478bd9Sstevel@tonic-gate 				ibtl_qp_flow_control_exit();
635*7c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
636*7c478bd9Sstevel@tonic-gate 			}
637*7c478bd9Sstevel@tonic-gate 			ibt_qp->ch_transport.rc.rc_free_flags |=
638*7c478bd9Sstevel@tonic-gate 			    IBTL_RC_QP_FREED;
639*7c478bd9Sstevel@tonic-gate 			status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
640*7c478bd9Sstevel@tonic-gate 			    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
641*7c478bd9Sstevel@tonic-gate 			    IBC_FREE_QP_ONLY,
642*7c478bd9Sstevel@tonic-gate 			    &ibt_qp->ch_transport.rc.rc_qpn_hdl);
643*7c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
644*7c478bd9Sstevel@tonic-gate 			ibtl_qp_flow_control_exit();
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 			if (status == IBT_SUCCESS) {
647*7c478bd9Sstevel@tonic-gate 				mutex_enter(&ibtl_clnt_list_mutex);
648*7c478bd9Sstevel@tonic-gate 				ibtl_hca->ha_qpn_cnt++;
649*7c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_clnt_list_mutex);
650*7c478bd9Sstevel@tonic-gate 				mutex_enter(&ibtl_hca->ha_mutex);
651*7c478bd9Sstevel@tonic-gate 				ibtl_hca->ha_qp_cnt--;
652*7c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_hca->ha_mutex);
653*7c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp(%p) - "
654*7c478bd9Sstevel@tonic-gate 				    "SUCCESS", ibt_qp);
655*7c478bd9Sstevel@tonic-gate 			} else
656*7c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
657*7c478bd9Sstevel@tonic-gate 				    "ibc_free_qp failed: status = %d", status);
658*7c478bd9Sstevel@tonic-gate 			return (status);
659*7c478bd9Sstevel@tonic-gate 		}
660*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
661*7c478bd9Sstevel@tonic-gate 	} else
662*7c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate 	status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
665*7c478bd9Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
666*7c478bd9Sstevel@tonic-gate 	    IBC_FREE_QP_AND_QPN, NULL);
667*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 	if (status == IBT_SUCCESS) {
670*7c478bd9Sstevel@tonic-gate 		/* effectively, this is kmem_free(ibt_qp); */
671*7c478bd9Sstevel@tonic-gate 		ibtl_free_qp_async_check(&ibt_qp->ch_qp);
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_hca->ha_mutex);
674*7c478bd9Sstevel@tonic-gate 		ibtl_hca->ha_qp_cnt--;
675*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_hca->ha_mutex);
676*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp(%p) - SUCCESS", ibt_qp);
677*7c478bd9Sstevel@tonic-gate 	} else {
678*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
679*7c478bd9Sstevel@tonic-gate 		    "ibc_free_qp failed with error %d", status);
680*7c478bd9Sstevel@tonic-gate 	}
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate 	return (status);
683*7c478bd9Sstevel@tonic-gate }
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate /* helper function for ibt_query_qp */
687*7c478bd9Sstevel@tonic-gate static void
688*7c478bd9Sstevel@tonic-gate ibtl_fillin_sgid(ibt_cep_path_t *pathp, ibtl_hca_devinfo_t *hca_devp)
689*7c478bd9Sstevel@tonic-gate {
690*7c478bd9Sstevel@tonic-gate 	uint8_t port;
691*7c478bd9Sstevel@tonic-gate 	uint32_t sgid_ix;
692*7c478bd9Sstevel@tonic-gate 	ib_gid_t *sgidp;
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	port = pathp->cep_hca_port_num;
695*7c478bd9Sstevel@tonic-gate 	sgid_ix = pathp->cep_adds_vect.av_sgid_ix;
696*7c478bd9Sstevel@tonic-gate 	if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
697*7c478bd9Sstevel@tonic-gate 	    sgid_ix >= IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
698*7c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_prefix = 0;
699*7c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_guid = 0;
700*7c478bd9Sstevel@tonic-gate 	} else {
701*7c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
702*7c478bd9Sstevel@tonic-gate 		sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
703*7c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid = sgidp[sgid_ix];
704*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
705*7c478bd9Sstevel@tonic-gate 	}
706*7c478bd9Sstevel@tonic-gate }
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate /*
710*7c478bd9Sstevel@tonic-gate  * Function:	ibt_query_qp
711*7c478bd9Sstevel@tonic-gate  *
712*7c478bd9Sstevel@tonic-gate  * Input:	ibt_qp 			- The IBT QP Handle.
713*7c478bd9Sstevel@tonic-gate  *
714*7c478bd9Sstevel@tonic-gate  * Output:	ibt_qp_query_attrp 	- Points to a ibt_qp_query_attr_t
715*7c478bd9Sstevel@tonic-gate  *					  that on return contains all the
716*7c478bd9Sstevel@tonic-gate  *					  attributes of the specified qp.
717*7c478bd9Sstevel@tonic-gate  *
718*7c478bd9Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
719*7c478bd9Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
720*7c478bd9Sstevel@tonic-gate  *
721*7c478bd9Sstevel@tonic-gate  * Description:
722*7c478bd9Sstevel@tonic-gate  *		Query QP attributes
723*7c478bd9Sstevel@tonic-gate  *
724*7c478bd9Sstevel@tonic-gate  */
725*7c478bd9Sstevel@tonic-gate ibt_status_t
726*7c478bd9Sstevel@tonic-gate ibt_query_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_query_attr_t *qp_query_attrp)
727*7c478bd9Sstevel@tonic-gate {
728*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
729*7c478bd9Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
730*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		*qp_infop;
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_qp(%p, %p)",
733*7c478bd9Sstevel@tonic-gate 	    ibt_qp, qp_query_attrp);
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
736*7c478bd9Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_query_qp(
737*7c478bd9Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), qp_query_attrp));
738*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
739*7c478bd9Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
740*7c478bd9Sstevel@tonic-gate 		ibt_qp->ch_current_state = qp_query_attrp->qp_info.qp_state;
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 		/* need to fill in sgid from port and sgid_ix for RC and UC */
743*7c478bd9Sstevel@tonic-gate 		hca_devp = ibt_qp->ch_qp.qp_hca->ha_hca_devp;
744*7c478bd9Sstevel@tonic-gate 		qp_infop = &qp_query_attrp->qp_info;
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate 		switch (qp_infop->qp_trans) {
747*7c478bd9Sstevel@tonic-gate 		case IBT_RC_SRV:
748*7c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_path,
749*7c478bd9Sstevel@tonic-gate 			    hca_devp);
750*7c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_alt_path,
751*7c478bd9Sstevel@tonic-gate 			    hca_devp);
752*7c478bd9Sstevel@tonic-gate 			break;
753*7c478bd9Sstevel@tonic-gate 		case IBT_UC_SRV:
754*7c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_path,
755*7c478bd9Sstevel@tonic-gate 			    hca_devp);
756*7c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_alt_path,
757*7c478bd9Sstevel@tonic-gate 			    hca_devp);
758*7c478bd9Sstevel@tonic-gate 			break;
759*7c478bd9Sstevel@tonic-gate 		}
760*7c478bd9Sstevel@tonic-gate 	} else {
761*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_qp: "
762*7c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
763*7c478bd9Sstevel@tonic-gate 	}
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 	return (retval);
766*7c478bd9Sstevel@tonic-gate }
767*7c478bd9Sstevel@tonic-gate 
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate /*
770*7c478bd9Sstevel@tonic-gate  * Function:
771*7c478bd9Sstevel@tonic-gate  *	ibt_modify_qp
772*7c478bd9Sstevel@tonic-gate  * Input:
773*7c478bd9Sstevel@tonic-gate  *	ibt_qp		The IBT QP Handle.
774*7c478bd9Sstevel@tonic-gate  *	flags		Specifies which attributes in ibt_qp_mod_attr_t
775*7c478bd9Sstevel@tonic-gate  *			are to be modified.
776*7c478bd9Sstevel@tonic-gate  *	qp_attrp	Points to an ibt_qp_mod_attr_t struct that contains all
777*7c478bd9Sstevel@tonic-gate  *			the attributes of the specified QP that a client is
778*7c478bd9Sstevel@tonic-gate  *			allowed to modify after a QP has been allocated
779*7c478bd9Sstevel@tonic-gate  * Output:
780*7c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual queue sizes.
781*7c478bd9Sstevel@tonic-gate  * Returns:
782*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
783*7c478bd9Sstevel@tonic-gate  * Description:
784*7c478bd9Sstevel@tonic-gate  *	Modify the attributes of an existing QP.
785*7c478bd9Sstevel@tonic-gate  */
786*7c478bd9Sstevel@tonic-gate ibt_status_t
787*7c478bd9Sstevel@tonic-gate ibt_modify_qp(ibt_qp_hdl_t ibt_qp, ibt_cep_modify_flags_t flags,
788*7c478bd9Sstevel@tonic-gate     ibt_qp_info_t *modify_attrp, ibt_queue_sizes_t *actual_sz)
789*7c478bd9Sstevel@tonic-gate {
790*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_qp(%p, %d, %p, %p)",
793*7c478bd9Sstevel@tonic-gate 	    ibt_qp, flags, modify_attrp, actual_sz);
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
796*7c478bd9Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_modify_qp)(
797*7c478bd9Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), flags,
798*7c478bd9Sstevel@tonic-gate 	    modify_attrp, actual_sz);
799*7c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
800*7c478bd9Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
801*7c478bd9Sstevel@tonic-gate 		ibt_qp->ch_current_state = modify_attrp->qp_state;
802*7c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_qp.qp_type == IBT_UD_SRV) {
803*7c478bd9Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_PORT | IBT_CEP_SET_RESET_INIT))
804*7c478bd9Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_port_num =
805*7c478bd9Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_port;
806*7c478bd9Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_QKEY | IBT_CEP_SET_RESET_INIT))
807*7c478bd9Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_qkey =
808*7c478bd9Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_qkey;
809*7c478bd9Sstevel@tonic-gate 		}
810*7c478bd9Sstevel@tonic-gate 	} else {
811*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_qp: failed on chan %p: %d",
812*7c478bd9Sstevel@tonic-gate 		    ibt_qp, retval);
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 		if (retval == IBT_CHAN_STATE_INVALID) {
815*7c478bd9Sstevel@tonic-gate 			/* That means our cache had invalid QP state value. */
816*7c478bd9Sstevel@tonic-gate 			ibt_qp_query_attr_t	qp_attr;
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate 			/* Query the channel (QP) */
819*7c478bd9Sstevel@tonic-gate 			if (ibt_query_qp(ibt_qp, &qp_attr) == IBT_SUCCESS)
820*7c478bd9Sstevel@tonic-gate 				ibt_qp->ch_current_state =
821*7c478bd9Sstevel@tonic-gate 				    qp_attr.qp_info.qp_state;
822*7c478bd9Sstevel@tonic-gate 		}
823*7c478bd9Sstevel@tonic-gate 	}
824*7c478bd9Sstevel@tonic-gate 	return (retval);
825*7c478bd9Sstevel@tonic-gate }
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate /*
829*7c478bd9Sstevel@tonic-gate  * Function:
830*7c478bd9Sstevel@tonic-gate  *	ibt_migrate_path
831*7c478bd9Sstevel@tonic-gate  * Input:
832*7c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
833*7c478bd9Sstevel@tonic-gate  * Output:
834*7c478bd9Sstevel@tonic-gate  *	none.
835*7c478bd9Sstevel@tonic-gate  * Returns:
836*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS on Success else appropriate error.
837*7c478bd9Sstevel@tonic-gate  * Description:
838*7c478bd9Sstevel@tonic-gate  *	Force the CI to use the alternate path. The alternate path becomes
839*7c478bd9Sstevel@tonic-gate  *	the primary path. A new alternate path should be loaded and enabled.
840*7c478bd9Sstevel@tonic-gate  *	Assumes that the given channel is in RTS/SQD state
841*7c478bd9Sstevel@tonic-gate  */
842*7c478bd9Sstevel@tonic-gate ibt_status_t
843*7c478bd9Sstevel@tonic-gate ibt_migrate_path(ibt_channel_hdl_t rc_chan)
844*7c478bd9Sstevel@tonic-gate {
845*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
846*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		qp_info;
847*7c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
848*7c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	cep_flags;
849*7c478bd9Sstevel@tonic-gate 	int			retries = 1;
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: channel %p", rc_chan);
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
854*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: "
855*7c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel");
856*7c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
857*7c478bd9Sstevel@tonic-gate 	}
858*7c478bd9Sstevel@tonic-gate 
859*7c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_current_state != IBT_STATE_RTS &&
860*7c478bd9Sstevel@tonic-gate 	    rc_chan->ch_current_state != IBT_STATE_SQD) {
861*7c478bd9Sstevel@tonic-gate 		if (ibt_query_qp(rc_chan, &qp_attr) == IBT_SUCCESS) {
862*7c478bd9Sstevel@tonic-gate 			/* ch_current_state is fixed by ibt_query_qp */
863*7c478bd9Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
864*7c478bd9Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
865*7c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
866*7c478bd9Sstevel@tonic-gate 			retries = 0;
867*7c478bd9Sstevel@tonic-gate 		} else /* query_qp should never really fail */
868*7c478bd9Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
869*7c478bd9Sstevel@tonic-gate 	}
870*7c478bd9Sstevel@tonic-gate 
871*7c478bd9Sstevel@tonic-gate retry:
872*7c478bd9Sstevel@tonic-gate 	/* Call modify_qp */
873*7c478bd9Sstevel@tonic-gate 	cep_flags = IBT_CEP_SET_MIG | IBT_CEP_SET_STATE;
874*7c478bd9Sstevel@tonic-gate 	qp_info.qp_state = rc_chan->ch_current_state;
875*7c478bd9Sstevel@tonic-gate 	qp_info.qp_current_state = rc_chan->ch_current_state;
876*7c478bd9Sstevel@tonic-gate 	qp_info.qp_trans = IBT_RC_SRV;
877*7c478bd9Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_mig_state = IBT_STATE_MIGRATED;
878*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, cep_flags, &qp_info, NULL);
879*7c478bd9Sstevel@tonic-gate 
880*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
881*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
882*7c478bd9Sstevel@tonic-gate 		    " ibt_modify_qp() returned = %d", retval);
883*7c478bd9Sstevel@tonic-gate 		if (rc_chan->ch_current_state != qp_info.qp_state &&
884*7c478bd9Sstevel@tonic-gate 		    --retries >= 0) {
885*7c478bd9Sstevel@tonic-gate 			/*
886*7c478bd9Sstevel@tonic-gate 			 * That means our cached 'state' was invalid.
887*7c478bd9Sstevel@tonic-gate 			 * We know ibt_modify_qp() fixed it up, so it
888*7c478bd9Sstevel@tonic-gate 			 * might be worth retrying.
889*7c478bd9Sstevel@tonic-gate 			 */
890*7c478bd9Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
891*7c478bd9Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
892*7c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
893*7c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
894*7c478bd9Sstevel@tonic-gate 			    " retrying after 'state' fixed");
895*7c478bd9Sstevel@tonic-gate 			goto retry;
896*7c478bd9Sstevel@tonic-gate 		}
897*7c478bd9Sstevel@tonic-gate 	}
898*7c478bd9Sstevel@tonic-gate 	return (retval);
899*7c478bd9Sstevel@tonic-gate }
900*7c478bd9Sstevel@tonic-gate 
901*7c478bd9Sstevel@tonic-gate 
902*7c478bd9Sstevel@tonic-gate /*
903*7c478bd9Sstevel@tonic-gate  * Function:
904*7c478bd9Sstevel@tonic-gate  *	ibt_set_qp_private
905*7c478bd9Sstevel@tonic-gate  * Input:
906*7c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
907*7c478bd9Sstevel@tonic-gate  *	clnt_private	The client private data.
908*7c478bd9Sstevel@tonic-gate  * Output:
909*7c478bd9Sstevel@tonic-gate  *	none.
910*7c478bd9Sstevel@tonic-gate  * Returns:
911*7c478bd9Sstevel@tonic-gate  *	none.
912*7c478bd9Sstevel@tonic-gate  * Description:
913*7c478bd9Sstevel@tonic-gate  *	Set the client private data.
914*7c478bd9Sstevel@tonic-gate  */
915*7c478bd9Sstevel@tonic-gate void
916*7c478bd9Sstevel@tonic-gate ibt_set_qp_private(ibt_qp_hdl_t ibt_qp, void *clnt_private)
917*7c478bd9Sstevel@tonic-gate {
918*7c478bd9Sstevel@tonic-gate 	ibt_qp->ch_clnt_private = clnt_private;
919*7c478bd9Sstevel@tonic-gate }
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 
922*7c478bd9Sstevel@tonic-gate /*
923*7c478bd9Sstevel@tonic-gate  * Function:
924*7c478bd9Sstevel@tonic-gate  *	ibt_get_qp_private
925*7c478bd9Sstevel@tonic-gate  * Input:
926*7c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
927*7c478bd9Sstevel@tonic-gate  * Output:
928*7c478bd9Sstevel@tonic-gate  *	none.
929*7c478bd9Sstevel@tonic-gate  * Returns:
930*7c478bd9Sstevel@tonic-gate  *	The client private data.
931*7c478bd9Sstevel@tonic-gate  * Description:
932*7c478bd9Sstevel@tonic-gate  *	Get the client private data.
933*7c478bd9Sstevel@tonic-gate  */
934*7c478bd9Sstevel@tonic-gate void *
935*7c478bd9Sstevel@tonic-gate ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)
936*7c478bd9Sstevel@tonic-gate {
937*7c478bd9Sstevel@tonic-gate 	return (ibt_qp->ch_clnt_private);
938*7c478bd9Sstevel@tonic-gate }
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate /*
942*7c478bd9Sstevel@tonic-gate  * Function:
943*7c478bd9Sstevel@tonic-gate  *	ibt_qp_to_hca_guid
944*7c478bd9Sstevel@tonic-gate  * Input:
945*7c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
946*7c478bd9Sstevel@tonic-gate  * Output:
947*7c478bd9Sstevel@tonic-gate  *	none.
948*7c478bd9Sstevel@tonic-gate  * Returns:
949*7c478bd9Sstevel@tonic-gate  *	hca_guid	Returned HCA GUID on which the specified QP is
950*7c478bd9Sstevel@tonic-gate  *			allocated. Valid if it is non-NULL on return.
951*7c478bd9Sstevel@tonic-gate  * Description:
952*7c478bd9Sstevel@tonic-gate  *	A helper function to retrieve HCA GUID for the specified QP.
953*7c478bd9Sstevel@tonic-gate  */
954*7c478bd9Sstevel@tonic-gate ib_guid_t
955*7c478bd9Sstevel@tonic-gate ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)
956*7c478bd9Sstevel@tonic-gate {
957*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_qp_to_hca_guid(%p)", ibt_qp);
958*7c478bd9Sstevel@tonic-gate 
959*7c478bd9Sstevel@tonic-gate 	return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ibt_qp)));
960*7c478bd9Sstevel@tonic-gate }
961*7c478bd9Sstevel@tonic-gate 
962*7c478bd9Sstevel@tonic-gate 
963*7c478bd9Sstevel@tonic-gate /*
964*7c478bd9Sstevel@tonic-gate  * Function:
965*7c478bd9Sstevel@tonic-gate  *	ibt_recover_ud_qp
966*7c478bd9Sstevel@tonic-gate  * Input:
967*7c478bd9Sstevel@tonic-gate  *	ibt_qp		An QP Handle which is in SQError state.
968*7c478bd9Sstevel@tonic-gate  * Output:
969*7c478bd9Sstevel@tonic-gate  *	none.
970*7c478bd9Sstevel@tonic-gate  * Returns:
971*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
972*7c478bd9Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
973*7c478bd9Sstevel@tonic-gate  *	IBT_QP_STATE_INVALID.
974*7c478bd9Sstevel@tonic-gate  * Description:
975*7c478bd9Sstevel@tonic-gate  *	Recover an UD QP which has transitioned to SQ Error state. The
976*7c478bd9Sstevel@tonic-gate  *	ibt_recover_ud_qp() transitions the QP from SQ Error state to
977*7c478bd9Sstevel@tonic-gate  *	Ready-To-Send QP state.
978*7c478bd9Sstevel@tonic-gate  *
979*7c478bd9Sstevel@tonic-gate  *	If a work request posted to a UD QP's send queue completes with an
980*7c478bd9Sstevel@tonic-gate  *	error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state.
981*7c478bd9Sstevel@tonic-gate  *	In order to reuse this QP, ibt_recover_ud_qp() can be used to recover
982*7c478bd9Sstevel@tonic-gate  *	the QP to a usable (Ready-to-Send) state.
983*7c478bd9Sstevel@tonic-gate  */
984*7c478bd9Sstevel@tonic-gate ibt_status_t
985*7c478bd9Sstevel@tonic-gate ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)
986*7c478bd9Sstevel@tonic-gate {
987*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recover_ud_qp(%p)", ibt_qp);
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate 	return (ibt_recover_ud_channel(IBTL_QP2CHAN(ibt_qp)));
990*7c478bd9Sstevel@tonic-gate }
991*7c478bd9Sstevel@tonic-gate 
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate /*
994*7c478bd9Sstevel@tonic-gate  * Function:
995*7c478bd9Sstevel@tonic-gate  *	ibt_recycle_ud
996*7c478bd9Sstevel@tonic-gate  * Input:
997*7c478bd9Sstevel@tonic-gate  *	ud_chan		The IBT UD QP Handle.
998*7c478bd9Sstevel@tonic-gate  *	various attributes
999*7c478bd9Sstevel@tonic-gate  *
1000*7c478bd9Sstevel@tonic-gate  * Output:
1001*7c478bd9Sstevel@tonic-gate  *	none
1002*7c478bd9Sstevel@tonic-gate  * Returns:
1003*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1004*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_SRV_TYPE_INVALID
1005*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
1006*7c478bd9Sstevel@tonic-gate  *
1007*7c478bd9Sstevel@tonic-gate  * Description:
1008*7c478bd9Sstevel@tonic-gate  *	Revert the UD QP back to a usable state.
1009*7c478bd9Sstevel@tonic-gate  */
1010*7c478bd9Sstevel@tonic-gate ibt_status_t
1011*7c478bd9Sstevel@tonic-gate ibt_recycle_ud(ibt_channel_hdl_t ud_chan, uint8_t hca_port_num,
1012*7c478bd9Sstevel@tonic-gate     uint16_t pkey_ix, ib_qkey_t qkey)
1013*7c478bd9Sstevel@tonic-gate {
1014*7c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
1015*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1016*7c478bd9Sstevel@tonic-gate 
1017*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recycle_ud(%p, %d, %x, %x): ",
1018*7c478bd9Sstevel@tonic-gate 	    ud_chan, hca_port_num, pkey_ix, qkey);
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
1021*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1022*7c478bd9Sstevel@tonic-gate 		    "chan %p is not a UD channel", ud_chan);
1023*7c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
1024*7c478bd9Sstevel@tonic-gate 	}
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(ud_chan, &qp_attr);
1027*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1028*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1029*7c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed on chan %p: %d", ud_chan, retval);
1030*7c478bd9Sstevel@tonic-gate 		return (retval);
1031*7c478bd9Sstevel@tonic-gate 	}
1032*7c478bd9Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR) {
1033*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1034*7c478bd9Sstevel@tonic-gate 		    "chan %p is in state %d (not in ERROR state)",
1035*7c478bd9Sstevel@tonic-gate 		    ud_chan, qp_attr.qp_info.qp_state);
1036*7c478bd9Sstevel@tonic-gate 		ud_chan->ch_current_state = qp_attr.qp_info.qp_state;
1037*7c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
1038*7c478bd9Sstevel@tonic-gate 	}
1039*7c478bd9Sstevel@tonic-gate 
1040*7c478bd9Sstevel@tonic-gate 	/* transition the QP from ERROR to RESET */
1041*7c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_state = IBT_STATE_RESET;
1042*7c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_trans = ud_chan->ch_qp.qp_type;
1043*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &qp_attr.qp_info,
1044*7c478bd9Sstevel@tonic-gate 	    NULL);
1045*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1046*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1047*7c478bd9Sstevel@tonic-gate 		    "ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d",
1048*7c478bd9Sstevel@tonic-gate 		    ud_chan, retval);
1049*7c478bd9Sstevel@tonic-gate 		return (retval);
1050*7c478bd9Sstevel@tonic-gate 	}
1051*7c478bd9Sstevel@tonic-gate 	ud_chan->ch_current_state = IBT_STATE_RESET;
1052*7c478bd9Sstevel@tonic-gate 
1053*7c478bd9Sstevel@tonic-gate 	/* transition the QP back to RTS */
1054*7c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_port = hca_port_num;
1055*7c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_qkey = qkey;
1056*7c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_pkey_ix = pkey_ix;
1057*7c478bd9Sstevel@tonic-gate 	retval = ibt_initialize_qp(ud_chan, &qp_attr.qp_info);
1058*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1059*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
1060*7c478bd9Sstevel@tonic-gate 		    "ibt_initialize_qp failed on chan %p: %d", ud_chan, retval);
1061*7c478bd9Sstevel@tonic-gate 		/* the man page says the QP should be left in ERROR state */
1062*7c478bd9Sstevel@tonic-gate 		(void) ibt_flush_qp(ud_chan);
1063*7c478bd9Sstevel@tonic-gate 	}
1064*7c478bd9Sstevel@tonic-gate 	return (retval);
1065*7c478bd9Sstevel@tonic-gate }
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate /*
1068*7c478bd9Sstevel@tonic-gate  * Function:
1069*7c478bd9Sstevel@tonic-gate  *	ibt_pause_sendq
1070*7c478bd9Sstevel@tonic-gate  * Input:
1071*7c478bd9Sstevel@tonic-gate  *	chan		The IBT QP Handle.
1072*7c478bd9Sstevel@tonic-gate  *	modify_flags	IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT
1073*7c478bd9Sstevel@tonic-gate  *
1074*7c478bd9Sstevel@tonic-gate  * Output:
1075*7c478bd9Sstevel@tonic-gate  *	none.
1076*7c478bd9Sstevel@tonic-gate  * Returns:
1077*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1078*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
1079*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
1080*7c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
1081*7c478bd9Sstevel@tonic-gate  *
1082*7c478bd9Sstevel@tonic-gate  * Description:
1083*7c478bd9Sstevel@tonic-gate  *	Place the send queue of the specified channel into the send queue
1084*7c478bd9Sstevel@tonic-gate  *	drained (SQD) state.
1085*7c478bd9Sstevel@tonic-gate  *
1086*7c478bd9Sstevel@tonic-gate  */
1087*7c478bd9Sstevel@tonic-gate ibt_status_t
1088*7c478bd9Sstevel@tonic-gate ibt_pause_sendq(ibt_channel_hdl_t chan, ibt_cep_modify_flags_t modify_flags)
1089*7c478bd9Sstevel@tonic-gate {
1090*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
1091*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1092*7c478bd9Sstevel@tonic-gate 
1093*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_pause_sendq(%p, %x)", chan, modify_flags);
1094*7c478bd9Sstevel@tonic-gate 
1095*7c478bd9Sstevel@tonic-gate 	modify_flags &= IBT_CEP_SET_SQD_EVENT;	/* ignore other bits */
1096*7c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
1097*7c478bd9Sstevel@tonic-gate 
1098*7c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
1099*7c478bd9Sstevel@tonic-gate 	/*
1100*7c478bd9Sstevel@tonic-gate 	 * Set the QP state to SQD.
1101*7c478bd9Sstevel@tonic-gate 	 */
1102*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
1103*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
1104*7c478bd9Sstevel@tonic-gate 
1105*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1106*7c478bd9Sstevel@tonic-gate 
1107*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1108*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_pause_sendq: "
1109*7c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
1110*7c478bd9Sstevel@tonic-gate 	}
1111*7c478bd9Sstevel@tonic-gate 	return (retval);
1112*7c478bd9Sstevel@tonic-gate }
1113*7c478bd9Sstevel@tonic-gate 
1114*7c478bd9Sstevel@tonic-gate 
1115*7c478bd9Sstevel@tonic-gate /*
1116*7c478bd9Sstevel@tonic-gate  * Function:
1117*7c478bd9Sstevel@tonic-gate  *	ibt_unpause_sendq
1118*7c478bd9Sstevel@tonic-gate  * Input:
1119*7c478bd9Sstevel@tonic-gate  *	chan	The IBT Channel Handle.
1120*7c478bd9Sstevel@tonic-gate  * Output:
1121*7c478bd9Sstevel@tonic-gate  *	none.
1122*7c478bd9Sstevel@tonic-gate  * Returns:
1123*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1124*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
1125*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
1126*7c478bd9Sstevel@tonic-gate  * Description:
1127*7c478bd9Sstevel@tonic-gate  *	Un-pauses the previously paused channel. This call will transition the
1128*7c478bd9Sstevel@tonic-gate  *	QP from SQD to RTS state.
1129*7c478bd9Sstevel@tonic-gate  */
1130*7c478bd9Sstevel@tonic-gate ibt_status_t
1131*7c478bd9Sstevel@tonic-gate ibt_unpause_sendq(ibt_channel_hdl_t chan)
1132*7c478bd9Sstevel@tonic-gate {
1133*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
1134*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1135*7c478bd9Sstevel@tonic-gate 
1136*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_unpause_sendq(%p)", chan);
1137*7c478bd9Sstevel@tonic-gate 
1138*7c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
1139*7c478bd9Sstevel@tonic-gate 
1140*7c478bd9Sstevel@tonic-gate 	/*
1141*7c478bd9Sstevel@tonic-gate 	 * Set the QP state to RTS.
1142*7c478bd9Sstevel@tonic-gate 	 */
1143*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_current_state = IBT_STATE_SQD;
1144*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_RTS;
1145*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
1146*7c478bd9Sstevel@tonic-gate 
1147*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
1148*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1149*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_unpause_sendq: "
1150*7c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
1151*7c478bd9Sstevel@tonic-gate 	}
1152*7c478bd9Sstevel@tonic-gate 	return (retval);
1153*7c478bd9Sstevel@tonic-gate }
1154*7c478bd9Sstevel@tonic-gate 
1155*7c478bd9Sstevel@tonic-gate 
1156*7c478bd9Sstevel@tonic-gate /*
1157*7c478bd9Sstevel@tonic-gate  * Function:
1158*7c478bd9Sstevel@tonic-gate  *	ibt_resize_queues
1159*7c478bd9Sstevel@tonic-gate  * Input:
1160*7c478bd9Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
1161*7c478bd9Sstevel@tonic-gate  *	flags		QP Flags
1162*7c478bd9Sstevel@tonic-gate  *				IBT_SEND_Q
1163*7c478bd9Sstevel@tonic-gate  *				IBT_RECV_Q
1164*7c478bd9Sstevel@tonic-gate  *	request_sz	Requested new sizes.
1165*7c478bd9Sstevel@tonic-gate  * Output:
1166*7c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
1167*7c478bd9Sstevel@tonic-gate  * Returns:
1168*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1169*7c478bd9Sstevel@tonic-gate  * Description:
1170*7c478bd9Sstevel@tonic-gate  *	Resize the SendQ/RecvQ sizes of a channel. Can only be called on
1171*7c478bd9Sstevel@tonic-gate  *	a previously opened channel.
1172*7c478bd9Sstevel@tonic-gate  */
1173*7c478bd9Sstevel@tonic-gate ibt_status_t
1174*7c478bd9Sstevel@tonic-gate ibt_resize_queues(ibt_channel_hdl_t chan, ibt_qflags_t flags,
1175*7c478bd9Sstevel@tonic-gate     ibt_queue_sizes_t *request_sz, ibt_queue_sizes_t *actual_sz)
1176*7c478bd9Sstevel@tonic-gate {
1177*7c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags = IBT_CEP_SET_STATE;
1178*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
1179*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1180*7c478bd9Sstevel@tonic-gate 
1181*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_resize_queues(%p, 0x%X, %p, %p)",
1182*7c478bd9Sstevel@tonic-gate 	    chan, flags, request_sz, actual_sz);
1183*7c478bd9Sstevel@tonic-gate 
1184*7c478bd9Sstevel@tonic-gate 	if ((flags & (IBT_SEND_Q | IBT_RECV_Q)) == 0)  {
1185*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
1186*7c478bd9Sstevel@tonic-gate 		    "Flags <0x%X> not set", flags);
1187*7c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
1188*7c478bd9Sstevel@tonic-gate 	}
1189*7c478bd9Sstevel@tonic-gate 
1190*7c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
1191*7c478bd9Sstevel@tonic-gate 
1192*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_current_state = chan->ch_current_state;
1193*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
1194*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = chan->ch_current_state;
1195*7c478bd9Sstevel@tonic-gate 
1196*7c478bd9Sstevel@tonic-gate 	if (flags & IBT_SEND_Q) {
1197*7c478bd9Sstevel@tonic-gate 		modify_attr.qp_sq_sz = request_sz->qs_sq;
1198*7c478bd9Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_SQ_SIZE;
1199*7c478bd9Sstevel@tonic-gate 	}
1200*7c478bd9Sstevel@tonic-gate 
1201*7c478bd9Sstevel@tonic-gate 	if (flags & IBT_RECV_Q) {
1202*7c478bd9Sstevel@tonic-gate 		modify_attr.qp_rq_sz = request_sz->qs_rq;
1203*7c478bd9Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_RQ_SIZE;
1204*7c478bd9Sstevel@tonic-gate 	}
1205*7c478bd9Sstevel@tonic-gate 
1206*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, actual_sz);
1207*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1208*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
1209*7c478bd9Sstevel@tonic-gate 		    "failed on QP %p: %d", chan, retval);
1210*7c478bd9Sstevel@tonic-gate 	}
1211*7c478bd9Sstevel@tonic-gate 
1212*7c478bd9Sstevel@tonic-gate 	return (retval);
1213*7c478bd9Sstevel@tonic-gate }
1214*7c478bd9Sstevel@tonic-gate 
1215*7c478bd9Sstevel@tonic-gate 
1216*7c478bd9Sstevel@tonic-gate /*
1217*7c478bd9Sstevel@tonic-gate  * Function:
1218*7c478bd9Sstevel@tonic-gate  *	ibt_query_queues
1219*7c478bd9Sstevel@tonic-gate  * Input:
1220*7c478bd9Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
1221*7c478bd9Sstevel@tonic-gate  * Output:
1222*7c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
1223*7c478bd9Sstevel@tonic-gate  * Returns:
1224*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1225*7c478bd9Sstevel@tonic-gate  * Description:
1226*7c478bd9Sstevel@tonic-gate  *	Query the SendQ/RecvQ sizes of a channel.
1227*7c478bd9Sstevel@tonic-gate  */
1228*7c478bd9Sstevel@tonic-gate ibt_status_t
1229*7c478bd9Sstevel@tonic-gate ibt_query_queues(ibt_channel_hdl_t chan, ibt_queue_sizes_t *actual_sz)
1230*7c478bd9Sstevel@tonic-gate {
1231*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1232*7c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_query_attr;
1233*7c478bd9Sstevel@tonic-gate 
1234*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_queues(%p)", chan);
1235*7c478bd9Sstevel@tonic-gate 
1236*7c478bd9Sstevel@tonic-gate 	/* Perform Query QP and retrieve QP sizes. */
1237*7c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(chan, &qp_query_attr);
1238*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1239*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_queues: "
1240*7c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed: qp %p: %d", chan, retval);
1241*7c478bd9Sstevel@tonic-gate 		return (retval);
1242*7c478bd9Sstevel@tonic-gate 	}
1243*7c478bd9Sstevel@tonic-gate 
1244*7c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
1245*7c478bd9Sstevel@tonic-gate 	    actual_sz->qs_sq))
1246*7c478bd9Sstevel@tonic-gate 	actual_sz->qs_sq = qp_query_attr.qp_info.qp_sq_sz;
1247*7c478bd9Sstevel@tonic-gate 	actual_sz->qs_rq = qp_query_attr.qp_info.qp_rq_sz;
1248*7c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
1249*7c478bd9Sstevel@tonic-gate 	    actual_sz->qs_sq))
1250*7c478bd9Sstevel@tonic-gate 	chan->ch_current_state = qp_query_attr.qp_info.qp_state;
1251*7c478bd9Sstevel@tonic-gate 
1252*7c478bd9Sstevel@tonic-gate 	return (retval);
1253*7c478bd9Sstevel@tonic-gate }
1254*7c478bd9Sstevel@tonic-gate 
1255*7c478bd9Sstevel@tonic-gate 
1256*7c478bd9Sstevel@tonic-gate /*
1257*7c478bd9Sstevel@tonic-gate  * Function:
1258*7c478bd9Sstevel@tonic-gate  *	ibt_modify_rdma
1259*7c478bd9Sstevel@tonic-gate  * Input:
1260*7c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated channel handle.
1261*7c478bd9Sstevel@tonic-gate  *
1262*7c478bd9Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
1263*7c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_R	Enable/Disable RDMA RD
1264*7c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_W	Enable/Disable RDMA WR
1265*7c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_ATOMIC	Enable/Disable Atomics
1266*7c478bd9Sstevel@tonic-gate  *
1267*7c478bd9Sstevel@tonic-gate  *	flags		Channel End Point (CEP) Disable Flags (0 => enable).
1268*7c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_RD	Disable incoming RDMA RD's
1269*7c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_WR	Disable incoming RDMA WR's
1270*7c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_ATOMIC	Disable incoming Atomics.
1271*7c478bd9Sstevel@tonic-gate  * Output:
1272*7c478bd9Sstevel@tonic-gate  *	none.
1273*7c478bd9Sstevel@tonic-gate  * Returns:
1274*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1275*7c478bd9Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
1276*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
1277*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_ATOMICS_NOT_SUPPORTED
1278*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
1279*7c478bd9Sstevel@tonic-gate  * Description:
1280*7c478bd9Sstevel@tonic-gate  *	Enable/disable RDMA operations. To enable an operation clear the
1281*7c478bd9Sstevel@tonic-gate  *	"disable" flag. Can call this function when the channel is in
1282*7c478bd9Sstevel@tonic-gate  *	INIT, RTS or SQD states. If called in any other state
1283*7c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID is returned. When the operation completes the
1284*7c478bd9Sstevel@tonic-gate  *	channel state is left unchanged.
1285*7c478bd9Sstevel@tonic-gate  */
1286*7c478bd9Sstevel@tonic-gate ibt_status_t
1287*7c478bd9Sstevel@tonic-gate ibt_modify_rdma(ibt_channel_hdl_t rc_chan,
1288*7c478bd9Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, ibt_cep_flags_t flags)
1289*7c478bd9Sstevel@tonic-gate {
1290*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1291*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
1292*7c478bd9Sstevel@tonic-gate 
1293*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_rdma(%p, 0x%x, 0x%x)",
1294*7c478bd9Sstevel@tonic-gate 	    rc_chan, modify_flags, flags);
1295*7c478bd9Sstevel@tonic-gate 
1296*7c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
1297*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
1298*7c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1299*7c478bd9Sstevel@tonic-gate 		    rc_chan->ch_qp.qp_type);
1300*7c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
1301*7c478bd9Sstevel@tonic-gate 	}
1302*7c478bd9Sstevel@tonic-gate 
1303*7c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
1304*7c478bd9Sstevel@tonic-gate 
1305*7c478bd9Sstevel@tonic-gate 	/*
1306*7c478bd9Sstevel@tonic-gate 	 * Can only call this function when the channel in INIT, RTS or SQD
1307*7c478bd9Sstevel@tonic-gate 	 * states.
1308*7c478bd9Sstevel@tonic-gate 	 */
1309*7c478bd9Sstevel@tonic-gate 	if ((rc_chan->ch_current_state != IBT_STATE_INIT) &&
1310*7c478bd9Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_RTS) &&
1311*7c478bd9Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_SQD)) {
1312*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: Invalid Channel "
1313*7c478bd9Sstevel@tonic-gate 		    "state: 0x%X", rc_chan->ch_current_state);
1314*7c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
1315*7c478bd9Sstevel@tonic-gate 	}
1316*7c478bd9Sstevel@tonic-gate 
1317*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = modify_attr.qp_current_state =
1318*7c478bd9Sstevel@tonic-gate 	    rc_chan->ch_current_state;
1319*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = rc_chan->ch_qp.qp_type;
1320*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_flags = flags;
1321*7c478bd9Sstevel@tonic-gate 
1322*7c478bd9Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
1323*7c478bd9Sstevel@tonic-gate 	    IBT_CEP_SET_ATOMIC);
1324*7c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
1325*7c478bd9Sstevel@tonic-gate 
1326*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, modify_flags, &modify_attr, NULL);
1327*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1328*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
1329*7c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", rc_chan, retval);
1330*7c478bd9Sstevel@tonic-gate 	}
1331*7c478bd9Sstevel@tonic-gate 	return (retval);
1332*7c478bd9Sstevel@tonic-gate }
1333*7c478bd9Sstevel@tonic-gate 
1334*7c478bd9Sstevel@tonic-gate 
1335*7c478bd9Sstevel@tonic-gate /*
1336*7c478bd9Sstevel@tonic-gate  * Function:
1337*7c478bd9Sstevel@tonic-gate  *	ibt_set_rdma_resource
1338*7c478bd9Sstevel@tonic-gate  * Input:
1339*7c478bd9Sstevel@tonic-gate  *	chan		A previously allocated RC channel handle.
1340*7c478bd9Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
1341*7c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_OUT	Initiator depth (rdma_ra_out)
1342*7c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_IN	Responder Resources
1343*7c478bd9Sstevel@tonic-gate  *						(rdma_ra_in)
1344*7c478bd9Sstevel@tonic-gate  *	rdma_ra_out	Outgoing RDMA Reads/Atomics
1345*7c478bd9Sstevel@tonic-gate  *	rdma_ra_in	Incoming RDMA Reads/Atomics
1346*7c478bd9Sstevel@tonic-gate  * Output:
1347*7c478bd9Sstevel@tonic-gate  *	none.
1348*7c478bd9Sstevel@tonic-gate  * Returns:
1349*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1350*7c478bd9Sstevel@tonic-gate  * Description:
1351*7c478bd9Sstevel@tonic-gate  *	Change the number of resources to be used for incoming and outgoing
1352*7c478bd9Sstevel@tonic-gate  *	RDMA reads & Atomics. Can only be called on a previously opened
1353*7c478bd9Sstevel@tonic-gate  *	RC channel.  Can only be called on a paused channel, and this will
1354*7c478bd9Sstevel@tonic-gate  *	un-pause that channel.
1355*7c478bd9Sstevel@tonic-gate  */
1356*7c478bd9Sstevel@tonic-gate ibt_status_t
1357*7c478bd9Sstevel@tonic-gate ibt_set_rdma_resource(ibt_channel_hdl_t chan,
1358*7c478bd9Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, uint8_t rdma_ra_out,
1359*7c478bd9Sstevel@tonic-gate     uint8_t resp_rdma_ra_out)
1360*7c478bd9Sstevel@tonic-gate {
1361*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
1362*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1363*7c478bd9Sstevel@tonic-gate 
1364*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_set_rdma_resource(%p, 0x%x, %d, %d)",
1365*7c478bd9Sstevel@tonic-gate 	    chan, modify_flags, rdma_ra_out, resp_rdma_ra_out);
1366*7c478bd9Sstevel@tonic-gate 
1367*7c478bd9Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
1368*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
1369*7c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1370*7c478bd9Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
1371*7c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
1372*7c478bd9Sstevel@tonic-gate 	}
1373*7c478bd9Sstevel@tonic-gate 
1374*7c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
1375*7c478bd9Sstevel@tonic-gate 
1376*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
1377*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
1378*7c478bd9Sstevel@tonic-gate 
1379*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_out = rdma_ra_out;
1380*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_in = resp_rdma_ra_out;
1381*7c478bd9Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN);
1382*7c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
1383*7c478bd9Sstevel@tonic-gate 
1384*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1385*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1386*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
1387*7c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
1388*7c478bd9Sstevel@tonic-gate 	}
1389*7c478bd9Sstevel@tonic-gate 	return (retval);
1390*7c478bd9Sstevel@tonic-gate }
1391*7c478bd9Sstevel@tonic-gate 
1392*7c478bd9Sstevel@tonic-gate 
1393*7c478bd9Sstevel@tonic-gate /*
1394*7c478bd9Sstevel@tonic-gate  * Function:
1395*7c478bd9Sstevel@tonic-gate  *	ibt_change_port
1396*7c478bd9Sstevel@tonic-gate  * Input:
1397*7c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
1398*7c478bd9Sstevel@tonic-gate  *	port_num	New HCA port.
1399*7c478bd9Sstevel@tonic-gate  * Output:
1400*7c478bd9Sstevel@tonic-gate  *	none.
1401*7c478bd9Sstevel@tonic-gate  * Returns:
1402*7c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1403*7c478bd9Sstevel@tonic-gate  * Description:
1404*7c478bd9Sstevel@tonic-gate  *	Change the primary physical port of a channel. (This is done only if
1405*7c478bd9Sstevel@tonic-gate  *	HCA supports this capability).
1406*7c478bd9Sstevel@tonic-gate  */
1407*7c478bd9Sstevel@tonic-gate ibt_status_t
1408*7c478bd9Sstevel@tonic-gate ibt_change_port(ibt_channel_hdl_t chan, uint8_t port_num)
1409*7c478bd9Sstevel@tonic-gate {
1410*7c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
1411*7c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
1412*7c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1413*7c478bd9Sstevel@tonic-gate 
1414*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_change_port(%p, %d)", chan, port_num);
1415*7c478bd9Sstevel@tonic-gate 
1416*7c478bd9Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
1417*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
1418*7c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
1419*7c478bd9Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
1420*7c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
1421*7c478bd9Sstevel@tonic-gate 	}
1422*7c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
1423*7c478bd9Sstevel@tonic-gate 
1424*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
1425*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
1426*7c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = port_num;
1427*7c478bd9Sstevel@tonic-gate 
1428*7c478bd9Sstevel@tonic-gate 	modify_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
1429*7c478bd9Sstevel@tonic-gate 
1430*7c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
1431*7c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1432*7c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
1433*7c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
1434*7c478bd9Sstevel@tonic-gate 	}
1435*7c478bd9Sstevel@tonic-gate 	return (retval);
1436*7c478bd9Sstevel@tonic-gate }
1437*7c478bd9Sstevel@tonic-gate 
1438*7c478bd9Sstevel@tonic-gate 
1439*7c478bd9Sstevel@tonic-gate void
1440*7c478bd9Sstevel@tonic-gate ibtl_init_cep_states(void)
1441*7c478bd9Sstevel@tonic-gate {
1442*7c478bd9Sstevel@tonic-gate 	int	index;
1443*7c478bd9Sstevel@tonic-gate 	int	ibt_nstate_inits;
1444*7c478bd9Sstevel@tonic-gate 
1445*7c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_init_cep_states()");
1446*7c478bd9Sstevel@tonic-gate 
1447*7c478bd9Sstevel@tonic-gate 	ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) /
1448*7c478bd9Sstevel@tonic-gate 	    sizeof (ibt_cep_next_state_inits[0]);
1449*7c478bd9Sstevel@tonic-gate 
1450*7c478bd9Sstevel@tonic-gate 	/*
1451*7c478bd9Sstevel@tonic-gate 	 * Initialize CEP next state table, using an indirect lookup table so
1452*7c478bd9Sstevel@tonic-gate 	 * that this code isn't dependent on the ibt_cep_state_t enum values.
1453*7c478bd9Sstevel@tonic-gate 	 */
1454*7c478bd9Sstevel@tonic-gate 	for (index = 0; index < ibt_nstate_inits; index++) {
1455*7c478bd9Sstevel@tonic-gate 		ibt_cep_state_t	state;
1456*7c478bd9Sstevel@tonic-gate 
1457*7c478bd9Sstevel@tonic-gate 		state = ibt_cep_next_state_inits[index].current_state;
1458*7c478bd9Sstevel@tonic-gate 
1459*7c478bd9Sstevel@tonic-gate 		ibt_cep_next_state[state].next_state =
1460*7c478bd9Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].next_state;
1461*7c478bd9Sstevel@tonic-gate 
1462*7c478bd9Sstevel@tonic-gate 		ibt_cep_next_state[state].modify_flags =
1463*7c478bd9Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].modify_flags;
1464*7c478bd9Sstevel@tonic-gate 	}
1465*7c478bd9Sstevel@tonic-gate }
1466