xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_qp.c (revision 934f0bcc)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*934f0bccShiremath  * Common Development and Distribution License (the "License").
6*934f0bccShiremath  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*934f0bccShiremath  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
297c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_cm.h>
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * ibtl_qp.c
337c478bd9Sstevel@tonic-gate  *	These routines implement (most of) the verbs related to
347c478bd9Sstevel@tonic-gate  *	Queue Pairs.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /* Globals. */
387c478bd9Sstevel@tonic-gate static char ibtf_qp[] = "ibtl";
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /* This table indirectly initializes the ibt_cep_next_state[] table. */
417c478bd9Sstevel@tonic-gate typedef struct ibt_cep_next_state_s {
427c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		next_state;
437c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
447c478bd9Sstevel@tonic-gate } ibt_cep_next_state_t;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate struct	{
477c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		current_state;
487c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		next_state;
497c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
507c478bd9Sstevel@tonic-gate } ibt_cep_next_state_inits[] = {
517c478bd9Sstevel@tonic-gate 	{ IBT_STATE_RESET, IBT_STATE_INIT, IBT_CEP_SET_RESET_INIT},
527c478bd9Sstevel@tonic-gate 	{ IBT_STATE_INIT, IBT_STATE_RTR, IBT_CEP_SET_INIT_RTR},
537c478bd9Sstevel@tonic-gate 	{ IBT_STATE_RTR, IBT_STATE_RTS, IBT_CEP_SET_RTR_RTS}
547c478bd9Sstevel@tonic-gate };
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate ibt_cep_next_state_t ibt_cep_next_state[IBT_STATE_NUM];
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique", ibt_cep_next_state))
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /* The following data and functions can increase system stability. */
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate int ibtl_qp_calls_curr;
637c478bd9Sstevel@tonic-gate int ibtl_qp_calls_max = 128;	/* limit on # of simultaneous QP verb calls */
647c478bd9Sstevel@tonic-gate kmutex_t ibtl_qp_mutex;
657c478bd9Sstevel@tonic-gate kcondvar_t ibtl_qp_cv;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate void
687c478bd9Sstevel@tonic-gate ibtl_qp_flow_control_enter(void)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_qp_mutex);
717c478bd9Sstevel@tonic-gate 	while (ibtl_qp_calls_curr >= ibtl_qp_calls_max) {
727c478bd9Sstevel@tonic-gate 		cv_wait(&ibtl_qp_cv, &ibtl_qp_mutex);
737c478bd9Sstevel@tonic-gate 	}
747c478bd9Sstevel@tonic-gate 	++ibtl_qp_calls_curr;
757c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_qp_mutex);
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate void
797c478bd9Sstevel@tonic-gate ibtl_qp_flow_control_exit(void)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_qp_mutex);
827c478bd9Sstevel@tonic-gate 	cv_signal(&ibtl_qp_cv);
837c478bd9Sstevel@tonic-gate 	--ibtl_qp_calls_curr;
847c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_qp_mutex);
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate  * Function:
897c478bd9Sstevel@tonic-gate  *	ibt_alloc_qp
907c478bd9Sstevel@tonic-gate  * Input:
917c478bd9Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
927c478bd9Sstevel@tonic-gate  *	type		Specifies the type of QP to alloc in ibt_alloc_qp()
937c478bd9Sstevel@tonic-gate  *	qp_attrp	Specifies the ibt_qp_alloc_attr_t that are needed to
947c478bd9Sstevel@tonic-gate  *			allocate a QP and transition it to the RTS state for
957c478bd9Sstevel@tonic-gate  *			UDs and INIT state for all other QPs.
967c478bd9Sstevel@tonic-gate  * Output:
977c478bd9Sstevel@tonic-gate  *	queue_sizes_p	Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
987c478bd9Sstevel@tonic-gate  *			WR SGL elements.
997c478bd9Sstevel@tonic-gate  *	qpn_p		Returned QP Number of the allocated QP.
1007c478bd9Sstevel@tonic-gate  *	ibt_qp_p	The ibt_qp_hdl_t of the allocated QP.
1017c478bd9Sstevel@tonic-gate  * Returns:
1027c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1037c478bd9Sstevel@tonic-gate  * Description:
1047c478bd9Sstevel@tonic-gate  *	Allocate a QP with specified attributes.
1057c478bd9Sstevel@tonic-gate  */
1067c478bd9Sstevel@tonic-gate ibt_status_t
1077c478bd9Sstevel@tonic-gate ibt_alloc_qp(ibt_hca_hdl_t hca_hdl, ibt_qp_type_t type,
1087c478bd9Sstevel@tonic-gate     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
1097c478bd9Sstevel@tonic-gate     ib_qpn_t *qpn_p, ibt_qp_hdl_t *ibt_qp_p)
1107c478bd9Sstevel@tonic-gate {
1117c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1127c478bd9Sstevel@tonic-gate 	ibtl_channel_t		*chanp;
1137c478bd9Sstevel@tonic-gate 	ibt_tran_srv_t		qp_type;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_qp(%p, %d, %p, %p, %p, %p) ",
1167c478bd9Sstevel@tonic-gate 	    hca_hdl, type, qp_attrp, queue_sizes_p, qpn_p, ibt_qp_p);
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	switch (type) {
1197c478bd9Sstevel@tonic-gate 	case IBT_UD_RQP:
1207c478bd9Sstevel@tonic-gate 		qp_type = IBT_UD_SRV;
1217c478bd9Sstevel@tonic-gate 		break;
1227c478bd9Sstevel@tonic-gate 	case IBT_RC_RQP:
1237c478bd9Sstevel@tonic-gate 		qp_type = IBT_RC_SRV;
1247c478bd9Sstevel@tonic-gate 		break;
1257c478bd9Sstevel@tonic-gate 	case IBT_UC_RQP:
1267c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Unreliable Connected "
1277c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
1287c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1297c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
1307c478bd9Sstevel@tonic-gate 	case IBT_RD_RQP:
1317c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Reliable Datagram "
1327c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
1337c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1347c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
1357c478bd9Sstevel@tonic-gate 	default:
1367c478bd9Sstevel@tonic-gate 		/* shouldn't happen ILLEGAL Type */
1377c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Illegal Transport Type "
1387c478bd9Sstevel@tonic-gate 		    "%d", type);
1397c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1407c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/* Get CI CQ handles */
1447c478bd9Sstevel@tonic-gate 	if ((qp_attrp->qp_scq_hdl == NULL) || (qp_attrp->qp_rcq_hdl == NULL)) {
1457c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Invalid CQ Handle");
1467c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1477c478bd9Sstevel@tonic-gate 		return (IBT_CQ_HDL_INVALID);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
1507c478bd9Sstevel@tonic-gate 	qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	if ((qp_attrp->qp_alloc_flags & IBT_QP_USES_SRQ) &&
1537c478bd9Sstevel@tonic-gate 	    (qp_attrp->qp_srq_hdl != NULL))
1547c478bd9Sstevel@tonic-gate 		qp_attrp->qp_ibc_srq_hdl =
1557c478bd9Sstevel@tonic-gate 		    qp_attrp->qp_srq_hdl->srq_ibc_srq_hdl;
1567c478bd9Sstevel@tonic-gate 	else
1577c478bd9Sstevel@tonic-gate 		qp_attrp->qp_ibc_srq_hdl = NULL;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	/* Allocate Channel structure */
1607c478bd9Sstevel@tonic-gate 	chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
1637c478bd9Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp)(
1647c478bd9Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), &chanp->ch_qp, type, qp_attrp,
1657c478bd9Sstevel@tonic-gate 	    queue_sizes_p, qpn_p, &chanp->ch_qp.qp_ibc_qp_hdl);
1667c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
1677c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1687c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: "
1697c478bd9Sstevel@tonic-gate 		    "Failed to allocate QP: %d", retval);
1707c478bd9Sstevel@tonic-gate 		kmem_free(chanp, sizeof (*chanp));
1717c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1727c478bd9Sstevel@tonic-gate 		return (retval);
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	/* Initialize the internal QP struct. */
1767c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_type = qp_type;
1777c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_hca = hca_hdl;
1787c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
1797c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
1807c478bd9Sstevel@tonic-gate 	chanp->ch_current_state = IBT_STATE_RESET;
1817c478bd9Sstevel@tonic-gate 	mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
1827c478bd9Sstevel@tonic-gate 	cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	mutex_enter(&hca_hdl->ha_mutex);
1857c478bd9Sstevel@tonic-gate 	hca_hdl->ha_qp_cnt++;
1867c478bd9Sstevel@tonic-gate 	mutex_exit(&hca_hdl->ha_mutex);
1877c478bd9Sstevel@tonic-gate 
188*934f0bccShiremath 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_qp: SUCCESS: qp %p owned by '%s'",
1897c478bd9Sstevel@tonic-gate 	    chanp, hca_hdl->ha_clnt_devp->clnt_name);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	*ibt_qp_p = chanp;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	return (retval);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  * Function:
1997c478bd9Sstevel@tonic-gate  *	ibt_initialize_qp
2007c478bd9Sstevel@tonic-gate  * Input:
2017c478bd9Sstevel@tonic-gate  *	ibt_qp		The previously allocated IBT QP Handle.
2027c478bd9Sstevel@tonic-gate  *	modify_attrp	Specifies the QP Modify attributes that to transition
2037c478bd9Sstevel@tonic-gate  *			the QP to the RTS state for UDs (including special QPs)
2047c478bd9Sstevel@tonic-gate  *			and INIT state for all other QPs.
2057c478bd9Sstevel@tonic-gate  * Output:
2067c478bd9Sstevel@tonic-gate  *	none.
2077c478bd9Sstevel@tonic-gate  * Returns:
2087c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
2097c478bd9Sstevel@tonic-gate  * Description:
2107c478bd9Sstevel@tonic-gate  *	Transition the QP to the RTS state for UDs (including special QPs)
2117c478bd9Sstevel@tonic-gate  *	and INIT state for all other QPs.
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate ibt_status_t
2147c478bd9Sstevel@tonic-gate ibt_initialize_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_info_t *modify_attrp)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
2177c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		state;
2187c478bd9Sstevel@tonic-gate 	ibc_hca_hdl_t		ibc_hca_hdl = IBTL_CHAN2CIHCA(ibt_qp);
2197c478bd9Sstevel@tonic-gate 	ibc_qp_hdl_t		ibc_qp_hdl = IBTL_CHAN2CIQP(ibt_qp);
2207c478bd9Sstevel@tonic-gate 	ibc_operations_t	*hca_ops_p = IBTL_CHAN2CIHCAOPS_P(ibt_qp);
2217c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp(%p, %p)",
2247c478bd9Sstevel@tonic-gate 	    ibt_qp, modify_attrp);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	/*
2277c478bd9Sstevel@tonic-gate 	 * Validate the QP Type from the channel with QP Type from the
2287c478bd9Sstevel@tonic-gate 	 * modify attribute struct.
2297c478bd9Sstevel@tonic-gate 	 */
2307c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type != modify_attrp->qp_trans) {
2317c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
2327c478bd9Sstevel@tonic-gate 		    "QP Type mismatch: Chan QP Type<%d>, Modify QP Type<%d>",
2337c478bd9Sstevel@tonic-gate 		    ibt_qp->ch_qp.qp_type, modify_attrp->qp_trans);
2347c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_current_state != IBT_STATE_RESET) {
2377c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: "
2387c478bd9Sstevel@tonic-gate 		    "QP needs to be in RESET state: Chan QP State<%d>",
2397c478bd9Sstevel@tonic-gate 		    ibt_qp->ch_current_state);
2407c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	/*
2447c478bd9Sstevel@tonic-gate 	 * Initialize the QP to the RTS state for UDs
2457c478bd9Sstevel@tonic-gate 	 * and INIT state for all other QPs.
2467c478bd9Sstevel@tonic-gate 	 */
2477c478bd9Sstevel@tonic-gate 	switch (modify_attrp->qp_trans) {
2487c478bd9Sstevel@tonic-gate 	case IBT_UD_SRV:
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 		/*
2517c478bd9Sstevel@tonic-gate 		 * Bring the QP to the RTS state.
2527c478bd9Sstevel@tonic-gate 		 */
2537c478bd9Sstevel@tonic-gate 		state = IBT_STATE_RESET;
2547c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
2557c478bd9Sstevel@tonic-gate 		do {
2567c478bd9Sstevel@tonic-gate 			modify_attrp->qp_current_state = state;
2577c478bd9Sstevel@tonic-gate 			modify_flags = ibt_cep_next_state[state].modify_flags;
2587c478bd9Sstevel@tonic-gate 			modify_attrp->qp_state = state =
2597c478bd9Sstevel@tonic-gate 			    ibt_cep_next_state[state].next_state;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(ibtf_qp, "ibt_initialize_qp: "
2627c478bd9Sstevel@tonic-gate 			    "modifying qp state to 0x%x", state);
2637c478bd9Sstevel@tonic-gate 			status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl,
2647c478bd9Sstevel@tonic-gate 			    ibc_qp_hdl, modify_flags, modify_attrp, NULL);
2657c478bd9Sstevel@tonic-gate 		} while ((state != IBT_STATE_RTS) && (status == IBT_SUCCESS));
2667c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_exit();
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		if (status == IBT_SUCCESS) {
2697c478bd9Sstevel@tonic-gate 			ibt_qp->ch_current_state = state;
2707c478bd9Sstevel@tonic-gate 			ibt_qp->ch_transport.ud.ud_port_num =
2717c478bd9Sstevel@tonic-gate 			    modify_attrp->qp_transport.ud.ud_port;
2727c478bd9Sstevel@tonic-gate 			ibt_qp->ch_transport.ud.ud_qkey =
2737c478bd9Sstevel@tonic-gate 			    modify_attrp->qp_transport.ud.ud_qkey;
2747c478bd9Sstevel@tonic-gate 		}
2757c478bd9Sstevel@tonic-gate 		break;
2767c478bd9Sstevel@tonic-gate 	case IBT_UC_SRV:
2777c478bd9Sstevel@tonic-gate 	case IBT_RD_SRV:
2787c478bd9Sstevel@tonic-gate 	case IBT_RC_SRV:
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 		/*
2817c478bd9Sstevel@tonic-gate 		 * Bring the QP to the INIT state.
2827c478bd9Sstevel@tonic-gate 		 */
2837c478bd9Sstevel@tonic-gate 		modify_attrp->qp_state = IBT_STATE_INIT;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
2867c478bd9Sstevel@tonic-gate 		status = (hca_ops_p->ibc_modify_qp)(ibc_hca_hdl, ibc_qp_hdl,
2877c478bd9Sstevel@tonic-gate 		    IBT_CEP_SET_RESET_INIT, modify_attrp, NULL);
2887c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_exit();
2897c478bd9Sstevel@tonic-gate 		if (status == IBT_SUCCESS)
2907c478bd9Sstevel@tonic-gate 			ibt_qp->ch_current_state = IBT_STATE_INIT;
2917c478bd9Sstevel@tonic-gate 		break;
2927c478bd9Sstevel@tonic-gate 	default:
2937c478bd9Sstevel@tonic-gate 		/* shouldn't happen ILLEGAL Type */
2947c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_initialize_qp: Illegal Type %d",
2957c478bd9Sstevel@tonic-gate 		    modify_attrp->qp_trans);
2967c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
2977c478bd9Sstevel@tonic-gate 	} /* End switch */
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	return (status);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate /*
3047c478bd9Sstevel@tonic-gate  * Function:
3057c478bd9Sstevel@tonic-gate  *	ibt_alloc_special_qp
3067c478bd9Sstevel@tonic-gate  * Input:
3077c478bd9Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
3087c478bd9Sstevel@tonic-gate  *	type		Specifies the type of Special QP to be allocated.
3097c478bd9Sstevel@tonic-gate  *	qp_attrp	Specifies the ibt_qp_alloc_attr_t that are needed to
3107c478bd9Sstevel@tonic-gate  *			allocate a special QP.
3117c478bd9Sstevel@tonic-gate  * Output:
3127c478bd9Sstevel@tonic-gate  *	queue_sizes_p	Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
3137c478bd9Sstevel@tonic-gate  *			WR SGL elements.
3147c478bd9Sstevel@tonic-gate  *	qpn_p		Returned qpn of the allocated QP.
3157c478bd9Sstevel@tonic-gate  *	ibt_qp_p	The ibt_qp_hdl_t of the allocated QP.
3167c478bd9Sstevel@tonic-gate  * Returns:
3177c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
3187c478bd9Sstevel@tonic-gate  * Description:
3197c478bd9Sstevel@tonic-gate  *	Allocate a special QP with specified attributes.
3207c478bd9Sstevel@tonic-gate  */
3217c478bd9Sstevel@tonic-gate ibt_status_t
3227c478bd9Sstevel@tonic-gate ibt_alloc_special_qp(ibt_hca_hdl_t hca_hdl, uint8_t port, ibt_sqp_type_t type,
3237c478bd9Sstevel@tonic-gate     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
3247c478bd9Sstevel@tonic-gate     ibt_qp_hdl_t *ibt_qp_p)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 	ibt_qp_hdl_t	chanp;
3277c478bd9Sstevel@tonic-gate 	ibt_status_t	retval;
3287c478bd9Sstevel@tonic-gate 	ibt_tran_srv_t	sqp_type;
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_special_qp(%p, %d, %x, %p, %p, %p)",
3317c478bd9Sstevel@tonic-gate 	    hca_hdl, port, type, qp_attrp, queue_sizes_p, ibt_qp_p);
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	switch (type) {
3347c478bd9Sstevel@tonic-gate 	case IBT_SMI_SQP:
3357c478bd9Sstevel@tonic-gate 	case IBT_GSI_SQP:
3367c478bd9Sstevel@tonic-gate 		sqp_type = IBT_UD_SRV;
3377c478bd9Sstevel@tonic-gate 		break;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	case IBT_RAWIP_SQP:
3407c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw IP "
3417c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
3427c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
3437c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	case IBT_RAWETHER_SQP:
3467c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: Raw Ethernet "
3477c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
3487c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
3497c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	default:
3527c478bd9Sstevel@tonic-gate 		/* Shouldn't happen */
3537c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
3547c478bd9Sstevel@tonic-gate 		    "Illegal Type 0x%x", type);
3557c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
3567c478bd9Sstevel@tonic-gate 		return (IBT_QP_SPECIAL_TYPE_INVALID);
3577c478bd9Sstevel@tonic-gate 	}
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	/* convert the CQ handles for the CI */
3607c478bd9Sstevel@tonic-gate 	qp_attrp->qp_ibc_scq_hdl = qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
3617c478bd9Sstevel@tonic-gate 	qp_attrp->qp_ibc_rcq_hdl = qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	/* Allocate Channel structure */
3647c478bd9Sstevel@tonic-gate 	chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
3677c478bd9Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_special_qp)(
3687c478bd9Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), port, &chanp->ch_qp, type, qp_attrp,
3697c478bd9Sstevel@tonic-gate 	    queue_sizes_p, &chanp->ch_qp.qp_ibc_qp_hdl);
3707c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
3717c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
3727c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_special_qp: "
3737c478bd9Sstevel@tonic-gate 		    "Failed to allocate Special QP: %d", retval);
3747c478bd9Sstevel@tonic-gate 		kmem_free(chanp, sizeof (*chanp));
3757c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
3767c478bd9Sstevel@tonic-gate 		return (retval);
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	/* Initialize the internal QP struct. */
3807c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_type = sqp_type;
3817c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_hca = hca_hdl;
3827c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
3837c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
3847c478bd9Sstevel@tonic-gate 	chanp->ch_current_state = IBT_STATE_RESET;
3857c478bd9Sstevel@tonic-gate 	mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
3867c478bd9Sstevel@tonic-gate 	cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	mutex_enter(&hca_hdl->ha_mutex);
3897c478bd9Sstevel@tonic-gate 	hca_hdl->ha_qp_cnt++;
3907c478bd9Sstevel@tonic-gate 	mutex_exit(&hca_hdl->ha_mutex);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	*ibt_qp_p = chanp;
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	return (retval);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate /*
3997c478bd9Sstevel@tonic-gate  * Function:
4007c478bd9Sstevel@tonic-gate  *	ibt_flush_qp
4017c478bd9Sstevel@tonic-gate  * Input:
4027c478bd9Sstevel@tonic-gate  *	ibtl_qp		Handle for QP that needs to be flushed.
4037c478bd9Sstevel@tonic-gate  * Output:
4047c478bd9Sstevel@tonic-gate  *	none.
4057c478bd9Sstevel@tonic-gate  * Returns:
4067c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
4077c478bd9Sstevel@tonic-gate  *	IBT_QP_HDL_INVALID
4087c478bd9Sstevel@tonic-gate  * Description:
4097c478bd9Sstevel@tonic-gate  *	Put the QP into error state to flush out work requests.
4107c478bd9Sstevel@tonic-gate  */
4117c478bd9Sstevel@tonic-gate ibt_status_t
4127c478bd9Sstevel@tonic-gate ibt_flush_qp(ibt_qp_hdl_t ibt_qp)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
4157c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_flush_qp(%p)", ibt_qp);
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
4207c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
4217c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_transport.rc.rc_free_flags &
4227c478bd9Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
4237c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
4247c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp(%p): "
4257c478bd9Sstevel@tonic-gate 			    "called with a connected RC QP", ibt_qp);
4267c478bd9Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
4277c478bd9Sstevel@tonic-gate 		}
4287c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	/*
4347c478bd9Sstevel@tonic-gate 	 * Set the QP state to error to flush any uncompleted WRs.
4357c478bd9Sstevel@tonic-gate 	 */
4367c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_ERROR;
4377c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = ibt_qp->ch_qp.qp_type;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(ibt_qp, IBT_CEP_SET_STATE, &modify_attr, NULL);
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
4427c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp: "
4437c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
4447c478bd9Sstevel@tonic-gate 	}
4457c478bd9Sstevel@tonic-gate 	return (retval);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate /*
4507c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_open()
4517c478bd9Sstevel@tonic-gate  *
4527c478bd9Sstevel@tonic-gate  *	Inform IBTL that the connection has been established on this
4537c478bd9Sstevel@tonic-gate  *	channel so that a later call to ibtl_cm_chan_is_closed()
4547c478bd9Sstevel@tonic-gate  *	will be required to free the QPN used by this channel.
4557c478bd9Sstevel@tonic-gate  *
4567c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
4577c478bd9Sstevel@tonic-gate  */
4587c478bd9Sstevel@tonic-gate void
4597c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)
4607c478bd9Sstevel@tonic-gate {
4617c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_open(%p)", chan);
4627c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
4637c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
4647c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_transport.rc.rc_free_flags == 0);
4657c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTED;
4667c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate  * ibtl_cm_is_chan_closing()
4717c478bd9Sstevel@tonic-gate  *
4727c478bd9Sstevel@tonic-gate  *	Returns 1, if the connection that has been
4737c478bd9Sstevel@tonic-gate  *	started for this channel has moved to TIMEWAIT
4747c478bd9Sstevel@tonic-gate  *	If not, returns 0
4757c478bd9Sstevel@tonic-gate  *
4767c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
4777c478bd9Sstevel@tonic-gate  */
4787c478bd9Sstevel@tonic-gate int
4797c478bd9Sstevel@tonic-gate ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)
4807c478bd9Sstevel@tonic-gate {
4817c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closing(%p)", chan);
4827c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
4837c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
4847c478bd9Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSING) {
4857c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
4867c478bd9Sstevel@tonic-gate 		return (1);
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
4897c478bd9Sstevel@tonic-gate 	return (0);
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate /*
4937c478bd9Sstevel@tonic-gate  * ibtl_cm_is_chan_closed()
4947c478bd9Sstevel@tonic-gate  *
4957c478bd9Sstevel@tonic-gate  *	Returns 1, if the connection that has been
4967c478bd9Sstevel@tonic-gate  *	started for this channel has completed TIMEWAIT
4977c478bd9Sstevel@tonic-gate  *	If not, returns 0
4987c478bd9Sstevel@tonic-gate  *
4997c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5007c478bd9Sstevel@tonic-gate  */
5017c478bd9Sstevel@tonic-gate int
5027c478bd9Sstevel@tonic-gate ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closed(%p)", chan);
5057c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5067c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5077c478bd9Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSED) {
5087c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
5097c478bd9Sstevel@tonic-gate 		return (1);
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5127c478bd9Sstevel@tonic-gate 	return (0);
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate /*
5157c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_closing()
5167c478bd9Sstevel@tonic-gate  *
5177c478bd9Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
5187c478bd9Sstevel@tonic-gate  *	started for this channel so that the QP can be freed.
5197c478bd9Sstevel@tonic-gate  *
5207c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5217c478bd9Sstevel@tonic-gate  */
5227c478bd9Sstevel@tonic-gate void
5237c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)
5247c478bd9Sstevel@tonic-gate {
5257c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closing(%p)", chan);
5267c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5277c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5287c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_transport.rc.rc_free_flags == IBTL_RC_QP_CONNECTED);
5297c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSING;
5307c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_closed()
5347c478bd9Sstevel@tonic-gate  *
5357c478bd9Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
5367c478bd9Sstevel@tonic-gate  *	reached for this channel so that the QPN can be reused.
5377c478bd9Sstevel@tonic-gate  *
5387c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5397c478bd9Sstevel@tonic-gate  */
5407c478bd9Sstevel@tonic-gate void
5417c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)
5427c478bd9Sstevel@tonic-gate {
5437c478bd9Sstevel@tonic-gate 	ibt_status_t status;
5447c478bd9Sstevel@tonic-gate 	ibtl_hca_t *ibtl_hca = chan->ch_qp.qp_hca;
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closed(%p)", chan);
5477c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5487c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5497c478bd9Sstevel@tonic-gate 	ASSERT((chan->ch_transport.rc.rc_free_flags &
5507c478bd9Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
5517c478bd9Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING));
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTED;
5547c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSING;
5557c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSED;
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	ibtl_cm_set_chan_private(chan, NULL);
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	if ((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_FREED) == 0) {
5607c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
5617c478bd9Sstevel@tonic-gate 		return;
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5647c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
5657c478bd9Sstevel@tonic-gate 	if ((status = (IBTL_CHAN2CIHCAOPS_P(chan)->ibc_release_qpn)
5667c478bd9Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(chan), chan->ch_transport.rc.rc_qpn_hdl)) ==
5677c478bd9Sstevel@tonic-gate 	    IBT_SUCCESS) {
5687c478bd9Sstevel@tonic-gate 		/* effectively, this is kmem_free(chan); */
5697c478bd9Sstevel@tonic-gate 		ibtl_free_qp_async_check(&chan->ch_qp);
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 		/* decrement ha_qpn_cnt and check for close in progress */
5727c478bd9Sstevel@tonic-gate 		ibtl_close_hca_check(ibtl_hca);
5737c478bd9Sstevel@tonic-gate 	} else
574*934f0bccShiremath 		IBTF_DPRINTF_L2(ibtf_qp, "ibtl_cm_chan_is_closed: "
5757c478bd9Sstevel@tonic-gate 		    "ibc_release_qpn failed: status = %d\n", status);
5767c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate /*
5807c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_reused()
5817c478bd9Sstevel@tonic-gate  *
5827c478bd9Sstevel@tonic-gate  *	Inform IBTL that the channel is going to be re-used
5837c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5847c478bd9Sstevel@tonic-gate  */
5857c478bd9Sstevel@tonic-gate void
5867c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)
5877c478bd9Sstevel@tonic-gate {
5887c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_reused(%p)", chan);
5897c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5907c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5917c478bd9Sstevel@tonic-gate 	ASSERT(((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CONNECTED) !=
5927c478bd9Sstevel@tonic-gate 	    IBTL_RC_QP_CONNECTED));
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	/* channel is no longer in closed state, shall be re-used */
595*934f0bccShiremath 	chan->ch_transport.rc.rc_free_flags = 0;
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate /*
6027c478bd9Sstevel@tonic-gate  * Function:	ibt_free_qp()
6037c478bd9Sstevel@tonic-gate  *
6047c478bd9Sstevel@tonic-gate  * Input:	ibt_qp		Handle for Channel(QP) that needs to be freed.
6057c478bd9Sstevel@tonic-gate  *
6067c478bd9Sstevel@tonic-gate  * Output:	NONE.
6077c478bd9Sstevel@tonic-gate  *
6087c478bd9Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
6097c478bd9Sstevel@tonic-gate  *		IBT_QP_STATE_INVALID
6107c478bd9Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
6117c478bd9Sstevel@tonic-gate  *
6127c478bd9Sstevel@tonic-gate  * Description:
6137c478bd9Sstevel@tonic-gate  *		Free a previously allocated QP.
6147c478bd9Sstevel@tonic-gate  */
6157c478bd9Sstevel@tonic-gate ibt_status_t
6167c478bd9Sstevel@tonic-gate ibt_free_qp(ibt_qp_hdl_t ibt_qp)
6177c478bd9Sstevel@tonic-gate {
6187c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
6197c478bd9Sstevel@tonic-gate 	ibtl_hca_t		*ibtl_hca = ibt_qp->ch_qp.qp_hca;
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p)", ibt_qp);
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
6247c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
6257c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
6267c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_transport.rc.rc_free_flags &
6277c478bd9Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
6287c478bd9Sstevel@tonic-gate 			if ((ibt_qp->ch_transport.rc.rc_free_flags &
6297c478bd9Sstevel@tonic-gate 			    IBTL_RC_QP_CLOSING) == 0) {
6307c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
6317c478bd9Sstevel@tonic-gate 				    "need to call ibt_close_rc_channel");
6327c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_free_qp_mutex);
6337c478bd9Sstevel@tonic-gate 				ibtl_qp_flow_control_exit();
6347c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
6357c478bd9Sstevel@tonic-gate 			}
6367c478bd9Sstevel@tonic-gate 			ibt_qp->ch_transport.rc.rc_free_flags |=
6377c478bd9Sstevel@tonic-gate 			    IBTL_RC_QP_FREED;
6387c478bd9Sstevel@tonic-gate 			status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
6397c478bd9Sstevel@tonic-gate 			    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
6407c478bd9Sstevel@tonic-gate 			    IBC_FREE_QP_ONLY,
6417c478bd9Sstevel@tonic-gate 			    &ibt_qp->ch_transport.rc.rc_qpn_hdl);
6427c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
6437c478bd9Sstevel@tonic-gate 			ibtl_qp_flow_control_exit();
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 			if (status == IBT_SUCCESS) {
6467c478bd9Sstevel@tonic-gate 				mutex_enter(&ibtl_clnt_list_mutex);
6477c478bd9Sstevel@tonic-gate 				ibtl_hca->ha_qpn_cnt++;
6487c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_clnt_list_mutex);
6497c478bd9Sstevel@tonic-gate 				mutex_enter(&ibtl_hca->ha_mutex);
6507c478bd9Sstevel@tonic-gate 				ibtl_hca->ha_qp_cnt--;
6517c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_hca->ha_mutex);
652*934f0bccShiremath 				IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - "
6537c478bd9Sstevel@tonic-gate 				    "SUCCESS", ibt_qp);
6547c478bd9Sstevel@tonic-gate 			} else
6557c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
6567c478bd9Sstevel@tonic-gate 				    "ibc_free_qp failed: status = %d", status);
6577c478bd9Sstevel@tonic-gate 			return (status);
6587c478bd9Sstevel@tonic-gate 		}
6597c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
6607c478bd9Sstevel@tonic-gate 	} else
6617c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
6647c478bd9Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
6657c478bd9Sstevel@tonic-gate 	    IBC_FREE_QP_AND_QPN, NULL);
6667c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	if (status == IBT_SUCCESS) {
6697c478bd9Sstevel@tonic-gate 		/* effectively, this is kmem_free(ibt_qp); */
6707c478bd9Sstevel@tonic-gate 		ibtl_free_qp_async_check(&ibt_qp->ch_qp);
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_hca->ha_mutex);
6737c478bd9Sstevel@tonic-gate 		ibtl_hca->ha_qp_cnt--;
6747c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_hca->ha_mutex);
675*934f0bccShiremath 		IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - SUCCESS", ibt_qp);
6767c478bd9Sstevel@tonic-gate 	} else {
6777c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
6787c478bd9Sstevel@tonic-gate 		    "ibc_free_qp failed with error %d", status);
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	return (status);
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate /* helper function for ibt_query_qp */
6867c478bd9Sstevel@tonic-gate static void
6877c478bd9Sstevel@tonic-gate ibtl_fillin_sgid(ibt_cep_path_t *pathp, ibtl_hca_devinfo_t *hca_devp)
6887c478bd9Sstevel@tonic-gate {
6897c478bd9Sstevel@tonic-gate 	uint8_t port;
6907c478bd9Sstevel@tonic-gate 	uint32_t sgid_ix;
6917c478bd9Sstevel@tonic-gate 	ib_gid_t *sgidp;
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	port = pathp->cep_hca_port_num;
6947c478bd9Sstevel@tonic-gate 	sgid_ix = pathp->cep_adds_vect.av_sgid_ix;
6957c478bd9Sstevel@tonic-gate 	if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
6967c478bd9Sstevel@tonic-gate 	    sgid_ix >= IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
6977c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_prefix = 0;
6987c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_guid = 0;
6997c478bd9Sstevel@tonic-gate 	} else {
7007c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
7017c478bd9Sstevel@tonic-gate 		sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
7027c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid = sgidp[sgid_ix];
7037c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7047c478bd9Sstevel@tonic-gate 	}
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate /*
7097c478bd9Sstevel@tonic-gate  * Function:	ibt_query_qp
7107c478bd9Sstevel@tonic-gate  *
7117c478bd9Sstevel@tonic-gate  * Input:	ibt_qp 			- The IBT QP Handle.
7127c478bd9Sstevel@tonic-gate  *
7137c478bd9Sstevel@tonic-gate  * Output:	ibt_qp_query_attrp 	- Points to a ibt_qp_query_attr_t
7147c478bd9Sstevel@tonic-gate  *					  that on return contains all the
7157c478bd9Sstevel@tonic-gate  *					  attributes of the specified qp.
7167c478bd9Sstevel@tonic-gate  *
7177c478bd9Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
7187c478bd9Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
7197c478bd9Sstevel@tonic-gate  *
7207c478bd9Sstevel@tonic-gate  * Description:
7217c478bd9Sstevel@tonic-gate  *		Query QP attributes
7227c478bd9Sstevel@tonic-gate  *
7237c478bd9Sstevel@tonic-gate  */
7247c478bd9Sstevel@tonic-gate ibt_status_t
7257c478bd9Sstevel@tonic-gate ibt_query_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_query_attr_t *qp_query_attrp)
7267c478bd9Sstevel@tonic-gate {
7277c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
7287c478bd9Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
7297c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		*qp_infop;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_qp(%p, %p)",
7327c478bd9Sstevel@tonic-gate 	    ibt_qp, qp_query_attrp);
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
7357c478bd9Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_query_qp(
7367c478bd9Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), qp_query_attrp));
7377c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
7387c478bd9Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
7397c478bd9Sstevel@tonic-gate 		ibt_qp->ch_current_state = qp_query_attrp->qp_info.qp_state;
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 		/* need to fill in sgid from port and sgid_ix for RC and UC */
7427c478bd9Sstevel@tonic-gate 		hca_devp = ibt_qp->ch_qp.qp_hca->ha_hca_devp;
7437c478bd9Sstevel@tonic-gate 		qp_infop = &qp_query_attrp->qp_info;
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 		switch (qp_infop->qp_trans) {
7467c478bd9Sstevel@tonic-gate 		case IBT_RC_SRV:
7477c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_path,
7487c478bd9Sstevel@tonic-gate 			    hca_devp);
7497c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_alt_path,
7507c478bd9Sstevel@tonic-gate 			    hca_devp);
7517c478bd9Sstevel@tonic-gate 			break;
7527c478bd9Sstevel@tonic-gate 		case IBT_UC_SRV:
7537c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_path,
7547c478bd9Sstevel@tonic-gate 			    hca_devp);
7557c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_alt_path,
7567c478bd9Sstevel@tonic-gate 			    hca_devp);
7577c478bd9Sstevel@tonic-gate 			break;
7587c478bd9Sstevel@tonic-gate 		}
7597c478bd9Sstevel@tonic-gate 	} else {
7607c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_qp: "
7617c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
7627c478bd9Sstevel@tonic-gate 	}
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 	return (retval);
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate /*
7697c478bd9Sstevel@tonic-gate  * Function:
7707c478bd9Sstevel@tonic-gate  *	ibt_modify_qp
7717c478bd9Sstevel@tonic-gate  * Input:
7727c478bd9Sstevel@tonic-gate  *	ibt_qp		The IBT QP Handle.
7737c478bd9Sstevel@tonic-gate  *	flags		Specifies which attributes in ibt_qp_mod_attr_t
7747c478bd9Sstevel@tonic-gate  *			are to be modified.
7757c478bd9Sstevel@tonic-gate  *	qp_attrp	Points to an ibt_qp_mod_attr_t struct that contains all
7767c478bd9Sstevel@tonic-gate  *			the attributes of the specified QP that a client is
7777c478bd9Sstevel@tonic-gate  *			allowed to modify after a QP has been allocated
7787c478bd9Sstevel@tonic-gate  * Output:
7797c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual queue sizes.
7807c478bd9Sstevel@tonic-gate  * Returns:
7817c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
7827c478bd9Sstevel@tonic-gate  * Description:
7837c478bd9Sstevel@tonic-gate  *	Modify the attributes of an existing QP.
7847c478bd9Sstevel@tonic-gate  */
7857c478bd9Sstevel@tonic-gate ibt_status_t
7867c478bd9Sstevel@tonic-gate ibt_modify_qp(ibt_qp_hdl_t ibt_qp, ibt_cep_modify_flags_t flags,
7877c478bd9Sstevel@tonic-gate     ibt_qp_info_t *modify_attrp, ibt_queue_sizes_t *actual_sz)
7887c478bd9Sstevel@tonic-gate {
7897c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_qp(%p, %d, %p, %p)",
7927c478bd9Sstevel@tonic-gate 	    ibt_qp, flags, modify_attrp, actual_sz);
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
7957c478bd9Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_modify_qp)(
7967c478bd9Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), flags,
7977c478bd9Sstevel@tonic-gate 	    modify_attrp, actual_sz);
7987c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
7997c478bd9Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
8007c478bd9Sstevel@tonic-gate 		ibt_qp->ch_current_state = modify_attrp->qp_state;
8017c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_qp.qp_type == IBT_UD_SRV) {
8027c478bd9Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_PORT | IBT_CEP_SET_RESET_INIT))
8037c478bd9Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_port_num =
8047c478bd9Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_port;
8057c478bd9Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_QKEY | IBT_CEP_SET_RESET_INIT))
8067c478bd9Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_qkey =
8077c478bd9Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_qkey;
8087c478bd9Sstevel@tonic-gate 		}
8097c478bd9Sstevel@tonic-gate 	} else {
8107c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_qp: failed on chan %p: %d",
8117c478bd9Sstevel@tonic-gate 		    ibt_qp, retval);
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 		if (retval == IBT_CHAN_STATE_INVALID) {
8147c478bd9Sstevel@tonic-gate 			/* That means our cache had invalid QP state value. */
8157c478bd9Sstevel@tonic-gate 			ibt_qp_query_attr_t	qp_attr;
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 			/* Query the channel (QP) */
8187c478bd9Sstevel@tonic-gate 			if (ibt_query_qp(ibt_qp, &qp_attr) == IBT_SUCCESS)
8197c478bd9Sstevel@tonic-gate 				ibt_qp->ch_current_state =
8207c478bd9Sstevel@tonic-gate 				    qp_attr.qp_info.qp_state;
8217c478bd9Sstevel@tonic-gate 		}
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate 	return (retval);
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate /*
8287c478bd9Sstevel@tonic-gate  * Function:
8297c478bd9Sstevel@tonic-gate  *	ibt_migrate_path
8307c478bd9Sstevel@tonic-gate  * Input:
8317c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
8327c478bd9Sstevel@tonic-gate  * Output:
8337c478bd9Sstevel@tonic-gate  *	none.
8347c478bd9Sstevel@tonic-gate  * Returns:
8357c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS on Success else appropriate error.
8367c478bd9Sstevel@tonic-gate  * Description:
8377c478bd9Sstevel@tonic-gate  *	Force the CI to use the alternate path. The alternate path becomes
8387c478bd9Sstevel@tonic-gate  *	the primary path. A new alternate path should be loaded and enabled.
8397c478bd9Sstevel@tonic-gate  *	Assumes that the given channel is in RTS/SQD state
8407c478bd9Sstevel@tonic-gate  */
8417c478bd9Sstevel@tonic-gate ibt_status_t
8427c478bd9Sstevel@tonic-gate ibt_migrate_path(ibt_channel_hdl_t rc_chan)
8437c478bd9Sstevel@tonic-gate {
8447c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
8457c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		qp_info;
8467c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
8477c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	cep_flags;
8487c478bd9Sstevel@tonic-gate 	int			retries = 1;
8497c478bd9Sstevel@tonic-gate 
850*934f0bccShiremath 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_migrate_path: channel %p", rc_chan);
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
8537c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: "
8547c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel");
8557c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
8567c478bd9Sstevel@tonic-gate 	}
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_current_state != IBT_STATE_RTS &&
8597c478bd9Sstevel@tonic-gate 	    rc_chan->ch_current_state != IBT_STATE_SQD) {
8607c478bd9Sstevel@tonic-gate 		if (ibt_query_qp(rc_chan, &qp_attr) == IBT_SUCCESS) {
8617c478bd9Sstevel@tonic-gate 			/* ch_current_state is fixed by ibt_query_qp */
8627c478bd9Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
8637c478bd9Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
8647c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
8657c478bd9Sstevel@tonic-gate 			retries = 0;
8667c478bd9Sstevel@tonic-gate 		} else /* query_qp should never really fail */
8677c478bd9Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
8687c478bd9Sstevel@tonic-gate 	}
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate retry:
8717c478bd9Sstevel@tonic-gate 	/* Call modify_qp */
8727c478bd9Sstevel@tonic-gate 	cep_flags = IBT_CEP_SET_MIG | IBT_CEP_SET_STATE;
8737c478bd9Sstevel@tonic-gate 	qp_info.qp_state = rc_chan->ch_current_state;
8747c478bd9Sstevel@tonic-gate 	qp_info.qp_current_state = rc_chan->ch_current_state;
8757c478bd9Sstevel@tonic-gate 	qp_info.qp_trans = IBT_RC_SRV;
8767c478bd9Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_mig_state = IBT_STATE_MIGRATED;
8777c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, cep_flags, &qp_info, NULL);
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
8807c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
8817c478bd9Sstevel@tonic-gate 		    " ibt_modify_qp() returned = %d", retval);
8827c478bd9Sstevel@tonic-gate 		if (rc_chan->ch_current_state != qp_info.qp_state &&
8837c478bd9Sstevel@tonic-gate 		    --retries >= 0) {
8847c478bd9Sstevel@tonic-gate 			/*
8857c478bd9Sstevel@tonic-gate 			 * That means our cached 'state' was invalid.
8867c478bd9Sstevel@tonic-gate 			 * We know ibt_modify_qp() fixed it up, so it
8877c478bd9Sstevel@tonic-gate 			 * might be worth retrying.
8887c478bd9Sstevel@tonic-gate 			 */
8897c478bd9Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
8907c478bd9Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
8917c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
8927c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
8937c478bd9Sstevel@tonic-gate 			    " retrying after 'state' fixed");
8947c478bd9Sstevel@tonic-gate 			goto retry;
8957c478bd9Sstevel@tonic-gate 		}
8967c478bd9Sstevel@tonic-gate 	}
8977c478bd9Sstevel@tonic-gate 	return (retval);
8987c478bd9Sstevel@tonic-gate }
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate /*
9027c478bd9Sstevel@tonic-gate  * Function:
9037c478bd9Sstevel@tonic-gate  *	ibt_set_qp_private
9047c478bd9Sstevel@tonic-gate  * Input:
9057c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9067c478bd9Sstevel@tonic-gate  *	clnt_private	The client private data.
9077c478bd9Sstevel@tonic-gate  * Output:
9087c478bd9Sstevel@tonic-gate  *	none.
9097c478bd9Sstevel@tonic-gate  * Returns:
9107c478bd9Sstevel@tonic-gate  *	none.
9117c478bd9Sstevel@tonic-gate  * Description:
9127c478bd9Sstevel@tonic-gate  *	Set the client private data.
9137c478bd9Sstevel@tonic-gate  */
9147c478bd9Sstevel@tonic-gate void
9157c478bd9Sstevel@tonic-gate ibt_set_qp_private(ibt_qp_hdl_t ibt_qp, void *clnt_private)
9167c478bd9Sstevel@tonic-gate {
9177c478bd9Sstevel@tonic-gate 	ibt_qp->ch_clnt_private = clnt_private;
9187c478bd9Sstevel@tonic-gate }
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate /*
9227c478bd9Sstevel@tonic-gate  * Function:
9237c478bd9Sstevel@tonic-gate  *	ibt_get_qp_private
9247c478bd9Sstevel@tonic-gate  * Input:
9257c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9267c478bd9Sstevel@tonic-gate  * Output:
9277c478bd9Sstevel@tonic-gate  *	none.
9287c478bd9Sstevel@tonic-gate  * Returns:
9297c478bd9Sstevel@tonic-gate  *	The client private data.
9307c478bd9Sstevel@tonic-gate  * Description:
9317c478bd9Sstevel@tonic-gate  *	Get the client private data.
9327c478bd9Sstevel@tonic-gate  */
9337c478bd9Sstevel@tonic-gate void *
9347c478bd9Sstevel@tonic-gate ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate 	return (ibt_qp->ch_clnt_private);
9377c478bd9Sstevel@tonic-gate }
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate /*
9417c478bd9Sstevel@tonic-gate  * Function:
9427c478bd9Sstevel@tonic-gate  *	ibt_qp_to_hca_guid
9437c478bd9Sstevel@tonic-gate  * Input:
9447c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9457c478bd9Sstevel@tonic-gate  * Output:
9467c478bd9Sstevel@tonic-gate  *	none.
9477c478bd9Sstevel@tonic-gate  * Returns:
9487c478bd9Sstevel@tonic-gate  *	hca_guid	Returned HCA GUID on which the specified QP is
9497c478bd9Sstevel@tonic-gate  *			allocated. Valid if it is non-NULL on return.
9507c478bd9Sstevel@tonic-gate  * Description:
9517c478bd9Sstevel@tonic-gate  *	A helper function to retrieve HCA GUID for the specified QP.
9527c478bd9Sstevel@tonic-gate  */
9537c478bd9Sstevel@tonic-gate ib_guid_t
9547c478bd9Sstevel@tonic-gate ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)
9557c478bd9Sstevel@tonic-gate {
9567c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_qp_to_hca_guid(%p)", ibt_qp);
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ibt_qp)));
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate /*
9637c478bd9Sstevel@tonic-gate  * Function:
9647c478bd9Sstevel@tonic-gate  *	ibt_recover_ud_qp
9657c478bd9Sstevel@tonic-gate  * Input:
9667c478bd9Sstevel@tonic-gate  *	ibt_qp		An QP Handle which is in SQError state.
9677c478bd9Sstevel@tonic-gate  * Output:
9687c478bd9Sstevel@tonic-gate  *	none.
9697c478bd9Sstevel@tonic-gate  * Returns:
9707c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
9717c478bd9Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
9727c478bd9Sstevel@tonic-gate  *	IBT_QP_STATE_INVALID.
9737c478bd9Sstevel@tonic-gate  * Description:
9747c478bd9Sstevel@tonic-gate  *	Recover an UD QP which has transitioned to SQ Error state. The
9757c478bd9Sstevel@tonic-gate  *	ibt_recover_ud_qp() transitions the QP from SQ Error state to
9767c478bd9Sstevel@tonic-gate  *	Ready-To-Send QP state.
9777c478bd9Sstevel@tonic-gate  *
9787c478bd9Sstevel@tonic-gate  *	If a work request posted to a UD QP's send queue completes with an
9797c478bd9Sstevel@tonic-gate  *	error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state.
9807c478bd9Sstevel@tonic-gate  *	In order to reuse this QP, ibt_recover_ud_qp() can be used to recover
9817c478bd9Sstevel@tonic-gate  *	the QP to a usable (Ready-to-Send) state.
9827c478bd9Sstevel@tonic-gate  */
9837c478bd9Sstevel@tonic-gate ibt_status_t
9847c478bd9Sstevel@tonic-gate ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recover_ud_qp(%p)", ibt_qp);
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate 	return (ibt_recover_ud_channel(IBTL_QP2CHAN(ibt_qp)));
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate /*
9937c478bd9Sstevel@tonic-gate  * Function:
9947c478bd9Sstevel@tonic-gate  *	ibt_recycle_ud
9957c478bd9Sstevel@tonic-gate  * Input:
9967c478bd9Sstevel@tonic-gate  *	ud_chan		The IBT UD QP Handle.
9977c478bd9Sstevel@tonic-gate  *	various attributes
9987c478bd9Sstevel@tonic-gate  *
9997c478bd9Sstevel@tonic-gate  * Output:
10007c478bd9Sstevel@tonic-gate  *	none
10017c478bd9Sstevel@tonic-gate  * Returns:
10027c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
10037c478bd9Sstevel@tonic-gate  *	IBT_CHAN_SRV_TYPE_INVALID
10047c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
10057c478bd9Sstevel@tonic-gate  *
10067c478bd9Sstevel@tonic-gate  * Description:
10077c478bd9Sstevel@tonic-gate  *	Revert the UD QP back to a usable state.
10087c478bd9Sstevel@tonic-gate  */
10097c478bd9Sstevel@tonic-gate ibt_status_t
10107c478bd9Sstevel@tonic-gate ibt_recycle_ud(ibt_channel_hdl_t ud_chan, uint8_t hca_port_num,
10117c478bd9Sstevel@tonic-gate     uint16_t pkey_ix, ib_qkey_t qkey)
10127c478bd9Sstevel@tonic-gate {
10137c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
10147c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recycle_ud(%p, %d, %x, %x): ",
10177c478bd9Sstevel@tonic-gate 	    ud_chan, hca_port_num, pkey_ix, qkey);
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
10207c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10217c478bd9Sstevel@tonic-gate 		    "chan %p is not a UD channel", ud_chan);
10227c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
10237c478bd9Sstevel@tonic-gate 	}
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(ud_chan, &qp_attr);
10267c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10277c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10287c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed on chan %p: %d", ud_chan, retval);
10297c478bd9Sstevel@tonic-gate 		return (retval);
10307c478bd9Sstevel@tonic-gate 	}
10317c478bd9Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR) {
10327c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10337c478bd9Sstevel@tonic-gate 		    "chan %p is in state %d (not in ERROR state)",
10347c478bd9Sstevel@tonic-gate 		    ud_chan, qp_attr.qp_info.qp_state);
10357c478bd9Sstevel@tonic-gate 		ud_chan->ch_current_state = qp_attr.qp_info.qp_state;
10367c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
10377c478bd9Sstevel@tonic-gate 	}
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 	/* transition the QP from ERROR to RESET */
10407c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_state = IBT_STATE_RESET;
10417c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_trans = ud_chan->ch_qp.qp_type;
10427c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &qp_attr.qp_info,
10437c478bd9Sstevel@tonic-gate 	    NULL);
10447c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10457c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10467c478bd9Sstevel@tonic-gate 		    "ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d",
10477c478bd9Sstevel@tonic-gate 		    ud_chan, retval);
10487c478bd9Sstevel@tonic-gate 		return (retval);
10497c478bd9Sstevel@tonic-gate 	}
10507c478bd9Sstevel@tonic-gate 	ud_chan->ch_current_state = IBT_STATE_RESET;
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 	/* transition the QP back to RTS */
10537c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_port = hca_port_num;
10547c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_qkey = qkey;
10557c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_pkey_ix = pkey_ix;
10567c478bd9Sstevel@tonic-gate 	retval = ibt_initialize_qp(ud_chan, &qp_attr.qp_info);
10577c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10587c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10597c478bd9Sstevel@tonic-gate 		    "ibt_initialize_qp failed on chan %p: %d", ud_chan, retval);
10607c478bd9Sstevel@tonic-gate 		/* the man page says the QP should be left in ERROR state */
10617c478bd9Sstevel@tonic-gate 		(void) ibt_flush_qp(ud_chan);
10627c478bd9Sstevel@tonic-gate 	}
10637c478bd9Sstevel@tonic-gate 	return (retval);
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate /*
10677c478bd9Sstevel@tonic-gate  * Function:
10687c478bd9Sstevel@tonic-gate  *	ibt_pause_sendq
10697c478bd9Sstevel@tonic-gate  * Input:
10707c478bd9Sstevel@tonic-gate  *	chan		The IBT QP Handle.
10717c478bd9Sstevel@tonic-gate  *	modify_flags	IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT
10727c478bd9Sstevel@tonic-gate  *
10737c478bd9Sstevel@tonic-gate  * Output:
10747c478bd9Sstevel@tonic-gate  *	none.
10757c478bd9Sstevel@tonic-gate  * Returns:
10767c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
10777c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
10787c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
10797c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
10807c478bd9Sstevel@tonic-gate  *
10817c478bd9Sstevel@tonic-gate  * Description:
10827c478bd9Sstevel@tonic-gate  *	Place the send queue of the specified channel into the send queue
10837c478bd9Sstevel@tonic-gate  *	drained (SQD) state.
10847c478bd9Sstevel@tonic-gate  *
10857c478bd9Sstevel@tonic-gate  */
10867c478bd9Sstevel@tonic-gate ibt_status_t
10877c478bd9Sstevel@tonic-gate ibt_pause_sendq(ibt_channel_hdl_t chan, ibt_cep_modify_flags_t modify_flags)
10887c478bd9Sstevel@tonic-gate {
10897c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
10907c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_pause_sendq(%p, %x)", chan, modify_flags);
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 	modify_flags &= IBT_CEP_SET_SQD_EVENT;	/* ignore other bits */
10957c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
10987c478bd9Sstevel@tonic-gate 	/*
10997c478bd9Sstevel@tonic-gate 	 * Set the QP state to SQD.
11007c478bd9Sstevel@tonic-gate 	 */
11017c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
11027c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11077c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_pause_sendq: "
11087c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
11097c478bd9Sstevel@tonic-gate 	}
11107c478bd9Sstevel@tonic-gate 	return (retval);
11117c478bd9Sstevel@tonic-gate }
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate /*
11157c478bd9Sstevel@tonic-gate  * Function:
11167c478bd9Sstevel@tonic-gate  *	ibt_unpause_sendq
11177c478bd9Sstevel@tonic-gate  * Input:
11187c478bd9Sstevel@tonic-gate  *	chan	The IBT Channel Handle.
11197c478bd9Sstevel@tonic-gate  * Output:
11207c478bd9Sstevel@tonic-gate  *	none.
11217c478bd9Sstevel@tonic-gate  * Returns:
11227c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
11237c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
11247c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
11257c478bd9Sstevel@tonic-gate  * Description:
11267c478bd9Sstevel@tonic-gate  *	Un-pauses the previously paused channel. This call will transition the
11277c478bd9Sstevel@tonic-gate  *	QP from SQD to RTS state.
11287c478bd9Sstevel@tonic-gate  */
11297c478bd9Sstevel@tonic-gate ibt_status_t
11307c478bd9Sstevel@tonic-gate ibt_unpause_sendq(ibt_channel_hdl_t chan)
11317c478bd9Sstevel@tonic-gate {
11327c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
11337c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_unpause_sendq(%p)", chan);
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 	/*
11407c478bd9Sstevel@tonic-gate 	 * Set the QP state to RTS.
11417c478bd9Sstevel@tonic-gate 	 */
11427c478bd9Sstevel@tonic-gate 	modify_attr.qp_current_state = IBT_STATE_SQD;
11437c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_RTS;
11447c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
11477c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11487c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_unpause_sendq: "
11497c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
11507c478bd9Sstevel@tonic-gate 	}
11517c478bd9Sstevel@tonic-gate 	return (retval);
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate /*
11567c478bd9Sstevel@tonic-gate  * Function:
11577c478bd9Sstevel@tonic-gate  *	ibt_resize_queues
11587c478bd9Sstevel@tonic-gate  * Input:
11597c478bd9Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
11607c478bd9Sstevel@tonic-gate  *	flags		QP Flags
11617c478bd9Sstevel@tonic-gate  *				IBT_SEND_Q
11627c478bd9Sstevel@tonic-gate  *				IBT_RECV_Q
11637c478bd9Sstevel@tonic-gate  *	request_sz	Requested new sizes.
11647c478bd9Sstevel@tonic-gate  * Output:
11657c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
11667c478bd9Sstevel@tonic-gate  * Returns:
11677c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
11687c478bd9Sstevel@tonic-gate  * Description:
11697c478bd9Sstevel@tonic-gate  *	Resize the SendQ/RecvQ sizes of a channel. Can only be called on
11707c478bd9Sstevel@tonic-gate  *	a previously opened channel.
11717c478bd9Sstevel@tonic-gate  */
11727c478bd9Sstevel@tonic-gate ibt_status_t
11737c478bd9Sstevel@tonic-gate ibt_resize_queues(ibt_channel_hdl_t chan, ibt_qflags_t flags,
11747c478bd9Sstevel@tonic-gate     ibt_queue_sizes_t *request_sz, ibt_queue_sizes_t *actual_sz)
11757c478bd9Sstevel@tonic-gate {
11767c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags = IBT_CEP_SET_STATE;
11777c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
11787c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_resize_queues(%p, 0x%X, %p, %p)",
11817c478bd9Sstevel@tonic-gate 	    chan, flags, request_sz, actual_sz);
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate 	if ((flags & (IBT_SEND_Q | IBT_RECV_Q)) == 0)  {
11847c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
11857c478bd9Sstevel@tonic-gate 		    "Flags <0x%X> not set", flags);
11867c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
11877c478bd9Sstevel@tonic-gate 	}
11887c478bd9Sstevel@tonic-gate 
11897c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate 	modify_attr.qp_current_state = chan->ch_current_state;
11927c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11937c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = chan->ch_current_state;
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 	if (flags & IBT_SEND_Q) {
11967c478bd9Sstevel@tonic-gate 		modify_attr.qp_sq_sz = request_sz->qs_sq;
11977c478bd9Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_SQ_SIZE;
11987c478bd9Sstevel@tonic-gate 	}
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 	if (flags & IBT_RECV_Q) {
12017c478bd9Sstevel@tonic-gate 		modify_attr.qp_rq_sz = request_sz->qs_rq;
12027c478bd9Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_RQ_SIZE;
12037c478bd9Sstevel@tonic-gate 	}
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, actual_sz);
12067c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
12077c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
12087c478bd9Sstevel@tonic-gate 		    "failed on QP %p: %d", chan, retval);
12097c478bd9Sstevel@tonic-gate 	}
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 	return (retval);
12127c478bd9Sstevel@tonic-gate }
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate /*
12167c478bd9Sstevel@tonic-gate  * Function:
12177c478bd9Sstevel@tonic-gate  *	ibt_query_queues
12187c478bd9Sstevel@tonic-gate  * Input:
12197c478bd9Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
12207c478bd9Sstevel@tonic-gate  * Output:
12217c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
12227c478bd9Sstevel@tonic-gate  * Returns:
12237c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
12247c478bd9Sstevel@tonic-gate  * Description:
12257c478bd9Sstevel@tonic-gate  *	Query the SendQ/RecvQ sizes of a channel.
12267c478bd9Sstevel@tonic-gate  */
12277c478bd9Sstevel@tonic-gate ibt_status_t
12287c478bd9Sstevel@tonic-gate ibt_query_queues(ibt_channel_hdl_t chan, ibt_queue_sizes_t *actual_sz)
12297c478bd9Sstevel@tonic-gate {
12307c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
12317c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_query_attr;
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_queues(%p)", chan);
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 	/* Perform Query QP and retrieve QP sizes. */
12367c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(chan, &qp_query_attr);
12377c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
12387c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_queues: "
12397c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed: qp %p: %d", chan, retval);
12407c478bd9Sstevel@tonic-gate 		return (retval);
12417c478bd9Sstevel@tonic-gate 	}
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
12447c478bd9Sstevel@tonic-gate 	    actual_sz->qs_sq))
12457c478bd9Sstevel@tonic-gate 	actual_sz->qs_sq = qp_query_attr.qp_info.qp_sq_sz;
12467c478bd9Sstevel@tonic-gate 	actual_sz->qs_rq = qp_query_attr.qp_info.qp_rq_sz;
12477c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
12487c478bd9Sstevel@tonic-gate 	    actual_sz->qs_sq))
12497c478bd9Sstevel@tonic-gate 	chan->ch_current_state = qp_query_attr.qp_info.qp_state;
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 	return (retval);
12527c478bd9Sstevel@tonic-gate }
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate /*
12567c478bd9Sstevel@tonic-gate  * Function:
12577c478bd9Sstevel@tonic-gate  *	ibt_modify_rdma
12587c478bd9Sstevel@tonic-gate  * Input:
12597c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated channel handle.
12607c478bd9Sstevel@tonic-gate  *
12617c478bd9Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
12627c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_R	Enable/Disable RDMA RD
12637c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_W	Enable/Disable RDMA WR
12647c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_ATOMIC	Enable/Disable Atomics
12657c478bd9Sstevel@tonic-gate  *
12667c478bd9Sstevel@tonic-gate  *	flags		Channel End Point (CEP) Disable Flags (0 => enable).
12677c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_RD	Disable incoming RDMA RD's
12687c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_WR	Disable incoming RDMA WR's
12697c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_ATOMIC	Disable incoming Atomics.
12707c478bd9Sstevel@tonic-gate  * Output:
12717c478bd9Sstevel@tonic-gate  *	none.
12727c478bd9Sstevel@tonic-gate  * Returns:
12737c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
12747c478bd9Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
12757c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
12767c478bd9Sstevel@tonic-gate  *	IBT_CHAN_ATOMICS_NOT_SUPPORTED
12777c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
12787c478bd9Sstevel@tonic-gate  * Description:
12797c478bd9Sstevel@tonic-gate  *	Enable/disable RDMA operations. To enable an operation clear the
12807c478bd9Sstevel@tonic-gate  *	"disable" flag. Can call this function when the channel is in
12817c478bd9Sstevel@tonic-gate  *	INIT, RTS or SQD states. If called in any other state
12827c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID is returned. When the operation completes the
12837c478bd9Sstevel@tonic-gate  *	channel state is left unchanged.
12847c478bd9Sstevel@tonic-gate  */
12857c478bd9Sstevel@tonic-gate ibt_status_t
12867c478bd9Sstevel@tonic-gate ibt_modify_rdma(ibt_channel_hdl_t rc_chan,
12877c478bd9Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, ibt_cep_flags_t flags)
12887c478bd9Sstevel@tonic-gate {
12897c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
12907c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_rdma(%p, 0x%x, 0x%x)",
12937c478bd9Sstevel@tonic-gate 	    rc_chan, modify_flags, flags);
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
12967c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
12977c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
12987c478bd9Sstevel@tonic-gate 		    rc_chan->ch_qp.qp_type);
12997c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
13007c478bd9Sstevel@tonic-gate 	}
13017c478bd9Sstevel@tonic-gate 
13027c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	/*
13057c478bd9Sstevel@tonic-gate 	 * Can only call this function when the channel in INIT, RTS or SQD
13067c478bd9Sstevel@tonic-gate 	 * states.
13077c478bd9Sstevel@tonic-gate 	 */
13087c478bd9Sstevel@tonic-gate 	if ((rc_chan->ch_current_state != IBT_STATE_INIT) &&
13097c478bd9Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_RTS) &&
13107c478bd9Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_SQD)) {
13117c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: Invalid Channel "
13127c478bd9Sstevel@tonic-gate 		    "state: 0x%X", rc_chan->ch_current_state);
13137c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
13147c478bd9Sstevel@tonic-gate 	}
13157c478bd9Sstevel@tonic-gate 
13167c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = modify_attr.qp_current_state =
13177c478bd9Sstevel@tonic-gate 	    rc_chan->ch_current_state;
13187c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = rc_chan->ch_qp.qp_type;
13197c478bd9Sstevel@tonic-gate 	modify_attr.qp_flags = flags;
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
13227c478bd9Sstevel@tonic-gate 	    IBT_CEP_SET_ATOMIC);
13237c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, modify_flags, &modify_attr, NULL);
13267c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
13277c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
13287c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", rc_chan, retval);
13297c478bd9Sstevel@tonic-gate 	}
13307c478bd9Sstevel@tonic-gate 	return (retval);
13317c478bd9Sstevel@tonic-gate }
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate /*
13357c478bd9Sstevel@tonic-gate  * Function:
13367c478bd9Sstevel@tonic-gate  *	ibt_set_rdma_resource
13377c478bd9Sstevel@tonic-gate  * Input:
13387c478bd9Sstevel@tonic-gate  *	chan		A previously allocated RC channel handle.
13397c478bd9Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
13407c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_OUT	Initiator depth (rdma_ra_out)
13417c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_IN	Responder Resources
13427c478bd9Sstevel@tonic-gate  *						(rdma_ra_in)
13437c478bd9Sstevel@tonic-gate  *	rdma_ra_out	Outgoing RDMA Reads/Atomics
13447c478bd9Sstevel@tonic-gate  *	rdma_ra_in	Incoming RDMA Reads/Atomics
13457c478bd9Sstevel@tonic-gate  * Output:
13467c478bd9Sstevel@tonic-gate  *	none.
13477c478bd9Sstevel@tonic-gate  * Returns:
13487c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
13497c478bd9Sstevel@tonic-gate  * Description:
13507c478bd9Sstevel@tonic-gate  *	Change the number of resources to be used for incoming and outgoing
13517c478bd9Sstevel@tonic-gate  *	RDMA reads & Atomics. Can only be called on a previously opened
13527c478bd9Sstevel@tonic-gate  *	RC channel.  Can only be called on a paused channel, and this will
13537c478bd9Sstevel@tonic-gate  *	un-pause that channel.
13547c478bd9Sstevel@tonic-gate  */
13557c478bd9Sstevel@tonic-gate ibt_status_t
13567c478bd9Sstevel@tonic-gate ibt_set_rdma_resource(ibt_channel_hdl_t chan,
13577c478bd9Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, uint8_t rdma_ra_out,
13587c478bd9Sstevel@tonic-gate     uint8_t resp_rdma_ra_out)
13597c478bd9Sstevel@tonic-gate {
13607c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
13617c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_set_rdma_resource(%p, 0x%x, %d, %d)",
13647c478bd9Sstevel@tonic-gate 	    chan, modify_flags, rdma_ra_out, resp_rdma_ra_out);
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
13677c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
13687c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
13697c478bd9Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
13707c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
13717c478bd9Sstevel@tonic-gate 	}
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
13747c478bd9Sstevel@tonic-gate 
13757c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
13767c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_out = rdma_ra_out;
13797c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_in = resp_rdma_ra_out;
13807c478bd9Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN);
13817c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
13847c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
13857c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
13867c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
13877c478bd9Sstevel@tonic-gate 	}
13887c478bd9Sstevel@tonic-gate 	return (retval);
13897c478bd9Sstevel@tonic-gate }
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate /*
13937c478bd9Sstevel@tonic-gate  * Function:
13947c478bd9Sstevel@tonic-gate  *	ibt_change_port
13957c478bd9Sstevel@tonic-gate  * Input:
13967c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
13977c478bd9Sstevel@tonic-gate  *	port_num	New HCA port.
13987c478bd9Sstevel@tonic-gate  * Output:
13997c478bd9Sstevel@tonic-gate  *	none.
14007c478bd9Sstevel@tonic-gate  * Returns:
14017c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
14027c478bd9Sstevel@tonic-gate  * Description:
14037c478bd9Sstevel@tonic-gate  *	Change the primary physical port of a channel. (This is done only if
14047c478bd9Sstevel@tonic-gate  *	HCA supports this capability).
14057c478bd9Sstevel@tonic-gate  */
14067c478bd9Sstevel@tonic-gate ibt_status_t
14077c478bd9Sstevel@tonic-gate ibt_change_port(ibt_channel_hdl_t chan, uint8_t port_num)
14087c478bd9Sstevel@tonic-gate {
14097c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
14107c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
14117c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_change_port(%p, %d)", chan, port_num);
14147c478bd9Sstevel@tonic-gate 
14157c478bd9Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
14167c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
14177c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
14187c478bd9Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
14197c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
14207c478bd9Sstevel@tonic-gate 	}
14217c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
14247c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
14257c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = port_num;
14267c478bd9Sstevel@tonic-gate 
14277c478bd9Sstevel@tonic-gate 	modify_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
14307c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
14317c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
14327c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
14337c478bd9Sstevel@tonic-gate 	}
14347c478bd9Sstevel@tonic-gate 	return (retval);
14357c478bd9Sstevel@tonic-gate }
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate void
14397c478bd9Sstevel@tonic-gate ibtl_init_cep_states(void)
14407c478bd9Sstevel@tonic-gate {
14417c478bd9Sstevel@tonic-gate 	int	index;
14427c478bd9Sstevel@tonic-gate 	int	ibt_nstate_inits;
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_init_cep_states()");
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 	ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) /
14477c478bd9Sstevel@tonic-gate 	    sizeof (ibt_cep_next_state_inits[0]);
14487c478bd9Sstevel@tonic-gate 
14497c478bd9Sstevel@tonic-gate 	/*
14507c478bd9Sstevel@tonic-gate 	 * Initialize CEP next state table, using an indirect lookup table so
14517c478bd9Sstevel@tonic-gate 	 * that this code isn't dependent on the ibt_cep_state_t enum values.
14527c478bd9Sstevel@tonic-gate 	 */
14537c478bd9Sstevel@tonic-gate 	for (index = 0; index < ibt_nstate_inits; index++) {
14547c478bd9Sstevel@tonic-gate 		ibt_cep_state_t	state;
14557c478bd9Sstevel@tonic-gate 
14567c478bd9Sstevel@tonic-gate 		state = ibt_cep_next_state_inits[index].current_state;
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 		ibt_cep_next_state[state].next_state =
14597c478bd9Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].next_state;
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate 		ibt_cep_next_state[state].modify_flags =
14627c478bd9Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].modify_flags;
14637c478bd9Sstevel@tonic-gate 	}
14647c478bd9Sstevel@tonic-gate }
1465