xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_qp.c (revision d99cb22f)
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*d99cb22fSagiri  * Copyright 2008 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 
1885974a6fcShiremath 	IBTF_DPRINTF_L2(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);
421*d99cb22fSagiri 		if ((ibt_qp->ch_transport.rc.rc_free_flags &
422*d99cb22fSagiri 		    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
4237c478bd9Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
4247c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
4257c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp(%p): "
4267c478bd9Sstevel@tonic-gate 			    "called with a connected RC QP", ibt_qp);
4277c478bd9Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
4287c478bd9Sstevel@tonic-gate 		}
4297c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
4307c478bd9Sstevel@tonic-gate 	}
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	/*
4357c478bd9Sstevel@tonic-gate 	 * Set the QP state to error to flush any uncompleted WRs.
4367c478bd9Sstevel@tonic-gate 	 */
4377c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_ERROR;
4387c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = ibt_qp->ch_qp.qp_type;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(ibt_qp, IBT_CEP_SET_STATE, &modify_attr, NULL);
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
4437c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp: "
4447c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 	return (retval);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate /*
4517c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_open()
4527c478bd9Sstevel@tonic-gate  *
4537c478bd9Sstevel@tonic-gate  *	Inform IBTL that the connection has been established on this
4547c478bd9Sstevel@tonic-gate  *	channel so that a later call to ibtl_cm_chan_is_closed()
4557c478bd9Sstevel@tonic-gate  *	will be required to free the QPN used by this channel.
4567c478bd9Sstevel@tonic-gate  *
4577c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
4587c478bd9Sstevel@tonic-gate  */
4597c478bd9Sstevel@tonic-gate void
4607c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_open(%p)", chan);
4637c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
4647c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
4657c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_transport.rc.rc_free_flags == 0);
4667c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTED;
4677c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate /*
4717c478bd9Sstevel@tonic-gate  * ibtl_cm_is_chan_closing()
4727c478bd9Sstevel@tonic-gate  *
4737c478bd9Sstevel@tonic-gate  *	Returns 1, if the connection that has been
4747c478bd9Sstevel@tonic-gate  *	started for this channel has moved to TIMEWAIT
4757c478bd9Sstevel@tonic-gate  *	If not, returns 0
4767c478bd9Sstevel@tonic-gate  *
4777c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
4787c478bd9Sstevel@tonic-gate  */
4797c478bd9Sstevel@tonic-gate int
4807c478bd9Sstevel@tonic-gate ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closing(%p)", chan);
4837c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
4847c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
4857c478bd9Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSING) {
4867c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
4877c478bd9Sstevel@tonic-gate 		return (1);
4887c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
4907c478bd9Sstevel@tonic-gate 	return (0);
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate /*
4947c478bd9Sstevel@tonic-gate  * ibtl_cm_is_chan_closed()
4957c478bd9Sstevel@tonic-gate  *
4967c478bd9Sstevel@tonic-gate  *	Returns 1, if the connection that has been
4977c478bd9Sstevel@tonic-gate  *	started for this channel has completed TIMEWAIT
4987c478bd9Sstevel@tonic-gate  *	If not, returns 0
4997c478bd9Sstevel@tonic-gate  *
5007c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5017c478bd9Sstevel@tonic-gate  */
5027c478bd9Sstevel@tonic-gate int
5037c478bd9Sstevel@tonic-gate ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closed(%p)", chan);
5067c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5077c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5087c478bd9Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSED) {
5097c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
5107c478bd9Sstevel@tonic-gate 		return (1);
5117c478bd9Sstevel@tonic-gate 	}
5127c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5137c478bd9Sstevel@tonic-gate 	return (0);
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate /*
5167c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_closing()
5177c478bd9Sstevel@tonic-gate  *
5187c478bd9Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
5197c478bd9Sstevel@tonic-gate  *	started for this channel so that the QP can be freed.
5207c478bd9Sstevel@tonic-gate  *
5217c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5227c478bd9Sstevel@tonic-gate  */
5237c478bd9Sstevel@tonic-gate void
5247c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closing(%p)", chan);
5277c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5287c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5297c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_transport.rc.rc_free_flags == IBTL_RC_QP_CONNECTED);
5307c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSING;
5317c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_closed()
5357c478bd9Sstevel@tonic-gate  *
5367c478bd9Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
5377c478bd9Sstevel@tonic-gate  *	reached for this channel so that the QPN can be reused.
5387c478bd9Sstevel@tonic-gate  *
5397c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5407c478bd9Sstevel@tonic-gate  */
5417c478bd9Sstevel@tonic-gate void
5427c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)
5437c478bd9Sstevel@tonic-gate {
5447c478bd9Sstevel@tonic-gate 	ibt_status_t status;
5457c478bd9Sstevel@tonic-gate 	ibtl_hca_t *ibtl_hca = chan->ch_qp.qp_hca;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closed(%p)", chan);
5487c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5497c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5507c478bd9Sstevel@tonic-gate 	ASSERT((chan->ch_transport.rc.rc_free_flags &
5517c478bd9Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
5527c478bd9Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING));
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTED;
5557c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSING;
5567c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSED;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	ibtl_cm_set_chan_private(chan, NULL);
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	if ((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_FREED) == 0) {
5617c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
5627c478bd9Sstevel@tonic-gate 		return;
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5657c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
5667c478bd9Sstevel@tonic-gate 	if ((status = (IBTL_CHAN2CIHCAOPS_P(chan)->ibc_release_qpn)
5677c478bd9Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(chan), chan->ch_transport.rc.rc_qpn_hdl)) ==
5687c478bd9Sstevel@tonic-gate 	    IBT_SUCCESS) {
5697c478bd9Sstevel@tonic-gate 		/* effectively, this is kmem_free(chan); */
5707c478bd9Sstevel@tonic-gate 		ibtl_free_qp_async_check(&chan->ch_qp);
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 		/* decrement ha_qpn_cnt and check for close in progress */
5737c478bd9Sstevel@tonic-gate 		ibtl_close_hca_check(ibtl_hca);
5747c478bd9Sstevel@tonic-gate 	} else
575934f0bccShiremath 		IBTF_DPRINTF_L2(ibtf_qp, "ibtl_cm_chan_is_closed: "
5767c478bd9Sstevel@tonic-gate 		    "ibc_release_qpn failed: status = %d\n", status);
5777c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate /*
5817c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_reused()
5827c478bd9Sstevel@tonic-gate  *
5837c478bd9Sstevel@tonic-gate  *	Inform IBTL that the channel is going to be re-used
5847c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5857c478bd9Sstevel@tonic-gate  */
5867c478bd9Sstevel@tonic-gate void
5877c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)
5887c478bd9Sstevel@tonic-gate {
5897c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_reused(%p)", chan);
5907c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5917c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5927c478bd9Sstevel@tonic-gate 	ASSERT(((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CONNECTED) !=
5937c478bd9Sstevel@tonic-gate 	    IBTL_RC_QP_CONNECTED));
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	/* channel is no longer in closed state, shall be re-used */
596934f0bccShiremath 	chan->ch_transport.rc.rc_free_flags = 0;
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate /*
6037c478bd9Sstevel@tonic-gate  * Function:	ibt_free_qp()
6047c478bd9Sstevel@tonic-gate  *
6057c478bd9Sstevel@tonic-gate  * Input:	ibt_qp		Handle for Channel(QP) that needs to be freed.
6067c478bd9Sstevel@tonic-gate  *
6077c478bd9Sstevel@tonic-gate  * Output:	NONE.
6087c478bd9Sstevel@tonic-gate  *
6097c478bd9Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
6107c478bd9Sstevel@tonic-gate  *		IBT_QP_STATE_INVALID
6117c478bd9Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
6127c478bd9Sstevel@tonic-gate  *
6137c478bd9Sstevel@tonic-gate  * Description:
6147c478bd9Sstevel@tonic-gate  *		Free a previously allocated QP.
6157c478bd9Sstevel@tonic-gate  */
6167c478bd9Sstevel@tonic-gate ibt_status_t
6177c478bd9Sstevel@tonic-gate ibt_free_qp(ibt_qp_hdl_t ibt_qp)
6187c478bd9Sstevel@tonic-gate {
6197c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
6207c478bd9Sstevel@tonic-gate 	ibtl_hca_t		*ibtl_hca = ibt_qp->ch_qp.qp_hca;
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p)", ibt_qp);
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
6257c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
6267c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
6277c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_transport.rc.rc_free_flags &
6287c478bd9Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
6297c478bd9Sstevel@tonic-gate 			if ((ibt_qp->ch_transport.rc.rc_free_flags &
6307c478bd9Sstevel@tonic-gate 			    IBTL_RC_QP_CLOSING) == 0) {
6317c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
6327c478bd9Sstevel@tonic-gate 				    "need to call ibt_close_rc_channel");
6337c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_free_qp_mutex);
6347c478bd9Sstevel@tonic-gate 				ibtl_qp_flow_control_exit();
6357c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
6367c478bd9Sstevel@tonic-gate 			}
6377c478bd9Sstevel@tonic-gate 			ibt_qp->ch_transport.rc.rc_free_flags |=
6387c478bd9Sstevel@tonic-gate 			    IBTL_RC_QP_FREED;
6397c478bd9Sstevel@tonic-gate 			status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
6407c478bd9Sstevel@tonic-gate 			    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
6417c478bd9Sstevel@tonic-gate 			    IBC_FREE_QP_ONLY,
6427c478bd9Sstevel@tonic-gate 			    &ibt_qp->ch_transport.rc.rc_qpn_hdl);
6437c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
6447c478bd9Sstevel@tonic-gate 			ibtl_qp_flow_control_exit();
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 			if (status == IBT_SUCCESS) {
6477c478bd9Sstevel@tonic-gate 				mutex_enter(&ibtl_clnt_list_mutex);
6487c478bd9Sstevel@tonic-gate 				ibtl_hca->ha_qpn_cnt++;
6497c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_clnt_list_mutex);
6507c478bd9Sstevel@tonic-gate 				mutex_enter(&ibtl_hca->ha_mutex);
6517c478bd9Sstevel@tonic-gate 				ibtl_hca->ha_qp_cnt--;
6527c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_hca->ha_mutex);
653934f0bccShiremath 				IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - "
6547c478bd9Sstevel@tonic-gate 				    "SUCCESS", ibt_qp);
6557c478bd9Sstevel@tonic-gate 			} else
6567c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
6577c478bd9Sstevel@tonic-gate 				    "ibc_free_qp failed: status = %d", status);
6587c478bd9Sstevel@tonic-gate 			return (status);
6597c478bd9Sstevel@tonic-gate 		}
6607c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
6617c478bd9Sstevel@tonic-gate 	} else
6627c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
6657c478bd9Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
6667c478bd9Sstevel@tonic-gate 	    IBC_FREE_QP_AND_QPN, NULL);
6677c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	if (status == IBT_SUCCESS) {
6707c478bd9Sstevel@tonic-gate 		/* effectively, this is kmem_free(ibt_qp); */
6717c478bd9Sstevel@tonic-gate 		ibtl_free_qp_async_check(&ibt_qp->ch_qp);
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_hca->ha_mutex);
6747c478bd9Sstevel@tonic-gate 		ibtl_hca->ha_qp_cnt--;
6757c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_hca->ha_mutex);
676934f0bccShiremath 		IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - SUCCESS", ibt_qp);
6777c478bd9Sstevel@tonic-gate 	} else {
6787c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
6797c478bd9Sstevel@tonic-gate 		    "ibc_free_qp failed with error %d", status);
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	return (status);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate /* helper function for ibt_query_qp */
6877c478bd9Sstevel@tonic-gate static void
6887c478bd9Sstevel@tonic-gate ibtl_fillin_sgid(ibt_cep_path_t *pathp, ibtl_hca_devinfo_t *hca_devp)
6897c478bd9Sstevel@tonic-gate {
6907c478bd9Sstevel@tonic-gate 	uint8_t port;
6917c478bd9Sstevel@tonic-gate 	uint32_t sgid_ix;
6927c478bd9Sstevel@tonic-gate 	ib_gid_t *sgidp;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	port = pathp->cep_hca_port_num;
6957c478bd9Sstevel@tonic-gate 	sgid_ix = pathp->cep_adds_vect.av_sgid_ix;
6967c478bd9Sstevel@tonic-gate 	if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
6977c478bd9Sstevel@tonic-gate 	    sgid_ix >= IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
6987c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_prefix = 0;
6997c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_guid = 0;
7007c478bd9Sstevel@tonic-gate 	} else {
7017c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
7027c478bd9Sstevel@tonic-gate 		sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
7037c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid = sgidp[sgid_ix];
7047c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7057c478bd9Sstevel@tonic-gate 	}
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate /*
7107c478bd9Sstevel@tonic-gate  * Function:	ibt_query_qp
7117c478bd9Sstevel@tonic-gate  *
7127c478bd9Sstevel@tonic-gate  * Input:	ibt_qp 			- The IBT QP Handle.
7137c478bd9Sstevel@tonic-gate  *
7147c478bd9Sstevel@tonic-gate  * Output:	ibt_qp_query_attrp 	- Points to a ibt_qp_query_attr_t
7157c478bd9Sstevel@tonic-gate  *					  that on return contains all the
7167c478bd9Sstevel@tonic-gate  *					  attributes of the specified qp.
7177c478bd9Sstevel@tonic-gate  *
7187c478bd9Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
7197c478bd9Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
7207c478bd9Sstevel@tonic-gate  *
7217c478bd9Sstevel@tonic-gate  * Description:
7227c478bd9Sstevel@tonic-gate  *		Query QP attributes
7237c478bd9Sstevel@tonic-gate  *
7247c478bd9Sstevel@tonic-gate  */
7257c478bd9Sstevel@tonic-gate ibt_status_t
7267c478bd9Sstevel@tonic-gate ibt_query_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_query_attr_t *qp_query_attrp)
7277c478bd9Sstevel@tonic-gate {
7287c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
7297c478bd9Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
7307c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		*qp_infop;
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_qp(%p, %p)",
7337c478bd9Sstevel@tonic-gate 	    ibt_qp, qp_query_attrp);
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
7367c478bd9Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_query_qp(
7377c478bd9Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), qp_query_attrp));
7387c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
7397c478bd9Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
7407c478bd9Sstevel@tonic-gate 		ibt_qp->ch_current_state = qp_query_attrp->qp_info.qp_state;
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 		/* need to fill in sgid from port and sgid_ix for RC and UC */
7437c478bd9Sstevel@tonic-gate 		hca_devp = ibt_qp->ch_qp.qp_hca->ha_hca_devp;
7447c478bd9Sstevel@tonic-gate 		qp_infop = &qp_query_attrp->qp_info;
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 		switch (qp_infop->qp_trans) {
7477c478bd9Sstevel@tonic-gate 		case IBT_RC_SRV:
7487c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_path,
7497c478bd9Sstevel@tonic-gate 			    hca_devp);
7507c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_alt_path,
7517c478bd9Sstevel@tonic-gate 			    hca_devp);
7527c478bd9Sstevel@tonic-gate 			break;
7537c478bd9Sstevel@tonic-gate 		case IBT_UC_SRV:
7547c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_path,
7557c478bd9Sstevel@tonic-gate 			    hca_devp);
7567c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_alt_path,
7577c478bd9Sstevel@tonic-gate 			    hca_devp);
7587c478bd9Sstevel@tonic-gate 			break;
7597c478bd9Sstevel@tonic-gate 		}
7607c478bd9Sstevel@tonic-gate 	} else {
7617c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_qp: "
7627c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
7637c478bd9Sstevel@tonic-gate 	}
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	return (retval);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate /*
7707c478bd9Sstevel@tonic-gate  * Function:
7717c478bd9Sstevel@tonic-gate  *	ibt_modify_qp
7727c478bd9Sstevel@tonic-gate  * Input:
7737c478bd9Sstevel@tonic-gate  *	ibt_qp		The IBT QP Handle.
7747c478bd9Sstevel@tonic-gate  *	flags		Specifies which attributes in ibt_qp_mod_attr_t
7757c478bd9Sstevel@tonic-gate  *			are to be modified.
7767c478bd9Sstevel@tonic-gate  *	qp_attrp	Points to an ibt_qp_mod_attr_t struct that contains all
7777c478bd9Sstevel@tonic-gate  *			the attributes of the specified QP that a client is
7787c478bd9Sstevel@tonic-gate  *			allowed to modify after a QP has been allocated
7797c478bd9Sstevel@tonic-gate  * Output:
7807c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual queue sizes.
7817c478bd9Sstevel@tonic-gate  * Returns:
7827c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
7837c478bd9Sstevel@tonic-gate  * Description:
7847c478bd9Sstevel@tonic-gate  *	Modify the attributes of an existing QP.
7857c478bd9Sstevel@tonic-gate  */
7867c478bd9Sstevel@tonic-gate ibt_status_t
7877c478bd9Sstevel@tonic-gate ibt_modify_qp(ibt_qp_hdl_t ibt_qp, ibt_cep_modify_flags_t flags,
7887c478bd9Sstevel@tonic-gate     ibt_qp_info_t *modify_attrp, ibt_queue_sizes_t *actual_sz)
7897c478bd9Sstevel@tonic-gate {
7907c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_qp(%p, %d, %p, %p)",
7937c478bd9Sstevel@tonic-gate 	    ibt_qp, flags, modify_attrp, actual_sz);
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
7967c478bd9Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_modify_qp)(
7977c478bd9Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), flags,
7987c478bd9Sstevel@tonic-gate 	    modify_attrp, actual_sz);
7997c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
8007c478bd9Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
8017c478bd9Sstevel@tonic-gate 		ibt_qp->ch_current_state = modify_attrp->qp_state;
8027c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_qp.qp_type == IBT_UD_SRV) {
8037c478bd9Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_PORT | IBT_CEP_SET_RESET_INIT))
8047c478bd9Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_port_num =
8057c478bd9Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_port;
8067c478bd9Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_QKEY | IBT_CEP_SET_RESET_INIT))
8077c478bd9Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_qkey =
8087c478bd9Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_qkey;
8097c478bd9Sstevel@tonic-gate 		}
8107c478bd9Sstevel@tonic-gate 	} else {
8117c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_qp: failed on chan %p: %d",
8127c478bd9Sstevel@tonic-gate 		    ibt_qp, retval);
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 		if (retval == IBT_CHAN_STATE_INVALID) {
8157c478bd9Sstevel@tonic-gate 			/* That means our cache had invalid QP state value. */
8167c478bd9Sstevel@tonic-gate 			ibt_qp_query_attr_t	qp_attr;
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 			/* Query the channel (QP) */
8197c478bd9Sstevel@tonic-gate 			if (ibt_query_qp(ibt_qp, &qp_attr) == IBT_SUCCESS)
8207c478bd9Sstevel@tonic-gate 				ibt_qp->ch_current_state =
8217c478bd9Sstevel@tonic-gate 				    qp_attr.qp_info.qp_state;
8227c478bd9Sstevel@tonic-gate 		}
8237c478bd9Sstevel@tonic-gate 	}
8247c478bd9Sstevel@tonic-gate 	return (retval);
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate /*
8297c478bd9Sstevel@tonic-gate  * Function:
8307c478bd9Sstevel@tonic-gate  *	ibt_migrate_path
8317c478bd9Sstevel@tonic-gate  * Input:
8327c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
8337c478bd9Sstevel@tonic-gate  * Output:
8347c478bd9Sstevel@tonic-gate  *	none.
8357c478bd9Sstevel@tonic-gate  * Returns:
8367c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS on Success else appropriate error.
8377c478bd9Sstevel@tonic-gate  * Description:
8387c478bd9Sstevel@tonic-gate  *	Force the CI to use the alternate path. The alternate path becomes
8397c478bd9Sstevel@tonic-gate  *	the primary path. A new alternate path should be loaded and enabled.
8407c478bd9Sstevel@tonic-gate  *	Assumes that the given channel is in RTS/SQD state
8417c478bd9Sstevel@tonic-gate  */
8427c478bd9Sstevel@tonic-gate ibt_status_t
8437c478bd9Sstevel@tonic-gate ibt_migrate_path(ibt_channel_hdl_t rc_chan)
8447c478bd9Sstevel@tonic-gate {
8457c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
8467c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		qp_info;
8477c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
8487c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	cep_flags;
8497c478bd9Sstevel@tonic-gate 	int			retries = 1;
8507c478bd9Sstevel@tonic-gate 
851934f0bccShiremath 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_migrate_path: channel %p", rc_chan);
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
8547c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: "
8557c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel");
8567c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_current_state != IBT_STATE_RTS &&
8607c478bd9Sstevel@tonic-gate 	    rc_chan->ch_current_state != IBT_STATE_SQD) {
8617c478bd9Sstevel@tonic-gate 		if (ibt_query_qp(rc_chan, &qp_attr) == IBT_SUCCESS) {
8627c478bd9Sstevel@tonic-gate 			/* ch_current_state is fixed by ibt_query_qp */
8637c478bd9Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
8647c478bd9Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
8657c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
8667c478bd9Sstevel@tonic-gate 			retries = 0;
8677c478bd9Sstevel@tonic-gate 		} else /* query_qp should never really fail */
8687c478bd9Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
8697c478bd9Sstevel@tonic-gate 	}
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate retry:
8727c478bd9Sstevel@tonic-gate 	/* Call modify_qp */
8737c478bd9Sstevel@tonic-gate 	cep_flags = IBT_CEP_SET_MIG | IBT_CEP_SET_STATE;
8747c478bd9Sstevel@tonic-gate 	qp_info.qp_state = rc_chan->ch_current_state;
8757c478bd9Sstevel@tonic-gate 	qp_info.qp_current_state = rc_chan->ch_current_state;
8767c478bd9Sstevel@tonic-gate 	qp_info.qp_trans = IBT_RC_SRV;
8777c478bd9Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_mig_state = IBT_STATE_MIGRATED;
8787c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, cep_flags, &qp_info, NULL);
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
8817c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
8827c478bd9Sstevel@tonic-gate 		    " ibt_modify_qp() returned = %d", retval);
8837c478bd9Sstevel@tonic-gate 		if (rc_chan->ch_current_state != qp_info.qp_state &&
8847c478bd9Sstevel@tonic-gate 		    --retries >= 0) {
8857c478bd9Sstevel@tonic-gate 			/*
8867c478bd9Sstevel@tonic-gate 			 * That means our cached 'state' was invalid.
8877c478bd9Sstevel@tonic-gate 			 * We know ibt_modify_qp() fixed it up, so it
8887c478bd9Sstevel@tonic-gate 			 * might be worth retrying.
8897c478bd9Sstevel@tonic-gate 			 */
8907c478bd9Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
8917c478bd9Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
8927c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
8937c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
8947c478bd9Sstevel@tonic-gate 			    " retrying after 'state' fixed");
8957c478bd9Sstevel@tonic-gate 			goto retry;
8967c478bd9Sstevel@tonic-gate 		}
8977c478bd9Sstevel@tonic-gate 	}
8987c478bd9Sstevel@tonic-gate 	return (retval);
8997c478bd9Sstevel@tonic-gate }
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate /*
9037c478bd9Sstevel@tonic-gate  * Function:
9047c478bd9Sstevel@tonic-gate  *	ibt_set_qp_private
9057c478bd9Sstevel@tonic-gate  * Input:
9067c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9077c478bd9Sstevel@tonic-gate  *	clnt_private	The client private data.
9087c478bd9Sstevel@tonic-gate  * Output:
9097c478bd9Sstevel@tonic-gate  *	none.
9107c478bd9Sstevel@tonic-gate  * Returns:
9117c478bd9Sstevel@tonic-gate  *	none.
9127c478bd9Sstevel@tonic-gate  * Description:
9137c478bd9Sstevel@tonic-gate  *	Set the client private data.
9147c478bd9Sstevel@tonic-gate  */
9157c478bd9Sstevel@tonic-gate void
9167c478bd9Sstevel@tonic-gate ibt_set_qp_private(ibt_qp_hdl_t ibt_qp, void *clnt_private)
9177c478bd9Sstevel@tonic-gate {
9187c478bd9Sstevel@tonic-gate 	ibt_qp->ch_clnt_private = clnt_private;
9197c478bd9Sstevel@tonic-gate }
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate /*
9237c478bd9Sstevel@tonic-gate  * Function:
9247c478bd9Sstevel@tonic-gate  *	ibt_get_qp_private
9257c478bd9Sstevel@tonic-gate  * Input:
9267c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9277c478bd9Sstevel@tonic-gate  * Output:
9287c478bd9Sstevel@tonic-gate  *	none.
9297c478bd9Sstevel@tonic-gate  * Returns:
9307c478bd9Sstevel@tonic-gate  *	The client private data.
9317c478bd9Sstevel@tonic-gate  * Description:
9327c478bd9Sstevel@tonic-gate  *	Get the client private data.
9337c478bd9Sstevel@tonic-gate  */
9347c478bd9Sstevel@tonic-gate void *
9357c478bd9Sstevel@tonic-gate ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)
9367c478bd9Sstevel@tonic-gate {
9377c478bd9Sstevel@tonic-gate 	return (ibt_qp->ch_clnt_private);
9387c478bd9Sstevel@tonic-gate }
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate /*
9427c478bd9Sstevel@tonic-gate  * Function:
9437c478bd9Sstevel@tonic-gate  *	ibt_qp_to_hca_guid
9447c478bd9Sstevel@tonic-gate  * Input:
9457c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9467c478bd9Sstevel@tonic-gate  * Output:
9477c478bd9Sstevel@tonic-gate  *	none.
9487c478bd9Sstevel@tonic-gate  * Returns:
9497c478bd9Sstevel@tonic-gate  *	hca_guid	Returned HCA GUID on which the specified QP is
9507c478bd9Sstevel@tonic-gate  *			allocated. Valid if it is non-NULL on return.
9517c478bd9Sstevel@tonic-gate  * Description:
9527c478bd9Sstevel@tonic-gate  *	A helper function to retrieve HCA GUID for the specified QP.
9537c478bd9Sstevel@tonic-gate  */
9547c478bd9Sstevel@tonic-gate ib_guid_t
9557c478bd9Sstevel@tonic-gate ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)
9567c478bd9Sstevel@tonic-gate {
9577c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_qp_to_hca_guid(%p)", ibt_qp);
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ibt_qp)));
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate /*
9647c478bd9Sstevel@tonic-gate  * Function:
9657c478bd9Sstevel@tonic-gate  *	ibt_recover_ud_qp
9667c478bd9Sstevel@tonic-gate  * Input:
9677c478bd9Sstevel@tonic-gate  *	ibt_qp		An QP Handle which is in SQError state.
9687c478bd9Sstevel@tonic-gate  * Output:
9697c478bd9Sstevel@tonic-gate  *	none.
9707c478bd9Sstevel@tonic-gate  * Returns:
9717c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
9727c478bd9Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
9737c478bd9Sstevel@tonic-gate  *	IBT_QP_STATE_INVALID.
9747c478bd9Sstevel@tonic-gate  * Description:
9757c478bd9Sstevel@tonic-gate  *	Recover an UD QP which has transitioned to SQ Error state. The
9767c478bd9Sstevel@tonic-gate  *	ibt_recover_ud_qp() transitions the QP from SQ Error state to
9777c478bd9Sstevel@tonic-gate  *	Ready-To-Send QP state.
9787c478bd9Sstevel@tonic-gate  *
9797c478bd9Sstevel@tonic-gate  *	If a work request posted to a UD QP's send queue completes with an
9807c478bd9Sstevel@tonic-gate  *	error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state.
9817c478bd9Sstevel@tonic-gate  *	In order to reuse this QP, ibt_recover_ud_qp() can be used to recover
9827c478bd9Sstevel@tonic-gate  *	the QP to a usable (Ready-to-Send) state.
9837c478bd9Sstevel@tonic-gate  */
9847c478bd9Sstevel@tonic-gate ibt_status_t
9857c478bd9Sstevel@tonic-gate ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)
9867c478bd9Sstevel@tonic-gate {
9877c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recover_ud_qp(%p)", ibt_qp);
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	return (ibt_recover_ud_channel(IBTL_QP2CHAN(ibt_qp)));
9907c478bd9Sstevel@tonic-gate }
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate /*
9947c478bd9Sstevel@tonic-gate  * Function:
9957c478bd9Sstevel@tonic-gate  *	ibt_recycle_ud
9967c478bd9Sstevel@tonic-gate  * Input:
9977c478bd9Sstevel@tonic-gate  *	ud_chan		The IBT UD QP Handle.
9987c478bd9Sstevel@tonic-gate  *	various attributes
9997c478bd9Sstevel@tonic-gate  *
10007c478bd9Sstevel@tonic-gate  * Output:
10017c478bd9Sstevel@tonic-gate  *	none
10027c478bd9Sstevel@tonic-gate  * Returns:
10037c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
10047c478bd9Sstevel@tonic-gate  *	IBT_CHAN_SRV_TYPE_INVALID
10057c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
10067c478bd9Sstevel@tonic-gate  *
10077c478bd9Sstevel@tonic-gate  * Description:
10087c478bd9Sstevel@tonic-gate  *	Revert the UD QP back to a usable state.
10097c478bd9Sstevel@tonic-gate  */
10107c478bd9Sstevel@tonic-gate ibt_status_t
10117c478bd9Sstevel@tonic-gate ibt_recycle_ud(ibt_channel_hdl_t ud_chan, uint8_t hca_port_num,
10127c478bd9Sstevel@tonic-gate     uint16_t pkey_ix, ib_qkey_t qkey)
10137c478bd9Sstevel@tonic-gate {
10147c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
10157c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recycle_ud(%p, %d, %x, %x): ",
10187c478bd9Sstevel@tonic-gate 	    ud_chan, hca_port_num, pkey_ix, qkey);
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
10217c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10227c478bd9Sstevel@tonic-gate 		    "chan %p is not a UD channel", ud_chan);
10237c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
10247c478bd9Sstevel@tonic-gate 	}
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(ud_chan, &qp_attr);
10277c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10287c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10297c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed on chan %p: %d", ud_chan, retval);
10307c478bd9Sstevel@tonic-gate 		return (retval);
10317c478bd9Sstevel@tonic-gate 	}
10327c478bd9Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR) {
10337c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10347c478bd9Sstevel@tonic-gate 		    "chan %p is in state %d (not in ERROR state)",
10357c478bd9Sstevel@tonic-gate 		    ud_chan, qp_attr.qp_info.qp_state);
10367c478bd9Sstevel@tonic-gate 		ud_chan->ch_current_state = qp_attr.qp_info.qp_state;
10377c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
10387c478bd9Sstevel@tonic-gate 	}
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 	/* transition the QP from ERROR to RESET */
10417c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_state = IBT_STATE_RESET;
10427c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_trans = ud_chan->ch_qp.qp_type;
10437c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &qp_attr.qp_info,
10447c478bd9Sstevel@tonic-gate 	    NULL);
10457c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10467c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10477c478bd9Sstevel@tonic-gate 		    "ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d",
10487c478bd9Sstevel@tonic-gate 		    ud_chan, retval);
10497c478bd9Sstevel@tonic-gate 		return (retval);
10507c478bd9Sstevel@tonic-gate 	}
10517c478bd9Sstevel@tonic-gate 	ud_chan->ch_current_state = IBT_STATE_RESET;
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate 	/* transition the QP back to RTS */
10547c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_port = hca_port_num;
10557c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_qkey = qkey;
10567c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_pkey_ix = pkey_ix;
10577c478bd9Sstevel@tonic-gate 	retval = ibt_initialize_qp(ud_chan, &qp_attr.qp_info);
10587c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10597c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10607c478bd9Sstevel@tonic-gate 		    "ibt_initialize_qp failed on chan %p: %d", ud_chan, retval);
10617c478bd9Sstevel@tonic-gate 		/* the man page says the QP should be left in ERROR state */
10627c478bd9Sstevel@tonic-gate 		(void) ibt_flush_qp(ud_chan);
10637c478bd9Sstevel@tonic-gate 	}
10647c478bd9Sstevel@tonic-gate 	return (retval);
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate /*
10687c478bd9Sstevel@tonic-gate  * Function:
10697c478bd9Sstevel@tonic-gate  *	ibt_pause_sendq
10707c478bd9Sstevel@tonic-gate  * Input:
10717c478bd9Sstevel@tonic-gate  *	chan		The IBT QP Handle.
10727c478bd9Sstevel@tonic-gate  *	modify_flags	IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT
10737c478bd9Sstevel@tonic-gate  *
10747c478bd9Sstevel@tonic-gate  * Output:
10757c478bd9Sstevel@tonic-gate  *	none.
10767c478bd9Sstevel@tonic-gate  * Returns:
10777c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
10787c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
10797c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
10807c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
10817c478bd9Sstevel@tonic-gate  *
10827c478bd9Sstevel@tonic-gate  * Description:
10837c478bd9Sstevel@tonic-gate  *	Place the send queue of the specified channel into the send queue
10847c478bd9Sstevel@tonic-gate  *	drained (SQD) state.
10857c478bd9Sstevel@tonic-gate  *
10867c478bd9Sstevel@tonic-gate  */
10877c478bd9Sstevel@tonic-gate ibt_status_t
10887c478bd9Sstevel@tonic-gate ibt_pause_sendq(ibt_channel_hdl_t chan, ibt_cep_modify_flags_t modify_flags)
10897c478bd9Sstevel@tonic-gate {
10907c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
10917c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_pause_sendq(%p, %x)", chan, modify_flags);
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	modify_flags &= IBT_CEP_SET_SQD_EVENT;	/* ignore other bits */
10967c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
10997c478bd9Sstevel@tonic-gate 	/*
11007c478bd9Sstevel@tonic-gate 	 * Set the QP state to SQD.
11017c478bd9Sstevel@tonic-gate 	 */
11027c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
11037c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11087c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_pause_sendq: "
11097c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
11107c478bd9Sstevel@tonic-gate 	}
11117c478bd9Sstevel@tonic-gate 	return (retval);
11127c478bd9Sstevel@tonic-gate }
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate /*
11167c478bd9Sstevel@tonic-gate  * Function:
11177c478bd9Sstevel@tonic-gate  *	ibt_unpause_sendq
11187c478bd9Sstevel@tonic-gate  * Input:
11197c478bd9Sstevel@tonic-gate  *	chan	The IBT Channel Handle.
11207c478bd9Sstevel@tonic-gate  * Output:
11217c478bd9Sstevel@tonic-gate  *	none.
11227c478bd9Sstevel@tonic-gate  * Returns:
11237c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
11247c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
11257c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
11267c478bd9Sstevel@tonic-gate  * Description:
11277c478bd9Sstevel@tonic-gate  *	Un-pauses the previously paused channel. This call will transition the
11287c478bd9Sstevel@tonic-gate  *	QP from SQD to RTS state.
11297c478bd9Sstevel@tonic-gate  */
11307c478bd9Sstevel@tonic-gate ibt_status_t
11317c478bd9Sstevel@tonic-gate ibt_unpause_sendq(ibt_channel_hdl_t chan)
11327c478bd9Sstevel@tonic-gate {
11337c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
11347c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_unpause_sendq(%p)", chan);
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 	/*
11417c478bd9Sstevel@tonic-gate 	 * Set the QP state to RTS.
11427c478bd9Sstevel@tonic-gate 	 */
11437c478bd9Sstevel@tonic-gate 	modify_attr.qp_current_state = IBT_STATE_SQD;
11447c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_RTS;
11457c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
11487c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11497c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_unpause_sendq: "
11507c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
11517c478bd9Sstevel@tonic-gate 	}
11527c478bd9Sstevel@tonic-gate 	return (retval);
11537c478bd9Sstevel@tonic-gate }
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate /*
11577c478bd9Sstevel@tonic-gate  * Function:
11587c478bd9Sstevel@tonic-gate  *	ibt_resize_queues
11597c478bd9Sstevel@tonic-gate  * Input:
11607c478bd9Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
11617c478bd9Sstevel@tonic-gate  *	flags		QP Flags
11627c478bd9Sstevel@tonic-gate  *				IBT_SEND_Q
11637c478bd9Sstevel@tonic-gate  *				IBT_RECV_Q
11647c478bd9Sstevel@tonic-gate  *	request_sz	Requested new sizes.
11657c478bd9Sstevel@tonic-gate  * Output:
11667c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
11677c478bd9Sstevel@tonic-gate  * Returns:
11687c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
11697c478bd9Sstevel@tonic-gate  * Description:
11707c478bd9Sstevel@tonic-gate  *	Resize the SendQ/RecvQ sizes of a channel. Can only be called on
11717c478bd9Sstevel@tonic-gate  *	a previously opened channel.
11727c478bd9Sstevel@tonic-gate  */
11737c478bd9Sstevel@tonic-gate ibt_status_t
11747c478bd9Sstevel@tonic-gate ibt_resize_queues(ibt_channel_hdl_t chan, ibt_qflags_t flags,
11757c478bd9Sstevel@tonic-gate     ibt_queue_sizes_t *request_sz, ibt_queue_sizes_t *actual_sz)
11767c478bd9Sstevel@tonic-gate {
11777c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags = IBT_CEP_SET_STATE;
11787c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
11797c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_resize_queues(%p, 0x%X, %p, %p)",
11827c478bd9Sstevel@tonic-gate 	    chan, flags, request_sz, actual_sz);
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	if ((flags & (IBT_SEND_Q | IBT_RECV_Q)) == 0)  {
11857c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
11867c478bd9Sstevel@tonic-gate 		    "Flags <0x%X> not set", flags);
11877c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
11887c478bd9Sstevel@tonic-gate 	}
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 	modify_attr.qp_current_state = chan->ch_current_state;
11937c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11947c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = chan->ch_current_state;
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 	if (flags & IBT_SEND_Q) {
11977c478bd9Sstevel@tonic-gate 		modify_attr.qp_sq_sz = request_sz->qs_sq;
11987c478bd9Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_SQ_SIZE;
11997c478bd9Sstevel@tonic-gate 	}
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 	if (flags & IBT_RECV_Q) {
12027c478bd9Sstevel@tonic-gate 		modify_attr.qp_rq_sz = request_sz->qs_rq;
12037c478bd9Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_RQ_SIZE;
12047c478bd9Sstevel@tonic-gate 	}
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, actual_sz);
12077c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
12087c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
12097c478bd9Sstevel@tonic-gate 		    "failed on QP %p: %d", chan, retval);
12107c478bd9Sstevel@tonic-gate 	}
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 	return (retval);
12137c478bd9Sstevel@tonic-gate }
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate /*
12177c478bd9Sstevel@tonic-gate  * Function:
12187c478bd9Sstevel@tonic-gate  *	ibt_query_queues
12197c478bd9Sstevel@tonic-gate  * Input:
12207c478bd9Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
12217c478bd9Sstevel@tonic-gate  * Output:
12227c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
12237c478bd9Sstevel@tonic-gate  * Returns:
12247c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
12257c478bd9Sstevel@tonic-gate  * Description:
12267c478bd9Sstevel@tonic-gate  *	Query the SendQ/RecvQ sizes of a channel.
12277c478bd9Sstevel@tonic-gate  */
12287c478bd9Sstevel@tonic-gate ibt_status_t
12297c478bd9Sstevel@tonic-gate ibt_query_queues(ibt_channel_hdl_t chan, ibt_queue_sizes_t *actual_sz)
12307c478bd9Sstevel@tonic-gate {
12317c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
12327c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_query_attr;
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_queues(%p)", chan);
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 	/* Perform Query QP and retrieve QP sizes. */
12377c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(chan, &qp_query_attr);
12387c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
12397c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_queues: "
12407c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed: qp %p: %d", chan, retval);
12417c478bd9Sstevel@tonic-gate 		return (retval);
12427c478bd9Sstevel@tonic-gate 	}
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
12457c478bd9Sstevel@tonic-gate 	    actual_sz->qs_sq))
12467c478bd9Sstevel@tonic-gate 	actual_sz->qs_sq = qp_query_attr.qp_info.qp_sq_sz;
12477c478bd9Sstevel@tonic-gate 	actual_sz->qs_rq = qp_query_attr.qp_info.qp_rq_sz;
12487c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
12497c478bd9Sstevel@tonic-gate 	    actual_sz->qs_sq))
12507c478bd9Sstevel@tonic-gate 	chan->ch_current_state = qp_query_attr.qp_info.qp_state;
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 	return (retval);
12537c478bd9Sstevel@tonic-gate }
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate /*
12577c478bd9Sstevel@tonic-gate  * Function:
12587c478bd9Sstevel@tonic-gate  *	ibt_modify_rdma
12597c478bd9Sstevel@tonic-gate  * Input:
12607c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated channel handle.
12617c478bd9Sstevel@tonic-gate  *
12627c478bd9Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
12637c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_R	Enable/Disable RDMA RD
12647c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_W	Enable/Disable RDMA WR
12657c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_ATOMIC	Enable/Disable Atomics
12667c478bd9Sstevel@tonic-gate  *
12677c478bd9Sstevel@tonic-gate  *	flags		Channel End Point (CEP) Disable Flags (0 => enable).
12687c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_RD	Disable incoming RDMA RD's
12697c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_WR	Disable incoming RDMA WR's
12707c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_ATOMIC	Disable incoming Atomics.
12717c478bd9Sstevel@tonic-gate  * Output:
12727c478bd9Sstevel@tonic-gate  *	none.
12737c478bd9Sstevel@tonic-gate  * Returns:
12747c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
12757c478bd9Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
12767c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
12777c478bd9Sstevel@tonic-gate  *	IBT_CHAN_ATOMICS_NOT_SUPPORTED
12787c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
12797c478bd9Sstevel@tonic-gate  * Description:
12807c478bd9Sstevel@tonic-gate  *	Enable/disable RDMA operations. To enable an operation clear the
12817c478bd9Sstevel@tonic-gate  *	"disable" flag. Can call this function when the channel is in
12827c478bd9Sstevel@tonic-gate  *	INIT, RTS or SQD states. If called in any other state
12837c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID is returned. When the operation completes the
12847c478bd9Sstevel@tonic-gate  *	channel state is left unchanged.
12857c478bd9Sstevel@tonic-gate  */
12867c478bd9Sstevel@tonic-gate ibt_status_t
12877c478bd9Sstevel@tonic-gate ibt_modify_rdma(ibt_channel_hdl_t rc_chan,
12887c478bd9Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, ibt_cep_flags_t flags)
12897c478bd9Sstevel@tonic-gate {
12907c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
12917c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_rdma(%p, 0x%x, 0x%x)",
12947c478bd9Sstevel@tonic-gate 	    rc_chan, modify_flags, flags);
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
12977c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
12987c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
12997c478bd9Sstevel@tonic-gate 		    rc_chan->ch_qp.qp_type);
13007c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
13017c478bd9Sstevel@tonic-gate 	}
13027c478bd9Sstevel@tonic-gate 
13037c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate 	/*
13067c478bd9Sstevel@tonic-gate 	 * Can only call this function when the channel in INIT, RTS or SQD
13077c478bd9Sstevel@tonic-gate 	 * states.
13087c478bd9Sstevel@tonic-gate 	 */
13097c478bd9Sstevel@tonic-gate 	if ((rc_chan->ch_current_state != IBT_STATE_INIT) &&
13107c478bd9Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_RTS) &&
13117c478bd9Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_SQD)) {
13127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: Invalid Channel "
13137c478bd9Sstevel@tonic-gate 		    "state: 0x%X", rc_chan->ch_current_state);
13147c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
13157c478bd9Sstevel@tonic-gate 	}
13167c478bd9Sstevel@tonic-gate 
13177c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = modify_attr.qp_current_state =
13187c478bd9Sstevel@tonic-gate 	    rc_chan->ch_current_state;
13197c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = rc_chan->ch_qp.qp_type;
13207c478bd9Sstevel@tonic-gate 	modify_attr.qp_flags = flags;
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
13237c478bd9Sstevel@tonic-gate 	    IBT_CEP_SET_ATOMIC);
13247c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, modify_flags, &modify_attr, NULL);
13277c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
13287c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
13297c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", rc_chan, retval);
13307c478bd9Sstevel@tonic-gate 	}
13317c478bd9Sstevel@tonic-gate 	return (retval);
13327c478bd9Sstevel@tonic-gate }
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate /*
13367c478bd9Sstevel@tonic-gate  * Function:
13377c478bd9Sstevel@tonic-gate  *	ibt_set_rdma_resource
13387c478bd9Sstevel@tonic-gate  * Input:
13397c478bd9Sstevel@tonic-gate  *	chan		A previously allocated RC channel handle.
13407c478bd9Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
13417c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_OUT	Initiator depth (rdma_ra_out)
13427c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_IN	Responder Resources
13437c478bd9Sstevel@tonic-gate  *						(rdma_ra_in)
13447c478bd9Sstevel@tonic-gate  *	rdma_ra_out	Outgoing RDMA Reads/Atomics
13457c478bd9Sstevel@tonic-gate  *	rdma_ra_in	Incoming RDMA Reads/Atomics
13467c478bd9Sstevel@tonic-gate  * Output:
13477c478bd9Sstevel@tonic-gate  *	none.
13487c478bd9Sstevel@tonic-gate  * Returns:
13497c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
13507c478bd9Sstevel@tonic-gate  * Description:
13517c478bd9Sstevel@tonic-gate  *	Change the number of resources to be used for incoming and outgoing
13527c478bd9Sstevel@tonic-gate  *	RDMA reads & Atomics. Can only be called on a previously opened
13537c478bd9Sstevel@tonic-gate  *	RC channel.  Can only be called on a paused channel, and this will
13547c478bd9Sstevel@tonic-gate  *	un-pause that channel.
13557c478bd9Sstevel@tonic-gate  */
13567c478bd9Sstevel@tonic-gate ibt_status_t
13577c478bd9Sstevel@tonic-gate ibt_set_rdma_resource(ibt_channel_hdl_t chan,
13587c478bd9Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, uint8_t rdma_ra_out,
13597c478bd9Sstevel@tonic-gate     uint8_t resp_rdma_ra_out)
13607c478bd9Sstevel@tonic-gate {
13617c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
13627c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_set_rdma_resource(%p, 0x%x, %d, %d)",
13657c478bd9Sstevel@tonic-gate 	    chan, modify_flags, rdma_ra_out, resp_rdma_ra_out);
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
13687c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
13697c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
13707c478bd9Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
13717c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
13727c478bd9Sstevel@tonic-gate 	}
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
13777c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_out = rdma_ra_out;
13807c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_in = resp_rdma_ra_out;
13817c478bd9Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN);
13827c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
13857c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
13867c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
13877c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
13887c478bd9Sstevel@tonic-gate 	}
13897c478bd9Sstevel@tonic-gate 	return (retval);
13907c478bd9Sstevel@tonic-gate }
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate /*
13947c478bd9Sstevel@tonic-gate  * Function:
13957c478bd9Sstevel@tonic-gate  *	ibt_change_port
13967c478bd9Sstevel@tonic-gate  * Input:
13977c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
13987c478bd9Sstevel@tonic-gate  *	port_num	New HCA port.
13997c478bd9Sstevel@tonic-gate  * Output:
14007c478bd9Sstevel@tonic-gate  *	none.
14017c478bd9Sstevel@tonic-gate  * Returns:
14027c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
14037c478bd9Sstevel@tonic-gate  * Description:
14047c478bd9Sstevel@tonic-gate  *	Change the primary physical port of a channel. (This is done only if
14057c478bd9Sstevel@tonic-gate  *	HCA supports this capability).
14067c478bd9Sstevel@tonic-gate  */
14077c478bd9Sstevel@tonic-gate ibt_status_t
14087c478bd9Sstevel@tonic-gate ibt_change_port(ibt_channel_hdl_t chan, uint8_t port_num)
14097c478bd9Sstevel@tonic-gate {
14107c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
14117c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
14127c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_change_port(%p, %d)", chan, port_num);
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
14177c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
14187c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
14197c478bd9Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
14207c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
14217c478bd9Sstevel@tonic-gate 	}
14227c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
14237c478bd9Sstevel@tonic-gate 
14247c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
14257c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
14267c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = port_num;
14277c478bd9Sstevel@tonic-gate 
14287c478bd9Sstevel@tonic-gate 	modify_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
14297c478bd9Sstevel@tonic-gate 
14307c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
14317c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
14327c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
14337c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
14347c478bd9Sstevel@tonic-gate 	}
14357c478bd9Sstevel@tonic-gate 	return (retval);
14367c478bd9Sstevel@tonic-gate }
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate void
14407c478bd9Sstevel@tonic-gate ibtl_init_cep_states(void)
14417c478bd9Sstevel@tonic-gate {
14427c478bd9Sstevel@tonic-gate 	int	index;
14437c478bd9Sstevel@tonic-gate 	int	ibt_nstate_inits;
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_init_cep_states()");
14467c478bd9Sstevel@tonic-gate 
14477c478bd9Sstevel@tonic-gate 	ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) /
14487c478bd9Sstevel@tonic-gate 	    sizeof (ibt_cep_next_state_inits[0]);
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 	/*
14517c478bd9Sstevel@tonic-gate 	 * Initialize CEP next state table, using an indirect lookup table so
14527c478bd9Sstevel@tonic-gate 	 * that this code isn't dependent on the ibt_cep_state_t enum values.
14537c478bd9Sstevel@tonic-gate 	 */
14547c478bd9Sstevel@tonic-gate 	for (index = 0; index < ibt_nstate_inits; index++) {
14557c478bd9Sstevel@tonic-gate 		ibt_cep_state_t	state;
14567c478bd9Sstevel@tonic-gate 
14577c478bd9Sstevel@tonic-gate 		state = ibt_cep_next_state_inits[index].current_state;
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate 		ibt_cep_next_state[state].next_state =
14607c478bd9Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].next_state;
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate 		ibt_cep_next_state[state].modify_flags =
14637c478bd9Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].modify_flags;
14647c478bd9Sstevel@tonic-gate 	}
14657c478bd9Sstevel@tonic-gate }
1466