xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_qp.c (revision 17a2b317)
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 /*
22a23420cfSShantkumar Hiremath  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl.h>
267c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_cm.h>
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * ibtl_qp.c
307c478bd9Sstevel@tonic-gate  *	These routines implement (most of) the verbs related to
317c478bd9Sstevel@tonic-gate  *	Queue Pairs.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /* Globals. */
357c478bd9Sstevel@tonic-gate static char ibtf_qp[] = "ibtl";
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /* This table indirectly initializes the ibt_cep_next_state[] table. */
387c478bd9Sstevel@tonic-gate typedef struct ibt_cep_next_state_s {
397c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		next_state;
407c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
417c478bd9Sstevel@tonic-gate } ibt_cep_next_state_t;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate struct	{
447c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		current_state;
457c478bd9Sstevel@tonic-gate 	ibt_cep_state_t		next_state;
467c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
477c478bd9Sstevel@tonic-gate } ibt_cep_next_state_inits[] = {
487c478bd9Sstevel@tonic-gate 	{ IBT_STATE_RESET, IBT_STATE_INIT, IBT_CEP_SET_RESET_INIT},
497c478bd9Sstevel@tonic-gate 	{ IBT_STATE_INIT, IBT_STATE_RTR, IBT_CEP_SET_INIT_RTR},
507c478bd9Sstevel@tonic-gate 	{ IBT_STATE_RTR, IBT_STATE_RTS, IBT_CEP_SET_RTR_RTS}
517c478bd9Sstevel@tonic-gate };
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate ibt_cep_next_state_t ibt_cep_next_state[IBT_STATE_NUM];
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique", ibt_cep_next_state))
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /* The following data and functions can increase system stability. */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate int ibtl_qp_calls_curr;
607c478bd9Sstevel@tonic-gate int ibtl_qp_calls_max = 128;	/* limit on # of simultaneous QP verb calls */
617c478bd9Sstevel@tonic-gate kmutex_t ibtl_qp_mutex;
627c478bd9Sstevel@tonic-gate kcondvar_t ibtl_qp_cv;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate void
ibtl_qp_flow_control_enter(void)657c478bd9Sstevel@tonic-gate ibtl_qp_flow_control_enter(void)
667c478bd9Sstevel@tonic-gate {
677c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_qp_mutex);
687c478bd9Sstevel@tonic-gate 	while (ibtl_qp_calls_curr >= ibtl_qp_calls_max) {
697c478bd9Sstevel@tonic-gate 		cv_wait(&ibtl_qp_cv, &ibtl_qp_mutex);
707c478bd9Sstevel@tonic-gate 	}
717c478bd9Sstevel@tonic-gate 	++ibtl_qp_calls_curr;
727c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_qp_mutex);
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate void
ibtl_qp_flow_control_exit(void)767c478bd9Sstevel@tonic-gate ibtl_qp_flow_control_exit(void)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_qp_mutex);
797c478bd9Sstevel@tonic-gate 	cv_signal(&ibtl_qp_cv);
807c478bd9Sstevel@tonic-gate 	--ibtl_qp_calls_curr;
817c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_qp_mutex);
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * Function:
867c478bd9Sstevel@tonic-gate  *	ibt_alloc_qp
877c478bd9Sstevel@tonic-gate  * Input:
887c478bd9Sstevel@tonic-gate  *	hca_hdl		HCA Handle.
897c478bd9Sstevel@tonic-gate  *	type		Specifies the type of QP to alloc in ibt_alloc_qp()
907c478bd9Sstevel@tonic-gate  *	qp_attrp	Specifies the ibt_qp_alloc_attr_t that are needed to
917c478bd9Sstevel@tonic-gate  *			allocate a QP and transition it to the RTS state for
927c478bd9Sstevel@tonic-gate  *			UDs and INIT state for all other QPs.
937c478bd9Sstevel@tonic-gate  * Output:
947c478bd9Sstevel@tonic-gate  *	queue_sizes_p	Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
957c478bd9Sstevel@tonic-gate  *			WR SGL elements.
967c478bd9Sstevel@tonic-gate  *	qpn_p		Returned QP Number of the allocated QP.
977c478bd9Sstevel@tonic-gate  *	ibt_qp_p	The ibt_qp_hdl_t of the allocated QP.
987c478bd9Sstevel@tonic-gate  * Returns:
997c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
1007c478bd9Sstevel@tonic-gate  * Description:
1017c478bd9Sstevel@tonic-gate  *	Allocate a QP with specified attributes.
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate ibt_status_t
ibt_alloc_qp(ibt_hca_hdl_t hca_hdl,ibt_qp_type_t type,ibt_qp_alloc_attr_t * qp_attrp,ibt_chan_sizes_t * queue_sizes_p,ib_qpn_t * qpn_p,ibt_qp_hdl_t * ibt_qp_p)1047c478bd9Sstevel@tonic-gate ibt_alloc_qp(ibt_hca_hdl_t hca_hdl, ibt_qp_type_t type,
1057c478bd9Sstevel@tonic-gate     ibt_qp_alloc_attr_t *qp_attrp, ibt_chan_sizes_t *queue_sizes_p,
1067c478bd9Sstevel@tonic-gate     ib_qpn_t *qpn_p, ibt_qp_hdl_t *ibt_qp_p)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
1097c478bd9Sstevel@tonic-gate 	ibtl_channel_t		*chanp;
1107c478bd9Sstevel@tonic-gate 	ibt_tran_srv_t		qp_type;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_alloc_qp(%p, %d, %p, %p, %p, %p) ",
1137c478bd9Sstevel@tonic-gate 	    hca_hdl, type, qp_attrp, queue_sizes_p, qpn_p, ibt_qp_p);
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	switch (type) {
1167c478bd9Sstevel@tonic-gate 	case IBT_UD_RQP:
1177c478bd9Sstevel@tonic-gate 		qp_type = IBT_UD_SRV;
1187c478bd9Sstevel@tonic-gate 		break;
1197c478bd9Sstevel@tonic-gate 	case IBT_RC_RQP:
1207c478bd9Sstevel@tonic-gate 		qp_type = IBT_RC_SRV;
1217c478bd9Sstevel@tonic-gate 		break;
1227c478bd9Sstevel@tonic-gate 	case IBT_UC_RQP:
1237c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Unreliable Connected "
1247c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
1257c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1267c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
1277c478bd9Sstevel@tonic-gate 	case IBT_RD_RQP:
1287c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Reliable Datagram "
1297c478bd9Sstevel@tonic-gate 		    "Transport Type is not supported.");
1307c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1317c478bd9Sstevel@tonic-gate 		return (IBT_NOT_SUPPORTED);
1327c478bd9Sstevel@tonic-gate 	default:
1337c478bd9Sstevel@tonic-gate 		/* shouldn't happen ILLEGAL Type */
1347c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: Illegal Transport Type "
1357c478bd9Sstevel@tonic-gate 		    "%d", type);
1367c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1377c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	/* Get CI CQ handles */
141*17a2b317SBill Taylor 	qp_attrp->qp_ibc_scq_hdl = (qp_attrp->qp_scq_hdl == NULL) ? NULL :
142*17a2b317SBill Taylor 	    qp_attrp->qp_scq_hdl->cq_ibc_cq_hdl;
143*17a2b317SBill Taylor 	qp_attrp->qp_ibc_rcq_hdl = (qp_attrp->qp_rcq_hdl == NULL) ? NULL :
144*17a2b317SBill Taylor 	    qp_attrp->qp_rcq_hdl->cq_ibc_cq_hdl;
1457c478bd9Sstevel@tonic-gate 
146*17a2b317SBill Taylor 	/* Get CI SRQ handle */
1477c478bd9Sstevel@tonic-gate 	if ((qp_attrp->qp_alloc_flags & IBT_QP_USES_SRQ) &&
1487c478bd9Sstevel@tonic-gate 	    (qp_attrp->qp_srq_hdl != NULL))
1497c478bd9Sstevel@tonic-gate 		qp_attrp->qp_ibc_srq_hdl =
1507c478bd9Sstevel@tonic-gate 		    qp_attrp->qp_srq_hdl->srq_ibc_srq_hdl;
1517c478bd9Sstevel@tonic-gate 	else
1527c478bd9Sstevel@tonic-gate 		qp_attrp->qp_ibc_srq_hdl = NULL;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* Allocate Channel structure */
1557c478bd9Sstevel@tonic-gate 	chanp = kmem_zalloc(sizeof (*chanp), KM_SLEEP);
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
1587c478bd9Sstevel@tonic-gate 	retval = (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_qp)(
1597c478bd9Sstevel@tonic-gate 	    IBTL_HCA2CIHCA(hca_hdl), &chanp->ch_qp, type, qp_attrp,
1607c478bd9Sstevel@tonic-gate 	    queue_sizes_p, qpn_p, &chanp->ch_qp.qp_ibc_qp_hdl);
1617c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
1627c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
1637c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_alloc_qp: "
1647c478bd9Sstevel@tonic-gate 		    "Failed to allocate QP: %d", retval);
1657c478bd9Sstevel@tonic-gate 		kmem_free(chanp, sizeof (*chanp));
1667c478bd9Sstevel@tonic-gate 		*ibt_qp_p = NULL;
1677c478bd9Sstevel@tonic-gate 		return (retval);
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	/* Initialize the internal QP struct. */
1717c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_type = qp_type;
1727c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_hca = hca_hdl;
1737c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_send_cq = qp_attrp->qp_scq_hdl;
1747c478bd9Sstevel@tonic-gate 	chanp->ch_qp.qp_recv_cq = qp_attrp->qp_rcq_hdl;
1757c478bd9Sstevel@tonic-gate 	chanp->ch_current_state = IBT_STATE_RESET;
176f07a6d2aSShantkumar Hiremath 	/*
177f07a6d2aSShantkumar Hiremath 	 * The IBTA spec does not include the signal type or PD on a QP
178f07a6d2aSShantkumar Hiremath 	 * query operation. In order to implement the "CLONE" feature
179f07a6d2aSShantkumar Hiremath 	 * we need to cache these values.  Mostly used by TI client.
180f07a6d2aSShantkumar Hiremath 	 */
181f07a6d2aSShantkumar Hiremath 	chanp->ch_qp.qp_flags = qp_attrp->qp_flags;
182f07a6d2aSShantkumar Hiremath 	chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl;
1837c478bd9Sstevel@tonic-gate 	mutex_init(&chanp->ch_cm_mutex, NULL, MUTEX_DEFAULT, NULL);
1847c478bd9Sstevel@tonic-gate 	cv_init(&chanp->ch_cm_cv, NULL, CV_DEFAULT, NULL);
1857c478bd9Sstevel@tonic-gate 
186f7327bbdSBill Taylor 	atomic_inc_32(&hca_hdl->ha_qp_cnt);
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
ibt_initialize_qp(ibt_qp_hdl_t ibt_qp,ibt_qp_info_t * modify_attrp)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
ibt_alloc_special_qp(ibt_hca_hdl_t hca_hdl,uint8_t port,ibt_sqp_type_t type,ibt_qp_alloc_attr_t * qp_attrp,ibt_chan_sizes_t * queue_sizes_p,ibt_qp_hdl_t * ibt_qp_p)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 
388f07a6d2aSShantkumar Hiremath 	/* Updating these variable, so that debugger shows correct values. */
389f07a6d2aSShantkumar Hiremath 	chanp->ch_qp.qp_flags = qp_attrp->qp_flags;
390f07a6d2aSShantkumar Hiremath 	chanp->ch_qp.qp_pd_hdl = qp_attrp->qp_pd_hdl;
391f07a6d2aSShantkumar Hiremath 
392f7327bbdSBill Taylor 	atomic_inc_32(&hca_hdl->ha_qp_cnt);
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	*ibt_qp_p = chanp;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	return (retval);
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate /*
4017c478bd9Sstevel@tonic-gate  * Function:
4027c478bd9Sstevel@tonic-gate  *	ibt_flush_qp
4037c478bd9Sstevel@tonic-gate  * Input:
4047c478bd9Sstevel@tonic-gate  *	ibtl_qp		Handle for QP that needs to be flushed.
4057c478bd9Sstevel@tonic-gate  * Output:
4067c478bd9Sstevel@tonic-gate  *	none.
4077c478bd9Sstevel@tonic-gate  * Returns:
4087c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
4097c478bd9Sstevel@tonic-gate  *	IBT_QP_HDL_INVALID
4107c478bd9Sstevel@tonic-gate  * Description:
4117c478bd9Sstevel@tonic-gate  *	Put the QP into error state to flush out work requests.
4127c478bd9Sstevel@tonic-gate  */
4137c478bd9Sstevel@tonic-gate ibt_status_t
ibt_flush_qp(ibt_qp_hdl_t ibt_qp)4147c478bd9Sstevel@tonic-gate ibt_flush_qp(ibt_qp_hdl_t ibt_qp)
4157c478bd9Sstevel@tonic-gate {
4167c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
4177c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_flush_qp(%p)", ibt_qp);
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
4227c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
423d99cb22fSagiri 		if ((ibt_qp->ch_transport.rc.rc_free_flags &
424d99cb22fSagiri 		    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
4257c478bd9Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
4267c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
4277c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp(%p): "
4287c478bd9Sstevel@tonic-gate 			    "called with a connected RC QP", ibt_qp);
4297c478bd9Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
4307c478bd9Sstevel@tonic-gate 		}
4317c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
4327c478bd9Sstevel@tonic-gate 	}
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	/*
4377c478bd9Sstevel@tonic-gate 	 * Set the QP state to error to flush any uncompleted WRs.
4387c478bd9Sstevel@tonic-gate 	 */
4397c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_ERROR;
4407c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = ibt_qp->ch_qp.qp_type;
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(ibt_qp, IBT_CEP_SET_STATE, &modify_attr, NULL);
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
4457c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_flush_qp: "
4467c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
4477c478bd9Sstevel@tonic-gate 	}
4487c478bd9Sstevel@tonic-gate 	return (retval);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate /*
4539c468ea9SPramod Gunjikar  * ibtl_cm_chan_is_opening()
4549c468ea9SPramod Gunjikar  *
4559c468ea9SPramod Gunjikar  *	Inform IBTL that the connection established process is in progress
4569c468ea9SPramod Gunjikar  *	on this channel so that care need to be taken while free'ing when
4579c468ea9SPramod Gunjikar  *	open is NOT yet complete.
4589c468ea9SPramod Gunjikar  *
4599c468ea9SPramod Gunjikar  *	chan	Channel Handle
4609c468ea9SPramod Gunjikar  */
4619c468ea9SPramod Gunjikar void
ibtl_cm_chan_is_opening(ibt_channel_hdl_t chan)4629c468ea9SPramod Gunjikar ibtl_cm_chan_is_opening(ibt_channel_hdl_t chan)
4639c468ea9SPramod Gunjikar {
4649c468ea9SPramod Gunjikar 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_opening(%p)", chan);
4659c468ea9SPramod Gunjikar 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
4669c468ea9SPramod Gunjikar 	mutex_enter(&ibtl_free_qp_mutex);
4679c468ea9SPramod Gunjikar 	ASSERT(chan->ch_transport.rc.rc_free_flags == 0);
4689c468ea9SPramod Gunjikar 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTING;
4699c468ea9SPramod Gunjikar 	mutex_exit(&ibtl_free_qp_mutex);
4709c468ea9SPramod Gunjikar }
4719c468ea9SPramod Gunjikar 
4729c468ea9SPramod Gunjikar /*
473a23420cfSShantkumar Hiremath  * ibtl_cm_chan_open_is_aborted()
474a23420cfSShantkumar Hiremath  *
475a23420cfSShantkumar Hiremath  *	Inform IBTL that the connection established on this channel has
476a23420cfSShantkumar Hiremath  *	aborted. So undo what was done in ibtl_cm_chan_is_opening().
477a23420cfSShantkumar Hiremath  *
478a23420cfSShantkumar Hiremath  *	chan	Channel Handle
479a23420cfSShantkumar Hiremath  */
480a23420cfSShantkumar Hiremath void
ibtl_cm_chan_open_is_aborted(ibt_channel_hdl_t chan)481a23420cfSShantkumar Hiremath ibtl_cm_chan_open_is_aborted(ibt_channel_hdl_t chan)
482a23420cfSShantkumar Hiremath {
483a23420cfSShantkumar Hiremath 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_open_is_aborted(%p)", chan);
484a23420cfSShantkumar Hiremath 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
485a23420cfSShantkumar Hiremath 	mutex_enter(&ibtl_free_qp_mutex);
486a23420cfSShantkumar Hiremath 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING;
487a23420cfSShantkumar Hiremath 	mutex_exit(&ibtl_free_qp_mutex);
488a23420cfSShantkumar Hiremath }
489a23420cfSShantkumar Hiremath 
490a23420cfSShantkumar Hiremath /*
4917c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_open()
4927c478bd9Sstevel@tonic-gate  *
4937c478bd9Sstevel@tonic-gate  *	Inform IBTL that the connection has been established on this
4947c478bd9Sstevel@tonic-gate  *	channel so that a later call to ibtl_cm_chan_is_closed()
4957c478bd9Sstevel@tonic-gate  *	will be required to free the QPN used by this channel.
4967c478bd9Sstevel@tonic-gate  *
4977c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
4987c478bd9Sstevel@tonic-gate  */
4997c478bd9Sstevel@tonic-gate void
ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)5007c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_open(ibt_channel_hdl_t chan)
5017c478bd9Sstevel@tonic-gate {
5027c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_open(%p)", chan);
5037c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5047c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5059c468ea9SPramod Gunjikar 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTING;
5067c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CONNECTED;
5077c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate /*
5117c478bd9Sstevel@tonic-gate  * ibtl_cm_is_chan_closing()
5127c478bd9Sstevel@tonic-gate  *
5137c478bd9Sstevel@tonic-gate  *	Returns 1, if the connection that has been
5147c478bd9Sstevel@tonic-gate  *	started for this channel has moved to TIMEWAIT
5157c478bd9Sstevel@tonic-gate  *	If not, returns 0
5167c478bd9Sstevel@tonic-gate  *
5177c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5187c478bd9Sstevel@tonic-gate  */
5197c478bd9Sstevel@tonic-gate int
ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)5207c478bd9Sstevel@tonic-gate ibtl_cm_is_chan_closing(ibt_channel_hdl_t chan)
5217c478bd9Sstevel@tonic-gate {
5227c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closing(%p)", chan);
5237c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5247c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5257c478bd9Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSING) {
5267c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
5277c478bd9Sstevel@tonic-gate 		return (1);
5287c478bd9Sstevel@tonic-gate 	}
5297c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5307c478bd9Sstevel@tonic-gate 	return (0);
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate  * ibtl_cm_is_chan_closed()
5357c478bd9Sstevel@tonic-gate  *
5367c478bd9Sstevel@tonic-gate  *	Returns 1, if the connection that has been
5377c478bd9Sstevel@tonic-gate  *	started for this channel has completed TIMEWAIT
5387c478bd9Sstevel@tonic-gate  *	If not, returns 0
5397c478bd9Sstevel@tonic-gate  *
5407c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5417c478bd9Sstevel@tonic-gate  */
5427c478bd9Sstevel@tonic-gate int
ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)5437c478bd9Sstevel@tonic-gate ibtl_cm_is_chan_closed(ibt_channel_hdl_t chan)
5447c478bd9Sstevel@tonic-gate {
5457c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_is_chan_closed(%p)", chan);
5467c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5477c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5487c478bd9Sstevel@tonic-gate 	if (chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CLOSED) {
5497c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
5507c478bd9Sstevel@tonic-gate 		return (1);
5517c478bd9Sstevel@tonic-gate 	}
5527c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5537c478bd9Sstevel@tonic-gate 	return (0);
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate /*
5567c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_closing()
5577c478bd9Sstevel@tonic-gate  *
5587c478bd9Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
5597c478bd9Sstevel@tonic-gate  *	started for this channel so that the QP can be freed.
5607c478bd9Sstevel@tonic-gate  *
5617c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5627c478bd9Sstevel@tonic-gate  */
5637c478bd9Sstevel@tonic-gate void
ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)5647c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_closing(ibt_channel_hdl_t chan)
5657c478bd9Sstevel@tonic-gate {
5667c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closing(%p)", chan);
5677c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5687c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5697c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_transport.rc.rc_free_flags == IBTL_RC_QP_CONNECTED);
5707c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSING;
5717c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate /*
5747c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_closed()
5757c478bd9Sstevel@tonic-gate  *
5767c478bd9Sstevel@tonic-gate  *	Inform IBTL that the TIMEWAIT delay for the connection has been
5777c478bd9Sstevel@tonic-gate  *	reached for this channel so that the QPN can be reused.
5787c478bd9Sstevel@tonic-gate  *
5797c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
5807c478bd9Sstevel@tonic-gate  */
5817c478bd9Sstevel@tonic-gate void
ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)5827c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_closed(ibt_channel_hdl_t chan)
5837c478bd9Sstevel@tonic-gate {
5847c478bd9Sstevel@tonic-gate 	ibt_status_t status;
5857c478bd9Sstevel@tonic-gate 	ibtl_hca_t *ibtl_hca = chan->ch_qp.qp_hca;
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_closed(%p)", chan);
5887c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
5897c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
5907c478bd9Sstevel@tonic-gate 	ASSERT((chan->ch_transport.rc.rc_free_flags &
5917c478bd9Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING)) ==
5927c478bd9Sstevel@tonic-gate 	    (IBTL_RC_QP_CONNECTED | IBTL_RC_QP_CLOSING));
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CONNECTED;
5957c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags &= ~IBTL_RC_QP_CLOSING;
5967c478bd9Sstevel@tonic-gate 	chan->ch_transport.rc.rc_free_flags |= IBTL_RC_QP_CLOSED;
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	ibtl_cm_set_chan_private(chan, NULL);
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	if ((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_FREED) == 0) {
6017c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
6027c478bd9Sstevel@tonic-gate 		return;
6037c478bd9Sstevel@tonic-gate 	}
6047c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
6057c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
6067c478bd9Sstevel@tonic-gate 	if ((status = (IBTL_CHAN2CIHCAOPS_P(chan)->ibc_release_qpn)
6077c478bd9Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(chan), chan->ch_transport.rc.rc_qpn_hdl)) ==
6087c478bd9Sstevel@tonic-gate 	    IBT_SUCCESS) {
6097c478bd9Sstevel@tonic-gate 		/* effectively, this is kmem_free(chan); */
6107c478bd9Sstevel@tonic-gate 		ibtl_free_qp_async_check(&chan->ch_qp);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 		/* decrement ha_qpn_cnt and check for close in progress */
6137c478bd9Sstevel@tonic-gate 		ibtl_close_hca_check(ibtl_hca);
6147c478bd9Sstevel@tonic-gate 	} else
615934f0bccShiremath 		IBTF_DPRINTF_L2(ibtf_qp, "ibtl_cm_chan_is_closed: "
6167c478bd9Sstevel@tonic-gate 		    "ibc_release_qpn failed: status = %d\n", status);
6177c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate /*
6217c478bd9Sstevel@tonic-gate  * ibtl_cm_chan_is_reused()
6227c478bd9Sstevel@tonic-gate  *
6237c478bd9Sstevel@tonic-gate  *	Inform IBTL that the channel is going to be re-used
6247c478bd9Sstevel@tonic-gate  *	chan	Channel Handle
6257c478bd9Sstevel@tonic-gate  */
6267c478bd9Sstevel@tonic-gate void
ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)6277c478bd9Sstevel@tonic-gate ibtl_cm_chan_is_reused(ibt_channel_hdl_t chan)
6287c478bd9Sstevel@tonic-gate {
6297c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_cm_chan_is_reused(%p)", chan);
6307c478bd9Sstevel@tonic-gate 	ASSERT(chan->ch_qp.qp_type == IBT_RC_SRV);
6317c478bd9Sstevel@tonic-gate 	mutex_enter(&ibtl_free_qp_mutex);
6327c478bd9Sstevel@tonic-gate 	ASSERT(((chan->ch_transport.rc.rc_free_flags & IBTL_RC_QP_CONNECTED) !=
6337c478bd9Sstevel@tonic-gate 	    IBTL_RC_QP_CONNECTED));
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 	/* channel is no longer in closed state, shall be re-used */
636934f0bccShiremath 	chan->ch_transport.rc.rc_free_flags = 0;
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	mutex_exit(&ibtl_free_qp_mutex);
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate /*
6437c478bd9Sstevel@tonic-gate  * Function:	ibt_free_qp()
6447c478bd9Sstevel@tonic-gate  *
6457c478bd9Sstevel@tonic-gate  * Input:	ibt_qp		Handle for Channel(QP) that needs to be freed.
6467c478bd9Sstevel@tonic-gate  *
6477c478bd9Sstevel@tonic-gate  * Output:	NONE.
6487c478bd9Sstevel@tonic-gate  *
6497c478bd9Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
6507c478bd9Sstevel@tonic-gate  *		IBT_QP_STATE_INVALID
6517c478bd9Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
6527c478bd9Sstevel@tonic-gate  *
6537c478bd9Sstevel@tonic-gate  * Description:
6547c478bd9Sstevel@tonic-gate  *		Free a previously allocated QP.
6557c478bd9Sstevel@tonic-gate  */
6567c478bd9Sstevel@tonic-gate ibt_status_t
ibt_free_qp(ibt_qp_hdl_t ibt_qp)6577c478bd9Sstevel@tonic-gate ibt_free_qp(ibt_qp_hdl_t ibt_qp)
6587c478bd9Sstevel@tonic-gate {
6597c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
6607c478bd9Sstevel@tonic-gate 	ibtl_hca_t		*ibtl_hca = ibt_qp->ch_qp.qp_hca;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p)", ibt_qp);
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	if (ibt_qp->ch_qp.qp_type == IBT_RC_SRV) {
6657c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
6667c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_free_qp_mutex);
6677c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_transport.rc.rc_free_flags &
6689c468ea9SPramod Gunjikar 		    IBTL_RC_QP_CONNECTING) {
6699c468ea9SPramod Gunjikar 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
6709c468ea9SPramod Gunjikar 			    "Channel establishment is still in PROGRESS.");
6719c468ea9SPramod Gunjikar 			mutex_exit(&ibtl_free_qp_mutex);
6729c468ea9SPramod Gunjikar 			ibtl_qp_flow_control_exit();
6739c468ea9SPramod Gunjikar 			return (IBT_CHAN_STATE_INVALID);
6749c468ea9SPramod Gunjikar 		}
6759c468ea9SPramod Gunjikar 		if (ibt_qp->ch_transport.rc.rc_free_flags &
6767c478bd9Sstevel@tonic-gate 		    IBTL_RC_QP_CONNECTED) {
6777c478bd9Sstevel@tonic-gate 			if ((ibt_qp->ch_transport.rc.rc_free_flags &
6787c478bd9Sstevel@tonic-gate 			    IBTL_RC_QP_CLOSING) == 0) {
6797c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: ERROR - "
6807c478bd9Sstevel@tonic-gate 				    "need to call ibt_close_rc_channel");
6817c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_free_qp_mutex);
6827c478bd9Sstevel@tonic-gate 				ibtl_qp_flow_control_exit();
6837c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
6847c478bd9Sstevel@tonic-gate 			}
6857c478bd9Sstevel@tonic-gate 			ibt_qp->ch_transport.rc.rc_free_flags |=
6867c478bd9Sstevel@tonic-gate 			    IBTL_RC_QP_FREED;
6877c478bd9Sstevel@tonic-gate 			status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
6887c478bd9Sstevel@tonic-gate 			    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
6897c478bd9Sstevel@tonic-gate 			    IBC_FREE_QP_ONLY,
6907c478bd9Sstevel@tonic-gate 			    &ibt_qp->ch_transport.rc.rc_qpn_hdl);
6917c478bd9Sstevel@tonic-gate 			mutex_exit(&ibtl_free_qp_mutex);
6927c478bd9Sstevel@tonic-gate 			ibtl_qp_flow_control_exit();
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 			if (status == IBT_SUCCESS) {
6957c478bd9Sstevel@tonic-gate 				mutex_enter(&ibtl_clnt_list_mutex);
6967c478bd9Sstevel@tonic-gate 				ibtl_hca->ha_qpn_cnt++;
6977c478bd9Sstevel@tonic-gate 				mutex_exit(&ibtl_clnt_list_mutex);
698f7327bbdSBill Taylor 				atomic_dec_32(&ibtl_hca->ha_qp_cnt);
699934f0bccShiremath 				IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - "
7007c478bd9Sstevel@tonic-gate 				    "SUCCESS", ibt_qp);
7017c478bd9Sstevel@tonic-gate 			} else
7027c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
7037c478bd9Sstevel@tonic-gate 				    "ibc_free_qp failed: status = %d", status);
7047c478bd9Sstevel@tonic-gate 			return (status);
7057c478bd9Sstevel@tonic-gate 		}
7067c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_free_qp_mutex);
7077c478bd9Sstevel@tonic-gate 	} else
7087c478bd9Sstevel@tonic-gate 		ibtl_qp_flow_control_enter();
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	status = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_free_qp)
7117c478bd9Sstevel@tonic-gate 	    (IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp),
7127c478bd9Sstevel@tonic-gate 	    IBC_FREE_QP_AND_QPN, NULL);
7137c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	if (status == IBT_SUCCESS) {
7167c478bd9Sstevel@tonic-gate 		/* effectively, this is kmem_free(ibt_qp); */
7177c478bd9Sstevel@tonic-gate 		ibtl_free_qp_async_check(&ibt_qp->ch_qp);
7187c478bd9Sstevel@tonic-gate 
719f7327bbdSBill Taylor 		atomic_dec_32(&ibtl_hca->ha_qp_cnt);
720934f0bccShiremath 		IBTF_DPRINTF_L3(ibtf_qp, "ibt_free_qp(%p) - SUCCESS", ibt_qp);
7217c478bd9Sstevel@tonic-gate 	} else {
7227c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_free_qp: "
7237c478bd9Sstevel@tonic-gate 		    "ibc_free_qp failed with error %d", status);
7247c478bd9Sstevel@tonic-gate 	}
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	return (status);
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate /* helper function for ibt_query_qp */
7317c478bd9Sstevel@tonic-gate static void
ibtl_fillin_sgid(ibt_cep_path_t * pathp,ibtl_hca_devinfo_t * hca_devp)7327c478bd9Sstevel@tonic-gate ibtl_fillin_sgid(ibt_cep_path_t *pathp, ibtl_hca_devinfo_t *hca_devp)
7337c478bd9Sstevel@tonic-gate {
7347c478bd9Sstevel@tonic-gate 	uint8_t port;
7357c478bd9Sstevel@tonic-gate 	uint32_t sgid_ix;
7367c478bd9Sstevel@tonic-gate 	ib_gid_t *sgidp;
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	port = pathp->cep_hca_port_num;
7397c478bd9Sstevel@tonic-gate 	sgid_ix = pathp->cep_adds_vect.av_sgid_ix;
7407c478bd9Sstevel@tonic-gate 	if (port == 0 || port > hca_devp->hd_hca_attr->hca_nports ||
7417c478bd9Sstevel@tonic-gate 	    sgid_ix >= IBTL_HDIP2SGIDTBLSZ(hca_devp)) {
7427c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_prefix = 0;
7437c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid.gid_guid = 0;
7447c478bd9Sstevel@tonic-gate 	} else {
7457c478bd9Sstevel@tonic-gate 		mutex_enter(&ibtl_clnt_list_mutex);
7467c478bd9Sstevel@tonic-gate 		sgidp = hca_devp->hd_portinfop[port-1].p_sgid_tbl;
7477c478bd9Sstevel@tonic-gate 		pathp->cep_adds_vect.av_sgid = sgidp[sgid_ix];
7487c478bd9Sstevel@tonic-gate 		mutex_exit(&ibtl_clnt_list_mutex);
7497c478bd9Sstevel@tonic-gate 	}
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate /*
7547c478bd9Sstevel@tonic-gate  * Function:	ibt_query_qp
7557c478bd9Sstevel@tonic-gate  *
7567c478bd9Sstevel@tonic-gate  * Input:	ibt_qp 			- The IBT QP Handle.
7577c478bd9Sstevel@tonic-gate  *
7587c478bd9Sstevel@tonic-gate  * Output:	ibt_qp_query_attrp 	- Points to a ibt_qp_query_attr_t
7597c478bd9Sstevel@tonic-gate  *					  that on return contains all the
7607c478bd9Sstevel@tonic-gate  *					  attributes of the specified qp.
7617c478bd9Sstevel@tonic-gate  *
7627c478bd9Sstevel@tonic-gate  * Returns:	IBT_SUCCESS
7637c478bd9Sstevel@tonic-gate  *		IBT_QP_HDL_INVALID
7647c478bd9Sstevel@tonic-gate  *
7657c478bd9Sstevel@tonic-gate  * Description:
7667c478bd9Sstevel@tonic-gate  *		Query QP attributes
7677c478bd9Sstevel@tonic-gate  *
7687c478bd9Sstevel@tonic-gate  */
7697c478bd9Sstevel@tonic-gate ibt_status_t
ibt_query_qp(ibt_qp_hdl_t ibt_qp,ibt_qp_query_attr_t * qp_query_attrp)7707c478bd9Sstevel@tonic-gate ibt_query_qp(ibt_qp_hdl_t ibt_qp, ibt_qp_query_attr_t *qp_query_attrp)
7717c478bd9Sstevel@tonic-gate {
7727c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
7737c478bd9Sstevel@tonic-gate 	ibtl_hca_devinfo_t	*hca_devp;
7747c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		*qp_infop;
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_qp(%p, %p)",
7777c478bd9Sstevel@tonic-gate 	    ibt_qp, qp_query_attrp);
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
7807c478bd9Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_query_qp(
7817c478bd9Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), qp_query_attrp));
7827c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
7837c478bd9Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
7847c478bd9Sstevel@tonic-gate 		ibt_qp->ch_current_state = qp_query_attrp->qp_info.qp_state;
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 		/* need to fill in sgid from port and sgid_ix for RC and UC */
7877c478bd9Sstevel@tonic-gate 		hca_devp = ibt_qp->ch_qp.qp_hca->ha_hca_devp;
7887c478bd9Sstevel@tonic-gate 		qp_infop = &qp_query_attrp->qp_info;
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 		switch (qp_infop->qp_trans) {
7917c478bd9Sstevel@tonic-gate 		case IBT_RC_SRV:
7927c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_path,
7937c478bd9Sstevel@tonic-gate 			    hca_devp);
7947c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.rc.rc_alt_path,
7957c478bd9Sstevel@tonic-gate 			    hca_devp);
7967c478bd9Sstevel@tonic-gate 			break;
7977c478bd9Sstevel@tonic-gate 		case IBT_UC_SRV:
7987c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_path,
7997c478bd9Sstevel@tonic-gate 			    hca_devp);
8007c478bd9Sstevel@tonic-gate 			ibtl_fillin_sgid(&qp_infop->qp_transport.uc.uc_alt_path,
8017c478bd9Sstevel@tonic-gate 			    hca_devp);
8027c478bd9Sstevel@tonic-gate 			break;
8037c478bd9Sstevel@tonic-gate 		}
8047c478bd9Sstevel@tonic-gate 	} else {
8057c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_qp: "
8067c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", ibt_qp, retval);
8077c478bd9Sstevel@tonic-gate 	}
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	return (retval);
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate /*
8147c478bd9Sstevel@tonic-gate  * Function:
8157c478bd9Sstevel@tonic-gate  *	ibt_modify_qp
8167c478bd9Sstevel@tonic-gate  * Input:
8177c478bd9Sstevel@tonic-gate  *	ibt_qp		The IBT QP Handle.
8187c478bd9Sstevel@tonic-gate  *	flags		Specifies which attributes in ibt_qp_mod_attr_t
8197c478bd9Sstevel@tonic-gate  *			are to be modified.
8207c478bd9Sstevel@tonic-gate  *	qp_attrp	Points to an ibt_qp_mod_attr_t struct that contains all
8217c478bd9Sstevel@tonic-gate  *			the attributes of the specified QP that a client is
8227c478bd9Sstevel@tonic-gate  *			allowed to modify after a QP has been allocated
8237c478bd9Sstevel@tonic-gate  * Output:
8247c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual queue sizes.
8257c478bd9Sstevel@tonic-gate  * Returns:
8267c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
8277c478bd9Sstevel@tonic-gate  * Description:
8287c478bd9Sstevel@tonic-gate  *	Modify the attributes of an existing QP.
8297c478bd9Sstevel@tonic-gate  */
8307c478bd9Sstevel@tonic-gate ibt_status_t
ibt_modify_qp(ibt_qp_hdl_t ibt_qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * modify_attrp,ibt_queue_sizes_t * actual_sz)8317c478bd9Sstevel@tonic-gate ibt_modify_qp(ibt_qp_hdl_t ibt_qp, ibt_cep_modify_flags_t flags,
8327c478bd9Sstevel@tonic-gate     ibt_qp_info_t *modify_attrp, ibt_queue_sizes_t *actual_sz)
8337c478bd9Sstevel@tonic-gate {
8347c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_qp(%p, %d, %p, %p)",
8377c478bd9Sstevel@tonic-gate 	    ibt_qp, flags, modify_attrp, actual_sz);
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_enter();
8407c478bd9Sstevel@tonic-gate 	retval = (IBTL_CHAN2CIHCAOPS_P(ibt_qp)->ibc_modify_qp)(
8417c478bd9Sstevel@tonic-gate 	    IBTL_CHAN2CIHCA(ibt_qp), IBTL_CHAN2CIQP(ibt_qp), flags,
8427c478bd9Sstevel@tonic-gate 	    modify_attrp, actual_sz);
8437c478bd9Sstevel@tonic-gate 	ibtl_qp_flow_control_exit();
8447c478bd9Sstevel@tonic-gate 	if (retval == IBT_SUCCESS) {
8457c478bd9Sstevel@tonic-gate 		ibt_qp->ch_current_state = modify_attrp->qp_state;
8467c478bd9Sstevel@tonic-gate 		if (ibt_qp->ch_qp.qp_type == IBT_UD_SRV) {
8477c478bd9Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_PORT | IBT_CEP_SET_RESET_INIT))
8487c478bd9Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_port_num =
8497c478bd9Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_port;
8507c478bd9Sstevel@tonic-gate 			if (flags & (IBT_CEP_SET_QKEY | IBT_CEP_SET_RESET_INIT))
8517c478bd9Sstevel@tonic-gate 				ibt_qp->ch_transport.ud.ud_qkey =
8527c478bd9Sstevel@tonic-gate 				    modify_attrp->qp_transport.ud.ud_qkey;
8537c478bd9Sstevel@tonic-gate 		}
8547c478bd9Sstevel@tonic-gate 	} else {
8557c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_qp: failed on chan %p: %d",
8567c478bd9Sstevel@tonic-gate 		    ibt_qp, retval);
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 		if (retval == IBT_CHAN_STATE_INVALID) {
8597c478bd9Sstevel@tonic-gate 			/* That means our cache had invalid QP state value. */
8607c478bd9Sstevel@tonic-gate 			ibt_qp_query_attr_t	qp_attr;
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 			/* Query the channel (QP) */
8637c478bd9Sstevel@tonic-gate 			if (ibt_query_qp(ibt_qp, &qp_attr) == IBT_SUCCESS)
8647c478bd9Sstevel@tonic-gate 				ibt_qp->ch_current_state =
8657c478bd9Sstevel@tonic-gate 				    qp_attr.qp_info.qp_state;
8667c478bd9Sstevel@tonic-gate 		}
8677c478bd9Sstevel@tonic-gate 	}
8687c478bd9Sstevel@tonic-gate 	return (retval);
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate /*
8737c478bd9Sstevel@tonic-gate  * Function:
8747c478bd9Sstevel@tonic-gate  *	ibt_migrate_path
8757c478bd9Sstevel@tonic-gate  * Input:
8767c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
8777c478bd9Sstevel@tonic-gate  * Output:
8787c478bd9Sstevel@tonic-gate  *	none.
8797c478bd9Sstevel@tonic-gate  * Returns:
8807c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS on Success else appropriate error.
8817c478bd9Sstevel@tonic-gate  * Description:
8827c478bd9Sstevel@tonic-gate  *	Force the CI to use the alternate path. The alternate path becomes
8837c478bd9Sstevel@tonic-gate  *	the primary path. A new alternate path should be loaded and enabled.
8847c478bd9Sstevel@tonic-gate  *	Assumes that the given channel is in RTS/SQD state
8857c478bd9Sstevel@tonic-gate  */
8867c478bd9Sstevel@tonic-gate ibt_status_t
ibt_migrate_path(ibt_channel_hdl_t rc_chan)8877c478bd9Sstevel@tonic-gate ibt_migrate_path(ibt_channel_hdl_t rc_chan)
8887c478bd9Sstevel@tonic-gate {
8897c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
8907c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		qp_info;
8917c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
8927c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	cep_flags;
8937c478bd9Sstevel@tonic-gate 	int			retries = 1;
8947c478bd9Sstevel@tonic-gate 
895934f0bccShiremath 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_migrate_path: channel %p", rc_chan);
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
8987c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path: "
8997c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel");
9007c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
9017c478bd9Sstevel@tonic-gate 	}
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_current_state != IBT_STATE_RTS &&
9047c478bd9Sstevel@tonic-gate 	    rc_chan->ch_current_state != IBT_STATE_SQD) {
9057c478bd9Sstevel@tonic-gate 		if (ibt_query_qp(rc_chan, &qp_attr) == IBT_SUCCESS) {
9067c478bd9Sstevel@tonic-gate 			/* ch_current_state is fixed by ibt_query_qp */
9077c478bd9Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
9087c478bd9Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
9097c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
9107c478bd9Sstevel@tonic-gate 			retries = 0;
9117c478bd9Sstevel@tonic-gate 		} else /* query_qp should never really fail */
9127c478bd9Sstevel@tonic-gate 			return (IBT_CHAN_STATE_INVALID);
9137c478bd9Sstevel@tonic-gate 	}
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate retry:
9167c478bd9Sstevel@tonic-gate 	/* Call modify_qp */
9177c478bd9Sstevel@tonic-gate 	cep_flags = IBT_CEP_SET_MIG | IBT_CEP_SET_STATE;
9187c478bd9Sstevel@tonic-gate 	qp_info.qp_state = rc_chan->ch_current_state;
9197c478bd9Sstevel@tonic-gate 	qp_info.qp_current_state = rc_chan->ch_current_state;
9207c478bd9Sstevel@tonic-gate 	qp_info.qp_trans = IBT_RC_SRV;
9217c478bd9Sstevel@tonic-gate 	qp_info.qp_transport.rc.rc_mig_state = IBT_STATE_MIGRATED;
9227c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, cep_flags, &qp_info, NULL);
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
9257c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
9267c478bd9Sstevel@tonic-gate 		    " ibt_modify_qp() returned = %d", retval);
9277c478bd9Sstevel@tonic-gate 		if (rc_chan->ch_current_state != qp_info.qp_state &&
9287c478bd9Sstevel@tonic-gate 		    --retries >= 0) {
9297c478bd9Sstevel@tonic-gate 			/*
9307c478bd9Sstevel@tonic-gate 			 * That means our cached 'state' was invalid.
9317c478bd9Sstevel@tonic-gate 			 * We know ibt_modify_qp() fixed it up, so it
9327c478bd9Sstevel@tonic-gate 			 * might be worth retrying.
9337c478bd9Sstevel@tonic-gate 			 */
9347c478bd9Sstevel@tonic-gate 			if (rc_chan->ch_current_state != IBT_STATE_RTS &&
9357c478bd9Sstevel@tonic-gate 			    rc_chan->ch_current_state != IBT_STATE_SQD)
9367c478bd9Sstevel@tonic-gate 				return (IBT_CHAN_STATE_INVALID);
9377c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(ibtf_qp, "ibt_migrate_path:"
9387c478bd9Sstevel@tonic-gate 			    " retrying after 'state' fixed");
9397c478bd9Sstevel@tonic-gate 			goto retry;
9407c478bd9Sstevel@tonic-gate 		}
9417c478bd9Sstevel@tonic-gate 	}
9427c478bd9Sstevel@tonic-gate 	return (retval);
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate /*
9477c478bd9Sstevel@tonic-gate  * Function:
9487c478bd9Sstevel@tonic-gate  *	ibt_set_qp_private
9497c478bd9Sstevel@tonic-gate  * Input:
9507c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9517c478bd9Sstevel@tonic-gate  *	clnt_private	The client private data.
9527c478bd9Sstevel@tonic-gate  * Output:
9537c478bd9Sstevel@tonic-gate  *	none.
9547c478bd9Sstevel@tonic-gate  * Returns:
9557c478bd9Sstevel@tonic-gate  *	none.
9567c478bd9Sstevel@tonic-gate  * Description:
9577c478bd9Sstevel@tonic-gate  *	Set the client private data.
9587c478bd9Sstevel@tonic-gate  */
9597c478bd9Sstevel@tonic-gate void
ibt_set_qp_private(ibt_qp_hdl_t ibt_qp,void * clnt_private)9607c478bd9Sstevel@tonic-gate ibt_set_qp_private(ibt_qp_hdl_t ibt_qp, void *clnt_private)
9617c478bd9Sstevel@tonic-gate {
9627c478bd9Sstevel@tonic-gate 	ibt_qp->ch_clnt_private = clnt_private;
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate /*
9677c478bd9Sstevel@tonic-gate  * Function:
9687c478bd9Sstevel@tonic-gate  *	ibt_get_qp_private
9697c478bd9Sstevel@tonic-gate  * Input:
9707c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9717c478bd9Sstevel@tonic-gate  * Output:
9727c478bd9Sstevel@tonic-gate  *	none.
9737c478bd9Sstevel@tonic-gate  * Returns:
9747c478bd9Sstevel@tonic-gate  *	The client private data.
9757c478bd9Sstevel@tonic-gate  * Description:
9767c478bd9Sstevel@tonic-gate  *	Get the client private data.
9777c478bd9Sstevel@tonic-gate  */
9787c478bd9Sstevel@tonic-gate void *
ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)9797c478bd9Sstevel@tonic-gate ibt_get_qp_private(ibt_qp_hdl_t ibt_qp)
9807c478bd9Sstevel@tonic-gate {
9817c478bd9Sstevel@tonic-gate 	return (ibt_qp->ch_clnt_private);
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate /*
9867c478bd9Sstevel@tonic-gate  * Function:
9877c478bd9Sstevel@tonic-gate  *	ibt_qp_to_hca_guid
9887c478bd9Sstevel@tonic-gate  * Input:
9897c478bd9Sstevel@tonic-gate  *	ibt_qp		The ibt_qp_hdl_t of the allocated QP.
9907c478bd9Sstevel@tonic-gate  * Output:
9917c478bd9Sstevel@tonic-gate  *	none.
9927c478bd9Sstevel@tonic-gate  * Returns:
9937c478bd9Sstevel@tonic-gate  *	hca_guid	Returned HCA GUID on which the specified QP is
9947c478bd9Sstevel@tonic-gate  *			allocated. Valid if it is non-NULL on return.
9957c478bd9Sstevel@tonic-gate  * Description:
9967c478bd9Sstevel@tonic-gate  *	A helper function to retrieve HCA GUID for the specified QP.
9977c478bd9Sstevel@tonic-gate  */
9987c478bd9Sstevel@tonic-gate ib_guid_t
ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)9997c478bd9Sstevel@tonic-gate ibt_qp_to_hca_guid(ibt_qp_hdl_t ibt_qp)
10007c478bd9Sstevel@tonic-gate {
10017c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_qp_to_hca_guid(%p)", ibt_qp);
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	return (IBTL_HCA2HCAGUID(IBTL_CHAN2HCA(ibt_qp)));
10047c478bd9Sstevel@tonic-gate }
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate /*
10087c478bd9Sstevel@tonic-gate  * Function:
10097c478bd9Sstevel@tonic-gate  *	ibt_recover_ud_qp
10107c478bd9Sstevel@tonic-gate  * Input:
10117c478bd9Sstevel@tonic-gate  *	ibt_qp		An QP Handle which is in SQError state.
10127c478bd9Sstevel@tonic-gate  * Output:
10137c478bd9Sstevel@tonic-gate  *	none.
10147c478bd9Sstevel@tonic-gate  * Returns:
10157c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
10167c478bd9Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
10177c478bd9Sstevel@tonic-gate  *	IBT_QP_STATE_INVALID.
10187c478bd9Sstevel@tonic-gate  * Description:
10197c478bd9Sstevel@tonic-gate  *	Recover an UD QP which has transitioned to SQ Error state. The
10207c478bd9Sstevel@tonic-gate  *	ibt_recover_ud_qp() transitions the QP from SQ Error state to
10217c478bd9Sstevel@tonic-gate  *	Ready-To-Send QP state.
10227c478bd9Sstevel@tonic-gate  *
10237c478bd9Sstevel@tonic-gate  *	If a work request posted to a UD QP's send queue completes with an
10247c478bd9Sstevel@tonic-gate  *	error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state.
10257c478bd9Sstevel@tonic-gate  *	In order to reuse this QP, ibt_recover_ud_qp() can be used to recover
10267c478bd9Sstevel@tonic-gate  *	the QP to a usable (Ready-to-Send) state.
10277c478bd9Sstevel@tonic-gate  */
10287c478bd9Sstevel@tonic-gate ibt_status_t
ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)10297c478bd9Sstevel@tonic-gate ibt_recover_ud_qp(ibt_qp_hdl_t ibt_qp)
10307c478bd9Sstevel@tonic-gate {
10317c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recover_ud_qp(%p)", ibt_qp);
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 	return (ibt_recover_ud_channel(IBTL_QP2CHAN(ibt_qp)));
10347c478bd9Sstevel@tonic-gate }
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate /*
10387c478bd9Sstevel@tonic-gate  * Function:
10397c478bd9Sstevel@tonic-gate  *	ibt_recycle_ud
10407c478bd9Sstevel@tonic-gate  * Input:
10417c478bd9Sstevel@tonic-gate  *	ud_chan		The IBT UD QP Handle.
10427c478bd9Sstevel@tonic-gate  *	various attributes
10437c478bd9Sstevel@tonic-gate  *
10447c478bd9Sstevel@tonic-gate  * Output:
10457c478bd9Sstevel@tonic-gate  *	none
10467c478bd9Sstevel@tonic-gate  * Returns:
10477c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
10487c478bd9Sstevel@tonic-gate  *	IBT_CHAN_SRV_TYPE_INVALID
10497c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
10507c478bd9Sstevel@tonic-gate  *
10517c478bd9Sstevel@tonic-gate  * Description:
10527c478bd9Sstevel@tonic-gate  *	Revert the UD QP back to a usable state.
10537c478bd9Sstevel@tonic-gate  */
10547c478bd9Sstevel@tonic-gate ibt_status_t
ibt_recycle_ud(ibt_channel_hdl_t ud_chan,uint8_t hca_port_num,uint16_t pkey_ix,ib_qkey_t qkey)10557c478bd9Sstevel@tonic-gate ibt_recycle_ud(ibt_channel_hdl_t ud_chan, uint8_t hca_port_num,
10567c478bd9Sstevel@tonic-gate     uint16_t pkey_ix, ib_qkey_t qkey)
10577c478bd9Sstevel@tonic-gate {
10587c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
10597c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_recycle_ud(%p, %d, %x, %x): ",
10627c478bd9Sstevel@tonic-gate 	    ud_chan, hca_port_num, pkey_ix, qkey);
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 	if (ud_chan->ch_qp.qp_type != IBT_UD_SRV) {
10657c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10667c478bd9Sstevel@tonic-gate 		    "chan %p is not a UD channel", ud_chan);
10677c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
10687c478bd9Sstevel@tonic-gate 	}
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(ud_chan, &qp_attr);
10717c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10727c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10737c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed on chan %p: %d", ud_chan, retval);
10747c478bd9Sstevel@tonic-gate 		return (retval);
10757c478bd9Sstevel@tonic-gate 	}
10767c478bd9Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR) {
10777c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10787c478bd9Sstevel@tonic-gate 		    "chan %p is in state %d (not in ERROR state)",
10797c478bd9Sstevel@tonic-gate 		    ud_chan, qp_attr.qp_info.qp_state);
10807c478bd9Sstevel@tonic-gate 		ud_chan->ch_current_state = qp_attr.qp_info.qp_state;
10817c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
10827c478bd9Sstevel@tonic-gate 	}
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 	/* transition the QP from ERROR to RESET */
10857c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_state = IBT_STATE_RESET;
10867c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_trans = ud_chan->ch_qp.qp_type;
10877c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(ud_chan, IBT_CEP_SET_STATE, &qp_attr.qp_info,
10887c478bd9Sstevel@tonic-gate 	    NULL);
10897c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
10907c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
10917c478bd9Sstevel@tonic-gate 		    "ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d",
10927c478bd9Sstevel@tonic-gate 		    ud_chan, retval);
10937c478bd9Sstevel@tonic-gate 		return (retval);
10947c478bd9Sstevel@tonic-gate 	}
10957c478bd9Sstevel@tonic-gate 	ud_chan->ch_current_state = IBT_STATE_RESET;
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate 	/* transition the QP back to RTS */
10987c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_port = hca_port_num;
10997c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_qkey = qkey;
11007c478bd9Sstevel@tonic-gate 	qp_attr.qp_info.qp_transport.ud.ud_pkey_ix = pkey_ix;
11017c478bd9Sstevel@tonic-gate 	retval = ibt_initialize_qp(ud_chan, &qp_attr.qp_info);
11027c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11037c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_recycle_ud: "
11047c478bd9Sstevel@tonic-gate 		    "ibt_initialize_qp failed on chan %p: %d", ud_chan, retval);
11057c478bd9Sstevel@tonic-gate 		/* the man page says the QP should be left in ERROR state */
11067c478bd9Sstevel@tonic-gate 		(void) ibt_flush_qp(ud_chan);
11077c478bd9Sstevel@tonic-gate 	}
11087c478bd9Sstevel@tonic-gate 	return (retval);
11097c478bd9Sstevel@tonic-gate }
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate /*
11127c478bd9Sstevel@tonic-gate  * Function:
11137c478bd9Sstevel@tonic-gate  *	ibt_pause_sendq
11147c478bd9Sstevel@tonic-gate  * Input:
11157c478bd9Sstevel@tonic-gate  *	chan		The IBT QP Handle.
11167c478bd9Sstevel@tonic-gate  *	modify_flags	IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT
11177c478bd9Sstevel@tonic-gate  *
11187c478bd9Sstevel@tonic-gate  * Output:
11197c478bd9Sstevel@tonic-gate  *	none.
11207c478bd9Sstevel@tonic-gate  * Returns:
11217c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
11227c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
11237c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
11247c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
11257c478bd9Sstevel@tonic-gate  *
11267c478bd9Sstevel@tonic-gate  * Description:
11277c478bd9Sstevel@tonic-gate  *	Place the send queue of the specified channel into the send queue
11287c478bd9Sstevel@tonic-gate  *	drained (SQD) state.
11297c478bd9Sstevel@tonic-gate  *
11307c478bd9Sstevel@tonic-gate  */
11317c478bd9Sstevel@tonic-gate ibt_status_t
ibt_pause_sendq(ibt_channel_hdl_t chan,ibt_cep_modify_flags_t modify_flags)11327c478bd9Sstevel@tonic-gate ibt_pause_sendq(ibt_channel_hdl_t chan, ibt_cep_modify_flags_t modify_flags)
11337c478bd9Sstevel@tonic-gate {
11347c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
11357c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_pause_sendq(%p, %x)", chan, modify_flags);
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 	modify_flags &= IBT_CEP_SET_SQD_EVENT;	/* ignore other bits */
11407c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
11437c478bd9Sstevel@tonic-gate 	/*
11447c478bd9Sstevel@tonic-gate 	 * Set the QP state to SQD.
11457c478bd9Sstevel@tonic-gate 	 */
11467c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
11477c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11527c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_pause_sendq: "
11537c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
11547c478bd9Sstevel@tonic-gate 	}
11557c478bd9Sstevel@tonic-gate 	return (retval);
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate /*
11607c478bd9Sstevel@tonic-gate  * Function:
11617c478bd9Sstevel@tonic-gate  *	ibt_unpause_sendq
11627c478bd9Sstevel@tonic-gate  * Input:
11637c478bd9Sstevel@tonic-gate  *	chan	The IBT Channel Handle.
11647c478bd9Sstevel@tonic-gate  * Output:
11657c478bd9Sstevel@tonic-gate  *	none.
11667c478bd9Sstevel@tonic-gate  * Returns:
11677c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
11687c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
11697c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
11707c478bd9Sstevel@tonic-gate  * Description:
11717c478bd9Sstevel@tonic-gate  *	Un-pauses the previously paused channel. This call will transition the
11727c478bd9Sstevel@tonic-gate  *	QP from SQD to RTS state.
11737c478bd9Sstevel@tonic-gate  */
11747c478bd9Sstevel@tonic-gate ibt_status_t
ibt_unpause_sendq(ibt_channel_hdl_t chan)11757c478bd9Sstevel@tonic-gate ibt_unpause_sendq(ibt_channel_hdl_t chan)
11767c478bd9Sstevel@tonic-gate {
11777c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
11787c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_unpause_sendq(%p)", chan);
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	/*
11857c478bd9Sstevel@tonic-gate 	 * Set the QP state to RTS.
11867c478bd9Sstevel@tonic-gate 	 */
11877c478bd9Sstevel@tonic-gate 	modify_attr.qp_current_state = IBT_STATE_SQD;
11887c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_RTS;
11897c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, IBT_CEP_SET_STATE, &modify_attr, NULL);
11927c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
11937c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_unpause_sendq: "
11947c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
11957c478bd9Sstevel@tonic-gate 	}
11967c478bd9Sstevel@tonic-gate 	return (retval);
11977c478bd9Sstevel@tonic-gate }
11987c478bd9Sstevel@tonic-gate 
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate /*
12017c478bd9Sstevel@tonic-gate  * Function:
12027c478bd9Sstevel@tonic-gate  *	ibt_resize_queues
12037c478bd9Sstevel@tonic-gate  * Input:
12047c478bd9Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
12057c478bd9Sstevel@tonic-gate  *	flags		QP Flags
12067c478bd9Sstevel@tonic-gate  *				IBT_SEND_Q
12077c478bd9Sstevel@tonic-gate  *				IBT_RECV_Q
12087c478bd9Sstevel@tonic-gate  *	request_sz	Requested new sizes.
12097c478bd9Sstevel@tonic-gate  * Output:
12107c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
12117c478bd9Sstevel@tonic-gate  * Returns:
12127c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
12137c478bd9Sstevel@tonic-gate  * Description:
12147c478bd9Sstevel@tonic-gate  *	Resize the SendQ/RecvQ sizes of a channel. Can only be called on
12157c478bd9Sstevel@tonic-gate  *	a previously opened channel.
12167c478bd9Sstevel@tonic-gate  */
12177c478bd9Sstevel@tonic-gate ibt_status_t
ibt_resize_queues(ibt_channel_hdl_t chan,ibt_qflags_t flags,ibt_queue_sizes_t * request_sz,ibt_queue_sizes_t * actual_sz)12187c478bd9Sstevel@tonic-gate ibt_resize_queues(ibt_channel_hdl_t chan, ibt_qflags_t flags,
12197c478bd9Sstevel@tonic-gate     ibt_queue_sizes_t *request_sz, ibt_queue_sizes_t *actual_sz)
12207c478bd9Sstevel@tonic-gate {
12217c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags = IBT_CEP_SET_STATE;
12227c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
12237c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_resize_queues(%p, 0x%X, %p, %p)",
12267c478bd9Sstevel@tonic-gate 	    chan, flags, request_sz, actual_sz);
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate 	if ((flags & (IBT_SEND_Q | IBT_RECV_Q)) == 0)  {
12297c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
12307c478bd9Sstevel@tonic-gate 		    "Flags <0x%X> not set", flags);
12317c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
12327c478bd9Sstevel@tonic-gate 	}
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 	modify_attr.qp_current_state = chan->ch_current_state;
12377c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
12387c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = chan->ch_current_state;
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 	if (flags & IBT_SEND_Q) {
12417c478bd9Sstevel@tonic-gate 		modify_attr.qp_sq_sz = request_sz->qs_sq;
12427c478bd9Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_SQ_SIZE;
12437c478bd9Sstevel@tonic-gate 	}
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 	if (flags & IBT_RECV_Q) {
12467c478bd9Sstevel@tonic-gate 		modify_attr.qp_rq_sz = request_sz->qs_rq;
12477c478bd9Sstevel@tonic-gate 		modify_flags |= IBT_CEP_SET_RQ_SIZE;
12487c478bd9Sstevel@tonic-gate 	}
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, actual_sz);
12517c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
12527c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_resize_queues: "
12537c478bd9Sstevel@tonic-gate 		    "failed on QP %p: %d", chan, retval);
12547c478bd9Sstevel@tonic-gate 	}
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 	return (retval);
12577c478bd9Sstevel@tonic-gate }
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate /*
12617c478bd9Sstevel@tonic-gate  * Function:
12627c478bd9Sstevel@tonic-gate  *	ibt_query_queues
12637c478bd9Sstevel@tonic-gate  * Input:
12647c478bd9Sstevel@tonic-gate  *	chan		A previously allocated channel handle.
12657c478bd9Sstevel@tonic-gate  * Output:
12667c478bd9Sstevel@tonic-gate  *	actual_sz	Returned actual sizes.
12677c478bd9Sstevel@tonic-gate  * Returns:
12687c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
12697c478bd9Sstevel@tonic-gate  * Description:
12707c478bd9Sstevel@tonic-gate  *	Query the SendQ/RecvQ sizes of a channel.
12717c478bd9Sstevel@tonic-gate  */
12727c478bd9Sstevel@tonic-gate ibt_status_t
ibt_query_queues(ibt_channel_hdl_t chan,ibt_queue_sizes_t * actual_sz)12737c478bd9Sstevel@tonic-gate ibt_query_queues(ibt_channel_hdl_t chan, ibt_queue_sizes_t *actual_sz)
12747c478bd9Sstevel@tonic-gate {
12757c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
12767c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_query_attr;
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_query_queues(%p)", chan);
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	/* Perform Query QP and retrieve QP sizes. */
12817c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(chan, &qp_query_attr);
12827c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
12837c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_query_queues: "
12847c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed: qp %p: %d", chan, retval);
12857c478bd9Sstevel@tonic-gate 		return (retval);
12867c478bd9Sstevel@tonic-gate 	}
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
12897c478bd9Sstevel@tonic-gate 	    actual_sz->qs_sq))
12907c478bd9Sstevel@tonic-gate 	actual_sz->qs_sq = qp_query_attr.qp_info.qp_sq_sz;
12917c478bd9Sstevel@tonic-gate 	actual_sz->qs_rq = qp_query_attr.qp_info.qp_rq_sz;
12927c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(actual_sz->qs_rq,
12937c478bd9Sstevel@tonic-gate 	    actual_sz->qs_sq))
12947c478bd9Sstevel@tonic-gate 	chan->ch_current_state = qp_query_attr.qp_info.qp_state;
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 	return (retval);
12977c478bd9Sstevel@tonic-gate }
12987c478bd9Sstevel@tonic-gate 
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate /*
13017c478bd9Sstevel@tonic-gate  * Function:
13027c478bd9Sstevel@tonic-gate  *	ibt_modify_rdma
13037c478bd9Sstevel@tonic-gate  * Input:
13047c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated channel handle.
13057c478bd9Sstevel@tonic-gate  *
13067c478bd9Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
13077c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_R	Enable/Disable RDMA RD
13087c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMA_W	Enable/Disable RDMA WR
13097c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_ATOMIC	Enable/Disable Atomics
13107c478bd9Sstevel@tonic-gate  *
13117c478bd9Sstevel@tonic-gate  *	flags		Channel End Point (CEP) Disable Flags (0 => enable).
13127c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_RD	Disable incoming RDMA RD's
13137c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_RDMA_WR	Disable incoming RDMA WR's
13147c478bd9Sstevel@tonic-gate  *			IBT_CEP_NO_ATOMIC	Disable incoming Atomics.
13157c478bd9Sstevel@tonic-gate  * Output:
13167c478bd9Sstevel@tonic-gate  *	none.
13177c478bd9Sstevel@tonic-gate  * Returns:
13187c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
13197c478bd9Sstevel@tonic-gate  *	IBT_QP_SRV_TYPE_INVALID
13207c478bd9Sstevel@tonic-gate  *	IBT_CHAN_HDL_INVALID
13217c478bd9Sstevel@tonic-gate  *	IBT_CHAN_ATOMICS_NOT_SUPPORTED
13227c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID
13237c478bd9Sstevel@tonic-gate  * Description:
13247c478bd9Sstevel@tonic-gate  *	Enable/disable RDMA operations. To enable an operation clear the
13257c478bd9Sstevel@tonic-gate  *	"disable" flag. Can call this function when the channel is in
13267c478bd9Sstevel@tonic-gate  *	INIT, RTS or SQD states. If called in any other state
13277c478bd9Sstevel@tonic-gate  *	IBT_CHAN_STATE_INVALID is returned. When the operation completes the
13287c478bd9Sstevel@tonic-gate  *	channel state is left unchanged.
13297c478bd9Sstevel@tonic-gate  */
13307c478bd9Sstevel@tonic-gate ibt_status_t
ibt_modify_rdma(ibt_channel_hdl_t rc_chan,ibt_cep_modify_flags_t modify_flags,ibt_cep_flags_t flags)13317c478bd9Sstevel@tonic-gate ibt_modify_rdma(ibt_channel_hdl_t rc_chan,
13327c478bd9Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, ibt_cep_flags_t flags)
13337c478bd9Sstevel@tonic-gate {
13347c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
13357c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
13367c478bd9Sstevel@tonic-gate 
13377c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_modify_rdma(%p, 0x%x, 0x%x)",
13387c478bd9Sstevel@tonic-gate 	    rc_chan, modify_flags, flags);
13397c478bd9Sstevel@tonic-gate 
13407c478bd9Sstevel@tonic-gate 	if (rc_chan->ch_qp.qp_type != IBT_RC_SRV) {
13417c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
13427c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
13437c478bd9Sstevel@tonic-gate 		    rc_chan->ch_qp.qp_type);
13447c478bd9Sstevel@tonic-gate 		return (IBT_QP_SRV_TYPE_INVALID);
13457c478bd9Sstevel@tonic-gate 	}
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	/*
13507c478bd9Sstevel@tonic-gate 	 * Can only call this function when the channel in INIT, RTS or SQD
13517c478bd9Sstevel@tonic-gate 	 * states.
13527c478bd9Sstevel@tonic-gate 	 */
13537c478bd9Sstevel@tonic-gate 	if ((rc_chan->ch_current_state != IBT_STATE_INIT) &&
13547c478bd9Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_RTS) &&
13557c478bd9Sstevel@tonic-gate 	    (rc_chan->ch_current_state != IBT_STATE_SQD)) {
13567c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: Invalid Channel "
13577c478bd9Sstevel@tonic-gate 		    "state: 0x%X", rc_chan->ch_current_state);
13587c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
13597c478bd9Sstevel@tonic-gate 	}
13607c478bd9Sstevel@tonic-gate 
13617c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = modify_attr.qp_current_state =
13627c478bd9Sstevel@tonic-gate 	    rc_chan->ch_current_state;
13637c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = rc_chan->ch_qp.qp_type;
13647c478bd9Sstevel@tonic-gate 	modify_attr.qp_flags = flags;
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
13677c478bd9Sstevel@tonic-gate 	    IBT_CEP_SET_ATOMIC);
13687c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(rc_chan, modify_flags, &modify_attr, NULL);
13717c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
13727c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_modify_rdma: "
13737c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", rc_chan, retval);
13747c478bd9Sstevel@tonic-gate 	}
13757c478bd9Sstevel@tonic-gate 	return (retval);
13767c478bd9Sstevel@tonic-gate }
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate /*
13807c478bd9Sstevel@tonic-gate  * Function:
13817c478bd9Sstevel@tonic-gate  *	ibt_set_rdma_resource
13827c478bd9Sstevel@tonic-gate  * Input:
13837c478bd9Sstevel@tonic-gate  *	chan		A previously allocated RC channel handle.
13847c478bd9Sstevel@tonic-gate  *	modify_flags	Bitwise "or" of any of the following:
13857c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_OUT	Initiator depth (rdma_ra_out)
13867c478bd9Sstevel@tonic-gate  *			IBT_CEP_SET_RDMARA_IN	Responder Resources
13877c478bd9Sstevel@tonic-gate  *						(rdma_ra_in)
13887c478bd9Sstevel@tonic-gate  *	rdma_ra_out	Outgoing RDMA Reads/Atomics
13897c478bd9Sstevel@tonic-gate  *	rdma_ra_in	Incoming RDMA Reads/Atomics
13907c478bd9Sstevel@tonic-gate  * Output:
13917c478bd9Sstevel@tonic-gate  *	none.
13927c478bd9Sstevel@tonic-gate  * Returns:
13937c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
13947c478bd9Sstevel@tonic-gate  * Description:
13957c478bd9Sstevel@tonic-gate  *	Change the number of resources to be used for incoming and outgoing
13967c478bd9Sstevel@tonic-gate  *	RDMA reads & Atomics. Can only be called on a previously opened
13977c478bd9Sstevel@tonic-gate  *	RC channel.  Can only be called on a paused channel, and this will
13987c478bd9Sstevel@tonic-gate  *	un-pause that channel.
13997c478bd9Sstevel@tonic-gate  */
14007c478bd9Sstevel@tonic-gate ibt_status_t
ibt_set_rdma_resource(ibt_channel_hdl_t chan,ibt_cep_modify_flags_t modify_flags,uint8_t rdma_ra_out,uint8_t resp_rdma_ra_out)14017c478bd9Sstevel@tonic-gate ibt_set_rdma_resource(ibt_channel_hdl_t chan,
14027c478bd9Sstevel@tonic-gate     ibt_cep_modify_flags_t modify_flags, uint8_t rdma_ra_out,
14037c478bd9Sstevel@tonic-gate     uint8_t resp_rdma_ra_out)
14047c478bd9Sstevel@tonic-gate {
14057c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
14067c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_set_rdma_resource(%p, 0x%x, %d, %d)",
14097c478bd9Sstevel@tonic-gate 	    chan, modify_flags, rdma_ra_out, resp_rdma_ra_out);
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
14127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
14137c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
14147c478bd9Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
14157c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
14167c478bd9Sstevel@tonic-gate 	}
14177c478bd9Sstevel@tonic-gate 
14187c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
14217c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_out = rdma_ra_out;
14247c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_rdma_ra_in = resp_rdma_ra_out;
14257c478bd9Sstevel@tonic-gate 	modify_flags &= (IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN);
14267c478bd9Sstevel@tonic-gate 	modify_flags |= IBT_CEP_SET_STATE;
14277c478bd9Sstevel@tonic-gate 
14287c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
14297c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
14307c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_set_rdma_resource: "
14317c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
14327c478bd9Sstevel@tonic-gate 	}
14337c478bd9Sstevel@tonic-gate 	return (retval);
14347c478bd9Sstevel@tonic-gate }
14357c478bd9Sstevel@tonic-gate 
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate /*
14387c478bd9Sstevel@tonic-gate  * Function:
14397c478bd9Sstevel@tonic-gate  *	ibt_change_port
14407c478bd9Sstevel@tonic-gate  * Input:
14417c478bd9Sstevel@tonic-gate  *	rc_chan		A previously allocated RC channel handle.
14427c478bd9Sstevel@tonic-gate  *	port_num	New HCA port.
14437c478bd9Sstevel@tonic-gate  * Output:
14447c478bd9Sstevel@tonic-gate  *	none.
14457c478bd9Sstevel@tonic-gate  * Returns:
14467c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
14477c478bd9Sstevel@tonic-gate  * Description:
14487c478bd9Sstevel@tonic-gate  *	Change the primary physical port of a channel. (This is done only if
14497c478bd9Sstevel@tonic-gate  *	HCA supports this capability).
14507c478bd9Sstevel@tonic-gate  */
14517c478bd9Sstevel@tonic-gate ibt_status_t
ibt_change_port(ibt_channel_hdl_t chan,uint8_t port_num)14527c478bd9Sstevel@tonic-gate ibt_change_port(ibt_channel_hdl_t chan, uint8_t port_num)
14537c478bd9Sstevel@tonic-gate {
14547c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	modify_flags;
14557c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		modify_attr;
14567c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibt_change_port(%p, %d)", chan, port_num);
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate 	if (chan->ch_qp.qp_type != IBT_RC_SRV) {
14617c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
14627c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: 0x%X, Applicable only to RC Channel",
14637c478bd9Sstevel@tonic-gate 		    chan->ch_qp.qp_type);
14647c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
14657c478bd9Sstevel@tonic-gate 	}
14667c478bd9Sstevel@tonic-gate 	bzero(&modify_attr, sizeof (ibt_qp_info_t));
14677c478bd9Sstevel@tonic-gate 
14687c478bd9Sstevel@tonic-gate 	modify_attr.qp_state = IBT_STATE_SQD;
14697c478bd9Sstevel@tonic-gate 	modify_attr.qp_trans = chan->ch_qp.qp_type;
14707c478bd9Sstevel@tonic-gate 	modify_attr.qp_transport.rc.rc_path.cep_hca_port_num = port_num;
14717c478bd9Sstevel@tonic-gate 
14727c478bd9Sstevel@tonic-gate 	modify_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 	retval = ibt_modify_qp(chan, modify_flags, &modify_attr, NULL);
14757c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
14767c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(ibtf_qp, "ibt_change_port: "
14777c478bd9Sstevel@tonic-gate 		    "failed on chan %p: %d", chan, retval);
14787c478bd9Sstevel@tonic-gate 	}
14797c478bd9Sstevel@tonic-gate 	return (retval);
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 
14837c478bd9Sstevel@tonic-gate void
ibtl_init_cep_states(void)14847c478bd9Sstevel@tonic-gate ibtl_init_cep_states(void)
14857c478bd9Sstevel@tonic-gate {
14867c478bd9Sstevel@tonic-gate 	int	index;
14877c478bd9Sstevel@tonic-gate 	int	ibt_nstate_inits;
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(ibtf_qp, "ibtl_init_cep_states()");
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate 	ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) /
14927c478bd9Sstevel@tonic-gate 	    sizeof (ibt_cep_next_state_inits[0]);
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 	/*
14957c478bd9Sstevel@tonic-gate 	 * Initialize CEP next state table, using an indirect lookup table so
14967c478bd9Sstevel@tonic-gate 	 * that this code isn't dependent on the ibt_cep_state_t enum values.
14977c478bd9Sstevel@tonic-gate 	 */
14987c478bd9Sstevel@tonic-gate 	for (index = 0; index < ibt_nstate_inits; index++) {
14997c478bd9Sstevel@tonic-gate 		ibt_cep_state_t	state;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 		state = ibt_cep_next_state_inits[index].current_state;
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 		ibt_cep_next_state[state].next_state =
15047c478bd9Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].next_state;
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 		ibt_cep_next_state[state].modify_flags =
15077c478bd9Sstevel@tonic-gate 		    ibt_cep_next_state_inits[index].modify_flags;
15087c478bd9Sstevel@tonic-gate 	}
15097c478bd9Sstevel@tonic-gate }
1510