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