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
503494a98SBill Taylor  * Common Development and Distribution License (the "License").
603494a98SBill Taylor  * 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  */
21*448bf859SLida.Horn 
227c478bd9Sstevel@tonic-gate /*
23*448bf859SLida.Horn  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * This file implements the client interfaces of the IBMF.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/ib/mgt/ibmf/ibmf_impl.h>
317c478bd9Sstevel@tonic-gate #include <sys/ib/mgt/ib_mad.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate extern ibmf_state_t *ibmf_statep;
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /* global settable */
367c478bd9Sstevel@tonic-gate int	ibmf_send_wqes_per_port = IBMF_MAX_SQ_WRE;
377c478bd9Sstevel@tonic-gate int	ibmf_recv_wqes_per_port = IBMF_MAX_RQ_WRE;
387c478bd9Sstevel@tonic-gate int	ibmf_send_wqes_posted_per_qp = IBMF_MAX_POSTED_SQ_PER_QP;
397c478bd9Sstevel@tonic-gate int	ibmf_recv_wqes_posted_per_qp = IBMF_MAX_POSTED_RQ_PER_QP;
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate int	ibmf_taskq_max_tasks = 1024;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate int	ibmf_trace_level = DPRINT_L0;
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define	IBMF_MAD_CL_HDR_OFF_1	0
467c478bd9Sstevel@tonic-gate #define	IBMF_MAD_CL_HDR_OFF_2	12
477c478bd9Sstevel@tonic-gate #define	IBMF_MAD_CL_HDR_SZ_1	40
487c478bd9Sstevel@tonic-gate #define	IBMF_MAD_CL_HDR_SZ_2	20
497c478bd9Sstevel@tonic-gate #define	IBMF_MAD_CL_HDR_SZ_3	0
507c478bd9Sstevel@tonic-gate #define	IBMF_MAD_CL_HDR_SZ_4	4
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #define	IBMF_VALID_CLIENT_TYPE(client_type)		\
537c478bd9Sstevel@tonic-gate 	((client_type) == SUBN_AGENT ||			\
547c478bd9Sstevel@tonic-gate 	(client_type) == SUBN_MANAGER ||		\
557c478bd9Sstevel@tonic-gate 	(client_type) == SUBN_ADM_AGENT ||		\
567c478bd9Sstevel@tonic-gate 	(client_type) == SUBN_ADM_MANAGER ||		\
577c478bd9Sstevel@tonic-gate 	(client_type) == PERF_AGENT ||			\
587c478bd9Sstevel@tonic-gate 	(client_type) == PERF_MANAGER ||		\
597c478bd9Sstevel@tonic-gate 	(client_type) == BM_AGENT ||			\
607c478bd9Sstevel@tonic-gate 	(client_type) == BM_MANAGER ||			\
617c478bd9Sstevel@tonic-gate 	(client_type) == DEV_MGT_AGENT ||		\
627c478bd9Sstevel@tonic-gate 	(client_type) == DEV_MGT_MANAGER ||		\
637c478bd9Sstevel@tonic-gate 	(client_type) == COMM_MGT_MANAGER_AGENT ||	\
647c478bd9Sstevel@tonic-gate 	(client_type) == SNMP_MANAGER_AGENT ||		\
657c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_09_MANAGER_AGENT ||	\
667c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_0A_MANAGER_AGENT ||	\
677c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_0B_MANAGER_AGENT ||	\
687c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_0C_MANAGER_AGENT ||	\
697c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_0D_MANAGER_AGENT ||	\
707c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_0E_MANAGER_AGENT ||	\
717c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_0F_MANAGER_AGENT ||	\
727c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_30_MANAGER_AGENT ||	\
737c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_31_MANAGER_AGENT ||	\
747c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_32_MANAGER_AGENT ||	\
757c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_33_MANAGER_AGENT ||	\
767c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_34_MANAGER_AGENT ||	\
777c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_35_MANAGER_AGENT ||	\
787c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_36_MANAGER_AGENT ||	\
797c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_37_MANAGER_AGENT ||	\
807c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_38_MANAGER_AGENT ||	\
817c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_39_MANAGER_AGENT ||	\
827c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_3A_MANAGER_AGENT ||	\
837c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_3B_MANAGER_AGENT ||	\
847c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_3C_MANAGER_AGENT ||	\
857c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_3D_MANAGER_AGENT ||	\
867c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_3E_MANAGER_AGENT ||	\
877c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_3F_MANAGER_AGENT ||	\
887c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_40_MANAGER_AGENT ||	\
897c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_41_MANAGER_AGENT ||	\
907c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_42_MANAGER_AGENT ||	\
917c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_43_MANAGER_AGENT ||	\
927c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_44_MANAGER_AGENT ||	\
937c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_45_MANAGER_AGENT ||	\
947c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_46_MANAGER_AGENT ||	\
957c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_47_MANAGER_AGENT ||	\
967c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_48_MANAGER_AGENT ||	\
977c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_49_MANAGER_AGENT ||	\
987c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_4A_MANAGER_AGENT ||	\
997c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_4B_MANAGER_AGENT ||	\
1007c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_4C_MANAGER_AGENT ||	\
1017c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_4D_MANAGER_AGENT ||	\
1027c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_4E_MANAGER_AGENT ||	\
1037c478bd9Sstevel@tonic-gate 	(client_type) == VENDOR_4F_MANAGER_AGENT ||	\
1047c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_10_MANAGER_AGENT || \
1057c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_11_MANAGER_AGENT || \
1067c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_12_MANAGER_AGENT || \
1077c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_13_MANAGER_AGENT || \
1087c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_14_MANAGER_AGENT || \
1097c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_15_MANAGER_AGENT || \
1107c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_16_MANAGER_AGENT || \
1117c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_17_MANAGER_AGENT || \
1127c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_18_MANAGER_AGENT || \
1137c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_19_MANAGER_AGENT || \
1147c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_1A_MANAGER_AGENT || \
1157c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_1B_MANAGER_AGENT || \
1167c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_1C_MANAGER_AGENT || \
1177c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_1D_MANAGER_AGENT || \
1187c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_1E_MANAGER_AGENT || \
1197c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_1F_MANAGER_AGENT || \
1207c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_20_MANAGER_AGENT || \
1217c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_21_MANAGER_AGENT || \
1227c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_22_MANAGER_AGENT || \
1237c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_23_MANAGER_AGENT || \
1247c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_24_MANAGER_AGENT || \
1257c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_25_MANAGER_AGENT || \
1267c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_26_MANAGER_AGENT || \
1277c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_27_MANAGER_AGENT || \
1287c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_28_MANAGER_AGENT || \
1297c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_29_MANAGER_AGENT || \
1307c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_2A_MANAGER_AGENT || \
1317c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_2B_MANAGER_AGENT || \
1327c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_2C_MANAGER_AGENT || \
1337c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_2D_MANAGER_AGENT || \
1347c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_2E_MANAGER_AGENT || \
1357c478bd9Sstevel@tonic-gate 	(client_type) == APPLICATION_2F_MANAGER_AGENT || \
1367c478bd9Sstevel@tonic-gate 	(client_type) == UNIVERSAL_CLASS)
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate static ibmf_ci_t *ibmf_i_lookup_ci(ib_guid_t ci_guid);
1397c478bd9Sstevel@tonic-gate static int ibmf_i_init_ci(ibmf_register_info_t *client_infop,
1407c478bd9Sstevel@tonic-gate     ibmf_ci_t *cip);
1417c478bd9Sstevel@tonic-gate static void ibmf_i_uninit_ci(ibmf_ci_t *cip);
1427c478bd9Sstevel@tonic-gate static void ibmf_i_init_ci_done(ibmf_ci_t *cip);
1437c478bd9Sstevel@tonic-gate static void ibmf_i_uninit_ci_done(ibmf_ci_t *cip);
1447c478bd9Sstevel@tonic-gate static int ibmf_i_init_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp);
1457c478bd9Sstevel@tonic-gate static void ibmf_i_uninit_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp);
1467c478bd9Sstevel@tonic-gate static int ibmf_i_init_cqs(ibmf_ci_t *cip);
1477c478bd9Sstevel@tonic-gate static void ibmf_i_fini_cqs(ibmf_ci_t *cip);
1487c478bd9Sstevel@tonic-gate static void ibmf_i_init_qplist(ibmf_ci_t *ibmf_cip);
1497c478bd9Sstevel@tonic-gate static void ibmf_i_fini_qplist(ibmf_ci_t *ibmf_cip);
1507c478bd9Sstevel@tonic-gate static int ibmf_i_lookup_client_by_info(ibmf_ci_t *ibmf_cip,
1517c478bd9Sstevel@tonic-gate     ibmf_register_info_t *ir_client, ibmf_client_t **clientpp);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate  * ibmf_init():
1557c478bd9Sstevel@tonic-gate  *	Initializes module state and registers with the IBT framework.
1567c478bd9Sstevel@tonic-gate  * 	Returns 0 if initialization was successful, else returns non-zero.
1577c478bd9Sstevel@tonic-gate  */
1587c478bd9Sstevel@tonic-gate int
ibmf_init(void)1597c478bd9Sstevel@tonic-gate ibmf_init(void)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	ibt_status_t 	status;
1627c478bd9Sstevel@tonic-gate 	ibt_clnt_hdl_t 	ibmf_ibt_handle;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_start,
1657c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_init() enter\n");
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	/* setup the IBT module information */
16803494a98SBill Taylor 	ibmf_statep->ibmf_ibt_modinfo.mi_ibt_version = IBTI_V_CURR;
1697c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_ibt_modinfo.mi_clnt_class = IBT_IBMA;
1707c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_ibt_modinfo.mi_async_handler
1717c478bd9Sstevel@tonic-gate 	    = ibmf_ibt_async_handler;
1727c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_ibt_modinfo.mi_reserved = NULL;
1737c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_ibt_modinfo.mi_clnt_name = "ibmf";
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	/* setup a connection to IB transport layer (IBTF) */
1767c478bd9Sstevel@tonic-gate 	status = ibt_attach(&ibmf_statep->ibmf_ibt_modinfo, (void *)NULL,
1777c478bd9Sstevel@tonic-gate 	    (void *)NULL, (void *)&ibmf_ibt_handle);
1787c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
1797c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_init_err,
1807c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
1817c478bd9Sstevel@tonic-gate 		    "ibt attach failed", tnf_uint, status, status);
1827c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_end,
1837c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_init() exit\n");
1847c478bd9Sstevel@tonic-gate 		return (1);
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	/* initialize the IBMF state context */
1887c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_ibt_handle = ibmf_ibt_handle;
1897c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_ci_list = (ibmf_ci_t *)NULL;
1907c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_ci_list_tail = (ibmf_ci_t *)NULL;
1917c478bd9Sstevel@tonic-gate 	mutex_init(&ibmf_statep->ibmf_mutex, NULL, MUTEX_DRIVER, NULL);
1927c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_cq_handler = ibmf_i_mad_completions;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	ibmf_statep->ibmf_taskq = taskq_create("ibmf_taskq", IBMF_TASKQ_1THREAD,
1957c478bd9Sstevel@tonic-gate 	    MINCLSYSPRI, 1, ibmf_taskq_max_tasks, TASKQ_PREPOPULATE);
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_end,
1987c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_init() exit\n");
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	return (0);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * ibmf_fini():
2057c478bd9Sstevel@tonic-gate  *	Cleans up module state resources and unregisters from IBT framework.
2067c478bd9Sstevel@tonic-gate  */
2077c478bd9Sstevel@tonic-gate int
ibmf_fini(void)2087c478bd9Sstevel@tonic-gate ibmf_fini(void)
2097c478bd9Sstevel@tonic-gate {
2107c478bd9Sstevel@tonic-gate 	ibmf_ci_t	*cip;
2117c478bd9Sstevel@tonic-gate 	ibmf_ci_t	*tcip;
2127c478bd9Sstevel@tonic-gate 	ibt_status_t	status;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_start,
2157c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_fini() enter\n");
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex));
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_statep->ibmf_mutex);
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	/* free all the Channel Interface (CI) context structures */
2227c478bd9Sstevel@tonic-gate 	cip = ibmf_statep->ibmf_ci_list;
2237c478bd9Sstevel@tonic-gate 	tcip = NULL;
2247c478bd9Sstevel@tonic-gate 	while (cip != (ibmf_ci_t *)NULL) {
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 		mutex_enter(&cip->ci_mutex);
2277c478bd9Sstevel@tonic-gate 		ASSERT((cip->ci_state == IBMF_CI_STATE_PRESENT && cip->ci_ref ==
2287c478bd9Sstevel@tonic-gate 		    0) || (cip->ci_state == IBMF_CI_STATE_GONE));
2297c478bd9Sstevel@tonic-gate 		ASSERT(cip->ci_init_state == IBMF_CI_INIT_HCA_LINKED);
2307c478bd9Sstevel@tonic-gate 		ASSERT(cip->ci_qp_list == NULL && cip->ci_qp_list_tail == NULL);
2317c478bd9Sstevel@tonic-gate 		if (tcip != (ibmf_ci_t *)NULL)
2327c478bd9Sstevel@tonic-gate 			tcip->ci_next = cip->ci_next;
2337c478bd9Sstevel@tonic-gate 		if (ibmf_statep->ibmf_ci_list_tail == cip)
2347c478bd9Sstevel@tonic-gate 			ibmf_statep->ibmf_ci_list_tail = NULL;
2357c478bd9Sstevel@tonic-gate 		if (ibmf_statep->ibmf_ci_list == cip)
2367c478bd9Sstevel@tonic-gate 			ibmf_statep->ibmf_ci_list = cip->ci_next;
2377c478bd9Sstevel@tonic-gate 		tcip = cip->ci_next;
2387c478bd9Sstevel@tonic-gate 		mutex_exit(&cip->ci_mutex);
2397c478bd9Sstevel@tonic-gate 		/* free up the ci structure */
2407c478bd9Sstevel@tonic-gate 		if (cip->ci_port_kstatp != NULL) {
2417c478bd9Sstevel@tonic-gate 			kstat_delete(cip->ci_port_kstatp);
2427c478bd9Sstevel@tonic-gate 		}
2437c478bd9Sstevel@tonic-gate 		mutex_destroy(&cip->ci_mutex);
2447c478bd9Sstevel@tonic-gate 		mutex_destroy(&cip->ci_clients_mutex);
2457c478bd9Sstevel@tonic-gate 		mutex_destroy(&cip->ci_wqe_mutex);
2467c478bd9Sstevel@tonic-gate 		cv_destroy(&cip->ci_state_cv);
2477c478bd9Sstevel@tonic-gate 		cv_destroy(&cip->ci_wqes_cv);
2487c478bd9Sstevel@tonic-gate 		kmem_free((void *) cip, sizeof (ibmf_ci_t));
2497c478bd9Sstevel@tonic-gate 		cip = tcip;
2507c478bd9Sstevel@tonic-gate 	}
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	ASSERT(ibmf_statep->ibmf_ci_list == NULL);
2537c478bd9Sstevel@tonic-gate 	ASSERT(ibmf_statep->ibmf_ci_list_tail == NULL);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	taskq_destroy(ibmf_statep->ibmf_taskq);
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_statep->ibmf_mutex);
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	/* detach from IBTF */
2607c478bd9Sstevel@tonic-gate 	status = ibt_detach(ibmf_statep->ibmf_ibt_handle);
2617c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
2627c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_fini_err,
2637c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
2647c478bd9Sstevel@tonic-gate 		    "ibt detach error", tnf_uint, status, status);
2657c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_end,
2667c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_fini() exit\n");
2677c478bd9Sstevel@tonic-gate 		return (1);
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	mutex_destroy(&ibmf_statep->ibmf_mutex);
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_end,
2737c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_fini() exit\n");
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	return (0);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate  * ibmf_i_validate_class_mask():
2807c478bd9Sstevel@tonic-gate  *	Checks client type value in client information structure.
2817c478bd9Sstevel@tonic-gate  */
2827c478bd9Sstevel@tonic-gate int
ibmf_i_validate_class_mask(ibmf_register_info_t * client_infop)2837c478bd9Sstevel@tonic-gate ibmf_i_validate_class_mask(ibmf_register_info_t	*client_infop)
2847c478bd9Sstevel@tonic-gate {
2857c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
2867c478bd9Sstevel@tonic-gate 	    ibmf_i_validate_class_mask_start, IBMF_TNF_TRACE, "",
2877c478bd9Sstevel@tonic-gate 	    "ibmf_i_validate_class_mask() enter, client_infop = %p\n",
2887c478bd9Sstevel@tonic-gate 	    tnf_opaque, client_infop, client_infop);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	if (IBMF_VALID_CLIENT_TYPE(client_infop->ir_client_class) == B_FALSE) {
2917c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
2927c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_class_mask_err, IBMF_TNF_ERROR, "",
2937c478bd9Sstevel@tonic-gate 		    "%s, class = %x\n", tnf_string, msg,
2947c478bd9Sstevel@tonic-gate 		    "invalid class", tnf_uint, class,
2957c478bd9Sstevel@tonic-gate 		    client_infop->ir_client_class);
2967c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
2977c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_class_mask_end, IBMF_TNF_TRACE, "",
2987c478bd9Sstevel@tonic-gate 		    "ibmf_i_validate_class_mask() exit\n");
2997c478bd9Sstevel@tonic-gate 		return (IBMF_BAD_CLASS);
3007c478bd9Sstevel@tonic-gate 	}
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_validate_class_mask_end,
3037c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_validate_class_mask() exit\n");
3047c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate  * ibmf_i_validate_ci_guid_and_port():
3097c478bd9Sstevel@tonic-gate  *	Checks validity of port number and HCA GUID at client
3107c478bd9Sstevel@tonic-gate  *	registration time.
3117c478bd9Sstevel@tonic-gate  */
3127c478bd9Sstevel@tonic-gate int
ibmf_i_validate_ci_guid_and_port(ib_guid_t hca_guid,uint8_t port_num)3137c478bd9Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port(ib_guid_t hca_guid, uint8_t port_num)
3147c478bd9Sstevel@tonic-gate {
3157c478bd9Sstevel@tonic-gate 	ibt_status_t	status;
3167c478bd9Sstevel@tonic-gate 	ibt_hca_attr_t	hca_attrs;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
3197c478bd9Sstevel@tonic-gate 	    ibmf_i_validate_ci_guid_and_port_start, IBMF_TNF_TRACE, "",
3207c478bd9Sstevel@tonic-gate 	    "ibmf_i_validate_ci_guid_and_port() enter, hca_guid = %x, "
3217c478bd9Sstevel@tonic-gate 	    "port_num = %d\n", tnf_opaque, hca_guid, hca_guid,
3227c478bd9Sstevel@tonic-gate 	    tnf_uint, port_num, port_num);
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	/* check for incorrect port number specification */
3257c478bd9Sstevel@tonic-gate 	if (port_num == 0) {
3267c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, 1,
3277c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_ci_guid_and_port_err, IBMF_TNF_ERROR, "",
3287c478bd9Sstevel@tonic-gate 		    "%s\n", tnf_string, msg, "port num is 0");
3297c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3307c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "",
3317c478bd9Sstevel@tonic-gate 		    "ibmf_i_validate_ci_guid_and_port() exit\n");
3327c478bd9Sstevel@tonic-gate 		return (IBMF_BAD_PORT);
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	/* call IB transport layer for HCA attributes */
3367c478bd9Sstevel@tonic-gate 	status = ibt_query_hca_byguid(hca_guid, &hca_attrs);
3377c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
3387c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
3397c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_ci_guid_and_port_err,
3407c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
3417c478bd9Sstevel@tonic-gate 		    "query_hca_guid failed", tnf_uint, status, status);
3427c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3437c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "",
3447c478bd9Sstevel@tonic-gate 		    "ibmf_i_validate_ci_guid_and_port() exit\n");
3457c478bd9Sstevel@tonic-gate 		return (IBMF_BAD_NODE);
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	/* check if the specified port number is within the HCAs range */
3497c478bd9Sstevel@tonic-gate 	if (port_num > hca_attrs.hca_nports) {
3507c478bd9Sstevel@tonic-gate 		IBMF_TRACE_3(IBMF_TNF_NODEBUG, 1,
3517c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_ci_guid_and_port_err, IBMF_TNF_ERROR, "",
3527c478bd9Sstevel@tonic-gate 		    "%s, num = %d, hca_ports = %d\n",
3537c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "port num > valid ports",
3547c478bd9Sstevel@tonic-gate 		    tnf_uint, num, port_num, tnf_uint, hca_nports,
3557c478bd9Sstevel@tonic-gate 		    hca_attrs.hca_nports);
3567c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3577c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "",
3587c478bd9Sstevel@tonic-gate 		    "ibmf_i_validate_ci_guid_and_port() exit\n");
3597c478bd9Sstevel@tonic-gate 		return (IBMF_BAD_PORT);
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3637c478bd9Sstevel@tonic-gate 	    ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "",
3647c478bd9Sstevel@tonic-gate 	    "ibmf_i_validate_ci_guid_and_port() exit\n");
3657c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate  * ibmf_i_lookup_ci():
3707c478bd9Sstevel@tonic-gate  * 	Lookup the ci and return if found. If the CI is not found, returns
3717c478bd9Sstevel@tonic-gate  * 	NULL.
3727c478bd9Sstevel@tonic-gate  */
3737c478bd9Sstevel@tonic-gate static ibmf_ci_t *
ibmf_i_lookup_ci(ib_guid_t ci_guid)3747c478bd9Sstevel@tonic-gate ibmf_i_lookup_ci(ib_guid_t ci_guid)
3757c478bd9Sstevel@tonic-gate {
3767c478bd9Sstevel@tonic-gate 	ibmf_ci_t	*cip = NULL;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex));
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_lookup_ci_start,
3817c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_lookup_ci(): enter, guid = 0x%x\n",
3827c478bd9Sstevel@tonic-gate 	    tnf_uint64, guid, ci_guid);
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	/* walk the CI list looking for one that matches the provided GUID */
3857c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_statep->ibmf_mutex);
3867c478bd9Sstevel@tonic-gate 	cip = ibmf_statep->ibmf_ci_list;
3877c478bd9Sstevel@tonic-gate 	while (cip != (ibmf_ci_t *)NULL) {
3887c478bd9Sstevel@tonic-gate 		if (ci_guid == cip->ci_node_guid) {
3897c478bd9Sstevel@tonic-gate 			/* found it in our list */
3907c478bd9Sstevel@tonic-gate 			break;
3917c478bd9Sstevel@tonic-gate 		}
3927c478bd9Sstevel@tonic-gate 		cip = cip->ci_next;
3937c478bd9Sstevel@tonic-gate 	}
3947c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_statep->ibmf_mutex);
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_lookup_ci_end,
3977c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_lookup_ci() exit\n");
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	return (cip);
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate /*
4037c478bd9Sstevel@tonic-gate  * ibmf_i_get_ci():
4047c478bd9Sstevel@tonic-gate  *	Get the CI structure based on the HCA GUID from a list if it exists.
4057c478bd9Sstevel@tonic-gate  *	If the CI structure does not exist, and the HCA GUID is valid,
4067c478bd9Sstevel@tonic-gate  *	create a new CI structure and add it to the list.
4077c478bd9Sstevel@tonic-gate  */
4087c478bd9Sstevel@tonic-gate int
ibmf_i_get_ci(ibmf_register_info_t * client_infop,ibmf_ci_t ** cipp)4097c478bd9Sstevel@tonic-gate ibmf_i_get_ci(ibmf_register_info_t *client_infop, ibmf_ci_t **cipp)
4107c478bd9Sstevel@tonic-gate {
4117c478bd9Sstevel@tonic-gate 	ibmf_ci_t 		*cip;
4127c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
4137c478bd9Sstevel@tonic-gate 	boolean_t		invalid = B_FALSE;
4147c478bd9Sstevel@tonic-gate 	ibt_hca_attr_t		hca_attrs;
4157c478bd9Sstevel@tonic-gate 	ibmf_port_kstat_t	*ksp;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_start,
4187c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_get_ci() enter, clinfop = %p\n",
4197c478bd9Sstevel@tonic-gate 	    tnf_opaque, client_infop, client_infop);
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	/* look for a CI context with a matching GUID */
4227c478bd9Sstevel@tonic-gate 	cip = ibmf_i_lookup_ci(client_infop->ir_ci_guid);
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	if (cip == NULL) {
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 		/*
4277c478bd9Sstevel@tonic-gate 		 * attempt to create the ci. First, verify the ci exists.
4287c478bd9Sstevel@tonic-gate 		 * If it exists, allocate ci memory and insert in the ci list.
4297c478bd9Sstevel@tonic-gate 		 * It is possible that some other thread raced with us
4307c478bd9Sstevel@tonic-gate 		 * and inserted created ci while we are blocked in
4317c478bd9Sstevel@tonic-gate 		 * allocating memory. Check for that case and if that is indeed
4327c478bd9Sstevel@tonic-gate 		 * the case, free up what we allocated and try to get a
4337c478bd9Sstevel@tonic-gate 		 * reference count on the ci that the other thread added.
4347c478bd9Sstevel@tonic-gate 		 */
4357c478bd9Sstevel@tonic-gate 		status = ibt_query_hca_byguid(client_infop->ir_ci_guid,
4367c478bd9Sstevel@tonic-gate 		    &hca_attrs);
4377c478bd9Sstevel@tonic-gate 		if (status == IBT_SUCCESS) {
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 			ibmf_ci_t *tcip;
4407c478bd9Sstevel@tonic-gate 			char buf[128];
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 			/* allocate memory for the CI structure */
4437c478bd9Sstevel@tonic-gate 			cip = (ibmf_ci_t *)kmem_zalloc(sizeof (ibmf_ci_t),
4447c478bd9Sstevel@tonic-gate 			    KM_SLEEP);
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 			_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cip))
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 			mutex_init(&cip->ci_mutex, NULL, MUTEX_DRIVER, NULL);
4497c478bd9Sstevel@tonic-gate 			mutex_init(&cip->ci_clients_mutex, NULL, MUTEX_DRIVER,
4507c478bd9Sstevel@tonic-gate 			    NULL);
4517c478bd9Sstevel@tonic-gate 			mutex_init(&cip->ci_wqe_mutex, NULL, MUTEX_DRIVER,
4527c478bd9Sstevel@tonic-gate 			    NULL);
4537c478bd9Sstevel@tonic-gate 			cv_init(&cip->ci_state_cv, NULL, CV_DRIVER, NULL);
4547c478bd9Sstevel@tonic-gate 			cv_init(&cip->ci_wqes_cv, NULL, CV_DRIVER, NULL);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "r%08X",
4577c478bd9Sstevel@tonic-gate 			    (uint32_t)client_infop->ir_ci_guid);
4587c478bd9Sstevel@tonic-gate 			mutex_enter(&cip->ci_mutex);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 			cip->ci_state = IBMF_CI_STATE_PRESENT;
4617c478bd9Sstevel@tonic-gate 			cip->ci_node_guid = client_infop->ir_ci_guid;
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 			/* set up per CI kstats */
4647c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "ibmf_%016" PRIx64 "_%d_stat",
4657c478bd9Sstevel@tonic-gate 			    client_infop->ir_ci_guid,
4667c478bd9Sstevel@tonic-gate 			    client_infop->ir_port_num);
4677c478bd9Sstevel@tonic-gate 			if ((cip->ci_port_kstatp = kstat_create("ibmf", 0, buf,
4687c478bd9Sstevel@tonic-gate 			    "misc", KSTAT_TYPE_NAMED,
4697c478bd9Sstevel@tonic-gate 			    sizeof (ibmf_port_kstat_t) / sizeof (kstat_named_t),
4707c478bd9Sstevel@tonic-gate 			    KSTAT_FLAG_WRITABLE)) == NULL) {
4717c478bd9Sstevel@tonic-gate 				mutex_exit(&cip->ci_mutex);
4727c478bd9Sstevel@tonic-gate 				mutex_destroy(&cip->ci_mutex);
4737c478bd9Sstevel@tonic-gate 				mutex_destroy(&cip->ci_clients_mutex);
4747c478bd9Sstevel@tonic-gate 				mutex_destroy(&cip->ci_wqe_mutex);
4757c478bd9Sstevel@tonic-gate 				cv_destroy(&cip->ci_state_cv);
4767c478bd9Sstevel@tonic-gate 				cv_destroy(&cip->ci_wqes_cv);
4777c478bd9Sstevel@tonic-gate 				kmem_free((void *)cip, sizeof (ibmf_ci_t));
4787c478bd9Sstevel@tonic-gate 				IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
4797c478bd9Sstevel@tonic-gate 				    ibmf_i_get_ci_err, IBMF_TNF_ERROR, "",
4807c478bd9Sstevel@tonic-gate 				    "%s\n", tnf_string, msg,
4817c478bd9Sstevel@tonic-gate 				    "kstat create failed");
4827c478bd9Sstevel@tonic-gate 				IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
4837c478bd9Sstevel@tonic-gate 				    ibmf_i_get_ci_end, IBMF_TNF_TRACE, "",
4847c478bd9Sstevel@tonic-gate 				    "ibmf_i_get_ci() exit\n");
4857c478bd9Sstevel@tonic-gate 				return (IBMF_NO_RESOURCES);
4867c478bd9Sstevel@tonic-gate 			}
4877c478bd9Sstevel@tonic-gate 			ksp = (ibmf_port_kstat_t *)cip->ci_port_kstatp->ks_data;
4887c478bd9Sstevel@tonic-gate 			kstat_named_init(&ksp->clients_registered,
4897c478bd9Sstevel@tonic-gate 			    "clients_registered", KSTAT_DATA_UINT32);
4907c478bd9Sstevel@tonic-gate 			kstat_named_init(&ksp->client_regs_failed,
4917c478bd9Sstevel@tonic-gate 			    "client_registrations_failed", KSTAT_DATA_UINT32);
4927c478bd9Sstevel@tonic-gate 			kstat_named_init(&ksp->send_wqes_alloced,
4937c478bd9Sstevel@tonic-gate 			    "send_wqes_allocated", KSTAT_DATA_UINT32);
4947c478bd9Sstevel@tonic-gate 			kstat_named_init(&ksp->recv_wqes_alloced,
4957c478bd9Sstevel@tonic-gate 			    "receive_wqes_allocated", KSTAT_DATA_UINT32);
4967c478bd9Sstevel@tonic-gate 			kstat_named_init(&ksp->swqe_allocs_failed,
4977c478bd9Sstevel@tonic-gate 			    "send_wqe_allocs_failed", KSTAT_DATA_UINT32);
4987c478bd9Sstevel@tonic-gate 			kstat_named_init(&ksp->rwqe_allocs_failed,
4997c478bd9Sstevel@tonic-gate 			    "recv_wqe_allocs_failed", KSTAT_DATA_UINT32);
5007c478bd9Sstevel@tonic-gate 			kstat_install(cip->ci_port_kstatp);
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 			mutex_exit(&cip->ci_mutex);
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 			mutex_enter(&ibmf_statep->ibmf_mutex);
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 			tcip = ibmf_statep->ibmf_ci_list;
5077c478bd9Sstevel@tonic-gate 			while (tcip != (ibmf_ci_t *)NULL) {
5087c478bd9Sstevel@tonic-gate 				if (client_infop->ir_ci_guid ==
5097c478bd9Sstevel@tonic-gate 				    tcip->ci_node_guid) {
5107c478bd9Sstevel@tonic-gate 					/* found it in our list */
5117c478bd9Sstevel@tonic-gate 					break;
5127c478bd9Sstevel@tonic-gate 				}
5137c478bd9Sstevel@tonic-gate 				tcip = tcip->ci_next;
5147c478bd9Sstevel@tonic-gate 			}
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 			/* if the ci isn't on the list, add it */
5177c478bd9Sstevel@tonic-gate 			if (tcip == NULL) {
5187c478bd9Sstevel@tonic-gate 				cip->ci_next = NULL;
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip))
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 				if (ibmf_statep->ibmf_ci_list_tail != NULL)
5237c478bd9Sstevel@tonic-gate 					ibmf_statep->ibmf_ci_list_tail->
5247c478bd9Sstevel@tonic-gate 					    ci_next = cip;
5257c478bd9Sstevel@tonic-gate 				if (ibmf_statep->ibmf_ci_list == NULL)
5267c478bd9Sstevel@tonic-gate 					ibmf_statep->ibmf_ci_list = cip;
5277c478bd9Sstevel@tonic-gate 				ibmf_statep->ibmf_ci_list_tail = cip;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 				mutex_enter(&cip->ci_mutex);
5307c478bd9Sstevel@tonic-gate 				cip->ci_init_state |= IBMF_CI_INIT_HCA_LINKED;
5317c478bd9Sstevel@tonic-gate 				mutex_exit(&cip->ci_mutex);
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 			} else {
5347c478bd9Sstevel@tonic-gate 				/* free cip and set it to the one on the list */
5357c478bd9Sstevel@tonic-gate 				kstat_delete(cip->ci_port_kstatp);
5367c478bd9Sstevel@tonic-gate 				mutex_destroy(&cip->ci_mutex);
5377c478bd9Sstevel@tonic-gate 				mutex_destroy(&cip->ci_clients_mutex);
5387c478bd9Sstevel@tonic-gate 				mutex_destroy(&cip->ci_wqe_mutex);
5397c478bd9Sstevel@tonic-gate 				cv_destroy(&cip->ci_state_cv);
5407c478bd9Sstevel@tonic-gate 				cv_destroy(&cip->ci_wqes_cv);
5417c478bd9Sstevel@tonic-gate 				kmem_free((void *)cip, sizeof (ibmf_ci_t));
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip))
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 				cip = tcip;
5467c478bd9Sstevel@tonic-gate 			}
5477c478bd9Sstevel@tonic-gate 			mutex_exit(&ibmf_statep->ibmf_mutex);
5487c478bd9Sstevel@tonic-gate 		} else {
5497c478bd9Sstevel@tonic-gate 			/* we didn't find it and the CI doesn't exist */
5507c478bd9Sstevel@tonic-gate 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1,
5517c478bd9Sstevel@tonic-gate 			    ibmf_i_get_ci_err, IBMF_TNF_ERROR, "", "%s\n",
5527c478bd9Sstevel@tonic-gate 			    tnf_string, msg, "GUID doesn't exist");
5537c478bd9Sstevel@tonic-gate 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
5547c478bd9Sstevel@tonic-gate 			    ibmf_i_get_ci_end, IBMF_TNF_TRACE, "",
5557c478bd9Sstevel@tonic-gate 			    "ibmf_i_get_ci() exit\n");
5567c478bd9Sstevel@tonic-gate 			return (IBMF_TRANSPORT_FAILURE);
5577c478bd9Sstevel@tonic-gate 		}
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	ASSERT(cip != NULL);
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	/*
5637c478bd9Sstevel@tonic-gate 	 * We now have a CI context structure, either found it on the list,
5647c478bd9Sstevel@tonic-gate 	 * or created it.
5657c478bd9Sstevel@tonic-gate 	 * We now proceed to intialize the CI context.
5667c478bd9Sstevel@tonic-gate 	 */
5677c478bd9Sstevel@tonic-gate 	for (;;) {
5687c478bd9Sstevel@tonic-gate 		mutex_enter(&cip->ci_mutex);
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 		/* CI is INITED & no state change in progress; we are all set */
5717c478bd9Sstevel@tonic-gate 		if (cip->ci_state == IBMF_CI_STATE_INITED && (cip->
5727c478bd9Sstevel@tonic-gate 		    ci_state_flags & (IBMF_CI_STATE_INVALIDATING |
5737c478bd9Sstevel@tonic-gate 		    IBMF_CI_STATE_UNINITING)) == 0) {
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 			cip->ci_ref++;
5767c478bd9Sstevel@tonic-gate 			mutex_exit(&cip->ci_mutex);
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 			break;
5797c478bd9Sstevel@tonic-gate 		}
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 		/* CI is PRESENT; transition it to INITED */
5827c478bd9Sstevel@tonic-gate 		if (cip->ci_state == IBMF_CI_STATE_PRESENT && (cip->
5837c478bd9Sstevel@tonic-gate 		    ci_state_flags & (IBMF_CI_STATE_INVALIDATING |
5847c478bd9Sstevel@tonic-gate 		    IBMF_CI_STATE_INITING)) == 0) {
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 			/* mark state as initing and init the ci */
5877c478bd9Sstevel@tonic-gate 			cip->ci_state_flags |= IBMF_CI_STATE_INITING;
5887c478bd9Sstevel@tonic-gate 			mutex_exit(&cip->ci_mutex);
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 			_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cip))
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 			if (ibmf_i_init_ci(client_infop, cip) != IBMF_SUCCESS) {
5937c478bd9Sstevel@tonic-gate 				invalid = B_TRUE;
5947c478bd9Sstevel@tonic-gate 				break;
5957c478bd9Sstevel@tonic-gate 			}
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 			_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip))
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 			continue;
6007c478bd9Sstevel@tonic-gate 		}
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 		/*
6037c478bd9Sstevel@tonic-gate 		 * If CI is GONE and no validation is in progress, we should
6047c478bd9Sstevel@tonic-gate 		 * return failure. Also, if CI is INITED but in the process of
6057c478bd9Sstevel@tonic-gate 		 * being made GONE (ie., a hot remove in progress), return
6067c478bd9Sstevel@tonic-gate 		 * failure.
6077c478bd9Sstevel@tonic-gate 		 */
6087c478bd9Sstevel@tonic-gate 		if ((cip->ci_state == IBMF_CI_STATE_GONE && (cip->
6097c478bd9Sstevel@tonic-gate 		    ci_state_flags & IBMF_CI_STATE_VALIDATING) == 0) ||
6107c478bd9Sstevel@tonic-gate 		    (cip->ci_state == IBMF_CI_STATE_INITED && (cip->
6117c478bd9Sstevel@tonic-gate 		    ci_state_flags & IBMF_CI_STATE_INVALIDATING) != 0)) {
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 			IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
6147c478bd9Sstevel@tonic-gate 			    ibmf_i_get_ci_err, IBMF_TNF_ERROR, "",
6157c478bd9Sstevel@tonic-gate 			    "ci_state = %x, ci_state_flags = %x\n",
6167c478bd9Sstevel@tonic-gate 			    tnf_opaque, cip->ci_state, cip->ci_state,
6177c478bd9Sstevel@tonic-gate 			    tnf_opaque, cip->ci_state_flags,
6187c478bd9Sstevel@tonic-gate 			    cip->ci_state_flags);
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 			invalid = B_TRUE;
6217c478bd9Sstevel@tonic-gate 			mutex_exit(&cip->ci_mutex);
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 			break;
6247c478bd9Sstevel@tonic-gate 		}
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		/* a state change in progress; block waiting for state change */
6277c478bd9Sstevel@tonic-gate 		if (cip->ci_state_flags & IBMF_CI_STATE_VALIDATING)
6287c478bd9Sstevel@tonic-gate 			cip->ci_state_flags |= IBMF_CI_STATE_VALIDATE_WAIT;
6297c478bd9Sstevel@tonic-gate 		else if (cip->ci_state_flags & IBMF_CI_STATE_INITING)
6307c478bd9Sstevel@tonic-gate 			cip->ci_state_flags |= IBMF_CI_STATE_INIT_WAIT;
6317c478bd9Sstevel@tonic-gate 		else if (cip->ci_state_flags & IBMF_CI_STATE_UNINITING)
6327c478bd9Sstevel@tonic-gate 			cip->ci_state_flags |= IBMF_CI_STATE_UNINIT_WAIT;
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 		cv_wait(&cip->ci_state_cv, &cip->ci_mutex);
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 		mutex_exit(&cip->ci_mutex);
6377c478bd9Sstevel@tonic-gate 	}
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	if (invalid == B_TRUE) {
6407c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L2, ibmf_i_get_ci_err,
6417c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "ibmf_i_get_ci() error\n");
6427c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end,
6437c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n");
6447c478bd9Sstevel@tonic-gate 		return (IBMF_FAILURE);
6457c478bd9Sstevel@tonic-gate 	}
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	if (cip != NULL) {
6487c478bd9Sstevel@tonic-gate 		*cipp = cip;
6497c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end,
6507c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n");
6517c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
6527c478bd9Sstevel@tonic-gate 	} else {
6537c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end,
6547c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n");
6557c478bd9Sstevel@tonic-gate 		return (IBMF_FAILURE);
6567c478bd9Sstevel@tonic-gate 	}
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate /*
6607c478bd9Sstevel@tonic-gate  * ibmf_i_release_ci():
6617c478bd9Sstevel@tonic-gate  *	Drop the reference count for the CI.
6627c478bd9Sstevel@tonic-gate  */
6637c478bd9Sstevel@tonic-gate void
ibmf_i_release_ci(ibmf_ci_t * cip)6647c478bd9Sstevel@tonic-gate ibmf_i_release_ci(ibmf_ci_t *cip)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate 	uint_t ref;
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_ci_start,
6697c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_release_ci() enter, cip = %p\n",
6707c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, cip);
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
6757c478bd9Sstevel@tonic-gate 	ref = cip->ci_ref--;
6767c478bd9Sstevel@tonic-gate 	if (ref == 1) {
6777c478bd9Sstevel@tonic-gate 		ASSERT(cip->ci_state == IBMF_CI_STATE_INITED);
6787c478bd9Sstevel@tonic-gate 		cip->ci_state_flags |= IBMF_CI_STATE_UNINITING;
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	if (ref == 1) {
6837c478bd9Sstevel@tonic-gate 		ibmf_i_uninit_ci(cip);
6847c478bd9Sstevel@tonic-gate 	}
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_ci_end,
6877c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_release_ci() exit\n");
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate /*
6917c478bd9Sstevel@tonic-gate  * ibmf_i_init_ci():
6927c478bd9Sstevel@tonic-gate  *	Initialize the CI structure by setting up the HCA, allocating
6937c478bd9Sstevel@tonic-gate  *	protection domains, completion queues, a pool of WQEs.
6947c478bd9Sstevel@tonic-gate  */
6957c478bd9Sstevel@tonic-gate /* ARGSUSED */
6967c478bd9Sstevel@tonic-gate static int
ibmf_i_init_ci(ibmf_register_info_t * client_infop,ibmf_ci_t * cip)6977c478bd9Sstevel@tonic-gate ibmf_i_init_ci(ibmf_register_info_t *client_infop, ibmf_ci_t *cip)
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate 	ibt_pd_hdl_t		pd;
7007c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
7017c478bd9Sstevel@tonic-gate 	ib_guid_t		ci_guid;
7027c478bd9Sstevel@tonic-gate 	ibt_hca_attr_t		hca_attrs;
7037c478bd9Sstevel@tonic-gate 	ibt_hca_hdl_t		hca_handle;
7047c478bd9Sstevel@tonic-gate 	ibt_pd_flags_t		pd_flags = IBT_PD_NO_FLAGS;
7057c478bd9Sstevel@tonic-gate 	boolean_t		error = B_FALSE;
7067c478bd9Sstevel@tonic-gate 	int			ibmfstatus = IBMF_SUCCESS;
7077c478bd9Sstevel@tonic-gate 	char			errmsg[128];
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	_NOTE(ASSUMING_PROTECTED(*cip))
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex));
7127c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_start,
7157c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_ci() enter, cip = %p\n",
7167c478bd9Sstevel@tonic-gate 	    tnf_opaque, ibmf_ci, cip);
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
7197c478bd9Sstevel@tonic-gate 	ci_guid = cip->ci_node_guid;
7207c478bd9Sstevel@tonic-gate 	ASSERT(cip->ci_state == IBMF_CI_STATE_PRESENT);
7217c478bd9Sstevel@tonic-gate 	ASSERT((cip->ci_state_flags & IBMF_CI_STATE_INITING) != 0);
7227c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	/* set up a connection to the HCA specified by the GUID */
7257c478bd9Sstevel@tonic-gate 	status = ibt_open_hca(ibmf_statep->ibmf_ibt_handle, ci_guid,
7267c478bd9Sstevel@tonic-gate 	    &hca_handle);
7277c478bd9Sstevel@tonic-gate 	ASSERT(status != IBT_HCA_IN_USE);
7287c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
7297c478bd9Sstevel@tonic-gate 		ibmf_i_init_ci_done(cip);
7307c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "ibt open hca failed, status = 0x%x",
7317c478bd9Sstevel@tonic-gate 		    status);
7327c478bd9Sstevel@tonic-gate 		error = B_TRUE;
7337c478bd9Sstevel@tonic-gate 		ibmfstatus = IBMF_TRANSPORT_FAILURE;
7347c478bd9Sstevel@tonic-gate 		goto bail;
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	/* get the HCA attributes */
7387c478bd9Sstevel@tonic-gate 	status = ibt_query_hca(hca_handle, &hca_attrs);
7397c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
7407c478bd9Sstevel@tonic-gate 		(void) ibt_close_hca(hca_handle);
7417c478bd9Sstevel@tonic-gate 		ibmf_i_init_ci_done(cip);
7427c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "ibt query hca failed, status = 0x%x",
7437c478bd9Sstevel@tonic-gate 		    status);
7447c478bd9Sstevel@tonic-gate 		error = B_TRUE;
7457c478bd9Sstevel@tonic-gate 		ibmfstatus = IBMF_TRANSPORT_FAILURE;
7467c478bd9Sstevel@tonic-gate 		goto bail;
7477c478bd9Sstevel@tonic-gate 	}
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	/* allocate a Protection Domain */
7507c478bd9Sstevel@tonic-gate 	status = ibt_alloc_pd(hca_handle, pd_flags, &pd);
7517c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
7527c478bd9Sstevel@tonic-gate 		(void) ibt_close_hca(hca_handle);
7537c478bd9Sstevel@tonic-gate 		ibmf_i_init_ci_done(cip);
7547c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "alloc PD failed, status = 0x%x",
7557c478bd9Sstevel@tonic-gate 		    status);
7567c478bd9Sstevel@tonic-gate 		error = B_TRUE;
7577c478bd9Sstevel@tonic-gate 		ibmfstatus = IBMF_TRANSPORT_FAILURE;
7587c478bd9Sstevel@tonic-gate 		goto bail;
7597c478bd9Sstevel@tonic-gate 	}
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	/* init the ci */
7627c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
7637c478bd9Sstevel@tonic-gate 	cip->ci_nports = hca_attrs.hca_nports;
7647c478bd9Sstevel@tonic-gate 	cip->ci_vendor_id = hca_attrs.hca_vendor_id;
7657c478bd9Sstevel@tonic-gate 	cip->ci_device_id = hca_attrs.hca_device_id;
7667c478bd9Sstevel@tonic-gate 	cip->ci_ci_handle = hca_handle;
7677c478bd9Sstevel@tonic-gate 	cip->ci_pd = pd;
7687c478bd9Sstevel@tonic-gate 	cip->ci_init_state |= IBMF_CI_INIT_HCA_INITED;
7697c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	/* initialize cqs */
7727c478bd9Sstevel@tonic-gate 	if (ibmf_i_init_cqs(cip) != IBMF_SUCCESS) {
7737c478bd9Sstevel@tonic-gate 		(void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd);
7747c478bd9Sstevel@tonic-gate 		mutex_enter(&cip->ci_mutex);
7757c478bd9Sstevel@tonic-gate 		cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED;
7767c478bd9Sstevel@tonic-gate 		mutex_exit(&cip->ci_mutex);
7777c478bd9Sstevel@tonic-gate 		(void) ibt_close_hca(cip->ci_ci_handle);
7787c478bd9Sstevel@tonic-gate 		ibmf_i_init_ci_done(cip);
7797c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "init CQs failed");
7807c478bd9Sstevel@tonic-gate 		error = B_TRUE;
7817c478bd9Sstevel@tonic-gate 		ibmfstatus = IBMF_FAILURE;
7827c478bd9Sstevel@tonic-gate 		goto bail;
7837c478bd9Sstevel@tonic-gate 	}
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	/* initialize wqes */
7867c478bd9Sstevel@tonic-gate 	if (ibmf_i_init_wqes(cip) != IBMF_SUCCESS) {
7877c478bd9Sstevel@tonic-gate 		ibmf_i_fini_cqs(cip);
7887c478bd9Sstevel@tonic-gate 		(void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd);
7897c478bd9Sstevel@tonic-gate 		mutex_enter(&cip->ci_mutex);
7907c478bd9Sstevel@tonic-gate 		cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED;
7917c478bd9Sstevel@tonic-gate 		mutex_exit(&cip->ci_mutex);
7927c478bd9Sstevel@tonic-gate 		(void) ibt_close_hca(cip->ci_ci_handle);
7937c478bd9Sstevel@tonic-gate 		ibmf_i_init_ci_done(cip);
7947c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "init WQEs failed");
7957c478bd9Sstevel@tonic-gate 		error = B_TRUE;
7967c478bd9Sstevel@tonic-gate 		ibmfstatus = IBMF_FAILURE;
7977c478bd9Sstevel@tonic-gate 		goto bail;
7987c478bd9Sstevel@tonic-gate 	}
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 	/* initialize the UD destination structure pool */
8017c478bd9Sstevel@tonic-gate 	ibmf_i_init_ud_dest(cip);
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 	/* initialize the QP list */
8047c478bd9Sstevel@tonic-gate 	ibmf_i_init_qplist(cip);
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	/* initialize condition variable, state, and enable CQ notification */
8077c478bd9Sstevel@tonic-gate 	cip->ci_init_state |= IBMF_CI_INIT_MUTEX_CV_INITED;
8087c478bd9Sstevel@tonic-gate 	(void) ibt_enable_cq_notify(cip->ci_cq_handle, IBT_NEXT_COMPLETION);
8097c478bd9Sstevel@tonic-gate 	(void) ibt_enable_cq_notify(cip->ci_alt_cq_handle, IBT_NEXT_COMPLETION);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	/* set state to INITED */
8127c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
8137c478bd9Sstevel@tonic-gate 	cip->ci_state = IBMF_CI_STATE_INITED;
8147c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	/* wake up waiters blocked on an initialization done event */
8177c478bd9Sstevel@tonic-gate 	ibmf_i_init_ci_done(cip);
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate bail:
8207c478bd9Sstevel@tonic-gate 	if (error) {
8217c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_ci_err,
8227c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
8237c478bd9Sstevel@tonic-gate 		    errmsg, tnf_uint, ibmfstatus, ibmfstatus);
8247c478bd9Sstevel@tonic-gate 	}
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_end,
8277c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_ci() exit, cip = %p\n",
8287c478bd9Sstevel@tonic-gate 	    tnf_opaque, ibmf_ci, cip);
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	return (ibmfstatus);
8317c478bd9Sstevel@tonic-gate }
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate /*
8347c478bd9Sstevel@tonic-gate  * ibmf_i_uninit_ci():
835*448bf859SLida.Horn  *	Free up the resources allocated when initializing the CI structure.
8367c478bd9Sstevel@tonic-gate  */
8377c478bd9Sstevel@tonic-gate static void
ibmf_i_uninit_ci(ibmf_ci_t * cip)8387c478bd9Sstevel@tonic-gate ibmf_i_uninit_ci(ibmf_ci_t *cip)
8397c478bd9Sstevel@tonic-gate {
8407c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_start,
8417c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci() enter, cip = %p\n",
8427c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, cip);
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cip->ci_mutex) == 0);
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	/* clean up the QP list */
8477c478bd9Sstevel@tonic-gate 	ibmf_i_fini_qplist(cip);
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	/* empty completions directly */
8507c478bd9Sstevel@tonic-gate 	ibmf_i_mad_completions(cip->ci_cq_handle, (void*)cip);
8517c478bd9Sstevel@tonic-gate 	ibmf_i_mad_completions(cip->ci_alt_cq_handle, (void*)cip);
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
8547c478bd9Sstevel@tonic-gate 	if (cip->ci_init_state & IBMF_CI_INIT_MUTEX_CV_INITED) {
8557c478bd9Sstevel@tonic-gate 		cip->ci_init_state &= ~IBMF_CI_INIT_MUTEX_CV_INITED;
8567c478bd9Sstevel@tonic-gate 	}
8577c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	/* clean up the UD destination structure pool */
8607c478bd9Sstevel@tonic-gate 	ibmf_i_fini_ud_dest(cip);
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	/* clean up any WQE caches */
8637c478bd9Sstevel@tonic-gate 	ibmf_i_fini_wqes(cip);
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	/* free up the completion queues */
8667c478bd9Sstevel@tonic-gate 	ibmf_i_fini_cqs(cip);
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 	/* free up the protection domain */
8697c478bd9Sstevel@tonic-gate 	(void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd);
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	/* close the HCA connection */
8727c478bd9Sstevel@tonic-gate 	(void) ibt_close_hca(cip->ci_ci_handle);
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	/* set state down to PRESENT */
8757c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
8767c478bd9Sstevel@tonic-gate 	cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED;
8777c478bd9Sstevel@tonic-gate 	cip->ci_state = IBMF_CI_STATE_PRESENT;
8787c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	/* wake up waiters blocked on an un-initialization done event */
8817c478bd9Sstevel@tonic-gate 	ibmf_i_uninit_ci_done(cip);
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_end,
8847c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci() exit\n");
8857c478bd9Sstevel@tonic-gate }
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate /*
8887c478bd9Sstevel@tonic-gate  * ibmf_i_init_ci_done():
8897c478bd9Sstevel@tonic-gate  *	Mark CI initialization as "done", and wake up any waiters.
8907c478bd9Sstevel@tonic-gate  */
8917c478bd9Sstevel@tonic-gate static void
ibmf_i_init_ci_done(ibmf_ci_t * cip)8927c478bd9Sstevel@tonic-gate ibmf_i_init_ci_done(ibmf_ci_t *cip)
8937c478bd9Sstevel@tonic-gate {
8947c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_done_start,
8957c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_ci_done() enter, cip = %p\n",
8967c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, cip);
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
8997c478bd9Sstevel@tonic-gate 	cip->ci_state_flags &= ~IBMF_CI_STATE_INITING;
9007c478bd9Sstevel@tonic-gate 	if (cip->ci_state_flags & IBMF_CI_STATE_INIT_WAIT) {
9017c478bd9Sstevel@tonic-gate 		cip->ci_state_flags &= ~IBMF_CI_STATE_INIT_WAIT;
9027c478bd9Sstevel@tonic-gate 		cv_broadcast(&cip->ci_state_cv);
9037c478bd9Sstevel@tonic-gate 	}
9047c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_done_end,
9077c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_ci_done() exit\n");
9087c478bd9Sstevel@tonic-gate }
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate /*
9117c478bd9Sstevel@tonic-gate  * ibmf_i_uninit_ci_done():
9127c478bd9Sstevel@tonic-gate  *	Mark CI uninitialization as "done", and wake up any waiters.
9137c478bd9Sstevel@tonic-gate  */
9147c478bd9Sstevel@tonic-gate static void
ibmf_i_uninit_ci_done(ibmf_ci_t * cip)9157c478bd9Sstevel@tonic-gate ibmf_i_uninit_ci_done(ibmf_ci_t *cip)
9167c478bd9Sstevel@tonic-gate {
9177c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_done_start,
9187c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci_done() enter, cip = %p\n",
9197c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, cip);
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
9227c478bd9Sstevel@tonic-gate 	cip->ci_state_flags &= ~IBMF_CI_STATE_UNINITING;
9237c478bd9Sstevel@tonic-gate 	if (cip->ci_state_flags & IBMF_CI_STATE_UNINIT_WAIT) {
9247c478bd9Sstevel@tonic-gate 		cip->ci_state_flags &= ~IBMF_CI_STATE_UNINIT_WAIT;
9257c478bd9Sstevel@tonic-gate 		cv_broadcast(&cip->ci_state_cv);
9267c478bd9Sstevel@tonic-gate 	}
9277c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_done_end,
9307c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci_done() exit\n");
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate /*
9347c478bd9Sstevel@tonic-gate  * ibmf_i_init_cqs():
9357c478bd9Sstevel@tonic-gate  *	Allocate a completion queue and set the CQ handler.
9367c478bd9Sstevel@tonic-gate  */
9377c478bd9Sstevel@tonic-gate static int
ibmf_i_init_cqs(ibmf_ci_t * cip)9387c478bd9Sstevel@tonic-gate ibmf_i_init_cqs(ibmf_ci_t *cip)
9397c478bd9Sstevel@tonic-gate {
9407c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
9417c478bd9Sstevel@tonic-gate 	ibt_cq_attr_t		cq_attrs;
9427c478bd9Sstevel@tonic-gate 	ibt_cq_hdl_t		cq_handle;
9437c478bd9Sstevel@tonic-gate 	uint32_t		num_entries;
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_start,
9487c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() enter, cip = %p\n",
9497c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, cip);
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 	/*
9527c478bd9Sstevel@tonic-gate 	 * Allocate completion queue handle.
9537c478bd9Sstevel@tonic-gate 	 * The CQ size should be a 2^n - 1 value to avoid excess CQ allocation
9547c478bd9Sstevel@tonic-gate 	 * as done by some HCAs when the CQ size is specified as a 2^n
9557c478bd9Sstevel@tonic-gate 	 * quantity.
9567c478bd9Sstevel@tonic-gate 	 */
9577c478bd9Sstevel@tonic-gate 	cq_attrs.cq_size = (cip->ci_nports * (ibmf_send_wqes_posted_per_qp +
9587c478bd9Sstevel@tonic-gate 	    ibmf_recv_wqes_posted_per_qp)) - 1;
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	cq_attrs.cq_sched = NULL;
9617c478bd9Sstevel@tonic-gate 	cq_attrs.cq_flags = 0;
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 	/* Get the CQ handle for the special QPs */
9647c478bd9Sstevel@tonic-gate 	status = ibt_alloc_cq(cip->ci_ci_handle, &cq_attrs,
9657c478bd9Sstevel@tonic-gate 	    &cq_handle, &num_entries);
9667c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
9677c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_cqs_err,
9687c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
9697c478bd9Sstevel@tonic-gate 		    "ibt_alloc_cq failed", tnf_uint, ibt_status, status);
9707c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end,
9717c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n");
9727c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
9737c478bd9Sstevel@tonic-gate 	}
9747c478bd9Sstevel@tonic-gate 	ibt_set_cq_handler(cq_handle, ibmf_statep->ibmf_cq_handler, cip);
9757c478bd9Sstevel@tonic-gate 	cip->ci_cq_handle = cq_handle;
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 	/* Get the CQ handle for the alternate QPs */
9787c478bd9Sstevel@tonic-gate 	status = ibt_alloc_cq(cip->ci_ci_handle, &cq_attrs,
9797c478bd9Sstevel@tonic-gate 	    &cq_handle, &num_entries);
9807c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
9817c478bd9Sstevel@tonic-gate 		(void) ibt_free_cq(cip->ci_cq_handle);
9827c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_cqs_err,
9837c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
9847c478bd9Sstevel@tonic-gate 		    "ibt_alloc_cq failed", tnf_uint, ibt_status, status);
9857c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end,
9867c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n");
9877c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
9887c478bd9Sstevel@tonic-gate 	}
9897c478bd9Sstevel@tonic-gate 	ibt_set_cq_handler(cq_handle, ibmf_statep->ibmf_cq_handler, cip);
9907c478bd9Sstevel@tonic-gate 	cip->ci_alt_cq_handle = cq_handle;
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 	/* set state to CQ INITED */
9937c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
9947c478bd9Sstevel@tonic-gate 	cip->ci_init_state |= IBMF_CI_INIT_CQ_INITED;
9957c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end,
9987c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n");
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
10017c478bd9Sstevel@tonic-gate }
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate /*
10047c478bd9Sstevel@tonic-gate  * ibmf_i_fini_cqs():
10057c478bd9Sstevel@tonic-gate  *	Free up the completion queue
10067c478bd9Sstevel@tonic-gate  */
10077c478bd9Sstevel@tonic-gate static void
ibmf_i_fini_cqs(ibmf_ci_t * cip)10087c478bd9Sstevel@tonic-gate ibmf_i_fini_cqs(ibmf_ci_t *cip)
10097c478bd9Sstevel@tonic-gate {
10107c478bd9Sstevel@tonic-gate 	ibt_status_t	status;
10117c478bd9Sstevel@tonic-gate 	uint_t		ci_init_state;
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_cqs_start,
10147c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_fini_cqs() enter, cip = %p\n",
10157c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, cip);
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
10187c478bd9Sstevel@tonic-gate 	ci_init_state = cip->ci_init_state;
10197c478bd9Sstevel@tonic-gate 	cip->ci_init_state &= ~IBMF_CI_INIT_CQ_INITED;
10207c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	if (ci_init_state & IBMF_CI_INIT_CQ_INITED) {
10237c478bd9Sstevel@tonic-gate 		status = ibt_free_cq(cip->ci_alt_cq_handle);
10247c478bd9Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
10257c478bd9Sstevel@tonic-gate 			IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L3,
10267c478bd9Sstevel@tonic-gate 			    ibmf_i_fini_cqs_err, IBMF_TNF_ERROR, "",
10277c478bd9Sstevel@tonic-gate 			    "%s, status = %d\n", tnf_string, msg,
10287c478bd9Sstevel@tonic-gate 			    "ibt free cqs failed", tnf_uint, status, status);
10297c478bd9Sstevel@tonic-gate 		}
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 		status = ibt_free_cq(cip->ci_cq_handle);
10327c478bd9Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
10337c478bd9Sstevel@tonic-gate 			IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L3,
10347c478bd9Sstevel@tonic-gate 			    ibmf_i_fini_cqs_err, IBMF_TNF_ERROR, "",
10357c478bd9Sstevel@tonic-gate 			    "%s, status = %d\n", tnf_string, msg,
10367c478bd9Sstevel@tonic-gate 			    "ibt free cqs failed", tnf_uint, status, status);
10377c478bd9Sstevel@tonic-gate 		}
10387c478bd9Sstevel@tonic-gate 	}
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_cqs_end,
10417c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_fini_cqs() exit");
10427c478bd9Sstevel@tonic-gate }
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate /*
10457c478bd9Sstevel@tonic-gate  * ibmf_i_init_qplist():
10467c478bd9Sstevel@tonic-gate  *	Set the QP list inited state flag
10477c478bd9Sstevel@tonic-gate  */
10487c478bd9Sstevel@tonic-gate static void
ibmf_i_init_qplist(ibmf_ci_t * ibmf_cip)10497c478bd9Sstevel@tonic-gate ibmf_i_init_qplist(ibmf_ci_t *ibmf_cip)
10507c478bd9Sstevel@tonic-gate {
10517c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qplist_start,
10527c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_qplist() enter, cip = %p\n",
10537c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, ibmf_cip);
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
10567c478bd9Sstevel@tonic-gate 	ASSERT((ibmf_cip->ci_init_state & IBMF_CI_INIT_QP_LIST_INITED) == 0);
10577c478bd9Sstevel@tonic-gate 	ASSERT(ibmf_cip->ci_qp_list == NULL && ibmf_cip->ci_qp_list_tail ==
10587c478bd9Sstevel@tonic-gate 	    NULL);
10597c478bd9Sstevel@tonic-gate 	cv_init(&ibmf_cip->ci_qp_cv, NULL, CV_DRIVER, NULL);
10607c478bd9Sstevel@tonic-gate 	ibmf_cip->ci_init_state |= IBMF_CI_INIT_QP_LIST_INITED;
10617c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qplist_end,
10647c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_qplist() exit\n");
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate /*
10687c478bd9Sstevel@tonic-gate  * ibmf_i_fini_qplist():
10697c478bd9Sstevel@tonic-gate  *	Clean up the QP list
10707c478bd9Sstevel@tonic-gate  */
10717c478bd9Sstevel@tonic-gate static void
ibmf_i_fini_qplist(ibmf_ci_t * ibmf_cip)10727c478bd9Sstevel@tonic-gate ibmf_i_fini_qplist(ibmf_ci_t *ibmf_cip)
10737c478bd9Sstevel@tonic-gate {
10747c478bd9Sstevel@tonic-gate 	ibmf_qp_t *qpp;
10757c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t *altqpp;
10767c478bd9Sstevel@tonic-gate 	ibt_status_t status;
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_qplist_start,
10797c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_fini_qplist() enter, cip = %p\n",
10807c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, ibmf_cip);
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 	if ((ibmf_cip->ci_init_state & IBMF_CI_INIT_QP_LIST_INITED) != 0) {
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 		/* walk through the qp list and free the memory */
10877c478bd9Sstevel@tonic-gate 		qpp = ibmf_cip->ci_qp_list;
10887c478bd9Sstevel@tonic-gate 		while (qpp != NULL) {
10897c478bd9Sstevel@tonic-gate 			/* Remove qpp from the list */
10907c478bd9Sstevel@tonic-gate 			ibmf_cip->ci_qp_list = qpp->iq_next;
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 			ASSERT(qpp->iq_qp_ref == 0);
10937c478bd9Sstevel@tonic-gate 			ASSERT(qpp->iq_flags == IBMF_QP_FLAGS_INVALID);
10947c478bd9Sstevel@tonic-gate 			mutex_exit(&ibmf_cip->ci_mutex);
10957c478bd9Sstevel@tonic-gate 			if (qpp->iq_qp_handle != NULL) {
10967c478bd9Sstevel@tonic-gate 				/* Flush the special QP */
10977c478bd9Sstevel@tonic-gate 				status = ibt_flush_qp(qpp->iq_qp_handle);
10987c478bd9Sstevel@tonic-gate 				if (status != IBT_SUCCESS) {
10997c478bd9Sstevel@tonic-gate 					IBMF_TRACE_2(IBMF_TNF_NODEBUG,
11007c478bd9Sstevel@tonic-gate 					    DPRINT_L1, ibmf_i_fini_qplist_err,
11017c478bd9Sstevel@tonic-gate 					    IBMF_TNF_ERROR, "",
11027c478bd9Sstevel@tonic-gate 					    "%s, status = %d\n", tnf_string,
11037c478bd9Sstevel@tonic-gate 					    msg, "ibt_flush_qp returned error",
11047c478bd9Sstevel@tonic-gate 					    tnf_int, status, status);
11057c478bd9Sstevel@tonic-gate 				}
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 				/* Grab the ci_mutex mutex before waiting */
11087c478bd9Sstevel@tonic-gate 				mutex_enter(&ibmf_cip->ci_mutex);
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 				/* Wait if WQEs for special QPs are alloced */
11117c478bd9Sstevel@tonic-gate 				while (ibmf_cip->ci_wqes_alloced != 0) {
11127c478bd9Sstevel@tonic-gate 					cv_wait(&ibmf_cip->ci_wqes_cv,
11137c478bd9Sstevel@tonic-gate 					    &ibmf_cip->ci_mutex);
11147c478bd9Sstevel@tonic-gate 				}
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 				mutex_exit(&ibmf_cip->ci_mutex);
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 				/* Free the special QP */
11197c478bd9Sstevel@tonic-gate 				status = ibt_free_qp(qpp->iq_qp_handle);
11207c478bd9Sstevel@tonic-gate 				if (status != IBT_SUCCESS) {
11217c478bd9Sstevel@tonic-gate 					IBMF_TRACE_2(IBMF_TNF_NODEBUG,
11227c478bd9Sstevel@tonic-gate 					    DPRINT_L1, ibmf_i_fini_qplist_err,
11237c478bd9Sstevel@tonic-gate 					    IBMF_TNF_ERROR, "",
11247c478bd9Sstevel@tonic-gate 					    "%s, status = %d\n", tnf_string,
11257c478bd9Sstevel@tonic-gate 					    msg, "ibt_free_qp returned error",
11267c478bd9Sstevel@tonic-gate 					    tnf_int, status, status);
11277c478bd9Sstevel@tonic-gate 				}
11287c478bd9Sstevel@tonic-gate 			}
11297c478bd9Sstevel@tonic-gate 			mutex_destroy(&qpp->iq_mutex);
11307c478bd9Sstevel@tonic-gate 			kmem_free((void *)qpp, sizeof (ibmf_qp_t));
11317c478bd9Sstevel@tonic-gate 
11327c478bd9Sstevel@tonic-gate 			/* Grab the mutex again before accessing the QP list */
11337c478bd9Sstevel@tonic-gate 			mutex_enter(&ibmf_cip->ci_mutex);
11347c478bd9Sstevel@tonic-gate 			qpp = ibmf_cip->ci_qp_list;
11357c478bd9Sstevel@tonic-gate 		}
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 		cv_destroy(&ibmf_cip->ci_qp_cv);
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 		ibmf_cip->ci_qp_list = ibmf_cip->ci_qp_list_tail = NULL;
11407c478bd9Sstevel@tonic-gate 		ibmf_cip->ci_init_state &=  ~IBMF_CI_INIT_QP_LIST_INITED;
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 		altqpp = ibmf_cip->ci_alt_qp_list;
11437c478bd9Sstevel@tonic-gate 		while (altqpp != NULL) {
11447c478bd9Sstevel@tonic-gate 			/* Remove altqpp from the list */
11457c478bd9Sstevel@tonic-gate 			ibmf_cip->ci_alt_qp_list = altqpp->isq_next;
11467c478bd9Sstevel@tonic-gate 			mutex_exit(&ibmf_cip->ci_mutex);
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate 			if (altqpp->isq_qp_handle != NULL) {
11497c478bd9Sstevel@tonic-gate 				/* Flush the special QP */
11507c478bd9Sstevel@tonic-gate 				status = ibt_flush_qp(altqpp->isq_qp_handle);
11517c478bd9Sstevel@tonic-gate 				if (status != IBT_SUCCESS) {
11527c478bd9Sstevel@tonic-gate 					IBMF_TRACE_2(IBMF_TNF_NODEBUG,
11537c478bd9Sstevel@tonic-gate 					    DPRINT_L1, ibmf_i_fini_qplist_err,
11547c478bd9Sstevel@tonic-gate 					    IBMF_TNF_ERROR, "",
11557c478bd9Sstevel@tonic-gate 					    "%s, status = %d\n", tnf_string,
11567c478bd9Sstevel@tonic-gate 					    msg, "ibt_flush_qp returned error",
11577c478bd9Sstevel@tonic-gate 					    tnf_int, status, status);
11587c478bd9Sstevel@tonic-gate 				}
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 				/* Free the special QP */
11617c478bd9Sstevel@tonic-gate 				status = ibt_free_qp(altqpp->isq_qp_handle);
11627c478bd9Sstevel@tonic-gate 				if (status != IBT_SUCCESS) {
11637c478bd9Sstevel@tonic-gate 					IBMF_TRACE_2(IBMF_TNF_NODEBUG,
11647c478bd9Sstevel@tonic-gate 					    DPRINT_L1, ibmf_i_fini_qplist_err,
11657c478bd9Sstevel@tonic-gate 					    IBMF_TNF_ERROR, "",
11667c478bd9Sstevel@tonic-gate 					    "%s, status = %d\n", tnf_string,
11677c478bd9Sstevel@tonic-gate 					    msg, "ibt_free_qp returned error",
11687c478bd9Sstevel@tonic-gate 					    tnf_int, status, status);
11697c478bd9Sstevel@tonic-gate 				}
11707c478bd9Sstevel@tonic-gate 			}
11717c478bd9Sstevel@tonic-gate 			mutex_destroy(&altqpp->isq_mutex);
11727c478bd9Sstevel@tonic-gate 			kmem_free((void *)altqpp, sizeof (ibmf_alt_qp_t));
11737c478bd9Sstevel@tonic-gate 
11747c478bd9Sstevel@tonic-gate 			/* Grab the mutex again before accessing the QP list */
11757c478bd9Sstevel@tonic-gate 			mutex_enter(&ibmf_cip->ci_mutex);
11767c478bd9Sstevel@tonic-gate 			altqpp = ibmf_cip->ci_alt_qp_list;
11777c478bd9Sstevel@tonic-gate 		}
11787c478bd9Sstevel@tonic-gate 	}
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_qplist_end,
11837c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_fini_qplist() exit\n");
11847c478bd9Sstevel@tonic-gate }
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate /*
11877c478bd9Sstevel@tonic-gate  * ibmf_i_alloc_client():
11887c478bd9Sstevel@tonic-gate  *	Allocate and initialize the client structure.
11897c478bd9Sstevel@tonic-gate  */
11907c478bd9Sstevel@tonic-gate int
ibmf_i_alloc_client(ibmf_register_info_t * client_infop,uint_t flags,ibmf_client_t ** clientpp)11917c478bd9Sstevel@tonic-gate ibmf_i_alloc_client(ibmf_register_info_t *client_infop, uint_t flags,
11927c478bd9Sstevel@tonic-gate     ibmf_client_t **clientpp)
11937c478bd9Sstevel@tonic-gate {
11947c478bd9Sstevel@tonic-gate 	ibmf_client_t		*ibmf_clientp;
11957c478bd9Sstevel@tonic-gate 	char			buf[128];
11967c478bd9Sstevel@tonic-gate 	ibmf_kstat_t		*ksp;
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_client_start,
11997c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_alloc_client() enter, "
12007c478bd9Sstevel@tonic-gate 	    "client_infop = %p\n", tnf_opaque, client_infop, client_infop);
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibmf_clientp))
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	/* allocate memory for ibmf_client and initialize it */
12057c478bd9Sstevel@tonic-gate 	ibmf_clientp = kmem_zalloc(sizeof (ibmf_client_t), KM_SLEEP);
12067c478bd9Sstevel@tonic-gate 	mutex_init(&ibmf_clientp->ic_mutex, NULL, MUTEX_DRIVER, NULL);
12077c478bd9Sstevel@tonic-gate 	mutex_init(&ibmf_clientp->ic_msg_mutex, NULL, MUTEX_DRIVER, NULL);
12087c478bd9Sstevel@tonic-gate 	mutex_init(&ibmf_clientp->ic_kstat_mutex, NULL, MUTEX_DRIVER, NULL);
12097c478bd9Sstevel@tonic-gate 	cv_init(&ibmf_clientp->ic_recv_cb_teardown_cv, NULL, CV_DRIVER, NULL);
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "s%08X_0x%08X",
12127c478bd9Sstevel@tonic-gate 	    (uint32_t)client_infop->ir_ci_guid, client_infop->ir_client_class);
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate 	/* create a taskq to handle send completions based on reg flags */
12157c478bd9Sstevel@tonic-gate 	if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
12167c478bd9Sstevel@tonic-gate 		if (flags & IBMF_REG_FLAG_SINGLE_OFFLOAD)
12177c478bd9Sstevel@tonic-gate 			ibmf_clientp->ic_send_taskq = taskq_create(buf,
12187c478bd9Sstevel@tonic-gate 			    IBMF_TASKQ_1THREAD, MINCLSYSPRI, 1,
12197c478bd9Sstevel@tonic-gate 			    ibmf_taskq_max_tasks, TASKQ_PREPOPULATE);
12207c478bd9Sstevel@tonic-gate 		else
12217c478bd9Sstevel@tonic-gate 			ibmf_clientp->ic_send_taskq = taskq_create(buf,
12227c478bd9Sstevel@tonic-gate 			    IBMF_TASKQ_NTHREADS, MINCLSYSPRI, 1,
12237c478bd9Sstevel@tonic-gate 			    ibmf_taskq_max_tasks,
12247c478bd9Sstevel@tonic-gate 			    TASKQ_DYNAMIC | TASKQ_PREPOPULATE);
12257c478bd9Sstevel@tonic-gate 		if (ibmf_clientp->ic_send_taskq == NULL) {
12267c478bd9Sstevel@tonic-gate 			cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv);
12277c478bd9Sstevel@tonic-gate 			mutex_destroy(&ibmf_clientp->ic_mutex);
12287c478bd9Sstevel@tonic-gate 			mutex_destroy(&ibmf_clientp->ic_msg_mutex);
12297c478bd9Sstevel@tonic-gate 			mutex_destroy(&ibmf_clientp->ic_kstat_mutex);
12307c478bd9Sstevel@tonic-gate 			kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t));
12317c478bd9Sstevel@tonic-gate 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
12327c478bd9Sstevel@tonic-gate 			    ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n",
12337c478bd9Sstevel@tonic-gate 			    tnf_string, msg, buf);
12347c478bd9Sstevel@tonic-gate 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
12357c478bd9Sstevel@tonic-gate 			    ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "",
12367c478bd9Sstevel@tonic-gate 			    "ibmf_i_alloc_client() exit\n");
12377c478bd9Sstevel@tonic-gate 			return (IBMF_NO_RESOURCES);
12387c478bd9Sstevel@tonic-gate 		}
12397c478bd9Sstevel@tonic-gate 	}
12407c478bd9Sstevel@tonic-gate 	ibmf_clientp->ic_init_state_class |= IBMF_CI_INIT_SEND_TASKQ_DONE;
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "r%08X_0x%08X",
12437c478bd9Sstevel@tonic-gate 	    (uint32_t)client_infop->ir_ci_guid, client_infop->ir_client_class);
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 	/* create a taskq to handle receive completions on reg flags */
12467c478bd9Sstevel@tonic-gate 	if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
12477c478bd9Sstevel@tonic-gate 		if (flags & IBMF_REG_FLAG_SINGLE_OFFLOAD)
12487c478bd9Sstevel@tonic-gate 			ibmf_clientp->ic_recv_taskq = taskq_create(buf,
12497c478bd9Sstevel@tonic-gate 			    IBMF_TASKQ_1THREAD, MINCLSYSPRI, 1,
12507c478bd9Sstevel@tonic-gate 			    ibmf_taskq_max_tasks, TASKQ_PREPOPULATE);
12517c478bd9Sstevel@tonic-gate 		else
12527c478bd9Sstevel@tonic-gate 			ibmf_clientp->ic_recv_taskq = taskq_create(buf,
12537c478bd9Sstevel@tonic-gate 			    IBMF_TASKQ_NTHREADS, MINCLSYSPRI, 1,
12547c478bd9Sstevel@tonic-gate 			    ibmf_taskq_max_tasks,
12557c478bd9Sstevel@tonic-gate 			    TASKQ_DYNAMIC | TASKQ_PREPOPULATE);
12567c478bd9Sstevel@tonic-gate 		if (ibmf_clientp->ic_recv_taskq == NULL) {
12577c478bd9Sstevel@tonic-gate 			cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv);
12587c478bd9Sstevel@tonic-gate 			mutex_destroy(&ibmf_clientp->ic_mutex);
12597c478bd9Sstevel@tonic-gate 			mutex_destroy(&ibmf_clientp->ic_msg_mutex);
12607c478bd9Sstevel@tonic-gate 			mutex_destroy(&ibmf_clientp->ic_kstat_mutex);
12617c478bd9Sstevel@tonic-gate 			taskq_destroy(ibmf_clientp->ic_send_taskq);
12627c478bd9Sstevel@tonic-gate 			kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t));
12637c478bd9Sstevel@tonic-gate 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
12647c478bd9Sstevel@tonic-gate 			    ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n",
12657c478bd9Sstevel@tonic-gate 			    tnf_string, msg, buf);
12667c478bd9Sstevel@tonic-gate 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
12677c478bd9Sstevel@tonic-gate 			    ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "",
12687c478bd9Sstevel@tonic-gate 			    "ibmf_i_alloc_client() exit\n");
12697c478bd9Sstevel@tonic-gate 			return (IBMF_NO_RESOURCES);
12707c478bd9Sstevel@tonic-gate 		}
12717c478bd9Sstevel@tonic-gate 	}
12727c478bd9Sstevel@tonic-gate 	ibmf_clientp->ic_init_state_class |= IBMF_CI_INIT_RECV_TASKQ_DONE;
12737c478bd9Sstevel@tonic-gate 	ibmf_clientp->ic_client_info.ci_guid = client_infop->ir_ci_guid;
12747c478bd9Sstevel@tonic-gate 	ibmf_clientp->ic_client_info.port_num = client_infop->ir_port_num;
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 	/* Get the base LID */
12777c478bd9Sstevel@tonic-gate 	(void) ibt_get_port_state_byguid(ibmf_clientp->ic_client_info.ci_guid,
12787c478bd9Sstevel@tonic-gate 	    ibmf_clientp->ic_client_info.port_num, NULL,
12797c478bd9Sstevel@tonic-gate 	    &ibmf_clientp->ic_base_lid);
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate 	ibmf_clientp->ic_client_info.client_class =
12827c478bd9Sstevel@tonic-gate 	    client_infop->ir_client_class;
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	/* set up the per client ibmf kstats */
12857c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "ibmf_%016" PRIx64 "_%d_%X_stat",
12867c478bd9Sstevel@tonic-gate 	    client_infop->ir_ci_guid, client_infop->ir_port_num,
12877c478bd9Sstevel@tonic-gate 	    client_infop->ir_client_class);
12887c478bd9Sstevel@tonic-gate 	if ((ibmf_clientp->ic_kstatp = kstat_create("ibmf", 0, buf, "misc",
12897c478bd9Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, sizeof (ibmf_kstat_t) / sizeof (kstat_named_t),
12907c478bd9Sstevel@tonic-gate 	    KSTAT_FLAG_WRITABLE)) == NULL) {
12917c478bd9Sstevel@tonic-gate 		cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv);
12927c478bd9Sstevel@tonic-gate 		mutex_destroy(&ibmf_clientp->ic_mutex);
12937c478bd9Sstevel@tonic-gate 		mutex_destroy(&ibmf_clientp->ic_msg_mutex);
12947c478bd9Sstevel@tonic-gate 		mutex_destroy(&ibmf_clientp->ic_kstat_mutex);
12957c478bd9Sstevel@tonic-gate 		if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
12967c478bd9Sstevel@tonic-gate 			taskq_destroy(ibmf_clientp->ic_send_taskq);
12977c478bd9Sstevel@tonic-gate 			taskq_destroy(ibmf_clientp->ic_recv_taskq);
12987c478bd9Sstevel@tonic-gate 		}
12997c478bd9Sstevel@tonic-gate 		kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t));
13007c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
13017c478bd9Sstevel@tonic-gate 		    ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n",
13027c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "kstat creation failed");
13037c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
13047c478bd9Sstevel@tonic-gate 		    ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "",
13057c478bd9Sstevel@tonic-gate 		    "ibmf_i_alloc_client() exit\n");
13067c478bd9Sstevel@tonic-gate 		return (IBMF_NO_RESOURCES);
13077c478bd9Sstevel@tonic-gate 	}
13087c478bd9Sstevel@tonic-gate 	ksp = (ibmf_kstat_t *)ibmf_clientp->ic_kstatp->ks_data;
13097c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->msgs_alloced, "messages_allocated",
13107c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13117c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->msgs_active, "messages_active",
13127c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13137c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->msgs_sent, "messages_sent", KSTAT_DATA_UINT32);
13147c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->msgs_received, "messages_received",
13157c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13167c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->sends_active, "sends_active", KSTAT_DATA_UINT32);
13177c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->recvs_active, "receives_active",
13187c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13197c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->ud_dests_alloced, "ud_dests_allocated",
13207c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13217c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->alt_qps_alloced, "alt_qps_allocated",
13227c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13237c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->send_cb_active, "send_callbacks_active",
13247c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13257c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->recv_cb_active, "receive_callbacks_active",
13267c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13277c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->recv_bufs_alloced, "receive_bufs_allocated",
13287c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13297c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->msg_allocs_failed, "msg_allocs_failed",
13307c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13317c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->uddest_allocs_failed, "uddest_allocs_failed",
13327c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13337c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->alt_qp_allocs_failed, "alt_qp_allocs_failed",
13347c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13357c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->send_pkt_failed, "send_pkt_failed",
13367c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13377c478bd9Sstevel@tonic-gate 	kstat_named_init(&ksp->rmpp_errors, "rmpp_errors",
13387c478bd9Sstevel@tonic-gate 	    KSTAT_DATA_UINT32);
13397c478bd9Sstevel@tonic-gate 
13407c478bd9Sstevel@tonic-gate 	kstat_install(ibmf_clientp->ic_kstatp);
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 	*clientpp = ibmf_clientp;
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibmf_clientp))
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_client_end,
13477c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_alloc_client() exit\n");
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
13507c478bd9Sstevel@tonic-gate }
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate /*
13537c478bd9Sstevel@tonic-gate  * ibmf_i_free_client():
13547c478bd9Sstevel@tonic-gate  *	Free up the client structure and release resources
13557c478bd9Sstevel@tonic-gate  */
13567c478bd9Sstevel@tonic-gate void
ibmf_i_free_client(ibmf_client_t * clientp)13577c478bd9Sstevel@tonic-gate ibmf_i_free_client(ibmf_client_t *clientp)
13587c478bd9Sstevel@tonic-gate {
13597c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_client_start,
13607c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_free_client() enter, clientp = %p\n",
13617c478bd9Sstevel@tonic-gate 	    tnf_opaque, clientp, clientp);
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 	/* delete the general ibmf kstats */
13647c478bd9Sstevel@tonic-gate 	if (clientp->ic_kstatp != NULL) {
13657c478bd9Sstevel@tonic-gate 		kstat_delete(clientp->ic_kstatp);
13667c478bd9Sstevel@tonic-gate 		clientp->ic_kstatp = NULL;
13677c478bd9Sstevel@tonic-gate 	}
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 	/* release references and destroy the resources */
13707c478bd9Sstevel@tonic-gate 	if (clientp->ic_init_state_class & IBMF_CI_INIT_SEND_TASKQ_DONE) {
13717c478bd9Sstevel@tonic-gate 		if ((clientp->ic_reg_flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
13727c478bd9Sstevel@tonic-gate 			taskq_destroy(clientp->ic_send_taskq);
13737c478bd9Sstevel@tonic-gate 		}
13747c478bd9Sstevel@tonic-gate 		clientp->ic_init_state_class &= ~IBMF_CI_INIT_SEND_TASKQ_DONE;
13757c478bd9Sstevel@tonic-gate 	}
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate 	if (clientp->ic_init_state_class & IBMF_CI_INIT_RECV_TASKQ_DONE) {
13787c478bd9Sstevel@tonic-gate 		if ((clientp->ic_reg_flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
13797c478bd9Sstevel@tonic-gate 			taskq_destroy(clientp->ic_recv_taskq);
13807c478bd9Sstevel@tonic-gate 		}
13817c478bd9Sstevel@tonic-gate 		clientp->ic_init_state_class &= ~IBMF_CI_INIT_RECV_TASKQ_DONE;
13827c478bd9Sstevel@tonic-gate 	}
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate 	mutex_destroy(&clientp->ic_mutex);
13857c478bd9Sstevel@tonic-gate 	mutex_destroy(&clientp->ic_msg_mutex);
13867c478bd9Sstevel@tonic-gate 	mutex_destroy(&clientp->ic_kstat_mutex);
13877c478bd9Sstevel@tonic-gate 	cv_destroy(&clientp->ic_recv_cb_teardown_cv);
13887c478bd9Sstevel@tonic-gate 	kmem_free((void *)clientp, sizeof (ibmf_client_t));
13897c478bd9Sstevel@tonic-gate 
13907c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_client_end,
13917c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_free_client() exit\n");
13927c478bd9Sstevel@tonic-gate }
13937c478bd9Sstevel@tonic-gate 
13947c478bd9Sstevel@tonic-gate /*
13957c478bd9Sstevel@tonic-gate  * ibmf_i_validate_classes_and_port():
13967c478bd9Sstevel@tonic-gate  *	Validate the class type and get the client structure
13977c478bd9Sstevel@tonic-gate  */
13987c478bd9Sstevel@tonic-gate int
ibmf_i_validate_classes_and_port(ibmf_ci_t * ibmf_cip,ibmf_register_info_t * client_infop)13997c478bd9Sstevel@tonic-gate ibmf_i_validate_classes_and_port(ibmf_ci_t *ibmf_cip,
14007c478bd9Sstevel@tonic-gate     ibmf_register_info_t *client_infop)
14017c478bd9Sstevel@tonic-gate {
14027c478bd9Sstevel@tonic-gate 	ibmf_client_t		*ibmf_clientp;
14037c478bd9Sstevel@tonic-gate 	int			status;
14047c478bd9Sstevel@tonic-gate 
14057c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
14067c478bd9Sstevel@tonic-gate 	    ibmf_i_validate_classes_and_port_start, IBMF_TNF_TRACE, "",
14077c478bd9Sstevel@tonic-gate 	    "ibmf_i_validate_classes_and_port() enter, cip = %p, "
14087c478bd9Sstevel@tonic-gate 	    "clientp = %p\n", tnf_opaque, cip, ibmf_cip,
14097c478bd9Sstevel@tonic-gate 	    tnf_opaque, client_infop, client_infop);
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 	/*
14127c478bd9Sstevel@tonic-gate 	 * the Solaris implementation of IBMF does not support
14137c478bd9Sstevel@tonic-gate 	 * the UNIVERSAL_CLASS
14147c478bd9Sstevel@tonic-gate 	 */
14157c478bd9Sstevel@tonic-gate 	if (client_infop->ir_client_class == UNIVERSAL_CLASS) {
14167c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
14177c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_classes_and_port_err, IBMF_TNF_ERROR, "",
14187c478bd9Sstevel@tonic-gate 		    "%s\n", tnf_string, msg,
14197c478bd9Sstevel@tonic-gate 		    "UNIVERSAL class is not supported");
14207c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
14217c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_classes_and_port_end, IBMF_TNF_TRACE, "",
14227c478bd9Sstevel@tonic-gate 		    "ibmf_i_validate_classes_and_port() exit\n");
14237c478bd9Sstevel@tonic-gate 		return (IBMF_NOT_SUPPORTED);
14247c478bd9Sstevel@tonic-gate 	}
14257c478bd9Sstevel@tonic-gate 
14267c478bd9Sstevel@tonic-gate 	/*
14277c478bd9Sstevel@tonic-gate 	 * Check if the client context already exists on the list
14287c478bd9Sstevel@tonic-gate 	 * maintained in the CI context. If it is, then the client class
14297c478bd9Sstevel@tonic-gate 	 * has already been registered for.
14307c478bd9Sstevel@tonic-gate 	 */
14317c478bd9Sstevel@tonic-gate 	status = ibmf_i_lookup_client_by_info(ibmf_cip, client_infop,
14327c478bd9Sstevel@tonic-gate 	    &ibmf_clientp);
14337c478bd9Sstevel@tonic-gate 	if (status != IBMF_SUCCESS) {
14347c478bd9Sstevel@tonic-gate 		/* client class has not been previously registered for */
14357c478bd9Sstevel@tonic-gate 		status = IBMF_SUCCESS;
14367c478bd9Sstevel@tonic-gate 	} else {
14377c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
14387c478bd9Sstevel@tonic-gate 		    ibmf_i_validate_classes_and_port_err, IBMF_TNF_ERROR, "",
14397c478bd9Sstevel@tonic-gate 		    "client already registered, class = 0x%X\n",
14407c478bd9Sstevel@tonic-gate 		    tnf_uint, class, client_infop->ir_client_class);
14417c478bd9Sstevel@tonic-gate 		status = IBMF_PORT_IN_USE;
14427c478bd9Sstevel@tonic-gate 	}
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
14457c478bd9Sstevel@tonic-gate 	    ibmf_i_validate_classes_and_port_end, IBMF_TNF_TRACE, "",
14467c478bd9Sstevel@tonic-gate 	    "ibmf_i_validate_classes_and_port() exit\n");
14477c478bd9Sstevel@tonic-gate 	return (status);
14487c478bd9Sstevel@tonic-gate }
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate /*
14517c478bd9Sstevel@tonic-gate  * ibmf_i_lookup_client_by_info():
14527c478bd9Sstevel@tonic-gate  *	Get the client structure from the list
14537c478bd9Sstevel@tonic-gate  */
14547c478bd9Sstevel@tonic-gate static int
ibmf_i_lookup_client_by_info(ibmf_ci_t * ibmf_cip,ibmf_register_info_t * ir_client,ibmf_client_t ** clientpp)14557c478bd9Sstevel@tonic-gate ibmf_i_lookup_client_by_info(ibmf_ci_t *ibmf_cip,
14567c478bd9Sstevel@tonic-gate     ibmf_register_info_t *ir_client, ibmf_client_t **clientpp)
14577c478bd9Sstevel@tonic-gate {
14587c478bd9Sstevel@tonic-gate 	ibmf_client_t *clientp;
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
14617c478bd9Sstevel@tonic-gate 	    ibmf_i_lookup_client_by_info_start, IBMF_TNF_TRACE, "",
14627c478bd9Sstevel@tonic-gate 	    "ibmf_i_lookup_client_by_info() enter, cip = %p, clientinfo = %p\n",
14637c478bd9Sstevel@tonic-gate 	    tnf_opaque, cip, ibmf_cip, tnf_opaque, clientinfo, ir_client);
14647c478bd9Sstevel@tonic-gate 
14657c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex));
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate 	/*
14687c478bd9Sstevel@tonic-gate 	 * walk the CI's client list searching for one with the specified class
14697c478bd9Sstevel@tonic-gate 	 */
14707c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_clients_mutex);
14717c478bd9Sstevel@tonic-gate 	clientp = ibmf_cip->ci_clients;
14727c478bd9Sstevel@tonic-gate 	while (clientp != NULL) {
14737c478bd9Sstevel@tonic-gate 		ibmf_client_info_t *tmp = &clientp->ic_client_info;
14747c478bd9Sstevel@tonic-gate 		if (tmp->client_class == ir_client->ir_client_class &&
14757c478bd9Sstevel@tonic-gate 		    ir_client->ir_client_class != UNIVERSAL_CLASS &&
14767c478bd9Sstevel@tonic-gate 		    tmp->ci_guid == ir_client->ir_ci_guid &&
14777c478bd9Sstevel@tonic-gate 		    tmp->port_num == ir_client->ir_port_num) {
14787c478bd9Sstevel@tonic-gate 			/* found our match */
14797c478bd9Sstevel@tonic-gate 			break;
14807c478bd9Sstevel@tonic-gate 		}
14817c478bd9Sstevel@tonic-gate 		clientp = clientp->ic_next;
14827c478bd9Sstevel@tonic-gate 	}
14837c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_clients_mutex);
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	if (clientp != NULL) {
14867c478bd9Sstevel@tonic-gate 		*clientpp = clientp;
14877c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
14887c478bd9Sstevel@tonic-gate 		    ibmf_i_lookup_client_by_info_end, IBMF_TNF_TRACE, "",
14897c478bd9Sstevel@tonic-gate 		    "ibmf_i_lookup_client_by_info(): clientp = %p\n",
14907c478bd9Sstevel@tonic-gate 		    tnf_opaque, clientp, clientp);
14917c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
14927c478bd9Sstevel@tonic-gate 	} else {
14937c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
14947c478bd9Sstevel@tonic-gate 		    ibmf_i_lookup_client_by_info_end, IBMF_TNF_TRACE, "",
14957c478bd9Sstevel@tonic-gate 		    "ibmf_i_lookup_client_by_info() exit\n");
14967c478bd9Sstevel@tonic-gate 		return (IBMF_FAILURE);
14977c478bd9Sstevel@tonic-gate 	}
14987c478bd9Sstevel@tonic-gate }
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate /*
15017c478bd9Sstevel@tonic-gate  * ibmf_i_add_client():
15027c478bd9Sstevel@tonic-gate  *	Add a new client to the client list
15037c478bd9Sstevel@tonic-gate  */
15047c478bd9Sstevel@tonic-gate void
ibmf_i_add_client(ibmf_ci_t * ibmf_cip,ibmf_client_t * ibmf_clientp)15057c478bd9Sstevel@tonic-gate ibmf_i_add_client(ibmf_ci_t *ibmf_cip, ibmf_client_t *ibmf_clientp)
15067c478bd9Sstevel@tonic-gate {
15077c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_add_start,
15087c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "",
15097c478bd9Sstevel@tonic-gate 	    "ibmf_i_add_client() enter, cip = %p, clientp = %p\n",
15107c478bd9Sstevel@tonic-gate 	    tnf_opaque, ibmf_ci, ibmf_cip, tnf_opaque, client, ibmf_clientp);
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex));
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_clients_mutex);
15157c478bd9Sstevel@tonic-gate 	ibmf_clientp->ic_next = NULL;
15167c478bd9Sstevel@tonic-gate 	ibmf_clientp->ic_prev = ibmf_cip->ci_clients_last;
15177c478bd9Sstevel@tonic-gate 	if (ibmf_cip->ci_clients == NULL) {
15187c478bd9Sstevel@tonic-gate 		ibmf_cip->ci_clients = ibmf_clientp;
15197c478bd9Sstevel@tonic-gate 	}
15207c478bd9Sstevel@tonic-gate 	if (ibmf_cip->ci_clients_last) {
15217c478bd9Sstevel@tonic-gate 		ibmf_cip->ci_clients_last->ic_next = ibmf_clientp;
15227c478bd9Sstevel@tonic-gate 	}
15237c478bd9Sstevel@tonic-gate 	ibmf_cip->ci_clients_last = ibmf_clientp;
15247c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_clients_mutex);
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_add_end,
15277c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_add_client() exit\n");
15287c478bd9Sstevel@tonic-gate }
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate /*
15317c478bd9Sstevel@tonic-gate  * ibmf_i_delete_client():
15327c478bd9Sstevel@tonic-gate  *	Delete a client from the client list
15337c478bd9Sstevel@tonic-gate  */
15347c478bd9Sstevel@tonic-gate void
ibmf_i_delete_client(ibmf_ci_t * ibmf_cip,ibmf_client_t * ibmf_clientp)15357c478bd9Sstevel@tonic-gate ibmf_i_delete_client(ibmf_ci_t *ibmf_cip, ibmf_client_t *ibmf_clientp)
15367c478bd9Sstevel@tonic-gate {
15377c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_delete_client_start,
15387c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_delete_client() enter, "
15397c478bd9Sstevel@tonic-gate 	    "ibmf_i_delete_client() enter, cip = %p, clientp = %p\n",
15407c478bd9Sstevel@tonic-gate 	    tnf_opaque, ibmf_ci, ibmf_cip, tnf_opaque, client, ibmf_clientp);
15417c478bd9Sstevel@tonic-gate 
15427c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex));
15437c478bd9Sstevel@tonic-gate 
15447c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_clients_mutex);
15457c478bd9Sstevel@tonic-gate 	if (ibmf_clientp->ic_next)
15467c478bd9Sstevel@tonic-gate 		ibmf_clientp->ic_next->ic_prev = ibmf_clientp->ic_prev;
15477c478bd9Sstevel@tonic-gate 
15487c478bd9Sstevel@tonic-gate 	if (ibmf_clientp->ic_prev)
15497c478bd9Sstevel@tonic-gate 		ibmf_clientp->ic_prev->ic_next = ibmf_clientp->ic_next;
15507c478bd9Sstevel@tonic-gate 
15517c478bd9Sstevel@tonic-gate 	if (ibmf_cip->ci_clients == ibmf_clientp) {
15527c478bd9Sstevel@tonic-gate 		ibmf_cip->ci_clients = ibmf_clientp->ic_next;
15537c478bd9Sstevel@tonic-gate 	}
15547c478bd9Sstevel@tonic-gate 	if (ibmf_cip->ci_clients_last == ibmf_clientp) {
15557c478bd9Sstevel@tonic-gate 		ibmf_cip->ci_clients_last = ibmf_clientp->ic_prev;
15567c478bd9Sstevel@tonic-gate 	}
15577c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_clients_mutex);
15587c478bd9Sstevel@tonic-gate 
15597c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_delete_client_end,
15607c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_delete_client() exit\n");
15617c478bd9Sstevel@tonic-gate }
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate /*
15647c478bd9Sstevel@tonic-gate  * ibmf_i_get_qp():
15657c478bd9Sstevel@tonic-gate  *	Get the QP structure based on the client class
15667c478bd9Sstevel@tonic-gate  */
15677c478bd9Sstevel@tonic-gate int
ibmf_i_get_qp(ibmf_ci_t * ibmf_cip,uint_t port_num,ibmf_client_type_t class,ibmf_qp_t ** qppp)15687c478bd9Sstevel@tonic-gate ibmf_i_get_qp(ibmf_ci_t *ibmf_cip, uint_t port_num, ibmf_client_type_t class,
15697c478bd9Sstevel@tonic-gate     ibmf_qp_t **qppp)
15707c478bd9Sstevel@tonic-gate {
15717c478bd9Sstevel@tonic-gate 	ibmf_qp_t		*qpp;
15727c478bd9Sstevel@tonic-gate 	int			qp_num, status = IBMF_SUCCESS;
15737c478bd9Sstevel@tonic-gate 
15747c478bd9Sstevel@tonic-gate 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_start,
15757c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_get_qp() enter, cip = %p, "
15767c478bd9Sstevel@tonic-gate 	    "port = %d, class = %x\n", tnf_opaque, ibmf_ci, ibmf_cip,
15777c478bd9Sstevel@tonic-gate 	    tnf_int, port, port_num, tnf_opaque, class, class);
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_mutex));
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
15827c478bd9Sstevel@tonic-gate 
15837c478bd9Sstevel@tonic-gate 	/*
15847c478bd9Sstevel@tonic-gate 	 * walk through the list of qps on this ci, looking for one that
15857c478bd9Sstevel@tonic-gate 	 * corresponds to the type and class the caller is interested in.
15867c478bd9Sstevel@tonic-gate 	 * If it is not there, we need allocate it from the transport. Since
15877c478bd9Sstevel@tonic-gate 	 * qp0 & qp1 can only be allocated once, we maintain a reference count
15887c478bd9Sstevel@tonic-gate 	 * and call the transport for allocation iff the ref count is 0.
15897c478bd9Sstevel@tonic-gate 	 */
15907c478bd9Sstevel@tonic-gate 	qp_num = (class == SUBN_AGENT || class == SUBN_MANAGER) ? 0 : 1;
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 	qpp = ibmf_cip->ci_qp_list;
15937c478bd9Sstevel@tonic-gate 	while (qpp != NULL) {
15947c478bd9Sstevel@tonic-gate 		if (port_num == qpp->iq_port_num && qp_num == qpp->iq_qp_num)
15957c478bd9Sstevel@tonic-gate 			break;
15967c478bd9Sstevel@tonic-gate 		qpp = qpp->iq_next;
15977c478bd9Sstevel@tonic-gate 	}
15987c478bd9Sstevel@tonic-gate 
15997c478bd9Sstevel@tonic-gate 	if (qpp == NULL) {
16007c478bd9Sstevel@tonic-gate 		/*
16017c478bd9Sstevel@tonic-gate 		 * allocate qp and add it the qp list; recheck to
16027c478bd9Sstevel@tonic-gate 		 * catch races
16037c478bd9Sstevel@tonic-gate 		 */
16047c478bd9Sstevel@tonic-gate 		ibmf_qp_t *tqpp;
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 		mutex_exit(&ibmf_cip->ci_mutex);
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate 		tqpp = (ibmf_qp_t *)kmem_zalloc(sizeof (ibmf_qp_t), KM_SLEEP);
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate 		/* check the list under lock */
16117c478bd9Sstevel@tonic-gate 		mutex_enter(&ibmf_cip->ci_mutex);
16127c478bd9Sstevel@tonic-gate 
16137c478bd9Sstevel@tonic-gate 		qpp = ibmf_cip->ci_qp_list;
16147c478bd9Sstevel@tonic-gate 		while (qpp != NULL) {
16157c478bd9Sstevel@tonic-gate 			if (port_num == qpp->iq_port_num && qp_num ==
16167c478bd9Sstevel@tonic-gate 			    qpp->iq_qp_num)
16177c478bd9Sstevel@tonic-gate 				break;
16187c478bd9Sstevel@tonic-gate 			qpp = qpp->iq_next;
16197c478bd9Sstevel@tonic-gate 		}
16207c478bd9Sstevel@tonic-gate 
16217c478bd9Sstevel@tonic-gate 		if (qpp != NULL) {
16227c478bd9Sstevel@tonic-gate 			/* some one raced past us and added to the list */
16237c478bd9Sstevel@tonic-gate 			kmem_free((void *)tqpp, sizeof (ibmf_qp_t));
16247c478bd9Sstevel@tonic-gate 		} else {
16257c478bd9Sstevel@tonic-gate 			/* add this to the qp list */
16267c478bd9Sstevel@tonic-gate 			qpp = tqpp;
16277c478bd9Sstevel@tonic-gate 			_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qpp))
16287c478bd9Sstevel@tonic-gate 			qpp->iq_next = NULL;
16297c478bd9Sstevel@tonic-gate 			if (ibmf_cip->ci_qp_list == NULL)
16307c478bd9Sstevel@tonic-gate 				ibmf_cip->ci_qp_list = qpp;
16317c478bd9Sstevel@tonic-gate 			if (ibmf_cip->ci_qp_list_tail != NULL)
16327c478bd9Sstevel@tonic-gate 				ibmf_cip->ci_qp_list_tail->iq_next = qpp;
16337c478bd9Sstevel@tonic-gate 			ibmf_cip->ci_qp_list_tail = qpp;
16347c478bd9Sstevel@tonic-gate 			qpp->iq_port_num = port_num;
16357c478bd9Sstevel@tonic-gate 			qpp->iq_qp_num = qp_num;
16367c478bd9Sstevel@tonic-gate 			qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
16377c478bd9Sstevel@tonic-gate 			mutex_init(&qpp->iq_mutex, NULL, MUTEX_DRIVER, NULL);
16387c478bd9Sstevel@tonic-gate 		}
16397c478bd9Sstevel@tonic-gate 	}
16407c478bd9Sstevel@tonic-gate 
16417c478bd9Sstevel@tonic-gate 	/* we now have a QP context */
16427c478bd9Sstevel@tonic-gate 	for (;;) {
16437c478bd9Sstevel@tonic-gate 		if (qpp->iq_flags == IBMF_QP_FLAGS_INITING) {
16447c478bd9Sstevel@tonic-gate 
16457c478bd9Sstevel@tonic-gate 			/* block till qp is in VALID state */
16467c478bd9Sstevel@tonic-gate 			cv_wait(&ibmf_cip->ci_qp_cv, &ibmf_cip->ci_mutex);
16477c478bd9Sstevel@tonic-gate 			continue;
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 		}
16507c478bd9Sstevel@tonic-gate 
16517c478bd9Sstevel@tonic-gate 		if (qpp->iq_flags == IBMF_QP_FLAGS_UNINITING) {
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate 			/* block till qp is in INVALID state */
16547c478bd9Sstevel@tonic-gate 			cv_wait(&ibmf_cip->ci_qp_cv, &ibmf_cip->ci_mutex);
16557c478bd9Sstevel@tonic-gate 			continue;
16567c478bd9Sstevel@tonic-gate 		}
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 		if (qpp->iq_flags == IBMF_QP_FLAGS_INVALID) {
16597c478bd9Sstevel@tonic-gate 			if ((status = ibmf_i_init_qp(ibmf_cip, qpp)) !=
16607c478bd9Sstevel@tonic-gate 			    IBMF_SUCCESS) {
16617c478bd9Sstevel@tonic-gate 				ibmf_qp_t *tqpp;
16627c478bd9Sstevel@tonic-gate 
16637c478bd9Sstevel@tonic-gate 				/*
16647c478bd9Sstevel@tonic-gate 				 * Remove the QP context from the CI's list.
16657c478bd9Sstevel@tonic-gate 				 * Only initialized QPs should be on the list.
16667c478bd9Sstevel@tonic-gate 				 * We know that this QP is on the list, so
16677c478bd9Sstevel@tonic-gate 				 * the list is not empty.
16687c478bd9Sstevel@tonic-gate 				 */
16697c478bd9Sstevel@tonic-gate 				tqpp = ibmf_cip->ci_qp_list;
16707c478bd9Sstevel@tonic-gate 				if (tqpp == qpp) {
16717c478bd9Sstevel@tonic-gate 					/* Only QP context on the list */
16727c478bd9Sstevel@tonic-gate 					ibmf_cip->ci_qp_list = NULL;
16737c478bd9Sstevel@tonic-gate 					ibmf_cip->ci_qp_list_tail = NULL;
16747c478bd9Sstevel@tonic-gate 				}
16757c478bd9Sstevel@tonic-gate 
16767c478bd9Sstevel@tonic-gate 				/* Find the QP context before the last one */
16777c478bd9Sstevel@tonic-gate 				if (tqpp != qpp) {
16787c478bd9Sstevel@tonic-gate 					while (tqpp->iq_next != qpp) {
16797c478bd9Sstevel@tonic-gate 						tqpp = tqpp->iq_next;
16807c478bd9Sstevel@tonic-gate 					}
16817c478bd9Sstevel@tonic-gate 
16827c478bd9Sstevel@tonic-gate 					/*
16837c478bd9Sstevel@tonic-gate 					 * We are at the second last element of
16847c478bd9Sstevel@tonic-gate 					 * the list. Readjust the tail pointer.
16857c478bd9Sstevel@tonic-gate 					 * Remove the last element from the
16867c478bd9Sstevel@tonic-gate 					 * list.
16877c478bd9Sstevel@tonic-gate 					 */
16887c478bd9Sstevel@tonic-gate 					tqpp->iq_next = NULL;
16897c478bd9Sstevel@tonic-gate 					ibmf_cip->ci_qp_list_tail = tqpp;
16907c478bd9Sstevel@tonic-gate 				}
16917c478bd9Sstevel@tonic-gate 
16927c478bd9Sstevel@tonic-gate 				/* Free up the QP context */
16937c478bd9Sstevel@tonic-gate 				kmem_free((void *)qpp, sizeof (ibmf_qp_t));
16947c478bd9Sstevel@tonic-gate 
16957c478bd9Sstevel@tonic-gate 				break;
16967c478bd9Sstevel@tonic-gate 			}
16977c478bd9Sstevel@tonic-gate 			continue;
16987c478bd9Sstevel@tonic-gate 		}
16997c478bd9Sstevel@tonic-gate 
17007c478bd9Sstevel@tonic-gate 		if (qpp->iq_flags == IBMF_QP_FLAGS_INITED) {
17017c478bd9Sstevel@tonic-gate 			qpp->iq_qp_ref++;
17027c478bd9Sstevel@tonic-gate 			break;
17037c478bd9Sstevel@tonic-gate 		}
17047c478bd9Sstevel@tonic-gate 	}
17057c478bd9Sstevel@tonic-gate 
17067c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*qpp))
17077c478bd9Sstevel@tonic-gate 
17087c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
17097c478bd9Sstevel@tonic-gate 
17107c478bd9Sstevel@tonic-gate 	if (status == IBMF_SUCCESS) {
17117c478bd9Sstevel@tonic-gate 		*qppp = qpp;
17127c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_end,
17137c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_get_qp() exit "
17147c478bd9Sstevel@tonic-gate 		    "qp_handle = %p\n", tnf_opaque, qp_handle, qpp);
17157c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
17167c478bd9Sstevel@tonic-gate 	} else {
17177c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_get_qp_err,
17187c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "%s\n", tnf_string, msg,
17197c478bd9Sstevel@tonic-gate 		    "ibmf_i_get_qp(): qp_not found");
17207c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_end,
17217c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_get_qp() exit\n");
17227c478bd9Sstevel@tonic-gate 		return (status);
17237c478bd9Sstevel@tonic-gate 	}
17247c478bd9Sstevel@tonic-gate }
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate /*
17277c478bd9Sstevel@tonic-gate  * ibmf_i_release_qp():
17287c478bd9Sstevel@tonic-gate  *	Drop the reference count on the QP structure
17297c478bd9Sstevel@tonic-gate  */
17307c478bd9Sstevel@tonic-gate void
ibmf_i_release_qp(ibmf_ci_t * ibmf_cip,ibmf_qp_t ** qppp)17317c478bd9Sstevel@tonic-gate ibmf_i_release_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t **qppp)
17327c478bd9Sstevel@tonic-gate {
17337c478bd9Sstevel@tonic-gate 	ibmf_qp_t	*qpp;
17347c478bd9Sstevel@tonic-gate 
17357c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_qp_start,
17367c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_release_qp() enter, cip = %p, "
17377c478bd9Sstevel@tonic-gate 	    "qpp = %p\n", tnf_opaque, cip, ibmf_cip, tnf_opaque, qpp, *qppp);
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_mutex));
17407c478bd9Sstevel@tonic-gate 
17417c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
17427c478bd9Sstevel@tonic-gate 	qpp = *qppp;
17437c478bd9Sstevel@tonic-gate 	qpp->iq_qp_ref--;
17447c478bd9Sstevel@tonic-gate 	if (qpp->iq_qp_ref == 0)
17457c478bd9Sstevel@tonic-gate 		ibmf_i_uninit_qp(ibmf_cip, qpp);
17467c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_qp_end,
17497c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_release_qp() exit\n");
17507c478bd9Sstevel@tonic-gate }
17517c478bd9Sstevel@tonic-gate 
17527c478bd9Sstevel@tonic-gate /*
17537c478bd9Sstevel@tonic-gate  * ibmf_i_init_qp():
17547c478bd9Sstevel@tonic-gate  *	Set up the QP context, request a QP from the IBT framework
17557c478bd9Sstevel@tonic-gate  *	and initialize it
17567c478bd9Sstevel@tonic-gate  */
17577c478bd9Sstevel@tonic-gate static int
ibmf_i_init_qp(ibmf_ci_t * ibmf_cip,ibmf_qp_t * qpp)17587c478bd9Sstevel@tonic-gate ibmf_i_init_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp)
17597c478bd9Sstevel@tonic-gate {
17607c478bd9Sstevel@tonic-gate 	ibt_sqp_type_t		qp_type;
17617c478bd9Sstevel@tonic-gate 	ibt_qp_alloc_attr_t	qp_attrs;
17627c478bd9Sstevel@tonic-gate 	ibt_qp_hdl_t		qp_handle;
17637c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		qp_modify_attr;
17647c478bd9Sstevel@tonic-gate 	ibt_status_t		ibt_status;
17657c478bd9Sstevel@tonic-gate 	int			i, status;
17667c478bd9Sstevel@tonic-gate 
17677c478bd9Sstevel@tonic-gate 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_start,
17687c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_qp() enter, cip = %p, "
17697c478bd9Sstevel@tonic-gate 	    "port = %d, qp = %d\n", tnf_opaque, ibmf_ci, ibmf_cip, tnf_int,
17707c478bd9Sstevel@tonic-gate 	    port, qpp->iq_port_num, tnf_int, num, qpp->iq_qp_num);
17717c478bd9Sstevel@tonic-gate 
17727c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(qpp->iq_qp_handle))
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibmf_cip->ci_mutex));
17757c478bd9Sstevel@tonic-gate 
17767c478bd9Sstevel@tonic-gate 	qpp->iq_flags = IBMF_QP_FLAGS_INITING;
17777c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
17787c478bd9Sstevel@tonic-gate 	if (qpp->iq_qp_handle) {	/* closed but not yet freed */
17797c478bd9Sstevel@tonic-gate 		ibt_status = ibt_free_qp(qpp->iq_qp_handle);
17807c478bd9Sstevel@tonic-gate 		if (ibt_status != IBT_SUCCESS) {
17817c478bd9Sstevel@tonic-gate 			IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
17827c478bd9Sstevel@tonic-gate 			    ibmf_i_init_qp_err, IBMF_TNF_ERROR, "",
17837c478bd9Sstevel@tonic-gate 			    "%s, status = %d\n", tnf_string, msg,
17847c478bd9Sstevel@tonic-gate 			    "ibt_free_qp returned error",
17857c478bd9Sstevel@tonic-gate 			    tnf_uint, ibt_status, ibt_status);
17867c478bd9Sstevel@tonic-gate 		}
17877c478bd9Sstevel@tonic-gate 		qpp->iq_qp_handle = NULL;
17887c478bd9Sstevel@tonic-gate 	}
17897c478bd9Sstevel@tonic-gate 	ASSERT(qpp->iq_qp_num == 0 || qpp->iq_qp_num == 1);
17907c478bd9Sstevel@tonic-gate 	if (qpp->iq_qp_num == 0)
17917c478bd9Sstevel@tonic-gate 		qp_type = IBT_SMI_SQP;
17927c478bd9Sstevel@tonic-gate 	else
17937c478bd9Sstevel@tonic-gate 		qp_type = IBT_GSI_SQP;
17947c478bd9Sstevel@tonic-gate 	qp_attrs.qp_scq_hdl = ibmf_cip->ci_cq_handle;
17957c478bd9Sstevel@tonic-gate 	qp_attrs.qp_rcq_hdl = ibmf_cip->ci_cq_handle;
17967c478bd9Sstevel@tonic-gate 	qp_attrs.qp_pd_hdl = ibmf_cip->ci_pd;
17977c478bd9Sstevel@tonic-gate 	qp_attrs.qp_sizes.cs_sq_sgl = 1;
17987c478bd9Sstevel@tonic-gate 	qp_attrs.qp_sizes.cs_rq_sgl = IBMF_MAX_RQ_WR_SGL_ELEMENTS;
17997c478bd9Sstevel@tonic-gate 	qp_attrs.qp_sizes.cs_sq = ibmf_send_wqes_posted_per_qp;
18007c478bd9Sstevel@tonic-gate 	qp_attrs.qp_sizes.cs_rq = ibmf_recv_wqes_posted_per_qp;
18017c478bd9Sstevel@tonic-gate 	qp_attrs.qp_flags = IBT_ALL_SIGNALED;
18027c478bd9Sstevel@tonic-gate 	qp_attrs.qp_alloc_flags = IBT_QP_NO_FLAGS;
18037c478bd9Sstevel@tonic-gate 
18047c478bd9Sstevel@tonic-gate 	/* call the IB transport to allocate a special QP */
18057c478bd9Sstevel@tonic-gate 	ibt_status = ibt_alloc_special_qp(ibmf_cip->ci_ci_handle,
18067c478bd9Sstevel@tonic-gate 	    qpp->iq_port_num, qp_type, &qp_attrs, NULL, &qp_handle);
18077c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
18087c478bd9Sstevel@tonic-gate 		mutex_enter(&ibmf_cip->ci_mutex);
18097c478bd9Sstevel@tonic-gate 		qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
18107c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibmf_cip->ci_qp_cv);
18117c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err,
18127c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "ibmf_i_init_qp() error status = %d\n",
18137c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, ibt_status);
18147c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end,
18157c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n");
18167c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
18177c478bd9Sstevel@tonic-gate 	}
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 	/* initialize qpp */
18207c478bd9Sstevel@tonic-gate 	qpp->iq_qp_handle = qp_handle;
18217c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_trans = IBT_UD_SRV;
18227c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 	/* get the pkey index for the specified pkey */
18257c478bd9Sstevel@tonic-gate 	if (ibmf_i_get_pkeyix(ibmf_cip->ci_ci_handle, IBMF_P_KEY_DEF_LIMITED,
18267c478bd9Sstevel@tonic-gate 	    qpp->iq_port_num, &qp_modify_attr.qp_transport.ud.ud_pkey_ix) !=
18277c478bd9Sstevel@tonic-gate 	    IBMF_SUCCESS) {
18287c478bd9Sstevel@tonic-gate 		ibt_status = ibt_free_qp(qpp->iq_qp_handle);
18297c478bd9Sstevel@tonic-gate 		if (ibt_status != IBT_SUCCESS) {
18307c478bd9Sstevel@tonic-gate 			IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
18317c478bd9Sstevel@tonic-gate 			    ibmf_i_init_qp_err, IBMF_TNF_ERROR, "",
18327c478bd9Sstevel@tonic-gate 			    "%s, status = %d\n", tnf_string, msg,
18337c478bd9Sstevel@tonic-gate 			    "ibt_free_qp returned error",
18347c478bd9Sstevel@tonic-gate 			    tnf_uint, ibt_status, ibt_status);
18357c478bd9Sstevel@tonic-gate 		}
18367c478bd9Sstevel@tonic-gate 		mutex_enter(&ibmf_cip->ci_mutex);
18377c478bd9Sstevel@tonic-gate 		qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
18387c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibmf_cip->ci_qp_cv);
18397c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err,
18407c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "ibmf_init_qp(): failed to get "
18417c478bd9Sstevel@tonic-gate 		    "pkey index\n");
18427c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end,
18437c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n");
18447c478bd9Sstevel@tonic-gate 		return (IBMF_FAILURE);
18457c478bd9Sstevel@tonic-gate 	}
18467c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
18477c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_transport.ud.ud_port = qpp->iq_port_num;
18487c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_transport.ud.ud_qkey = IBMF_MGMT_Q_KEY;
18497c478bd9Sstevel@tonic-gate 
18507c478bd9Sstevel@tonic-gate 	/* call the IB transport to initialize the QP */
18517c478bd9Sstevel@tonic-gate 	ibt_status = ibt_initialize_qp(qp_handle, &qp_modify_attr);
18527c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
18537c478bd9Sstevel@tonic-gate 		ibt_status = ibt_free_qp(qpp->iq_qp_handle);
18547c478bd9Sstevel@tonic-gate 		if (ibt_status != IBT_SUCCESS) {
18557c478bd9Sstevel@tonic-gate 			IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
18567c478bd9Sstevel@tonic-gate 			    ibmf_i_init_qp_err, IBMF_TNF_ERROR, "",
18577c478bd9Sstevel@tonic-gate 			    "%s, status = %d\n", tnf_string, msg,
18587c478bd9Sstevel@tonic-gate 			    "ibt_free_qp returned error",
18597c478bd9Sstevel@tonic-gate 			    tnf_uint, ibt_status, ibt_status);
18607c478bd9Sstevel@tonic-gate 		}
18617c478bd9Sstevel@tonic-gate 		mutex_enter(&ibmf_cip->ci_mutex);
18627c478bd9Sstevel@tonic-gate 		qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
18637c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibmf_cip->ci_qp_cv);
18647c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err,
18657c478bd9Sstevel@tonic-gate 		    IBMF_TNF_ERROR, "", "ibmf_init_qp(): error status = %d\n",
18667c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, ibt_status);
18677c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end,
18687c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n");
18697c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
18707c478bd9Sstevel@tonic-gate 	}
18717c478bd9Sstevel@tonic-gate 
18727c478bd9Sstevel@tonic-gate 	/* post receive wqes to the RQ to handle unsolicited inbound packets  */
18737c478bd9Sstevel@tonic-gate 	for (i = 0; i < ibmf_recv_wqes_per_port; i++) {
18747c478bd9Sstevel@tonic-gate 		status =  ibmf_i_post_recv_buffer(ibmf_cip, qpp,
18757c478bd9Sstevel@tonic-gate 		    B_TRUE, IBMF_QP_HANDLE_DEFAULT);
18767c478bd9Sstevel@tonic-gate 		if (status != IBMF_SUCCESS) {
18777c478bd9Sstevel@tonic-gate 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1,
18787c478bd9Sstevel@tonic-gate 			    ibmf_i_init_qp, IBMF_TNF_TRACE, "",
18797c478bd9Sstevel@tonic-gate 			    "%s\n", tnf_string, msg, "ibmf_i_init_qp(): "
18807c478bd9Sstevel@tonic-gate 			    "ibmf_i_post_recv_buffer() failed");
18817c478bd9Sstevel@tonic-gate 		}
18827c478bd9Sstevel@tonic-gate 	}
18837c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
18847c478bd9Sstevel@tonic-gate 
18857c478bd9Sstevel@tonic-gate 	/* set the state and signal blockers */
18867c478bd9Sstevel@tonic-gate 	qpp->iq_flags = IBMF_QP_FLAGS_INITED;
18877c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibmf_cip->ci_qp_cv);
18887c478bd9Sstevel@tonic-gate 
18897c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end,
18907c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n");
18917c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
18927c478bd9Sstevel@tonic-gate }
18937c478bd9Sstevel@tonic-gate 
18947c478bd9Sstevel@tonic-gate /*
18957c478bd9Sstevel@tonic-gate  * ibmf_i_uninit_qp():
18967c478bd9Sstevel@tonic-gate  *	Invalidate the QP context
18977c478bd9Sstevel@tonic-gate  */
18987c478bd9Sstevel@tonic-gate static void
ibmf_i_uninit_qp(ibmf_ci_t * ibmf_cip,ibmf_qp_t * qpp)18997c478bd9Sstevel@tonic-gate ibmf_i_uninit_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp)
19007c478bd9Sstevel@tonic-gate {
19017c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
19027c478bd9Sstevel@tonic-gate 
19037c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_qp_start,
19047c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_uninit_qp() enter, cip = %p "
19057c478bd9Sstevel@tonic-gate 	    "qpp = %p\n", tnf_opaque, cip, ibmf_cip, tnf_opaque, qpp, qpp);
19067c478bd9Sstevel@tonic-gate 
19077c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibmf_cip->ci_mutex));
19087c478bd9Sstevel@tonic-gate 
19097c478bd9Sstevel@tonic-gate 	/* mark the state as uniniting */
19107c478bd9Sstevel@tonic-gate 	ASSERT(qpp->iq_qp_ref == 0);
19117c478bd9Sstevel@tonic-gate 	qpp->iq_flags = IBMF_QP_FLAGS_UNINITING;
19127c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
19137c478bd9Sstevel@tonic-gate 
19147c478bd9Sstevel@tonic-gate 	/* note: we ignore error values from ibt_flush_qp */
19157c478bd9Sstevel@tonic-gate 	status = ibt_flush_qp(qpp->iq_qp_handle);
19167c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
19177c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L2,
19187c478bd9Sstevel@tonic-gate 		    ibmf_i_uninit_qp_err, IBMF_TNF_ERROR, "",
19197c478bd9Sstevel@tonic-gate 		    "ibmf_i_uninit_qp(): %s, status = %d\n", tnf_string, msg,
19207c478bd9Sstevel@tonic-gate 		    "ibt_flush_qp returned error", tnf_int, status, status);
19217c478bd9Sstevel@tonic-gate 	}
19227c478bd9Sstevel@tonic-gate 
19237c478bd9Sstevel@tonic-gate 	/* mark state as INVALID and signal any blockers */
19247c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
19257c478bd9Sstevel@tonic-gate 	qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
19267c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibmf_cip->ci_qp_cv);
19277c478bd9Sstevel@tonic-gate 
19287c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_qp_end,
19297c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_uninit_qp() exit\n");
19307c478bd9Sstevel@tonic-gate }
19317c478bd9Sstevel@tonic-gate 
19327c478bd9Sstevel@tonic-gate /*
19337c478bd9Sstevel@tonic-gate  * ibmf_i_alloc_msg():
19347c478bd9Sstevel@tonic-gate  *	Allocate and set up a message context
19357c478bd9Sstevel@tonic-gate  */
19367c478bd9Sstevel@tonic-gate int
ibmf_i_alloc_msg(ibmf_client_t * clientp,ibmf_msg_impl_t ** msgp,int km_flags)19377c478bd9Sstevel@tonic-gate ibmf_i_alloc_msg(ibmf_client_t *clientp, ibmf_msg_impl_t **msgp, int km_flags)
19387c478bd9Sstevel@tonic-gate {
19397c478bd9Sstevel@tonic-gate 	ibmf_msg_impl_t *msgimplp;
19407c478bd9Sstevel@tonic-gate 
19417c478bd9Sstevel@tonic-gate 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
19427c478bd9Sstevel@tonic-gate 	    ibmf_i_alloc_msg_start, IBMF_TNF_TRACE, "",
19437c478bd9Sstevel@tonic-gate 	    "ibmf_i_alloc_msg() enter, clientp = %p, msg = %p, "
19447c478bd9Sstevel@tonic-gate 	    " kmflags = %d\n", tnf_opaque, clientp, clientp, tnf_opaque, msg,
19457c478bd9Sstevel@tonic-gate 	    *msgp, tnf_int, km_flags, km_flags);
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate 	/* allocate the message context */
19487c478bd9Sstevel@tonic-gate 	msgimplp = (ibmf_msg_impl_t *)kmem_zalloc(sizeof (ibmf_msg_impl_t),
19497c478bd9Sstevel@tonic-gate 	    km_flags);
19507c478bd9Sstevel@tonic-gate 	if (msgimplp != NULL) {
19517c478bd9Sstevel@tonic-gate 		if (km_flags == KM_SLEEP) {
19527c478bd9Sstevel@tonic-gate 			ibmf_i_pop_ud_dest_thread(clientp->ic_myci);
19537c478bd9Sstevel@tonic-gate 		}
19547c478bd9Sstevel@tonic-gate 	} else {
19557c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
19567c478bd9Sstevel@tonic-gate 		    ibmf_i_alloc_msg_err, IBMF_TNF_ERROR, "",
19577c478bd9Sstevel@tonic-gate 		    "ibmf_i_alloc_msg(): %s\n",
19587c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "kmem_xalloc failed");
19597c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_msg_end,
19607c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_alloc_msg() exit\n");
19617c478bd9Sstevel@tonic-gate 		return (IBMF_NO_RESOURCES);
19627c478bd9Sstevel@tonic-gate 	}
19637c478bd9Sstevel@tonic-gate 
19647c478bd9Sstevel@tonic-gate 	*msgp = msgimplp;
19657c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_msg_end,
19667c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_alloc_msg() exit\n");
19677c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
19687c478bd9Sstevel@tonic-gate }
19697c478bd9Sstevel@tonic-gate 
19707c478bd9Sstevel@tonic-gate /*
19717c478bd9Sstevel@tonic-gate  * ibmf_i_free_msg():
19727c478bd9Sstevel@tonic-gate  *	frees up all buffers allocated by IBMF for
19737c478bd9Sstevel@tonic-gate  * 	this message context, and then frees up the context
19747c478bd9Sstevel@tonic-gate  */
19757c478bd9Sstevel@tonic-gate void
ibmf_i_free_msg(ibmf_msg_impl_t * msgimplp)19767c478bd9Sstevel@tonic-gate ibmf_i_free_msg(ibmf_msg_impl_t *msgimplp)
19777c478bd9Sstevel@tonic-gate {
19787c478bd9Sstevel@tonic-gate 	ibmf_msg_bufs_t *msgbufp = &msgimplp->im_msgbufs_recv;
19797c478bd9Sstevel@tonic-gate 	ibmf_client_t *clientp = (ibmf_client_t *)msgimplp->im_client;
19807c478bd9Sstevel@tonic-gate 	uint32_t	cl_hdr_sz, cl_hdr_off;
19817c478bd9Sstevel@tonic-gate 
19827c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
19837c478bd9Sstevel@tonic-gate 	    ibmf_i_free_msg_start, IBMF_TNF_TRACE, "",
19847c478bd9Sstevel@tonic-gate 	    "ibmf_i_free_msg() enter, msg = %p\n", tnf_opaque, msg, msgimplp);
19857c478bd9Sstevel@tonic-gate 
19867c478bd9Sstevel@tonic-gate 	/* free up the UD destination resource */
19877c478bd9Sstevel@tonic-gate 	if (msgimplp->im_ibmf_ud_dest != NULL) {
19887c478bd9Sstevel@tonic-gate 		ibmf_i_free_ud_dest(clientp, msgimplp);
19897c478bd9Sstevel@tonic-gate 		ibmf_i_clean_ud_dest_list(clientp->ic_myci, B_FALSE);
19907c478bd9Sstevel@tonic-gate 	}
19917c478bd9Sstevel@tonic-gate 
19927c478bd9Sstevel@tonic-gate 	/* free up the receive buffer if allocated previously */
19937c478bd9Sstevel@tonic-gate 	if (msgbufp->im_bufs_mad_hdr != NULL) {
19947c478bd9Sstevel@tonic-gate 		ibmf_i_mgt_class_to_hdr_sz_off(
19957c478bd9Sstevel@tonic-gate 		    msgbufp->im_bufs_mad_hdr->MgmtClass,
19967c478bd9Sstevel@tonic-gate 		    &cl_hdr_sz, &cl_hdr_off);
19977c478bd9Sstevel@tonic-gate 		kmem_free(msgbufp->im_bufs_mad_hdr, sizeof (ib_mad_hdr_t) +
19987c478bd9Sstevel@tonic-gate 		    cl_hdr_off + msgbufp->im_bufs_cl_hdr_len +
19997c478bd9Sstevel@tonic-gate 		    msgbufp->im_bufs_cl_data_len);
20007c478bd9Sstevel@tonic-gate 		mutex_enter(&clientp->ic_kstat_mutex);
20017c478bd9Sstevel@tonic-gate 		IBMF_SUB32_KSTATS(clientp, recv_bufs_alloced, 1);
20027c478bd9Sstevel@tonic-gate 		mutex_exit(&clientp->ic_kstat_mutex);
20037c478bd9Sstevel@tonic-gate 	}
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 	/* destroy the message mutex */
20067c478bd9Sstevel@tonic-gate 	mutex_destroy(&msgimplp->im_mutex);
20077c478bd9Sstevel@tonic-gate 
20087c478bd9Sstevel@tonic-gate 	/* free the message context */
20097c478bd9Sstevel@tonic-gate 	kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
20107c478bd9Sstevel@tonic-gate 
20117c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_msg_end,
20127c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_free_msg() exit\n");
20137c478bd9Sstevel@tonic-gate }
20147c478bd9Sstevel@tonic-gate 
20157c478bd9Sstevel@tonic-gate /*
20167c478bd9Sstevel@tonic-gate  * ibmf_i_msg_transport():
20177c478bd9Sstevel@tonic-gate  *	Send a message posted by the IBMF client using the RMPP protocol
20187c478bd9Sstevel@tonic-gate  *	if specified
20197c478bd9Sstevel@tonic-gate  */
20207c478bd9Sstevel@tonic-gate int
ibmf_i_msg_transport(ibmf_client_t * clientp,ibmf_qp_handle_t ibmf_qp_handle,ibmf_msg_impl_t * msgimplp,int blocking)20217c478bd9Sstevel@tonic-gate ibmf_i_msg_transport(ibmf_client_t *clientp, ibmf_qp_handle_t ibmf_qp_handle,
20227c478bd9Sstevel@tonic-gate     ibmf_msg_impl_t *msgimplp, int blocking)
20237c478bd9Sstevel@tonic-gate {
20247c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t	*madhdrp;
20257c478bd9Sstevel@tonic-gate 	ibmf_msg_bufs_t *msgbufp, *smsgbufp;
20267c478bd9Sstevel@tonic-gate 	uint32_t	cl_hdr_sz, cl_hdr_off;
20277c478bd9Sstevel@tonic-gate 	boolean_t	isDS = 0; /* double sided (sequenced) transaction */
20287c478bd9Sstevel@tonic-gate 	boolean_t	error = B_FALSE;
20297c478bd9Sstevel@tonic-gate 	int		status = IBMF_SUCCESS;
20307c478bd9Sstevel@tonic-gate 	uint_t		refcnt;
20317c478bd9Sstevel@tonic-gate 	char		errmsg[128];
20327c478bd9Sstevel@tonic-gate 	timeout_id_t	msg_rp_unset_id, msg_tr_unset_id;
20337c478bd9Sstevel@tonic-gate 
20347c478bd9Sstevel@tonic-gate 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_msg_transport_start,
20357c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): clientp = 0x%p, "
20367c478bd9Sstevel@tonic-gate 	    "qphdl = 0x%p, msgp = 0x%p, block = %d\n",
20377c478bd9Sstevel@tonic-gate 	    tnf_opaque, clientp, clientp, tnf_opaque, qphdl, ibmf_qp_handle,
20387c478bd9Sstevel@tonic-gate 	    tnf_opaque, msg, msgimplp, tnf_uint, block, blocking);
20397c478bd9Sstevel@tonic-gate 
20407c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp, *msgbufp))
20417c478bd9Sstevel@tonic-gate 
20427c478bd9Sstevel@tonic-gate 	mutex_enter(&msgimplp->im_mutex);
20437c478bd9Sstevel@tonic-gate 
20447c478bd9Sstevel@tonic-gate 	madhdrp = msgimplp->im_msgbufs_send.im_bufs_mad_hdr;
20457c478bd9Sstevel@tonic-gate 	msgbufp = &msgimplp->im_msgbufs_recv;
20467c478bd9Sstevel@tonic-gate 	smsgbufp = &msgimplp->im_msgbufs_send;
20477c478bd9Sstevel@tonic-gate 
20487c478bd9Sstevel@tonic-gate 	/*
20497c478bd9Sstevel@tonic-gate 	 * check if transp_op_flags specify that the transaction is
20507c478bd9Sstevel@tonic-gate 	 * a single packet, then the size of the message header + data
20517c478bd9Sstevel@tonic-gate 	 * does not exceed 256 bytes
20527c478bd9Sstevel@tonic-gate 	 */
20537c478bd9Sstevel@tonic-gate 	if ((msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) == 0) {
20547c478bd9Sstevel@tonic-gate 		ibmf_i_mgt_class_to_hdr_sz_off(
20557c478bd9Sstevel@tonic-gate 		    smsgbufp->im_bufs_mad_hdr->MgmtClass,
20567c478bd9Sstevel@tonic-gate 		    &cl_hdr_sz, &cl_hdr_off);
20577c478bd9Sstevel@tonic-gate 
20587c478bd9Sstevel@tonic-gate 		if ((sizeof (ib_mad_hdr_t) + cl_hdr_off +
20597c478bd9Sstevel@tonic-gate 		    smsgbufp->im_bufs_cl_hdr_len +
20607c478bd9Sstevel@tonic-gate 		    smsgbufp->im_bufs_cl_data_len) > IBMF_MAD_SIZE) {
20617c478bd9Sstevel@tonic-gate 			mutex_exit(&msgimplp->im_mutex);
20627c478bd9Sstevel@tonic-gate 			(void) sprintf(errmsg,
20637c478bd9Sstevel@tonic-gate 			    "Non-RMPP message size is too large");
20647c478bd9Sstevel@tonic-gate 			error = B_TRUE;
20657c478bd9Sstevel@tonic-gate 			status = IBMF_BAD_SIZE;
20667c478bd9Sstevel@tonic-gate 			goto bail;
20677c478bd9Sstevel@tonic-gate 		}
20687c478bd9Sstevel@tonic-gate 	}
20697c478bd9Sstevel@tonic-gate 
20707c478bd9Sstevel@tonic-gate 	/* more message context initialization */
20717c478bd9Sstevel@tonic-gate 	msgimplp->im_qp_hdl 	= ibmf_qp_handle;
20727c478bd9Sstevel@tonic-gate 	msgimplp->im_tid	= b2h64(madhdrp->TransactionID);
20737c478bd9Sstevel@tonic-gate 	msgimplp->im_mgt_class 	= madhdrp->MgmtClass;
20747c478bd9Sstevel@tonic-gate 	msgimplp->im_unsolicited = B_FALSE;
20757c478bd9Sstevel@tonic-gate 	msgimplp->im_trans_state_flags = IBMF_TRANS_STATE_FLAG_UNINIT;
2076d0141297Ssandipb 	bzero(&msgimplp->im_rmpp_ctx, sizeof (ibmf_rmpp_ctx_t));
20777c478bd9Sstevel@tonic-gate 	msgimplp->im_rmpp_ctx.rmpp_state = IBMF_RMPP_STATE_UNDEFINED;
20787c478bd9Sstevel@tonic-gate 	msgimplp->im_rmpp_ctx.rmpp_respt = IBMF_RMPP_DEFAULT_RRESPT;
20797c478bd9Sstevel@tonic-gate 	msgimplp->im_rmpp_ctx.rmpp_retry_cnt = 0;
2080d0141297Ssandipb 	msgimplp->im_ref_count = 0;
2081d0141297Ssandipb 	msgimplp->im_pending_send_compls = 0;
20827c478bd9Sstevel@tonic-gate 	IBMF_MSG_INCR_REFCNT(msgimplp);
20837c478bd9Sstevel@tonic-gate 	if (msgimplp->im_retrans.retrans_retries == 0)
20847c478bd9Sstevel@tonic-gate 		msgimplp->im_retrans.retrans_retries = IBMF_RETRANS_DEF_RETRIES;
20857c478bd9Sstevel@tonic-gate 	if (msgimplp->im_retrans.retrans_rtv == 0)
20867c478bd9Sstevel@tonic-gate 		msgimplp->im_retrans.retrans_rtv = IBMF_RETRANS_DEF_RTV;
20877c478bd9Sstevel@tonic-gate 	if (msgimplp->im_retrans.retrans_rttv == 0)
20887c478bd9Sstevel@tonic-gate 		msgimplp->im_retrans.retrans_rttv = IBMF_RETRANS_DEF_RTTV;
20897c478bd9Sstevel@tonic-gate 
20907c478bd9Sstevel@tonic-gate 	IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
20917c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): %s, msgp = 0x%p, "
20927c478bd9Sstevel@tonic-gate 	    "class = 0x%x, method = 0x%x, attributeID = 0x%x\n",
20937c478bd9Sstevel@tonic-gate 	    tnf_string, msg, "Added message", tnf_opaque, msgimplp,
20947c478bd9Sstevel@tonic-gate 	    msgimplp, tnf_opaque, class, msgimplp->im_mgt_class, tnf_opaque,
20957c478bd9Sstevel@tonic-gate 	    method, madhdrp->R_Method, tnf_opaque, attrib_id,
20967c478bd9Sstevel@tonic-gate 	    b2h16(madhdrp->AttributeID));
20977c478bd9Sstevel@tonic-gate 
20987c478bd9Sstevel@tonic-gate 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
20997c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): msgp = 0x%p, "
21007c478bd9Sstevel@tonic-gate 	    "TID = 0x%p, transp_op_flags = 0x%x\n",
21017c478bd9Sstevel@tonic-gate 	    tnf_opaque, msgimplp, msgimplp, tnf_opaque, tid, msgimplp->im_tid,
21027c478bd9Sstevel@tonic-gate 	    tnf_uint, transp_op_flags, msgimplp->im_transp_op_flags);
21037c478bd9Sstevel@tonic-gate 
21047c478bd9Sstevel@tonic-gate 	/*
21057c478bd9Sstevel@tonic-gate 	 * Do not allow reuse of a message where the receive buffers are
21067c478bd9Sstevel@tonic-gate 	 * being used as send buffers if this is a sequenced transaction
21077c478bd9Sstevel@tonic-gate 	 */
21087c478bd9Sstevel@tonic-gate 	if ((madhdrp == msgbufp->im_bufs_mad_hdr) &&
21097c478bd9Sstevel@tonic-gate 	    (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)) {
21107c478bd9Sstevel@tonic-gate 		IBMF_MSG_DECR_REFCNT(msgimplp);
21117c478bd9Sstevel@tonic-gate 		mutex_exit(&msgimplp->im_mutex);
21127c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg,
21137c478bd9Sstevel@tonic-gate 		    "Send and Recv buffers are the same for sequenced"
21147c478bd9Sstevel@tonic-gate 		    " transaction");
21157c478bd9Sstevel@tonic-gate 		error = B_TRUE;
21167c478bd9Sstevel@tonic-gate 		status = IBMF_REQ_INVALID;
21177c478bd9Sstevel@tonic-gate 		goto bail;
21187c478bd9Sstevel@tonic-gate 	}
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate 	/* set transaction flags */
21217c478bd9Sstevel@tonic-gate 	if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)
21227c478bd9Sstevel@tonic-gate 		msgimplp->im_flags |= IBMF_MSG_FLAGS_SEQUENCED;
21237c478bd9Sstevel@tonic-gate 
21247c478bd9Sstevel@tonic-gate 	if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP)
21257c478bd9Sstevel@tonic-gate 		msgimplp->im_flags |= IBMF_MSG_FLAGS_SEND_RMPP;
21267c478bd9Sstevel@tonic-gate 	else
21277c478bd9Sstevel@tonic-gate 		msgimplp->im_flags |= IBMF_MSG_FLAGS_NOT_RMPP;
21287c478bd9Sstevel@tonic-gate 
21297c478bd9Sstevel@tonic-gate 	/* free recv buffers if this is a reused message */
21307c478bd9Sstevel@tonic-gate 	if ((msgbufp->im_bufs_mad_hdr != NULL) &&
21317c478bd9Sstevel@tonic-gate 	    (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)) {
21327c478bd9Sstevel@tonic-gate 
21337c478bd9Sstevel@tonic-gate 		IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
21347c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): %s, "
21357c478bd9Sstevel@tonic-gate 		    "msgp = 0x%p, mad_hdrp = 0x%p\n", tnf_string, msg,
21367c478bd9Sstevel@tonic-gate 		    "Freeing recv buffer for reused message",
21377c478bd9Sstevel@tonic-gate 		    tnf_opaque, msgimplp, msgimplp,
21387c478bd9Sstevel@tonic-gate 		    tnf_opaque, mad_hdr, msgbufp->im_bufs_mad_hdr);
21397c478bd9Sstevel@tonic-gate 
21407c478bd9Sstevel@tonic-gate 		ibmf_i_mgt_class_to_hdr_sz_off(
21417c478bd9Sstevel@tonic-gate 		    msgbufp->im_bufs_mad_hdr->MgmtClass,
21427c478bd9Sstevel@tonic-gate 		    &cl_hdr_sz, &cl_hdr_off);
21437c478bd9Sstevel@tonic-gate 
21447c478bd9Sstevel@tonic-gate 		kmem_free(msgbufp->im_bufs_mad_hdr, sizeof (ib_mad_hdr_t) +
21457c478bd9Sstevel@tonic-gate 		    cl_hdr_off + msgbufp->im_bufs_cl_hdr_len +
21467c478bd9Sstevel@tonic-gate 		    msgbufp->im_bufs_cl_data_len);
21477c478bd9Sstevel@tonic-gate 
21487c478bd9Sstevel@tonic-gate 		msgbufp->im_bufs_mad_hdr = NULL;
21497c478bd9Sstevel@tonic-gate 		msgbufp->im_bufs_cl_hdr = NULL;
21507c478bd9Sstevel@tonic-gate 		msgbufp->im_bufs_cl_hdr_len = 0;
21517c478bd9Sstevel@tonic-gate 		msgbufp->im_bufs_cl_data = NULL;
21527c478bd9Sstevel@tonic-gate 		msgbufp->im_bufs_cl_data_len = 0;
21537c478bd9Sstevel@tonic-gate 	}
21547c478bd9Sstevel@tonic-gate 
21557c478bd9Sstevel@tonic-gate 	mutex_exit(&msgimplp->im_mutex);
21567c478bd9Sstevel@tonic-gate 
21577c478bd9Sstevel@tonic-gate 	/* initialize (and possibly allocate) the address handle */
21587c478bd9Sstevel@tonic-gate 	status = ibmf_i_alloc_ud_dest(clientp, msgimplp,
21597c478bd9Sstevel@tonic-gate 	    &msgimplp->im_ud_dest, blocking);
21607c478bd9Sstevel@tonic-gate 	if (status != IBMF_SUCCESS) {
21617c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "ibmf_i_alloc_ud_dest() failed");
21627c478bd9Sstevel@tonic-gate 		error = B_TRUE;
21637c478bd9Sstevel@tonic-gate 		goto bail;
21647c478bd9Sstevel@tonic-gate 	}
21657c478bd9Sstevel@tonic-gate 
21667c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msgimplp, *msgbufp))
21677c478bd9Sstevel@tonic-gate 
21687c478bd9Sstevel@tonic-gate 	/* add the message to the client context's message list */
21697c478bd9Sstevel@tonic-gate 	ibmf_i_client_add_msg(clientp, msgimplp);
21707c478bd9Sstevel@tonic-gate 
21717c478bd9Sstevel@tonic-gate 	mutex_enter(&msgimplp->im_mutex);
21727c478bd9Sstevel@tonic-gate 
21737c478bd9Sstevel@tonic-gate 	/* no one should have touched our state */
21747c478bd9Sstevel@tonic-gate 	ASSERT(msgimplp->im_trans_state_flags == IBMF_TRANS_STATE_FLAG_UNINIT);
21757c478bd9Sstevel@tonic-gate 
21767c478bd9Sstevel@tonic-gate 	/* transition out of uninit state */
21777c478bd9Sstevel@tonic-gate 	msgimplp->im_trans_state_flags = IBMF_TRANS_STATE_FLAG_INIT;
21787c478bd9Sstevel@tonic-gate 
21797c478bd9Sstevel@tonic-gate 	IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
21807c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): msgp = 0x%p, "
21817c478bd9Sstevel@tonic-gate 	    "local_lid = 0x%x, remote_lid = 0x%x, remote_qpn = 0x%x, "
21827c478bd9Sstevel@tonic-gate 	    "block = %d\n", tnf_opaque, msgp, msgimplp,
21837c478bd9Sstevel@tonic-gate 	    tnf_uint, local_lid, msgimplp->im_local_addr.ia_local_lid,
21847c478bd9Sstevel@tonic-gate 	    tnf_uint, remote_lid, msgimplp->im_local_addr.ia_remote_lid,
21857c478bd9Sstevel@tonic-gate 	    tnf_uint, remote_qpn, msgimplp->im_local_addr.ia_remote_qno,
21867c478bd9Sstevel@tonic-gate 	    tnf_uint, blocking, blocking);
21877c478bd9Sstevel@tonic-gate 
21887c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
21897c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): "
21907c478bd9Sstevel@tonic-gate 	    "unsetting timer %p %d\n", tnf_opaque, msgimplp, msgimplp,
21917c478bd9Sstevel@tonic-gate 	    tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id);
21927c478bd9Sstevel@tonic-gate 
21937c478bd9Sstevel@tonic-gate 	ASSERT(msgimplp->im_rp_timeout_id == 0);
21947c478bd9Sstevel@tonic-gate 	ASSERT(msgimplp->im_tr_timeout_id == 0);
21957c478bd9Sstevel@tonic-gate 
21967c478bd9Sstevel@tonic-gate 	if ((msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) == 0) {
21977c478bd9Sstevel@tonic-gate 
21987c478bd9Sstevel@tonic-gate 		/* Non-RMPP transaction */
21997c478bd9Sstevel@tonic-gate 
22007c478bd9Sstevel@tonic-gate 		status = ibmf_i_send_single_pkt(clientp, ibmf_qp_handle,
22017c478bd9Sstevel@tonic-gate 		    msgimplp, blocking);
22027c478bd9Sstevel@tonic-gate 		if (status != IBMF_SUCCESS) {
22037c478bd9Sstevel@tonic-gate 			IBMF_MSG_DECR_REFCNT(msgimplp);
22047c478bd9Sstevel@tonic-gate 			mutex_exit(&msgimplp->im_mutex);
22057c478bd9Sstevel@tonic-gate 			ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt);
22067c478bd9Sstevel@tonic-gate 			(void) sprintf(errmsg, "Single packet send failed");
22077c478bd9Sstevel@tonic-gate 			error = B_TRUE;
22087c478bd9Sstevel@tonic-gate 			goto bail;
22097c478bd9Sstevel@tonic-gate 		}
22107c478bd9Sstevel@tonic-gate 
22117c478bd9Sstevel@tonic-gate 	} else if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) {
22127c478bd9Sstevel@tonic-gate 
22137c478bd9Sstevel@tonic-gate 		/* RMPP transaction */
22147c478bd9Sstevel@tonic-gate 
22157c478bd9Sstevel@tonic-gate 		/* check if client supports RMPP traffic */
22167c478bd9Sstevel@tonic-gate 		if ((clientp->ic_reg_flags & IBMF_REG_FLAG_RMPP) == 0) {
22177c478bd9Sstevel@tonic-gate 			IBMF_MSG_DECR_REFCNT(msgimplp);
22187c478bd9Sstevel@tonic-gate 			mutex_exit(&msgimplp->im_mutex);
22197c478bd9Sstevel@tonic-gate 			ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt);
22207c478bd9Sstevel@tonic-gate 			(void) sprintf(errmsg, "Class does not support RMPP");
22217c478bd9Sstevel@tonic-gate 			error = B_TRUE;
22227c478bd9Sstevel@tonic-gate 			status = IBMF_BAD_RMPP_OPT;
22237c478bd9Sstevel@tonic-gate 			goto bail;
22247c478bd9Sstevel@tonic-gate 		}
22257c478bd9Sstevel@tonic-gate 
22267c478bd9Sstevel@tonic-gate 		/* for non-special QPs, check if QP supports RMPP traffic */
22277c478bd9Sstevel@tonic-gate 		if (ibmf_qp_handle != IBMF_QP_HANDLE_DEFAULT &&
22287c478bd9Sstevel@tonic-gate 		    (((ibmf_alt_qp_t *)ibmf_qp_handle)->isq_supports_rmpp ==
22297c478bd9Sstevel@tonic-gate 		    B_FALSE)) {
22307c478bd9Sstevel@tonic-gate 			IBMF_MSG_DECR_REFCNT(msgimplp);
22317c478bd9Sstevel@tonic-gate 			mutex_exit(&msgimplp->im_mutex);
22327c478bd9Sstevel@tonic-gate 			ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt);
22337c478bd9Sstevel@tonic-gate 			(void) sprintf(errmsg, "QP does not support RMPP");
22347c478bd9Sstevel@tonic-gate 			error = B_TRUE;
22357c478bd9Sstevel@tonic-gate 			status = IBMF_BAD_RMPP_OPT;
22367c478bd9Sstevel@tonic-gate 			goto bail;
22377c478bd9Sstevel@tonic-gate 		}
22387c478bd9Sstevel@tonic-gate 
22397c478bd9Sstevel@tonic-gate 		/* check if transaction is "double sided" (send and receive) */
22407c478bd9Sstevel@tonic-gate 		if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)
22417c478bd9Sstevel@tonic-gate 			isDS = 1;
22427c478bd9Sstevel@tonic-gate 
22437c478bd9Sstevel@tonic-gate 		status = ibmf_i_send_rmpp_pkts(clientp, ibmf_qp_handle,
22447c478bd9Sstevel@tonic-gate 		    msgimplp, isDS, blocking);
22457c478bd9Sstevel@tonic-gate 		if (status != IBMF_SUCCESS) {
22467c478bd9Sstevel@tonic-gate 			IBMF_MSG_DECR_REFCNT(msgimplp);
22477c478bd9Sstevel@tonic-gate 			mutex_exit(&msgimplp->im_mutex);
22487c478bd9Sstevel@tonic-gate 			ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt);
22497c478bd9Sstevel@tonic-gate 			(void) sprintf(errmsg, "RMPP packets send failed");
22507c478bd9Sstevel@tonic-gate 			error = B_TRUE;
22517c478bd9Sstevel@tonic-gate 			goto bail;
22527c478bd9Sstevel@tonic-gate 		}
22537c478bd9Sstevel@tonic-gate 	}
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate 	/*
22567c478bd9Sstevel@tonic-gate 	 * decrement the reference count so notify_client() can remove the
22577c478bd9Sstevel@tonic-gate 	 * message when it's ready
22587c478bd9Sstevel@tonic-gate 	 */
22597c478bd9Sstevel@tonic-gate 	IBMF_MSG_DECR_REFCNT(msgimplp);
22607c478bd9Sstevel@tonic-gate 
22617c478bd9Sstevel@tonic-gate 	/* check if the transaction is a blocking transaction */
22627c478bd9Sstevel@tonic-gate 	if (blocking && ((msgimplp->im_trans_state_flags &
22637c478bd9Sstevel@tonic-gate 	    IBMF_TRANS_STATE_FLAG_SIGNALED) == 0)) {
22647c478bd9Sstevel@tonic-gate 
22657c478bd9Sstevel@tonic-gate 		/* indicate that the tranaction is waiting */
22667c478bd9Sstevel@tonic-gate 		msgimplp->im_trans_state_flags |= IBMF_TRANS_STATE_FLAG_WAIT;
22677c478bd9Sstevel@tonic-gate 
22687c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
22697c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "",
22707c478bd9Sstevel@tonic-gate 		    "ibmf_i_msg_transport(): %s, msgp = 0x%p\n",
22717c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "blocking for completion",
22727c478bd9Sstevel@tonic-gate 		    tnf_opaque, msgimplp, msgimplp);
22737c478bd9Sstevel@tonic-gate 
22747c478bd9Sstevel@tonic-gate 		/* wait for transaction completion */
22757c478bd9Sstevel@tonic-gate 		cv_wait(&msgimplp->im_trans_cv, &msgimplp->im_mutex);
22767c478bd9Sstevel@tonic-gate 
22777c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
22787c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "",
22797c478bd9Sstevel@tonic-gate 		    "ibmf_i_msg_transport(): %s, msgp = 0x%p\n",
22807c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "unblocking for completion",
22817c478bd9Sstevel@tonic-gate 		    tnf_opaque, msgimplp, msgimplp);
22827c478bd9Sstevel@tonic-gate 
22837c478bd9Sstevel@tonic-gate 		/* clean up flags */
22847c478bd9Sstevel@tonic-gate 		msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_WAIT;
22857c478bd9Sstevel@tonic-gate 		msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
22867c478bd9Sstevel@tonic-gate 
22877c478bd9Sstevel@tonic-gate 		if (msgimplp->im_msg_status != IBMF_SUCCESS) {
22887c478bd9Sstevel@tonic-gate 
22897c478bd9Sstevel@tonic-gate 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
22907c478bd9Sstevel@tonic-gate 			    ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "",
22917c478bd9Sstevel@tonic-gate 			    "ibmf_i_msg_transport(): msg_status = %d\n",
22927c478bd9Sstevel@tonic-gate 			    tnf_uint, msgstatus, msgimplp->im_msg_status);
22937c478bd9Sstevel@tonic-gate 
22947c478bd9Sstevel@tonic-gate 			status = msgimplp->im_msg_status;
22957c478bd9Sstevel@tonic-gate 		}
22967c478bd9Sstevel@tonic-gate 	} else if (blocking && (msgimplp->im_trans_state_flags &
22977c478bd9Sstevel@tonic-gate 	    IBMF_TRANS_STATE_FLAG_SIGNALED)) {
22987c478bd9Sstevel@tonic-gate 		msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
22997c478bd9Sstevel@tonic-gate 
23007c478bd9Sstevel@tonic-gate 		if (msgimplp->im_msg_status != IBMF_SUCCESS) {
23017c478bd9Sstevel@tonic-gate 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
23027c478bd9Sstevel@tonic-gate 			    ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "",
23037c478bd9Sstevel@tonic-gate 			    "ibmf_i_msg_transport(): msg_status = %d\n",
23047c478bd9Sstevel@tonic-gate 			    tnf_uint, msgstatus, msgimplp->im_msg_status);
23057c478bd9Sstevel@tonic-gate 			status = msgimplp->im_msg_status;
23067c478bd9Sstevel@tonic-gate 		}
23077c478bd9Sstevel@tonic-gate 	}
23087c478bd9Sstevel@tonic-gate 
23097c478bd9Sstevel@tonic-gate 	msg_rp_unset_id = msg_tr_unset_id = 0;
23107c478bd9Sstevel@tonic-gate 	msg_rp_unset_id = msgimplp->im_rp_unset_timeout_id;
23117c478bd9Sstevel@tonic-gate 	msg_tr_unset_id = msgimplp->im_tr_unset_timeout_id;
23127c478bd9Sstevel@tonic-gate 	msgimplp->im_rp_unset_timeout_id = 0;
23137c478bd9Sstevel@tonic-gate 	msgimplp->im_tr_unset_timeout_id = 0;
23147c478bd9Sstevel@tonic-gate 
23157c478bd9Sstevel@tonic-gate 	mutex_exit(&msgimplp->im_mutex);
23167c478bd9Sstevel@tonic-gate 
23177c478bd9Sstevel@tonic-gate 	/* Unset the timers */
23187c478bd9Sstevel@tonic-gate 	if (msg_rp_unset_id != 0) {
23197c478bd9Sstevel@tonic-gate 		(void) untimeout(msg_rp_unset_id);
23207c478bd9Sstevel@tonic-gate 	}
23217c478bd9Sstevel@tonic-gate 
23227c478bd9Sstevel@tonic-gate 	if (msg_tr_unset_id != 0) {
23237c478bd9Sstevel@tonic-gate 		(void) untimeout(msg_tr_unset_id);
23247c478bd9Sstevel@tonic-gate 	}
23257c478bd9Sstevel@tonic-gate 
23267c478bd9Sstevel@tonic-gate 	/* increment kstats of the number of sent messages */
23277c478bd9Sstevel@tonic-gate 	mutex_enter(&clientp->ic_kstat_mutex);
23287c478bd9Sstevel@tonic-gate 	IBMF_ADD32_KSTATS(clientp, msgs_sent, 1);
23297c478bd9Sstevel@tonic-gate 	mutex_exit(&clientp->ic_kstat_mutex);
23307c478bd9Sstevel@tonic-gate 
23317c478bd9Sstevel@tonic-gate bail:
23327c478bd9Sstevel@tonic-gate 	if (error) {
23337c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
23347c478bd9Sstevel@tonic-gate 		    ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "",
23357c478bd9Sstevel@tonic-gate 		    "ibmf_i_msg_transport(): %s, msgp = 0x%p\n",
23367c478bd9Sstevel@tonic-gate 		    tnf_string, msg, errmsg, tnf_opaque, msgimplp, msgimplp);
23377c478bd9Sstevel@tonic-gate 	}
23387c478bd9Sstevel@tonic-gate 
23397c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,	ibmf_i_msg_transport_end,
23407c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_msg_transport() exit, status = %d\n",
23417c478bd9Sstevel@tonic-gate 	    tnf_uint, status, status);
23427c478bd9Sstevel@tonic-gate 
23437c478bd9Sstevel@tonic-gate 	return (status);
23447c478bd9Sstevel@tonic-gate }
23457c478bd9Sstevel@tonic-gate 
23467c478bd9Sstevel@tonic-gate /*
23477c478bd9Sstevel@tonic-gate  * ibmf_i_init_msg():
23487c478bd9Sstevel@tonic-gate  *	Initialize the message fields
23497c478bd9Sstevel@tonic-gate  */
23507c478bd9Sstevel@tonic-gate void
ibmf_i_init_msg(ibmf_msg_impl_t * msgimplp,ibmf_msg_cb_t trans_cb,void * trans_cb_arg,ibmf_retrans_t * retrans,boolean_t block)23517c478bd9Sstevel@tonic-gate ibmf_i_init_msg(ibmf_msg_impl_t *msgimplp, ibmf_msg_cb_t trans_cb,
23527c478bd9Sstevel@tonic-gate     void *trans_cb_arg, ibmf_retrans_t *retrans, boolean_t block)
23537c478bd9Sstevel@tonic-gate {
23547c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_msg_start,
23557c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_msg() enter\n");
23567c478bd9Sstevel@tonic-gate 
23577c478bd9Sstevel@tonic-gate 	_NOTE(ASSUMING_PROTECTED(msgimplp->im_trans_cb,
23587c478bd9Sstevel@tonic-gate 	    msgimplp->im_trans_cb_arg))
23597c478bd9Sstevel@tonic-gate 
23607c478bd9Sstevel@tonic-gate 	if (block == B_TRUE)
23617c478bd9Sstevel@tonic-gate 		msgimplp->im_msg_flags |= IBMF_MSG_FLAGS_BLOCKING;
23627c478bd9Sstevel@tonic-gate 	msgimplp->im_trans_cb = trans_cb;
23637c478bd9Sstevel@tonic-gate 	msgimplp->im_trans_cb_arg = trans_cb_arg;
23647c478bd9Sstevel@tonic-gate 
2365d0141297Ssandipb 	bzero(&msgimplp->im_retrans, sizeof (ibmf_retrans_t));
23667c478bd9Sstevel@tonic-gate 	if (retrans != NULL) {
23677c478bd9Sstevel@tonic-gate 		bcopy((void *)retrans, (void *)&msgimplp->im_retrans,
23687c478bd9Sstevel@tonic-gate 		    sizeof (ibmf_retrans_t));
23697c478bd9Sstevel@tonic-gate 	}
23707c478bd9Sstevel@tonic-gate 
23717c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_msg_end,
23727c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_init_msg() exit\n");
23737c478bd9Sstevel@tonic-gate }
23747c478bd9Sstevel@tonic-gate 
23757c478bd9Sstevel@tonic-gate /*
23767c478bd9Sstevel@tonic-gate  * ibmf_i_alloc_qp():
23777c478bd9Sstevel@tonic-gate  *	Allocate a QP context for the alternate QPs
23787c478bd9Sstevel@tonic-gate  */
23797c478bd9Sstevel@tonic-gate int
ibmf_i_alloc_qp(ibmf_client_t * clientp,ib_pkey_t p_key,ib_qkey_t q_key,uint_t flags,ibmf_qp_handle_t * ibmf_qp_handlep)23807c478bd9Sstevel@tonic-gate ibmf_i_alloc_qp(ibmf_client_t *clientp, ib_pkey_t p_key, ib_qkey_t q_key,
23817c478bd9Sstevel@tonic-gate     uint_t flags, ibmf_qp_handle_t *ibmf_qp_handlep)
23827c478bd9Sstevel@tonic-gate {
23837c478bd9Sstevel@tonic-gate 	ibmf_ci_t		*ibmf_cip = clientp->ic_myci;
23847c478bd9Sstevel@tonic-gate 	ibt_qp_alloc_attr_t	qp_attrs;
23857c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		qp_modify_attr;
23867c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t		*qp_ctx;
23877c478bd9Sstevel@tonic-gate 	uint16_t		pkey_ix;
23887c478bd9Sstevel@tonic-gate 	ibt_status_t		ibt_status;
23897c478bd9Sstevel@tonic-gate 	int			i, blocking;
23907c478bd9Sstevel@tonic-gate 	boolean_t		error = B_FALSE;
23917c478bd9Sstevel@tonic-gate 	int			status = IBMF_SUCCESS;
23927c478bd9Sstevel@tonic-gate 	char			errmsg[128];
23937c478bd9Sstevel@tonic-gate 
23947c478bd9Sstevel@tonic-gate 
23957c478bd9Sstevel@tonic-gate 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
23967c478bd9Sstevel@tonic-gate 	    ibmf_i_alloc_qp_start, IBMF_TNF_TRACE, "",
23977c478bd9Sstevel@tonic-gate 	    "ibmf_i_alloc_qp() enter, clientp = %p, pkey = %x, qkey = %x \n",
23987c478bd9Sstevel@tonic-gate 	    tnf_opaque, clientp, clientp, tnf_uint, p_key, p_key,
23997c478bd9Sstevel@tonic-gate 	    tnf_uint, q_key, q_key);
24007c478bd9Sstevel@tonic-gate 
24017c478bd9Sstevel@tonic-gate 	/*
24027c478bd9Sstevel@tonic-gate 	 * get the pkey index associated with this pkey if present in table
24037c478bd9Sstevel@tonic-gate 	 */
24047c478bd9Sstevel@tonic-gate 	if (ibmf_i_get_pkeyix(clientp->ic_ci_handle, p_key,
24057c478bd9Sstevel@tonic-gate 	    clientp->ic_client_info.port_num, &pkey_ix) != IBMF_SUCCESS) {
24067c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "pkey not in table, pkey = %x", p_key);
24077c478bd9Sstevel@tonic-gate 		error = B_TRUE;
24087c478bd9Sstevel@tonic-gate 		status = IBMF_FAILURE;
24097c478bd9Sstevel@tonic-gate 		goto bail;
24107c478bd9Sstevel@tonic-gate 	}
24117c478bd9Sstevel@tonic-gate 
24127c478bd9Sstevel@tonic-gate 	/* allocate QP context memory */
24137c478bd9Sstevel@tonic-gate 	qp_ctx = (ibmf_alt_qp_t *)kmem_zalloc(sizeof (ibmf_alt_qp_t),
24147c478bd9Sstevel@tonic-gate 	    (flags & IBMF_ALLOC_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
24157c478bd9Sstevel@tonic-gate 	if (qp_ctx == NULL) {
24167c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "failed to kmem_zalloc qp ctx");
24177c478bd9Sstevel@tonic-gate 		error = B_TRUE;
24187c478bd9Sstevel@tonic-gate 		status = IBMF_NO_RESOURCES;
24197c478bd9Sstevel@tonic-gate 		goto bail;
24207c478bd9Sstevel@tonic-gate 	}
24217c478bd9Sstevel@tonic-gate 
24227c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qp_ctx));
24237c478bd9Sstevel@tonic-gate 
24247c478bd9Sstevel@tonic-gate 	/* setup the qp attrs for the alloc call */
24257c478bd9Sstevel@tonic-gate 	qp_attrs.qp_scq_hdl = ibmf_cip->ci_alt_cq_handle;
24267c478bd9Sstevel@tonic-gate 	qp_attrs.qp_rcq_hdl = ibmf_cip->ci_alt_cq_handle;
24277c478bd9Sstevel@tonic-gate 	qp_attrs.qp_pd_hdl = ibmf_cip->ci_pd;
24287c478bd9Sstevel@tonic-gate 	qp_attrs.qp_sizes.cs_sq_sgl = IBMF_MAX_SQ_WR_SGL_ELEMENTS;
24297c478bd9Sstevel@tonic-gate 	qp_attrs.qp_sizes.cs_rq_sgl = IBMF_MAX_RQ_WR_SGL_ELEMENTS;
24307c478bd9Sstevel@tonic-gate 	qp_attrs.qp_sizes.cs_sq = ibmf_send_wqes_posted_per_qp;
24317c478bd9Sstevel@tonic-gate 	qp_attrs.qp_sizes.cs_rq = ibmf_recv_wqes_posted_per_qp;
24327c478bd9Sstevel@tonic-gate 	qp_attrs.qp_flags = IBT_ALL_SIGNALED;
24337c478bd9Sstevel@tonic-gate 	qp_attrs.qp_alloc_flags = IBT_QP_NO_FLAGS;
24347c478bd9Sstevel@tonic-gate 
24357c478bd9Sstevel@tonic-gate 	/* request IBT for a qp with the desired attributes */
24367c478bd9Sstevel@tonic-gate 	ibt_status = ibt_alloc_qp(clientp->ic_ci_handle, IBT_UD_RQP,
24377c478bd9Sstevel@tonic-gate 	    &qp_attrs, &qp_ctx->isq_qp_sizes, &qp_ctx->isq_qpn,
24387c478bd9Sstevel@tonic-gate 	    &qp_ctx->isq_qp_handle);
24397c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
24407c478bd9Sstevel@tonic-gate 		kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t));
24417c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "failed to alloc qp, status = %d",
24427c478bd9Sstevel@tonic-gate 		    ibt_status);
24437c478bd9Sstevel@tonic-gate 		error = B_TRUE;
24447c478bd9Sstevel@tonic-gate 		status = IBMF_NO_RESOURCES;
24457c478bd9Sstevel@tonic-gate 		goto bail;
24467c478bd9Sstevel@tonic-gate 	}
24477c478bd9Sstevel@tonic-gate 
24487c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_trans = IBT_UD_SRV;
24497c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
24507c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_transport.ud.ud_qkey = q_key;
24517c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
24527c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_transport.ud.ud_pkey_ix = pkey_ix;
24537c478bd9Sstevel@tonic-gate 	qp_modify_attr.qp_transport.ud.ud_port =
24547c478bd9Sstevel@tonic-gate 	    clientp->ic_client_info.port_num;
24557c478bd9Sstevel@tonic-gate 
24567c478bd9Sstevel@tonic-gate 	/* Set up the client handle in the QP context */
24577c478bd9Sstevel@tonic-gate 	qp_ctx->isq_client_hdl = clientp;
24587c478bd9Sstevel@tonic-gate 
24597c478bd9Sstevel@tonic-gate 	/* call the IB transport to initialize the QP */
24607c478bd9Sstevel@tonic-gate 	ibt_status = ibt_initialize_qp(qp_ctx->isq_qp_handle, &qp_modify_attr);
24617c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
24627c478bd9Sstevel@tonic-gate 		(void) ibt_free_qp(qp_ctx->isq_qp_handle);
24637c478bd9Sstevel@tonic-gate 		kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t));
24647c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "failed to initialize qp, status = %d",
24657c478bd9Sstevel@tonic-gate 		    ibt_status);
24667c478bd9Sstevel@tonic-gate 		error = B_TRUE;
24677c478bd9Sstevel@tonic-gate 		status = IBMF_NO_RESOURCES;
24687c478bd9Sstevel@tonic-gate 		goto bail;
24697c478bd9Sstevel@tonic-gate 	}
24707c478bd9Sstevel@tonic-gate 
24717c478bd9Sstevel@tonic-gate 	/* Set up the WQE caches */
24727c478bd9Sstevel@tonic-gate 	status = ibmf_i_init_altqp_wqes(qp_ctx);
24737c478bd9Sstevel@tonic-gate 	if (status != IBMF_SUCCESS) {
24747c478bd9Sstevel@tonic-gate 		(void) ibt_free_qp(qp_ctx->isq_qp_handle);
24757c478bd9Sstevel@tonic-gate 		kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t));
24767c478bd9Sstevel@tonic-gate 		(void) sprintf(errmsg, "failed to init wqe caches, status = %d",
24777c478bd9Sstevel@tonic-gate 		    status);
24787c478bd9Sstevel@tonic-gate 		error = B_TRUE;
24797c478bd9Sstevel@tonic-gate 		goto bail;
24807c478bd9Sstevel@tonic-gate 	}
24817c478bd9Sstevel@tonic-gate 
24827c478bd9Sstevel@tonic-gate 	qp_ctx->isq_next = NULL;
24837c478bd9Sstevel@tonic-gate 	qp_ctx->isq_pkey = p_key;
24847c478bd9Sstevel@tonic-gate 	qp_ctx->isq_qkey = q_key;
24857c478bd9Sstevel@tonic-gate 	qp_ctx->isq_port_num = clientp->ic_client_info.port_num;
24867c478bd9Sstevel@tonic-gate 	mutex_init(&qp_ctx->isq_mutex, NULL, MUTEX_DRIVER, NULL);
24877c478bd9Sstevel@tonic-gate 	mutex_init(&qp_ctx->isq_wqe_mutex, NULL, MUTEX_DRIVER, NULL);
24887c478bd9Sstevel@tonic-gate 	cv_init(&qp_ctx->isq_recv_cb_teardown_cv, NULL, CV_DRIVER, NULL);
24897c478bd9Sstevel@tonic-gate 	cv_init(&qp_ctx->isq_sqd_cv, NULL, CV_DRIVER, NULL);
24907c478bd9Sstevel@tonic-gate 	cv_init(&qp_ctx->isq_wqes_cv, NULL, CV_DRIVER, NULL);
24917c478bd9Sstevel@tonic-gate 
24927c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*qp_ctx));
24937c478bd9Sstevel@tonic-gate 
24947c478bd9Sstevel@tonic-gate 	/* add alt qp to the list in CI context */
24957c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
24967c478bd9Sstevel@tonic-gate 	if (ibmf_cip->ci_alt_qp_list == NULL) {
24977c478bd9Sstevel@tonic-gate 		ibmf_cip->ci_alt_qp_list = qp_ctx;
24987c478bd9Sstevel@tonic-gate 	} else {
24997c478bd9Sstevel@tonic-gate 		ibmf_alt_qp_t *qpp;
25007c478bd9Sstevel@tonic-gate 
25017c478bd9Sstevel@tonic-gate 		qpp = ibmf_cip->ci_alt_qp_list;
25027c478bd9Sstevel@tonic-gate 		while (qpp->isq_next != NULL) {
25037c478bd9Sstevel@tonic-gate 			qpp = qpp->isq_next;
25047c478bd9Sstevel@tonic-gate 		}
25057c478bd9Sstevel@tonic-gate 		qpp->isq_next = qp_ctx;
25067c478bd9Sstevel@tonic-gate 	}
25077c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
25087c478bd9Sstevel@tonic-gate 
25097c478bd9Sstevel@tonic-gate 	*ibmf_qp_handlep = (ibmf_qp_handle_t)qp_ctx;
25107c478bd9Sstevel@tonic-gate 
25117c478bd9Sstevel@tonic-gate 	if (flags & IBMF_ALLOC_SLEEP)
25127c478bd9Sstevel@tonic-gate 		blocking = 1;
25137c478bd9Sstevel@tonic-gate 	else
25147c478bd9Sstevel@tonic-gate 		blocking = 0;
25157c478bd9Sstevel@tonic-gate 
25167c478bd9Sstevel@tonic-gate 	/* post the max number of buffers to RQ */
25177c478bd9Sstevel@tonic-gate 	for (i = 0; i < ibmf_recv_wqes_per_port; i++) {
25187c478bd9Sstevel@tonic-gate 		status = ibmf_i_post_recv_buffer(ibmf_cip, clientp->ic_qp,
25197c478bd9Sstevel@tonic-gate 		    blocking, *ibmf_qp_handlep);
25207c478bd9Sstevel@tonic-gate 		if (status != IBMF_SUCCESS) {
25217c478bd9Sstevel@tonic-gate 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
25227c478bd9Sstevel@tonic-gate 			    ibmf_i_alloc_qp, IBMF_TNF_TRACE, "",
25237c478bd9Sstevel@tonic-gate 			    "ibmf_i_alloc_qp(): %s, status = %d\n",
25247c478bd9Sstevel@tonic-gate 			    tnf_string, msg, "ibmf_i_post_recv_buffer() failed",
25257c478bd9Sstevel@tonic-gate 			    tnf_int, status, status);
25267c478bd9Sstevel@tonic-gate 		}
25277c478bd9Sstevel@tonic-gate 	}
25287c478bd9Sstevel@tonic-gate 
25297c478bd9Sstevel@tonic-gate 	mutex_enter(&clientp->ic_kstat_mutex);
25307c478bd9Sstevel@tonic-gate 	IBMF_ADD32_KSTATS(clientp, alt_qps_alloced, 1);
25317c478bd9Sstevel@tonic-gate 	mutex_exit(&clientp->ic_kstat_mutex);
25327c478bd9Sstevel@tonic-gate 
25337c478bd9Sstevel@tonic-gate bail:
25347c478bd9Sstevel@tonic-gate 	if (error) {
25357c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
25367c478bd9Sstevel@tonic-gate 		    ibmf_i_alloc_qp_err, IBMF_TNF_TRACE, "",
25377c478bd9Sstevel@tonic-gate 		    "ibmf_i_alloc_qp(): %s\n", tnf_string, msg, errmsg);
25387c478bd9Sstevel@tonic-gate 	}
25397c478bd9Sstevel@tonic-gate 
25407c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_qp_end,
25417c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_alloc_qp() exit, qp = %p\n",
25427c478bd9Sstevel@tonic-gate 	    tnf_opaque, qp_handlep, *ibmf_qp_handlep);
25437c478bd9Sstevel@tonic-gate 	return (status);
25447c478bd9Sstevel@tonic-gate }
25457c478bd9Sstevel@tonic-gate 
25467c478bd9Sstevel@tonic-gate /*
25477c478bd9Sstevel@tonic-gate  * ibmf_i_free_qp():
25487c478bd9Sstevel@tonic-gate  *	Free an alternate QP context
25497c478bd9Sstevel@tonic-gate  */
25507c478bd9Sstevel@tonic-gate /* ARGSUSED */
25517c478bd9Sstevel@tonic-gate int
ibmf_i_free_qp(ibmf_qp_handle_t ibmf_qp_handle,uint_t flags)25527c478bd9Sstevel@tonic-gate ibmf_i_free_qp(ibmf_qp_handle_t ibmf_qp_handle, uint_t flags)
25537c478bd9Sstevel@tonic-gate {
25547c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t		*qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
25557c478bd9Sstevel@tonic-gate 	ibmf_client_t		*clientp = qp_ctx->isq_client_hdl;
25567c478bd9Sstevel@tonic-gate 	ibmf_ci_t		*ibmf_cip = qp_ctx->isq_client_hdl->ic_myci;
25577c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t		*qpp, *pqpp;
25587c478bd9Sstevel@tonic-gate 	ibt_status_t		ibt_status;
25597c478bd9Sstevel@tonic-gate 
25607c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
25617c478bd9Sstevel@tonic-gate 	    ibmf_i_free_qp_start, IBMF_TNF_TRACE, "",
25627c478bd9Sstevel@tonic-gate 	    "ibmf_i_free_qp() enter, qp_hdl = %p, flags = %x\n",
25637c478bd9Sstevel@tonic-gate 	    tnf_opaque, qp_hdl, ibmf_qp_handle, tnf_uint, flags, flags);
25647c478bd9Sstevel@tonic-gate 
25657c478bd9Sstevel@tonic-gate 	/* remove qp from the list in CI context */
25667c478bd9Sstevel@tonic-gate 
25677c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
25687c478bd9Sstevel@tonic-gate 	qpp = ibmf_cip->ci_alt_qp_list;
25697c478bd9Sstevel@tonic-gate 	ASSERT(qpp != NULL);
25707c478bd9Sstevel@tonic-gate 	if (qpp == qp_ctx) {
25717c478bd9Sstevel@tonic-gate 		ibmf_cip->ci_alt_qp_list = qpp->isq_next;
25727c478bd9Sstevel@tonic-gate 	} else {
25737c478bd9Sstevel@tonic-gate 		while (qpp != NULL) {
25747c478bd9Sstevel@tonic-gate 			if (qpp == qp_ctx)
25757c478bd9Sstevel@tonic-gate 				break;
25767c478bd9Sstevel@tonic-gate 			pqpp = qpp;
25777c478bd9Sstevel@tonic-gate 			qpp = qpp->isq_next;
25787c478bd9Sstevel@tonic-gate 		}
25797c478bd9Sstevel@tonic-gate 		ASSERT(qpp != NULL);
25807c478bd9Sstevel@tonic-gate 		pqpp->isq_next = qpp->isq_next;
25817c478bd9Sstevel@tonic-gate 	}
25827c478bd9Sstevel@tonic-gate 
25837c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
25847c478bd9Sstevel@tonic-gate 
25857c478bd9Sstevel@tonic-gate 	/* flush the WQEs in the QP queues */
25867c478bd9Sstevel@tonic-gate 	ibt_status = ibt_flush_qp(qp_ctx->isq_qp_handle);
25877c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
25887c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
25897c478bd9Sstevel@tonic-gate 		    ibmf_i_free_qp_err, IBMF_TNF_TRACE, "",
25907c478bd9Sstevel@tonic-gate 		    "ibmf_i_free_qp(): %s, status = %d\n",
25917c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "failed to close qp",
25927c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, ibt_status);
25937c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end,
25947c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n");
25957c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
25967c478bd9Sstevel@tonic-gate 	}
25977c478bd9Sstevel@tonic-gate 
25987c478bd9Sstevel@tonic-gate 	/* Call the MAD completion handler */
25997c478bd9Sstevel@tonic-gate 	ibmf_i_mad_completions(ibmf_cip->ci_alt_cq_handle, (void*)ibmf_cip);
26007c478bd9Sstevel@tonic-gate 
26017c478bd9Sstevel@tonic-gate 	/* Wait here for all WQE owned by this QP to get freed */
26027c478bd9Sstevel@tonic-gate 	mutex_enter(&qpp->isq_mutex);
26037c478bd9Sstevel@tonic-gate 	while (qpp->isq_wqes_alloced != 0) {
26047c478bd9Sstevel@tonic-gate 		cv_wait(&qpp->isq_wqes_cv, &qpp->isq_mutex);
26057c478bd9Sstevel@tonic-gate 	}
26067c478bd9Sstevel@tonic-gate 	mutex_exit(&qpp->isq_mutex);
26077c478bd9Sstevel@tonic-gate 
26087c478bd9Sstevel@tonic-gate 	cv_destroy(&qp_ctx->isq_recv_cb_teardown_cv);
26097c478bd9Sstevel@tonic-gate 	cv_destroy(&qp_ctx->isq_sqd_cv);
26107c478bd9Sstevel@tonic-gate 	cv_destroy(&qp_ctx->isq_wqes_cv);
26117c478bd9Sstevel@tonic-gate 
26127c478bd9Sstevel@tonic-gate 	/* call the IB transport to free the QP */
26137c478bd9Sstevel@tonic-gate 	ibt_status = ibt_free_qp(qp_ctx->isq_qp_handle);
26147c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
26157c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
26167c478bd9Sstevel@tonic-gate 		    ibmf_i_free_qp_err, IBMF_TNF_TRACE, "",
26177c478bd9Sstevel@tonic-gate 		    "ibmf_i_free_qp(): %s, status = %d\n",
26187c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "failed to free qp",
26197c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, ibt_status);
26207c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end,
26217c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n");
26227c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
26237c478bd9Sstevel@tonic-gate 	}
26247c478bd9Sstevel@tonic-gate 
26257c478bd9Sstevel@tonic-gate 	/* Clean up the WQE caches */
26267c478bd9Sstevel@tonic-gate 	ibmf_i_fini_altqp_wqes(qp_ctx);
26277c478bd9Sstevel@tonic-gate 	mutex_destroy(&qp_ctx->isq_wqe_mutex);
26287c478bd9Sstevel@tonic-gate 	mutex_destroy(&qp_ctx->isq_mutex);
26297c478bd9Sstevel@tonic-gate 
26307c478bd9Sstevel@tonic-gate 	mutex_enter(&clientp->ic_kstat_mutex);
26317c478bd9Sstevel@tonic-gate 	IBMF_SUB32_KSTATS(clientp, alt_qps_alloced, 1);
26327c478bd9Sstevel@tonic-gate 	mutex_exit(&clientp->ic_kstat_mutex);
26337c478bd9Sstevel@tonic-gate 
26347c478bd9Sstevel@tonic-gate 	kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t));
26357c478bd9Sstevel@tonic-gate 
26367c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end,
26377c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n");
26387c478bd9Sstevel@tonic-gate 
26397c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
26407c478bd9Sstevel@tonic-gate }
26417c478bd9Sstevel@tonic-gate 
26427c478bd9Sstevel@tonic-gate /*
26437c478bd9Sstevel@tonic-gate  * ibmf_i_query_qp():
26447c478bd9Sstevel@tonic-gate  *	Query an alternate QP context
26457c478bd9Sstevel@tonic-gate  */
26467c478bd9Sstevel@tonic-gate /* ARGSUSED */
26477c478bd9Sstevel@tonic-gate int
ibmf_i_query_qp(ibmf_qp_handle_t ibmf_qp_handle,uint_t flags,uint_t * qp_nump,ib_pkey_t * p_keyp,ib_qkey_t * q_keyp,uint8_t * portnump)26487c478bd9Sstevel@tonic-gate ibmf_i_query_qp(ibmf_qp_handle_t ibmf_qp_handle, uint_t flags,
26497c478bd9Sstevel@tonic-gate     uint_t *qp_nump, ib_pkey_t *p_keyp, ib_qkey_t *q_keyp, uint8_t *portnump)
26507c478bd9Sstevel@tonic-gate {
26517c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_query;
26527c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t		*qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
26537c478bd9Sstevel@tonic-gate 	uint16_t		pkey_ix;
26547c478bd9Sstevel@tonic-gate 	ibt_status_t		ibt_status;
26557c478bd9Sstevel@tonic-gate 
26567c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
26577c478bd9Sstevel@tonic-gate 	    ibmf_i_free_qp_start, IBMF_TNF_TRACE, "",
26587c478bd9Sstevel@tonic-gate 	    "ibmf_i_free_qp() enter, qp_hdl = %p, flags = %x\n",
26597c478bd9Sstevel@tonic-gate 	    tnf_opaque, qp_hdl, ibmf_qp_handle, tnf_uint, flags, flags);
26607c478bd9Sstevel@tonic-gate 
26617c478bd9Sstevel@tonic-gate 	ibt_status = ibt_query_qp(qp_ctx->isq_qp_handle, &qp_query);
26627c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
26637c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
26647c478bd9Sstevel@tonic-gate 		    ibmf_i_query_qp_err, IBMF_TNF_TRACE, "",
26657c478bd9Sstevel@tonic-gate 		    "ibmf_i_query_qp(): %s, status = %d\n",
26667c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "failed to query qp",
26677c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, ibt_status);
26687c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end,
26697c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit\n");
26707c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
26717c478bd9Sstevel@tonic-gate 	}
26727c478bd9Sstevel@tonic-gate 
26737c478bd9Sstevel@tonic-gate 	/* move the desired attributes into the locations provided */
26747c478bd9Sstevel@tonic-gate 	*qp_nump = qp_query.qp_qpn;
26757c478bd9Sstevel@tonic-gate 	*q_keyp = qp_query.qp_info.qp_transport.ud.ud_qkey;
26767c478bd9Sstevel@tonic-gate 	*portnump = qp_query.qp_info.qp_transport.ud.ud_port;
26777c478bd9Sstevel@tonic-gate 
26787c478bd9Sstevel@tonic-gate 	pkey_ix = qp_query.qp_info.qp_transport.ud.ud_pkey_ix;
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 	/* get the pkey based on the pkey_ix */
26817c478bd9Sstevel@tonic-gate 	ibt_status = ibt_index2pkey(qp_ctx->isq_client_hdl->ic_ci_handle,
26827c478bd9Sstevel@tonic-gate 	    *portnump, pkey_ix, p_keyp);
26837c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
26847c478bd9Sstevel@tonic-gate 		IBMF_TRACE_3(IBMF_TNF_NODEBUG, DPRINT_L1,
26857c478bd9Sstevel@tonic-gate 		    ibmf_i_query_qp_err, IBMF_TNF_TRACE, "",
26867c478bd9Sstevel@tonic-gate 		    "ibmf_i_query_qp(): %s, pkey_ix = %d, status = %d\n",
26877c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "failed to get pkey from index",
26887c478bd9Sstevel@tonic-gate 		    tnf_uint, pkey_ix, pkey_ix,
26897c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, ibt_status);
26907c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end,
26917c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit\n");
26927c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
26937c478bd9Sstevel@tonic-gate 	}
26947c478bd9Sstevel@tonic-gate 
26957c478bd9Sstevel@tonic-gate 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end,
26967c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit, qp_num = 0x%x, "
26977c478bd9Sstevel@tonic-gate 	    "pkey = 0x%x, qkey = 0x%x, portnum = %d\n",
26987c478bd9Sstevel@tonic-gate 	    tnf_uint, qp_num, *qp_nump, tnf_uint, pkey, *p_keyp,
26997c478bd9Sstevel@tonic-gate 	    tnf_uint, qkey, *q_keyp, tnf_uint, portnum, *portnump);
27007c478bd9Sstevel@tonic-gate 
27017c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
27027c478bd9Sstevel@tonic-gate }
27037c478bd9Sstevel@tonic-gate 
27047c478bd9Sstevel@tonic-gate /*
27057c478bd9Sstevel@tonic-gate  * ibmf_i_modify_qp():
27067c478bd9Sstevel@tonic-gate  *	Modify an alternate QP context
27077c478bd9Sstevel@tonic-gate  */
27087c478bd9Sstevel@tonic-gate /* ARGSUSED */
27097c478bd9Sstevel@tonic-gate int
ibmf_i_modify_qp(ibmf_qp_handle_t ibmf_qp_handle,ib_pkey_t p_key,ib_qkey_t q_key,uint_t flags)27107c478bd9Sstevel@tonic-gate ibmf_i_modify_qp(ibmf_qp_handle_t ibmf_qp_handle, ib_pkey_t p_key,
27117c478bd9Sstevel@tonic-gate     ib_qkey_t q_key, uint_t flags)
27127c478bd9Sstevel@tonic-gate {
27137c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t		*qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
27147c478bd9Sstevel@tonic-gate 	ibmf_client_t		*clientp = qp_ctx->isq_client_hdl;
27157c478bd9Sstevel@tonic-gate 	ibmf_ci_t		*ibmf_cip = clientp->ic_myci;
27167c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t		*qpp;
27177c478bd9Sstevel@tonic-gate 	ibt_qp_info_t		qp_mod;
27187c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t	qp_mod_flags;
27197c478bd9Sstevel@tonic-gate 	ibt_queue_sizes_t	actual_sz;
27207c478bd9Sstevel@tonic-gate 	uint16_t		pkey_ix;
27217c478bd9Sstevel@tonic-gate 	ibt_status_t		ibt_status;
27227c478bd9Sstevel@tonic-gate 
27237c478bd9Sstevel@tonic-gate 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
27247c478bd9Sstevel@tonic-gate 	    ibmf_i_modify_qp_start, IBMF_TNF_TRACE, "",
27257c478bd9Sstevel@tonic-gate 	    "ibmf_i_modify_qp() enter, qp_hdl = %p, flags = %x, pkey = 0x%x, "
27267c478bd9Sstevel@tonic-gate 	    "qkey = 0x%x\n", tnf_opaque, qp_hdl, ibmf_qp_handle,
27277c478bd9Sstevel@tonic-gate 	    tnf_uint, flags, flags, tnf_uint, p_key, p_key,
27287c478bd9Sstevel@tonic-gate 	    tnf_uint, q_key, q_key);
27297c478bd9Sstevel@tonic-gate 
27307c478bd9Sstevel@tonic-gate 	/*
27317c478bd9Sstevel@tonic-gate 	 * get the pkey index associated with this pkey if present in table
27327c478bd9Sstevel@tonic-gate 	 */
27337c478bd9Sstevel@tonic-gate 	if (ibmf_i_get_pkeyix(clientp->ic_ci_handle, p_key,
27347c478bd9Sstevel@tonic-gate 	    clientp->ic_client_info.port_num, &pkey_ix) != IBMF_SUCCESS) {
27357c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
27367c478bd9Sstevel@tonic-gate 		    ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "",
27377c478bd9Sstevel@tonic-gate 		    "ibmf_i_modify_qp(): %s, pkey = %x\n",
27387c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "pkey not in table",
27397c478bd9Sstevel@tonic-gate 		    tnf_uint, pkey, p_key);
27407c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
27417c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
27427c478bd9Sstevel@tonic-gate 		return (IBMF_FAILURE);
27437c478bd9Sstevel@tonic-gate 	}
27447c478bd9Sstevel@tonic-gate 
27457c478bd9Sstevel@tonic-gate 	/* Find the QP context in the CI QP context list */
27467c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_mutex);
27477c478bd9Sstevel@tonic-gate 	qpp = ibmf_cip->ci_alt_qp_list;
27487c478bd9Sstevel@tonic-gate 	while (qpp != NULL) {
27497c478bd9Sstevel@tonic-gate 		if (qpp == qp_ctx) {
27507c478bd9Sstevel@tonic-gate 			break;
27517c478bd9Sstevel@tonic-gate 		}
27527c478bd9Sstevel@tonic-gate 		qpp = qpp->isq_next;
27537c478bd9Sstevel@tonic-gate 	}
27547c478bd9Sstevel@tonic-gate 
27557c478bd9Sstevel@tonic-gate 	if (qpp == NULL) {
27567c478bd9Sstevel@tonic-gate 		mutex_exit(&ibmf_cip->ci_mutex);
27577c478bd9Sstevel@tonic-gate 
27587c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
27597c478bd9Sstevel@tonic-gate 		    ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "",
27607c478bd9Sstevel@tonic-gate 		    "ibmf_i_modify_qp(): %s\n",
27617c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "QP not in altqp list");
27627c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
27637c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
27647c478bd9Sstevel@tonic-gate 		return (IBMF_BAD_QP_HANDLE);
27657c478bd9Sstevel@tonic-gate 
27667c478bd9Sstevel@tonic-gate 	} else {
27677c478bd9Sstevel@tonic-gate 
27687c478bd9Sstevel@tonic-gate 		mutex_enter(&qp_ctx->isq_mutex);
27697c478bd9Sstevel@tonic-gate 	}
27707c478bd9Sstevel@tonic-gate 
27717c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_mutex);
27727c478bd9Sstevel@tonic-gate 
27737c478bd9Sstevel@tonic-gate 	/*
27747c478bd9Sstevel@tonic-gate 	 * Transition the QP to SQD state
27757c478bd9Sstevel@tonic-gate 	 */
27767c478bd9Sstevel@tonic-gate 	bzero(&qp_mod, sizeof (ibt_qp_info_t));
27777c478bd9Sstevel@tonic-gate 	qp_mod.qp_trans = IBT_UD_SRV;
27787c478bd9Sstevel@tonic-gate 	qp_mod.qp_state = IBT_STATE_SQD;
27797c478bd9Sstevel@tonic-gate 	qp_mod_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_SQD_EVENT;
27807c478bd9Sstevel@tonic-gate 	ibt_status = ibt_modify_qp(qp_ctx->isq_qp_handle, qp_mod_flags,
27817c478bd9Sstevel@tonic-gate 	    &qp_mod, &actual_sz);
27827c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
27837c478bd9Sstevel@tonic-gate 		mutex_exit(&qp_ctx->isq_mutex);
27847c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
27857c478bd9Sstevel@tonic-gate 		    ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "",
27867c478bd9Sstevel@tonic-gate 		    "ibmf_i_modify_qp(): %s, qp_hdl = %p\n",
27877c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "QP transition RTS to SQD failed",
27887c478bd9Sstevel@tonic-gate 		    tnf_opaque, qp_handle, qp_ctx->isq_qp_handle);
27897c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
27907c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
27917c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
27927c478bd9Sstevel@tonic-gate 	}
27937c478bd9Sstevel@tonic-gate 
27947c478bd9Sstevel@tonic-gate 	/*
27957c478bd9Sstevel@tonic-gate 	 * Wait for an event indicating that the QP is in SQD state
27967c478bd9Sstevel@tonic-gate 	 */
27977c478bd9Sstevel@tonic-gate 	cv_wait(&qp_ctx->isq_sqd_cv, &qp_ctx->isq_mutex);
27987c478bd9Sstevel@tonic-gate 
27997c478bd9Sstevel@tonic-gate 	/* Setup QP modification information for transition to RTS state */
28007c478bd9Sstevel@tonic-gate 	bzero(&qp_mod, sizeof (ibt_qp_info_t));
28017c478bd9Sstevel@tonic-gate 	qp_mod.qp_trans = IBT_UD_SRV;
28027c478bd9Sstevel@tonic-gate 	qp_mod.qp_state = IBT_STATE_RTS;
28037c478bd9Sstevel@tonic-gate 	qp_mod.qp_current_state = IBT_STATE_SQD;
28047c478bd9Sstevel@tonic-gate 	qp_mod.qp_transport.ud.ud_pkey_ix = pkey_ix;
28057c478bd9Sstevel@tonic-gate 	qp_mod.qp_transport.ud.ud_qkey = q_key;
28067c478bd9Sstevel@tonic-gate 	qp_mod_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PKEY_IX |
28077c478bd9Sstevel@tonic-gate 	    IBT_CEP_SET_QKEY;
28087c478bd9Sstevel@tonic-gate 
28097c478bd9Sstevel@tonic-gate 	/*
28107c478bd9Sstevel@tonic-gate 	 * transition the QP back to RTS state to allow
28117c478bd9Sstevel@tonic-gate 	 * modification of the pkey and qkey
28127c478bd9Sstevel@tonic-gate 	 */
28137c478bd9Sstevel@tonic-gate 
28147c478bd9Sstevel@tonic-gate 	ibt_status = ibt_modify_qp(qp_ctx->isq_qp_handle, qp_mod_flags,
28157c478bd9Sstevel@tonic-gate 	    &qp_mod, &actual_sz);
28167c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
28177c478bd9Sstevel@tonic-gate 		mutex_exit(&qp_ctx->isq_mutex);
28187c478bd9Sstevel@tonic-gate 		IBMF_TRACE_3(IBMF_TNF_NODEBUG, DPRINT_L1,
28197c478bd9Sstevel@tonic-gate 		    ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "",
28207c478bd9Sstevel@tonic-gate 		    "ibmf_i_modify_qp(): %s, qp_hdl = %p, status = %d\n",
28217c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "QP transition SQD to RTS failed",
28227c478bd9Sstevel@tonic-gate 		    tnf_opaque, qp_handle, qp_ctx->isq_qp_handle,
28237c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, ibt_status);
28247c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
28257c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
28267c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
28277c478bd9Sstevel@tonic-gate 	}
28287c478bd9Sstevel@tonic-gate 
28297c478bd9Sstevel@tonic-gate 	qp_ctx->isq_pkey = p_key;
28307c478bd9Sstevel@tonic-gate 	qp_ctx->isq_qkey = q_key;
28317c478bd9Sstevel@tonic-gate 	mutex_exit(&qp_ctx->isq_mutex);
28327c478bd9Sstevel@tonic-gate 
28337c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
28347c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
28357c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
28367c478bd9Sstevel@tonic-gate }
28377c478bd9Sstevel@tonic-gate 
28387c478bd9Sstevel@tonic-gate /*
28397c478bd9Sstevel@tonic-gate  * ibmf_i_post_recv_buffer():
28407c478bd9Sstevel@tonic-gate  *	Post a WQE to the RQ of the specified QP
28417c478bd9Sstevel@tonic-gate  */
28427c478bd9Sstevel@tonic-gate int
ibmf_i_post_recv_buffer(ibmf_ci_t * cip,ibmf_qp_t * qpp,boolean_t block,ibmf_qp_handle_t ibmf_qp_handle)28437c478bd9Sstevel@tonic-gate ibmf_i_post_recv_buffer(ibmf_ci_t *cip, ibmf_qp_t *qpp, boolean_t block,
28447c478bd9Sstevel@tonic-gate     ibmf_qp_handle_t ibmf_qp_handle)
28457c478bd9Sstevel@tonic-gate {
28467c478bd9Sstevel@tonic-gate 	int			ret;
28477c478bd9Sstevel@tonic-gate 	ibt_wr_ds_t		*sgl;
28487c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
28497c478bd9Sstevel@tonic-gate 	ibmf_recv_wqe_t		*recv_wqep;
28507c478bd9Sstevel@tonic-gate 	ibt_qp_hdl_t		ibt_qp_handle;
28517c478bd9Sstevel@tonic-gate 	struct kmem_cache	*kmem_cachep;
28527c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t		*altqp;
28537c478bd9Sstevel@tonic-gate 
28547c478bd9Sstevel@tonic-gate 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
28557c478bd9Sstevel@tonic-gate 	    ibmf_i_post_recv_buffer_start, IBMF_TNF_TRACE, "",
28567c478bd9Sstevel@tonic-gate 	    "ibmf_i_post_recv_buffer() enter, cip = %p, qpp = %p, "
28577c478bd9Sstevel@tonic-gate 	    "qp_hdl = %p, block = %d\n", tnf_opaque, cip, cip,
28587c478bd9Sstevel@tonic-gate 	    tnf_opaque, qpp, qpp, tnf_opaque, qp_hdl, ibmf_qp_handle,
28597c478bd9Sstevel@tonic-gate 	    tnf_uint, block, block);
28607c478bd9Sstevel@tonic-gate 
28617c478bd9Sstevel@tonic-gate 	/*
28627c478bd9Sstevel@tonic-gate 	 * if we haven't hit the max wqes per qp, attempt to allocate a recv
28637c478bd9Sstevel@tonic-gate 	 * wqe and post it to the recv queue.
28647c478bd9Sstevel@tonic-gate 	 * It is possible for more than one thread to get through this
28657c478bd9Sstevel@tonic-gate 	 * check below and post wqes that could push us above the
28667c478bd9Sstevel@tonic-gate 	 * ibmf_recv_wqes_posted_per_qp. We catch that case when the recv
28677c478bd9Sstevel@tonic-gate 	 * completion is signaled.
28687c478bd9Sstevel@tonic-gate 	 */
28697c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
28707c478bd9Sstevel@tonic-gate 
28717c478bd9Sstevel@tonic-gate 	/* Get the WQE kmem cache pointer based on the QP type */
28727c478bd9Sstevel@tonic-gate 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT)
28737c478bd9Sstevel@tonic-gate 		kmem_cachep = cip->ci_recv_wqes_cache;
28747c478bd9Sstevel@tonic-gate 	else {
28757c478bd9Sstevel@tonic-gate 		altqp = (ibmf_alt_qp_t *)ibmf_qp_handle;
28767c478bd9Sstevel@tonic-gate 		kmem_cachep = altqp->isq_recv_wqes_cache;
28777c478bd9Sstevel@tonic-gate 	}
28787c478bd9Sstevel@tonic-gate 
28797c478bd9Sstevel@tonic-gate 	/* allocate a receive WQE from the receive WQE kmem cache */
28807c478bd9Sstevel@tonic-gate 	recv_wqep = kmem_cache_alloc(kmem_cachep,
28817c478bd9Sstevel@tonic-gate 	    (block == B_TRUE ? KM_SLEEP : KM_NOSLEEP));
28827c478bd9Sstevel@tonic-gate 	if (recv_wqep == NULL) {
28837c478bd9Sstevel@tonic-gate 		/*
28847c478bd9Sstevel@tonic-gate 		 * Attempt to extend the cache and then retry the
28857c478bd9Sstevel@tonic-gate 		 * kmem_cache_alloc()
28867c478bd9Sstevel@tonic-gate 		 */
28877c478bd9Sstevel@tonic-gate 		if (ibmf_i_extend_wqe_cache(cip, ibmf_qp_handle, block) ==
28887c478bd9Sstevel@tonic-gate 		    IBMF_NO_RESOURCES) {
28897c478bd9Sstevel@tonic-gate 			mutex_enter(&cip->ci_mutex);
28907c478bd9Sstevel@tonic-gate 			IBMF_ADD32_PORT_KSTATS(cip, rwqe_allocs_failed, 1);
28917c478bd9Sstevel@tonic-gate 			mutex_exit(&cip->ci_mutex);
28927c478bd9Sstevel@tonic-gate 			IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
28937c478bd9Sstevel@tonic-gate 			    ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "",
28947c478bd9Sstevel@tonic-gate 			    "ibmf_i_post_recv_buffer(): %s, status = %d\n",
28957c478bd9Sstevel@tonic-gate 			    tnf_string, msg, "alloc recv_wqe failed",
28967c478bd9Sstevel@tonic-gate 			    tnf_int, ibmf_status, IBMF_NO_RESOURCES);
28977c478bd9Sstevel@tonic-gate 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
28987c478bd9Sstevel@tonic-gate 			    ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "",
28997c478bd9Sstevel@tonic-gate 			    "ibmf_i_post_recv_buffer() exit\n");
29007c478bd9Sstevel@tonic-gate 			return (IBMF_NO_RESOURCES);
29017c478bd9Sstevel@tonic-gate 		} else {
29027c478bd9Sstevel@tonic-gate 			recv_wqep = kmem_cache_alloc(kmem_cachep,
29037c478bd9Sstevel@tonic-gate 			    (block == B_TRUE ? KM_SLEEP : KM_NOSLEEP));
29047c478bd9Sstevel@tonic-gate 			if (recv_wqep == NULL) {
29057c478bd9Sstevel@tonic-gate 				/* Allocation failed again. Give up here. */
29067c478bd9Sstevel@tonic-gate 				mutex_enter(&cip->ci_mutex);
29077c478bd9Sstevel@tonic-gate 				IBMF_ADD32_PORT_KSTATS(cip, rwqe_allocs_failed,
29087c478bd9Sstevel@tonic-gate 				    1);
29097c478bd9Sstevel@tonic-gate 				mutex_exit(&cip->ci_mutex);
29107c478bd9Sstevel@tonic-gate 				IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
29117c478bd9Sstevel@tonic-gate 				    ibmf_i_post_recv_buffer_err,
29127c478bd9Sstevel@tonic-gate 				    IBMF_TNF_ERROR, "",
29137c478bd9Sstevel@tonic-gate 				    "ibmf_i_post_recv_buffer(): %s, "
29147c478bd9Sstevel@tonic-gate 				    "status = %d\n",
29157c478bd9Sstevel@tonic-gate 				    tnf_string, msg, "alloc recv_wqe failed",
29167c478bd9Sstevel@tonic-gate 				    tnf_int, ibmf_status, IBMF_NO_RESOURCES);
29177c478bd9Sstevel@tonic-gate 				IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
29187c478bd9Sstevel@tonic-gate 				    ibmf_i_post_recv_buffer_end,
29197c478bd9Sstevel@tonic-gate 				    IBMF_TNF_TRACE, "",
29207c478bd9Sstevel@tonic-gate 				    "ibmf_i_post_recv_buffer() exit\n");
29217c478bd9Sstevel@tonic-gate 				return (IBMF_NO_RESOURCES);
29227c478bd9Sstevel@tonic-gate 			}
29237c478bd9Sstevel@tonic-gate 		}
29247c478bd9Sstevel@tonic-gate 	}
29257c478bd9Sstevel@tonic-gate 
29267c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqep))
29277c478bd9Sstevel@tonic-gate 
29287c478bd9Sstevel@tonic-gate 	/*
29297c478bd9Sstevel@tonic-gate 	 * if the qp handle provided in ibmf_send_pkt() or
29307c478bd9Sstevel@tonic-gate 	 * ibmf_setup_recv_cb() is not the default qp handle
29317c478bd9Sstevel@tonic-gate 	 * for this client, then the wqe must be queued on this qp,
29327c478bd9Sstevel@tonic-gate 	 * else use the default qp handle set up during ibmf_register()
29337c478bd9Sstevel@tonic-gate 	 */
29347c478bd9Sstevel@tonic-gate 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
29357c478bd9Sstevel@tonic-gate 		ibt_qp_handle = qpp->iq_qp_handle;
29367c478bd9Sstevel@tonic-gate 	} else {
29377c478bd9Sstevel@tonic-gate 		ibt_qp_handle =
29387c478bd9Sstevel@tonic-gate 		    ((ibmf_alt_qp_t *)ibmf_qp_handle)->isq_qp_handle;
29397c478bd9Sstevel@tonic-gate 	}
29407c478bd9Sstevel@tonic-gate 
29417c478bd9Sstevel@tonic-gate 	/* allocate memory for the scatter-gather list */
29427c478bd9Sstevel@tonic-gate 	sgl = kmem_zalloc(IBMF_MAX_RQ_WR_SGL_ELEMENTS * sizeof (ibt_wr_ds_t),
29437c478bd9Sstevel@tonic-gate 	    (block == B_TRUE) ? KM_SLEEP : KM_NOSLEEP);
29447c478bd9Sstevel@tonic-gate 	if (sgl == NULL) {
29457c478bd9Sstevel@tonic-gate 		kmem_cache_free(kmem_cachep, recv_wqep);
29467c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
29477c478bd9Sstevel@tonic-gate 		    ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "",
29487c478bd9Sstevel@tonic-gate 		    "ibmf_i_post_recv_buffer(): %s\n",
29497c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "failed to kmem_zalloc qp ctx");
29507c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
29517c478bd9Sstevel@tonic-gate 		    ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "",
29527c478bd9Sstevel@tonic-gate 		    "ibmf_i_post_recv_buffer() exit\n");
29537c478bd9Sstevel@tonic-gate 		return (IBMF_NO_RESOURCES);
29547c478bd9Sstevel@tonic-gate 	}
29557c478bd9Sstevel@tonic-gate 
29567c478bd9Sstevel@tonic-gate 	/* initialize it */
29577c478bd9Sstevel@tonic-gate 	ibmf_i_init_recv_wqe(qpp, sgl, recv_wqep, ibt_qp_handle,
29587c478bd9Sstevel@tonic-gate 	    ibmf_qp_handle);
29597c478bd9Sstevel@tonic-gate 
29607c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*recv_wqep))
29617c478bd9Sstevel@tonic-gate 
29627c478bd9Sstevel@tonic-gate 	/* and post it */
29637c478bd9Sstevel@tonic-gate 	status = ibt_post_recv(recv_wqep->recv_qp_handle, &recv_wqep->recv_wr,
29647c478bd9Sstevel@tonic-gate 	    1, NULL);
29657c478bd9Sstevel@tonic-gate 
29667c478bd9Sstevel@tonic-gate 	ret = ibmf_i_ibt_to_ibmf_status(status);
29677c478bd9Sstevel@tonic-gate 	if (ret != IBMF_SUCCESS) {
29687c478bd9Sstevel@tonic-gate 		kmem_free(sgl, IBMF_MAX_RQ_WR_SGL_ELEMENTS *
29697c478bd9Sstevel@tonic-gate 		    sizeof (ibt_wr_ds_t));
29707c478bd9Sstevel@tonic-gate 		kmem_cache_free(kmem_cachep, recv_wqep);
29717c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
29727c478bd9Sstevel@tonic-gate 		    ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "",
29737c478bd9Sstevel@tonic-gate 		    "ibmf_i_post_recv_buffer(): %s, status = %d\n",
29747c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "ibt_post_recv failed",
29757c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, status);
29767c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
29777c478bd9Sstevel@tonic-gate 		    ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "",
29787c478bd9Sstevel@tonic-gate 		    "ibmf_i_post_recv_buffer() exit\n");
29797c478bd9Sstevel@tonic-gate 		return (ret);
29807c478bd9Sstevel@tonic-gate 	}
29817c478bd9Sstevel@tonic-gate 
29827c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
29837c478bd9Sstevel@tonic-gate 	IBMF_ADD32_PORT_KSTATS(cip, recv_wqes_alloced, 1);
29847c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
29857c478bd9Sstevel@tonic-gate 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
29867c478bd9Sstevel@tonic-gate 		mutex_enter(&qpp->iq_mutex);
29877c478bd9Sstevel@tonic-gate 		qpp->iq_rwqes_posted++;
29887c478bd9Sstevel@tonic-gate 		mutex_exit(&qpp->iq_mutex);
29897c478bd9Sstevel@tonic-gate 		mutex_enter(&cip->ci_mutex);
29907c478bd9Sstevel@tonic-gate 		cip->ci_wqes_alloced++;
29917c478bd9Sstevel@tonic-gate 		mutex_exit(&cip->ci_mutex);
29927c478bd9Sstevel@tonic-gate 	} else {
29937c478bd9Sstevel@tonic-gate 		mutex_enter(&altqp->isq_mutex);
29947c478bd9Sstevel@tonic-gate 		altqp->isq_wqes_alloced++;
29957c478bd9Sstevel@tonic-gate 		altqp->isq_rwqes_posted++;
29967c478bd9Sstevel@tonic-gate 		mutex_exit(&altqp->isq_mutex);
29977c478bd9Sstevel@tonic-gate 	}
29987c478bd9Sstevel@tonic-gate 
29997c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_post_recv_buffer_end,
30007c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_post_recv_buffer() exit\n");
30017c478bd9Sstevel@tonic-gate 
30027c478bd9Sstevel@tonic-gate 	return (ret);
30037c478bd9Sstevel@tonic-gate }
30047c478bd9Sstevel@tonic-gate 
30057c478bd9Sstevel@tonic-gate /*
30067c478bd9Sstevel@tonic-gate  * ibmf_i_mgt_class_to_hdr_sz_off():
30077c478bd9Sstevel@tonic-gate  *	Determine class header offser and size for management classes
30087c478bd9Sstevel@tonic-gate  */
30097c478bd9Sstevel@tonic-gate void
ibmf_i_mgt_class_to_hdr_sz_off(uint32_t mgt_class,uint32_t * szp,uint32_t * offp)30107c478bd9Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off(uint32_t mgt_class, uint32_t *szp,
30117c478bd9Sstevel@tonic-gate     uint32_t *offp)
30127c478bd9Sstevel@tonic-gate {
30137c478bd9Sstevel@tonic-gate 	uint32_t	hdr_sz = 0, hdr_off = 0;
30147c478bd9Sstevel@tonic-gate 
30157c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
30167c478bd9Sstevel@tonic-gate 	    ibmf_i_mgt_class_to_hdr_sz_off_start, IBMF_TNF_TRACE, "",
30177c478bd9Sstevel@tonic-gate 	    "ibmf_i_mgt_class_to_hdr_sz_off(): mgt_class = 0x%x\n",
30187c478bd9Sstevel@tonic-gate 	    tnf_uint, mgt_class, mgt_class);
30197c478bd9Sstevel@tonic-gate 
30207c478bd9Sstevel@tonic-gate 	switch (mgt_class) {
30217c478bd9Sstevel@tonic-gate 	case MAD_MGMT_CLASS_SUBN_LID_ROUTED :
30227c478bd9Sstevel@tonic-gate 	case MAD_MGMT_CLASS_SUBN_DIRECT_ROUTE :
30237c478bd9Sstevel@tonic-gate 	case MAD_MGMT_CLASS_PERF :
30247c478bd9Sstevel@tonic-gate 	case MAD_MGMT_CLASS_BM :
30257c478bd9Sstevel@tonic-gate 	case MAD_MGMT_CLASS_DEV_MGT :
30267c478bd9Sstevel@tonic-gate 	case MAD_MGMT_CLASS_SNMP :
3027*448bf859SLida.Horn 	case MAD_MGMT_CLASS_COMM_MGT:
30287c478bd9Sstevel@tonic-gate 		hdr_sz = IBMF_MAD_CL_HDR_SZ_1;
30297c478bd9Sstevel@tonic-gate 		hdr_off = IBMF_MAD_CL_HDR_OFF_1;
30307c478bd9Sstevel@tonic-gate 		break;
30317c478bd9Sstevel@tonic-gate 	case MAD_MGMT_CLASS_SUBN_ADM :
30327c478bd9Sstevel@tonic-gate 		hdr_sz = IBMF_MAD_CL_HDR_SZ_2;
30337c478bd9Sstevel@tonic-gate 		hdr_off = IBMF_MAD_CL_HDR_OFF_2;
30347c478bd9Sstevel@tonic-gate 		break;
3035*448bf859SLida.Horn 	default:
3036*448bf859SLida.Horn 		if (((mgt_class >= MAD_MGMT_CLASS_VENDOR_START) &&
3037*448bf859SLida.Horn 		    (mgt_class <= MAD_MGMT_CLASS_VENDOR_END)) ||
3038*448bf859SLida.Horn 		    ((mgt_class >= MAD_MGMT_CLASS_APPLICATION_START) &&
3039*448bf859SLida.Horn 		    (mgt_class <= MAD_MGMT_CLASS_APPLICATION_END))) {
3040*448bf859SLida.Horn 			hdr_sz = IBMF_MAD_CL_HDR_SZ_3;
3041*448bf859SLida.Horn 			hdr_off = IBMF_MAD_CL_HDR_OFF_1;
3042*448bf859SLida.Horn 		} else if ((mgt_class >= MAD_MGMT_CLASS_VENDOR2_START) &&
3043*448bf859SLida.Horn 		    (mgt_class <= MAD_MGMT_CLASS_VENDOR2_END)) {
3044*448bf859SLida.Horn 			hdr_sz = IBMF_MAD_CL_HDR_SZ_4;
3045*448bf859SLida.Horn 			hdr_off = IBMF_MAD_CL_HDR_OFF_2;
3046*448bf859SLida.Horn 		} else {
3047*448bf859SLida.Horn 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
3048*448bf859SLida.Horn 			    ibmf_i_mgt_class_to_hdr_sz_off_start,
3049*448bf859SLida.Horn 			    IBMF_TNF_TRACE, "",
3050*448bf859SLida.Horn 			    "ibmf_i_mgt_class_to_hdr_sz_off():"
3051*448bf859SLida.Horn 			    "got illegal management class = 0x%x\n",
3052*448bf859SLida.Horn 			    tnf_uint, mgt_class, mgt_class);
3053*448bf859SLida.Horn 		}
3054*448bf859SLida.Horn 		break;
30557c478bd9Sstevel@tonic-gate 	}
30567c478bd9Sstevel@tonic-gate 
30577c478bd9Sstevel@tonic-gate 
30587c478bd9Sstevel@tonic-gate 
30597c478bd9Sstevel@tonic-gate 	*szp = hdr_sz;
30607c478bd9Sstevel@tonic-gate 	*offp = hdr_off;
30617c478bd9Sstevel@tonic-gate 
30627c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
30637c478bd9Sstevel@tonic-gate 	    ibmf_i_mgt_class_to_hdr_sz_off_end, IBMF_TNF_TRACE, "",
30647c478bd9Sstevel@tonic-gate 	    "ibmf_i_mgt_class_to_hdr_sz_off() exit,hdr_sz = %d, hdr_off = %d\n",
30657c478bd9Sstevel@tonic-gate 	    tnf_uint, hdr_sz, hdr_sz, tnf_uint, hdr_off, hdr_off);
30667c478bd9Sstevel@tonic-gate }
30677c478bd9Sstevel@tonic-gate 
30687c478bd9Sstevel@tonic-gate /*
30697c478bd9Sstevel@tonic-gate  * ibmf_i_lookup_client_by_mgmt_class():
30707c478bd9Sstevel@tonic-gate  *	Lookup the client context based on the management class of
30717c478bd9Sstevel@tonic-gate  *	the incoming packet
30727c478bd9Sstevel@tonic-gate  */
30737c478bd9Sstevel@tonic-gate int
ibmf_i_lookup_client_by_mgmt_class(ibmf_ci_t * ibmf_cip,int port_num,ibmf_client_type_t class,ibmf_client_t ** clientpp)30747c478bd9Sstevel@tonic-gate ibmf_i_lookup_client_by_mgmt_class(ibmf_ci_t *ibmf_cip, int port_num,
30757c478bd9Sstevel@tonic-gate     ibmf_client_type_t class, ibmf_client_t **clientpp)
30767c478bd9Sstevel@tonic-gate {
30777c478bd9Sstevel@tonic-gate 	ibmf_client_t 		*clientp;
30787c478bd9Sstevel@tonic-gate 	ibmf_client_info_t	*client_infop;
30797c478bd9Sstevel@tonic-gate 
30807c478bd9Sstevel@tonic-gate 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
30817c478bd9Sstevel@tonic-gate 	    ibmf_i_lookup_client_by_mgmt_class_start, IBMF_TNF_TRACE, "",
30827c478bd9Sstevel@tonic-gate 	    "ibmf_i_lookup_client_by_mgmt_class() enter, cip = %p, "
30837c478bd9Sstevel@tonic-gate 	    "port_num = %d, class = 0x%x\n", tnf_opaque, cip, ibmf_cip,
30847c478bd9Sstevel@tonic-gate 	    tnf_int, port, port_num, tnf_opaque, class, class);
30857c478bd9Sstevel@tonic-gate 
30867c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex));
30877c478bd9Sstevel@tonic-gate 
30887c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_cip->ci_clients_mutex);
30897c478bd9Sstevel@tonic-gate 
30907c478bd9Sstevel@tonic-gate 	clientp = ibmf_cip->ci_clients;
30917c478bd9Sstevel@tonic-gate 
30927c478bd9Sstevel@tonic-gate 	/* walk client context list looking for class/portnum match */
30937c478bd9Sstevel@tonic-gate 	while (clientp != NULL) {
30947c478bd9Sstevel@tonic-gate 		client_infop = &clientp->ic_client_info;
30957c478bd9Sstevel@tonic-gate 		if (class == client_infop->client_class &&
30967c478bd9Sstevel@tonic-gate 		    port_num == client_infop->port_num) {
30977c478bd9Sstevel@tonic-gate 			/* found our match */
30987c478bd9Sstevel@tonic-gate 			break;
30997c478bd9Sstevel@tonic-gate 		}
31007c478bd9Sstevel@tonic-gate 		clientp = clientp->ic_next;
31017c478bd9Sstevel@tonic-gate 	}
31027c478bd9Sstevel@tonic-gate 
31037c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_cip->ci_clients_mutex);
31047c478bd9Sstevel@tonic-gate 
31057c478bd9Sstevel@tonic-gate 	if (clientp != NULL) {
31067c478bd9Sstevel@tonic-gate 		*clientpp = clientp;
31077c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
31087c478bd9Sstevel@tonic-gate 		    ibmf_i_lookup_client_by_mgmt_class_end, IBMF_TNF_TRACE, "",
31097c478bd9Sstevel@tonic-gate 		    "ibmf_i_lookup_client_by_mgmt_class() exit, clp = %p\n",
31107c478bd9Sstevel@tonic-gate 		    tnf_opaque, clientp, clientp);
31117c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
31127c478bd9Sstevel@tonic-gate 	} else {
31137c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
31147c478bd9Sstevel@tonic-gate 		    ibmf_i_lookup_client_by_mgmt_class_end, IBMF_TNF_TRACE, "",
31157c478bd9Sstevel@tonic-gate 		    "ibmf_i_lookup_client_by_mgmt_class() failure exit\n");
31167c478bd9Sstevel@tonic-gate 		return (IBMF_FAILURE);
31177c478bd9Sstevel@tonic-gate 	}
31187c478bd9Sstevel@tonic-gate }
31197c478bd9Sstevel@tonic-gate 
31207c478bd9Sstevel@tonic-gate /*
31217c478bd9Sstevel@tonic-gate  * ibmf_i_get_pkeyix():
31227c478bd9Sstevel@tonic-gate  *	Get the pkey index of the pkey in the pkey table of the specified
31237c478bd9Sstevel@tonic-gate  *	port. Take into account the partition membership.
31247c478bd9Sstevel@tonic-gate  */
31257c478bd9Sstevel@tonic-gate int
ibmf_i_get_pkeyix(ibt_hca_hdl_t hca_handle,ib_pkey_t pkey,uint8_t port,ib_pkey_t * pkeyixp)31267c478bd9Sstevel@tonic-gate ibmf_i_get_pkeyix(ibt_hca_hdl_t hca_handle, ib_pkey_t pkey, uint8_t port,
31277c478bd9Sstevel@tonic-gate     ib_pkey_t *pkeyixp)
31287c478bd9Sstevel@tonic-gate {
31297c478bd9Sstevel@tonic-gate 	ib_pkey_t		tpkey;
31307c478bd9Sstevel@tonic-gate 	ibt_status_t		ibt_status;
31317c478bd9Sstevel@tonic-gate 
31327c478bd9Sstevel@tonic-gate 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_start,
31337c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix() enter, hcahdl = %p, "
31347c478bd9Sstevel@tonic-gate 	    "pkey = 0x%x, port = %d\n", tnf_opaque, hcahdl, hca_handle,
31357c478bd9Sstevel@tonic-gate 	    tnf_int, pkey, pkey, tnf_int, port, port);
31367c478bd9Sstevel@tonic-gate 
31377c478bd9Sstevel@tonic-gate 	/*
31387c478bd9Sstevel@tonic-gate 	 * If the client specifies the FULL membership pkey and the
31397c478bd9Sstevel@tonic-gate 	 * pkey is not in the table, this function should fail.
31407c478bd9Sstevel@tonic-gate 	 */
31417c478bd9Sstevel@tonic-gate 	if (pkey & IBMF_PKEY_MEMBERSHIP_MASK) {
31427c478bd9Sstevel@tonic-gate 		ibt_status = ibt_pkey2index(hca_handle, port,
31437c478bd9Sstevel@tonic-gate 		    pkey, pkeyixp);
31447c478bd9Sstevel@tonic-gate 		if (ibt_status != IBT_SUCCESS) {
31457c478bd9Sstevel@tonic-gate 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
31467c478bd9Sstevel@tonic-gate 			    ibmf_i_get_pkeyix_err, IBMF_TNF_ERROR, "",
31477c478bd9Sstevel@tonic-gate 			    "ibmf_i_get_pkeyix() error status = %d\n",
31487c478bd9Sstevel@tonic-gate 			    tnf_uint, ibt_status, ibt_status);
31497c478bd9Sstevel@tonic-gate 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
31507c478bd9Sstevel@tonic-gate 			    ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "",
31517c478bd9Sstevel@tonic-gate 			    "ibmf_i_get_pkeyix() exit\n");
31527c478bd9Sstevel@tonic-gate 			return (IBMF_TRANSPORT_FAILURE);
31537c478bd9Sstevel@tonic-gate 		}
31547c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_end,
31557c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix() exit\n");
31567c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
31577c478bd9Sstevel@tonic-gate 	}
31587c478bd9Sstevel@tonic-gate 
31597c478bd9Sstevel@tonic-gate 	/*
31607c478bd9Sstevel@tonic-gate 	 * Limited member pkey processing
31617c478bd9Sstevel@tonic-gate 	 * Check if this limited member pkey is in the pkey table
31627c478bd9Sstevel@tonic-gate 	 */
31637c478bd9Sstevel@tonic-gate 	ibt_status = ibt_pkey2index(hca_handle, port, pkey, pkeyixp);
31647c478bd9Sstevel@tonic-gate 	if (ibt_status == IBT_SUCCESS) {
31657c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
31667c478bd9Sstevel@tonic-gate 		    ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "",
31677c478bd9Sstevel@tonic-gate 		    "ibmf_i_get_pkeyix() exit\n");
31687c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
31697c478bd9Sstevel@tonic-gate 	}
31707c478bd9Sstevel@tonic-gate 
31717c478bd9Sstevel@tonic-gate 	/*
31727c478bd9Sstevel@tonic-gate 	 * Could not find the limited member version of the pkey.
31737c478bd9Sstevel@tonic-gate 	 * Now check if the full member version of the pkey is in the
31747c478bd9Sstevel@tonic-gate 	 * pkey table. If not, fail the call.
31757c478bd9Sstevel@tonic-gate 	 */
31767c478bd9Sstevel@tonic-gate 	tpkey = pkey | IBMF_PKEY_MEMBERSHIP_MASK;
31777c478bd9Sstevel@tonic-gate 	ibt_status = ibt_pkey2index(hca_handle, port, tpkey, pkeyixp);
31787c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
31797c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
31807c478bd9Sstevel@tonic-gate 		    ibmf_i_get_pkeyix_err, IBMF_TNF_ERROR, "",
31817c478bd9Sstevel@tonic-gate 		    "ibmf_i_get_pkeyix() error status = %d\n",
31827c478bd9Sstevel@tonic-gate 		    tnf_uint, ibt_status, ibt_status);
31837c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
31847c478bd9Sstevel@tonic-gate 		    ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "",
31857c478bd9Sstevel@tonic-gate 		    "ibmf_i_get_pkeyix() exit\n");
31867c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
31877c478bd9Sstevel@tonic-gate 	}
31887c478bd9Sstevel@tonic-gate 
31897c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_end,
31907c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix(): pkey_ix = %d\n",
31917c478bd9Sstevel@tonic-gate 	    tnf_int, pkeyix, *pkeyixp);
31927c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
31937c478bd9Sstevel@tonic-gate }
31947c478bd9Sstevel@tonic-gate 
31957c478bd9Sstevel@tonic-gate /*
31967c478bd9Sstevel@tonic-gate  * ibmf_i_pkey_ix_to_key():
31977c478bd9Sstevel@tonic-gate  *	Figure out pkey from pkey index
31987c478bd9Sstevel@tonic-gate  */
31997c478bd9Sstevel@tonic-gate int
ibmf_i_pkey_ix_to_key(ibmf_ci_t * cip,uint_t port_num,uint_t pkey_ix,ib_pkey_t * pkeyp)32007c478bd9Sstevel@tonic-gate ibmf_i_pkey_ix_to_key(ibmf_ci_t *cip, uint_t port_num, uint_t pkey_ix,
32017c478bd9Sstevel@tonic-gate     ib_pkey_t *pkeyp)
32027c478bd9Sstevel@tonic-gate {
32037c478bd9Sstevel@tonic-gate 	ibt_status_t		ibt_status;
32047c478bd9Sstevel@tonic-gate 
32057c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_pkey_ix_to_key_start,
32067c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() enter\n");
32077c478bd9Sstevel@tonic-gate 
32087c478bd9Sstevel@tonic-gate 	ibt_status = ibt_index2pkey(cip->ci_ci_handle, port_num, pkey_ix,
32097c478bd9Sstevel@tonic-gate 	    pkeyp);
32107c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS) {
32117c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
32127c478bd9Sstevel@tonic-gate 		    ibmf_i_pkey_ix_to_key, IBMF_TNF_TRACE, "",
32137c478bd9Sstevel@tonic-gate 		    "ibmf_i_pkey_ix_to_key(): ibt_index2pkey failed for "
32147c478bd9Sstevel@tonic-gate 		    " pkey index %d \n", tnf_uint, pkey_ix, pkey_ix);
32157c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
32167c478bd9Sstevel@tonic-gate 		    ibmf_i_pkey_ix_to_key_end,
32177c478bd9Sstevel@tonic-gate 		    IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() exit\n");
32187c478bd9Sstevel@tonic-gate 		return (IBMF_TRANSPORT_FAILURE);
32197c478bd9Sstevel@tonic-gate 	}
32207c478bd9Sstevel@tonic-gate 
32217c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_pkey_ix_to_key_end,
32227c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() exit\n");
32237c478bd9Sstevel@tonic-gate 
32247c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
32257c478bd9Sstevel@tonic-gate }
32267c478bd9Sstevel@tonic-gate 
32277c478bd9Sstevel@tonic-gate /*
32287c478bd9Sstevel@tonic-gate  * ibmf_i_ibt_to_ibmf_status():
32297c478bd9Sstevel@tonic-gate  *	Map IBT return code to IBMF return code
32307c478bd9Sstevel@tonic-gate  */
32317c478bd9Sstevel@tonic-gate int
ibmf_i_ibt_to_ibmf_status(ibt_status_t ibt_status)32327c478bd9Sstevel@tonic-gate ibmf_i_ibt_to_ibmf_status(ibt_status_t ibt_status)
32337c478bd9Sstevel@tonic-gate {
32347c478bd9Sstevel@tonic-gate 	int ibmf_status;
32357c478bd9Sstevel@tonic-gate 
32367c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_ibt_to_ibmf_status_start,
32377c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_ibt_to_ibmf_status() enter, "
32387c478bd9Sstevel@tonic-gate 	    "status = %d\n", tnf_uint, ibt_status, ibt_status);
32397c478bd9Sstevel@tonic-gate 
32407c478bd9Sstevel@tonic-gate 	switch (ibt_status) {
32417c478bd9Sstevel@tonic-gate 
32427c478bd9Sstevel@tonic-gate 	case IBT_SUCCESS:
32437c478bd9Sstevel@tonic-gate 		ibmf_status = IBMF_SUCCESS;
32447c478bd9Sstevel@tonic-gate 		break;
32457c478bd9Sstevel@tonic-gate 
32467c478bd9Sstevel@tonic-gate 	case IBT_INSUFF_KERNEL_RESOURCE:
32477c478bd9Sstevel@tonic-gate 	case IBT_INSUFF_RESOURCE:
32487c478bd9Sstevel@tonic-gate 	case IBT_QP_FULL:
32497c478bd9Sstevel@tonic-gate 		ibmf_status = IBMF_NO_RESOURCES;
32507c478bd9Sstevel@tonic-gate 		break;
32517c478bd9Sstevel@tonic-gate 
32527c478bd9Sstevel@tonic-gate 	case IBT_HCA_IN_USE:
32537c478bd9Sstevel@tonic-gate 	case IBT_QP_IN_USE:
32547c478bd9Sstevel@tonic-gate 	case IBT_CQ_BUSY:
32557c478bd9Sstevel@tonic-gate 	case IBT_PD_IN_USE:
32567c478bd9Sstevel@tonic-gate 	case IBT_MR_IN_USE:
32577c478bd9Sstevel@tonic-gate 		ibmf_status = IBMF_BUSY;
32587c478bd9Sstevel@tonic-gate 		break;
32597c478bd9Sstevel@tonic-gate 
32607c478bd9Sstevel@tonic-gate 	default:
32617c478bd9Sstevel@tonic-gate 		ibmf_status = IBMF_FAILURE;
32627c478bd9Sstevel@tonic-gate 		break;
32637c478bd9Sstevel@tonic-gate 	}
32647c478bd9Sstevel@tonic-gate 
32657c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_ibt_to_ibmf_status_end,
32667c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_i_ibt_to_ibmf_status() exit, "
32677c478bd9Sstevel@tonic-gate 	    "ibt_status = %d, ibmf_status = %d\n", tnf_uint, ibt_status,
32687c478bd9Sstevel@tonic-gate 	    ibt_status, tnf_int, ibmf_status, ibmf_status);
32697c478bd9Sstevel@tonic-gate 
32707c478bd9Sstevel@tonic-gate 	return (ibmf_status);
32717c478bd9Sstevel@tonic-gate }
32727c478bd9Sstevel@tonic-gate 
32737c478bd9Sstevel@tonic-gate /*
32747c478bd9Sstevel@tonic-gate  * ibmf_i_ibt_wc_to_ibmf_status():
32757c478bd9Sstevel@tonic-gate  *	Map work completion code to IBMF return code
32767c478bd9Sstevel@tonic-gate  */
32777c478bd9Sstevel@tonic-gate int
ibmf_i_ibt_wc_to_ibmf_status(ibt_wc_status_t ibt_wc_status)32787c478bd9Sstevel@tonic-gate ibmf_i_ibt_wc_to_ibmf_status(ibt_wc_status_t ibt_wc_status)
32797c478bd9Sstevel@tonic-gate {
32807c478bd9Sstevel@tonic-gate 	int ibmf_status;
32817c478bd9Sstevel@tonic-gate 
32827c478bd9Sstevel@tonic-gate 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
32837c478bd9Sstevel@tonic-gate 	    ibmf_i_ibt_wc_to_ibmf_status_start, IBMF_TNF_TRACE, "",
32847c478bd9Sstevel@tonic-gate 	    "ibmf_i_ibt_to_ibmf_status() enter, status = %d\n",
32857c478bd9Sstevel@tonic-gate 	    tnf_uint, ibt_wc_status, ibt_wc_status);
32867c478bd9Sstevel@tonic-gate 
32877c478bd9Sstevel@tonic-gate 	switch (ibt_wc_status) {
32887c478bd9Sstevel@tonic-gate 
32897c478bd9Sstevel@tonic-gate 	case IBT_WC_SUCCESS:
32907c478bd9Sstevel@tonic-gate 		ibmf_status = IBMF_SUCCESS;
32917c478bd9Sstevel@tonic-gate 		break;
32927c478bd9Sstevel@tonic-gate 
32937c478bd9Sstevel@tonic-gate 	default:
32947c478bd9Sstevel@tonic-gate 		ibmf_status = IBMF_FAILURE;
32957c478bd9Sstevel@tonic-gate 		break;
32967c478bd9Sstevel@tonic-gate 	}
32977c478bd9Sstevel@tonic-gate 
32987c478bd9Sstevel@tonic-gate 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
32997c478bd9Sstevel@tonic-gate 	    ibmf_i_ibt_wc_to_ibmf_status_end, IBMF_TNF_TRACE, "",
33007c478bd9Sstevel@tonic-gate 	    "ibmf_i_ibt_to_ibmf_status() exit, wc_status = %d, "
33017c478bd9Sstevel@tonic-gate 	    "ibmf_status = %d\n", tnf_uint, ibt_wc_status,
33027c478bd9Sstevel@tonic-gate 	    ibt_wc_status, tnf_int, ibmf_status, ibmf_status);
33037c478bd9Sstevel@tonic-gate 
33047c478bd9Sstevel@tonic-gate 	return (ibmf_status);
33057c478bd9Sstevel@tonic-gate }
33067c478bd9Sstevel@tonic-gate 
33077c478bd9Sstevel@tonic-gate /*
33087c478bd9Sstevel@tonic-gate  * ibmf_i_is_ibmf_handle_valid():
33097c478bd9Sstevel@tonic-gate  *	Validate the ibmf handle
33107c478bd9Sstevel@tonic-gate  */
33117c478bd9Sstevel@tonic-gate int
ibmf_i_is_ibmf_handle_valid(ibmf_handle_t ibmf_handle)33127c478bd9Sstevel@tonic-gate ibmf_i_is_ibmf_handle_valid(ibmf_handle_t ibmf_handle)
33137c478bd9Sstevel@tonic-gate {
33147c478bd9Sstevel@tonic-gate 	ibmf_ci_t	*cip;
33157c478bd9Sstevel@tonic-gate 	ibmf_client_t	*clp, *clientp = (ibmf_client_t *)ibmf_handle;
33167c478bd9Sstevel@tonic-gate 
33177c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
33187c478bd9Sstevel@tonic-gate 	    ibmf_i_is_ibmf_handle_valid_start, IBMF_TNF_TRACE, "",
33197c478bd9Sstevel@tonic-gate 	    "ibmf_i_is_ibmf_handle_valid() enter\n");
33207c478bd9Sstevel@tonic-gate 
33217c478bd9Sstevel@tonic-gate 	mutex_enter(&ibmf_statep->ibmf_mutex);
33227c478bd9Sstevel@tonic-gate 
33237c478bd9Sstevel@tonic-gate 	cip = ibmf_statep->ibmf_ci_list;
33247c478bd9Sstevel@tonic-gate 
33257c478bd9Sstevel@tonic-gate 	/* iterate through all the channel interace contexts */
33267c478bd9Sstevel@tonic-gate 	while (cip != NULL) {
33277c478bd9Sstevel@tonic-gate 
33287c478bd9Sstevel@tonic-gate 		mutex_enter(&cip->ci_clients_mutex);
33297c478bd9Sstevel@tonic-gate 
33307c478bd9Sstevel@tonic-gate 		clp = cip->ci_clients;
33317c478bd9Sstevel@tonic-gate 
33327c478bd9Sstevel@tonic-gate 		/* search all registration contexts for this ci */
33337c478bd9Sstevel@tonic-gate 		while (clp != NULL) {
33347c478bd9Sstevel@tonic-gate 			if (clp == clientp)
33357c478bd9Sstevel@tonic-gate 				break;
33367c478bd9Sstevel@tonic-gate 			clp = clp->ic_next;
33377c478bd9Sstevel@tonic-gate 		}
33387c478bd9Sstevel@tonic-gate 
33397c478bd9Sstevel@tonic-gate 		mutex_exit(&cip->ci_clients_mutex);
33407c478bd9Sstevel@tonic-gate 
33417c478bd9Sstevel@tonic-gate 		if (clp == clientp) {
33427c478bd9Sstevel@tonic-gate 			/* ci found */
33437c478bd9Sstevel@tonic-gate 			break;
33447c478bd9Sstevel@tonic-gate 		} else {
33457c478bd9Sstevel@tonic-gate 			/* ci not found, move onto next ci */
33467c478bd9Sstevel@tonic-gate 			cip = cip->ci_next;
33477c478bd9Sstevel@tonic-gate 		}
33487c478bd9Sstevel@tonic-gate 	}
33497c478bd9Sstevel@tonic-gate 
33507c478bd9Sstevel@tonic-gate 	mutex_exit(&ibmf_statep->ibmf_mutex);
33517c478bd9Sstevel@tonic-gate 
33527c478bd9Sstevel@tonic-gate 	if (cip != NULL) {
33537c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
33547c478bd9Sstevel@tonic-gate 		    ibmf_i_is_ibmf_handle_valid_end, IBMF_TNF_TRACE, "",
33557c478bd9Sstevel@tonic-gate 		    "ibmf_i_is_ibmf_handle_valid() exit\n");
33567c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
33577c478bd9Sstevel@tonic-gate 	} else {
33587c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
33597c478bd9Sstevel@tonic-gate 		    ibmf_i_is_ibmf_handle_valid_end, IBMF_TNF_TRACE, "",
33607c478bd9Sstevel@tonic-gate 		    "ibmf_i_is_ibmf_handle_valid() failure exit\n");
33617c478bd9Sstevel@tonic-gate 		return (IBMF_FAILURE);
33627c478bd9Sstevel@tonic-gate 	}
33637c478bd9Sstevel@tonic-gate }
33647c478bd9Sstevel@tonic-gate 
33657c478bd9Sstevel@tonic-gate /*
33667c478bd9Sstevel@tonic-gate  * ibmf_i_is_qp_handle_valid():
33677c478bd9Sstevel@tonic-gate  *	Validate the QP handle
33687c478bd9Sstevel@tonic-gate  */
33697c478bd9Sstevel@tonic-gate int
ibmf_i_is_qp_handle_valid(ibmf_handle_t ibmf_handle,ibmf_qp_handle_t ibmf_qp_handle)33707c478bd9Sstevel@tonic-gate ibmf_i_is_qp_handle_valid(ibmf_handle_t ibmf_handle,
33717c478bd9Sstevel@tonic-gate     ibmf_qp_handle_t ibmf_qp_handle)
33727c478bd9Sstevel@tonic-gate {
33737c478bd9Sstevel@tonic-gate 	ibmf_client_t	*clientp = (ibmf_client_t *)ibmf_handle;
33747c478bd9Sstevel@tonic-gate 	ibmf_alt_qp_t	*alt_qp, *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
33757c478bd9Sstevel@tonic-gate 	ibmf_ci_t	*cip = clientp->ic_myci;
33767c478bd9Sstevel@tonic-gate 
33777c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
33787c478bd9Sstevel@tonic-gate 	    ibmf_i_is_qp_handle_valid_start, IBMF_TNF_TRACE, "",
33797c478bd9Sstevel@tonic-gate 	    "ibmf_i_is_qp_handle_valid() enter\n");
33807c478bd9Sstevel@tonic-gate 
33817c478bd9Sstevel@tonic-gate 	/* the default qp handle is always valid */
33827c478bd9Sstevel@tonic-gate 	if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT)
33837c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
33847c478bd9Sstevel@tonic-gate 
33857c478bd9Sstevel@tonic-gate 	mutex_enter(&cip->ci_mutex);
33867c478bd9Sstevel@tonic-gate 
33877c478bd9Sstevel@tonic-gate 	alt_qp = cip->ci_alt_qp_list;
33887c478bd9Sstevel@tonic-gate 
33897c478bd9Sstevel@tonic-gate 	while (alt_qp != NULL) {
33907c478bd9Sstevel@tonic-gate 		if (alt_qp == qpp) {
33917c478bd9Sstevel@tonic-gate 			/* qp handle found */
33927c478bd9Sstevel@tonic-gate 			break;
33937c478bd9Sstevel@tonic-gate 		} else {
33947c478bd9Sstevel@tonic-gate 			/* qp handle not found, get next qp on list */
33957c478bd9Sstevel@tonic-gate 			alt_qp = alt_qp->isq_next;
33967c478bd9Sstevel@tonic-gate 		}
33977c478bd9Sstevel@tonic-gate 	}
33987c478bd9Sstevel@tonic-gate 
33997c478bd9Sstevel@tonic-gate 	mutex_exit(&cip->ci_mutex);
34007c478bd9Sstevel@tonic-gate 
34017c478bd9Sstevel@tonic-gate 	if (alt_qp != NULL) {
34027c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34037c478bd9Sstevel@tonic-gate 		    ibmf_i_is_qp_handle_valid_end, IBMF_TNF_TRACE, "",
34047c478bd9Sstevel@tonic-gate 		    "ibmf_i_is_qp_handle_valid() exit\n");
34057c478bd9Sstevel@tonic-gate 		return (IBMF_SUCCESS);
34067c478bd9Sstevel@tonic-gate 	} else {
34077c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34087c478bd9Sstevel@tonic-gate 		    ibmf_i_is_qp_handle_valid_end, IBMF_TNF_TRACE, "",
34097c478bd9Sstevel@tonic-gate 		    "ibmf_i_is_qp_handle_valid() failure exit\n");
34107c478bd9Sstevel@tonic-gate 		return (IBMF_FAILURE);
34117c478bd9Sstevel@tonic-gate 	}
34127c478bd9Sstevel@tonic-gate }
34137c478bd9Sstevel@tonic-gate 
34147c478bd9Sstevel@tonic-gate void
ibmf_dprintf(int l,const char * fmt,...)34157c478bd9Sstevel@tonic-gate ibmf_dprintf(int l, const char *fmt, ...)
34167c478bd9Sstevel@tonic-gate {
34177c478bd9Sstevel@tonic-gate 	va_list ap;
34187c478bd9Sstevel@tonic-gate 
34197c478bd9Sstevel@tonic-gate 	if ((l) > ibmf_trace_level) {
34207c478bd9Sstevel@tonic-gate 
34217c478bd9Sstevel@tonic-gate 		return;
34227c478bd9Sstevel@tonic-gate 	}
34237c478bd9Sstevel@tonic-gate 
34247c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
34257c478bd9Sstevel@tonic-gate 	(void) vprintf(fmt, ap);
34267c478bd9Sstevel@tonic-gate 	va_end(ap);
34277c478bd9Sstevel@tonic-gate }
34287c478bd9Sstevel@tonic-gate 
34297c478bd9Sstevel@tonic-gate /*
34307c478bd9Sstevel@tonic-gate  * ibmf_setup_term_ctx():
34317c478bd9Sstevel@tonic-gate  * Sets up a message context that is the duplicate of the one
34327c478bd9Sstevel@tonic-gate  * passed in the regmsgimplp argument. The duplicate message context
34337c478bd9Sstevel@tonic-gate  * is not visible to the client. It is managed internally by ibmf
34347c478bd9Sstevel@tonic-gate  * to process the RMPP receiver termination flow logic for the
34357c478bd9Sstevel@tonic-gate  * transaction while the client is notified of the completion of the
34367c478bd9Sstevel@tonic-gate  * same transaction (i.e. all the solicited data has been received).
34377c478bd9Sstevel@tonic-gate  */
34387c478bd9Sstevel@tonic-gate int
ibmf_setup_term_ctx(ibmf_client_t * clientp,ibmf_msg_impl_t * regmsgimplp)34397c478bd9Sstevel@tonic-gate ibmf_setup_term_ctx(ibmf_client_t *clientp, ibmf_msg_impl_t *regmsgimplp)
34407c478bd9Sstevel@tonic-gate {
34417c478bd9Sstevel@tonic-gate 	ibmf_msg_impl_t	*msgimplp;
34427c478bd9Sstevel@tonic-gate 	size_t		offset;
34437c478bd9Sstevel@tonic-gate 	uint32_t	cl_hdr_sz, cl_hdr_off;
34447c478bd9Sstevel@tonic-gate 	int		status;
34457c478bd9Sstevel@tonic-gate 
34467c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34477c478bd9Sstevel@tonic-gate 	    ibmf_setup_term_ctx_start, IBMF_TNF_TRACE, "",
34487c478bd9Sstevel@tonic-gate 	    "ibmf_setup_term_ctx() enter\n");
34497c478bd9Sstevel@tonic-gate 
34507c478bd9Sstevel@tonic-gate 	/*
34517c478bd9Sstevel@tonic-gate 	 * Allocate the termination message context
34527c478bd9Sstevel@tonic-gate 	 */
34537c478bd9Sstevel@tonic-gate 	msgimplp = (ibmf_msg_impl_t *)kmem_zalloc(sizeof (ibmf_msg_impl_t),
34547c478bd9Sstevel@tonic-gate 	    KM_NOSLEEP);
34557c478bd9Sstevel@tonic-gate 	if (msgimplp == NULL) {
34567c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
34577c478bd9Sstevel@tonic-gate 		    ibmf_setup_term_ctx_error, IBMF_TNF_ERROR, "",
34587c478bd9Sstevel@tonic-gate 		    "ibmf_setup_term_ctx(): %s\n", tnf_string, msg,
34597c478bd9Sstevel@tonic-gate 		    "message mem allocation failure");
34607c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34617c478bd9Sstevel@tonic-gate 		    ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "",
34627c478bd9Sstevel@tonic-gate 		    "ibmf_setup_term_ctx() exit\n");
34637c478bd9Sstevel@tonic-gate 		return (IBMF_NO_RESOURCES);
34647c478bd9Sstevel@tonic-gate 	}
34657c478bd9Sstevel@tonic-gate 
34667c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp))
34677c478bd9Sstevel@tonic-gate 
34687c478bd9Sstevel@tonic-gate 	/* Copy the message context to the termination message structure */
34697c478bd9Sstevel@tonic-gate 	*msgimplp = *regmsgimplp;
34707c478bd9Sstevel@tonic-gate 
34717c478bd9Sstevel@tonic-gate 	/* Initialize the message mutex */
34727c478bd9Sstevel@tonic-gate 	mutex_init(&msgimplp->im_mutex, NULL, MUTEX_DRIVER, NULL);
34737c478bd9Sstevel@tonic-gate 
34747c478bd9Sstevel@tonic-gate 	/*
34757c478bd9Sstevel@tonic-gate 	 * Allocate enough memory for the MAD header only.
34767c478bd9Sstevel@tonic-gate 	 */
34777c478bd9Sstevel@tonic-gate 	msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
34787c478bd9Sstevel@tonic-gate 	    (ib_mad_hdr_t *)kmem_zalloc(IBMF_MAD_SIZE, KM_NOSLEEP);
34797c478bd9Sstevel@tonic-gate 	if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
34807c478bd9Sstevel@tonic-gate 		kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
34817c478bd9Sstevel@tonic-gate 		IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
34827c478bd9Sstevel@tonic-gate 		    ibmf_setup_term_ctx_error, IBMF_TNF_ERROR, "",
34837c478bd9Sstevel@tonic-gate 		    "ibmf_setup_term_ctx(): %s\n", tnf_string, msg,
34847c478bd9Sstevel@tonic-gate 		    "recv buf mem allocation failure");
34857c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34867c478bd9Sstevel@tonic-gate 		    ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "",
34877c478bd9Sstevel@tonic-gate 		    "ibmf_setup_term_ctx() exit\n");
34887c478bd9Sstevel@tonic-gate 		return (IBMF_NO_RESOURCES);
34897c478bd9Sstevel@tonic-gate 	}
34907c478bd9Sstevel@tonic-gate 
34917c478bd9Sstevel@tonic-gate 	/* Copy over just the MAD header contents */
34927c478bd9Sstevel@tonic-gate 	bcopy((const void *)regmsgimplp->im_msgbufs_recv.im_bufs_mad_hdr,
34937c478bd9Sstevel@tonic-gate 	    (void *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr,
34947c478bd9Sstevel@tonic-gate 	    sizeof (ib_mad_hdr_t));
34957c478bd9Sstevel@tonic-gate 
34967c478bd9Sstevel@tonic-gate 	offset = sizeof (ib_mad_hdr_t);
34977c478bd9Sstevel@tonic-gate 	ibmf_i_mgt_class_to_hdr_sz_off(
34987c478bd9Sstevel@tonic-gate 	    regmsgimplp->im_msgbufs_recv.im_bufs_mad_hdr->MgmtClass,
34997c478bd9Sstevel@tonic-gate 	    &cl_hdr_sz, &cl_hdr_off);
35007c478bd9Sstevel@tonic-gate 	offset += cl_hdr_off;
35017c478bd9Sstevel@tonic-gate 
35027c478bd9Sstevel@tonic-gate 	/*
35037c478bd9Sstevel@tonic-gate 	 * Copy the management class header
35047c478bd9Sstevel@tonic-gate 	 */
35057c478bd9Sstevel@tonic-gate 	msgimplp->im_msgbufs_recv.im_bufs_cl_hdr =
35067c478bd9Sstevel@tonic-gate 	    (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr + offset;
35077c478bd9Sstevel@tonic-gate 	msgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len =
35087c478bd9Sstevel@tonic-gate 	    regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len;
35097c478bd9Sstevel@tonic-gate 	bcopy((void *)regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr,
35107c478bd9Sstevel@tonic-gate 	    (void *)msgimplp->im_msgbufs_recv.im_bufs_cl_hdr,
35117c478bd9Sstevel@tonic-gate 	    regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len);
35127c478bd9Sstevel@tonic-gate 
35137c478bd9Sstevel@tonic-gate 	/*
35147c478bd9Sstevel@tonic-gate 	 * Clear the termination message timers copied from the regular message
35157c478bd9Sstevel@tonic-gate 	 * since ibmf_i_set_timer() expects them to be cleared.
35167c478bd9Sstevel@tonic-gate 	 */
35177c478bd9Sstevel@tonic-gate 	msgimplp->im_rp_timeout_id = 0;
35187c478bd9Sstevel@tonic-gate 	msgimplp->im_tr_timeout_id = 0;
35197c478bd9Sstevel@tonic-gate 
35207c478bd9Sstevel@tonic-gate 	/* Mark this message as being in a receiver RMPP mode */
35217c478bd9Sstevel@tonic-gate 	msgimplp->im_flags |= IBMF_MSG_FLAGS_RECV_RMPP;
35227c478bd9Sstevel@tonic-gate 
35237c478bd9Sstevel@tonic-gate 	/* Mark this message as being a "termination flow" message */
35247c478bd9Sstevel@tonic-gate 	msgimplp->im_flags |= IBMF_MSG_FLAGS_TERMINATION;
35257c478bd9Sstevel@tonic-gate 
35267c478bd9Sstevel@tonic-gate 	/*
35277c478bd9Sstevel@tonic-gate 	 * Clear the IBMF_MSG_FLAGS_SET_TERMINATION copied over from the regular
35287c478bd9Sstevel@tonic-gate 	 * message.
35297c478bd9Sstevel@tonic-gate 	 */
35307c478bd9Sstevel@tonic-gate 	msgimplp->im_flags &= ~IBMF_MSG_FLAGS_SET_TERMINATION;
35317c478bd9Sstevel@tonic-gate 
35327c478bd9Sstevel@tonic-gate 	/*
35337c478bd9Sstevel@tonic-gate 	 * Clear the trans_state RECV_DONE and DONE flags so that the
35347c478bd9Sstevel@tonic-gate 	 * protocol continues with the termination message context.
35357c478bd9Sstevel@tonic-gate 	 */
35367c478bd9Sstevel@tonic-gate 	msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_RECV_DONE;
35377c478bd9Sstevel@tonic-gate 	msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_DONE;
35387c478bd9Sstevel@tonic-gate 
35397c478bd9Sstevel@tonic-gate 	/* Clear out references to the old UD dest handles */
35407c478bd9Sstevel@tonic-gate 	msgimplp->im_ibmf_ud_dest = NULL;
35417c478bd9Sstevel@tonic-gate 	msgimplp->im_ud_dest = NULL;
35427c478bd9Sstevel@tonic-gate 
35437c478bd9Sstevel@tonic-gate 	/*
35447c478bd9Sstevel@tonic-gate 	 * Request new UD dest resources for the termination phase.
35457c478bd9Sstevel@tonic-gate 	 * The old UD dest resources are freed when the IBMF client
35467c478bd9Sstevel@tonic-gate 	 * calls ibmf_free_msg(), so they cannot be relied on to exist
35477c478bd9Sstevel@tonic-gate 	 * when the RMPP termination loop completes.
35487c478bd9Sstevel@tonic-gate 	 */
35497c478bd9Sstevel@tonic-gate 	status = ibmf_i_alloc_ud_dest(clientp, msgimplp, &msgimplp->im_ud_dest,
35507c478bd9Sstevel@tonic-gate 	    B_FALSE);
35517c478bd9Sstevel@tonic-gate 	if (status != IBMF_SUCCESS) {
35527c478bd9Sstevel@tonic-gate 		kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
35537c478bd9Sstevel@tonic-gate 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
35547c478bd9Sstevel@tonic-gate 		    ibmf_setup_term_ctx_err, IBMF_TNF_ERROR, "",
35557c478bd9Sstevel@tonic-gate 		    "ibmf_setup_term_ctx(): %s, status = %d\n",
35567c478bd9Sstevel@tonic-gate 		    tnf_string, msg, "UD destination resource allocation"
35577c478bd9Sstevel@tonic-gate 		    " failed", tnf_int, ibmf_status, status);
35587c478bd9Sstevel@tonic-gate 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
35597c478bd9Sstevel@tonic-gate 		    ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "",
35607c478bd9Sstevel@tonic-gate 		    "ibmf_setup_term_ctx() exit\n");
35617c478bd9Sstevel@tonic-gate 		return (status);
35627c478bd9Sstevel@tonic-gate 	}
35637c478bd9Sstevel@tonic-gate 
35647c478bd9Sstevel@tonic-gate 	/*
35657c478bd9Sstevel@tonic-gate 	 * Add the message to the termination client list by virtue of
35667c478bd9Sstevel@tonic-gate 	 * having the IBMF_MSG_FLAGS_TERMINATION "im_flags" flag set.
35677c478bd9Sstevel@tonic-gate 	 */
35687c478bd9Sstevel@tonic-gate 	ibmf_i_client_add_msg(clientp, msgimplp);
35697c478bd9Sstevel@tonic-gate 
35707c478bd9Sstevel@tonic-gate 	/*
35717c478bd9Sstevel@tonic-gate 	 * Increase the "allocted messages" count so that the client
35727c478bd9Sstevel@tonic-gate 	 * does not unregister before this message has been freed.
35737c478bd9Sstevel@tonic-gate 	 * This is necessary because we want the client context to
35747c478bd9Sstevel@tonic-gate 	 * be around when the receive timeout expires for this termination
35757c478bd9Sstevel@tonic-gate 	 * loop, otherwise the code will access freed memory and crash.
35767c478bd9Sstevel@tonic-gate 	 */
35777c478bd9Sstevel@tonic-gate 	mutex_enter(&clientp->ic_mutex);
35787c478bd9Sstevel@tonic-gate 	clientp->ic_msgs_alloced++;
35797c478bd9Sstevel@tonic-gate 	mutex_exit(&clientp->ic_mutex);
35807c478bd9Sstevel@tonic-gate 
35817c478bd9Sstevel@tonic-gate 	mutex_enter(&msgimplp->im_mutex);
35827c478bd9Sstevel@tonic-gate 	/* Set the response timer for the termination message. */
35837c478bd9Sstevel@tonic-gate 	ibmf_i_set_timer(ibmf_i_recv_timeout, msgimplp, IBMF_RESP_TIMER);
35847c478bd9Sstevel@tonic-gate 	mutex_exit(&msgimplp->im_mutex);
35857c478bd9Sstevel@tonic-gate 
35867c478bd9Sstevel@tonic-gate 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_setup_term_ctx_end,
35877c478bd9Sstevel@tonic-gate 	    IBMF_TNF_TRACE, "", "ibmf_setup_term_ctx() exit\n");
35887c478bd9Sstevel@tonic-gate 
35897c478bd9Sstevel@tonic-gate 	return (IBMF_SUCCESS);
35907c478bd9Sstevel@tonic-gate }
3591