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