xref: /onnv-gate/usr/src/uts/common/io/ib/ibtl/ibtl_qp.c (revision 12965:b65a8427f8fe)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53241Shiremath  * Common Development and Distribution License (the "License").
63241Shiremath  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
2212064SShantkumar.Hiremath@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
260Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_cm.h>
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * ibtl_qp.c
300Sstevel@tonic-gate  *	These routines implement (most of) the verbs related to
310Sstevel@tonic-gate  *	Queue Pairs.
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate /* Globals. */
350Sstevel@tonic-gate static char ibtf_qp[] = "ibtl";
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /* This table indirectly initializes the ibt_cep_next_state[] table. */
380Sstevel@tonic-gate typedef struct ibt_cep_next_state_s {
390Sstevel@tonic-gate 	ibt_cep_state_t		next_state;
400Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
410Sstevel@tonic-gate } ibt_cep_next_state_t;
420Sstevel@tonic-gate 
430Sstevel@tonic-gate struct	{
440Sstevel@tonic-gate 	ibt_cep_state_t		current_state;
450Sstevel@tonic-gate 	ibt_cep_state_t		next_state;
460Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
470Sstevel@tonic-gate } ibt_cep_next_state_inits[] = {
480Sstevel@tonic-gate 	{ IBT_STATE_RESET, IBT_STATE_INIT, IBT_CEP_SET_RESET_INIT},
490Sstevel@tonic-gate 	{ IBT_STATE_INIT, IBT_STATE_RTR, IBT_CEP_SET_INIT_RTR},
500Sstevel@tonic-gate 	{ IBT_STATE_RTR, IBT_STATE_RTS, IBT_CEP_SET_RTR_RTS}
510Sstevel@tonic-gate };
520Sstevel@tonic-gate 
530Sstevel@tonic-gate ibt_cep_next_state_t ibt_cep_next_state[IBT_STATE_NUM];
540Sstevel@tonic-gate 
550Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique", ibt_cep_next_state))
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /* The following data and functions can increase system stability. */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate int ibtl_qp_calls_curr;
600Sstevel@tonic-gate int ibtl_qp_calls_max = 128;	/* limit on # of simultaneous QP verb calls */
610Sstevel@tonic-gate kmutex_t ibtl_qp_mutex;
620Sstevel@tonic-gate kcondvar_t ibtl_qp_cv;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate void
ibtl_qp_flow_control_enter(void)650Sstevel@tonic-gate ibtl_qp_flow_control_enter(void)
660Sstevel@tonic-gate {
670Sstevel@tonic-gate 	mutex_enter(&ibtl_qp_mutex);
680Sstevel@tonic-gate 	while (ibtl_qp_calls_curr >= ibtl_qp_calls_max) {
690Sstevel@tonic-gate 		cv_wait(&ibtl_qp_cv, &ibtl_qp_mutex);
700Sstevel@tonic-gate 	}
710Sstevel@tonic-gate 	++ibtl_qp_calls_curr;
720Sstevel@tonic-gate 	mutex_exit(&ibtl_qp_mutex);
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
750Sstevel@tonic-gate void
ibtl_qp_flow_control_exit(void)760Sstevel@tonic-gate ibtl_qp_flow_control_exit(void)
770Sstevel@tonic-gate {
780Sstevel@tonic-gate 	mutex_enter(&ibtl_qp_mutex);
790Sstevel@tonic-gate 	cv_signal(&ibtl_qp_cv);
800Sstevel@tonic-gate 	--ibtl_qp_calls_curr;
810Sstevel@tonic-gate 	mutex_exit(&ibtl_qp_mutex);
820Sstevel@tonic-gate }
830Sstevel@tonic-gate 
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate  * Function:
860Sstevel@tonic-gate  *	ibt_alloc_qp
870Sstevel@tonic-gate  * Input:
880Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
890Sstevel@tonic-gate  *	type		Specifies the type of QP to alloc in ibt_alloc_qp()
900Sstevel@tonic-gate  *	qp_attrp	Specifies the ibt_qp_alloc_attr_t that are needed to
910Sstevel@tonic-gate  *			allocate a QP and transition it to the RTS state for
920Sstevel@tonic-gate  *			UDs and INIT state for all other QPs.
930Sstevel@tonic-gate  * Output:
940Sstevel@tonic-gate  *	queue_sizes_p	Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
950Sstevel@tonic-gate  *			WR SGL elements.
960Sstevel@tonic-gate  *	qpn_p		Returned QP Number of the allocated QP.
970Sstevel@tonic-gate  *	ibt_qp_p	The ibt_qp_hdl_t of the allocated QP.
980Sstevel@tonic-gate  * Returns:
990Sstevel@tonic-gate  *	IBT_SUCCESS
1000Sstevel@tonic-gate  * Description:
1010Sstevel@tonic-gate  *	Allocate a QP with specified attributes.
1020Sstevel@tonic-gate  */
1030Sstevel@tonic-gate ibt_status_t
ibt_alloc_qp(ibt_hca_hdl_t hca_hdl,ibt_qp_type_t type,ibt_qp_alloc_attr_t * qp_attrp,ibt_chan_sizes_t * queue_sizes_p,ib_qpn_t * qpn_p,ibt_qp_hdl_t * ibt_qp_p)1040Sstevel@tonic-gate ibt_alloc_qp(ibt_hca_hdl_t hca_hdl, ibt_qp_type_t type,
1050Sstevel@tonic-gate     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
1060Sstevel@tonic-gate     ib_qpn_t *qpn_p, ibt_qp_hdl_t *ibt_qp_p)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	ibt_status_t		retval;
1090Sstevel@tonic-gate 	ibtl_channel_t		*chanp;
1100Sstevel@tonic-gate 	ibt_tran_srv_t		qp_type;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_qp(%p, %d, %p, %p, %p, %p) ",
1130Sstevel@tonic-gate 	    hca_hdl, type, qp_attrp, queue_sizes_p, qpn_p, ibt_qp_p);
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	switch (type) {
1160Sstevel@tonic-gate 	case IBT_UD_RQP:
1170Sstevel@tonic-gate 		qp_type = IBT_UD_SRV;
1180Sstevel@tonic-gate 		break;
1190Sstevel@tonic-gate 	case IBT_RC_RQP:
1200Sstevel@tonic-gate 		qp_type = IBT_RC_SRV;
1210Sstevel@tonic-gate 		break;
1220Sstevel@tonic-gate 	case IBT_UC_RQP:
1230Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Unreliable Connected "
1240Sstevel@tonic-gate 		    "Transport Type is not supported.");
1250Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1260Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
1270Sstevel@tonic-gate 	case IBT_RD_RQP:
1280Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Reliable Datagram "
1290Sstevel@tonic-gate 		    "Transport Type is not supported.");
1300Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1310Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
1320Sstevel@tonic-gate 	default:
1330Sstevel@tonic-gate 		/* shouldn't happen ILLEGAL Type */
1340Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Illegal Transport Type "
1350Sstevel@tonic-gate 		    "%d", type);
1360Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1370Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	/* Get CI CQ handles */
141*12965SWilliam.Taylor@Oracle.COM 	qp_attrp->qp_ibc_scq_hdl = (qp_attrp->qp_scq_hdl == NULL) ? NULL :
142*12965SWilliam.Taylor@Oracle.COM 	    qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
143*12965SWilliam.Taylor@Oracle.COM 	qp_attrp->qp_ibc_rcq_hdl = (qp_attrp->qp_rcq_hdl == NULL) ? NULL :
144*12965SWilliam.Taylor@Oracle.COM 	    qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
1450Sstevel@tonic-gate 
146*12965SWilliam.Taylor@Oracle.COM 	/* Get CI SRQ handle */
1470Sstevel@tonic-gate 	if ((qp_attrp->qp_alloc_flags & IBT_QP_USES_SRQ) &&
1480Sstevel@tonic-gate 	    (qp_attrp->qp_srq_hdl != NULL))
1490Sstevel@tonic-gate 		qp_attrp->qp_ibc_srq_hdl =
1500Sstevel@tonic-gate 		    qp_attrp->qp_srq_hdl->srq_ibc_srq_hdl;
1510Sstevel@tonic-gate 	else
1520Sstevel@tonic-gate 		qp_attrp->qp_ibc_srq_hdl = NULL;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	/* Allocate Channel structure */
1550Sstevel@tonic-gate 	chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
1580Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp)(
1590Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), &chanp->ch_qp, type, qp_attrp,
1600Sstevel@tonic-gate 	    queue_sizes_p, qpn_p, &chanp->ch_qp.qp_ibc_qp_hdl);
1610Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
1620Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1630Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: "
1640Sstevel@tonic-gate 		    "Failed to allocate QP: %d", retval);
1650Sstevel@tonic-gate 		kmem_free(chanp, sizeof (*chanp));
1660Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1670Sstevel@tonic-gate 		return (retval);
1680Sstevel@tonic-gate 	}
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	/* Initialize the internal QP struct. */
1710Sstevel@tonic-gate 	chanp->ch_qp.qp_type = qp_type;
1720Sstevel@tonic-gate 	chanp->ch_qp.qp_hca = hca_hdl;
1730Sstevel@tonic-gate 	chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
1740Sstevel@tonic-gate 	chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
1750Sstevel@tonic-gate 	chanp->ch_current_state = IBT_STATE_RESET;
1769913SShantkumar.Hiremath@Sun.COM 	/*
1779913SShantkumar.Hiremath@Sun.COM 	 * The IBTA spec does not include the signal type or PD on a QP
1789913SShantkumar.Hiremath@Sun.COM 	 * query operation. In order to implement the "CLONE" feature
1799913SShantkumar.Hiremath@Sun.COM 	 * we need to cache these values.  Mostly used by TI client.
1809913SShantkumar.Hiremath@Sun.COM 	 */
1819913SShantkumar.Hiremath@Sun.COM 	chanp->ch_qp.qp_flags = qp_attrp->qp_flags;
1829913SShantkumar.Hiremath@Sun.COM 	chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl;
1830Sstevel@tonic-gate 	mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
1840Sstevel@tonic-gate 	cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
1850Sstevel@tonic-gate 
18612574SWilliam.Taylor@Oracle.COM 	atomic_inc_32(&hca_hdl->ha_qp_cnt);
1870Sstevel@tonic-gate 
1884908Shiremath 	IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: SUCCESS: qp %p owned by '%s'",
1890Sstevel@tonic-gate 	    chanp, hca_hdl->ha_clnt_devp->clnt_name);
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	*ibt_qp_p = chanp;
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	return (retval);
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate  * Function:
1990Sstevel@tonic-gate  *	ibt_initialize_qp
2000Sstevel@tonic-gate  * Input:
2010Sstevel@tonic-gate  *	ibt_qp		The previously allocated IBT QP Handle.
2020Sstevel@tonic-gate  *	modify_attrp	Specifies the QP Modify attributes that to transition
2030Sstevel@tonic-gate  *			the QP to the RTS state for UDs (including special QPs)
2040Sstevel@tonic-gate  *			and INIT state for all other QPs.
2050Sstevel@tonic-gate  * Output:
2060Sstevel@tonic-gate  *	none.
2070Sstevel@tonic-gate  * Returns:
2080Sstevel@tonic-gate  *	IBT_SUCCESS
2090Sstevel@tonic-gate  * Description:
2100Sstevel@tonic-gate  *	Transition the QP to the RTS state for UDs (including special QPs)
2110Sstevel@tonic-gate  *	and INIT state for all other QPs.
2120Sstevel@tonic-gate  */
2130Sstevel@tonic-gate ibt_status_t
ibt_initialize_qp(ibt_qp_hdl_t ibt_qp,ibt_qp_info_t * modify_attrp)2140Sstevel@tonic-gate ibt_initialize_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_info_t *modify_attrp)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate 	ibt_status_t		status;
2170Sstevel@tonic-gate 	ibt_cep_state_t		state;
2180Sstevel@tonic-gate 	ibc_hca_hdl_t		ibc_hca_hdl = IBTL_CHAN2CIHCA(ibt_qp);
2190Sstevel@tonic-gate 	ibc_qp_hdl_t		ibc_qp_hdl = IBTL_CHAN2CIQP(ibt_qp);
2200Sstevel@tonic-gate 	ibc_operations_t	*hca_ops_p = IBTL_CHAN2CIHCAOPS_P(ibt_qp);
2210Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp(%p, %p)",
2240Sstevel@tonic-gate 	    ibt_qp, modify_attrp);
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	/*
2270Sstevel@tonic-gate 	 * Validate the QP Type from the channel with QP Type from the
2280Sstevel@tonic-gate 	 * modify attribute struct.
2290Sstevel@tonic-gate 	 */
2300Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type != modify_attrp->qp_trans) {
2310Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
2320Sstevel@tonic-gate 		    "QP Type mismatch: Chan QP Type<%d>, Modify QP Type<%d>",
2330Sstevel@tonic-gate 		    ibt_qp->ch_qp.qp_type, modify_attrp->qp_trans);
2340Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 	if (ibt_qp->ch_current_state != IBT_STATE_RESET) {
2370Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
2380Sstevel@tonic-gate 		    "QP needs to be in RESET state: Chan QP State<%d>",
2390Sstevel@tonic-gate 		    ibt_qp->ch_current_state);
2400Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
2410Sstevel@tonic-gate 	}
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	/*
2440Sstevel@tonic-gate 	 * Initialize the QP to the RTS state for UDs
2450Sstevel@tonic-gate 	 * and INIT state for all other QPs.
2460Sstevel@tonic-gate 	 */
2470Sstevel@tonic-gate 	switch (modify_attrp->qp_trans) {
2480Sstevel@tonic-gate 	case IBT_UD_SRV:
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 		/*
2510Sstevel@tonic-gate 		 * Bring the QP to the RTS state.
2520Sstevel@tonic-gate 		 */
2530Sstevel@tonic-gate 		state = IBT_STATE_RESET;
2540Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
2550Sstevel@tonic-gate 		do {
2560Sstevel@tonic-gate 			modify_attrp->qp_current_state = state;
2570Sstevel@tonic-gate 			modify_flags = ibt_cep_next_state[state].modify_flags;
2580Sstevel@tonic-gate 			modify_attrp->qp_state = state =
2590Sstevel@tonic-gate 			    ibt_cep_next_state[state].next_state;
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 			IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp: "
2620Sstevel@tonic-gate 			    "modifying qp state to 0x%x", state);
2630Sstevel@tonic-gate 			status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl,
2640Sstevel@tonic-gate 			    ibc_qp_hdl, modify_flags, modify_attrp, NULL);
2650Sstevel@tonic-gate 		} while ((state != IBT_STATE_RTS) && (status == IBT_SUCCESS));
2660Sstevel@tonic-gate 		ibtl_qp_flow_control_exit();
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 		if (status == IBT_SUCCESS) {
2690Sstevel@tonic-gate 			ibt_qp->ch_current_state = state;
2700Sstevel@tonic-gate 			ibt_qp->ch_transport.ud.ud_port_num =
2710Sstevel@tonic-gate 			    modify_attrp->qp_transport.ud.ud_port;
2720Sstevel@tonic-gate 			ibt_qp->ch_transport.ud.ud_qkey =
2730Sstevel@tonic-gate 			    modify_attrp->qp_transport.ud.ud_qkey;
2740Sstevel@tonic-gate 		}
2750Sstevel@tonic-gate 		break;
2760Sstevel@tonic-gate 	case IBT_UC_SRV:
2770Sstevel@tonic-gate 	case IBT_RD_SRV:
2780Sstevel@tonic-gate 	case IBT_RC_SRV:
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 		/*
2810Sstevel@tonic-gate 		 * Bring the QP to the INIT state.
2820Sstevel@tonic-gate 		 */
2830Sstevel@tonic-gate 		modify_attrp->qp_state = IBT_STATE_INIT;
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
2860Sstevel@tonic-gate 		status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl, ibc_qp_hdl,
2870Sstevel@tonic-gate 		    IBT_CEP_SET_RESET_INIT, modify_attrp, NULL);
2880Sstevel@tonic-gate 		ibtl_qp_flow_control_exit();
2890Sstevel@tonic-gate 		if (status == IBT_SUCCESS)
2900Sstevel@tonic-gate 			ibt_qp->ch_current_state = IBT_STATE_INIT;
2910Sstevel@tonic-gate 		break;
2920Sstevel@tonic-gate 	default:
2930Sstevel@tonic-gate 		/* shouldn't happen ILLEGAL Type */
2940Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: Illegal Type %d",
2950Sstevel@tonic-gate 		    modify_attrp->qp_trans);
2960Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
2970Sstevel@tonic-gate 	} /* End switch */
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	return (status);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate /*
3040Sstevel@tonic-gate  * Function:
3050Sstevel@tonic-gate  *	ibt_alloc_special_qp
3060Sstevel@tonic-gate  * Input:
3070Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
3080Sstevel@tonic-gate  *	type		Specifies the type of Special QP to be allocated.
3090Sstevel@tonic-gate  *	qp_attrp	Specifies the ibt_qp_alloc_attr_t that are needed to
3100Sstevel@tonic-gate  *			allocate a special QP.
3110Sstevel@tonic-gate  * Output:
3120Sstevel@tonic-gate  *	queue_sizes_p	Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
3130Sstevel@tonic-gate  *			WR SGL elements.
3140Sstevel@tonic-gate  *	qpn_p		Returned qpn of the allocated QP.
3150Sstevel@tonic-gate  *	ibt_qp_p	The ibt_qp_hdl_t of the allocated QP.
3160Sstevel@tonic-gate  * Returns:
3170Sstevel@tonic-gate  *	IBT_SUCCESS
3180Sstevel@tonic-gate  * Description:
3190Sstevel@tonic-gate  *	Allocate a special QP with specified attributes.
3200Sstevel@tonic-gate  */
3210Sstevel@tonic-gate ibt_status_t
ibt_alloc_special_qp(ibt_hca_hdl_t hca_hdl,uint8_t port,ibt_sqp_type_t type,ibt_qp_alloc_attr_t * qp_attrp,ibt_chan_sizes_t * queue_sizes_p,ibt_qp_hdl_t * ibt_qp_p)3220Sstevel@tonic-gate ibt_alloc_special_qp(ibt_hca_hdl_t hca_hdl, uint8_t port, ibt_sqp_type_t type,
3230Sstevel@tonic-gate     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
3240Sstevel@tonic-gate     ibt_qp_hdl_t *ibt_qp_p)
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate 	ibt_qp_hdl_t	chanp;
3270Sstevel@tonic-gate 	ibt_status_t	retval;
3280Sstevel@tonic-gate 	ibt_tran_srv_t	sqp_type;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_special_qp(%p, %d, %x, %p, %p, %p)",
3310Sstevel@tonic-gate 	    hca_hdl, port, type, qp_attrp, queue_sizes_p, ibt_qp_p);
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	switch (type) {
3340Sstevel@tonic-gate 	case IBT_SMI_SQP:
3350Sstevel@tonic-gate 	case IBT_GSI_SQP:
3360Sstevel@tonic-gate 		sqp_type = IBT_UD_SRV;
3370Sstevel@tonic-gate 		break;
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	case IBT_RAWIP_SQP:
3400Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw IP "
3410Sstevel@tonic-gate 		    "Transport Type is not supported.");
3420Sstevel@tonic-gate 		*ibt_qp_p = NULL;
3430Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	case IBT_RAWETHER_SQP:
3460Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw Ethernet "
3470Sstevel@tonic-gate 		    "Transport Type is not supported.");
3480Sstevel@tonic-gate 		*ibt_qp_p = NULL;
3490Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	default:
3520Sstevel@tonic-gate 		/* Shouldn't happen */
3530Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
3540Sstevel@tonic-gate 		    "Illegal Type 0x%x", type);
3550Sstevel@tonic-gate 		*ibt_qp_p = NULL;
3560Sstevel@tonic-gate 		return (IBT_QP_SPECIAL_TYPE_INVALID);
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	/* convert the CQ handles for the CI */
3600Sstevel@tonic-gate 	qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
3610Sstevel@tonic-gate 	qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	/* Allocate Channel structure */
3640Sstevel@tonic-gate 	chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
3670Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_special_qp)(
3680Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), port, &chanp->ch_qp, type, qp_attrp,
3690Sstevel@tonic-gate 	    queue_sizes_p, &chanp->ch_qp.qp_ibc_qp_hdl);
3700Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
3710Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
3720Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
3730Sstevel@tonic-gate 		    "Failed to allocate Special QP: %d", retval);
3740Sstevel@tonic-gate 		kmem_free(chanp, sizeof (*chanp));
3750Sstevel@tonic-gate 		*ibt_qp_p = NULL;
3760Sstevel@tonic-gate 		return (retval);
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	/* Initialize the internal QP struct. */
3800Sstevel@tonic-gate 	chanp->ch_qp.qp_type = sqp_type;
3810Sstevel@tonic-gate 	chanp->ch_qp.qp_hca = hca_hdl;
3820Sstevel@tonic-gate 	chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
3830Sstevel@tonic-gate 	chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
3840Sstevel@tonic-gate 	chanp->ch_current_state = IBT_STATE_RESET;
3850Sstevel@tonic-gate 	mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
3860Sstevel@tonic-gate 	cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
3870Sstevel@tonic-gate 
3889913SShantkumar.Hiremath@Sun.COM 	/* Updating these variable, so that debugger shows correct values. */
3899913SShantkumar.Hiremath@Sun.COM 	chanp->ch_qp.qp_flags = qp_attrp->qp_flags;
3909913SShantkumar.Hiremath@Sun.COM 	chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl;
3919913SShantkumar.Hiremath@Sun.COM 
39212574SWilliam.Taylor@Oracle.COM 	atomic_inc_32(&hca_hdl->ha_qp_cnt);
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	*ibt_qp_p = chanp;
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	return (retval);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate /*
4010Sstevel@tonic-gate  * Function:
4020Sstevel@tonic-gate  *	ibt_flush_qp
4030Sstevel@tonic-gate  * Input:
4040Sstevel@tonic-gate  *	ibtl_qp		Handle for QP that needs to be flushed.
4050Sstevel@tonic-gate  * Output:
4060Sstevel@tonic-gate  *	none.
4070Sstevel@tonic-gate  * Returns:
4080Sstevel@tonic-gate  *	IBT_SUCCESS
4090Sstevel@tonic-gate  *	IBT_QP_HDL_INVALID
4100Sstevel@tonic-gate  * Description:
4110Sstevel@tonic-gate  *	Put the QP into error state to flush out work requests.
4120Sstevel@tonic-gate  */
4130Sstevel@tonic-gate ibt_status_t
ibt_flush_qp(ibt_qp_hdl_t ibt_qp)4140Sstevel@tonic-gate ibt_flush_qp(ibt_qp_hdl_t ibt_qp)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
4170Sstevel@tonic-gate 	ibt_status_t		retval;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_flush_qp(%p)", ibt_qp);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
4220Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
4236438Sagiri 		if ((ibt_qp->ch_transport.rc.rc_free_flags &
4246438Sagiri 		    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
4250Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
4260Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
4270Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp(%p): "
4280Sstevel@tonic-gate 			    "called with a connected RC QP", ibt_qp);
4290Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
4300Sstevel@tonic-gate 		}
4310Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
4320Sstevel@tonic-gate 	}
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	/*
4370Sstevel@tonic-gate 	 * Set the QP state to error to flush any uncompleted WRs.
4380Sstevel@tonic-gate 	 */
4390Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_ERROR;
4400Sstevel@tonic-gate 	modify_attr.qp_trans = ibt_qp->ch_qp.qp_type;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	retval = ibt_modify_qp(ibt_qp, IBT_CEP_SET_STATE, &modify_attr, NULL);
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
4450Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp: "
4460Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
4470Sstevel@tonic-gate 	}
4480Sstevel@tonic-gate 	return (retval);
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate /*
45311369SPramod.Gunjikar@Sun.COM  * ibtl_cm_chan_is_opening()
45411369SPramod.Gunjikar@Sun.COM  *
45511369SPramod.Gunjikar@Sun.COM  *	Inform IBTL that the connection established process is in progress
45611369SPramod.Gunjikar@Sun.COM  *	on this channel so that care need to be taken while free'ing when
45711369SPramod.Gunjikar@Sun.COM  *	open is NOT yet complete.
45811369SPramod.Gunjikar@Sun.COM  *
45911369SPramod.Gunjikar@Sun.COM  *	chan	Channel Handle
46011369SPramod.Gunjikar@Sun.COM  */
46111369SPramod.Gunjikar@Sun.COM void
ibtl_cm_chan_is_opening(ibt_channel_hdl_t chan)46211369SPramod.Gunjikar@Sun.COM ibtl_cm_chan_is_opening(ibt_channel_hdl_t chan)
46311369SPramod.Gunjikar@Sun.COM {
46411369SPramod.Gunjikar@Sun.COM 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_opening(%p)", chan);
46511369SPramod.Gunjikar@Sun.COM 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
46611369SPramod.Gunjikar@Sun.COM 	mutex_enter(&ibtl_free_qp_mutex);
46711369SPramod.Gunjikar@Sun.COM 	ASSERT(chan->ch_transport.rc.rc_free_flags == 0);
46811369SPramod.Gunjikar@Sun.COM 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTING;
46911369SPramod.Gunjikar@Sun.COM 	mutex_exit(&ibtl_free_qp_mutex);
47011369SPramod.Gunjikar@Sun.COM }
47111369SPramod.Gunjikar@Sun.COM 
47211369SPramod.Gunjikar@Sun.COM /*
47312064SShantkumar.Hiremath@Sun.COM  * ibtl_cm_chan_open_is_aborted()
47412064SShantkumar.Hiremath@Sun.COM  *
47512064SShantkumar.Hiremath@Sun.COM  *	Inform IBTL that the connection established on this channel has
47612064SShantkumar.Hiremath@Sun.COM  *	aborted. So undo what was done in ibtl_cm_chan_is_opening().
47712064SShantkumar.Hiremath@Sun.COM  *
47812064SShantkumar.Hiremath@Sun.COM  *	chan	Channel Handle
47912064SShantkumar.Hiremath@Sun.COM  */
48012064SShantkumar.Hiremath@Sun.COM void
ibtl_cm_chan_open_is_aborted(ibt_channel_hdl_t chan)48112064SShantkumar.Hiremath@Sun.COM ibtl_cm_chan_open_is_aborted(ibt_channel_hdl_t chan)
48212064SShantkumar.Hiremath@Sun.COM {
48312064SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_open_is_aborted(%p)", chan);
48412064SShantkumar.Hiremath@Sun.COM 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
48512064SShantkumar.Hiremath@Sun.COM 	mutex_enter(&ibtl_free_qp_mutex);
48612064SShantkumar.Hiremath@Sun.COM 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING;
48712064SShantkumar.Hiremath@Sun.COM 	mutex_exit(&ibtl_free_qp_mutex);
48812064SShantkumar.Hiremath@Sun.COM }
48912064SShantkumar.Hiremath@Sun.COM 
49012064SShantkumar.Hiremath@Sun.COM /*
4910Sstevel@tonic-gate  * ibtl_cm_chan_is_open()
4920Sstevel@tonic-gate  *
4930Sstevel@tonic-gate  *	Inform IBTL that the connection has been established on this
4940Sstevel@tonic-gate  *	channel so that a later call to ibtl_cm_chan_is_closed()
4950Sstevel@tonic-gate  *	will be required to free the QPN used by this channel.
4960Sstevel@tonic-gate  *
4970Sstevel@tonic-gate  *	chan	Channel Handle
4980Sstevel@tonic-gate  */
4990Sstevel@tonic-gate void
ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)5000Sstevel@tonic-gate ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)
5010Sstevel@tonic-gate {
5020Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_open(%p)", chan);
5030Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5040Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
50511369SPramod.Gunjikar@Sun.COM 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING;
5060Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTED;
5070Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate /*
5110Sstevel@tonic-gate  * ibtl_cm_is_chan_closing()
5120Sstevel@tonic-gate  *
5130Sstevel@tonic-gate  *	Returns 1, if the connection that has been
5140Sstevel@tonic-gate  *	started for this channel has moved to TIMEWAIT
5150Sstevel@tonic-gate  *	If not, returns 0
5160Sstevel@tonic-gate  *
5170Sstevel@tonic-gate  *	chan	Channel Handle
5180Sstevel@tonic-gate  */
5190Sstevel@tonic-gate int
ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)5200Sstevel@tonic-gate ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)
5210Sstevel@tonic-gate {
5220Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closing(%p)", chan);
5230Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5240Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5250Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSING) {
5260Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
5270Sstevel@tonic-gate 		return (1);
5280Sstevel@tonic-gate 	}
5290Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5300Sstevel@tonic-gate 	return (0);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate /*
5340Sstevel@tonic-gate  * ibtl_cm_is_chan_closed()
5350Sstevel@tonic-gate  *
5360Sstevel@tonic-gate  *	Returns 1, if the connection that has been
5370Sstevel@tonic-gate  *	started for this channel has completed TIMEWAIT
5380Sstevel@tonic-gate  *	If not, returns 0
5390Sstevel@tonic-gate  *
5400Sstevel@tonic-gate  *	chan	Channel Handle
5410Sstevel@tonic-gate  */
5420Sstevel@tonic-gate int
ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)5430Sstevel@tonic-gate ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)
5440Sstevel@tonic-gate {
5450Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closed(%p)", chan);
5460Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5470Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5480Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSED) {
5490Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
5500Sstevel@tonic-gate 		return (1);
5510Sstevel@tonic-gate 	}
5520Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5530Sstevel@tonic-gate 	return (0);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate /*
5560Sstevel@tonic-gate  * ibtl_cm_chan_is_closing()
5570Sstevel@tonic-gate  *
5580Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
5590Sstevel@tonic-gate  *	started for this channel so that the QP can be freed.
5600Sstevel@tonic-gate  *
5610Sstevel@tonic-gate  *	chan	Channel Handle
5620Sstevel@tonic-gate  */
5630Sstevel@tonic-gate void
ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)5640Sstevel@tonic-gate ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closing(%p)", chan);
5670Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5680Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5690Sstevel@tonic-gate 	ASSERT(chan->ch_transport.rc.rc_free_flags == IBTL_RC_QP_CONNECTED);
5700Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSING;
5710Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate /*
5740Sstevel@tonic-gate  * ibtl_cm_chan_is_closed()
5750Sstevel@tonic-gate  *
5760Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
5770Sstevel@tonic-gate  *	reached for this channel so that the QPN can be reused.
5780Sstevel@tonic-gate  *
5790Sstevel@tonic-gate  *	chan	Channel Handle
5800Sstevel@tonic-gate  */
5810Sstevel@tonic-gate void
ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)5820Sstevel@tonic-gate ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate 	ibt_status_t status;
5850Sstevel@tonic-gate 	ibtl_hca_t *ibtl_hca = chan->ch_qp.qp_hca;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closed(%p)", chan);
5880Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5890Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5900Sstevel@tonic-gate 	ASSERT((chan->ch_transport.rc.rc_free_flags &
5910Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
5920Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING));
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTED;
5950Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSING;
5960Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSED;
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	ibtl_cm_set_chan_private(chan, NULL);
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	if ((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_FREED) == 0) {
6010Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
6020Sstevel@tonic-gate 		return;
6030Sstevel@tonic-gate 	}
6040Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
6050Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
6060Sstevel@tonic-gate 	if ((status = (IBTL_CHAN2CIHCAOPS_P(chan)->ibc_release_qpn)
6070Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(chan), chan->ch_transport.rc.rc_qpn_hdl)) ==
6080Sstevel@tonic-gate 	    IBT_SUCCESS) {
6090Sstevel@tonic-gate 		/* effectively, this is kmem_free(chan); */
6100Sstevel@tonic-gate 		ibtl_free_qp_async_check(&chan->ch_qp);
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 		/* decrement ha_qpn_cnt and check for close in progress */
6130Sstevel@tonic-gate 		ibtl_close_hca_check(ibtl_hca);
6140Sstevel@tonic-gate 	} else
6153241Shiremath 		IBTF_DPRINTF_L2(ibtf_qp, "ibtl_cm_chan_is_closed: "
6160Sstevel@tonic-gate 		    "ibc_release_qpn failed: status = %d\n", status);
6170Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate /*
6210Sstevel@tonic-gate  * ibtl_cm_chan_is_reused()
6220Sstevel@tonic-gate  *
6230Sstevel@tonic-gate  *	Inform IBTL that the channel is going to be re-used
6240Sstevel@tonic-gate  *	chan	Channel Handle
6250Sstevel@tonic-gate  */
6260Sstevel@tonic-gate void
ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)6270Sstevel@tonic-gate ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)
6280Sstevel@tonic-gate {
6290Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_reused(%p)", chan);
6300Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
6310Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
6320Sstevel@tonic-gate 	ASSERT(((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CONNECTED) !=
6330Sstevel@tonic-gate 	    IBTL_RC_QP_CONNECTED));
6340Sstevel@tonic-gate 
6350Sstevel@tonic-gate 	/* channel is no longer in closed state, shall be re-used */
6363241Shiremath 	chan->ch_transport.rc.rc_free_flags = 0;
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate /*
6430Sstevel@tonic-gate  * Function:	ibt_free_qp()
6440Sstevel@tonic-gate  *
6450Sstevel@tonic-gate  * Input:	ibt_qp		Handle for Channel(QP) that needs to be freed.
6460Sstevel@tonic-gate  *
6470Sstevel@tonic-gate  * Output:	NONE.
6480Sstevel@tonic-gate  *
6490Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
6500Sstevel@tonic-gate  *		IBT_QP_STATE_INVALID
6510Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
6520Sstevel@tonic-gate  *
6530Sstevel@tonic-gate  * Description:
6540Sstevel@tonic-gate  *		Free a previously allocated QP.
6550Sstevel@tonic-gate  */
6560Sstevel@tonic-gate ibt_status_t
ibt_free_qp(ibt_qp_hdl_t ibt_qp)6570Sstevel@tonic-gate ibt_free_qp(ibt_qp_hdl_t ibt_qp)
6580Sstevel@tonic-gate {
6590Sstevel@tonic-gate 	ibt_status_t		status;
6600Sstevel@tonic-gate 	ibtl_hca_t		*ibtl_hca = ibt_qp->ch_qp.qp_hca;
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p)", ibt_qp);
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
6650Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
6660Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
6670Sstevel@tonic-gate 		if (ibt_qp->ch_transport.rc.rc_free_flags &
66811369SPramod.Gunjikar@Sun.COM 		    IBTL_RC_QP_CONNECTING) {
66911369SPramod.Gunjikar@Sun.COM 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
67011369SPramod.Gunjikar@Sun.COM 			    "Channel establishment is still in PROGRESS.");
67111369SPramod.Gunjikar@Sun.COM 			mutex_exit(&ibtl_free_qp_mutex);
67211369SPramod.Gunjikar@Sun.COM 			ibtl_qp_flow_control_exit();
67311369SPramod.Gunjikar@Sun.COM 			return (IBT_CHAN_STATE_INVALID);
67411369SPramod.Gunjikar@Sun.COM 		}
67511369SPramod.Gunjikar@Sun.COM 		if (ibt_qp->ch_transport.rc.rc_free_flags &
6760Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
6770Sstevel@tonic-gate 			if ((ibt_qp->ch_transport.rc.rc_free_flags &
6780Sstevel@tonic-gate 			    IBTL_RC_QP_CLOSING) == 0) {
6790Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
6800Sstevel@tonic-gate 				    "need to call ibt_close_rc_channel");
6810Sstevel@tonic-gate 				mutex_exit(&ibtl_free_qp_mutex);
6820Sstevel@tonic-gate 				ibtl_qp_flow_control_exit();
6830Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
6840Sstevel@tonic-gate 			}
6850Sstevel@tonic-gate 			ibt_qp->ch_transport.rc.rc_free_flags |=
6860Sstevel@tonic-gate 			    IBTL_RC_QP_FREED;
6870Sstevel@tonic-gate 			status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
6880Sstevel@tonic-gate 			    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
6890Sstevel@tonic-gate 			    IBC_FREE_QP_ONLY,
6900Sstevel@tonic-gate 			    &ibt_qp->ch_transport.rc.rc_qpn_hdl);
6910Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
6920Sstevel@tonic-gate 			ibtl_qp_flow_control_exit();
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 			if (status == IBT_SUCCESS) {
6950Sstevel@tonic-gate 				mutex_enter(&ibtl_clnt_list_mutex);
6960Sstevel@tonic-gate 				ibtl_hca->ha_qpn_cnt++;
6970Sstevel@tonic-gate 				mutex_exit(&ibtl_clnt_list_mutex);
69812574SWilliam.Taylor@Oracle.COM 				atomic_dec_32(&ibtl_hca->ha_qp_cnt);
6993241Shiremath 				IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - "
7000Sstevel@tonic-gate 				    "SUCCESS", ibt_qp);
7010Sstevel@tonic-gate 			} else
7020Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
7030Sstevel@tonic-gate 				    "ibc_free_qp failed: status = %d", status);
7040Sstevel@tonic-gate 			return (status);
7050Sstevel@tonic-gate 		}
7060Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
7070Sstevel@tonic-gate 	} else
7080Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate 	status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
7110Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
7120Sstevel@tonic-gate 	    IBC_FREE_QP_AND_QPN, NULL);
7130Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	if (status == IBT_SUCCESS) {
7160Sstevel@tonic-gate 		/* effectively, this is kmem_free(ibt_qp); */
7170Sstevel@tonic-gate 		ibtl_free_qp_async_check(&ibt_qp->ch_qp);
7180Sstevel@tonic-gate 
71912574SWilliam.Taylor@Oracle.COM 		atomic_dec_32(&ibtl_hca->ha_qp_cnt);
7203241Shiremath 		IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - SUCCESS", ibt_qp);
7210Sstevel@tonic-gate 	} else {
7220Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
7230Sstevel@tonic-gate 		    "ibc_free_qp failed with error %d", status);
7240Sstevel@tonic-gate 	}
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	return (status);
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate /* helper function for ibt_query_qp */
7310Sstevel@tonic-gate static void
ibtl_fillin_sgid(ibt_cep_path_t * pathp,ibtl_hca_devinfo_t * hca_devp)7320Sstevel@tonic-gate ibtl_fillin_sgid(ibt_cep_path_t *pathp, ibtl_hca_devinfo_t *hca_devp)
7330Sstevel@tonic-gate {
7340Sstevel@tonic-gate 	uint8_t port;
7350Sstevel@tonic-gate 	uint32_t sgid_ix;
7360Sstevel@tonic-gate 	ib_gid_t *sgidp;
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 	port = pathp->cep_hca_port_num;
7390Sstevel@tonic-gate 	sgid_ix = pathp->cep_adds_vect.av_sgid_ix;
7400Sstevel@tonic-gate 	if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
7410Sstevel@tonic-gate 	    sgid_ix >= IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
7420Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_prefix = 0;
7430Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_guid = 0;
7440Sstevel@tonic-gate 	} else {
7450Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
7460Sstevel@tonic-gate 		sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
7470Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid = sgidp[sgid_ix];
7480Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7490Sstevel@tonic-gate 	}
7500Sstevel@tonic-gate }
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate /*
7540Sstevel@tonic-gate  * Function:	ibt_query_qp
7550Sstevel@tonic-gate  *
7560Sstevel@tonic-gate  * Input:	ibt_qp 			- The IBT QP Handle.
7570Sstevel@tonic-gate  *
7580Sstevel@tonic-gate  * Output:	ibt_qp_query_attrp 	- Points to a ibt_qp_query_attr_t
7590Sstevel@tonic-gate  *					  that on return contains all the
7600Sstevel@tonic-gate  *					  attributes of the specified qp.
7610Sstevel@tonic-gate  *
7620Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
7630Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
7640Sstevel@tonic-gate  *
7650Sstevel@tonic-gate  * Description:
7660Sstevel@tonic-gate  *		Query QP attributes
7670Sstevel@tonic-gate  *
7680Sstevel@tonic-gate  */
7690Sstevel@tonic-gate ibt_status_t
ibt_query_qp(ibt_qp_hdl_t ibt_qp,ibt_qp_query_attr_t * qp_query_attrp)7700Sstevel@tonic-gate ibt_query_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_query_attr_t *qp_query_attrp)
7710Sstevel@tonic-gate {
7720Sstevel@tonic-gate 	ibt_status_t		retval;
7730Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
7740Sstevel@tonic-gate 	ibt_qp_info_t		*qp_infop;
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_qp(%p, %p)",
7770Sstevel@tonic-gate 	    ibt_qp, qp_query_attrp);
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
7800Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_query_qp(
7810Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), qp_query_attrp));
7820Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
7830Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
7840Sstevel@tonic-gate 		ibt_qp->ch_current_state = qp_query_attrp->qp_info.qp_state;
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate 		/* need to fill in sgid from port and sgid_ix for RC and UC */
7870Sstevel@tonic-gate 		hca_devp = ibt_qp->ch_qp.qp_hca->ha_hca_devp;
7880Sstevel@tonic-gate 		qp_infop = &qp_query_attrp->qp_info;
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 		switch (qp_infop->qp_trans) {
7910Sstevel@tonic-gate 		case IBT_RC_SRV:
7920Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_path,
7930Sstevel@tonic-gate 			    hca_devp);
7940Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_alt_path,
7950Sstevel@tonic-gate 			    hca_devp);
7960Sstevel@tonic-gate 			break;
7970Sstevel@tonic-gate 		case IBT_UC_SRV:
7980Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_path,
7990Sstevel@tonic-gate 			    hca_devp);
8000Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_alt_path,
8010Sstevel@tonic-gate 			    hca_devp);
8020Sstevel@tonic-gate 			break;
8030Sstevel@tonic-gate 		}
8040Sstevel@tonic-gate 	} else {
8050Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_qp: "
8060Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
8070Sstevel@tonic-gate 	}
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	return (retval);
8100Sstevel@tonic-gate }
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate /*
8140Sstevel@tonic-gate  * Function:
8150Sstevel@tonic-gate  *	ibt_modify_qp
8160Sstevel@tonic-gate  * Input:
8170Sstevel@tonic-gate  *	ibt_qp		The IBT QP Handle.
8180Sstevel@tonic-gate  *	flags		Specifies which attributes in ibt_qp_mod_attr_t
8190Sstevel@tonic-gate  *			are to be modified.
8200Sstevel@tonic-gate  *	qp_attrp	Points to an ibt_qp_mod_attr_t struct that contains all
8210Sstevel@tonic-gate  *			the attributes of the specified QP that a client is
8220Sstevel@tonic-gate  *			allowed to modify after a QP has been allocated
8230Sstevel@tonic-gate  * Output:
8240Sstevel@tonic-gate  *	actual_sz	Returned actual queue sizes.
8250Sstevel@tonic-gate  * Returns:
8260Sstevel@tonic-gate  *	IBT_SUCCESS
8270Sstevel@tonic-gate  * Description:
8280Sstevel@tonic-gate  *	Modify the attributes of an existing QP.
8290Sstevel@tonic-gate  */
8300Sstevel@tonic-gate ibt_status_t
ibt_modify_qp(ibt_qp_hdl_t ibt_qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * modify_attrp,ibt_queue_sizes_t * actual_sz)8310Sstevel@tonic-gate ibt_modify_qp(ibt_qp_hdl_t ibt_qp, ibt_cep_modify_flags_t flags,
8320Sstevel@tonic-gate     ibt_qp_info_t *modify_attrp, ibt_queue_sizes_t *actual_sz)
8330Sstevel@tonic-gate {
8340Sstevel@tonic-gate 	ibt_status_t		retval;
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_qp(%p, %d, %p, %p)",
8370Sstevel@tonic-gate 	    ibt_qp, flags, modify_attrp, actual_sz);
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
8400Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_modify_qp)(
8410Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), flags,
8420Sstevel@tonic-gate 	    modify_attrp, actual_sz);
8430Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
8440Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
8450Sstevel@tonic-gate 		ibt_qp->ch_current_state = modify_attrp->qp_state;
8460Sstevel@tonic-gate 		if (ibt_qp->ch_qp.qp_type == IBT_UD_SRV) {
8470Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_PORT | IBT_CEP_SET_RESET_INIT))
8480Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_port_num =
8490Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_port;
8500Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_QKEY | IBT_CEP_SET_RESET_INIT))
8510Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_qkey =
8520Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_qkey;
8530Sstevel@tonic-gate 		}
8540Sstevel@tonic-gate 	} else {
8550Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_qp: failed on chan %p: %d",
8560Sstevel@tonic-gate 		    ibt_qp, retval);
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 		if (retval == IBT_CHAN_STATE_INVALID) {
8590Sstevel@tonic-gate 			/* That means our cache had invalid QP state value. */
8600Sstevel@tonic-gate 			ibt_qp_query_attr_t	qp_attr;
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate 			/* Query the channel (QP) */
8630Sstevel@tonic-gate 			if (ibt_query_qp(ibt_qp, &qp_attr) == IBT_SUCCESS)
8640Sstevel@tonic-gate 				ibt_qp->ch_current_state =
8650Sstevel@tonic-gate 				    qp_attr.qp_info.qp_state;
8660Sstevel@tonic-gate 		}
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 	return (retval);
8690Sstevel@tonic-gate }
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate 
8720Sstevel@tonic-gate /*
8730Sstevel@tonic-gate  * Function:
8740Sstevel@tonic-gate  *	ibt_migrate_path
8750Sstevel@tonic-gate  * Input:
8760Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
8770Sstevel@tonic-gate  * Output:
8780Sstevel@tonic-gate  *	none.
8790Sstevel@tonic-gate  * Returns:
8800Sstevel@tonic-gate  *	IBT_SUCCESS on Success else appropriate error.
8810Sstevel@tonic-gate  * Description:
8820Sstevel@tonic-gate  *	Force the CI to use the alternate path. The alternate path becomes
8830Sstevel@tonic-gate  *	the primary path. A new alternate path should be loaded and enabled.
8840Sstevel@tonic-gate  *	Assumes that the given channel is in RTS/SQD state
8850Sstevel@tonic-gate  */
8860Sstevel@tonic-gate ibt_status_t
ibt_migrate_path(ibt_channel_hdl_t rc_chan)8870Sstevel@tonic-gate ibt_migrate_path(ibt_channel_hdl_t rc_chan)
8880Sstevel@tonic-gate {
8890Sstevel@tonic-gate 	ibt_status_t		retval;
8900Sstevel@tonic-gate 	ibt_qp_info_t		qp_info;
8910Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
8920Sstevel@tonic-gate 	ibt_cep_modify_flags_t	cep_flags;
8930Sstevel@tonic-gate 	int			retries = 1;
8940Sstevel@tonic-gate 
8953241Shiremath 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_migrate_path: channel %p", rc_chan);
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
8980Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: "
8990Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel");
9000Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
9010Sstevel@tonic-gate 	}
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 	if (rc_chan->ch_current_state != IBT_STATE_RTS &&
9040Sstevel@tonic-gate 	    rc_chan->ch_current_state != IBT_STATE_SQD) {
9050Sstevel@tonic-gate 		if (ibt_query_qp(rc_chan, &qp_attr) == IBT_SUCCESS) {
9060Sstevel@tonic-gate 			/* ch_current_state is fixed by ibt_query_qp */
9070Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
9080Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
9090Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
9100Sstevel@tonic-gate 			retries = 0;
9110Sstevel@tonic-gate 		} else /* query_qp should never really fail */
9120Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
9130Sstevel@tonic-gate 	}
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate retry:
9160Sstevel@tonic-gate 	/* Call modify_qp */
9170Sstevel@tonic-gate 	cep_flags = IBT_CEP_SET_MIG | IBT_CEP_SET_STATE;
9180Sstevel@tonic-gate 	qp_info.qp_state = rc_chan->ch_current_state;
9190Sstevel@tonic-gate 	qp_info.qp_current_state = rc_chan->ch_current_state;
9200Sstevel@tonic-gate 	qp_info.qp_trans = IBT_RC_SRV;
9210Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_mig_state = IBT_STATE_MIGRATED;
9220Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, cep_flags, &qp_info, NULL);
9230Sstevel@tonic-gate 
9240Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
9250Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
9260Sstevel@tonic-gate 		    " ibt_modify_qp() returned = %d", retval);
9270Sstevel@tonic-gate 		if (rc_chan->ch_current_state != qp_info.qp_state &&
9280Sstevel@tonic-gate 		    --retries >= 0) {
9290Sstevel@tonic-gate 			/*
9300Sstevel@tonic-gate 			 * That means our cached 'state' was invalid.
9310Sstevel@tonic-gate 			 * We know ibt_modify_qp() fixed it up, so it
9320Sstevel@tonic-gate 			 * might be worth retrying.
9330Sstevel@tonic-gate 			 */
9340Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
9350Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
9360Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
9370Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
9380Sstevel@tonic-gate 			    " retrying after 'state' fixed");
9390Sstevel@tonic-gate 			goto retry;
9400Sstevel@tonic-gate 		}
9410Sstevel@tonic-gate 	}
9420Sstevel@tonic-gate 	return (retval);
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate /*
9470Sstevel@tonic-gate  * Function:
9480Sstevel@tonic-gate  *	ibt_set_qp_private
9490Sstevel@tonic-gate  * Input:
9500Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9510Sstevel@tonic-gate  *	clnt_private	The client private data.
9520Sstevel@tonic-gate  * Output:
9530Sstevel@tonic-gate  *	none.
9540Sstevel@tonic-gate  * Returns:
9550Sstevel@tonic-gate  *	none.
9560Sstevel@tonic-gate  * Description:
9570Sstevel@tonic-gate  *	Set the client private data.
9580Sstevel@tonic-gate  */
9590Sstevel@tonic-gate void
ibt_set_qp_private(ibt_qp_hdl_t ibt_qp,void * clnt_private)9600Sstevel@tonic-gate ibt_set_qp_private(ibt_qp_hdl_t ibt_qp, void *clnt_private)
9610Sstevel@tonic-gate {
9620Sstevel@tonic-gate 	ibt_qp->ch_clnt_private = clnt_private;
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 
9660Sstevel@tonic-gate /*
9670Sstevel@tonic-gate  * Function:
9680Sstevel@tonic-gate  *	ibt_get_qp_private
9690Sstevel@tonic-gate  * Input:
9700Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9710Sstevel@tonic-gate  * Output:
9720Sstevel@tonic-gate  *	none.
9730Sstevel@tonic-gate  * Returns:
9740Sstevel@tonic-gate  *	The client private data.
9750Sstevel@tonic-gate  * Description:
9760Sstevel@tonic-gate  *	Get the client private data.
9770Sstevel@tonic-gate  */
9780Sstevel@tonic-gate void *
ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)9790Sstevel@tonic-gate ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)
9800Sstevel@tonic-gate {
9810Sstevel@tonic-gate 	return (ibt_qp->ch_clnt_private);
9820Sstevel@tonic-gate }
9830Sstevel@tonic-gate 
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate /*
9860Sstevel@tonic-gate  * Function:
9870Sstevel@tonic-gate  *	ibt_qp_to_hca_guid
9880Sstevel@tonic-gate  * Input:
9890Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9900Sstevel@tonic-gate  * Output:
9910Sstevel@tonic-gate  *	none.
9920Sstevel@tonic-gate  * Returns:
9930Sstevel@tonic-gate  *	hca_guid	Returned HCA GUID on which the specified QP is
9940Sstevel@tonic-gate  *			allocated. Valid if it is non-NULL on return.
9950Sstevel@tonic-gate  * Description:
9960Sstevel@tonic-gate  *	A helper function to retrieve HCA GUID for the specified QP.
9970Sstevel@tonic-gate  */
9980Sstevel@tonic-gate ib_guid_t
ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)9990Sstevel@tonic-gate ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)
10000Sstevel@tonic-gate {
10010Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_qp_to_hca_guid(%p)", ibt_qp);
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 	return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ibt_qp)));
10040Sstevel@tonic-gate }
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate /*
10080Sstevel@tonic-gate  * Function:
10090Sstevel@tonic-gate  *	ibt_recover_ud_qp
10100Sstevel@tonic-gate  * Input:
10110Sstevel@tonic-gate  *	ibt_qp		An QP Handle which is in SQError state.
10120Sstevel@tonic-gate  * Output:
10130Sstevel@tonic-gate  *	none.
10140Sstevel@tonic-gate  * Returns:
10150Sstevel@tonic-gate  *	IBT_SUCCESS
10160Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
10170Sstevel@tonic-gate  *	IBT_QP_STATE_INVALID.
10180Sstevel@tonic-gate  * Description:
10190Sstevel@tonic-gate  *	Recover an UD QP which has transitioned to SQ Error state. The
10200Sstevel@tonic-gate  *	ibt_recover_ud_qp() transitions the QP from SQ Error state to
10210Sstevel@tonic-gate  *	Ready-To-Send QP state.
10220Sstevel@tonic-gate  *
10230Sstevel@tonic-gate  *	If a work request posted to a UD QP's send queue completes with an
10240Sstevel@tonic-gate  *	error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state.
10250Sstevel@tonic-gate  *	In order to reuse this QP, ibt_recover_ud_qp() can be used to recover
10260Sstevel@tonic-gate  *	the QP to a usable (Ready-to-Send) state.
10270Sstevel@tonic-gate  */
10280Sstevel@tonic-gate ibt_status_t
ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)10290Sstevel@tonic-gate ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)
10300Sstevel@tonic-gate {
10310Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recover_ud_qp(%p)", ibt_qp);
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 	return (ibt_recover_ud_channel(IBTL_QP2CHAN(ibt_qp)));
10340Sstevel@tonic-gate }
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate /*
10380Sstevel@tonic-gate  * Function:
10390Sstevel@tonic-gate  *	ibt_recycle_ud
10400Sstevel@tonic-gate  * Input:
10410Sstevel@tonic-gate  *	ud_chan		The IBT UD QP Handle.
10420Sstevel@tonic-gate  *	various attributes
10430Sstevel@tonic-gate  *
10440Sstevel@tonic-gate  * Output:
10450Sstevel@tonic-gate  *	none
10460Sstevel@tonic-gate  * Returns:
10470Sstevel@tonic-gate  *	IBT_SUCCESS
10480Sstevel@tonic-gate  *	IBT_CHAN_SRV_TYPE_INVALID
10490Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
10500Sstevel@tonic-gate  *
10510Sstevel@tonic-gate  * Description:
10520Sstevel@tonic-gate  *	Revert the UD QP back to a usable state.
10530Sstevel@tonic-gate  */
10540Sstevel@tonic-gate ibt_status_t
ibt_recycle_ud(ibt_channel_hdl_t ud_chan,uint8_t hca_port_num,uint16_t pkey_ix,ib_qkey_t qkey)10550Sstevel@tonic-gate ibt_recycle_ud(ibt_channel_hdl_t ud_chan, uint8_t hca_port_num,
10560Sstevel@tonic-gate     uint16_t pkey_ix, ib_qkey_t qkey)
10570Sstevel@tonic-gate {
10580Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
10590Sstevel@tonic-gate 	ibt_status_t		retval;
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recycle_ud(%p, %d, %x, %x): ",
10620Sstevel@tonic-gate 	    ud_chan, hca_port_num, pkey_ix, qkey);
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
10650Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10660Sstevel@tonic-gate 		    "chan %p is not a UD channel", ud_chan);
10670Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
10680Sstevel@tonic-gate 	}
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate 	retval = ibt_query_qp(ud_chan, &qp_attr);
10710Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10720Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10730Sstevel@tonic-gate 		    "ibt_query_qp failed on chan %p: %d", ud_chan, retval);
10740Sstevel@tonic-gate 		return (retval);
10750Sstevel@tonic-gate 	}
10760Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR) {
10770Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10780Sstevel@tonic-gate 		    "chan %p is in state %d (not in ERROR state)",
10790Sstevel@tonic-gate 		    ud_chan, qp_attr.qp_info.qp_state);
10800Sstevel@tonic-gate 		ud_chan->ch_current_state = qp_attr.qp_info.qp_state;
10810Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
10820Sstevel@tonic-gate 	}
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate 	/* transition the QP from ERROR to RESET */
10850Sstevel@tonic-gate 	qp_attr.qp_info.qp_state = IBT_STATE_RESET;
10860Sstevel@tonic-gate 	qp_attr.qp_info.qp_trans = ud_chan->ch_qp.qp_type;
10870Sstevel@tonic-gate 	retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &qp_attr.qp_info,
10880Sstevel@tonic-gate 	    NULL);
10890Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10900Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10910Sstevel@tonic-gate 		    "ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d",
10920Sstevel@tonic-gate 		    ud_chan, retval);
10930Sstevel@tonic-gate 		return (retval);
10940Sstevel@tonic-gate 	}
10950Sstevel@tonic-gate 	ud_chan->ch_current_state = IBT_STATE_RESET;
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate 	/* transition the QP back to RTS */
10980Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_port = hca_port_num;
10990Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_qkey = qkey;
11000Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_pkey_ix = pkey_ix;
11010Sstevel@tonic-gate 	retval = ibt_initialize_qp(ud_chan, &qp_attr.qp_info);
11020Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11030Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
11040Sstevel@tonic-gate 		    "ibt_initialize_qp failed on chan %p: %d", ud_chan, retval);
11050Sstevel@tonic-gate 		/* the man page says the QP should be left in ERROR state */
11060Sstevel@tonic-gate 		(void) ibt_flush_qp(ud_chan);
11070Sstevel@tonic-gate 	}
11080Sstevel@tonic-gate 	return (retval);
11090Sstevel@tonic-gate }
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate /*
11120Sstevel@tonic-gate  * Function:
11130Sstevel@tonic-gate  *	ibt_pause_sendq
11140Sstevel@tonic-gate  * Input:
11150Sstevel@tonic-gate  *	chan		The IBT QP Handle.
11160Sstevel@tonic-gate  *	modify_flags	IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT
11170Sstevel@tonic-gate  *
11180Sstevel@tonic-gate  * Output:
11190Sstevel@tonic-gate  *	none.
11200Sstevel@tonic-gate  * Returns:
11210Sstevel@tonic-gate  *	IBT_SUCCESS
11220Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
11230Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
11240Sstevel@tonic-gate  *	IBT_INVALID_PARAM
11250Sstevel@tonic-gate  *
11260Sstevel@tonic-gate  * Description:
11270Sstevel@tonic-gate  *	Place the send queue of the specified channel into the send queue
11280Sstevel@tonic-gate  *	drained (SQD) state.
11290Sstevel@tonic-gate  *
11300Sstevel@tonic-gate  */
11310Sstevel@tonic-gate ibt_status_t
ibt_pause_sendq(ibt_channel_hdl_t chan,ibt_cep_modify_flags_t modify_flags)11320Sstevel@tonic-gate ibt_pause_sendq(ibt_channel_hdl_t chan, ibt_cep_modify_flags_t modify_flags)
11330Sstevel@tonic-gate {
11340Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
11350Sstevel@tonic-gate 	ibt_status_t		retval;
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_pause_sendq(%p, %x)", chan, modify_flags);
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate 	modify_flags &= IBT_CEP_SET_SQD_EVENT;	/* ignore other bits */
11400Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
11430Sstevel@tonic-gate 	/*
11440Sstevel@tonic-gate 	 * Set the QP state to SQD.
11450Sstevel@tonic-gate 	 */
11460Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
11470Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11520Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_pause_sendq: "
11530Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
11540Sstevel@tonic-gate 	}
11550Sstevel@tonic-gate 	return (retval);
11560Sstevel@tonic-gate }
11570Sstevel@tonic-gate 
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate /*
11600Sstevel@tonic-gate  * Function:
11610Sstevel@tonic-gate  *	ibt_unpause_sendq
11620Sstevel@tonic-gate  * Input:
11630Sstevel@tonic-gate  *	chan	The IBT Channel Handle.
11640Sstevel@tonic-gate  * Output:
11650Sstevel@tonic-gate  *	none.
11660Sstevel@tonic-gate  * Returns:
11670Sstevel@tonic-gate  *	IBT_SUCCESS
11680Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
11690Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
11700Sstevel@tonic-gate  * Description:
11710Sstevel@tonic-gate  *	Un-pauses the previously paused channel. This call will transition the
11720Sstevel@tonic-gate  *	QP from SQD to RTS state.
11730Sstevel@tonic-gate  */
11740Sstevel@tonic-gate ibt_status_t
ibt_unpause_sendq(ibt_channel_hdl_t chan)11750Sstevel@tonic-gate ibt_unpause_sendq(ibt_channel_hdl_t chan)
11760Sstevel@tonic-gate {
11770Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
11780Sstevel@tonic-gate 	ibt_status_t		retval;
11790Sstevel@tonic-gate 
11800Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_unpause_sendq(%p)", chan);
11810Sstevel@tonic-gate 
11820Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	/*
11850Sstevel@tonic-gate 	 * Set the QP state to RTS.
11860Sstevel@tonic-gate 	 */
11870Sstevel@tonic-gate 	modify_attr.qp_current_state = IBT_STATE_SQD;
11880Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_RTS;
11890Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
11920Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11930Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_unpause_sendq: "
11940Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
11950Sstevel@tonic-gate 	}
11960Sstevel@tonic-gate 	return (retval);
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate 
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate /*
12010Sstevel@tonic-gate  * Function:
12020Sstevel@tonic-gate  *	ibt_resize_queues
12030Sstevel@tonic-gate  * Input:
12040Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
12050Sstevel@tonic-gate  *	flags		QP Flags
12060Sstevel@tonic-gate  *				IBT_SEND_Q
12070Sstevel@tonic-gate  *				IBT_RECV_Q
12080Sstevel@tonic-gate  *	request_sz	Requested new sizes.
12090Sstevel@tonic-gate  * Output:
12100Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
12110Sstevel@tonic-gate  * Returns:
12120Sstevel@tonic-gate  *	IBT_SUCCESS
12130Sstevel@tonic-gate  * Description:
12140Sstevel@tonic-gate  *	Resize the SendQ/RecvQ sizes of a channel. Can only be called on
12150Sstevel@tonic-gate  *	a previously opened channel.
12160Sstevel@tonic-gate  */
12170Sstevel@tonic-gate ibt_status_t
ibt_resize_queues(ibt_channel_hdl_t chan,ibt_qflags_t flags,ibt_queue_sizes_t * request_sz,ibt_queue_sizes_t * actual_sz)12180Sstevel@tonic-gate ibt_resize_queues(ibt_channel_hdl_t chan, ibt_qflags_t flags,
12190Sstevel@tonic-gate     ibt_queue_sizes_t *request_sz, ibt_queue_sizes_t *actual_sz)
12200Sstevel@tonic-gate {
12210Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags = IBT_CEP_SET_STATE;
12220Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
12230Sstevel@tonic-gate 	ibt_status_t		retval;
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_resize_queues(%p, 0x%X, %p, %p)",
12260Sstevel@tonic-gate 	    chan, flags, request_sz, actual_sz);
12270Sstevel@tonic-gate 
12280Sstevel@tonic-gate 	if ((flags & (IBT_SEND_Q | IBT_RECV_Q)) == 0)  {
12290Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
12300Sstevel@tonic-gate 		    "Flags <0x%X> not set", flags);
12310Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
12320Sstevel@tonic-gate 	}
12330Sstevel@tonic-gate 
12340Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate 	modify_attr.qp_current_state = chan->ch_current_state;
12370Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
12380Sstevel@tonic-gate 	modify_attr.qp_state = chan->ch_current_state;
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 	if (flags & IBT_SEND_Q) {
12410Sstevel@tonic-gate 		modify_attr.qp_sq_sz = request_sz->qs_sq;
12420Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_SQ_SIZE;
12430Sstevel@tonic-gate 	}
12440Sstevel@tonic-gate 
12450Sstevel@tonic-gate 	if (flags & IBT_RECV_Q) {
12460Sstevel@tonic-gate 		modify_attr.qp_rq_sz = request_sz->qs_rq;
12470Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_RQ_SIZE;
12480Sstevel@tonic-gate 	}
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, actual_sz);
12510Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
12520Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
12530Sstevel@tonic-gate 		    "failed on QP %p: %d", chan, retval);
12540Sstevel@tonic-gate 	}
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 	return (retval);
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate /*
12610Sstevel@tonic-gate  * Function:
12620Sstevel@tonic-gate  *	ibt_query_queues
12630Sstevel@tonic-gate  * Input:
12640Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
12650Sstevel@tonic-gate  * Output:
12660Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
12670Sstevel@tonic-gate  * Returns:
12680Sstevel@tonic-gate  *	IBT_SUCCESS
12690Sstevel@tonic-gate  * Description:
12700Sstevel@tonic-gate  *	Query the SendQ/RecvQ sizes of a channel.
12710Sstevel@tonic-gate  */
12720Sstevel@tonic-gate ibt_status_t
ibt_query_queues(ibt_channel_hdl_t chan,ibt_queue_sizes_t * actual_sz)12730Sstevel@tonic-gate ibt_query_queues(ibt_channel_hdl_t chan, ibt_queue_sizes_t *actual_sz)
12740Sstevel@tonic-gate {
12750Sstevel@tonic-gate 	ibt_status_t		retval;
12760Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_query_attr;
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_queues(%p)", chan);
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate 	/* Perform Query QP and retrieve QP sizes. */
12810Sstevel@tonic-gate 	retval = ibt_query_qp(chan, &qp_query_attr);
12820Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
12830Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_queues: "
12840Sstevel@tonic-gate 		    "ibt_query_qp failed: qp %p: %d", chan, retval);
12850Sstevel@tonic-gate 		return (retval);
12860Sstevel@tonic-gate 	}
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
12890Sstevel@tonic-gate 	    actual_sz->qs_sq))
12900Sstevel@tonic-gate 	actual_sz->qs_sq = qp_query_attr.qp_info.qp_sq_sz;
12910Sstevel@tonic-gate 	actual_sz->qs_rq = qp_query_attr.qp_info.qp_rq_sz;
12920Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
12930Sstevel@tonic-gate 	    actual_sz->qs_sq))
12940Sstevel@tonic-gate 	chan->ch_current_state = qp_query_attr.qp_info.qp_state;
12950Sstevel@tonic-gate 
12960Sstevel@tonic-gate 	return (retval);
12970Sstevel@tonic-gate }
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate 
13000Sstevel@tonic-gate /*
13010Sstevel@tonic-gate  * Function:
13020Sstevel@tonic-gate  *	ibt_modify_rdma
13030Sstevel@tonic-gate  * Input:
13040Sstevel@tonic-gate  *	rc_chan		A previously allocated channel handle.
13050Sstevel@tonic-gate  *
13060Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
13070Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_R	Enable/Disable RDMA RD
13080Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_W	Enable/Disable RDMA WR
13090Sstevel@tonic-gate  *			IBT_CEP_SET_ATOMIC	Enable/Disable Atomics
13100Sstevel@tonic-gate  *
13110Sstevel@tonic-gate  *	flags		Channel End Point (CEP) Disable Flags (0 => enable).
13120Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_RD	Disable incoming RDMA RD's
13130Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_WR	Disable incoming RDMA WR's
13140Sstevel@tonic-gate  *			IBT_CEP_NO_ATOMIC	Disable incoming Atomics.
13150Sstevel@tonic-gate  * Output:
13160Sstevel@tonic-gate  *	none.
13170Sstevel@tonic-gate  * Returns:
13180Sstevel@tonic-gate  *	IBT_SUCCESS
13190Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
13200Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
13210Sstevel@tonic-gate  *	IBT_CHAN_ATOMICS_NOT_SUPPORTED
13220Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
13230Sstevel@tonic-gate  * Description:
13240Sstevel@tonic-gate  *	Enable/disable RDMA operations. To enable an operation clear the
13250Sstevel@tonic-gate  *	"disable" flag. Can call this function when the channel is in
13260Sstevel@tonic-gate  *	INIT, RTS or SQD states. If called in any other state
13270Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID is returned. When the operation completes the
13280Sstevel@tonic-gate  *	channel state is left unchanged.
13290Sstevel@tonic-gate  */
13300Sstevel@tonic-gate ibt_status_t
ibt_modify_rdma(ibt_channel_hdl_t rc_chan,ibt_cep_modify_flags_t modify_flags,ibt_cep_flags_t flags)13310Sstevel@tonic-gate ibt_modify_rdma(ibt_channel_hdl_t rc_chan,
13320Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, ibt_cep_flags_t flags)
13330Sstevel@tonic-gate {
13340Sstevel@tonic-gate 	ibt_status_t		retval;
13350Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_rdma(%p, 0x%x, 0x%x)",
13380Sstevel@tonic-gate 	    rc_chan, modify_flags, flags);
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
13410Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
13420Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
13430Sstevel@tonic-gate 		    rc_chan->ch_qp.qp_type);
13440Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
13450Sstevel@tonic-gate 	}
13460Sstevel@tonic-gate 
13470Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate 	/*
13500Sstevel@tonic-gate 	 * Can only call this function when the channel in INIT, RTS or SQD
13510Sstevel@tonic-gate 	 * states.
13520Sstevel@tonic-gate 	 */
13530Sstevel@tonic-gate 	if ((rc_chan->ch_current_state != IBT_STATE_INIT) &&
13540Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_RTS) &&
13550Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_SQD)) {
13560Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: Invalid Channel "
13570Sstevel@tonic-gate 		    "state: 0x%X", rc_chan->ch_current_state);
13580Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
13590Sstevel@tonic-gate 	}
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate 	modify_attr.qp_state = modify_attr.qp_current_state =
13620Sstevel@tonic-gate 	    rc_chan->ch_current_state;
13630Sstevel@tonic-gate 	modify_attr.qp_trans = rc_chan->ch_qp.qp_type;
13640Sstevel@tonic-gate 	modify_attr.qp_flags = flags;
13650Sstevel@tonic-gate 
13660Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
13670Sstevel@tonic-gate 	    IBT_CEP_SET_ATOMIC);
13680Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, modify_flags, &modify_attr, NULL);
13710Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
13720Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
13730Sstevel@tonic-gate 		    "failed on chan %p: %d", rc_chan, retval);
13740Sstevel@tonic-gate 	}
13750Sstevel@tonic-gate 	return (retval);
13760Sstevel@tonic-gate }
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate 
13790Sstevel@tonic-gate /*
13800Sstevel@tonic-gate  * Function:
13810Sstevel@tonic-gate  *	ibt_set_rdma_resource
13820Sstevel@tonic-gate  * Input:
13830Sstevel@tonic-gate  *	chan		A previously allocated RC channel handle.
13840Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
13850Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_OUT	Initiator depth (rdma_ra_out)
13860Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_IN	Responder Resources
13870Sstevel@tonic-gate  *						(rdma_ra_in)
13880Sstevel@tonic-gate  *	rdma_ra_out	Outgoing RDMA Reads/Atomics
13890Sstevel@tonic-gate  *	rdma_ra_in	Incoming RDMA Reads/Atomics
13900Sstevel@tonic-gate  * Output:
13910Sstevel@tonic-gate  *	none.
13920Sstevel@tonic-gate  * Returns:
13930Sstevel@tonic-gate  *	IBT_SUCCESS
13940Sstevel@tonic-gate  * Description:
13950Sstevel@tonic-gate  *	Change the number of resources to be used for incoming and outgoing
13960Sstevel@tonic-gate  *	RDMA reads & Atomics. Can only be called on a previously opened
13970Sstevel@tonic-gate  *	RC channel.  Can only be called on a paused channel, and this will
13980Sstevel@tonic-gate  *	un-pause that channel.
13990Sstevel@tonic-gate  */
14000Sstevel@tonic-gate ibt_status_t
ibt_set_rdma_resource(ibt_channel_hdl_t chan,ibt_cep_modify_flags_t modify_flags,uint8_t rdma_ra_out,uint8_t resp_rdma_ra_out)14010Sstevel@tonic-gate ibt_set_rdma_resource(ibt_channel_hdl_t chan,
14020Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, uint8_t rdma_ra_out,
14030Sstevel@tonic-gate     uint8_t resp_rdma_ra_out)
14040Sstevel@tonic-gate {
14050Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
14060Sstevel@tonic-gate 	ibt_status_t		retval;
14070Sstevel@tonic-gate 
14080Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_set_rdma_resource(%p, 0x%x, %d, %d)",
14090Sstevel@tonic-gate 	    chan, modify_flags, rdma_ra_out, resp_rdma_ra_out);
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
14120Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
14130Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
14140Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
14150Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
14160Sstevel@tonic-gate 	}
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
14190Sstevel@tonic-gate 
14200Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
14210Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
14220Sstevel@tonic-gate 
14230Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_out = rdma_ra_out;
14240Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_in = resp_rdma_ra_out;
14250Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN);
14260Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
14270Sstevel@tonic-gate 
14280Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
14290Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
14300Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
14310Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
14320Sstevel@tonic-gate 	}
14330Sstevel@tonic-gate 	return (retval);
14340Sstevel@tonic-gate }
14350Sstevel@tonic-gate 
14360Sstevel@tonic-gate 
14370Sstevel@tonic-gate /*
14380Sstevel@tonic-gate  * Function:
14390Sstevel@tonic-gate  *	ibt_change_port
14400Sstevel@tonic-gate  * Input:
14410Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
14420Sstevel@tonic-gate  *	port_num	New HCA port.
14430Sstevel@tonic-gate  * Output:
14440Sstevel@tonic-gate  *	none.
14450Sstevel@tonic-gate  * Returns:
14460Sstevel@tonic-gate  *	IBT_SUCCESS
14470Sstevel@tonic-gate  * Description:
14480Sstevel@tonic-gate  *	Change the primary physical port of a channel. (This is done only if
14490Sstevel@tonic-gate  *	HCA supports this capability).
14500Sstevel@tonic-gate  */
14510Sstevel@tonic-gate ibt_status_t
ibt_change_port(ibt_channel_hdl_t chan,uint8_t port_num)14520Sstevel@tonic-gate ibt_change_port(ibt_channel_hdl_t chan, uint8_t port_num)
14530Sstevel@tonic-gate {
14540Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
14550Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
14560Sstevel@tonic-gate 	ibt_status_t		retval;
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_change_port(%p, %d)", chan, port_num);
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
14610Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
14620Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
14630Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
14640Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
14650Sstevel@tonic-gate 	}
14660Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
14670Sstevel@tonic-gate 
14680Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
14690Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
14700Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = port_num;
14710Sstevel@tonic-gate 
14720Sstevel@tonic-gate 	modify_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
14750Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
14760Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
14770Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
14780Sstevel@tonic-gate 	}
14790Sstevel@tonic-gate 	return (retval);
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate void
ibtl_init_cep_states(void)14840Sstevel@tonic-gate ibtl_init_cep_states(void)
14850Sstevel@tonic-gate {
14860Sstevel@tonic-gate 	int	index;
14870Sstevel@tonic-gate 	int	ibt_nstate_inits;
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_init_cep_states()");
14900Sstevel@tonic-gate 
14910Sstevel@tonic-gate 	ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) /
14920Sstevel@tonic-gate 	    sizeof (ibt_cep_next_state_inits[0]);
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate 	/*
14950Sstevel@tonic-gate 	 * Initialize CEP next state table, using an indirect lookup table so
14960Sstevel@tonic-gate 	 * that this code isn't dependent on the ibt_cep_state_t enum values.
14970Sstevel@tonic-gate 	 */
14980Sstevel@tonic-gate 	for (index = 0; index < ibt_nstate_inits; index++) {
14990Sstevel@tonic-gate 		ibt_cep_state_t	state;
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 		state = ibt_cep_next_state_inits[index].current_state;
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate 		ibt_cep_next_state[state].next_state =
15040Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].next_state;
15050Sstevel@tonic-gate 
15060Sstevel@tonic-gate 		ibt_cep_next_state[state].modify_flags =
15070Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].modify_flags;
15080Sstevel@tonic-gate 	}
15090Sstevel@tonic-gate }
1510