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