xref: /illumos-gate/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_ti.c (revision fc8ae2ec4282de7ec96f48e11078345f3dc0ac3d)
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
5448978d3Shiremath  * Common Development and Distribution License (the "License").
6448978d3Shiremath  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22a23420cfSShantkumar Hiremath  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <sys/ib/mgt/ibcm/ibcm_impl.h>
267c478bd9Sstevel@tonic-gate #include <sys/ib/ibtl/ibti.h>
27015f8fffShiremath #include <sys/ib/mgt/ibcm/ibcm_arp.h>
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * ibcm_ti.c
317c478bd9Sstevel@tonic-gate  *	These routines implement the Communication Manager's interfaces to IBTL.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /* CM rc recycle task args structure definition */
357c478bd9Sstevel@tonic-gate typedef struct ibcm_taskq_recycle_arg_s {
367c478bd9Sstevel@tonic-gate 	ibt_channel_hdl_t	rc_chan;
377c478bd9Sstevel@tonic-gate 	ibt_cep_flags_t		control;
387c478bd9Sstevel@tonic-gate 	uint8_t			hca_port_num;
397c478bd9Sstevel@tonic-gate 	ibt_recycle_handler_t	func;
407c478bd9Sstevel@tonic-gate 	void			*arg;
417c478bd9Sstevel@tonic-gate } ibcm_taskq_recycle_arg_t;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_taskq_recycle_arg_s))
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate static ibt_status_t	ibcm_init_reply_addr(ibcm_hca_info_t *hcap,
467c478bd9Sstevel@tonic-gate     ibcm_mad_addr_t *reply_addr, ibt_chan_open_args_t *chan_args,
477c478bd9Sstevel@tonic-gate     ibt_chan_open_flags_t flags, ib_time_t *cm_pkt_lt, ib_lid_t prim_slid);
487c478bd9Sstevel@tonic-gate static void		ibcm_process_abort_via_taskq(void *args);
497c478bd9Sstevel@tonic-gate static ibt_status_t	ibcm_process_rc_recycle_ret(void *recycle_arg);
507c478bd9Sstevel@tonic-gate static ibt_status_t	ibcm_process_join_mcg(void *taskq_arg);
517c478bd9Sstevel@tonic-gate static void		ibcm_process_async_join_mcg(void *tq_arg);
527c478bd9Sstevel@tonic-gate 
5376c04273SRajkumar Sivaprakasam ibt_status_t ibcm_get_node_rec(ibmf_saa_handle_t, sa_node_record_t *,
547c478bd9Sstevel@tonic-gate     uint64_t c_mask, void *, size_t *);
557c478bd9Sstevel@tonic-gate 
56934f0bccShiremath static ibt_status_t ibcm_close_rc_channel(ibt_channel_hdl_t channel,
57934f0bccShiremath     ibcm_state_data_t *statep, ibt_execution_mode_t mode);
58934f0bccShiremath 
597c478bd9Sstevel@tonic-gate /* Address Record management definitions */
607c478bd9Sstevel@tonic-gate #define	IBCM_DAPL_ATS_NAME	"DAPL Address Translation Service"
617c478bd9Sstevel@tonic-gate #define	IBCM_DAPL_ATS_SID	0x10000CE100415453ULL
627c478bd9Sstevel@tonic-gate #define	IBCM_DAPL_ATS_NBYTES	16
637c478bd9Sstevel@tonic-gate ibcm_svc_info_t *ibcm_ar_svcinfop;
647c478bd9Sstevel@tonic-gate ibcm_ar_t	*ibcm_ar_list;
657c478bd9Sstevel@tonic-gate 
66934f0bccShiremath /*
67934f0bccShiremath  * Tunable parameter to turnoff the overriding of pi_path_mtu value.
68934f0bccShiremath  *	1 	By default override the path record's pi_path_mtu value to
69934f0bccShiremath  *		IB_MTU_1K for all RC channels. This is done only for the
70934f0bccShiremath  *		channels established on Tavor HCA and the path's pi_path_mtu
71934f0bccShiremath  *		is greater than IB_MTU_1K.
72934f0bccShiremath  *	0	Do not override, use pi_path_mtu by default.
73934f0bccShiremath  */
74934f0bccShiremath int	ibcm_override_path_mtu = 1;
75934f0bccShiremath 
767c478bd9Sstevel@tonic-gate #ifdef DEBUG
777c478bd9Sstevel@tonic-gate static void	ibcm_print_reply_addr(ibt_channel_hdl_t channel,
787c478bd9Sstevel@tonic-gate 		    ibcm_mad_addr_t *cm_reply_addr);
797c478bd9Sstevel@tonic-gate #endif
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_hdl}))
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /* access is controlled between ibcm_sm.c and ibcm_ti.c by CVs */
847c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Serialized access by CV", {ibt_rc_returns_t
857c478bd9Sstevel@tonic-gate     ibt_ud_returns_t ibt_ap_returns_t ibt_ar_t}))
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate  * Typically, clients initialize these args in one api call, and use in
897c478bd9Sstevel@tonic-gate  * another api
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Expected usage of ibtl api by client",
927c478bd9Sstevel@tonic-gate     {ibt_path_info_s ibt_cep_path_s ibt_adds_vect_s ibt_mcg_info_s ib_gid_s
937c478bd9Sstevel@tonic-gate     ibt_ud_dest_attr_s ibt_ud_dest_s ibt_srv_data_s ibt_redirect_info_s}))
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * ibt_open_rc_channel()
977c478bd9Sstevel@tonic-gate  *	ibt_open_rc_channel opens a communication channel on the specified
987c478bd9Sstevel@tonic-gate  *	channel to the specified service. For connection service type qp's
997c478bd9Sstevel@tonic-gate  *	the CM initiates the CEP to establish the connection and transitions
1007c478bd9Sstevel@tonic-gate  *	the QP/EEC to the "Ready to send" State modifying the QP/EEC's
1017c478bd9Sstevel@tonic-gate  *	attributes as necessary.
1027c478bd9Sstevel@tonic-gate  *	The implementation of this function assumes that alt path is different
1037c478bd9Sstevel@tonic-gate  *	from primary path. It is assumed that the Path functions ensure that.
1047c478bd9Sstevel@tonic-gate  *
1057c478bd9Sstevel@tonic-gate  * RETURN VALUES:
1067c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS	on success (or respective failure on error)
1077c478bd9Sstevel@tonic-gate  */
1087c478bd9Sstevel@tonic-gate ibt_status_t
ibt_open_rc_channel(ibt_channel_hdl_t channel,ibt_chan_open_flags_t flags,ibt_execution_mode_t mode,ibt_chan_open_args_t * chan_args,ibt_rc_returns_t * ret_args)1097c478bd9Sstevel@tonic-gate ibt_open_rc_channel(ibt_channel_hdl_t channel, ibt_chan_open_flags_t flags,
1107c478bd9Sstevel@tonic-gate     ibt_execution_mode_t mode, ibt_chan_open_args_t *chan_args,
1117c478bd9Sstevel@tonic-gate     ibt_rc_returns_t *ret_args)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate 	/* all fields that are related to REQ MAD formation */
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	ib_pkey_t		prim_pkey;
1167c478bd9Sstevel@tonic-gate 	ib_lid_t		primary_slid, alternate_slid;
1177c478bd9Sstevel@tonic-gate 	ib_qpn_t		local_qpn = 0;
1187c478bd9Sstevel@tonic-gate 	ib_guid_t		hca_guid;
1197c478bd9Sstevel@tonic-gate 	ib_qkey_t		local_qkey = 0;
1207c478bd9Sstevel@tonic-gate 	ib_eecn_t		local_eecn = 0;
1217c478bd9Sstevel@tonic-gate 	ib_eecn_t		remote_eecn = 0;
1227c478bd9Sstevel@tonic-gate 	boolean_t		primary_grh;
1237c478bd9Sstevel@tonic-gate 	boolean_t		alternate_grh = B_FALSE;
1247c478bd9Sstevel@tonic-gate 	ib_lid_t		base_lid;
1257c478bd9Sstevel@tonic-gate 	ib_com_id_t		local_comid;
126934f0bccShiremath 	ibmf_msg_t		*ibmf_msg, *ibmf_msg_dreq;
1277c478bd9Sstevel@tonic-gate 	ibcm_req_msg_t		*req_msgp;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	uint8_t			rdma_in, rdma_out;
1307c478bd9Sstevel@tonic-gate 	uint8_t			cm_retries;
1317c478bd9Sstevel@tonic-gate 	uint64_t		local_cm_proc_time;	/* In usec */
1327c478bd9Sstevel@tonic-gate 	uint8_t			local_cm_resp_time;	/* IB time */
1337c478bd9Sstevel@tonic-gate 	uint64_t		remote_cm_resp_time;	/* In usec */
1347c478bd9Sstevel@tonic-gate 	uint32_t		starting_psn = 0;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	/* CM path related fields */
1377c478bd9Sstevel@tonic-gate 	ibmf_handle_t		ibmf_hdl;
1387c478bd9Sstevel@tonic-gate 	ibcm_qp_list_t		*cm_qp_entry;
1397c478bd9Sstevel@tonic-gate 	ibcm_mad_addr_t		cm_reply_addr;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	uint8_t			cm_pkt_lt;
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/* Local args for ibtl/internal CM functions called within */
1447c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
1457c478bd9Sstevel@tonic-gate 	ibcm_status_t		lkup_status;
1467c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_query_attr;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/* Other misc local args */
1497c478bd9Sstevel@tonic-gate 	ibt_priv_data_len_t	len;
1507c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
1517c478bd9Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
1527c478bd9Sstevel@tonic-gate 	uint8_t			port_no;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel(chan %p, %X, %x, %p, %p)",
1557c478bd9Sstevel@tonic-gate 	    channel, flags, mode, chan_args, ret_args);
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
1587c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: invalid channel");
1597c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	/* cm handler should always be specified */
1637c478bd9Sstevel@tonic-gate 	if (chan_args->oc_cm_handler == NULL) {
1647c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
1657c478bd9Sstevel@tonic-gate 		    "CM handler is not be specified", channel);
1667c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING) {
1707c478bd9Sstevel@tonic-gate 		if (ret_args != NULL) {
1717c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1727c478bd9Sstevel@tonic-gate 			    " ret_args should be NULL when called in "
1737c478bd9Sstevel@tonic-gate 			    "non-blocking mode", channel);
1747c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1757c478bd9Sstevel@tonic-gate 		}
1767c478bd9Sstevel@tonic-gate 	} else if (mode == IBT_BLOCKING) {
1777c478bd9Sstevel@tonic-gate 		if (ret_args == NULL) {
1787c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1797c478bd9Sstevel@tonic-gate 			    " ret_args should be Non-NULL when called in "
1807c478bd9Sstevel@tonic-gate 			    "blocking mode", channel);
1817c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1827c478bd9Sstevel@tonic-gate 		}
1837c478bd9Sstevel@tonic-gate 		if (ret_args->rc_priv_data_len > IBT_REP_PRIV_DATA_SZ) {
1847c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1857c478bd9Sstevel@tonic-gate 			    " private data length is too large", channel);
1867c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1877c478bd9Sstevel@tonic-gate 		}
1887c478bd9Sstevel@tonic-gate 		if ((ret_args->rc_priv_data_len > 0) &&
1897c478bd9Sstevel@tonic-gate 		    (ret_args->rc_priv_data == NULL)) {
1907c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1917c478bd9Sstevel@tonic-gate 			    " rc_priv_data_len > 0, but rc_priv_data NULL",
1927c478bd9Sstevel@tonic-gate 			    channel);
1937c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1947c478bd9Sstevel@tonic-gate 		}
1957c478bd9Sstevel@tonic-gate 	} else { /* any other mode is not valid for ibt_open_rc_channel */
1967c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
1977c478bd9Sstevel@tonic-gate 		    "invalid mode %x specified", channel, mode);
1987c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	/*
2027c478bd9Sstevel@tonic-gate 	 * XXX: no support yet for ibt_chan_open_flags_t - IBT_OCHAN_DUP
2037c478bd9Sstevel@tonic-gate 	 */
2047c478bd9Sstevel@tonic-gate 	if (flags & IBT_OCHAN_DUP) {
2057c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2067c478bd9Sstevel@tonic-gate 		    "Unsupported Flags specified: 0x%X", channel, flags);
2077c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2087c478bd9Sstevel@tonic-gate 	}
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	if ((flags & IBT_OCHAN_REDIRECTED) &&
2117c478bd9Sstevel@tonic-gate 	    (flags & IBT_OCHAN_PORT_REDIRECTED)) {
2127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2137c478bd9Sstevel@tonic-gate 		    "Illegal to specify IBT_OCHAN_REDIRECTED and "
2147c478bd9Sstevel@tonic-gate 		    "IBT_OCHAN_PORT_REDIRECTED flags together", channel);
2157c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	if (((flags & IBT_OCHAN_REDIRECTED) &&
2197c478bd9Sstevel@tonic-gate 	    (chan_args->oc_cm_redirect_info == NULL)) ||
2207c478bd9Sstevel@tonic-gate 	    ((flags & IBT_OCHAN_PORT_REDIRECTED) &&
2217c478bd9Sstevel@tonic-gate 	    (chan_args->oc_cm_cep_path == NULL))) {
2227c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2237c478bd9Sstevel@tonic-gate 		    "Redirect flag specified, but respective arg is NULL",
2247c478bd9Sstevel@tonic-gate 		    channel);
2257c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2267c478bd9Sstevel@tonic-gate 	}
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	if ((flags & IBT_OCHAN_REDIRECTED) &&
2297c478bd9Sstevel@tonic-gate 	    (chan_args->oc_cm_redirect_info->rdi_dlid == 0) &&
2307c478bd9Sstevel@tonic-gate 	    (chan_args->oc_cm_redirect_info->rdi_gid.gid_guid == 0)) {
2317c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2327c478bd9Sstevel@tonic-gate 		    "Either rdi_dlid or rdi_gid must be specified for"
2337c478bd9Sstevel@tonic-gate 		    " IBT_OCHAN_REDIRECTED", channel);
2347c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/* primary dlid and hca_port_num should never be zero */
2387c478bd9Sstevel@tonic-gate 	port_no = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	if ((IBCM_PRIM_ADDS_VECT(chan_args).av_dlid == 0) && (port_no == 0)) {
2417c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2427c478bd9Sstevel@tonic-gate 		    "Primary Path's information is not valid", channel);
2437c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	/* validate SID */
2477c478bd9Sstevel@tonic-gate 	if (chan_args->oc_path->pi_sid == 0) {
2487c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2497c478bd9Sstevel@tonic-gate 		    "ERROR: Service ID in path information is 0", channel);
2507c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2517c478bd9Sstevel@tonic-gate 	}
252d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p  SID %llX",
253d3a82192SShantkumar Hiremath 	    channel, chan_args->oc_path->pi_sid);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	/* validate rnr_retry_cnt (enum has more than 3 bits) */
2567c478bd9Sstevel@tonic-gate 	if ((uint_t)chan_args->oc_path_rnr_retry_cnt > IBT_RNR_INFINITE_RETRY) {
2577c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2587c478bd9Sstevel@tonic-gate 		    "ERROR: oc_path_rnr_retry_cnt(%d) is out of range",
2597c478bd9Sstevel@tonic-gate 		    channel, chan_args->oc_path_rnr_retry_cnt);
2607c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2617c478bd9Sstevel@tonic-gate 	}
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	/*
2647c478bd9Sstevel@tonic-gate 	 * Ensure that client is not re-using a QP that is still associated
2657c478bd9Sstevel@tonic-gate 	 * with a statep
2667c478bd9Sstevel@tonic-gate 	 */
2677c478bd9Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
2687c478bd9Sstevel@tonic-gate 	if (statep != NULL) {
2697c478bd9Sstevel@tonic-gate 		IBCM_RELEASE_CHAN_PRIVATE(channel);
2707c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2717c478bd9Sstevel@tonic-gate 		    "Channel being re-used on active side", channel);
2727c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_IN_USE);
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	/* Get GUID from Channel */
2767c478bd9Sstevel@tonic-gate 	hca_guid = ibt_channel_to_hca_guid(channel);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	/* validate QP's hca guid with that from primary path  */
2797c478bd9Sstevel@tonic-gate 	if (hca_guid != chan_args->oc_path->pi_hca_guid) {
2807c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2817c478bd9Sstevel@tonic-gate 		    "GUID from Channel and primary path don't match", channel);
2827c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2837c478bd9Sstevel@tonic-gate 		    "Channel GUID %llX primary path GUID %llX", channel,
2847c478bd9Sstevel@tonic-gate 		    hca_guid, chan_args->oc_path->pi_hca_guid);
2857c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
2867c478bd9Sstevel@tonic-gate 	}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
2897c478bd9Sstevel@tonic-gate 	    "Local HCA GUID %llX", channel, hca_guid);
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	status = ibt_query_qp(channel, &qp_query_attr);
2927c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
2937c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2947c478bd9Sstevel@tonic-gate 		    "ibt_query_qp failed %d", channel, status);
2957c478bd9Sstevel@tonic-gate 		return (status);
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	/* If client specified "no port change on QP" */
2997c478bd9Sstevel@tonic-gate 	if ((qp_query_attr.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
3007c478bd9Sstevel@tonic-gate 	    port_no) && (flags & IBT_OCHAN_PORT_FIXED)) {
3017c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3027c478bd9Sstevel@tonic-gate 		    "chan port %d and path port %d does not match", channel,
3037c478bd9Sstevel@tonic-gate 		    qp_query_attr.qp_info.qp_transport.rc.rc_path. \
3047c478bd9Sstevel@tonic-gate 		    cep_hca_port_num, port_no);
3057c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	if (qp_query_attr.qp_info.qp_trans != IBT_RC_SRV) {
3097c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3107c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel",
3117c478bd9Sstevel@tonic-gate 		    channel);
3127c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	/* Check if QP is in INIT state or not */
3167c478bd9Sstevel@tonic-gate 	if (qp_query_attr.qp_info.qp_state != IBT_STATE_INIT) {
3177c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3187c478bd9Sstevel@tonic-gate 		    "QP is not in INIT state %x", channel,
3197c478bd9Sstevel@tonic-gate 		    qp_query_attr.qp_info.qp_state);
3207c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	local_qpn = qp_query_attr.qp_qpn;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p Active QPN 0x%x",
3267c478bd9Sstevel@tonic-gate 	    channel, local_qpn);
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate #ifdef	NO_EEC_SUPPORT_YET
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	if (flags & IBT_OCHAN_RDC_EXISTS) {
3317c478bd9Sstevel@tonic-gate 		ibt_eec_query_attr_t	eec_query_attr;
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 		local_qkey = qp_query_attr.qp_info.qp_transport.rd_qkey;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: RD");
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 		status = ibt_query_eec(channel, &eec_query_attr);
3387c478bd9Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
3397c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
3407c478bd9Sstevel@tonic-gate 			    " ibt_query_eec failed %d", channel, status);
3417c478bd9Sstevel@tonic-gate 			return (status);
3427c478bd9Sstevel@tonic-gate 		}
3437c478bd9Sstevel@tonic-gate 		local_eecn = eec_query_attr.eec_eecn;
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate #endif
3475c42ea03Shiremath 	if (chan_args->oc_path->pi_prim_pkt_lt > ibcm_max_ib_pkt_lt) {
3485c42ea03Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3495c42ea03Shiremath 		    "Huge PktLifeTime %d, Max is %d", channel,
3505c42ea03Shiremath 		    chan_args->oc_path->pi_prim_pkt_lt, ibcm_max_ib_pkt_lt);
3515c42ea03Shiremath 		return (IBT_PATH_PKT_LT_TOO_HIGH);
3525c42ea03Shiremath 	}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	/* If no HCA found return failure */
3557c478bd9Sstevel@tonic-gate 	if ((hcap = ibcm_find_hca_entry(hca_guid)) == NULL) {
3567c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3577c478bd9Sstevel@tonic-gate 		    "hcap is NULL. Probably hca is not in active state",
3587c478bd9Sstevel@tonic-gate 		    channel);
3597c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	rdma_out = chan_args->oc_rdma_ra_out;
3637c478bd9Sstevel@tonic-gate 	rdma_in = chan_args->oc_rdma_ra_in;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	if ((rdma_in > hcap->hca_max_rdma_in_qp) ||
3667c478bd9Sstevel@tonic-gate 	    (rdma_out > hcap->hca_max_rdma_out_qp)) {
3677c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3685c42ea03Shiremath 		    "rdma in %d/out %d values exceed hca limits(%d/%d)",
3695c42ea03Shiremath 		    channel, rdma_in, rdma_out, hcap->hca_max_rdma_in_qp,
3705c42ea03Shiremath 		    hcap->hca_max_rdma_out_qp);
3717c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
3727c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
3737c478bd9Sstevel@tonic-gate 	}
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
3767c478bd9Sstevel@tonic-gate 	    "rdma_in %d rdma_out %d", channel, rdma_in, rdma_out);
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	status = ibt_get_port_state_byguid(hcap->hca_guid, port_no,
3797c478bd9Sstevel@tonic-gate 	    NULL, &base_lid);
3807c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
3817c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3827c478bd9Sstevel@tonic-gate 		    "primary port_num %d not active", channel, port_no);
3837c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
3847c478bd9Sstevel@tonic-gate 		return (status);
3857c478bd9Sstevel@tonic-gate 	}
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/* Validate P_KEY Index */
3887c478bd9Sstevel@tonic-gate 	status = ibt_index2pkey_byguid(hcap->hca_guid, port_no,
3897c478bd9Sstevel@tonic-gate 	    IBCM_PRIM_CEP_PATH(chan_args).cep_pkey_ix, &prim_pkey);
3907c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
3917c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3927c478bd9Sstevel@tonic-gate 		    "Invalid Primary PKeyIx %x", channel,
3937c478bd9Sstevel@tonic-gate 		    IBCM_PRIM_CEP_PATH(chan_args).cep_pkey_ix);
3947c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
3957c478bd9Sstevel@tonic-gate 		return (status);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
3997c478bd9Sstevel@tonic-gate 	    "primary_port_num %d primary_pkey 0x%x", channel, port_no,
4007c478bd9Sstevel@tonic-gate 	    prim_pkey);
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	if ((hcap->hca_port_info[port_no - 1].port_ibmf_hdl == NULL) &&
4037c478bd9Sstevel@tonic-gate 	    ((status = ibcm_hca_reinit_port(hcap, port_no - 1))
4047c478bd9Sstevel@tonic-gate 	    != IBT_SUCCESS)) {
4057c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4067c478bd9Sstevel@tonic-gate 		    "ibmf reg or callback setup failed during re-initialize",
4077c478bd9Sstevel@tonic-gate 		    channel);
4087c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
4097c478bd9Sstevel@tonic-gate 		return (status);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	ibmf_hdl = hcap->hca_port_info[port_no - 1].port_ibmf_hdl;
4137c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
4147c478bd9Sstevel@tonic-gate 	    "primary ibmf_hdl = 0x%p", channel, ibmf_hdl);
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	primary_slid = base_lid + IBCM_PRIM_ADDS_VECT(chan_args).av_src_path;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: channel 0x%p "
4197c478bd9Sstevel@tonic-gate 	    "primary SLID = %x", channel, primary_slid);
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	/* check first if alternate path exists or not as it is OPTIONAL */
4227c478bd9Sstevel@tonic-gate 	if (IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num != 0) {
4237c478bd9Sstevel@tonic-gate 		uint8_t	alt_port_no;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 		alt_port_no = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 		if (chan_args->oc_path->pi_alt_pkt_lt > ibcm_max_ib_pkt_lt) {
4287c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4297c478bd9Sstevel@tonic-gate 			    "Huge Alt Pkt lt %d", channel,
4307c478bd9Sstevel@tonic-gate 			    chan_args->oc_path->pi_alt_pkt_lt);
4317c478bd9Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
4327c478bd9Sstevel@tonic-gate 			return (IBT_PATH_PKT_LT_TOO_HIGH);
4337c478bd9Sstevel@tonic-gate 		}
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 		if (port_no != alt_port_no) {
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 			status = ibt_get_port_state_byguid(hcap->hca_guid,
4387c478bd9Sstevel@tonic-gate 			    alt_port_no, NULL, &base_lid);
4397c478bd9Sstevel@tonic-gate 			if (status != IBT_SUCCESS) {
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
4427c478bd9Sstevel@tonic-gate 				    "chan 0x%p alt_port_num %d inactive %d",
4437c478bd9Sstevel@tonic-gate 				    channel, alt_port_no, status);
4447c478bd9Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
4457c478bd9Sstevel@tonic-gate 				return (status);
4467c478bd9Sstevel@tonic-gate 			}
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 		}
4497c478bd9Sstevel@tonic-gate 		alternate_slid =
4507c478bd9Sstevel@tonic-gate 		    base_lid + IBCM_ALT_ADDS_VECT(chan_args).av_src_path;
4517c478bd9Sstevel@tonic-gate 
4525c42ea03Shiremath 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
4537c478bd9Sstevel@tonic-gate 		    "alternate SLID = %x", channel, alternate_slid);
4547c478bd9Sstevel@tonic-gate 	}
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	/*
4577c478bd9Sstevel@tonic-gate 	 * only pkey needs to be zero'ed, because all other fields are set in
4587c478bd9Sstevel@tonic-gate 	 * in ibcm_init_reply_addr. But, let's bzero the complete struct for
4597c478bd9Sstevel@tonic-gate 	 * any future modifications.
4607c478bd9Sstevel@tonic-gate 	 */
4617c478bd9Sstevel@tonic-gate 	bzero(&cm_reply_addr, sizeof (cm_reply_addr));
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	/* Initialize the MAD destination address in stored_reply_addr */
4647c478bd9Sstevel@tonic-gate 	if ((status = ibcm_init_reply_addr(hcap, &cm_reply_addr, chan_args,
4657c478bd9Sstevel@tonic-gate 	    flags, &cm_pkt_lt, primary_slid)) != IBT_SUCCESS) {
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4687c478bd9Sstevel@tonic-gate 		    "ibcm_init_reply_addr failed status %d ", channel, status);
4697c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
4707c478bd9Sstevel@tonic-gate 		return (status);
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	/* Initialize the pkey for CM MAD communication */
4757c478bd9Sstevel@tonic-gate 	if (cm_reply_addr.rcvd_addr.ia_p_key == 0)
4767c478bd9Sstevel@tonic-gate 		cm_reply_addr.rcvd_addr.ia_p_key = prim_pkey;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate #ifdef DEBUG
4797c478bd9Sstevel@tonic-gate 	ibcm_print_reply_addr(channel, &cm_reply_addr);
4807c478bd9Sstevel@tonic-gate #endif
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	/* Retrieve an ibmf qp for sending CM MADs */
4837c478bd9Sstevel@tonic-gate 	if ((cm_qp_entry = ibcm_find_qp(hcap, port_no,
4847c478bd9Sstevel@tonic-gate 	    cm_reply_addr.rcvd_addr.ia_p_key)) == NULL) {
4857c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4867c478bd9Sstevel@tonic-gate 		    "unable to allocate ibmf qp for CM MADs", channel);
4877c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
4887c478bd9Sstevel@tonic-gate 		return (IBT_INSUFF_RESOURCE);
4897c478bd9Sstevel@tonic-gate 	}
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
4937c478bd9Sstevel@tonic-gate 		ibcm_release_qp(cm_qp_entry);
4947c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
4957c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
4967c478bd9Sstevel@tonic-gate 		    " Unable to allocate comid", channel);
4977c478bd9Sstevel@tonic-gate 		return (IBT_INSUFF_KERNEL_RESOURCE);
4987c478bd9Sstevel@tonic-gate 	}
4997c478bd9Sstevel@tonic-gate 
500934f0bccShiremath 	/* allocate an IBMF mad buffer (REQ) */
5017c478bd9Sstevel@tonic-gate 	if ((status = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg,
5027c478bd9Sstevel@tonic-gate 	    MAD_METHOD_SEND)) != IBT_SUCCESS) {
5037c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
5047c478bd9Sstevel@tonic-gate 		    "chan 0x%p ibcm_alloc_out_msg failed", channel);
5057c478bd9Sstevel@tonic-gate 		ibcm_release_qp(cm_qp_entry);
5067c478bd9Sstevel@tonic-gate 		ibcm_free_comid(hcap, local_comid);
5077c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
5087c478bd9Sstevel@tonic-gate 		return (status);
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 
511934f0bccShiremath 	/* allocate an IBMF mad buffer (DREQ) */
512934f0bccShiremath 	if ((status = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg_dreq,
513934f0bccShiremath 	    MAD_METHOD_SEND)) != IBT_SUCCESS) {
514934f0bccShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
515934f0bccShiremath 		    "chan 0x%p ibcm_alloc_out_msg failed", channel);
516934f0bccShiremath 		(void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg);
517934f0bccShiremath 		ibcm_release_qp(cm_qp_entry);
518934f0bccShiremath 		ibcm_free_comid(hcap, local_comid);
519934f0bccShiremath 		ibcm_dec_hca_acc_cnt(hcap);
520934f0bccShiremath 		return (status);
521934f0bccShiremath 	}
522934f0bccShiremath 
5237c478bd9Sstevel@tonic-gate 	/* Init to Init, if QP's port does not match with path information */
5247c478bd9Sstevel@tonic-gate 	if (qp_query_attr.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
5257c478bd9Sstevel@tonic-gate 	    IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num) {
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 		ibt_qp_info_t		qp_info;
5287c478bd9Sstevel@tonic-gate 		ibt_cep_modify_flags_t	cep_flags;
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5317c478bd9Sstevel@tonic-gate 		    "chan 0x%p chan port %d", channel,
5327c478bd9Sstevel@tonic-gate 		    qp_query_attr.qp_info.qp_transport.rc.rc_path.\
5337c478bd9Sstevel@tonic-gate 		    cep_hca_port_num);
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5367c478bd9Sstevel@tonic-gate 		    "chan 0x%p path port %d", channel, port_no);
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 		bzero(&qp_info, sizeof (qp_info));
5397c478bd9Sstevel@tonic-gate 		/* For now, set it to RC type */
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		qp_info.qp_trans = IBT_RC_SRV;
5427c478bd9Sstevel@tonic-gate 		qp_info.qp_state = IBT_STATE_INIT;
5437c478bd9Sstevel@tonic-gate 		qp_info.qp_transport.rc.rc_path.cep_hca_port_num = port_no;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 		cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 		status = ibt_modify_qp(channel, cep_flags, &qp_info, NULL);
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
5507c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
5517c478bd9Sstevel@tonic-gate 			    "chan 0x%p ibt_modify_qp() = %d", channel, status);
5527c478bd9Sstevel@tonic-gate 			ibcm_release_qp(cm_qp_entry);
5537c478bd9Sstevel@tonic-gate 			ibcm_free_comid(hcap, local_comid);
5547c478bd9Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
5557c478bd9Sstevel@tonic-gate 			(void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg);
556934f0bccShiremath 			(void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg_dreq);
5577c478bd9Sstevel@tonic-gate 			return (status);
5587c478bd9Sstevel@tonic-gate 		} else
5597c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5607c478bd9Sstevel@tonic-gate 			    "chan 0x%p ibt_modify_qp() = %d", channel, status);
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	/* allocate ibcm_state_data_t before grabbing the WRITER lock */
5647c478bd9Sstevel@tonic-gate 	statep = kmem_zalloc(sizeof (ibcm_state_data_t), KM_SLEEP);
5657c478bd9Sstevel@tonic-gate 	rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
5667c478bd9Sstevel@tonic-gate 	lkup_status = ibcm_lookup_msg(IBCM_OUTGOING_REQ, local_comid, 0, 0,
5677c478bd9Sstevel@tonic-gate 	    hcap, &statep);
5687c478bd9Sstevel@tonic-gate 	rw_exit(&hcap->hca_state_rwlock);
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	/* CM should be seeing this for the first time */
5717c478bd9Sstevel@tonic-gate 	ASSERT(lkup_status == IBCM_LOOKUP_NEW);
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	/* Increment the hca's resource count */
5747c478bd9Sstevel@tonic-gate 	ibcm_inc_hca_res_cnt(hcap);
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	/* Once a resource created on hca, no need to hold the acc cnt */
5777c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	statep->timerid = 0;
5827c478bd9Sstevel@tonic-gate 	statep->local_hca_guid = hca_guid;
5837c478bd9Sstevel@tonic-gate 	statep->local_qpn = local_qpn;
5847c478bd9Sstevel@tonic-gate 	statep->stored_reply_addr.cm_qp_entry = cm_qp_entry;
5857c478bd9Sstevel@tonic-gate 	statep->prim_port = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
5867c478bd9Sstevel@tonic-gate 	statep->alt_port = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	/* Save "statep" as channel's CM private data.  */
5907c478bd9Sstevel@tonic-gate 	statep->channel = channel;
5917c478bd9Sstevel@tonic-gate 	IBCM_SET_CHAN_PRIVATE(statep->channel, statep);
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	statep->stored_msg = ibmf_msg;
594934f0bccShiremath 	statep->dreq_msg = ibmf_msg_dreq;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*req_msgp))
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	/* Start filling in the REQ MAD */
5997c478bd9Sstevel@tonic-gate 	req_msgp = (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6007c478bd9Sstevel@tonic-gate 	req_msgp->req_local_comm_id = h2b32(local_comid);
6017c478bd9Sstevel@tonic-gate 	req_msgp->req_svc_id = h2b64(chan_args->oc_path->pi_sid);
6027c478bd9Sstevel@tonic-gate 	req_msgp->req_local_ca_guid = h2b64(hca_guid);
6037c478bd9Sstevel@tonic-gate 	req_msgp->req_local_qkey = h2b32(local_qkey);	/* for EEC/RD */
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	/* Bytes 32-35 are req_local_qpn and req_off_resp_resources */
6067c478bd9Sstevel@tonic-gate 	req_msgp->req_local_qpn_plus = h2b32(local_qpn << 8 | rdma_in);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	/* Bytes 36-39 are req_local_eec_no and req_off_initiator_depth */
6097c478bd9Sstevel@tonic-gate 	req_msgp->req_local_eec_no_plus = h2b32(local_eecn << 8 | rdma_out);
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	if (flags & IBT_OCHAN_REMOTE_CM_TM)
6127c478bd9Sstevel@tonic-gate 		remote_cm_resp_time = chan_args->oc_remote_cm_time;
6137c478bd9Sstevel@tonic-gate 	else
6147c478bd9Sstevel@tonic-gate 		remote_cm_resp_time = ibcm_remote_response_time;
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	/*
6177c478bd9Sstevel@tonic-gate 	 * Bytes 40-43 - remote_eecn, remote_cm_resp_time, tran_type,
6187c478bd9Sstevel@tonic-gate 	 * IBT_CM_FLOW_CONTROL is always set by default.
6197c478bd9Sstevel@tonic-gate 	 */
6207c478bd9Sstevel@tonic-gate 	req_msgp->req_remote_eecn_plus = h2b32(
6217c478bd9Sstevel@tonic-gate 	    remote_eecn << 8 | (ibt_usec2ib(remote_cm_resp_time) & 0x1f) << 3 |
6227c478bd9Sstevel@tonic-gate 	    IBT_RC_SRV << 1 | IBT_CM_FLOW_CONTROL);
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	if (flags & IBT_OCHAN_LOCAL_CM_TM)
6257c478bd9Sstevel@tonic-gate 		local_cm_proc_time = chan_args->oc_local_cm_time;
6267c478bd9Sstevel@tonic-gate 	else
6277c478bd9Sstevel@tonic-gate 		local_cm_proc_time = ibcm_local_processing_time;
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	local_cm_resp_time = ibt_usec2ib(local_cm_proc_time +
6307c478bd9Sstevel@tonic-gate 	    2 * ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt) +
6317c478bd9Sstevel@tonic-gate 	    ibcm_sw_delay);
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	/* save retry count */
6347c478bd9Sstevel@tonic-gate 	statep->cep_retry_cnt = chan_args->oc_path_retry_cnt;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	if (flags & IBT_OCHAN_STARTING_PSN)
6377c478bd9Sstevel@tonic-gate 		starting_psn = chan_args->oc_starting_psn;
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	if (local_cm_resp_time > 0x1f)
6407c478bd9Sstevel@tonic-gate 		local_cm_resp_time = 0x1f;
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	/* Bytes 44-47 are req_starting_psn, local_cm_resp_time and retry_cnt */
6437c478bd9Sstevel@tonic-gate 	req_msgp->req_starting_psn_plus = h2b32(starting_psn << 8 |
6447c478bd9Sstevel@tonic-gate 	    local_cm_resp_time << 3 | statep->cep_retry_cnt);
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6477c478bd9Sstevel@tonic-gate 	    "Prim Pkt lt (IB time) 0x%x", channel,
6487c478bd9Sstevel@tonic-gate 	    chan_args->oc_path->pi_prim_pkt_lt);
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6517c478bd9Sstevel@tonic-gate 	    "local_cm_proc_time(usec) %d ", channel, local_cm_proc_time);
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6547c478bd9Sstevel@tonic-gate 	    "local_cm_resp_time(ib_time) %d", channel, local_cm_resp_time);
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6577c478bd9Sstevel@tonic-gate 	    "remote_cm_resp_time (usec) %d", channel, remote_cm_resp_time);
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 	statep->starting_psn = starting_psn;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	/* Pkey - bytes 48-49 */
6627c478bd9Sstevel@tonic-gate 	req_msgp->req_part_key = h2b16(prim_pkey);
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	if (flags & IBT_OCHAN_CM_RETRY)
6657c478bd9Sstevel@tonic-gate 		cm_retries = chan_args->oc_cm_retry_cnt;
6667c478bd9Sstevel@tonic-gate 	else
6677c478bd9Sstevel@tonic-gate 		cm_retries = ibcm_max_retries;
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	statep->max_cm_retries = statep->remaining_retry_cnt = cm_retries;
6707c478bd9Sstevel@tonic-gate 	req_msgp->req_max_cm_retries_plus = statep->max_cm_retries << 4;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	/*
6737c478bd9Sstevel@tonic-gate 	 * Check whether SRQ is associated with this Channel, if yes, then
6747c478bd9Sstevel@tonic-gate 	 * set the SRQ Exists bit in the REQ.
6757c478bd9Sstevel@tonic-gate 	 */
6767c478bd9Sstevel@tonic-gate 	if (qp_query_attr.qp_srq != NULL) {
6777c478bd9Sstevel@tonic-gate 		req_msgp->req_max_cm_retries_plus |= (1 << 3);
6787c478bd9Sstevel@tonic-gate 	}
6797c478bd9Sstevel@tonic-gate 
680934f0bccShiremath 	/*
681934f0bccShiremath 	 * By default on Tavor, we override the PathMTU to 1K.
682934f0bccShiremath 	 * To turn this off, set ibcm_override_path_mtu = 0.
683934f0bccShiremath 	 */
684934f0bccShiremath 	if (ibcm_override_path_mtu && IBCM_IS_HCA_TAVOR(hcap) &&
685934f0bccShiremath 	    (chan_args->oc_path->pi_path_mtu > IB_MTU_1K)) {
686934f0bccShiremath 		req_msgp->req_mtu_plus = IB_MTU_1K << 4 |
687934f0bccShiremath 		    chan_args->oc_path_rnr_retry_cnt;
688934f0bccShiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p PathMTU"
689f07a6d2aSShantkumar Hiremath 		    " overridden to IB_MTU_1K(%d) from %d", channel, IB_MTU_1K,
690934f0bccShiremath 		    chan_args->oc_path->pi_path_mtu);
691934f0bccShiremath 	} else
6927c478bd9Sstevel@tonic-gate 		req_msgp->req_mtu_plus = chan_args->oc_path->pi_path_mtu << 4 |
6937c478bd9Sstevel@tonic-gate 		    chan_args->oc_path_rnr_retry_cnt;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p CM retry cnt %d"
6967c478bd9Sstevel@tonic-gate 	    " staring PSN %x", channel, cm_retries, starting_psn);
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate #ifdef	NO_EEC_SUPPORT_YET
7007c478bd9Sstevel@tonic-gate 	if (flags & IBT_OCHAN_RDC_EXISTS)
7017c478bd9Sstevel@tonic-gate 		req_msgp->req_mtu_plus |= 8;
7027c478bd9Sstevel@tonic-gate #endif
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	/* Initialize the "primary" port stuff next - bytes 52-95 */
7057c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_l_port_lid = h2b16(primary_slid);
7067c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_r_port_lid =
7077c478bd9Sstevel@tonic-gate 	    h2b16(IBCM_PRIM_ADDS_VECT(chan_args).av_dlid);
7087c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_l_port_gid.gid_prefix =
7097c478bd9Sstevel@tonic-gate 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_sgid.gid_prefix);
7107c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_l_port_gid.gid_guid =
7117c478bd9Sstevel@tonic-gate 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_sgid.gid_guid);
7127c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_r_port_gid.gid_prefix =
7137c478bd9Sstevel@tonic-gate 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_prefix);
7147c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_r_port_gid.gid_guid =
7157c478bd9Sstevel@tonic-gate 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid);
7167c478bd9Sstevel@tonic-gate 	primary_grh = IBCM_PRIM_ADDS_VECT(chan_args).av_send_grh;
7177c478bd9Sstevel@tonic-gate 
7189d3d2ed0Shiremath 	statep->remote_hca_guid = /* not correct, but helpful for debugging */
7199d3d2ed0Shiremath 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid;
7209d3d2ed0Shiremath 
7217c478bd9Sstevel@tonic-gate 	/* Bytes 88-91 - primary_flowlbl, and primary_srate */
7227c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_flow_label_plus =
7237c478bd9Sstevel@tonic-gate 	    h2b32(((primary_grh == B_TRUE) ?
7247c478bd9Sstevel@tonic-gate 	    (IBCM_PRIM_ADDS_VECT(chan_args).av_flow << 12) : 0) |
7257c478bd9Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_srate);
7267c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_traffic_class = (primary_grh == B_TRUE) ?
7277c478bd9Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_tclass : 0;
7287c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_hop_limit = (primary_grh == B_TRUE) ?
7296db9c6ddShiremath 	    IBCM_PRIM_ADDS_VECT(chan_args).av_hop : 1;
7307c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_sl_plus =
7317c478bd9Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_srvl << 4 |
7327c478bd9Sstevel@tonic-gate 	    ((primary_grh == B_TRUE) ? 0 : 8);
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	req_msgp->req_primary_localtime_plus =
7357c478bd9Sstevel@tonic-gate 	    ibt_usec2ib((2 * ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt)) +
7367c478bd9Sstevel@tonic-gate 	    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan %p statep %p",
7397c478bd9Sstevel@tonic-gate 	    channel, statep);
7407c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7417c478bd9Sstevel@tonic-gate 	    "active hca_ack_delay (usec) %d", channel,
7427c478bd9Sstevel@tonic-gate 	    req_msgp->req_primary_localtime_plus);
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7457c478bd9Sstevel@tonic-gate 	    "Sent primary cep timeout (IB Time) %d", channel,
7467c478bd9Sstevel@tonic-gate 	    hcap->hca_ack_delay);
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p prim_dlid %x ",
7497c478bd9Sstevel@tonic-gate 	    channel, IBCM_PRIM_ADDS_VECT(chan_args).av_dlid);
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7529d3d2ed0Shiremath 	    "prim GID %llX:%llX", channel,
7539d3d2ed0Shiremath 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_prefix,
7547c478bd9Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid);
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	/* Initialize the "alternate" port stuff - optional */
7577c478bd9Sstevel@tonic-gate 	if (chan_args->oc_path->pi_alt_cep_path.cep_hca_port_num != 0) {
7587c478bd9Sstevel@tonic-gate 		ib_gid_t	tmp_gid;
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 		req_msgp->req_alt_l_port_lid = h2b16(alternate_slid);
7617c478bd9Sstevel@tonic-gate 		req_msgp->req_alt_r_port_lid =
7627c478bd9Sstevel@tonic-gate 		    h2b16(IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
7637c478bd9Sstevel@tonic-gate 		/*
7647c478bd9Sstevel@tonic-gate 		 * doing all this as req_alt_r/l_port_gid is at offset
7657c478bd9Sstevel@tonic-gate 		 * 100, 116 which is not divisible by 8
7667c478bd9Sstevel@tonic-gate 		 */
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 		tmp_gid.gid_prefix =
7697c478bd9Sstevel@tonic-gate 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix);
7707c478bd9Sstevel@tonic-gate 		tmp_gid.gid_guid =
7717c478bd9Sstevel@tonic-gate 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
7727c478bd9Sstevel@tonic-gate 		bcopy(&tmp_gid, &req_msgp->req_alt_r_port_gid[0],
7737c478bd9Sstevel@tonic-gate 		    sizeof (ib_gid_t));
7747c478bd9Sstevel@tonic-gate 		tmp_gid.gid_prefix =
7757c478bd9Sstevel@tonic-gate 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_sgid.gid_prefix);
7767c478bd9Sstevel@tonic-gate 		tmp_gid.gid_guid =
7777c478bd9Sstevel@tonic-gate 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_sgid.gid_guid);
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 		bcopy(&tmp_gid, &req_msgp->req_alt_l_port_gid[0],
7807c478bd9Sstevel@tonic-gate 		    sizeof (ib_gid_t));
7817c478bd9Sstevel@tonic-gate 		alternate_grh = IBCM_ALT_ADDS_VECT(chan_args).av_send_grh;
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 		/* Bytes 132-135 - alternate_flow_label, and alternate srate */
7847c478bd9Sstevel@tonic-gate 		req_msgp->req_alt_flow_label_plus = h2b32(
7857c478bd9Sstevel@tonic-gate 		    (((alternate_grh == B_TRUE) ?
7867c478bd9Sstevel@tonic-gate 		    (IBCM_ALT_ADDS_VECT(chan_args).av_flow << 12) : 0) |
7877c478bd9Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_srate));
7887c478bd9Sstevel@tonic-gate 		req_msgp->req_alt_traffic_class = (alternate_grh == B_TRUE) ?
7897c478bd9Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_tclass : 0;
7907c478bd9Sstevel@tonic-gate 		req_msgp->req_alt_hop_limit = (alternate_grh == B_TRUE) ?
7916db9c6ddShiremath 		    IBCM_ALT_ADDS_VECT(chan_args).av_hop : 1;
7927c478bd9Sstevel@tonic-gate 		req_msgp->req_alt_sl_plus =
7937c478bd9Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_srvl << 4 |
7947c478bd9Sstevel@tonic-gate 		    ((alternate_grh == B_TRUE) ? 0 : 8);
7957c478bd9Sstevel@tonic-gate 		req_msgp->req_alt_localtime_plus = ibt_usec2ib((2 *
7967c478bd9Sstevel@tonic-gate 		    ibt_ib2usec(chan_args->oc_path->pi_alt_pkt_lt)) +
7977c478bd9Sstevel@tonic-gate 		    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
8007c478bd9Sstevel@tonic-gate 		    "alt_dlid %x ", channel,
8017c478bd9Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
8049d3d2ed0Shiremath 		    "alt GID %llX:%llX", channel,
8059d3d2ed0Shiremath 		    IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix,
8067c478bd9Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
8077c478bd9Sstevel@tonic-gate 	}
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	len = min(chan_args->oc_priv_data_len, IBT_REQ_PRIV_DATA_SZ);
8107c478bd9Sstevel@tonic-gate 	if ((len > 0) && chan_args->oc_priv_data)
8117c478bd9Sstevel@tonic-gate 		bcopy(chan_args->oc_priv_data, req_msgp->req_private_data, len);
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*req_msgp))
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	/* return_data is filled up in the state machine code */
8167c478bd9Sstevel@tonic-gate 	if (ret_args != NULL) {
8177c478bd9Sstevel@tonic-gate 		statep->open_return_data = ret_args;
8187c478bd9Sstevel@tonic-gate 	}
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	/* initialize some statep fields here */
8217c478bd9Sstevel@tonic-gate 	statep->mode = IBCM_ACTIVE_MODE;
8227c478bd9Sstevel@tonic-gate 	statep->hcap = hcap;
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	statep->cm_handler = chan_args->oc_cm_handler;
8257c478bd9Sstevel@tonic-gate 	statep->state_cm_private = chan_args->oc_cm_clnt_private;
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	statep->pkt_life_time =
8287c478bd9Sstevel@tonic-gate 	    ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt);
8297c478bd9Sstevel@tonic-gate 
8309d3d2ed0Shiremath 	statep->timer_value = ibt_ib2usec(ibt_usec2ib(
8319d3d2ed0Shiremath 	    2 * ibt_ib2usec(cm_pkt_lt) + remote_cm_resp_time));
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	/* Initialize statep->stored_reply_addr */
8347c478bd9Sstevel@tonic-gate 	statep->stored_reply_addr.ibmf_hdl = ibmf_hdl;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	/* Initialize stored reply addr fields */
8377c478bd9Sstevel@tonic-gate 	statep->stored_reply_addr.grh_hdr = cm_reply_addr.grh_hdr;
8387c478bd9Sstevel@tonic-gate 	statep->stored_reply_addr.rcvd_addr = cm_reply_addr.rcvd_addr;
8397c478bd9Sstevel@tonic-gate 	statep->stored_reply_addr.grh_exists = cm_reply_addr.grh_exists;
8407c478bd9Sstevel@tonic-gate 	statep->stored_reply_addr.port_num = cm_reply_addr.port_num;
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	/*
8437c478bd9Sstevel@tonic-gate 	 * The IPD on local/active side is calculated by path functions,
8447c478bd9Sstevel@tonic-gate 	 * hence available in the args of ibt_open_rc_channel
8457c478bd9Sstevel@tonic-gate 	 */
8467c478bd9Sstevel@tonic-gate 	statep->local_srate = IBCM_PRIM_ADDS_VECT(chan_args).av_srate;
8477c478bd9Sstevel@tonic-gate 	statep->local_alt_srate = IBCM_ALT_ADDS_VECT(chan_args).av_srate;
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	/* Store the source path bits for primary and alt paths */
8507c478bd9Sstevel@tonic-gate 	statep->prim_src_path_bits = IBCM_PRIM_ADDS_VECT(chan_args).av_src_path;
8517c478bd9Sstevel@tonic-gate 	statep->alt_src_path_bits = IBCM_ALT_ADDS_VECT(chan_args).av_src_path;
8527c478bd9Sstevel@tonic-gate 
8539d3d2ed0Shiremath 	statep->open_flow = 1;
8547c478bd9Sstevel@tonic-gate 	statep->open_done = B_FALSE;
8557c478bd9Sstevel@tonic-gate 	statep->state = statep->timer_stored_state = IBCM_STATE_REQ_SENT;
8569d3d2ed0Shiremath 	IBCM_REF_CNT_INCR(statep);	/* Decremented before return */
8579d3d2ed0Shiremath 	IBCM_REF_CNT_INCR(statep);	/* Decremented after REQ is posted */
8587c478bd9Sstevel@tonic-gate 	statep->send_mad_flags |= IBCM_REQ_POST_BUSY;
8597c478bd9Sstevel@tonic-gate 
8609c468ea9SPramod Gunjikar 	/*
8619c468ea9SPramod Gunjikar 	 * Skip moving channel to error state during close, for OFUV clients.
8629c468ea9SPramod Gunjikar 	 * OFUV clients transition the channel to error state by itself.
8639c468ea9SPramod Gunjikar 	 */
8649c468ea9SPramod Gunjikar 	if (flags & IBT_OCHAN_OFUV)
8659c468ea9SPramod Gunjikar 		statep->is_this_ofuv_chan = B_TRUE;
8669c468ea9SPramod Gunjikar 
8677c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
8687c478bd9Sstevel@tonic-gate 	    h2b16(IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID);
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->stored_msg)->TransactionID =
8717c478bd9Sstevel@tonic-gate 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_REQ, statep->local_comid,
8727c478bd9Sstevel@tonic-gate 	    0));
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
8757c478bd9Sstevel@tonic-gate 
8769c468ea9SPramod Gunjikar 	ibtl_cm_chan_is_opening(channel);
8779c468ea9SPramod Gunjikar 
8789d3d2ed0Shiremath 	ibcm_open_enqueue(statep);
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 		/* wait for REQ/REP/RTU */
8857c478bd9Sstevel@tonic-gate 		while (statep->open_done != B_TRUE) {
8867c478bd9Sstevel@tonic-gate 			cv_wait(&statep->block_client_cv, &statep->state_mutex);
8877c478bd9Sstevel@tonic-gate 		}
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 		/*
8907c478bd9Sstevel@tonic-gate 		 * In the case that open_channel() fails because of a
8917c478bd9Sstevel@tonic-gate 		 * REJ or timeout, change retval to IBT_CM_FAILURE
8927c478bd9Sstevel@tonic-gate 		 */
8932c2d21e9SRichard Lowe 		if (statep->open_return_data->rc_status != IBT_CM_SUCCESS) {
8947c478bd9Sstevel@tonic-gate 			status = IBT_CM_FAILURE;
895a23420cfSShantkumar Hiremath 			ibtl_cm_chan_open_is_aborted(channel);
896a23420cfSShantkumar Hiremath 		}
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p "
8997c478bd9Sstevel@tonic-gate 		    "ret status %d cm status %d", channel, status,
9007c478bd9Sstevel@tonic-gate 		    statep->open_return_data->rc_status);
9017c478bd9Sstevel@tonic-gate 	}
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	/* decrement the ref-count before leaving here */
9047c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_open_rc_channel: chan 0x%p done", channel);
9097c478bd9Sstevel@tonic-gate 	return (status);
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate /*
9137c478bd9Sstevel@tonic-gate  * ibcm_init_reply_addr:
9147c478bd9Sstevel@tonic-gate  *
9157c478bd9Sstevel@tonic-gate  * The brief description of functionality below.
9167c478bd9Sstevel@tonic-gate  *
9177c478bd9Sstevel@tonic-gate  * For IBT_OCHAN_PORT_REDIRECTED (ie., port redirected case):
9187c478bd9Sstevel@tonic-gate  *	Build CM path from chan_args->oc_cm_cep_path
9197c478bd9Sstevel@tonic-gate  *	Set CM pkt lt (ie.,life time) to chan_args->oc_cm_pkt_lt
9207c478bd9Sstevel@tonic-gate  *
9217c478bd9Sstevel@tonic-gate  * For IBT_OCHAN_REDIRECTED (ie., port and CM redirected case):
9227c478bd9Sstevel@tonic-gate  *	If Redirect LID is specified,
9237c478bd9Sstevel@tonic-gate  *		If Redirect GID is not specified or specified to be on the same
9247c478bd9Sstevel@tonic-gate  *		    subnet, then
9257c478bd9Sstevel@tonic-gate  *			Build CM path from chan_args->oc_cm_redirect_info
9267c478bd9Sstevel@tonic-gate  *			Set CM pkt lt to subnet timeout
9277c478bd9Sstevel@tonic-gate  *		Else (ie., GID specified, but on a different subnet)
9287c478bd9Sstevel@tonic-gate  *			Do a path lookup to build CM Path and set CM pkt lt
9297c478bd9Sstevel@tonic-gate  *
9307c478bd9Sstevel@tonic-gate  */
9317c478bd9Sstevel@tonic-gate static ibt_status_t
ibcm_init_reply_addr(ibcm_hca_info_t * hcap,ibcm_mad_addr_t * reply_addr,ibt_chan_open_args_t * chan_args,ibt_chan_open_flags_t flags,ib_time_t * cm_pkt_lt,ib_lid_t prim_slid)9327c478bd9Sstevel@tonic-gate ibcm_init_reply_addr(ibcm_hca_info_t *hcap, ibcm_mad_addr_t *reply_addr,
9337c478bd9Sstevel@tonic-gate     ibt_chan_open_args_t *chan_args, ibt_chan_open_flags_t flags,
9347c478bd9Sstevel@tonic-gate     ib_time_t *cm_pkt_lt, ib_lid_t prim_slid)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate 	ibt_adds_vect_t	*cm_adds;
9377c478bd9Sstevel@tonic-gate 	ibt_path_info_t	path;
9387c478bd9Sstevel@tonic-gate 	boolean_t	cm_grh;
9397c478bd9Sstevel@tonic-gate 	ibt_status_t	status;
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_init_reply_addr:");
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*reply_addr))
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	/*
9467c478bd9Sstevel@tonic-gate 	 * sending side CM lid/gid/port num are not based on any redirect
9477c478bd9Sstevel@tonic-gate 	 * params. These values are set to primary RC path lid/gid/port num.
9487c478bd9Sstevel@tonic-gate 	 * In the future, these values can be set based on framework policy
9497c478bd9Sstevel@tonic-gate 	 * decisions ensuring reachability.
9507c478bd9Sstevel@tonic-gate 	 */
9517c478bd9Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_sender_gid =
9527c478bd9Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_sgid;
9537c478bd9Sstevel@tonic-gate 	reply_addr->rcvd_addr.ia_local_lid = prim_slid;
9547c478bd9Sstevel@tonic-gate 	reply_addr->port_num = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 	if (flags & IBT_OCHAN_PORT_REDIRECTED) {
9577c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
9587c478bd9Sstevel@tonic-gate 		    "IBT_OCHAN_PORT_REDIRECTED specified");
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 		status = ibt_index2pkey_byguid(hcap->hca_guid,
9617c478bd9Sstevel@tonic-gate 		    chan_args->oc_cm_cep_path->cep_hca_port_num,
9627c478bd9Sstevel@tonic-gate 		    chan_args->oc_cm_cep_path->cep_pkey_ix,
9637c478bd9Sstevel@tonic-gate 		    &reply_addr->rcvd_addr.ia_p_key);
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
9667c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_init_rely_addr: Invalid "
9677c478bd9Sstevel@tonic-gate 			    "CM PKeyIx %x port_num %x",
9687c478bd9Sstevel@tonic-gate 			    chan_args->oc_cm_cep_path->cep_pkey_ix,
9697c478bd9Sstevel@tonic-gate 			    chan_args->oc_cm_cep_path->cep_hca_port_num);
9707c478bd9Sstevel@tonic-gate 			return (status);
9717c478bd9Sstevel@tonic-gate 		}
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 		cm_adds = &(chan_args->oc_cm_cep_path->cep_adds_vect);
9747c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: dlid = %x",
9757c478bd9Sstevel@tonic-gate 		    cm_adds->av_dlid);
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_q_key = IB_GSI_QKEY;
9787c478bd9Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_remote_qno = 1;
9797c478bd9Sstevel@tonic-gate 		*cm_pkt_lt = chan_args->oc_cm_pkt_lt;
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 	} else if (flags & IBT_OCHAN_REDIRECTED) {
9827c478bd9Sstevel@tonic-gate 		ibt_redirect_info_t	*redirect_info;
9837c478bd9Sstevel@tonic-gate 		ibt_hca_portinfo_t	*port_infop;
9847c478bd9Sstevel@tonic-gate 		uint_t			psize, nports;
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
9877c478bd9Sstevel@tonic-gate 		    "IBT_OCHAN_REDIRECTED specified");
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 		redirect_info = chan_args->oc_cm_redirect_info;
9907c478bd9Sstevel@tonic-gate 
9919d3d2ed0Shiremath 		if ((redirect_info->rdi_gid.gid_prefix == 0) ||
9929d3d2ed0Shiremath 		    (redirect_info->rdi_gid.gid_guid == 0)) {
9939d3d2ed0Shiremath 			IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
9949d3d2ed0Shiremath 			    "ERROR: Re-direct GID value NOT Provided.");
9959d3d2ed0Shiremath 			return (IBT_INVALID_PARAM);
9969d3d2ed0Shiremath 		}
9979d3d2ed0Shiremath 
9987c478bd9Sstevel@tonic-gate 		/* As per spec definition 1.1, it's always IB_GSI_QKEY */
9997c478bd9Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_q_key = redirect_info->rdi_qkey;
10007c478bd9Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_remote_qno = redirect_info->rdi_qpn;
10017c478bd9Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_p_key = redirect_info->rdi_pkey;
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 		/*
10049d3d2ed0Shiremath 		 * if LID is non-zero in classportinfo then use classportinfo
10059d3d2ed0Shiremath 		 * fields to form CM MAD destination address.
10067c478bd9Sstevel@tonic-gate 		 */
10079d3d2ed0Shiremath 		if (redirect_info->rdi_dlid != 0) {
10087c478bd9Sstevel@tonic-gate 			status = ibtl_cm_query_hca_ports_byguid(hcap->hca_guid,
10097c478bd9Sstevel@tonic-gate 			    reply_addr->port_num, &port_infop, &nports, &psize);
10107c478bd9Sstevel@tonic-gate 			if ((status != IBT_SUCCESS) || (nports == 0)) {
10117c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
10127c478bd9Sstevel@tonic-gate 				    "Query Ports Failed: %d", status);
10137c478bd9Sstevel@tonic-gate 				return (status);
10147c478bd9Sstevel@tonic-gate 			} else if (port_infop->p_subnet_timeout >
1015bbd67193Shiremath 			    ibcm_max_ib_pkt_lt) {
10167c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
10177c478bd9Sstevel@tonic-gate 				    "large subnet timeout %x port_no %x",
10187c478bd9Sstevel@tonic-gate 				    port_infop->p_subnet_timeout,
10197c478bd9Sstevel@tonic-gate 				    reply_addr->port_num);
10207c478bd9Sstevel@tonic-gate 				ibt_free_portinfo(port_infop, psize);
10217c478bd9Sstevel@tonic-gate 				return (IBT_PATH_PKT_LT_TOO_HIGH);
10227c478bd9Sstevel@tonic-gate 			} else {
10237c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibcm_init_reply_addr: "
10247c478bd9Sstevel@tonic-gate 				    "subnet timeout %x port_no %x",
10257c478bd9Sstevel@tonic-gate 				    port_infop->p_subnet_timeout,
10267c478bd9Sstevel@tonic-gate 				    reply_addr->port_num);
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 				*cm_pkt_lt =
10297c478bd9Sstevel@tonic-gate 				    ibt_ib2usec(min(ibcm_max_ib_mad_pkt_lt,
10307c478bd9Sstevel@tonic-gate 				    port_infop->p_subnet_timeout));
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 				ibt_free_portinfo(port_infop, psize);
10337c478bd9Sstevel@tonic-gate 			}
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 			reply_addr->rcvd_addr.ia_remote_lid =
10367c478bd9Sstevel@tonic-gate 			    redirect_info->rdi_dlid;
10377c478bd9Sstevel@tonic-gate 			reply_addr->rcvd_addr.ia_service_level =
10387c478bd9Sstevel@tonic-gate 			    redirect_info->rdi_sl;
10397c478bd9Sstevel@tonic-gate 			reply_addr->grh_exists = B_TRUE;
10407c478bd9Sstevel@tonic-gate 			reply_addr->grh_hdr.ig_recver_gid =
10417c478bd9Sstevel@tonic-gate 			    redirect_info->rdi_gid;
10427c478bd9Sstevel@tonic-gate 			reply_addr->grh_hdr.ig_tclass =
10437c478bd9Sstevel@tonic-gate 			    redirect_info->rdi_tclass;
10447c478bd9Sstevel@tonic-gate 			reply_addr->grh_hdr.ig_flow_label =
10457c478bd9Sstevel@tonic-gate 			    redirect_info->rdi_flow;
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 			/* Classportinfo doesn't have hoplimit field */
10486db9c6ddShiremath 			reply_addr->grh_hdr.ig_hop_limit = 1;
10497c478bd9Sstevel@tonic-gate 			return (IBT_SUCCESS);
10507c478bd9Sstevel@tonic-gate 
10519d3d2ed0Shiremath 		} else {
10527c478bd9Sstevel@tonic-gate 			ibt_path_attr_t	path_attr;
10537c478bd9Sstevel@tonic-gate 			ib_gid_t	path_dgid[1];
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 			/*
10567c478bd9Sstevel@tonic-gate 			 * If GID is specified, and LID is zero in classportinfo
10579d3d2ed0Shiremath 			 * do a path lookup using specified GID, Pkey,
10587c478bd9Sstevel@tonic-gate 			 * in classportinfo
10597c478bd9Sstevel@tonic-gate 			 */
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 			bzero(&path_attr, sizeof (path_attr));
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 			path_attr.pa_dgids = &path_dgid[0];
10647c478bd9Sstevel@tonic-gate 			path_attr.pa_dgids[0] = redirect_info->rdi_gid;
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 			/*
10677c478bd9Sstevel@tonic-gate 			 * use reply_addr below, as sender_gid in reply_addr
10687c478bd9Sstevel@tonic-gate 			 * may have been set above based on some policy decision
10697c478bd9Sstevel@tonic-gate 			 * for originating end point for CM MADs above
10707c478bd9Sstevel@tonic-gate 			 */
10717c478bd9Sstevel@tonic-gate 			path_attr.pa_sgid = reply_addr->grh_hdr.ig_sender_gid;
10727c478bd9Sstevel@tonic-gate 			path_attr.pa_num_dgids = 1;
10737c478bd9Sstevel@tonic-gate 			path_attr.pa_pkey = redirect_info->rdi_pkey;
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 			if ((status = ibt_get_paths(ibcm_ibt_handle,
10769d3d2ed0Shiremath 			    IBT_PATH_PKEY, &path_attr, 1, &path, NULL)) !=
10777c478bd9Sstevel@tonic-gate 			    IBT_SUCCESS)
10787c478bd9Sstevel@tonic-gate 				return (status);
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 			/* Initialize cm_adds */
10817c478bd9Sstevel@tonic-gate 			cm_adds = &path.pi_prim_cep_path.cep_adds_vect;
10827c478bd9Sstevel@tonic-gate 			*cm_pkt_lt = path.pi_prim_pkt_lt;
10837c478bd9Sstevel@tonic-gate 		}
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 	} else	{ /* cm_pkey initialized in ibt_open_rc_channel */
10867c478bd9Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_q_key = IB_GSI_QKEY;
10877c478bd9Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_remote_qno = 1;
10887c478bd9Sstevel@tonic-gate 		*cm_pkt_lt = chan_args->oc_path->pi_prim_pkt_lt;
10897c478bd9Sstevel@tonic-gate 		cm_adds = &(IBCM_PRIM_ADDS_VECT(chan_args));
10907c478bd9Sstevel@tonic-gate 	}
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	cm_grh = cm_adds->av_send_grh;
10947c478bd9Sstevel@tonic-gate 	reply_addr->grh_exists = cm_grh;
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	reply_addr->rcvd_addr.ia_remote_lid =
10977c478bd9Sstevel@tonic-gate 	    cm_adds->av_dlid;
10987c478bd9Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_recver_gid =
10997c478bd9Sstevel@tonic-gate 	    cm_adds->av_dgid;
11007c478bd9Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_flow_label =
11017c478bd9Sstevel@tonic-gate 	    cm_adds->av_flow & IB_GRH_FLOW_LABEL_MASK;
11027c478bd9Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_tclass =
11037c478bd9Sstevel@tonic-gate 	    (cm_grh == B_TRUE) ? cm_adds->av_tclass : 0;
11047c478bd9Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_hop_limit =
11056db9c6ddShiremath 	    (cm_grh == B_TRUE) ? cm_adds->av_hop : 1;
11067c478bd9Sstevel@tonic-gate 	reply_addr->rcvd_addr.ia_service_level =
11077c478bd9Sstevel@tonic-gate 	    cm_adds->av_srvl;
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*reply_addr))
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
11127c478bd9Sstevel@tonic-gate }
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate /*
11167c478bd9Sstevel@tonic-gate  * ibt_prime_close_rc_channel()
11177c478bd9Sstevel@tonic-gate  *	It allocates resources required for close channel operation, so
11187c478bd9Sstevel@tonic-gate  *	ibt_close_rc_channel can be called from interrupt routine.
11197c478bd9Sstevel@tonic-gate  *
11207c478bd9Sstevel@tonic-gate  * INPUTS:
11217c478bd9Sstevel@tonic-gate  *	channel			The address of an ibt_channel_t struct that
11227c478bd9Sstevel@tonic-gate  *				specifies the channel to open.
11237c478bd9Sstevel@tonic-gate  *
11247c478bd9Sstevel@tonic-gate  * RETURN VALUES:
11257c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS	on success(or respective failure on error)
11267c478bd9Sstevel@tonic-gate  *
11277c478bd9Sstevel@tonic-gate  * Clients are typically expected to call this function in established state
11287c478bd9Sstevel@tonic-gate  */
11297c478bd9Sstevel@tonic-gate ibt_status_t
ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)11307c478bd9Sstevel@tonic-gate ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)
11317c478bd9Sstevel@tonic-gate {
11327c478bd9Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
11337c478bd9Sstevel@tonic-gate 	ibt_status_t		status = IBT_SUCCESS;
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_prime_close_rc_channel(%p)", channel);
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 	/* validate channel, first */
11387c478bd9Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
11397c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11407c478bd9Sstevel@tonic-gate 		    "invalid channel", channel);
11417c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
11427c478bd9Sstevel@tonic-gate 	}
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
11457c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11467c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel",
11477c478bd9Sstevel@tonic-gate 		    channel);
11487c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
11497c478bd9Sstevel@tonic-gate 	}
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 	/* get the statep */
11527c478bd9Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 	/*
11557c478bd9Sstevel@tonic-gate 	 * This can happen, if the statep is already gone by a DREQ from
11567c478bd9Sstevel@tonic-gate 	 * the remote side
11577c478bd9Sstevel@tonic-gate 	 */
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 	if (statep == NULL) {
11607c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11617c478bd9Sstevel@tonic-gate 		    "statep NULL", channel);
11627c478bd9Sstevel@tonic-gate 		return (IBT_SUCCESS);
11637c478bd9Sstevel@tonic-gate 	}
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
11667c478bd9Sstevel@tonic-gate 	IBCM_RELEASE_CHAN_PRIVATE(channel);
11677c478bd9Sstevel@tonic-gate 	if (statep->state != IBCM_STATE_ESTABLISHED) {
11687c478bd9Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
11697c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
11707c478bd9Sstevel@tonic-gate 	}
11717c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);
11727c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_prime_close_rc_channel: chan 0x%p statep %p"
11737c478bd9Sstevel@tonic-gate 	    " state %x", channel, statep, statep->state);
11747c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 	/* clients could pre-allocate dreq mad, even before connection est */
11777c478bd9Sstevel@tonic-gate 	if (statep->dreq_msg == NULL)
11787c478bd9Sstevel@tonic-gate 		status = ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl,
11797c478bd9Sstevel@tonic-gate 		    &statep->dreq_msg, MAD_METHOD_SEND);
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
11827c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
11837c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
11867c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11877c478bd9Sstevel@tonic-gate 		    "ibcm_alloc_out_msg failed ", channel);
11887c478bd9Sstevel@tonic-gate 		return (status);
11897c478bd9Sstevel@tonic-gate 	}
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate 	/* If this message isn't seen then ibt_prime_close_rc_channel failed */
11927c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_prime_close_rc_channel: chan 0x%p done",
11937c478bd9Sstevel@tonic-gate 	    channel);
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
11967c478bd9Sstevel@tonic-gate }
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate /*
11997c478bd9Sstevel@tonic-gate  * ibt_close_rc_channel()
12007c478bd9Sstevel@tonic-gate  *	It closes an established channel.
12017c478bd9Sstevel@tonic-gate  *
12027c478bd9Sstevel@tonic-gate  * RETURN VALUES:
12037c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS	on success(or respective failure on error)
12047c478bd9Sstevel@tonic-gate  */
12057c478bd9Sstevel@tonic-gate ibt_status_t
ibt_close_rc_channel(ibt_channel_hdl_t channel,ibt_execution_mode_t mode,void * priv_data,ibt_priv_data_len_t priv_data_len,uint8_t * ret_status,void * ret_priv_data,ibt_priv_data_len_t * ret_priv_data_len_p)12067c478bd9Sstevel@tonic-gate ibt_close_rc_channel(ibt_channel_hdl_t channel, ibt_execution_mode_t mode,
12077c478bd9Sstevel@tonic-gate     void *priv_data, ibt_priv_data_len_t priv_data_len, uint8_t *ret_status,
12087c478bd9Sstevel@tonic-gate     void *ret_priv_data, ibt_priv_data_len_t *ret_priv_data_len_p)
12097c478bd9Sstevel@tonic-gate {
12107c478bd9Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel(%p, %x, %p, %d, %p)",
12137c478bd9Sstevel@tonic-gate 	    channel, mode, priv_data, priv_data_len,
12147c478bd9Sstevel@tonic-gate 	    (ret_priv_data_len_p == NULL) ? 0 : *ret_priv_data_len_p);
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 	/* validate channel, first */
12177c478bd9Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
12187c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12197c478bd9Sstevel@tonic-gate 		    "invalid channel", channel);
12207c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
12217c478bd9Sstevel@tonic-gate 	}
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
12247c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12257c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel",
12267c478bd9Sstevel@tonic-gate 		    channel);
12277c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
12287c478bd9Sstevel@tonic-gate 	}
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
12317c478bd9Sstevel@tonic-gate 		/* valid only for BLOCKING MODE */
12327c478bd9Sstevel@tonic-gate 		if ((ret_priv_data_len_p != NULL) &&
12337c478bd9Sstevel@tonic-gate 		    (*ret_priv_data_len_p > IBT_DREP_PRIV_DATA_SZ)) {
12347c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p"
12357c478bd9Sstevel@tonic-gate 			    " private data len %d is too large", channel,
12367c478bd9Sstevel@tonic-gate 			    *ret_priv_data_len_p);
12377c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
12387c478bd9Sstevel@tonic-gate 		}
12397c478bd9Sstevel@tonic-gate 	} else if ((mode != IBT_NONBLOCKING) && (mode != IBT_NOCALLBACKS)) {
12407c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12417c478bd9Sstevel@tonic-gate 		    "invalid mode %x specified", channel, mode);
12427c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
12437c478bd9Sstevel@tonic-gate 	}
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 	if (ibtl_cm_is_chan_closing(channel) ||
12467c478bd9Sstevel@tonic-gate 	    ibtl_cm_is_chan_closed(channel)) {
12477c478bd9Sstevel@tonic-gate 		if (ret_status)
12487c478bd9Sstevel@tonic-gate 			*ret_status = IBT_CM_CLOSED_ALREADY;
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 		/* No private data to return to the client */
12517c478bd9Sstevel@tonic-gate 		if (ret_priv_data_len_p != NULL)
12527c478bd9Sstevel@tonic-gate 			*ret_priv_data_len_p = 0;
12537c478bd9Sstevel@tonic-gate 
12542e8bde70Sagiri 		if ((mode == IBT_BLOCKING) ||
12552e8bde70Sagiri 		    (mode == IBT_NOCALLBACKS)) {
12562e8bde70Sagiri 			IBCM_GET_CHAN_PRIVATE(channel, statep);
12572e8bde70Sagiri 			if (statep == NULL)
12582e8bde70Sagiri 				return (IBT_SUCCESS);
12592e8bde70Sagiri 			mutex_enter(&statep->state_mutex);
12602e8bde70Sagiri 			IBCM_RELEASE_CHAN_PRIVATE(channel);
12612e8bde70Sagiri 			IBCM_REF_CNT_INCR(statep);
12622e8bde70Sagiri 			while (statep->close_done != B_TRUE)
12632e8bde70Sagiri 				cv_wait(&statep->block_client_cv,
12642e8bde70Sagiri 				    &statep->state_mutex);
12652e8bde70Sagiri 			IBCM_REF_CNT_DECR(statep);
12662e8bde70Sagiri 			mutex_exit(&statep->state_mutex);
12672e8bde70Sagiri 		}
12682e8bde70Sagiri 
1269934f0bccShiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel: chan 0x%p "
1270934f0bccShiremath 		    "already marked for closing", channel);
1271934f0bccShiremath 
12727c478bd9Sstevel@tonic-gate 		return (IBT_SUCCESS);
12737c478bd9Sstevel@tonic-gate 	}
1274934f0bccShiremath 
1275934f0bccShiremath 	/* get the statep */
1276934f0bccShiremath 	IBCM_GET_CHAN_PRIVATE(channel, statep);
1277934f0bccShiremath 	if (statep == NULL) {
1278934f0bccShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
1279934f0bccShiremath 		    "statep NULL", channel);
12807c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
12817c478bd9Sstevel@tonic-gate 	}
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
1284934f0bccShiremath 
1285934f0bccShiremath 	if (statep->dreq_msg == NULL) {
1286015f8fffShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
1287934f0bccShiremath 		    "Fatal Error: dreq_msg is NULL", channel);
1288934f0bccShiremath 		IBCM_RELEASE_CHAN_PRIVATE(channel);
1289934f0bccShiremath 		mutex_exit(&statep->state_mutex);
1290934f0bccShiremath 		return (IBT_CHAN_STATE_INVALID);
1291934f0bccShiremath 	}
1292934f0bccShiremath 
1293934f0bccShiremath 	if ((ret_priv_data == NULL) || (ret_priv_data_len_p == NULL)) {
1294934f0bccShiremath 		statep->close_ret_priv_data = NULL;
1295934f0bccShiremath 		statep->close_ret_priv_data_len = NULL;
1296934f0bccShiremath 	} else {
1297934f0bccShiremath 		statep->close_ret_priv_data = ret_priv_data;
1298934f0bccShiremath 		statep->close_ret_priv_data_len = ret_priv_data_len_p;
1299934f0bccShiremath 	}
1300934f0bccShiremath 
1301934f0bccShiremath 	priv_data_len = min(priv_data_len, IBT_DREQ_PRIV_DATA_SZ);
1302934f0bccShiremath 	if ((priv_data != NULL) && (priv_data_len > 0)) {
1303934f0bccShiremath 		bcopy(priv_data, ((ibcm_dreq_msg_t *)
1304934f0bccShiremath 		    IBCM_OUT_MSGP(statep->dreq_msg))->dreq_private_data,
1305934f0bccShiremath 		    priv_data_len);
1306934f0bccShiremath 	}
1307934f0bccShiremath 	statep->close_ret_status = ret_status;
1308934f0bccShiremath 
13097c478bd9Sstevel@tonic-gate 	IBCM_RELEASE_CHAN_PRIVATE(channel);
13107c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);
1311934f0bccShiremath 
1312934f0bccShiremath 	if (mode != IBT_NONBLOCKING) {
1313934f0bccShiremath 		return (ibcm_close_rc_channel(channel, statep, mode));
1314934f0bccShiremath 	}
1315934f0bccShiremath 
1316934f0bccShiremath 	/* IBT_NONBLOCKING */
1317934f0bccShiremath 	ibcm_close_enqueue(statep);
13187c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
13197c478bd9Sstevel@tonic-gate 
1320934f0bccShiremath 	return (IBT_SUCCESS);
1321934f0bccShiremath }
1322934f0bccShiremath 
1323934f0bccShiremath void
ibcm_close_start(ibcm_state_data_t * statep)1324934f0bccShiremath ibcm_close_start(ibcm_state_data_t *statep)
1325934f0bccShiremath {
1326934f0bccShiremath 	mutex_enter(&statep->state_mutex);
1327934f0bccShiremath 	(void) ibcm_close_rc_channel(statep->channel, statep, IBT_NONBLOCKING);
1328934f0bccShiremath }
1329934f0bccShiremath 
1330934f0bccShiremath static
1331934f0bccShiremath ibt_status_t
ibcm_close_rc_channel(ibt_channel_hdl_t channel,ibcm_state_data_t * statep,ibt_execution_mode_t mode)1332934f0bccShiremath ibcm_close_rc_channel(ibt_channel_hdl_t channel, ibcm_state_data_t *statep,
1333934f0bccShiremath     ibt_execution_mode_t mode)
1334934f0bccShiremath {
1335934f0bccShiremath 	ibcm_hca_info_t		*hcap;
1336934f0bccShiremath 
1337934f0bccShiremath 	_NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex));
1338934f0bccShiremath 	ASSERT(MUTEX_HELD(&statep->state_mutex));
1339934f0bccShiremath 
1340934f0bccShiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_close_rc_channel: chan 0x%p statep %p",
13417c478bd9Sstevel@tonic-gate 	    channel, statep);
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 	hcap = statep->hcap;
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 	/* HCA must have been in active state. If not, it's a client bug */
13467c478bd9Sstevel@tonic-gate 	if (!IBCM_ACCESS_HCA_OK(hcap)) {
1347934f0bccShiremath 		IBTF_DPRINTF_L2(cmlog, "ibcm_close_rc_channel: chan 0x%p "
13487c478bd9Sstevel@tonic-gate 		    "hcap 0x%p not active", channel, hcap);
13497c478bd9Sstevel@tonic-gate 		IBCM_REF_CNT_DECR(statep);
13507c478bd9Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
13517c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
13527c478bd9Sstevel@tonic-gate 	}
13537c478bd9Sstevel@tonic-gate 
13547c478bd9Sstevel@tonic-gate 	if (statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) {
13557c478bd9Sstevel@tonic-gate 		while (statep->cep_in_rts == IBCM_BLOCK)
13567c478bd9Sstevel@tonic-gate 			cv_wait(&statep->block_mad_cv, &statep->state_mutex);
13577c478bd9Sstevel@tonic-gate 	}
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 	/* Do TRANSIENT_DREQ check after TRANSIENT_ESTABLISHED check */
13607c478bd9Sstevel@tonic-gate 	while (statep->state == IBCM_STATE_TRANSIENT_DREQ_SENT)
13617c478bd9Sstevel@tonic-gate 		cv_wait(&statep->block_mad_cv, &statep->state_mutex);
13627c478bd9Sstevel@tonic-gate 
1363934f0bccShiremath 	IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: chan 0x%p "
13647c478bd9Sstevel@tonic-gate 	    "connection state is %x", channel, statep->state);
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	/* If state is in pre-established states, abort the connection est */
13677c478bd9Sstevel@tonic-gate 	if (statep->state != IBCM_STATE_ESTABLISHED) {
13689d3d2ed0Shiremath 		statep->cm_retries++;	/* ensure connection trace is dumped */
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 		/* No DREP private data possible */
1371934f0bccShiremath 		if (statep->close_ret_priv_data_len != NULL)
1372934f0bccShiremath 			*statep->close_ret_priv_data_len = 0;
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 		/*
13757c478bd9Sstevel@tonic-gate 		 * If waiting for a response mad, then cancel the timer,
13767c478bd9Sstevel@tonic-gate 		 * and delete the connection
13777c478bd9Sstevel@tonic-gate 		 */
13787c478bd9Sstevel@tonic-gate 		if (statep->state == IBCM_STATE_REQ_SENT ||
13797c478bd9Sstevel@tonic-gate 		    statep->state == IBCM_STATE_REP_SENT ||
13807c478bd9Sstevel@tonic-gate 		    statep->state == IBCM_STATE_REP_WAIT ||
13817c478bd9Sstevel@tonic-gate 		    statep->state == IBCM_STATE_MRA_REP_RCVD) {
13827c478bd9Sstevel@tonic-gate 			timeout_id_t		timer_val = statep->timerid;
13837c478bd9Sstevel@tonic-gate 			ibcm_conn_state_t	old_state;
13847c478bd9Sstevel@tonic-gate 
1385934f0bccShiremath 			IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
13867c478bd9Sstevel@tonic-gate 			    "chan 0x%p connection aborted in state %x", channel,
13877c478bd9Sstevel@tonic-gate 			    statep->state);
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 			old_state = statep->state;
13907c478bd9Sstevel@tonic-gate 			statep->state = IBCM_STATE_DELETE;
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 			if (mode == IBT_NONBLOCKING) {
13937c478bd9Sstevel@tonic-gate 				if (taskq_dispatch(ibcm_taskq,
13947c478bd9Sstevel@tonic-gate 				    ibcm_process_abort_via_taskq, statep,
1395*fc8ae2ecSToomas Soome 				    TQ_NOSLEEP) == TASKQID_INVALID) {
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate 					IBCM_REF_CNT_DECR(statep);
13987c478bd9Sstevel@tonic-gate 					statep->state = old_state;
13997c478bd9Sstevel@tonic-gate 					mutex_exit(&statep->state_mutex);
14007c478bd9Sstevel@tonic-gate 					return (IBT_INSUFF_KERNEL_RESOURCE);
14017c478bd9Sstevel@tonic-gate 				}	/* if taskq_dispatch succeeds */
14027c478bd9Sstevel@tonic-gate 				/* Cancel the timer */
14037c478bd9Sstevel@tonic-gate 				statep->timerid = 0;
14047c478bd9Sstevel@tonic-gate 				mutex_exit(&statep->state_mutex);
14057c478bd9Sstevel@tonic-gate 			} else {
14067c478bd9Sstevel@tonic-gate 				/* Cancel the timer */
14077c478bd9Sstevel@tonic-gate 				statep->timerid = 0;
14087c478bd9Sstevel@tonic-gate 				mutex_exit(&statep->state_mutex);
14097c478bd9Sstevel@tonic-gate 				(void) taskq_dispatch(ibcm_taskq,
14107c478bd9Sstevel@tonic-gate 				    ibcm_process_abort_via_taskq, statep,
14117c478bd9Sstevel@tonic-gate 				    TQ_SLEEP);
14127c478bd9Sstevel@tonic-gate 			}
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate 			/* cancel the currently running timer */
14157c478bd9Sstevel@tonic-gate 			if (timer_val != 0)
14167c478bd9Sstevel@tonic-gate 				(void) untimeout(timer_val);
14177c478bd9Sstevel@tonic-gate 
14187c478bd9Sstevel@tonic-gate 			/* wait until cm handler returns for BLOCKING cases */
1419934f0bccShiremath 			mutex_enter(&statep->state_mutex);
14207c478bd9Sstevel@tonic-gate 			if ((mode == IBT_BLOCKING) ||
14217c478bd9Sstevel@tonic-gate 			    (mode == IBT_NOCALLBACKS)) {
14227c478bd9Sstevel@tonic-gate 				while (statep->close_done != B_TRUE)
14237c478bd9Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
14247c478bd9Sstevel@tonic-gate 					    &statep->state_mutex);
14257c478bd9Sstevel@tonic-gate 			}
14267c478bd9Sstevel@tonic-gate 
1427934f0bccShiremath 			if (statep->close_ret_status)
1428934f0bccShiremath 				*statep->close_ret_status = IBT_CM_CLOSED_ABORT;
1429934f0bccShiremath 			mutex_exit(&statep->state_mutex);
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate 			/*
14327c478bd9Sstevel@tonic-gate 			 * It would ideal to post a REJ MAD, but that would
14337c478bd9Sstevel@tonic-gate 			 * be non-conformance to spec. Hence, delete the state
14347c478bd9Sstevel@tonic-gate 			 * data. Assuming that happens quickly, any retransmits
14357c478bd9Sstevel@tonic-gate 			 * from the remote are replied by CM with reject
14367c478bd9Sstevel@tonic-gate 			 * reason " no valid com id". That would stop remote
14377c478bd9Sstevel@tonic-gate 			 * sending any more MADs.
14387c478bd9Sstevel@tonic-gate 			 */
14397c478bd9Sstevel@tonic-gate 			ibcm_delete_state_data(statep);
14407c478bd9Sstevel@tonic-gate 			return (IBT_SUCCESS);
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate 		/* if CM busy in cm handler, wait until cm handler returns */
14437c478bd9Sstevel@tonic-gate 		} else if (statep->state == IBCM_STATE_REQ_RCVD ||
14447c478bd9Sstevel@tonic-gate 		    statep->state == IBCM_STATE_REP_RCVD ||
14457c478bd9Sstevel@tonic-gate 		    statep->state == IBCM_STATE_MRA_SENT ||
14467c478bd9Sstevel@tonic-gate 		    statep->state == IBCM_STATE_MRA_REP_SENT) {
14477c478bd9Sstevel@tonic-gate 
14487c478bd9Sstevel@tonic-gate 			/* take control of statep */
14497c478bd9Sstevel@tonic-gate 			statep->abort_flag |= IBCM_ABORT_CLIENT;
14507c478bd9Sstevel@tonic-gate 
1451934f0bccShiremath 			IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
14527c478bd9Sstevel@tonic-gate 			    "chan 0x%p connection aborted in state = %x",
14537c478bd9Sstevel@tonic-gate 			    channel, statep->state);
14547c478bd9Sstevel@tonic-gate 
14557c478bd9Sstevel@tonic-gate 			/*
14567c478bd9Sstevel@tonic-gate 			 * wait until state machine modifies qp state to error,
14577c478bd9Sstevel@tonic-gate 			 * including disassociating statep and QP
14587c478bd9Sstevel@tonic-gate 			 */
14597c478bd9Sstevel@tonic-gate 			if ((mode == IBT_BLOCKING) || (mode == IBT_NOCALLBACKS))
14607c478bd9Sstevel@tonic-gate 				while (statep->close_done != B_TRUE)
14617c478bd9Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
14627c478bd9Sstevel@tonic-gate 					    &statep->state_mutex);
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 			/* a sanity setting */
14657c478bd9Sstevel@tonic-gate 			if (mode == IBT_NOCALLBACKS)
14667c478bd9Sstevel@tonic-gate 				statep->cm_handler = NULL;
14677c478bd9Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 			/*
14707c478bd9Sstevel@tonic-gate 			 * In rare situations, connection attempt could be
14717c478bd9Sstevel@tonic-gate 			 * terminated for some other reason, before abort is
14727c478bd9Sstevel@tonic-gate 			 * processed, but CM still returns ret_status as abort
14737c478bd9Sstevel@tonic-gate 			 */
1474934f0bccShiremath 			if (statep->close_ret_status)
1475934f0bccShiremath 				*statep->close_ret_status = IBT_CM_CLOSED_ABORT;
1476934f0bccShiremath 			mutex_exit(&statep->state_mutex);
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate 			/*
14797c478bd9Sstevel@tonic-gate 			 * REJ MAD is posted by the CM state machine for this
14807c478bd9Sstevel@tonic-gate 			 * case, hence state structure is deleted in the
14817c478bd9Sstevel@tonic-gate 			 * state machine processing.
14827c478bd9Sstevel@tonic-gate 			 */
14837c478bd9Sstevel@tonic-gate 			return (IBT_SUCCESS);
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 		} else if ((statep->state == IBCM_STATE_TIMEWAIT) ||
14867c478bd9Sstevel@tonic-gate 		    (statep->state == IBCM_STATE_DELETE)) {
14877c478bd9Sstevel@tonic-gate 
14887c478bd9Sstevel@tonic-gate 			/* State already in timewait, so no return priv data */
14897c478bd9Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate 			/* The teardown has already been done */
1492934f0bccShiremath 			if (statep->close_ret_status)
1493934f0bccShiremath 				*statep->close_ret_status =
1494934f0bccShiremath 				    IBT_CM_CLOSED_ALREADY;
1495934f0bccShiremath 			mutex_exit(&statep->state_mutex);
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate 			return (IBT_SUCCESS);
14987c478bd9Sstevel@tonic-gate 
14997c478bd9Sstevel@tonic-gate 		} else if ((statep->state == IBCM_STATE_DREQ_RCVD) ||
15007c478bd9Sstevel@tonic-gate 		    (statep->state == IBCM_STATE_DREQ_SENT) ||
15017c478bd9Sstevel@tonic-gate 		    (statep->state == IBCM_STATE_DREP_RCVD) ||
15027c478bd9Sstevel@tonic-gate 		    ((statep->state == IBCM_STATE_TIMED_OUT) &&
15037c478bd9Sstevel@tonic-gate 		    (statep->timedout_state == IBCM_STATE_DREQ_SENT))) {
15047c478bd9Sstevel@tonic-gate 
15057c478bd9Sstevel@tonic-gate 			/*
15067c478bd9Sstevel@tonic-gate 			 * Either the remote or local client has already
15077c478bd9Sstevel@tonic-gate 			 * initiated the teardown.  IBCM_STATE_DREP_RCVD is
15087c478bd9Sstevel@tonic-gate 			 * possible, if CM initiated teardown without client's
15097c478bd9Sstevel@tonic-gate 			 * knowledge, for stale handling, etc.,
15107c478bd9Sstevel@tonic-gate 			 */
15117c478bd9Sstevel@tonic-gate 			if (mode == IBT_NOCALLBACKS) {
15127c478bd9Sstevel@tonic-gate 				if (statep->close_nocb_state == IBCM_UNBLOCK) {
15137c478bd9Sstevel@tonic-gate 					statep->close_nocb_state = IBCM_FAIL;
15147c478bd9Sstevel@tonic-gate 					/* enable free qp after return */
15157c478bd9Sstevel@tonic-gate 					ibtl_cm_chan_is_closing(
15167c478bd9Sstevel@tonic-gate 					    statep->channel);
15177c478bd9Sstevel@tonic-gate 				} else while (statep->close_nocb_state ==
15187c478bd9Sstevel@tonic-gate 				    IBCM_BLOCK)
15197c478bd9Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
15207c478bd9Sstevel@tonic-gate 					    &statep->state_mutex);
15217c478bd9Sstevel@tonic-gate 				statep->cm_handler = NULL; /* sanity setting */
1522934f0bccShiremath 				if (statep->close_ret_status)
1523934f0bccShiremath 					*statep->close_ret_status =
1524934f0bccShiremath 					    IBT_CM_CLOSED_ALREADY;
15257c478bd9Sstevel@tonic-gate 			} else if (mode == IBT_BLOCKING) {
15267c478bd9Sstevel@tonic-gate 				/* wait until state is moved to timewait */
15277c478bd9Sstevel@tonic-gate 				while (statep->close_done != B_TRUE)
15287c478bd9Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
15297c478bd9Sstevel@tonic-gate 					    &statep->state_mutex);
15307c478bd9Sstevel@tonic-gate 			}
15317c478bd9Sstevel@tonic-gate 
15327c478bd9Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
15337c478bd9Sstevel@tonic-gate 			mutex_exit(&statep->state_mutex);
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 			/* ret_status is set in state machine code */
15367c478bd9Sstevel@tonic-gate 			return (IBT_SUCCESS);
15377c478bd9Sstevel@tonic-gate 
15387c478bd9Sstevel@tonic-gate 		} else if (statep->state == IBCM_STATE_TIMED_OUT) {
15397c478bd9Sstevel@tonic-gate 
15407c478bd9Sstevel@tonic-gate 			if ((mode == IBT_BLOCKING) ||
15417c478bd9Sstevel@tonic-gate 			    (mode == IBT_NOCALLBACKS)) {
15427c478bd9Sstevel@tonic-gate 
15437c478bd9Sstevel@tonic-gate 				/*
15447c478bd9Sstevel@tonic-gate 				 * wait until cm handler invocation and
15457c478bd9Sstevel@tonic-gate 				 * disassociation between statep and channel
15467c478bd9Sstevel@tonic-gate 				 * is complete
15477c478bd9Sstevel@tonic-gate 				 */
15487c478bd9Sstevel@tonic-gate 				while (statep->close_done != B_TRUE)
15497c478bd9Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
15507c478bd9Sstevel@tonic-gate 					    &statep->state_mutex);
15517c478bd9Sstevel@tonic-gate 			}
15527c478bd9Sstevel@tonic-gate 
1553934f0bccShiremath 			if (statep->close_ret_status)
1554934f0bccShiremath 				*statep->close_ret_status = IBT_CM_CLOSED_ABORT;
15557c478bd9Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
15567c478bd9Sstevel@tonic-gate 			mutex_exit(&statep->state_mutex);
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 			return (IBT_SUCCESS);
15597c478bd9Sstevel@tonic-gate 		} else {
15607c478bd9Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
15617c478bd9Sstevel@tonic-gate 			mutex_exit(&statep->state_mutex);
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 			return (IBT_CM_FAILURE);
15647c478bd9Sstevel@tonic-gate 		}
15657c478bd9Sstevel@tonic-gate 	}
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate 	ASSERT(statep->close_nocb_state != IBCM_BLOCK);
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate 	if (mode == IBT_NOCALLBACKS) {
15707c478bd9Sstevel@tonic-gate 		statep->close_nocb_state = IBCM_FAIL;
15717c478bd9Sstevel@tonic-gate 		statep->cm_handler = NULL;
15727c478bd9Sstevel@tonic-gate 		ibtl_cm_chan_is_closing(statep->channel);
1573934f0bccShiremath 		IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
15747c478bd9Sstevel@tonic-gate 		    "NOCALLBACKS on in statep = %p", statep);
15757c478bd9Sstevel@tonic-gate 	}
15767c478bd9Sstevel@tonic-gate 
15779d3d2ed0Shiremath 	if (statep->state != IBCM_STATE_ESTABLISHED) {
15789d3d2ed0Shiremath 		goto lost_race;
15799d3d2ed0Shiremath 	}
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate 	/*
15827c478bd9Sstevel@tonic-gate 	 * Cancel/wait for any pending ibt_set_alt_path, and
15837c478bd9Sstevel@tonic-gate 	 * release state mutex
15847c478bd9Sstevel@tonic-gate 	 */
15857c478bd9Sstevel@tonic-gate 	ibcm_sync_lapr_idle(statep);
15867c478bd9Sstevel@tonic-gate 
15879d3d2ed0Shiremath 	ibcm_close_enter();
15889d3d2ed0Shiremath 
15899d3d2ed0Shiremath 	mutex_enter(&statep->state_mutex);
15909d3d2ed0Shiremath 	if (statep->state != IBCM_STATE_ESTABLISHED) {
15919d3d2ed0Shiremath 		ibcm_close_exit();
15929d3d2ed0Shiremath 		goto lost_race;
15939d3d2ed0Shiremath 	}
15949d3d2ed0Shiremath 
15959d3d2ed0Shiremath 	statep->state = IBCM_STATE_TRANSIENT_DREQ_SENT;
15969d3d2ed0Shiremath 	statep->timerid = 0;
15979d3d2ed0Shiremath 	statep->close_done = B_FALSE;
15989d3d2ed0Shiremath 	statep->close_flow = 1;
15999d3d2ed0Shiremath 	mutex_exit(&statep->state_mutex);
16009d3d2ed0Shiremath 
16017c478bd9Sstevel@tonic-gate 	ibcm_post_dreq_mad(statep);
16027c478bd9Sstevel@tonic-gate 
16037c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
16047c478bd9Sstevel@tonic-gate 
16059d3d2ed0Shiremath lost_race:
16067c478bd9Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate 		/* wait for DREP */
16097c478bd9Sstevel@tonic-gate 		while (statep->close_done != B_TRUE)
16107c478bd9Sstevel@tonic-gate 			cv_wait(&statep->block_client_cv,
16117c478bd9Sstevel@tonic-gate 			    &statep->state_mutex);
16127c478bd9Sstevel@tonic-gate 
1613934f0bccShiremath 		IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: chan 0x%p "
16147c478bd9Sstevel@tonic-gate 		    "done blocking", channel);
16157c478bd9Sstevel@tonic-gate 	}
16167c478bd9Sstevel@tonic-gate 
16177c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
16187c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
16197c478bd9Sstevel@tonic-gate 
16207c478bd9Sstevel@tonic-gate 	/* If this message isn't seen then ibt_close_rc_channel failed */
1621934f0bccShiremath 	IBTF_DPRINTF_L5(cmlog, "ibcm_close_rc_channel: chan 0x%p done",
16227c478bd9Sstevel@tonic-gate 	    channel);
16237c478bd9Sstevel@tonic-gate 
16247c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
16257c478bd9Sstevel@tonic-gate }
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate ibt_status_t
ibt_recycle_rc(ibt_channel_hdl_t rc_chan,ibt_cep_flags_t control,uint8_t hca_port_num,ibt_recycle_handler_t func,void * arg)16287c478bd9Sstevel@tonic-gate ibt_recycle_rc(ibt_channel_hdl_t rc_chan, ibt_cep_flags_t control,
16297c478bd9Sstevel@tonic-gate     uint8_t hca_port_num, ibt_recycle_handler_t func, void *arg)
16307c478bd9Sstevel@tonic-gate {
16317c478bd9Sstevel@tonic-gate 	ibcm_state_data_t		*statep;
16327c478bd9Sstevel@tonic-gate 	ibcm_taskq_recycle_arg_t	*ibcm_tq_recycle_arg;
16337c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t		qp_attr;
16347c478bd9Sstevel@tonic-gate 	ibt_status_t			retval;
16357c478bd9Sstevel@tonic-gate 
16367c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_recycle_rc (%p, 0x%X, %d, %p, %p)", rc_chan,
16377c478bd9Sstevel@tonic-gate 	    control, hca_port_num, func, arg);
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(rc_chan)) {
16407c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_recycle_rc: invalid channel");
16417c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
16427c478bd9Sstevel@tonic-gate 	}
16437c478bd9Sstevel@tonic-gate 
16447c478bd9Sstevel@tonic-gate 	/* check qp state */
16457c478bd9Sstevel@tonic-gate 	retval = ibt_query_qp(rc_chan, &qp_attr);
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS)
16487c478bd9Sstevel@tonic-gate 		return (retval);
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_trans != IBT_RC_SRV)
16517c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR)
16547c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 	ibcm_tq_recycle_arg = kmem_alloc(sizeof (ibcm_taskq_recycle_arg_t),
16597c478bd9Sstevel@tonic-gate 	    KM_SLEEP);
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate 	ibcm_tq_recycle_arg->rc_chan		= rc_chan;
16627c478bd9Sstevel@tonic-gate 	ibcm_tq_recycle_arg->control		= control;
16637c478bd9Sstevel@tonic-gate 	ibcm_tq_recycle_arg->hca_port_num	= hca_port_num;
16647c478bd9Sstevel@tonic-gate 	ibcm_tq_recycle_arg->func		= func;
16657c478bd9Sstevel@tonic-gate 	ibcm_tq_recycle_arg->arg		= arg;
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
16687c478bd9Sstevel@tonic-gate 
16697c478bd9Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(rc_chan, statep);
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate 	/*
16727c478bd9Sstevel@tonic-gate 	 * If non-blocking ie., func specified and channel has not yet completed
16737c478bd9Sstevel@tonic-gate 	 * the timewait, then schedule the work for later
16747c478bd9Sstevel@tonic-gate 	 */
16757c478bd9Sstevel@tonic-gate 	if ((func != NULL) && (statep != NULL)) {
16767c478bd9Sstevel@tonic-gate 		IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
16777c478bd9Sstevel@tonic-gate 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
16787c478bd9Sstevel@tonic-gate 		statep->recycle_arg = ibcm_tq_recycle_arg;
16797c478bd9Sstevel@tonic-gate 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
16807c478bd9Sstevel@tonic-gate 		return (IBT_SUCCESS);
16817c478bd9Sstevel@tonic-gate 	}
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate 	/*
16847c478bd9Sstevel@tonic-gate 	 * if blocking ie., func specified, and channel has not yet completed
16857c478bd9Sstevel@tonic-gate 	 * the timewait, then block until the channel completes the timewait
16867c478bd9Sstevel@tonic-gate 	 */
16877c478bd9Sstevel@tonic-gate 	if (statep != NULL)
16887c478bd9Sstevel@tonic-gate 		IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
16897c478bd9Sstevel@tonic-gate 	IBCM_WAIT_CHAN_PRIVATE(rc_chan);
16907c478bd9Sstevel@tonic-gate 
16917c478bd9Sstevel@tonic-gate 	if (func) {	/* NON BLOCKING case. Taskq for QP state change */
16927c478bd9Sstevel@tonic-gate 		(void) taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
16937c478bd9Sstevel@tonic-gate 		    ibcm_tq_recycle_arg, TQ_SLEEP);
16947c478bd9Sstevel@tonic-gate 		return (IBT_SUCCESS);
16957c478bd9Sstevel@tonic-gate 	} else	/* BLOCKING case */
16967c478bd9Sstevel@tonic-gate 		return (ibcm_process_rc_recycle_ret(ibcm_tq_recycle_arg));
16977c478bd9Sstevel@tonic-gate }
16987c478bd9Sstevel@tonic-gate 
16997c478bd9Sstevel@tonic-gate void
ibcm_process_rc_recycle(void * recycle_arg)17007c478bd9Sstevel@tonic-gate ibcm_process_rc_recycle(void *recycle_arg)
17017c478bd9Sstevel@tonic-gate {
17027c478bd9Sstevel@tonic-gate 	(void) ibcm_process_rc_recycle_ret(recycle_arg);
17037c478bd9Sstevel@tonic-gate }
17047c478bd9Sstevel@tonic-gate 
17057c478bd9Sstevel@tonic-gate static ibt_status_t
ibcm_process_rc_recycle_ret(void * recycle_arg)17067c478bd9Sstevel@tonic-gate ibcm_process_rc_recycle_ret(void *recycle_arg)
17077c478bd9Sstevel@tonic-gate {
17087c478bd9Sstevel@tonic-gate 	ibt_qp_info_t			qp_info;
17097c478bd9Sstevel@tonic-gate 	ibt_status_t			ibt_status = IBT_SUCCESS;
17107c478bd9Sstevel@tonic-gate 	ibt_cep_modify_flags_t		cep_flags;
17117c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t		qp_attr;
17127c478bd9Sstevel@tonic-gate 	ibcm_taskq_recycle_arg_t	*ibcm_tq_recycle_arg =
17137c478bd9Sstevel@tonic-gate 	    (ibcm_taskq_recycle_arg_t *)recycle_arg;
17147c478bd9Sstevel@tonic-gate 
17157c478bd9Sstevel@tonic-gate 	/* QP must have been in error state */
17167c478bd9Sstevel@tonic-gate 	ibt_status = ibt_query_qp(ibcm_tq_recycle_arg->rc_chan, &qp_attr);
17177c478bd9Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS)
17187c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17197c478bd9Sstevel@tonic-gate 		    "chanp %p ibt_query_qp() = %d",
17207c478bd9Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->rc_chan, ibt_status);
17217c478bd9Sstevel@tonic-gate 	else {
17227c478bd9Sstevel@tonic-gate 		/* perform the QP state change from ERROR to RESET */
17237c478bd9Sstevel@tonic-gate 		bzero(&qp_info, sizeof (qp_info));
17247c478bd9Sstevel@tonic-gate 
17257c478bd9Sstevel@tonic-gate 		qp_info.qp_trans = IBT_RC_SRV;
17267c478bd9Sstevel@tonic-gate 		qp_info.qp_state = IBT_STATE_RESET;
17277c478bd9Sstevel@tonic-gate 
17287c478bd9Sstevel@tonic-gate 		/* Call modify_qp to move to RESET state */
17297c478bd9Sstevel@tonic-gate 		ibt_status = ibt_modify_qp(ibcm_tq_recycle_arg->rc_chan,
17307c478bd9Sstevel@tonic-gate 		    IBT_CEP_SET_STATE, &qp_info, NULL);
17317c478bd9Sstevel@tonic-gate 
17327c478bd9Sstevel@tonic-gate 		if (ibt_status != IBT_SUCCESS)
17337c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17347c478bd9Sstevel@tonic-gate 			    "chanp %p ibt_modify_qp() = %d for ERROR to RESET",
17357c478bd9Sstevel@tonic-gate 			    ibcm_tq_recycle_arg->rc_chan, ibt_status);
17367c478bd9Sstevel@tonic-gate 	}
17377c478bd9Sstevel@tonic-gate 
17387c478bd9Sstevel@tonic-gate 	if (ibt_status == IBT_SUCCESS) {
17397c478bd9Sstevel@tonic-gate 
17407c478bd9Sstevel@tonic-gate 		qp_info.qp_state = IBT_STATE_INIT;
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 		/* set flags for all mandatory args from RESET to INIT */
17437c478bd9Sstevel@tonic-gate 		cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
17447c478bd9Sstevel@tonic-gate 		cep_flags |= IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W;
17457c478bd9Sstevel@tonic-gate 		cep_flags |= IBT_CEP_SET_ATOMIC;
17467c478bd9Sstevel@tonic-gate 
17477c478bd9Sstevel@tonic-gate 		qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
17487c478bd9Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->hca_port_num;
17497c478bd9Sstevel@tonic-gate 		qp_info.qp_flags |=
17507c478bd9Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->control & IBT_CEP_RDMA_RD;
17517c478bd9Sstevel@tonic-gate 		qp_info.qp_flags |=
17527c478bd9Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->control & IBT_CEP_RDMA_WR;
17537c478bd9Sstevel@tonic-gate 		qp_info.qp_flags |=
17547c478bd9Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->control & IBT_CEP_ATOMIC;
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 		/* Always use the existing pkey */
17577c478bd9Sstevel@tonic-gate 		qp_info.qp_transport.rc.rc_path.cep_pkey_ix =
17587c478bd9Sstevel@tonic-gate 		    qp_attr. qp_info.qp_transport.rc.rc_path.cep_pkey_ix;
17597c478bd9Sstevel@tonic-gate 
17607c478bd9Sstevel@tonic-gate 		/* Call modify_qp to move to INIT state */
17617c478bd9Sstevel@tonic-gate 		ibt_status = ibt_modify_qp(ibcm_tq_recycle_arg->rc_chan,
17627c478bd9Sstevel@tonic-gate 		    cep_flags, &qp_info, NULL);
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate 		if (ibt_status != IBT_SUCCESS)
17657c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17667c478bd9Sstevel@tonic-gate 			    "chanp %p ibt_modify_qp() = %d for RESET to INIT",
17677c478bd9Sstevel@tonic-gate 			    ibcm_tq_recycle_arg->rc_chan, ibt_status);
17687c478bd9Sstevel@tonic-gate 	}
17697c478bd9Sstevel@tonic-gate 
17707c478bd9Sstevel@tonic-gate 	/* Change the QP CM state to indicate QP being re-used */
17717c478bd9Sstevel@tonic-gate 	if (ibt_status == IBT_SUCCESS)
17727c478bd9Sstevel@tonic-gate 		ibtl_cm_chan_is_reused(ibcm_tq_recycle_arg->rc_chan);
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate 	/* Call func, if defined */
17757c478bd9Sstevel@tonic-gate 	if (ibcm_tq_recycle_arg->func)
17767c478bd9Sstevel@tonic-gate 		(*(ibcm_tq_recycle_arg->func))(ibt_status,
17777c478bd9Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->arg);
17787c478bd9Sstevel@tonic-gate 
17797c478bd9Sstevel@tonic-gate 	kmem_free(ibcm_tq_recycle_arg, sizeof (ibcm_taskq_recycle_arg_t));
17807c478bd9Sstevel@tonic-gate 
17817c478bd9Sstevel@tonic-gate 	return (ibt_status);
17827c478bd9Sstevel@tonic-gate }
17837c478bd9Sstevel@tonic-gate 
17847c478bd9Sstevel@tonic-gate static void
ibcm_process_abort_via_taskq(void * args)17857c478bd9Sstevel@tonic-gate ibcm_process_abort_via_taskq(void *args)
17867c478bd9Sstevel@tonic-gate {
17877c478bd9Sstevel@tonic-gate 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
17887c478bd9Sstevel@tonic-gate 
17897c478bd9Sstevel@tonic-gate 	ibcm_process_abort(statep);
17907c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
17917c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
17927c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
17937c478bd9Sstevel@tonic-gate }
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate /*
17967c478bd9Sstevel@tonic-gate  * Local UD CM Handler's private data, used during ibt_request_ud_dest() in
17977c478bd9Sstevel@tonic-gate  * Non-Blocking mode operations.
17987c478bd9Sstevel@tonic-gate  */
17997c478bd9Sstevel@tonic-gate typedef struct ibcm_local_handler_s {
18007c478bd9Sstevel@tonic-gate 	ibt_cm_ud_handler_t	actual_cm_handler;
18017c478bd9Sstevel@tonic-gate 	void			*actual_cm_private;
18027c478bd9Sstevel@tonic-gate 	ibt_ud_dest_t		*dest_hdl;
18037c478bd9Sstevel@tonic-gate } ibcm_local_handler_t;
18047c478bd9Sstevel@tonic-gate 
_NOTE(READ_ONLY_DATA (ibcm_local_handler_s))18057c478bd9Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_local_handler_s))
18067c478bd9Sstevel@tonic-gate 
18077c478bd9Sstevel@tonic-gate /*
18087c478bd9Sstevel@tonic-gate  * Local UD CM Handler, used when ibt_alloc_ud_dest() is issued in
18097c478bd9Sstevel@tonic-gate  * NON-Blocking mode.
18107c478bd9Sstevel@tonic-gate  *
18117c478bd9Sstevel@tonic-gate  * Out here, we update the UD Destination handle with
18127c478bd9Sstevel@tonic-gate  * the obtained DQPN and QKey (from SIDR REP) and invokes actual client
18137c478bd9Sstevel@tonic-gate  * handler that was specified by the client.
18147c478bd9Sstevel@tonic-gate  */
18157c478bd9Sstevel@tonic-gate static ibt_cm_status_t
18167c478bd9Sstevel@tonic-gate ibcm_local_cm_handler(void *priv, ibt_cm_ud_event_t *event,
18177c478bd9Sstevel@tonic-gate     ibt_cm_ud_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
18187c478bd9Sstevel@tonic-gate {
18197c478bd9Sstevel@tonic-gate 	ibcm_local_handler_t	*handler_priv = (ibcm_local_handler_t *)priv;
18207c478bd9Sstevel@tonic-gate 
18217c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_local_cm_handler: event %d",
18227c478bd9Sstevel@tonic-gate 	    event->cm_type);
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 	ASSERT(handler_priv != NULL);
18257c478bd9Sstevel@tonic-gate 
18267c478bd9Sstevel@tonic-gate 	switch (event->cm_type) {
18277c478bd9Sstevel@tonic-gate 	case IBT_CM_UD_EVENT_SIDR_REP:
18287c478bd9Sstevel@tonic-gate 		/* Update QPN & QKey from event into destination handle. */
18297c478bd9Sstevel@tonic-gate 		if (handler_priv->dest_hdl != NULL) {
18307c478bd9Sstevel@tonic-gate 			handler_priv->dest_hdl->ud_dst_qpn =
18317c478bd9Sstevel@tonic-gate 			    event->cm_event.sidr_rep.srep_remote_qpn;
18327c478bd9Sstevel@tonic-gate 			handler_priv->dest_hdl->ud_qkey =
18337c478bd9Sstevel@tonic-gate 			    event->cm_event.sidr_rep.srep_remote_qkey;
18347c478bd9Sstevel@tonic-gate 		}
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate 		/* Invoke the client handler - inform only, so ignore retval */
18377c478bd9Sstevel@tonic-gate 		(void) handler_priv->actual_cm_handler(
18387c478bd9Sstevel@tonic-gate 		    handler_priv->actual_cm_private, event, ret_args, priv_data,
18397c478bd9Sstevel@tonic-gate 		    len);
18407c478bd9Sstevel@tonic-gate 
18417c478bd9Sstevel@tonic-gate 		/* Free memory allocated for local handler's private data. */
18427c478bd9Sstevel@tonic-gate 		if (handler_priv != NULL)
18437c478bd9Sstevel@tonic-gate 			kmem_free(handler_priv, sizeof (*handler_priv));
18447c478bd9Sstevel@tonic-gate 
18457c478bd9Sstevel@tonic-gate 		break;
18467c478bd9Sstevel@tonic-gate 	default:
18477c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_local_cm_handler: ERROR");
18487c478bd9Sstevel@tonic-gate 		break;
18497c478bd9Sstevel@tonic-gate 	}
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 	return (IBT_CM_ACCEPT);
18527c478bd9Sstevel@tonic-gate }
18537c478bd9Sstevel@tonic-gate 
18547c478bd9Sstevel@tonic-gate 
18557c478bd9Sstevel@tonic-gate /* Validate the input UD destination attributes.  */
18567c478bd9Sstevel@tonic-gate static ibt_status_t
ibcm_validate_dqpn_data(ibt_ud_dest_attr_t * attr,ibt_execution_mode_t mode,ibt_ud_returns_t * ret_args)18577c478bd9Sstevel@tonic-gate ibcm_validate_dqpn_data(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
18587c478bd9Sstevel@tonic-gate     ibt_ud_returns_t *ret_args)
18597c478bd9Sstevel@tonic-gate {
18607c478bd9Sstevel@tonic-gate 	/* cm handler must always be specified */
18617c478bd9Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING && attr->ud_cm_handler == NULL) {
18627c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18637c478bd9Sstevel@tonic-gate 		    "CM handler is not specified ");
18647c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
18657c478bd9Sstevel@tonic-gate 	}
18667c478bd9Sstevel@tonic-gate 
18677c478bd9Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING) {
18687c478bd9Sstevel@tonic-gate 		if (ret_args != NULL) {
18697c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18707c478bd9Sstevel@tonic-gate 			    "ret_args should be NULL when called in "
18717c478bd9Sstevel@tonic-gate 			    "non-blocking mode");
18727c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
18737c478bd9Sstevel@tonic-gate 		}
18747c478bd9Sstevel@tonic-gate 	} else if (mode == IBT_BLOCKING) {
18757c478bd9Sstevel@tonic-gate 		if (ret_args == NULL) {
18767c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18777c478bd9Sstevel@tonic-gate 			    "ret_args should be Non-NULL when called in "
18787c478bd9Sstevel@tonic-gate 			    "blocking mode");
18797c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
18807c478bd9Sstevel@tonic-gate 		}
18817c478bd9Sstevel@tonic-gate 	} else {
18827c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18837c478bd9Sstevel@tonic-gate 		    "invalid mode %x specified ", mode);
18847c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
18857c478bd9Sstevel@tonic-gate 	}
18867c478bd9Sstevel@tonic-gate 
18877c478bd9Sstevel@tonic-gate 	if (attr->ud_sid == 0) {
18887c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18897c478bd9Sstevel@tonic-gate 		    "ServiceID must be specified. ");
18907c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
18917c478bd9Sstevel@tonic-gate 	}
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate 	if (attr->ud_addr == NULL) {
18947c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18957c478bd9Sstevel@tonic-gate 		    "Address Info NULL");
18967c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
18977c478bd9Sstevel@tonic-gate 	}
18987c478bd9Sstevel@tonic-gate 
18997c478bd9Sstevel@tonic-gate 	/* Validate SGID */
19007c478bd9Sstevel@tonic-gate 	if ((attr->ud_addr->av_sgid.gid_prefix == 0) ||
19017c478bd9Sstevel@tonic-gate 	    (attr->ud_addr->av_sgid.gid_guid == 0)) {
19027c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: Invalid SGID");
19037c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
19047c478bd9Sstevel@tonic-gate 	}
19057c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_validate_dqpn_data: SGID<%llX:%llX>",
19067c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_sgid.gid_prefix,
19077c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_sgid.gid_guid);
19087c478bd9Sstevel@tonic-gate 
19097c478bd9Sstevel@tonic-gate 	/* Validate DGID */
19107c478bd9Sstevel@tonic-gate 	if ((attr->ud_addr->av_dgid.gid_prefix == 0) ||
19117c478bd9Sstevel@tonic-gate 	    (attr->ud_addr->av_dgid.gid_guid == 0)) {
19127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: Invalid DGID");
19137c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
19147c478bd9Sstevel@tonic-gate 	}
19157c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_validate_dqpn_data: DGID<%llX:%llX>",
19167c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_dgid.gid_prefix,
19177c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_dgid.gid_guid);
19187c478bd9Sstevel@tonic-gate 
19197c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
19207c478bd9Sstevel@tonic-gate }
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate 
19237c478bd9Sstevel@tonic-gate /* Perform SIDR to retrieve DQPN and QKey.  */
19247c478bd9Sstevel@tonic-gate static ibt_status_t
ibcm_ud_get_dqpn(ibt_ud_dest_attr_t * attr,ibt_execution_mode_t mode,ibt_ud_returns_t * ret_args)19257c478bd9Sstevel@tonic-gate ibcm_ud_get_dqpn(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
19267c478bd9Sstevel@tonic-gate     ibt_ud_returns_t *ret_args)
19277c478bd9Sstevel@tonic-gate {
19287c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
19297c478bd9Sstevel@tonic-gate 	ib_pkey_t		ud_pkey;
19307c478bd9Sstevel@tonic-gate 	ibmf_handle_t		ibmf_hdl;
19317c478bd9Sstevel@tonic-gate 	ibmf_msg_t		*ibmf_msg;
19327c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
19337c478bd9Sstevel@tonic-gate 	ibcm_sidr_req_msg_t	*sidr_req_msgp;
19347c478bd9Sstevel@tonic-gate 	ibcm_ud_state_data_t	*ud_statep;
19357c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	port;
19367c478bd9Sstevel@tonic-gate 	ibcm_sidr_srch_t	sidr_entry;
19377c478bd9Sstevel@tonic-gate 	ibcm_qp_list_t		*cm_qp_entry;
19387c478bd9Sstevel@tonic-gate 
19397c478bd9Sstevel@tonic-gate 	/* Retrieve HCA GUID value from the available SGID info. */
19407c478bd9Sstevel@tonic-gate 	retval = ibtl_cm_get_hca_port(attr->ud_addr->av_sgid, 0, &port);
19417c478bd9Sstevel@tonic-gate 	if ((retval != IBT_SUCCESS) || (port.hp_port == 0)) {
19427c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19437c478bd9Sstevel@tonic-gate 		    "ibtl_cm_get_hca_port failed: %d", retval);
19447c478bd9Sstevel@tonic-gate 		return (retval);
19457c478bd9Sstevel@tonic-gate 	}
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: "
19487c478bd9Sstevel@tonic-gate 	    "HCA GUID:%llX, port_num:%d", port.hp_hca_guid, port.hp_port);
19497c478bd9Sstevel@tonic-gate 
19507c478bd9Sstevel@tonic-gate 	/* Lookup the HCA info for this GUID */
19517c478bd9Sstevel@tonic-gate 	if ((hcap = ibcm_find_hca_entry(port.hp_hca_guid)) == NULL) {
19527c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: hcap is NULL");
19537c478bd9Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
19547c478bd9Sstevel@tonic-gate 	}
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate 	/* Return failure if the HCA device or Port is not operational */
19577c478bd9Sstevel@tonic-gate 
19587c478bd9Sstevel@tonic-gate 	if ((retval = ibt_get_port_state_byguid(port.hp_hca_guid, port.hp_port,
19597c478bd9Sstevel@tonic-gate 	    NULL, NULL)) != IBT_SUCCESS) {
19607c478bd9Sstevel@tonic-gate 		/* Device Port is not in good state, don't use it. */
19617c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: Invalid "
19627c478bd9Sstevel@tonic-gate 		    "port specified or port not active");
19637c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
19647c478bd9Sstevel@tonic-gate 		return (retval);
19657c478bd9Sstevel@tonic-gate 	}
19667c478bd9Sstevel@tonic-gate 
19677c478bd9Sstevel@tonic-gate 	retval = ibt_index2pkey_byguid(port.hp_hca_guid, port.hp_port,
19687c478bd9Sstevel@tonic-gate 	    attr->ud_pkey_ix, &ud_pkey);
19697c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
19707c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19717c478bd9Sstevel@tonic-gate 		    "Failed to convert index2pkey: %d", retval);
19727c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
19737c478bd9Sstevel@tonic-gate 		return (retval);
19747c478bd9Sstevel@tonic-gate 	}
19757c478bd9Sstevel@tonic-gate 
19767c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(sidr_entry))
19777c478bd9Sstevel@tonic-gate 
19787c478bd9Sstevel@tonic-gate 	/* Allocate a new request id */
19797c478bd9Sstevel@tonic-gate 	if (ibcm_alloc_reqid(hcap, &sidr_entry.srch_req_id) == IBCM_FAILURE) {
19807c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19817c478bd9Sstevel@tonic-gate 		    "no req id available");
19827c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
19837c478bd9Sstevel@tonic-gate 		return (IBT_INSUFF_KERNEL_RESOURCE);
19847c478bd9Sstevel@tonic-gate 	}
19857c478bd9Sstevel@tonic-gate 
19867c478bd9Sstevel@tonic-gate 	if ((hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl == NULL) &&
19877c478bd9Sstevel@tonic-gate 	    ((retval = ibcm_hca_reinit_port(hcap, port.hp_port - 1))
19887c478bd9Sstevel@tonic-gate 	    != IBT_SUCCESS)) {
19897c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19907c478bd9Sstevel@tonic-gate 		    "ibmf reg or callback setup failed during re-initialize");
19917c478bd9Sstevel@tonic-gate 		return (retval);
19927c478bd9Sstevel@tonic-gate 	}
19937c478bd9Sstevel@tonic-gate 
19947c478bd9Sstevel@tonic-gate 	ibmf_hdl = hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl;
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate 	/* find the ibmf QP to post the SIDR REQ */
19977c478bd9Sstevel@tonic-gate 	if ((cm_qp_entry = ibcm_find_qp(hcap, port.hp_port, ud_pkey)) ==
19987c478bd9Sstevel@tonic-gate 	    NULL) {
19997c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF QP allocation"
20007c478bd9Sstevel@tonic-gate 		    " failed");
20017c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
20027c478bd9Sstevel@tonic-gate 		return (IBT_INSUFF_RESOURCE);
20037c478bd9Sstevel@tonic-gate 	}
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 	if ((retval = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg, MAD_METHOD_SEND))
20067c478bd9Sstevel@tonic-gate 	    != IBT_SUCCESS) {
20077c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF MSG allocation"
20087c478bd9Sstevel@tonic-gate 		    " failed");
20097c478bd9Sstevel@tonic-gate 		ibcm_release_qp(cm_qp_entry);
20107c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
20117c478bd9Sstevel@tonic-gate 		return (retval);
20127c478bd9Sstevel@tonic-gate 	}
20137c478bd9Sstevel@tonic-gate 
20147c478bd9Sstevel@tonic-gate 	sidr_entry.srch_lid = port.hp_base_lid;
20157c478bd9Sstevel@tonic-gate 	sidr_entry.srch_gid = attr->ud_addr->av_sgid;
20167c478bd9Sstevel@tonic-gate 	sidr_entry.srch_grh_exists = attr->ud_addr->av_send_grh;
20177c478bd9Sstevel@tonic-gate 	sidr_entry.srch_mode = IBCM_ACTIVE_MODE;
20187c478bd9Sstevel@tonic-gate 
20197c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(sidr_entry))
20207c478bd9Sstevel@tonic-gate 
20217c478bd9Sstevel@tonic-gate 	/* do various allocations needed here */
20227c478bd9Sstevel@tonic-gate 	rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
20237c478bd9Sstevel@tonic-gate 
20247c478bd9Sstevel@tonic-gate 	(void) ibcm_find_sidr_entry(&sidr_entry, hcap, &ud_statep,
20257c478bd9Sstevel@tonic-gate 	    IBCM_FLAG_ADD);
20267c478bd9Sstevel@tonic-gate 	rw_exit(&hcap->hca_sidr_list_lock);
20277c478bd9Sstevel@tonic-gate 
20287c478bd9Sstevel@tonic-gate 	/* Increment hca's resource count */
20297c478bd9Sstevel@tonic-gate 	ibcm_inc_hca_res_cnt(hcap);
20307c478bd9Sstevel@tonic-gate 
20317c478bd9Sstevel@tonic-gate 	/* After a resource created on hca, no need to hold the acc cnt */
20327c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
20337c478bd9Sstevel@tonic-gate 
20347c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
20357c478bd9Sstevel@tonic-gate 
20367c478bd9Sstevel@tonic-gate 	/* Initialize some ud_statep fields */
20377c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_msg = ibmf_msg;
20387c478bd9Sstevel@tonic-gate 	ud_statep->ud_svc_id = attr->ud_sid;
20397c478bd9Sstevel@tonic-gate 	ud_statep->ud_pkt_life_time =
20407c478bd9Sstevel@tonic-gate 	    ibt_ib2usec(attr->ud_pkt_lt);
20417c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.cm_qp_entry = cm_qp_entry;
20427c478bd9Sstevel@tonic-gate 
20437c478bd9Sstevel@tonic-gate 	/* set remaining retry cnt */
20447c478bd9Sstevel@tonic-gate 	ud_statep->ud_remaining_retry_cnt = ud_statep->ud_max_cm_retries;
20457c478bd9Sstevel@tonic-gate 
20467c478bd9Sstevel@tonic-gate 	/*
20477c478bd9Sstevel@tonic-gate 	 * Get UD handler and corresponding args which is pass it back
20487c478bd9Sstevel@tonic-gate 	 * as first argument for the handler.
20497c478bd9Sstevel@tonic-gate 	 */
20507c478bd9Sstevel@tonic-gate 	ud_statep->ud_state_cm_private = attr->ud_cm_private;
20517c478bd9Sstevel@tonic-gate 
20527c478bd9Sstevel@tonic-gate 	if (mode == IBT_BLOCKING)
20537c478bd9Sstevel@tonic-gate 		ud_statep->ud_return_data = ret_args;
20547c478bd9Sstevel@tonic-gate 	else
20557c478bd9Sstevel@tonic-gate 		ud_statep->ud_cm_handler = attr->ud_cm_handler;
20567c478bd9Sstevel@tonic-gate 
20577c478bd9Sstevel@tonic-gate 	/* Initialize the fields of ud_statep->ud_stored_reply_addr */
20587c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_exists = attr->ud_addr->av_send_grh;
20597c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.ibmf_hdl = ibmf_hdl;
20607c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_hop_limit =
20617c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_hop;
20627c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_sender_gid =
20637c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_sgid;
20647c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_recver_gid =
20657c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_dgid;
20667c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_tclass =
20677c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_tclass;
20687c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_flow_label =
20697c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_flow & IB_GRH_FLOW_LABEL_MASK;
20707c478bd9Sstevel@tonic-gate 
20717c478bd9Sstevel@tonic-gate 	/* needs to be derived based on the base LID and path bits */
20727c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_local_lid =
20737c478bd9Sstevel@tonic-gate 	    port.hp_base_lid;
20747c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_lid =
20757c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_dlid;
20767c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_p_key = ud_pkey;
20777c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_q_key = IB_GSI_QKEY;
20787c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_service_level =
20797c478bd9Sstevel@tonic-gate 	    attr->ud_addr->av_srvl;
20807c478bd9Sstevel@tonic-gate 
20817c478bd9Sstevel@tonic-gate 	/*
20827c478bd9Sstevel@tonic-gate 	 * This may be enchanced later, to use a remote qno based on past
20837c478bd9Sstevel@tonic-gate 	 * redirect rej mad responses. This would be the place to specify
20847c478bd9Sstevel@tonic-gate 	 * appropriate remote qno
20857c478bd9Sstevel@tonic-gate 	 */
20867c478bd9Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_qno = 1;
20877c478bd9Sstevel@tonic-gate 
20887c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
20897c478bd9Sstevel@tonic-gate 
20907c478bd9Sstevel@tonic-gate 	/* Initialize the SIDR REQ message fields */
20917c478bd9Sstevel@tonic-gate 	sidr_req_msgp =
20927c478bd9Sstevel@tonic-gate 	    (ibcm_sidr_req_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
20937c478bd9Sstevel@tonic-gate 
20947c478bd9Sstevel@tonic-gate 	sidr_req_msgp->sidr_req_request_id = h2b32(ud_statep->ud_req_id);
20957c478bd9Sstevel@tonic-gate 	sidr_req_msgp->sidr_req_service_id = h2b64(attr->ud_sid);
20967c478bd9Sstevel@tonic-gate 	sidr_req_msgp->sidr_req_pkey = h2b16(ud_pkey);
20977c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
20987c478bd9Sstevel@tonic-gate 	    h2b16(IBCM_INCOMING_SIDR_REQ + IBCM_ATTR_BASE_ID);
20997c478bd9Sstevel@tonic-gate 
21007c478bd9Sstevel@tonic-gate 	if ((attr->ud_priv_data != NULL) && (attr->ud_priv_data_len > 0)) {
21017c478bd9Sstevel@tonic-gate 		bcopy(attr->ud_priv_data, sidr_req_msgp->sidr_req_private_data,
21027c478bd9Sstevel@tonic-gate 		    min(attr->ud_priv_data_len, IBT_SIDR_REQ_PRIV_DATA_SZ));
21037c478bd9Sstevel@tonic-gate 	}
21047c478bd9Sstevel@tonic-gate 
21057c478bd9Sstevel@tonic-gate 	/* Send out the SIDR REQ message */
21067c478bd9Sstevel@tonic-gate 	ud_statep->ud_state = IBCM_STATE_SIDR_REQ_SENT;
21077c478bd9Sstevel@tonic-gate 	ud_statep->ud_timer_stored_state = IBCM_STATE_SIDR_REQ_SENT;
21087c478bd9Sstevel@tonic-gate 	IBCM_UD_REF_CNT_INCR(ud_statep); /* for non-blocking SIDR REQ post */
21097c478bd9Sstevel@tonic-gate 	ud_statep->ud_timer_value = ibt_ib2usec(ibcm_max_sidr_rep_proctime) +
21107c478bd9Sstevel@tonic-gate 	    (ud_statep->ud_pkt_life_time * 2);
21117c478bd9Sstevel@tonic-gate 
21127c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID =
21137c478bd9Sstevel@tonic-gate 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_SIDR_REQ,
21147c478bd9Sstevel@tonic-gate 	    ud_statep->ud_req_id, 0));
21157c478bd9Sstevel@tonic-gate 
21167c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: timer_value in HZ = %x",
21177c478bd9Sstevel@tonic-gate 	    ud_statep->ud_timer_value);
21187c478bd9Sstevel@tonic-gate 
21197c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
21207c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
21217c478bd9Sstevel@tonic-gate 
21227c478bd9Sstevel@tonic-gate 	ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
21237c478bd9Sstevel@tonic-gate 	    ibcm_post_sidr_req_complete, ud_statep);
21247c478bd9Sstevel@tonic-gate 
21257c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_statep->ud_state_mutex);
21267c478bd9Sstevel@tonic-gate 
21277c478bd9Sstevel@tonic-gate 	/* Wait for SIDR_REP */
21287c478bd9Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
21297c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: blocking");
21307c478bd9Sstevel@tonic-gate 
21317c478bd9Sstevel@tonic-gate 		while (ud_statep->ud_blocking_done != B_TRUE) {
21327c478bd9Sstevel@tonic-gate 			cv_wait(&ud_statep->ud_block_client_cv,
21337c478bd9Sstevel@tonic-gate 			    &ud_statep->ud_state_mutex);
21347c478bd9Sstevel@tonic-gate 		}
21357c478bd9Sstevel@tonic-gate 
21367c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: finished blocking");
21377c478bd9Sstevel@tonic-gate 
21387c478bd9Sstevel@tonic-gate 		if (ret_args->ud_status == IBT_CM_SREP_QPN_VALID) {
21397c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: DQPN = %x, "
21407c478bd9Sstevel@tonic-gate 			    "status = %x, QKey = %x", ret_args->ud_dqpn,
21417c478bd9Sstevel@tonic-gate 			    ret_args->ud_status, ret_args->ud_qkey);
21427c478bd9Sstevel@tonic-gate 
21437c478bd9Sstevel@tonic-gate 		} else {
21447c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: Status<%x>",
21457c478bd9Sstevel@tonic-gate 			    ret_args->ud_status);
21467c478bd9Sstevel@tonic-gate 			retval = IBT_CM_FAILURE;
21477c478bd9Sstevel@tonic-gate 		}
21487c478bd9Sstevel@tonic-gate 	}
21497c478bd9Sstevel@tonic-gate 
21507c478bd9Sstevel@tonic-gate 	IBCM_UD_REF_CNT_DECR(ud_statep);
21517c478bd9Sstevel@tonic-gate 	mutex_exit(&ud_statep->ud_state_mutex);
21527c478bd9Sstevel@tonic-gate 
21537c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: done");
21547c478bd9Sstevel@tonic-gate 
21557c478bd9Sstevel@tonic-gate 	return (retval);
21567c478bd9Sstevel@tonic-gate }
21577c478bd9Sstevel@tonic-gate 
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate /*
21607c478bd9Sstevel@tonic-gate  * Function:
21617c478bd9Sstevel@tonic-gate  *	ibt_request_ud_dest
21627c478bd9Sstevel@tonic-gate  * Input:
21637c478bd9Sstevel@tonic-gate  *	ud_dest		A previously allocated UD destination handle.
21647c478bd9Sstevel@tonic-gate  *	mode		This function can execute in blocking or non blocking
21657c478bd9Sstevel@tonic-gate  *			modes.
21667c478bd9Sstevel@tonic-gate  *	attr		UD destination attributes to be modified.
21677c478bd9Sstevel@tonic-gate  * Output:
21687c478bd9Sstevel@tonic-gate  *	ud_ret_args	If the function is called in blocking mode, ud_ret_args
21697c478bd9Sstevel@tonic-gate  *			should be a pointer to an ibt_ud_returns_t struct.
21707c478bd9Sstevel@tonic-gate  * Returns:
21717c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
21727c478bd9Sstevel@tonic-gate  * Description:
21737c478bd9Sstevel@tonic-gate  *	Modify a previously allocated UD destination handle based on the
21747c478bd9Sstevel@tonic-gate  *	results of doing the SIDR protocol.
21757c478bd9Sstevel@tonic-gate  */
21767c478bd9Sstevel@tonic-gate ibt_status_t
ibt_request_ud_dest(ibt_ud_dest_hdl_t ud_dest,ibt_execution_mode_t mode,ibt_ud_dest_attr_t * attr,ibt_ud_returns_t * ud_ret_args)21777c478bd9Sstevel@tonic-gate ibt_request_ud_dest(ibt_ud_dest_hdl_t ud_dest, ibt_execution_mode_t mode,
21787c478bd9Sstevel@tonic-gate     ibt_ud_dest_attr_t *attr, ibt_ud_returns_t *ud_ret_args)
21797c478bd9Sstevel@tonic-gate {
21807c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
21817c478bd9Sstevel@tonic-gate 	ibt_ud_dest_t		*ud_destp;
21827c478bd9Sstevel@tonic-gate 	ibcm_local_handler_t	*local_handler_priv = NULL;
21837c478bd9Sstevel@tonic-gate 
21847c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_request_ud_dest(%p, %x, %p, %p)",
21857c478bd9Sstevel@tonic-gate 	    ud_dest, mode, attr, ud_ret_args);
21867c478bd9Sstevel@tonic-gate 
21877c478bd9Sstevel@tonic-gate 	retval = ibcm_validate_dqpn_data(attr, mode, ud_ret_args);
21887c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
21897c478bd9Sstevel@tonic-gate 		return (retval);
21907c478bd9Sstevel@tonic-gate 	}
21917c478bd9Sstevel@tonic-gate 
21927c478bd9Sstevel@tonic-gate 	ud_destp = ud_dest;
21937c478bd9Sstevel@tonic-gate 
21947c478bd9Sstevel@tonic-gate 	/* Allocate an Address handle. */
21957c478bd9Sstevel@tonic-gate 	retval = ibt_modify_ah(ud_destp->ud_dest_hca, ud_destp->ud_ah,
21967c478bd9Sstevel@tonic-gate 	    attr->ud_addr);
21977c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
21987c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
21997c478bd9Sstevel@tonic-gate 		    "Address Handle Modification failed: %d", retval);
22007c478bd9Sstevel@tonic-gate 		return (retval);
22017c478bd9Sstevel@tonic-gate 	}
22027c478bd9Sstevel@tonic-gate 
22037c478bd9Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING) {
22047c478bd9Sstevel@tonic-gate 		/*
22057c478bd9Sstevel@tonic-gate 		 * In NON-BLOCKING mode, and we need to update the destination
22067c478bd9Sstevel@tonic-gate 		 * handle with the DQPN and QKey that are obtained from
22077c478bd9Sstevel@tonic-gate 		 * SIDR REP, hook-up our own handler, so that we can catch
22087c478bd9Sstevel@tonic-gate 		 * the event, and we ourselves call the actual client's
22097c478bd9Sstevel@tonic-gate 		 * ud_cm_handler, in our handler.
22107c478bd9Sstevel@tonic-gate 		 */
22117c478bd9Sstevel@tonic-gate 
22127c478bd9Sstevel@tonic-gate 		/* Allocate memory for local handler's private data. */
22137c478bd9Sstevel@tonic-gate 		local_handler_priv =
22147c478bd9Sstevel@tonic-gate 		    kmem_alloc(sizeof (*local_handler_priv), KM_SLEEP);
22157c478bd9Sstevel@tonic-gate 
22167c478bd9Sstevel@tonic-gate 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*local_handler_priv))
22177c478bd9Sstevel@tonic-gate 
22187c478bd9Sstevel@tonic-gate 		local_handler_priv->actual_cm_handler = attr->ud_cm_handler;
22197c478bd9Sstevel@tonic-gate 		local_handler_priv->actual_cm_private = attr->ud_cm_private;
22207c478bd9Sstevel@tonic-gate 		local_handler_priv->dest_hdl = ud_destp;
22217c478bd9Sstevel@tonic-gate 
22227c478bd9Sstevel@tonic-gate 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*local_handler_priv))
22237c478bd9Sstevel@tonic-gate 
22247c478bd9Sstevel@tonic-gate 		attr->ud_cm_handler = ibcm_local_cm_handler;
22257c478bd9Sstevel@tonic-gate 		attr->ud_cm_private = local_handler_priv;
22267c478bd9Sstevel@tonic-gate 	}
22277c478bd9Sstevel@tonic-gate 
22287c478bd9Sstevel@tonic-gate 	/* In order to get DQPN and Destination QKey, perform SIDR */
22297c478bd9Sstevel@tonic-gate 	retval = ibcm_ud_get_dqpn(attr, mode, ud_ret_args);
22307c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
22317c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
22327c478bd9Sstevel@tonic-gate 		    "Failed to get DQPN: %d", retval);
22337c478bd9Sstevel@tonic-gate 
22347c478bd9Sstevel@tonic-gate 		/* Free memory allocated for local handler's private data. */
22357c478bd9Sstevel@tonic-gate 		if (local_handler_priv != NULL)
22367c478bd9Sstevel@tonic-gate 			kmem_free(local_handler_priv,
22377c478bd9Sstevel@tonic-gate 			    sizeof (*local_handler_priv));
22387c478bd9Sstevel@tonic-gate 		return (retval);
22397c478bd9Sstevel@tonic-gate 	}
22407c478bd9Sstevel@tonic-gate 
22417c478bd9Sstevel@tonic-gate 	/*
22427c478bd9Sstevel@tonic-gate 	 * Fill in the dqpn and dqkey as obtained from ud_ret_args,
22437c478bd9Sstevel@tonic-gate 	 * values will be valid only on BLOCKING mode.
22447c478bd9Sstevel@tonic-gate 	 */
22457c478bd9Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
22467c478bd9Sstevel@tonic-gate 		ud_destp->ud_dst_qpn = ud_ret_args->ud_dqpn;
22477c478bd9Sstevel@tonic-gate 		ud_destp->ud_qkey = ud_ret_args->ud_qkey;
22487c478bd9Sstevel@tonic-gate 	}
22497c478bd9Sstevel@tonic-gate 
22507c478bd9Sstevel@tonic-gate 	return (retval);
22517c478bd9Sstevel@tonic-gate }
22527c478bd9Sstevel@tonic-gate 
22537c478bd9Sstevel@tonic-gate /*
22547c478bd9Sstevel@tonic-gate  * Function:
22557c478bd9Sstevel@tonic-gate  *	ibt_ud_get_dqpn
22567c478bd9Sstevel@tonic-gate  * Input:
22577c478bd9Sstevel@tonic-gate  *	attr		A pointer to an ibt_ud_dest_attr_t struct that are
22587c478bd9Sstevel@tonic-gate  *			required for SIDR REQ message. Not specified attributes
22597c478bd9Sstevel@tonic-gate  *			should be set to "NULL" or "0".
22607c478bd9Sstevel@tonic-gate  *			ud_sid, ud_addr and ud_pkt_lt must be specified.
22617c478bd9Sstevel@tonic-gate  *	mode		This function can execute in blocking or non blocking
22627c478bd9Sstevel@tonic-gate  *			modes.
22637c478bd9Sstevel@tonic-gate  * Output:
22647c478bd9Sstevel@tonic-gate  *	returns		If the function is called in blocking mode, returns
22657c478bd9Sstevel@tonic-gate  *			should be a pointer to an ibt_ud_returns_t struct.
22667c478bd9Sstevel@tonic-gate  * Return:
22677c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS	on success or respective failure on error.
22687c478bd9Sstevel@tonic-gate  * Description:
22697c478bd9Sstevel@tonic-gate  *	Finds the destination QPN at the specified destination that the
22707c478bd9Sstevel@tonic-gate  *	specified service can be reached on. The IBTF CM initiates the
22717c478bd9Sstevel@tonic-gate  *	service ID resolution protocol (SIDR) to determine a destination QPN.
22727c478bd9Sstevel@tonic-gate  *
22737c478bd9Sstevel@tonic-gate  * NOTE: SIDR_REQ is initiated from active side.
22747c478bd9Sstevel@tonic-gate  */
22757c478bd9Sstevel@tonic-gate ibt_status_t
ibt_ud_get_dqpn(ibt_ud_dest_attr_t * attr,ibt_execution_mode_t mode,ibt_ud_returns_t * returns)22767c478bd9Sstevel@tonic-gate ibt_ud_get_dqpn(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
22777c478bd9Sstevel@tonic-gate     ibt_ud_returns_t *returns)
22787c478bd9Sstevel@tonic-gate {
22797c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
22807c478bd9Sstevel@tonic-gate 
22817c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_ud_get_dqpn(%p, %x, %p)",
22827c478bd9Sstevel@tonic-gate 	    attr, mode, returns);
22837c478bd9Sstevel@tonic-gate 
22847c478bd9Sstevel@tonic-gate 	retval = ibcm_validate_dqpn_data(attr, mode, returns);
22857c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
22867c478bd9Sstevel@tonic-gate 		return (retval);
22877c478bd9Sstevel@tonic-gate 	}
22887c478bd9Sstevel@tonic-gate 
22897c478bd9Sstevel@tonic-gate 	return (ibcm_ud_get_dqpn(attr, mode, returns));
22907c478bd9Sstevel@tonic-gate }
22917c478bd9Sstevel@tonic-gate 
22927c478bd9Sstevel@tonic-gate 
22937c478bd9Sstevel@tonic-gate /*
22947c478bd9Sstevel@tonic-gate  * ibt_cm_delay:
22957c478bd9Sstevel@tonic-gate  *	A client CM handler function can call this function
22967c478bd9Sstevel@tonic-gate  *	to extend its response time to a CM event.
22977c478bd9Sstevel@tonic-gate  * INPUTS:
22987c478bd9Sstevel@tonic-gate  *	flags		Indicates what CM message processing is being delayed
22997c478bd9Sstevel@tonic-gate  *			by the CM handler, valid values are:
23007c478bd9Sstevel@tonic-gate  *				IBT_CM_DELAY_REQ
23017c478bd9Sstevel@tonic-gate  *				IBT_CM_DELAY_REP
23027c478bd9Sstevel@tonic-gate  *				IBT_CM_DELAY_LAP
23037c478bd9Sstevel@tonic-gate  *	cm_session_id	The session ID that was passed to client srv_handler
23047c478bd9Sstevel@tonic-gate  *			by the CM
23057c478bd9Sstevel@tonic-gate  *	service_time	The extended service time
23067c478bd9Sstevel@tonic-gate  *	priv_data	Vendor specific data to be sent in the CM generated
23077c478bd9Sstevel@tonic-gate  *			MRA message. Should be NULL if not specified.
23087c478bd9Sstevel@tonic-gate  *	len		The number of bytes of data specified by priv_data.
23097c478bd9Sstevel@tonic-gate  *
23107c478bd9Sstevel@tonic-gate  * RETURN VALUES:
23117c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS	on success (or respective failure on error)
23127c478bd9Sstevel@tonic-gate  */
23137c478bd9Sstevel@tonic-gate ibt_status_t
ibt_cm_delay(ibt_cmdelay_flags_t flags,void * cm_session_id,clock_t service_time,void * priv_data,ibt_priv_data_len_t len)23147c478bd9Sstevel@tonic-gate ibt_cm_delay(ibt_cmdelay_flags_t flags, void *cm_session_id,
23157c478bd9Sstevel@tonic-gate     clock_t service_time, void *priv_data, ibt_priv_data_len_t len)
23167c478bd9Sstevel@tonic-gate {
23177c478bd9Sstevel@tonic-gate 	uint8_t			msg_typ = 0;
23187c478bd9Sstevel@tonic-gate 	ibcm_mra_msg_t		*mra_msgp;
23197c478bd9Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
23207c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
23217c478bd9Sstevel@tonic-gate 
23229d3d2ed0Shiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_delay(0x%x, %p, 0x%x)",
23237c478bd9Sstevel@tonic-gate 	    flags, cm_session_id, service_time);
23247c478bd9Sstevel@tonic-gate 
23257c478bd9Sstevel@tonic-gate 	/*
23267c478bd9Sstevel@tonic-gate 	 * Make sure channel is associated with a statep
23277c478bd9Sstevel@tonic-gate 	 */
23287c478bd9Sstevel@tonic-gate 	statep = (ibcm_state_data_t *)cm_session_id;
23297c478bd9Sstevel@tonic-gate 
23307c478bd9Sstevel@tonic-gate 	if (statep == NULL) {
23317c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: statep NULL");
23327c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
23337c478bd9Sstevel@tonic-gate 	}
23347c478bd9Sstevel@tonic-gate 
23357c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_cm_delay: statep %p", statep);
23367c478bd9Sstevel@tonic-gate 
23377c478bd9Sstevel@tonic-gate 	/* Allocate an ibmf msg for mra, if not allocated yet */
23387c478bd9Sstevel@tonic-gate 	if (statep->mra_msg == NULL) {
23397c478bd9Sstevel@tonic-gate 		if ((status = ibcm_alloc_out_msg(
23407c478bd9Sstevel@tonic-gate 		    statep->stored_reply_addr.ibmf_hdl, &statep->mra_msg,
23417c478bd9Sstevel@tonic-gate 		    MAD_METHOD_SEND)) != IBT_SUCCESS) {
23427c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: chan 0x%p"
23437c478bd9Sstevel@tonic-gate 			    "IBMF MSG allocation failed", statep->channel);
23447c478bd9Sstevel@tonic-gate 			return (status);
23457c478bd9Sstevel@tonic-gate 		}
23467c478bd9Sstevel@tonic-gate 	}
23477c478bd9Sstevel@tonic-gate 
23487c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mra_msgp))
23497c478bd9Sstevel@tonic-gate 
23507c478bd9Sstevel@tonic-gate 	mra_msgp = (ibcm_mra_msg_t *)IBCM_OUT_MSGP(statep->mra_msg);
23517c478bd9Sstevel@tonic-gate 	mra_msgp->mra_local_comm_id = h2b32(statep->local_comid);
23527c478bd9Sstevel@tonic-gate 	mra_msgp->mra_remote_comm_id = h2b32(statep->remote_comid);
23537c478bd9Sstevel@tonic-gate 
23547c478bd9Sstevel@tonic-gate 	/* fill in rest of MRA's fields - Message MRAed and Service Timeout */
23557c478bd9Sstevel@tonic-gate 	if (flags == IBT_CM_DELAY_REQ) {
23567c478bd9Sstevel@tonic-gate 		msg_typ = IBT_CM_MRA_TYPE_REQ;
23577c478bd9Sstevel@tonic-gate 	} else if (flags == IBT_CM_DELAY_REP) {
23587c478bd9Sstevel@tonic-gate 		msg_typ = IBT_CM_MRA_TYPE_REP;
23597c478bd9Sstevel@tonic-gate 	} else if (flags == IBT_CM_DELAY_LAP) {
23607c478bd9Sstevel@tonic-gate 		msg_typ = IBT_CM_MRA_TYPE_LAP;
23617c478bd9Sstevel@tonic-gate 	}
23627c478bd9Sstevel@tonic-gate 
23637c478bd9Sstevel@tonic-gate 	mra_msgp->mra_message_type_plus = msg_typ << 6;
23647c478bd9Sstevel@tonic-gate 	mra_msgp->mra_service_timeout_plus = ibt_usec2ib(service_time) << 3;
23657c478bd9Sstevel@tonic-gate 
23667c478bd9Sstevel@tonic-gate 	len = min(len, IBT_MRA_PRIV_DATA_SZ);
23677c478bd9Sstevel@tonic-gate 	if (priv_data && (len > 0))
23687c478bd9Sstevel@tonic-gate 		bcopy(priv_data, mra_msgp->mra_private_data, len);
23697c478bd9Sstevel@tonic-gate 
23707c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->mra_msg)->AttributeID =
23717c478bd9Sstevel@tonic-gate 	    h2b16(IBCM_INCOMING_MRA + IBCM_ATTR_BASE_ID);
23727c478bd9Sstevel@tonic-gate 
23737c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mra_msgp))
23747c478bd9Sstevel@tonic-gate 
23757c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
23767c478bd9Sstevel@tonic-gate 
23777c478bd9Sstevel@tonic-gate 	if ((statep->mode == IBCM_ACTIVE_MODE) &&
23787c478bd9Sstevel@tonic-gate 	    (statep->state == IBCM_STATE_REP_RCVD)) {
23797c478bd9Sstevel@tonic-gate 		statep->state = IBCM_STATE_MRA_REP_SENT;
23807c478bd9Sstevel@tonic-gate 	} else if (statep->mode == IBCM_PASSIVE_MODE) {
238124b28d04Shiremath 		if (statep->state == IBCM_STATE_REQ_RCVD) {
23827c478bd9Sstevel@tonic-gate 			statep->state = IBCM_STATE_MRA_SENT;
238324b28d04Shiremath 		} else if (statep->ap_state == IBCM_AP_STATE_LAP_RCVD) {
23847c478bd9Sstevel@tonic-gate 			statep->ap_state = IBCM_AP_STATE_MRA_LAP_RCVD;
238524b28d04Shiremath 		} else {
238624b28d04Shiremath 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
238724b28d04Shiremath 			    "/ap_state/mode %x, %x, %x", statep->state,
238824b28d04Shiremath 			    statep->ap_state, statep->mode);
238924b28d04Shiremath 			mutex_exit(&statep->state_mutex);
239024b28d04Shiremath 			return (IBT_CHAN_STATE_INVALID);
23917c478bd9Sstevel@tonic-gate 		}
23927c478bd9Sstevel@tonic-gate 	} else {
23937c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
23947c478bd9Sstevel@tonic-gate 		    "/ap_state/mode %x, %x, %x", statep->state,
23957c478bd9Sstevel@tonic-gate 		    statep->ap_state, statep->mode);
23967c478bd9Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
23977c478bd9Sstevel@tonic-gate 
23987c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
23997c478bd9Sstevel@tonic-gate 	}
240024b28d04Shiremath 	/* service time is usecs, stale_clock is nsecs */
2401fde3102fShiremath 	statep->stale_clock = gethrtime() +
2402fde3102fShiremath 	    (hrtime_t)ibt_ib2usec(ibt_usec2ib(service_time)) * (1000 *
240324b28d04Shiremath 	    statep->max_cm_retries);
24047c478bd9Sstevel@tonic-gate 
24057c478bd9Sstevel@tonic-gate 	statep->send_mad_flags |= IBCM_MRA_POST_BUSY;
24067c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);	/* for ibcm_post_mra_complete */
24077c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
24087c478bd9Sstevel@tonic-gate 
24097c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->mra_msg)->TransactionID =
24107c478bd9Sstevel@tonic-gate 	    IBCM_OUT_HDRP(statep->stored_msg)->TransactionID;
24117c478bd9Sstevel@tonic-gate 
24127c478bd9Sstevel@tonic-gate 	/* post the MRA mad in blocking mode, as no timers involved */
24137c478bd9Sstevel@tonic-gate 	ibcm_post_rc_mad(statep, statep->mra_msg, ibcm_post_mra_complete,
24147c478bd9Sstevel@tonic-gate 	    statep);
24159d3d2ed0Shiremath 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_MRA);
24167c478bd9Sstevel@tonic-gate 	/* If this message isn't seen then ibt_cm_delay failed */
24179d3d2ed0Shiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_delay: done !!");
24187c478bd9Sstevel@tonic-gate 
24197c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
24207c478bd9Sstevel@tonic-gate }
24217c478bd9Sstevel@tonic-gate 
24227c478bd9Sstevel@tonic-gate 
24237c478bd9Sstevel@tonic-gate /*
24247c478bd9Sstevel@tonic-gate  * ibt_register_service()
24257c478bd9Sstevel@tonic-gate  *	Register a service with the IBCM
24267c478bd9Sstevel@tonic-gate  *
24277c478bd9Sstevel@tonic-gate  * INPUTS:
24287c478bd9Sstevel@tonic-gate  *	ibt_hdl		The IBT client handle returned to the client
24297c478bd9Sstevel@tonic-gate  *			on an ibt_attach() call.
24307c478bd9Sstevel@tonic-gate  *
24317c478bd9Sstevel@tonic-gate  *	srv		The address of a ibt_srv_desc_t that describes
24327c478bd9Sstevel@tonic-gate  *			the service, containing the following:
24337c478bd9Sstevel@tonic-gate  *
24347c478bd9Sstevel@tonic-gate  *		sd_ud_handler	The Service CM UD event Handler.
24357c478bd9Sstevel@tonic-gate  *		sd_handler	The Service CM RC/UC/RD event Handler.
24367c478bd9Sstevel@tonic-gate  *		sd_flags	Service flags (peer-to-peer, or not).
24377c478bd9Sstevel@tonic-gate  *
24387c478bd9Sstevel@tonic-gate  *	sid		This tells CM if the service is local (sid is 0) or
24397c478bd9Sstevel@tonic-gate  *			wellknown (sid is the starting service id of the range).
24407c478bd9Sstevel@tonic-gate  *
24417c478bd9Sstevel@tonic-gate  *	num_sids	The number of contiguous service-ids to reserve.
24427c478bd9Sstevel@tonic-gate  *
24437c478bd9Sstevel@tonic-gate  *	srv_hdl		The address of a service identification handle, used
24447c478bd9Sstevel@tonic-gate  *			to deregister a service, and to bind GIDs to.
24457c478bd9Sstevel@tonic-gate  *
24467c478bd9Sstevel@tonic-gate  *	ret_sid		The address to store the Service ID return value.
24477c478bd9Sstevel@tonic-gate  *			If num_sids > 1, ret_sid is the first Service ID
24487c478bd9Sstevel@tonic-gate  *			in the range.
24497c478bd9Sstevel@tonic-gate  *
24507c478bd9Sstevel@tonic-gate  * ibt_register_service() returns:
24517c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS		- added a service successfully.
24527c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM	- invalid input parameter.
24537c478bd9Sstevel@tonic-gate  *	IBT_CM_FAILURE		- failed to add the service.
24547c478bd9Sstevel@tonic-gate  *	IBT_CM_SERVICE_EXISTS	- service already exists.
24557c478bd9Sstevel@tonic-gate  *	IBT_INSUFF_KERNEL_RESOURCE - ran out of local service ids (should
24567c478bd9Sstevel@tonic-gate  *				     never happen).
24577c478bd9Sstevel@tonic-gate  */
24587c478bd9Sstevel@tonic-gate ibt_status_t
ibt_register_service(ibt_clnt_hdl_t ibt_hdl,ibt_srv_desc_t * srv,ib_svc_id_t sid,int num_sids,ibt_srv_hdl_t * srv_hdl,ib_svc_id_t * ret_sid)24597c478bd9Sstevel@tonic-gate ibt_register_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_desc_t *srv,
24607c478bd9Sstevel@tonic-gate     ib_svc_id_t sid, int num_sids, ibt_srv_hdl_t *srv_hdl, ib_svc_id_t *ret_sid)
24617c478bd9Sstevel@tonic-gate {
24627c478bd9Sstevel@tonic-gate 	ibcm_svc_info_t		*svcinfop;
24637c478bd9Sstevel@tonic-gate 
2464d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L2(cmlog, "ibt_register_service(%p (%s), %p, 0x%llX, %d)",
2465d3a82192SShantkumar Hiremath 	    ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv, (longlong_t)sid,
2466d3a82192SShantkumar Hiremath 	    num_sids);
24677c478bd9Sstevel@tonic-gate 
24687c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*svcinfop))
24697c478bd9Sstevel@tonic-gate 
24707c478bd9Sstevel@tonic-gate 	*srv_hdl = NULL;
24717c478bd9Sstevel@tonic-gate 
24727c478bd9Sstevel@tonic-gate 	if (num_sids <= 0) {
24737c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24747c478bd9Sstevel@tonic-gate 		    "Invalid number of service-ids specified (%d)", num_sids);
24757c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
24767c478bd9Sstevel@tonic-gate 	}
24777c478bd9Sstevel@tonic-gate 
24787c478bd9Sstevel@tonic-gate 	if (sid == 0) {
24797c478bd9Sstevel@tonic-gate 		if (ret_sid == NULL)
24807c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
24817c478bd9Sstevel@tonic-gate 		sid = ibcm_alloc_local_sids(num_sids);
24827c478bd9Sstevel@tonic-gate 		if (sid == 0)
24837c478bd9Sstevel@tonic-gate 			return (IBT_INSUFF_KERNEL_RESOURCE);
24847c478bd9Sstevel@tonic-gate 
24857c478bd9Sstevel@tonic-gate 	/* Make sure that the ServiceId specified is not of LOCAL AGN type. */
24867c478bd9Sstevel@tonic-gate 	} else if ((sid & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL) {
24877c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24887c478bd9Sstevel@tonic-gate 		    "Invalid non-LOCAL SID specified: 0x%llX",
24897c478bd9Sstevel@tonic-gate 		    (longlong_t)sid);
24907c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
24917c478bd9Sstevel@tonic-gate 	}
24927c478bd9Sstevel@tonic-gate 
24937c478bd9Sstevel@tonic-gate 	svcinfop = ibcm_create_svc_entry(sid, num_sids);
24947c478bd9Sstevel@tonic-gate 
24957c478bd9Sstevel@tonic-gate 	if (svcinfop == NULL) {
24967c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24977c478bd9Sstevel@tonic-gate 		    "Service-ID 0x%llx already registered", (longlong_t)sid);
24987c478bd9Sstevel@tonic-gate 		return (IBT_CM_SERVICE_EXISTS);
24997c478bd9Sstevel@tonic-gate 	}
25007c478bd9Sstevel@tonic-gate 
25017c478bd9Sstevel@tonic-gate 	/*
25027c478bd9Sstevel@tonic-gate 	 * 'sid' and 'num_sids' are filled in ibcm_create_svc_entry()
25037c478bd9Sstevel@tonic-gate 	 */
25047c478bd9Sstevel@tonic-gate 	svcinfop->svc_flags = srv->sd_flags;
25057c478bd9Sstevel@tonic-gate 	svcinfop->svc_rc_handler = srv->sd_handler;
25067c478bd9Sstevel@tonic-gate 	svcinfop->svc_ud_handler = srv->sd_ud_handler;
25077c478bd9Sstevel@tonic-gate 
25087c478bd9Sstevel@tonic-gate 	if (ret_sid != NULL)
25097c478bd9Sstevel@tonic-gate 		*ret_sid = sid;
25107c478bd9Sstevel@tonic-gate 
25117c478bd9Sstevel@tonic-gate 	*srv_hdl = svcinfop;
25127c478bd9Sstevel@tonic-gate 
25137c478bd9Sstevel@tonic-gate 	ibtl_cm_change_service_cnt(ibt_hdl, num_sids);
25147c478bd9Sstevel@tonic-gate 
25157c478bd9Sstevel@tonic-gate 	/* If this message isn't seen, then ibt_register_service failed. */
25167c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_register_service: done (%p, %llX)",
25177c478bd9Sstevel@tonic-gate 	    svcinfop, sid);
25187c478bd9Sstevel@tonic-gate 
25197c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*svcinfop))
25207c478bd9Sstevel@tonic-gate 
25217c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
25227c478bd9Sstevel@tonic-gate }
25237c478bd9Sstevel@tonic-gate 
25247c478bd9Sstevel@tonic-gate 
25257c478bd9Sstevel@tonic-gate static ibt_status_t
ibcm_write_service_record(ibmf_saa_handle_t saa_handle,sa_service_record_t * srv_recp,ibmf_saa_access_type_t saa_type)25267c478bd9Sstevel@tonic-gate ibcm_write_service_record(ibmf_saa_handle_t saa_handle,
25277c478bd9Sstevel@tonic-gate     sa_service_record_t *srv_recp, ibmf_saa_access_type_t saa_type)
25287c478bd9Sstevel@tonic-gate {
25297c478bd9Sstevel@tonic-gate 	int	rval;
25307c478bd9Sstevel@tonic-gate 	int	retry;
25317c478bd9Sstevel@tonic-gate 
25327c478bd9Sstevel@tonic-gate 	ibcm_sa_access_enter();
25337c478bd9Sstevel@tonic-gate 	for (retry = 0; retry < ibcm_max_sa_retries; retry++) {
25347c478bd9Sstevel@tonic-gate 		rval = ibmf_saa_update_service_record(
25357c478bd9Sstevel@tonic-gate 		    saa_handle, srv_recp, saa_type, 0);
25367c478bd9Sstevel@tonic-gate 		if (rval != IBMF_TRANS_TIMEOUT) {
25377c478bd9Sstevel@tonic-gate 			break;
25387c478bd9Sstevel@tonic-gate 		}
25397c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
25407c478bd9Sstevel@tonic-gate 		    "ibmf_saa_update_service_record timed out"
25417c478bd9Sstevel@tonic-gate 		    " SID = %llX, rval = %d, saa_type = %d",
25427c478bd9Sstevel@tonic-gate 		    (longlong_t)srv_recp->ServiceID, rval, saa_type);
25437c478bd9Sstevel@tonic-gate 		delay(ibcm_sa_timeout_delay);
25447c478bd9Sstevel@tonic-gate 	}
25457c478bd9Sstevel@tonic-gate 	ibcm_sa_access_exit();
25467c478bd9Sstevel@tonic-gate 
25477c478bd9Sstevel@tonic-gate 	if (rval != IBMF_SUCCESS) {
25487c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
25497c478bd9Sstevel@tonic-gate 		    "ibmf_saa_update_service_record() : Failed - %d", rval);
25507c478bd9Sstevel@tonic-gate 		return (ibcm_ibmf_analyze_error(rval));
25517c478bd9Sstevel@tonic-gate 	} else
25527c478bd9Sstevel@tonic-gate 		return (IBT_SUCCESS);
25537c478bd9Sstevel@tonic-gate }
25547c478bd9Sstevel@tonic-gate 
25557c478bd9Sstevel@tonic-gate 
25567c478bd9Sstevel@tonic-gate static void
ibcm_rem_stale_srec(ibmf_saa_handle_t saa_handle,sa_service_record_t * srec)25577c478bd9Sstevel@tonic-gate ibcm_rem_stale_srec(ibmf_saa_handle_t saa_handle, sa_service_record_t *srec)
25587c478bd9Sstevel@tonic-gate {
25597c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
25607c478bd9Sstevel@tonic-gate 	uint_t			num_found;
25617c478bd9Sstevel@tonic-gate 	size_t			length;
25627c478bd9Sstevel@tonic-gate 	sa_service_record_t	*srv_resp;
25637c478bd9Sstevel@tonic-gate 	void			*results_p;
25647c478bd9Sstevel@tonic-gate 	uint_t			i;
25657c478bd9Sstevel@tonic-gate 	uint64_t		component_mask;
25667c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
25677c478bd9Sstevel@tonic-gate 
25687c478bd9Sstevel@tonic-gate 	component_mask =
25697c478bd9Sstevel@tonic-gate 	    SA_SR_COMPMASK_PKEY | SA_SR_COMPMASK_NAME | SA_SR_COMPMASK_GID;
25707c478bd9Sstevel@tonic-gate 
25717c478bd9Sstevel@tonic-gate 	/* Call in SA Access retrieve routine to get Service Records. */
25727c478bd9Sstevel@tonic-gate 	access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
25737c478bd9Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
25747c478bd9Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
25757c478bd9Sstevel@tonic-gate 	access_args.sq_template = srec;
25767c478bd9Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_service_record_t);
25777c478bd9Sstevel@tonic-gate 	access_args.sq_callback = NULL;
25787c478bd9Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
25797c478bd9Sstevel@tonic-gate 
25807c478bd9Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
25817c478bd9Sstevel@tonic-gate 	    &results_p);
25827c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
25837c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
25847c478bd9Sstevel@tonic-gate 		    "SA Access Failure");
25857c478bd9Sstevel@tonic-gate 		return;
25867c478bd9Sstevel@tonic-gate 	}
25877c478bd9Sstevel@tonic-gate 
25887c478bd9Sstevel@tonic-gate 	num_found = length / sizeof (sa_service_record_t);
25897c478bd9Sstevel@tonic-gate 
25907c478bd9Sstevel@tonic-gate 	if (num_found)
25917c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
25927c478bd9Sstevel@tonic-gate 		    "Found %d matching Service Records.", num_found);
25937c478bd9Sstevel@tonic-gate 
25947c478bd9Sstevel@tonic-gate 	/* Validate the returned number of records. */
25957c478bd9Sstevel@tonic-gate 	if ((results_p != NULL) && (num_found > 0)) {
25967c478bd9Sstevel@tonic-gate 
25977c478bd9Sstevel@tonic-gate 		/* Remove all the records. */
25987c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_found; i++) {
25997c478bd9Sstevel@tonic-gate 
26007c478bd9Sstevel@tonic-gate 			srv_resp = (sa_service_record_t *)
26017c478bd9Sstevel@tonic-gate 			    ((uchar_t *)results_p +
26027c478bd9Sstevel@tonic-gate 			    i * sizeof (sa_service_record_t));
26037c478bd9Sstevel@tonic-gate 
26047c478bd9Sstevel@tonic-gate 			/*
26057c478bd9Sstevel@tonic-gate 			 * Found some matching records, but check out whether
26067c478bd9Sstevel@tonic-gate 			 * this Record is really stale or just happens to match
26077c478bd9Sstevel@tonic-gate 			 * the current session records. If yes, don't remove it.
26087c478bd9Sstevel@tonic-gate 			 */
26097c478bd9Sstevel@tonic-gate 			mutex_enter(&ibcm_svc_info_lock);
26107c478bd9Sstevel@tonic-gate 			if (ibcm_find_svc_entry(srv_resp->ServiceID) != NULL) {
26117c478bd9Sstevel@tonic-gate 				/* This record is NOT STALE. */
26127c478bd9Sstevel@tonic-gate 				mutex_exit(&ibcm_svc_info_lock);
26137c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
26147c478bd9Sstevel@tonic-gate 				    "This is not Stale, it's an active record");
26157c478bd9Sstevel@tonic-gate 				continue;
26167c478bd9Sstevel@tonic-gate 			}
26177c478bd9Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
26187c478bd9Sstevel@tonic-gate 
26197c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
26207c478bd9Sstevel@tonic-gate 			    "Removing Stale Rec: %s, %llX",
26217c478bd9Sstevel@tonic-gate 			    srv_resp->ServiceName, srv_resp->ServiceID);
26227c478bd9Sstevel@tonic-gate 
26237c478bd9Sstevel@tonic-gate 			IBCM_DUMP_SERVICE_REC(srv_resp);
26247c478bd9Sstevel@tonic-gate 
26257c478bd9Sstevel@tonic-gate 			/*
26267c478bd9Sstevel@tonic-gate 			 * Remove the Service Record Entry from SA.
26277c478bd9Sstevel@tonic-gate 			 *
26287c478bd9Sstevel@tonic-gate 			 * Get ServiceID info from Response Buf, other
26297c478bd9Sstevel@tonic-gate 			 * attributes are already filled-in.
26307c478bd9Sstevel@tonic-gate 			 */
26317c478bd9Sstevel@tonic-gate 
26327c478bd9Sstevel@tonic-gate 			 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srec->ServiceID))
26337c478bd9Sstevel@tonic-gate 
26347c478bd9Sstevel@tonic-gate 			srec->ServiceID = srv_resp->ServiceID;
26357c478bd9Sstevel@tonic-gate 
26367c478bd9Sstevel@tonic-gate 			 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srec->ServiceID))
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate 			(void) ibcm_write_service_record(saa_handle, srec,
26397c478bd9Sstevel@tonic-gate 			    IBMF_SAA_DELETE);
26407c478bd9Sstevel@tonic-gate 		}
26417c478bd9Sstevel@tonic-gate 
26427c478bd9Sstevel@tonic-gate 		/* Deallocate the memory for results_p. */
26437c478bd9Sstevel@tonic-gate 		kmem_free(results_p, length);
26447c478bd9Sstevel@tonic-gate 	}
26457c478bd9Sstevel@tonic-gate }
26467c478bd9Sstevel@tonic-gate 
26477c478bd9Sstevel@tonic-gate 
26487c478bd9Sstevel@tonic-gate 
26497c478bd9Sstevel@tonic-gate /*
26507c478bd9Sstevel@tonic-gate  * ibt_bind_service()
26517c478bd9Sstevel@tonic-gate  *	Register a service with the IBCM
26527c478bd9Sstevel@tonic-gate  *
26537c478bd9Sstevel@tonic-gate  * INPUTS:
26547c478bd9Sstevel@tonic-gate  *	srv_hdl		The service id handle returned to the client
26557c478bd9Sstevel@tonic-gate  *			on an ibt_service_register() call.
26567c478bd9Sstevel@tonic-gate  *
26577c478bd9Sstevel@tonic-gate  *	gid		The GID to which to bind the service.
26587c478bd9Sstevel@tonic-gate  *
26597c478bd9Sstevel@tonic-gate  *	srv_bind	The address of a ibt_srv_bind_t that describes
26607c478bd9Sstevel@tonic-gate  *			the service record.  This should be NULL if there
26617c478bd9Sstevel@tonic-gate  *			is to be no service record.  This contains:
26627c478bd9Sstevel@tonic-gate  *
26637c478bd9Sstevel@tonic-gate  *		sb_lease	Lease period
26647c478bd9Sstevel@tonic-gate  *		sb_pkey		Partition
26657c478bd9Sstevel@tonic-gate  *		sb_name		pointer to ASCII string Service Name,
26667c478bd9Sstevel@tonic-gate  *				NULL terminated.
26677c478bd9Sstevel@tonic-gate  *		sb_key[]	Key to secure the service record.
26687c478bd9Sstevel@tonic-gate  *		sb_data		Service Data structure (64-byte)
26697c478bd9Sstevel@tonic-gate  *
26707c478bd9Sstevel@tonic-gate  *	cm_private	First argument of Service handler.
26717c478bd9Sstevel@tonic-gate  *
26727c478bd9Sstevel@tonic-gate  *	sb_hdl_p	The address of a service bind handle, used
26737c478bd9Sstevel@tonic-gate  *			to undo the service binding.
26747c478bd9Sstevel@tonic-gate  *
26757c478bd9Sstevel@tonic-gate  * ibt_bind_service() returns:
26767c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS		- added a service successfully.
26777c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM	- invalid input parameter.
26787c478bd9Sstevel@tonic-gate  *	IBT_CM_FAILURE		- failed to add the service.
26797c478bd9Sstevel@tonic-gate  *	IBT_CM_SERVICE_EXISTS	- service already exists.
26807c478bd9Sstevel@tonic-gate  */
26817c478bd9Sstevel@tonic-gate ibt_status_t
ibt_bind_service(ibt_srv_hdl_t srv_hdl,ib_gid_t gid,ibt_srv_bind_t * srv_bind,void * cm_private,ibt_sbind_hdl_t * sb_hdl_p)26827c478bd9Sstevel@tonic-gate ibt_bind_service(ibt_srv_hdl_t srv_hdl, ib_gid_t gid, ibt_srv_bind_t *srv_bind,
26837c478bd9Sstevel@tonic-gate     void *cm_private, ibt_sbind_hdl_t *sb_hdl_p)
26847c478bd9Sstevel@tonic-gate {
26857c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
26867c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	port;
26877c478bd9Sstevel@tonic-gate 	ibcm_svc_bind_t		*sbindp, *sbp;
26887c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
26897c478bd9Sstevel@tonic-gate 	ib_svc_id_t		sid, start_sid, end_sid;
26907c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
26917c478bd9Sstevel@tonic-gate 	sa_service_record_t	srv_rec;
26927c478bd9Sstevel@tonic-gate 	uint16_t		pkey_ix;
26937c478bd9Sstevel@tonic-gate 
26947c478bd9Sstevel@tonic-gate 	if (sb_hdl_p != NULL)
26957c478bd9Sstevel@tonic-gate 		*sb_hdl_p = NULL;	/* return value for error cases */
26967c478bd9Sstevel@tonic-gate 
26977c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: srv_hdl %p, gid (%llX:%llX)",
26987c478bd9Sstevel@tonic-gate 	    srv_hdl, (longlong_t)gid.gid_prefix, (longlong_t)gid.gid_guid);
26997c478bd9Sstevel@tonic-gate 
27007c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sbindp))
27017c478bd9Sstevel@tonic-gate 
27027c478bd9Sstevel@tonic-gate 	/* Call ibtl_cm_get_hca_port to get the port number and the HCA GUID. */
27037c478bd9Sstevel@tonic-gate 	if ((status = ibtl_cm_get_hca_port(gid, 0, &port)) != IBT_SUCCESS) {
27047c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27057c478bd9Sstevel@tonic-gate 		    "ibtl_cm_get_hca_port failed: %d", status);
27067c478bd9Sstevel@tonic-gate 		return (status);
27077c478bd9Sstevel@tonic-gate 	}
27087c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: Port:%d HCA GUID:%llX",
27097c478bd9Sstevel@tonic-gate 	    port.hp_port, port.hp_hca_guid);
27107c478bd9Sstevel@tonic-gate 
27117c478bd9Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(port.hp_hca_guid);
27127c478bd9Sstevel@tonic-gate 	if (hcap == NULL) {
27137c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: NO HCA found");
27147c478bd9Sstevel@tonic-gate 		return (IBT_HCA_BUSY_DETACHING);
27157c478bd9Sstevel@tonic-gate 	}
27167c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: hcap = %p", hcap);
27177c478bd9Sstevel@tonic-gate 
27187c478bd9Sstevel@tonic-gate 	if (srv_bind != NULL) {
27197c478bd9Sstevel@tonic-gate 		saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
27207c478bd9Sstevel@tonic-gate 		if (saa_handle == NULL) {
27217c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27227c478bd9Sstevel@tonic-gate 			    "saa_handle is NULL");
27237c478bd9Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
27247c478bd9Sstevel@tonic-gate 			return (IBT_HCA_PORT_NOT_ACTIVE);
27257c478bd9Sstevel@tonic-gate 		}
27267c478bd9Sstevel@tonic-gate 		if (srv_bind->sb_pkey == 0) {
27277c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27287c478bd9Sstevel@tonic-gate 			    "P_Key must not be 0");
27297c478bd9Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
27307c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
27317c478bd9Sstevel@tonic-gate 		}
27327c478bd9Sstevel@tonic-gate 		if (strlen(srv_bind->sb_name) >= IB_SVC_NAME_LEN) {
27337c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27347c478bd9Sstevel@tonic-gate 			    "Service Name is too long");
27357c478bd9Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
27367c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
27377c478bd9Sstevel@tonic-gate 		} else
27387c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_bind_service: "
27397c478bd9Sstevel@tonic-gate 			    "Service Name='%s'", srv_bind->sb_name);
27407c478bd9Sstevel@tonic-gate 		status = ibt_pkey2index_byguid(port.hp_hca_guid,
27417c478bd9Sstevel@tonic-gate 		    port.hp_port, srv_bind->sb_pkey, &pkey_ix);
27427c478bd9Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
27437c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27447c478bd9Sstevel@tonic-gate 			    "P_Key 0x%x not found in P_Key_Table",
27457c478bd9Sstevel@tonic-gate 			    srv_bind->sb_pkey);
27467c478bd9Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
27477c478bd9Sstevel@tonic-gate 			return (status);
27487c478bd9Sstevel@tonic-gate 		}
27497c478bd9Sstevel@tonic-gate 	}
27507c478bd9Sstevel@tonic-gate 
27517c478bd9Sstevel@tonic-gate 	/* assume success - allocate before locking */
27527c478bd9Sstevel@tonic-gate 	sbindp = kmem_zalloc(sizeof (*sbindp), KM_SLEEP);
27537c478bd9Sstevel@tonic-gate 	sbindp->sbind_cm_private = cm_private;
27547c478bd9Sstevel@tonic-gate 	sbindp->sbind_gid = gid;
27557c478bd9Sstevel@tonic-gate 	sbindp->sbind_hcaguid = port.hp_hca_guid;
27567c478bd9Sstevel@tonic-gate 	sbindp->sbind_port = port.hp_port;
27577c478bd9Sstevel@tonic-gate 
27587c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
27597c478bd9Sstevel@tonic-gate 
27607c478bd9Sstevel@tonic-gate 	sbp = srv_hdl->svc_bind_list;
27617c478bd9Sstevel@tonic-gate 	while (sbp != NULL) {
27627c478bd9Sstevel@tonic-gate 		if (sbp->sbind_gid.gid_guid == gid.gid_guid &&
27637c478bd9Sstevel@tonic-gate 		    sbp->sbind_gid.gid_prefix == gid.gid_prefix) {
27647c478bd9Sstevel@tonic-gate 			if (srv_bind == NULL ||
27657c478bd9Sstevel@tonic-gate 			    srv_bind->sb_pkey == sbp->sbind_pkey) {
27667c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2767448978d3Shiremath 				    "failed: GID %llX:%llX and PKEY %x is "
27685c42ea03Shiremath 				    "already bound", gid.gid_prefix,
27695c42ea03Shiremath 				    gid.gid_guid, sbp->sbind_pkey);
27707c478bd9Sstevel@tonic-gate 				mutex_exit(&ibcm_svc_info_lock);
27717c478bd9Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
27727c478bd9Sstevel@tonic-gate 				kmem_free(sbindp, sizeof (*sbindp));
27737c478bd9Sstevel@tonic-gate 				return (IBT_CM_SERVICE_EXISTS);
27747c478bd9Sstevel@tonic-gate 			}
27757c478bd9Sstevel@tonic-gate 		}
27767c478bd9Sstevel@tonic-gate 		sbp = sbp->sbind_link;
27777c478bd9Sstevel@tonic-gate 	}
27787c478bd9Sstevel@tonic-gate 	/* no entry found */
27797c478bd9Sstevel@tonic-gate 
27807c478bd9Sstevel@tonic-gate 	sbindp->sbind_link = srv_hdl->svc_bind_list;
27817c478bd9Sstevel@tonic-gate 	srv_hdl->svc_bind_list = sbindp;
27827c478bd9Sstevel@tonic-gate 
27837c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
27847c478bd9Sstevel@tonic-gate 
27857c478bd9Sstevel@tonic-gate 	if (srv_bind != NULL) {
27867c478bd9Sstevel@tonic-gate 		bzero(&srv_rec, sizeof (srv_rec));
27877c478bd9Sstevel@tonic-gate 
27887c478bd9Sstevel@tonic-gate 		srv_rec.ServiceLease =
27897c478bd9Sstevel@tonic-gate 		    sbindp->sbind_lease = srv_bind->sb_lease;
27907c478bd9Sstevel@tonic-gate 		srv_rec.ServiceP_Key =
27917c478bd9Sstevel@tonic-gate 		    sbindp->sbind_pkey = srv_bind->sb_pkey;
27927c478bd9Sstevel@tonic-gate 		srv_rec.ServiceKey_hi =
27937c478bd9Sstevel@tonic-gate 		    sbindp->sbind_key[0] = srv_bind->sb_key[0];
27947c478bd9Sstevel@tonic-gate 		srv_rec.ServiceKey_lo =
27957c478bd9Sstevel@tonic-gate 		    sbindp->sbind_key[1] = srv_bind->sb_key[1];
27967c478bd9Sstevel@tonic-gate 		(void) strcpy(sbindp->sbind_name, srv_bind->sb_name);
27977c478bd9Sstevel@tonic-gate 		(void) strcpy((char *)srv_rec.ServiceName, srv_bind->sb_name);
27987c478bd9Sstevel@tonic-gate 		srv_rec.ServiceGID = gid;
27997c478bd9Sstevel@tonic-gate 
28007c478bd9Sstevel@tonic-gate 		/*
28017c478bd9Sstevel@tonic-gate 		 * Find out whether we have any stale Local Service records
28027c478bd9Sstevel@tonic-gate 		 * matching the current attributes.  If yes, we shall try to
28037c478bd9Sstevel@tonic-gate 		 * remove them from SA using the current request's ServiceKey.
28047c478bd9Sstevel@tonic-gate 		 *
28057c478bd9Sstevel@tonic-gate 		 * We will perform this operation only for Local Services, as
28067c478bd9Sstevel@tonic-gate 		 * it is handled by SA automatically for WellKnown Services.
28077c478bd9Sstevel@tonic-gate 		 *
28087c478bd9Sstevel@tonic-gate 		 * Ofcourse, clients can specify NOT to do this clean-up by
28097c478bd9Sstevel@tonic-gate 		 * setting IBT_SBIND_NO_CLEANUP flag (srv_bind->sb_flag).
28107c478bd9Sstevel@tonic-gate 		 */
28117c478bd9Sstevel@tonic-gate 		if ((srv_hdl->svc_id & IB_SID_AGN_LOCAL) &&
28127c478bd9Sstevel@tonic-gate 		    (!(srv_bind->sb_flag & IBT_SBIND_NO_CLEANUP))) {
28137c478bd9Sstevel@tonic-gate 			ibcm_rem_stale_srec(saa_handle, &srv_rec);
28147c478bd9Sstevel@tonic-gate 		}
28157c478bd9Sstevel@tonic-gate 
28167c478bd9Sstevel@tonic-gate 		/* Handle endianess for service data. */
28177c478bd9Sstevel@tonic-gate 		ibcm_swizzle_from_srv(&srv_bind->sb_data, sbindp->sbind_data);
28187c478bd9Sstevel@tonic-gate 
28197c478bd9Sstevel@tonic-gate 		bcopy(sbindp->sbind_data, srv_rec.ServiceData, IB_SVC_DATA_LEN);
28207c478bd9Sstevel@tonic-gate 
28217c478bd9Sstevel@tonic-gate 		/* insert srv record into the SA */
28227c478bd9Sstevel@tonic-gate 		start_sid = srv_hdl->svc_id;
28237c478bd9Sstevel@tonic-gate 		end_sid = start_sid + srv_hdl->svc_num_sids - 1;
28247c478bd9Sstevel@tonic-gate 		for (sid = start_sid; sid <= end_sid; sid++) {
28257c478bd9Sstevel@tonic-gate 
28267c478bd9Sstevel@tonic-gate 			srv_rec.ServiceID = sid;
28277c478bd9Sstevel@tonic-gate 
28287c478bd9Sstevel@tonic-gate 			IBCM_DUMP_SERVICE_REC(&srv_rec);
28297c478bd9Sstevel@tonic-gate 
28307c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: "
28317c478bd9Sstevel@tonic-gate 			    "ibmf_saa_write_service_record, SvcId = %llX",
28327c478bd9Sstevel@tonic-gate 			    (longlong_t)sid);
28337c478bd9Sstevel@tonic-gate 
28347c478bd9Sstevel@tonic-gate 			status = ibcm_write_service_record(saa_handle, &srv_rec,
28357c478bd9Sstevel@tonic-gate 			    IBMF_SAA_UPDATE);
28367c478bd9Sstevel@tonic-gate 			if (status != IBT_SUCCESS) {
28377c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_bind_service:"
28387c478bd9Sstevel@tonic-gate 				    " ibcm_write_service_record fails %d, "
28397c478bd9Sstevel@tonic-gate 				    "sid %llX", status, (longlong_t)sid);
28407c478bd9Sstevel@tonic-gate 
28417c478bd9Sstevel@tonic-gate 				if (sid != start_sid) {
28427c478bd9Sstevel@tonic-gate 					/*
28437c478bd9Sstevel@tonic-gate 					 * Bind failed while bind SID other than
28447c478bd9Sstevel@tonic-gate 					 * first in the sid_range.  So we need
28457c478bd9Sstevel@tonic-gate 					 * to unbind those, which are passed.
28467c478bd9Sstevel@tonic-gate 					 *
28477c478bd9Sstevel@tonic-gate 					 * Need to increment svc count to
28487c478bd9Sstevel@tonic-gate 					 * compensate for ibt_unbind_service().
28497c478bd9Sstevel@tonic-gate 					 */
28507c478bd9Sstevel@tonic-gate 					ibcm_inc_hca_svc_cnt(hcap);
28517c478bd9Sstevel@tonic-gate 					ibcm_dec_hca_acc_cnt(hcap);
28527c478bd9Sstevel@tonic-gate 
28537c478bd9Sstevel@tonic-gate 					(void) ibt_unbind_service(srv_hdl,
28547c478bd9Sstevel@tonic-gate 					    sbindp);
28557c478bd9Sstevel@tonic-gate 				} else {
28567c478bd9Sstevel@tonic-gate 					ibcm_svc_bind_t		**sbpp;
28577c478bd9Sstevel@tonic-gate 
28587c478bd9Sstevel@tonic-gate 					/*
28597c478bd9Sstevel@tonic-gate 					 * Bind failed for the first SID or the
28607c478bd9Sstevel@tonic-gate 					 * only SID in question, then no need
28617c478bd9Sstevel@tonic-gate 					 * to unbind, just free memory and
28627c478bd9Sstevel@tonic-gate 					 * return error.
28637c478bd9Sstevel@tonic-gate 					 */
28647c478bd9Sstevel@tonic-gate 					mutex_enter(&ibcm_svc_info_lock);
28657c478bd9Sstevel@tonic-gate 
28667c478bd9Sstevel@tonic-gate 					sbpp = &srv_hdl->svc_bind_list;
28677c478bd9Sstevel@tonic-gate 					sbp = *sbpp;
28687c478bd9Sstevel@tonic-gate 					while (sbp != NULL) {
28697c478bd9Sstevel@tonic-gate 						if (sbp == sbindp) {
28707c478bd9Sstevel@tonic-gate 							*sbpp = sbp->sbind_link;
28717c478bd9Sstevel@tonic-gate 							break;
28727c478bd9Sstevel@tonic-gate 						}
28737c478bd9Sstevel@tonic-gate 						sbpp = &sbp->sbind_link;
28747c478bd9Sstevel@tonic-gate 						sbp = *sbpp;
28757c478bd9Sstevel@tonic-gate 					}
28767c478bd9Sstevel@tonic-gate 					mutex_exit(&ibcm_svc_info_lock);
28777c478bd9Sstevel@tonic-gate 					ibcm_dec_hca_acc_cnt(hcap);
28787c478bd9Sstevel@tonic-gate 
28797c478bd9Sstevel@tonic-gate 					kmem_free(sbindp, sizeof (*sbindp));
28807c478bd9Sstevel@tonic-gate 				}
28817c478bd9Sstevel@tonic-gate 				return (status);
28827c478bd9Sstevel@tonic-gate 			}
28837c478bd9Sstevel@tonic-gate 		}
28847c478bd9Sstevel@tonic-gate 	}
28857c478bd9Sstevel@tonic-gate 	ibcm_inc_hca_svc_cnt(hcap);
28867c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
28877c478bd9Sstevel@tonic-gate 
28887c478bd9Sstevel@tonic-gate 	/* If this message isn't seen then ibt_bind_service failed */
28899d3d2ed0Shiremath 	IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: DONE (%p, %llX:%llX)",
28907c478bd9Sstevel@tonic-gate 	    srv_hdl, gid.gid_prefix, gid.gid_guid);
28917c478bd9Sstevel@tonic-gate 
28927c478bd9Sstevel@tonic-gate 	if (sb_hdl_p != NULL)
28937c478bd9Sstevel@tonic-gate 		*sb_hdl_p = sbindp;
28947c478bd9Sstevel@tonic-gate 
28957c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sbindp))
28967c478bd9Sstevel@tonic-gate 
28977c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
28987c478bd9Sstevel@tonic-gate }
28997c478bd9Sstevel@tonic-gate 
29007c478bd9Sstevel@tonic-gate ibt_status_t
ibt_unbind_service(ibt_srv_hdl_t srv_hdl,ibt_sbind_hdl_t sbindp)29017c478bd9Sstevel@tonic-gate ibt_unbind_service(ibt_srv_hdl_t srv_hdl, ibt_sbind_hdl_t sbindp)
29027c478bd9Sstevel@tonic-gate {
29037c478bd9Sstevel@tonic-gate 	ib_svc_id_t	sid, end_sid;
29047c478bd9Sstevel@tonic-gate 	ibt_status_t	rval;
29057c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t	*hcap;
29067c478bd9Sstevel@tonic-gate 	ibcm_svc_bind_t	*sbp, **sbpp;
29077c478bd9Sstevel@tonic-gate 
29087c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service(%p, %p)",
29097c478bd9Sstevel@tonic-gate 	    srv_hdl, sbindp);
29107c478bd9Sstevel@tonic-gate 
29117c478bd9Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
29127c478bd9Sstevel@tonic-gate 
29137c478bd9Sstevel@tonic-gate 	/* If there is a service on hca, respective hcap cannot go away */
29147c478bd9Sstevel@tonic-gate 	ASSERT(hcap != NULL);
29157c478bd9Sstevel@tonic-gate 
29167c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
29177c478bd9Sstevel@tonic-gate 
29187c478bd9Sstevel@tonic-gate 	sbpp = &srv_hdl->svc_bind_list;
29197c478bd9Sstevel@tonic-gate 	sbp = *sbpp;
29207c478bd9Sstevel@tonic-gate 	while (sbp != NULL) {
29217c478bd9Sstevel@tonic-gate 		if (sbp == sbindp) {
29227c478bd9Sstevel@tonic-gate 			*sbpp = sbp->sbind_link;
29237c478bd9Sstevel@tonic-gate 			break;
29247c478bd9Sstevel@tonic-gate 		}
29257c478bd9Sstevel@tonic-gate 		sbpp = &sbp->sbind_link;
29267c478bd9Sstevel@tonic-gate 		sbp = *sbpp;
29277c478bd9Sstevel@tonic-gate 	}
29287c478bd9Sstevel@tonic-gate 	sid = srv_hdl->svc_id;
29297c478bd9Sstevel@tonic-gate 	end_sid = srv_hdl->svc_id + srv_hdl->svc_num_sids - 1;
29307c478bd9Sstevel@tonic-gate 	if (sbp != NULL)
29317c478bd9Sstevel@tonic-gate 		while (sbp->sbind_rewrite_state == IBCM_REWRITE_BUSY)
29327c478bd9Sstevel@tonic-gate 			cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
29337c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
29347c478bd9Sstevel@tonic-gate 
29357c478bd9Sstevel@tonic-gate 	if (sbp == NULL) {
29367c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29377c478bd9Sstevel@tonic-gate 		    "service binding not found: srv_hdl %p, srv_bind %p",
29387c478bd9Sstevel@tonic-gate 		    srv_hdl, sbindp);
29397c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
29407c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
29417c478bd9Sstevel@tonic-gate 	}
29427c478bd9Sstevel@tonic-gate 
29437c478bd9Sstevel@tonic-gate 	if (sbindp->sbind_pkey != 0) {	/* Are there service records? */
29447c478bd9Sstevel@tonic-gate 		ibtl_cm_hca_port_t	port;
29457c478bd9Sstevel@tonic-gate 		sa_service_record_t	srv_rec;
29467c478bd9Sstevel@tonic-gate 		ibmf_saa_handle_t	saa_handle;
29477c478bd9Sstevel@tonic-gate 		ibt_status_t		status;
29487c478bd9Sstevel@tonic-gate 
29497c478bd9Sstevel@tonic-gate 		/* get the default SGID of the port */
29507c478bd9Sstevel@tonic-gate 		if ((status = ibtl_cm_get_hca_port(sbindp->sbind_gid, 0, &port))
29517c478bd9Sstevel@tonic-gate 		    != IBT_SUCCESS) {
29527c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29537c478bd9Sstevel@tonic-gate 			    "ibtl_cm_get_hca_port failed: %d", status);
29547c478bd9Sstevel@tonic-gate 			/* we're done, but there may be stale service records */
29557c478bd9Sstevel@tonic-gate 			goto done;
29567c478bd9Sstevel@tonic-gate 		}
29577c478bd9Sstevel@tonic-gate 
29587c478bd9Sstevel@tonic-gate 		saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
29597c478bd9Sstevel@tonic-gate 		if (saa_handle == NULL) {
29607c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29617c478bd9Sstevel@tonic-gate 			    "saa_handle is NULL");
29627c478bd9Sstevel@tonic-gate 			/* we're done, but there may be stale service records */
29637c478bd9Sstevel@tonic-gate 			goto done;
29647c478bd9Sstevel@tonic-gate 		}
29657c478bd9Sstevel@tonic-gate 
29667c478bd9Sstevel@tonic-gate 		/* Fill in fields of srv_rec */
29677c478bd9Sstevel@tonic-gate 		bzero(&srv_rec, sizeof (srv_rec));
29687c478bd9Sstevel@tonic-gate 
29697c478bd9Sstevel@tonic-gate 		srv_rec.ServiceP_Key = sbindp->sbind_pkey;
29707c478bd9Sstevel@tonic-gate 		srv_rec.ServiceKey_hi = sbindp->sbind_key[0];
29717c478bd9Sstevel@tonic-gate 		srv_rec.ServiceKey_lo = sbindp->sbind_key[1];
29727c478bd9Sstevel@tonic-gate 		srv_rec.ServiceGID = sbindp->sbind_gid;
29737c478bd9Sstevel@tonic-gate 		(void) strcpy((char *)srv_rec.ServiceName, sbindp->sbind_name);
29747c478bd9Sstevel@tonic-gate 
29757c478bd9Sstevel@tonic-gate 		while (sid <= end_sid) {
29767c478bd9Sstevel@tonic-gate 
29777c478bd9Sstevel@tonic-gate 			srv_rec.ServiceID = sid;
29787c478bd9Sstevel@tonic-gate 			IBCM_DUMP_SERVICE_REC(&srv_rec);
29797c478bd9Sstevel@tonic-gate 
29807c478bd9Sstevel@tonic-gate 			rval = ibcm_write_service_record(saa_handle, &srv_rec,
29817c478bd9Sstevel@tonic-gate 			    IBMF_SAA_DELETE);
29827c478bd9Sstevel@tonic-gate 
29837c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibt_unbind_service: "
29847c478bd9Sstevel@tonic-gate 			    "ibcm_write_service_record rval = %d, SID %llx",
29857c478bd9Sstevel@tonic-gate 			    rval, sid);
29867c478bd9Sstevel@tonic-gate 			if (rval != IBT_SUCCESS) {
29877c478bd9Sstevel@tonic-gate 				/* this is not considered a reason to fail */
29887c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29897c478bd9Sstevel@tonic-gate 				    "ibcm_write_service_record fails %d, "
29907c478bd9Sstevel@tonic-gate 				    "sid %llx", rval, sid);
29917c478bd9Sstevel@tonic-gate 			}
29927c478bd9Sstevel@tonic-gate 			sid++;
29937c478bd9Sstevel@tonic-gate 		}
29947c478bd9Sstevel@tonic-gate 	}
29957c478bd9Sstevel@tonic-gate done:
29967c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_svc_cnt(hcap);
29977c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
29987c478bd9Sstevel@tonic-gate 	kmem_free(sbindp, sizeof (*sbindp));
29997c478bd9Sstevel@tonic-gate 
30007c478bd9Sstevel@tonic-gate 	/* If this message isn't seen then ibt_unbind_service failed */
30017c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: done !!");
30027c478bd9Sstevel@tonic-gate 
30037c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
30047c478bd9Sstevel@tonic-gate }
30057c478bd9Sstevel@tonic-gate 
30067c478bd9Sstevel@tonic-gate /*
30077c478bd9Sstevel@tonic-gate  * Simply pull off each binding from the list and unbind it.
30087c478bd9Sstevel@tonic-gate  * If any of the unbind calls fail, we fail.
30097c478bd9Sstevel@tonic-gate  */
30107c478bd9Sstevel@tonic-gate ibt_status_t
ibt_unbind_all_services(ibt_srv_hdl_t srv_hdl)30117c478bd9Sstevel@tonic-gate ibt_unbind_all_services(ibt_srv_hdl_t srv_hdl)
30127c478bd9Sstevel@tonic-gate {
30137c478bd9Sstevel@tonic-gate 	ibt_status_t	status;
30147c478bd9Sstevel@tonic-gate 	ibcm_svc_bind_t	*sbp;
30157c478bd9Sstevel@tonic-gate 
30167c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
30177c478bd9Sstevel@tonic-gate 	sbp = NULL;
30187c478bd9Sstevel@tonic-gate 
30197c478bd9Sstevel@tonic-gate 	/* this compare keeps the loop from being infinite */
30207c478bd9Sstevel@tonic-gate 	while (sbp != srv_hdl->svc_bind_list) {
30217c478bd9Sstevel@tonic-gate 		sbp = srv_hdl->svc_bind_list;
30227c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
30237c478bd9Sstevel@tonic-gate 		status = ibt_unbind_service(srv_hdl, sbp);
30247c478bd9Sstevel@tonic-gate 		if (status != IBT_SUCCESS)
30257c478bd9Sstevel@tonic-gate 			return (status);
30267c478bd9Sstevel@tonic-gate 		mutex_enter(&ibcm_svc_info_lock);
30277c478bd9Sstevel@tonic-gate 		if (srv_hdl->svc_bind_list == NULL)
30287c478bd9Sstevel@tonic-gate 			break;
30297c478bd9Sstevel@tonic-gate 	}
30307c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
30317c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
30327c478bd9Sstevel@tonic-gate }
30337c478bd9Sstevel@tonic-gate 
30347c478bd9Sstevel@tonic-gate /*
30357c478bd9Sstevel@tonic-gate  * ibt_deregister_service()
30367c478bd9Sstevel@tonic-gate  *	Deregister a service with the IBCM
30377c478bd9Sstevel@tonic-gate  *
30387c478bd9Sstevel@tonic-gate  * INPUTS:
30397c478bd9Sstevel@tonic-gate  *	ibt_hdl		The IBT client handle returned to the client
30407c478bd9Sstevel@tonic-gate  *			on an ibt_attach() call.
30417c478bd9Sstevel@tonic-gate  *
30427c478bd9Sstevel@tonic-gate  *	srv_hdl		The address of a service identification handle, used
30437c478bd9Sstevel@tonic-gate  *			to de-register a service.
30447c478bd9Sstevel@tonic-gate  * RETURN VALUES:
30457c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS	on success (or respective failure on error)
30467c478bd9Sstevel@tonic-gate  */
30477c478bd9Sstevel@tonic-gate ibt_status_t
ibt_deregister_service(ibt_clnt_hdl_t ibt_hdl,ibt_srv_hdl_t srv_hdl)30487c478bd9Sstevel@tonic-gate ibt_deregister_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_hdl_t srv_hdl)
30497c478bd9Sstevel@tonic-gate {
30507c478bd9Sstevel@tonic-gate 	ibcm_svc_info_t		*svcp;
30517c478bd9Sstevel@tonic-gate 	ibcm_svc_lookup_t	svc;
30527c478bd9Sstevel@tonic-gate 
3053d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(%p (%s), %p)",
3054d3a82192SShantkumar Hiremath 	    ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv_hdl);
30557c478bd9Sstevel@tonic-gate 
30567c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
30577c478bd9Sstevel@tonic-gate 
30587c478bd9Sstevel@tonic-gate 	if (srv_hdl->svc_bind_list != NULL) {
30597c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service:"
30607c478bd9Sstevel@tonic-gate 		    " srv_hdl %p still has bindings", srv_hdl);
30617c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
30627c478bd9Sstevel@tonic-gate 		return (IBT_CM_SERVICE_BUSY);
30637c478bd9Sstevel@tonic-gate 	}
30647c478bd9Sstevel@tonic-gate 	svc.sid = srv_hdl->svc_id;
30657c478bd9Sstevel@tonic-gate 	svc.num_sids = 1;
306624b28d04Shiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_deregister_service: SID 0x%llX, numsids %d",
306724b28d04Shiremath 	    srv_hdl->svc_id, srv_hdl->svc_num_sids);
306824b28d04Shiremath 
30697c478bd9Sstevel@tonic-gate #ifdef __lock_lint
30707c478bd9Sstevel@tonic-gate 	ibcm_svc_compare(NULL, NULL);
30717c478bd9Sstevel@tonic-gate #endif
30727c478bd9Sstevel@tonic-gate 	svcp = avl_find(&ibcm_svc_avl_tree, &svc, NULL);
30737c478bd9Sstevel@tonic-gate 	if (svcp != srv_hdl) {
30747c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
30757c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(): "
30767c478bd9Sstevel@tonic-gate 		    "srv_hdl %p not found", srv_hdl);
30777c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
30787c478bd9Sstevel@tonic-gate 	}
30797c478bd9Sstevel@tonic-gate 	avl_remove(&ibcm_svc_avl_tree, svcp);
30807c478bd9Sstevel@tonic-gate 
30817c478bd9Sstevel@tonic-gate 	/* wait for active REQ/SREQ handling to be done */
30827c478bd9Sstevel@tonic-gate 	svcp->svc_to_delete = 1;
30837c478bd9Sstevel@tonic-gate 	while (svcp->svc_ref_cnt != 0)
30847c478bd9Sstevel@tonic-gate 		cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
30857c478bd9Sstevel@tonic-gate 
30867c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
30877c478bd9Sstevel@tonic-gate 
30887c478bd9Sstevel@tonic-gate 	if ((srv_hdl->svc_id & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL)
30897c478bd9Sstevel@tonic-gate 		ibcm_free_local_sids(srv_hdl->svc_id, srv_hdl->svc_num_sids);
30907c478bd9Sstevel@tonic-gate 
30917c478bd9Sstevel@tonic-gate 	ibtl_cm_change_service_cnt(ibt_hdl, -srv_hdl->svc_num_sids);
30927c478bd9Sstevel@tonic-gate 	kmem_free(srv_hdl, sizeof (*srv_hdl));
30937c478bd9Sstevel@tonic-gate 
30947c478bd9Sstevel@tonic-gate 	/* If this message isn't seen then ibt_deregister_service failed */
30957c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service: done !!");
30967c478bd9Sstevel@tonic-gate 
30977c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
30987c478bd9Sstevel@tonic-gate }
30997c478bd9Sstevel@tonic-gate 
31007c478bd9Sstevel@tonic-gate ibcm_status_t
ibcm_ar_init(void)31017c478bd9Sstevel@tonic-gate ibcm_ar_init(void)
31027c478bd9Sstevel@tonic-gate {
31037c478bd9Sstevel@tonic-gate 	ib_svc_id_t	sid = IBCM_DAPL_ATS_SID;
31047c478bd9Sstevel@tonic-gate 	ibcm_svc_info_t *tmp_svcp;
31057c478bd9Sstevel@tonic-gate 
31067c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_ar_init()");
31077c478bd9Sstevel@tonic-gate 
31087c478bd9Sstevel@tonic-gate 	/* remove this special SID from the pool of available SIDs */
31097c478bd9Sstevel@tonic-gate 	if ((tmp_svcp = ibcm_create_svc_entry(sid, 1)) == NULL) {
3110d3a82192SShantkumar Hiremath 		IBTF_DPRINTF_L3(cmlog, "ibcm_ar_init: "
31117c478bd9Sstevel@tonic-gate 		    "DAPL ATS SID 0x%llx already registered", (longlong_t)sid);
31127c478bd9Sstevel@tonic-gate 		return (IBCM_FAILURE);
31137c478bd9Sstevel@tonic-gate 	}
31147c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
31157c478bd9Sstevel@tonic-gate 	ibcm_ar_svcinfop = tmp_svcp;
31167c478bd9Sstevel@tonic-gate 	ibcm_ar_list = NULL;	/* no address records registered yet */
31177c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
31187c478bd9Sstevel@tonic-gate 	return (IBCM_SUCCESS);
31197c478bd9Sstevel@tonic-gate }
31207c478bd9Sstevel@tonic-gate 
31217c478bd9Sstevel@tonic-gate ibcm_status_t
ibcm_ar_fini(void)31227c478bd9Sstevel@tonic-gate ibcm_ar_fini(void)
31237c478bd9Sstevel@tonic-gate {
31247c478bd9Sstevel@tonic-gate 	ibcm_ar_t	*ar_list;
31257c478bd9Sstevel@tonic-gate 	ibcm_svc_info_t	*tmp_svcp;
31267c478bd9Sstevel@tonic-gate 
31277c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
31287c478bd9Sstevel@tonic-gate 	ar_list = ibcm_ar_list;
31297c478bd9Sstevel@tonic-gate 
31307c478bd9Sstevel@tonic-gate 	if (ar_list == NULL &&
31317c478bd9Sstevel@tonic-gate 	    avl_numnodes(&ibcm_svc_avl_tree) == 1 &&
31327c478bd9Sstevel@tonic-gate 	    avl_first(&ibcm_svc_avl_tree) == ibcm_ar_svcinfop) {
31337c478bd9Sstevel@tonic-gate 		avl_remove(&ibcm_svc_avl_tree, ibcm_ar_svcinfop);
31347c478bd9Sstevel@tonic-gate 		tmp_svcp = ibcm_ar_svcinfop;
31357c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
31367c478bd9Sstevel@tonic-gate 		kmem_free(tmp_svcp, sizeof (*ibcm_ar_svcinfop));
31377c478bd9Sstevel@tonic-gate 		return (IBCM_SUCCESS);
31387c478bd9Sstevel@tonic-gate 	}
31397c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
31407c478bd9Sstevel@tonic-gate 	return (IBCM_FAILURE);
31417c478bd9Sstevel@tonic-gate }
31427c478bd9Sstevel@tonic-gate 
31437c478bd9Sstevel@tonic-gate 
31447c478bd9Sstevel@tonic-gate /*
31457c478bd9Sstevel@tonic-gate  * Return to the caller:
31467c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS		Found a perfect match.
31477c478bd9Sstevel@tonic-gate  *				*arpp is set to the record.
31487c478bd9Sstevel@tonic-gate  *	IBT_INCONSISTENT_AR	Found a record that's inconsistent.
31497c478bd9Sstevel@tonic-gate  *	IBT_AR_NOT_REGISTERED	Found no record with same GID/pkey and
31507c478bd9Sstevel@tonic-gate  *				found no record with same data.
31517c478bd9Sstevel@tonic-gate  */
31527c478bd9Sstevel@tonic-gate static ibt_status_t
ibcm_search_ar(ibt_ar_t * arp,ibcm_ar_t ** arpp)31537c478bd9Sstevel@tonic-gate ibcm_search_ar(ibt_ar_t *arp, ibcm_ar_t **arpp)
31547c478bd9Sstevel@tonic-gate {
31557c478bd9Sstevel@tonic-gate 	ibcm_ar_t	*tmp;
31567c478bd9Sstevel@tonic-gate 	int		i;
31577c478bd9Sstevel@tonic-gate 
31587c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
31597c478bd9Sstevel@tonic-gate 	tmp = ibcm_ar_list;
31607c478bd9Sstevel@tonic-gate 	while (tmp != NULL) {
31617c478bd9Sstevel@tonic-gate 		if (tmp->ar.ar_gid.gid_prefix == arp->ar_gid.gid_prefix &&
31627c478bd9Sstevel@tonic-gate 		    tmp->ar.ar_gid.gid_guid == arp->ar_gid.gid_guid &&
31637c478bd9Sstevel@tonic-gate 		    tmp->ar.ar_pkey == arp->ar_pkey) {
31647c478bd9Sstevel@tonic-gate 			for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++)
31657c478bd9Sstevel@tonic-gate 				if (tmp->ar.ar_data[i] != arp->ar_data[i])
31667c478bd9Sstevel@tonic-gate 					return (IBT_INCONSISTENT_AR);
31677c478bd9Sstevel@tonic-gate 			*arpp = tmp;
31687c478bd9Sstevel@tonic-gate 			return (IBT_SUCCESS);
31697c478bd9Sstevel@tonic-gate 		} else {
31707c478bd9Sstevel@tonic-gate 			/* if all the data bytes match, we have inconsistency */
31717c478bd9Sstevel@tonic-gate 			for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++)
31727c478bd9Sstevel@tonic-gate 				if (tmp->ar.ar_data[i] != arp->ar_data[i])
31737c478bd9Sstevel@tonic-gate 					break;
31747c478bd9Sstevel@tonic-gate 			if (i == IBCM_DAPL_ATS_NBYTES)
31757c478bd9Sstevel@tonic-gate 				return (IBT_INCONSISTENT_AR);
31767c478bd9Sstevel@tonic-gate 			/* try next address record */
31777c478bd9Sstevel@tonic-gate 		}
31787c478bd9Sstevel@tonic-gate 		tmp = tmp->ar_link;
31797c478bd9Sstevel@tonic-gate 	}
31807c478bd9Sstevel@tonic-gate 	return (IBT_AR_NOT_REGISTERED);
31817c478bd9Sstevel@tonic-gate }
31827c478bd9Sstevel@tonic-gate 
31837c478bd9Sstevel@tonic-gate ibt_status_t
ibt_register_ar(ibt_clnt_hdl_t ibt_hdl,ibt_ar_t * arp)31847c478bd9Sstevel@tonic-gate ibt_register_ar(ibt_clnt_hdl_t ibt_hdl, ibt_ar_t *arp)
31857c478bd9Sstevel@tonic-gate {
31867c478bd9Sstevel@tonic-gate 	ibcm_ar_t		*found;
31877c478bd9Sstevel@tonic-gate 	ibcm_ar_t		*tmp;
31887c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
31897c478bd9Sstevel@tonic-gate 	ibt_status_t		s1, s2;
31907c478bd9Sstevel@tonic-gate 	char			*s;
31917c478bd9Sstevel@tonic-gate 	ibcm_ar_ref_t		*hdlp;
31927c478bd9Sstevel@tonic-gate 	ibcm_ar_t		*new;
31937c478bd9Sstevel@tonic-gate 	ibcm_ar_t		**linkp;
31947c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	cm_port;
31957c478bd9Sstevel@tonic-gate 	uint16_t		pkey_ix;
31967c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
31977c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
31987c478bd9Sstevel@tonic-gate 	sa_service_record_t	*srv_recp;
31997c478bd9Sstevel@tonic-gate 	uint64_t		gid_ored;
32007c478bd9Sstevel@tonic-gate 
3201d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_register_ar: PKey 0x%X GID %llX:%llX",
32027c478bd9Sstevel@tonic-gate 	    arp->ar_pkey, (longlong_t)arp->ar_gid.gid_prefix,
32037c478bd9Sstevel@tonic-gate 	    (longlong_t)arp->ar_gid.gid_guid);
32047c478bd9Sstevel@tonic-gate 
32057c478bd9Sstevel@tonic-gate 	/*
32067c478bd9Sstevel@tonic-gate 	 * If P_Key is 0, but GID is not, this query is invalid.
32077c478bd9Sstevel@tonic-gate 	 * If GID is 0, but P_Key is not, this query is invalid.
32087c478bd9Sstevel@tonic-gate 	 */
32097c478bd9Sstevel@tonic-gate 	gid_ored = arp->ar_gid.gid_guid | arp->ar_gid.gid_prefix;
32107c478bd9Sstevel@tonic-gate 	if ((arp->ar_pkey == 0 && gid_ored != 0ULL) ||
32117c478bd9Sstevel@tonic-gate 	    (arp->ar_pkey != 0 && gid_ored == 0ULL)) {
32127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
32137c478bd9Sstevel@tonic-gate 		    "GID/P_Key is not valid");
32147c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
32157c478bd9Sstevel@tonic-gate 	}
32167c478bd9Sstevel@tonic-gate 
32177c478bd9Sstevel@tonic-gate 	/* assume success, so these might be needed */
32187c478bd9Sstevel@tonic-gate 	hdlp = kmem_alloc(sizeof (*hdlp), KM_SLEEP);
321910243922Srm78299 	new = kmem_zalloc(sizeof (*new), KM_SLEEP);
32207c478bd9Sstevel@tonic-gate 
32217c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
32227c478bd9Sstevel@tonic-gate 	/* search for existing GID/pkey (there can be at most 1) */
32237c478bd9Sstevel@tonic-gate 	status = ibcm_search_ar(arp, &found);
32247c478bd9Sstevel@tonic-gate 	if (status == IBT_INCONSISTENT_AR) {
32257c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
32267c478bd9Sstevel@tonic-gate 		kmem_free(new, sizeof (*new));
32277c478bd9Sstevel@tonic-gate 		kmem_free(hdlp, sizeof (*hdlp));
32287c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
32297c478bd9Sstevel@tonic-gate 		    "address record is inconsistent with a known one");
32307c478bd9Sstevel@tonic-gate 		return (IBT_INCONSISTENT_AR);
32317c478bd9Sstevel@tonic-gate 	} else if (status == IBT_SUCCESS) {
32327c478bd9Sstevel@tonic-gate 		if (found->ar_flags == IBCM_AR_INITING) {
32337c478bd9Sstevel@tonic-gate 			found->ar_waiters++;
32347c478bd9Sstevel@tonic-gate 			cv_wait(&found->ar_cv, &ibcm_svc_info_lock);
32357c478bd9Sstevel@tonic-gate 			found->ar_waiters--;
32367c478bd9Sstevel@tonic-gate 		}
32377c478bd9Sstevel@tonic-gate 		if (found->ar_flags == IBCM_AR_FAILED) {
32387c478bd9Sstevel@tonic-gate 			if (found->ar_waiters == 0) {
32397c478bd9Sstevel@tonic-gate 				cv_destroy(&found->ar_cv);
32407c478bd9Sstevel@tonic-gate 				kmem_free(found, sizeof (*found));
32417c478bd9Sstevel@tonic-gate 			}
32427c478bd9Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
32437c478bd9Sstevel@tonic-gate 			kmem_free(new, sizeof (*new));
32447c478bd9Sstevel@tonic-gate 			kmem_free(hdlp, sizeof (*hdlp));
32457c478bd9Sstevel@tonic-gate 			return (ibt_get_module_failure(IBT_FAILURE_IBCM, 0));
32467c478bd9Sstevel@tonic-gate 		}
32477c478bd9Sstevel@tonic-gate 		hdlp->ar_ibt_hdl = ibt_hdl;
32487c478bd9Sstevel@tonic-gate 		hdlp->ar_ref_link = found->ar_ibt_hdl_list;
32497c478bd9Sstevel@tonic-gate 		found->ar_ibt_hdl_list = hdlp;
32507c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
32517c478bd9Sstevel@tonic-gate 		kmem_free(new, sizeof (*new));
32527c478bd9Sstevel@tonic-gate 		ibtl_cm_change_service_cnt(ibt_hdl, 1);
32537c478bd9Sstevel@tonic-gate 		return (IBT_SUCCESS);
32547c478bd9Sstevel@tonic-gate 	} else {
32557c478bd9Sstevel@tonic-gate 		ASSERT(status == IBT_AR_NOT_REGISTERED);
32567c478bd9Sstevel@tonic-gate 	}
32577c478bd9Sstevel@tonic-gate 	hdlp->ar_ref_link = NULL;
32587c478bd9Sstevel@tonic-gate 	hdlp->ar_ibt_hdl = ibt_hdl;
32597c478bd9Sstevel@tonic-gate 	new->ar_ibt_hdl_list = hdlp;
32607c478bd9Sstevel@tonic-gate 	new->ar = *arp;
32617c478bd9Sstevel@tonic-gate 	new->ar_flags = IBCM_AR_INITING;
32627c478bd9Sstevel@tonic-gate 	new->ar_waiters = 0;
32637c478bd9Sstevel@tonic-gate 	cv_init(&new->ar_cv, NULL, CV_DEFAULT, NULL);
32647c478bd9Sstevel@tonic-gate 	new->ar_link = ibcm_ar_list;
32657c478bd9Sstevel@tonic-gate 	ibcm_ar_list = new;
32667c478bd9Sstevel@tonic-gate 
32677c478bd9Sstevel@tonic-gate 	/* verify GID/pkey is valid for a local port, etc. */
32687c478bd9Sstevel@tonic-gate 	hcap = NULL;
32697c478bd9Sstevel@tonic-gate 	if ((s1 = ibtl_cm_get_hca_port(arp->ar_gid, 0, &cm_port))
32707c478bd9Sstevel@tonic-gate 	    != IBT_SUCCESS ||
32717c478bd9Sstevel@tonic-gate 	    (s2 = ibt_pkey2index_byguid(cm_port.hp_hca_guid, cm_port.hp_port,
32727c478bd9Sstevel@tonic-gate 	    arp->ar_pkey, &pkey_ix)) != IBT_SUCCESS ||
32737c478bd9Sstevel@tonic-gate 	    (hcap = ibcm_find_hca_entry(cm_port.hp_hca_guid)) == NULL) {
32747c478bd9Sstevel@tonic-gate 		cv_destroy(&new->ar_cv);
32757c478bd9Sstevel@tonic-gate 		ibcm_ar_list = new->ar_link;
32767c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
32777c478bd9Sstevel@tonic-gate 		kmem_free(new, sizeof (*new));
32787c478bd9Sstevel@tonic-gate 		kmem_free(hdlp, sizeof (*hdlp));
32797c478bd9Sstevel@tonic-gate 		status = IBT_INVALID_PARAM;
32807c478bd9Sstevel@tonic-gate 		if (s1 == IBT_HCA_PORT_NOT_ACTIVE) {
32817c478bd9Sstevel@tonic-gate 			s = "PORT DOWN";
32827c478bd9Sstevel@tonic-gate 			status = IBT_HCA_PORT_NOT_ACTIVE;
32837c478bd9Sstevel@tonic-gate 		} else if (s1 != IBT_SUCCESS)
32847c478bd9Sstevel@tonic-gate 			s = "GID not found";
32857c478bd9Sstevel@tonic-gate 		else if (s2 != IBT_SUCCESS)
32867c478bd9Sstevel@tonic-gate 			s = "PKEY not found";
32877c478bd9Sstevel@tonic-gate 		else
32887c478bd9Sstevel@tonic-gate 			s = "CM could not find its HCA entry";
32897c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: %s, status = %d",
32907c478bd9Sstevel@tonic-gate 		    s, status);
32917c478bd9Sstevel@tonic-gate 		return (status);
32927c478bd9Sstevel@tonic-gate 	}
32937c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
32947c478bd9Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, cm_port.hp_port);
32957c478bd9Sstevel@tonic-gate 
32967c478bd9Sstevel@tonic-gate 	/* create service record */
32977c478bd9Sstevel@tonic-gate 	srv_recp = kmem_zalloc(sizeof (*srv_recp), KM_SLEEP);
32987c478bd9Sstevel@tonic-gate 	srv_recp->ServiceLease = 0xFFFFFFFF;	/* infinite */
32997c478bd9Sstevel@tonic-gate 	srv_recp->ServiceP_Key = arp->ar_pkey;
33007c478bd9Sstevel@tonic-gate 	srv_recp->ServiceKey_hi = 0xDA410000ULL;	/* DAPL */
33017c478bd9Sstevel@tonic-gate 	srv_recp->ServiceKey_lo = 0xA7500000ULL;	/* ATS */
33027c478bd9Sstevel@tonic-gate 	(void) strcpy((char *)srv_recp->ServiceName, IBCM_DAPL_ATS_NAME);
33037c478bd9Sstevel@tonic-gate 	srv_recp->ServiceGID = arp->ar_gid;
33047c478bd9Sstevel@tonic-gate 	bcopy(arp->ar_data, srv_recp->ServiceData, IBCM_DAPL_ATS_NBYTES);
33057c478bd9Sstevel@tonic-gate 	srv_recp->ServiceID = IBCM_DAPL_ATS_SID;
33067c478bd9Sstevel@tonic-gate 
33077c478bd9Sstevel@tonic-gate 	/* insert service record into the SA */
33087c478bd9Sstevel@tonic-gate 
33097c478bd9Sstevel@tonic-gate 	IBCM_DUMP_SERVICE_REC(srv_recp);
33107c478bd9Sstevel@tonic-gate 
33117c478bd9Sstevel@tonic-gate 	if (saa_handle != NULL)
33127c478bd9Sstevel@tonic-gate 		status = ibcm_write_service_record(saa_handle, srv_recp,
33137c478bd9Sstevel@tonic-gate 		    IBMF_SAA_UPDATE);
33147c478bd9Sstevel@tonic-gate 	else
33157c478bd9Sstevel@tonic-gate 		status = IBT_HCA_PORT_NOT_ACTIVE;
33167c478bd9Sstevel@tonic-gate 
33177c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
33187c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: sa access fails %d, "
33197c478bd9Sstevel@tonic-gate 		    "sid %llX", status, (longlong_t)srv_recp->ServiceID);
33207c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: FAILED for gid "
33217c478bd9Sstevel@tonic-gate 		    "%llX:%llX pkey 0x%X", (longlong_t)arp->ar_gid.gid_prefix,
33227c478bd9Sstevel@tonic-gate 		    (longlong_t)arp->ar_gid.gid_guid, arp->ar_pkey);
33237c478bd9Sstevel@tonic-gate 
33247c478bd9Sstevel@tonic-gate 		kmem_free(srv_recp, sizeof (*srv_recp));
33257c478bd9Sstevel@tonic-gate 		kmem_free(hdlp, sizeof (*hdlp));
33267c478bd9Sstevel@tonic-gate 
33277c478bd9Sstevel@tonic-gate 		mutex_enter(&ibcm_svc_info_lock);
33287c478bd9Sstevel@tonic-gate 		linkp = &ibcm_ar_list;
33297c478bd9Sstevel@tonic-gate 		tmp = *linkp;
33307c478bd9Sstevel@tonic-gate 		while (tmp != NULL) {
33317c478bd9Sstevel@tonic-gate 			if (tmp == new) {
33327c478bd9Sstevel@tonic-gate 				*linkp = new->ar_link;
33337c478bd9Sstevel@tonic-gate 				break;
33347c478bd9Sstevel@tonic-gate 			}
33357c478bd9Sstevel@tonic-gate 			linkp = &tmp->ar_link;
33367c478bd9Sstevel@tonic-gate 			tmp = *linkp;
33377c478bd9Sstevel@tonic-gate 		}
33387c478bd9Sstevel@tonic-gate 		if (new->ar_waiters > 0) {
33397c478bd9Sstevel@tonic-gate 			new->ar_flags = IBCM_AR_FAILED;
33407c478bd9Sstevel@tonic-gate 			cv_broadcast(&new->ar_cv);
33417c478bd9Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
33427c478bd9Sstevel@tonic-gate 		} else {
33437c478bd9Sstevel@tonic-gate 			cv_destroy(&new->ar_cv);
33447c478bd9Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
33457c478bd9Sstevel@tonic-gate 			kmem_free(new, sizeof (*new));
33467c478bd9Sstevel@tonic-gate 		}
33477c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
33487c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
33497c478bd9Sstevel@tonic-gate 		    "IBMF_SAA failed to write address record");
33507c478bd9Sstevel@tonic-gate 	} else {					/* SUCCESS */
33517c478bd9Sstevel@tonic-gate 		uint8_t		*b;
33527c478bd9Sstevel@tonic-gate 
3353d3a82192SShantkumar Hiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_register_ar: SUCCESS for gid "
33547c478bd9Sstevel@tonic-gate 		    "%llx:%llx pkey %x", (longlong_t)arp->ar_gid.gid_prefix,
33557c478bd9Sstevel@tonic-gate 		    (longlong_t)arp->ar_gid.gid_guid, arp->ar_pkey);
33567c478bd9Sstevel@tonic-gate 		b = arp->ar_data;
33577c478bd9Sstevel@tonic-gate 
3358d3a82192SShantkumar Hiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_register_ar:"
33597c478bd9Sstevel@tonic-gate 		    " data %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
33607c478bd9Sstevel@tonic-gate 		    b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9],
33617c478bd9Sstevel@tonic-gate 		    b[10], b[11], b[12], b[13], b[14], b[15]);
33627c478bd9Sstevel@tonic-gate 		mutex_enter(&ibcm_svc_info_lock);
33637c478bd9Sstevel@tonic-gate 		new->ar_srv_recp = srv_recp;
33647c478bd9Sstevel@tonic-gate 		new->ar_saa_handle = saa_handle;
33657c478bd9Sstevel@tonic-gate 		new->ar_port = cm_port.hp_port;
33667c478bd9Sstevel@tonic-gate 		new->ar_hcap = hcap;
33677c478bd9Sstevel@tonic-gate 		new->ar_flags = IBCM_AR_SUCCESS;
33687c478bd9Sstevel@tonic-gate 		if (new->ar_waiters > 0)
33697c478bd9Sstevel@tonic-gate 			cv_broadcast(&new->ar_cv);
33707c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
33717c478bd9Sstevel@tonic-gate 		ibtl_cm_change_service_cnt(ibt_hdl, 1);
33727c478bd9Sstevel@tonic-gate 		/* do not call ibcm_dec_hca_acc_cnt(hcap) until deregister */
33737c478bd9Sstevel@tonic-gate 	}
33747c478bd9Sstevel@tonic-gate 	return (status);
33757c478bd9Sstevel@tonic-gate }
33767c478bd9Sstevel@tonic-gate 
33777c478bd9Sstevel@tonic-gate ibt_status_t
ibt_deregister_ar(ibt_clnt_hdl_t ibt_hdl,ibt_ar_t * arp)33787c478bd9Sstevel@tonic-gate ibt_deregister_ar(ibt_clnt_hdl_t ibt_hdl, ibt_ar_t *arp)
33797c478bd9Sstevel@tonic-gate {
33807c478bd9Sstevel@tonic-gate 	ibcm_ar_t		*found;
33817c478bd9Sstevel@tonic-gate 	ibcm_ar_t		*tmp;
33827c478bd9Sstevel@tonic-gate 	ibcm_ar_t		**linkp;
33837c478bd9Sstevel@tonic-gate 	ibcm_ar_ref_t		*hdlp;
33847c478bd9Sstevel@tonic-gate 	ibcm_ar_ref_t		**hdlpp;
33857c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
33867c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
33877c478bd9Sstevel@tonic-gate 	sa_service_record_t	*srv_recp;
33887c478bd9Sstevel@tonic-gate 	uint64_t		gid_ored;
33897c478bd9Sstevel@tonic-gate 
3390d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_deregister_ar: pkey %x", arp->ar_pkey);
3391d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_deregister_ar: gid %llx:%llx",
33927c478bd9Sstevel@tonic-gate 	    (longlong_t)arp->ar_gid.gid_prefix,
33937c478bd9Sstevel@tonic-gate 	    (longlong_t)arp->ar_gid.gid_guid);
33947c478bd9Sstevel@tonic-gate 
33957c478bd9Sstevel@tonic-gate 	/*
33967c478bd9Sstevel@tonic-gate 	 * If P_Key is 0, but GID is not, this query is invalid.
33977c478bd9Sstevel@tonic-gate 	 * If GID is 0, but P_Key is not, this query is invalid.
33987c478bd9Sstevel@tonic-gate 	 */
33997c478bd9Sstevel@tonic-gate 	gid_ored = arp->ar_gid.gid_guid | arp->ar_gid.gid_prefix;
34007c478bd9Sstevel@tonic-gate 	if ((arp->ar_pkey == 0 && gid_ored != 0ULL) ||
34017c478bd9Sstevel@tonic-gate 	    (arp->ar_pkey != 0 && gid_ored == 0ULL)) {
34027c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34037c478bd9Sstevel@tonic-gate 		    "GID/P_Key is not valid");
34047c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
34057c478bd9Sstevel@tonic-gate 	}
34067c478bd9Sstevel@tonic-gate 
34077c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
34087c478bd9Sstevel@tonic-gate 	/* search for existing GID/pkey (there can be at most 1) */
34097c478bd9Sstevel@tonic-gate 	status = ibcm_search_ar(arp, &found);
34107c478bd9Sstevel@tonic-gate 	if (status == IBT_INCONSISTENT_AR || status == IBT_AR_NOT_REGISTERED) {
34117c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
34127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34137c478bd9Sstevel@tonic-gate 		    "address record not found");
34147c478bd9Sstevel@tonic-gate 		return (IBT_AR_NOT_REGISTERED);
34157c478bd9Sstevel@tonic-gate 	}
34167c478bd9Sstevel@tonic-gate 	ASSERT(status == IBT_SUCCESS);
34177c478bd9Sstevel@tonic-gate 
34187c478bd9Sstevel@tonic-gate 	hdlpp = &found->ar_ibt_hdl_list;
34197c478bd9Sstevel@tonic-gate 	hdlp = *hdlpp;
34207c478bd9Sstevel@tonic-gate 	while (hdlp != NULL) {
34217c478bd9Sstevel@tonic-gate 		if (hdlp->ar_ibt_hdl == ibt_hdl)
34227c478bd9Sstevel@tonic-gate 			break;
34237c478bd9Sstevel@tonic-gate 		hdlpp = &hdlp->ar_ref_link;
34247c478bd9Sstevel@tonic-gate 		hdlp = *hdlpp;
34257c478bd9Sstevel@tonic-gate 	}
34267c478bd9Sstevel@tonic-gate 	if (hdlp == NULL) {	/* could not find ibt_hdl on list */
34277c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
34287c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34297c478bd9Sstevel@tonic-gate 		    "address record found, but not for this client");
34307c478bd9Sstevel@tonic-gate 		return (IBT_AR_NOT_REGISTERED);
34317c478bd9Sstevel@tonic-gate 	}
34327c478bd9Sstevel@tonic-gate 	*hdlpp = hdlp->ar_ref_link;	/* remove ref for this client */
34337c478bd9Sstevel@tonic-gate 	if (found->ar_ibt_hdl_list == NULL && found->ar_waiters == 0) {
34347c478bd9Sstevel@tonic-gate 		/* last entry was removed */
34357c478bd9Sstevel@tonic-gate 		found->ar_flags = IBCM_AR_INITING; /* hold off register_ar */
34367c478bd9Sstevel@tonic-gate 		saa_handle = found->ar_saa_handle;
34377c478bd9Sstevel@tonic-gate 		srv_recp = found->ar_srv_recp;
34387c478bd9Sstevel@tonic-gate 
34397c478bd9Sstevel@tonic-gate 		/* wait if this service record is being rewritten */
34407c478bd9Sstevel@tonic-gate 		while (found->ar_rewrite_state == IBCM_REWRITE_BUSY)
34417c478bd9Sstevel@tonic-gate 			cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
34427c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
34437c478bd9Sstevel@tonic-gate 
34447c478bd9Sstevel@tonic-gate 		/* remove service record */
34457c478bd9Sstevel@tonic-gate 		status = ibcm_write_service_record(saa_handle, srv_recp,
34467c478bd9Sstevel@tonic-gate 		    IBMF_SAA_DELETE);
34477c478bd9Sstevel@tonic-gate 		if (status != IBT_SUCCESS)
34487c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34497c478bd9Sstevel@tonic-gate 			    "IBMF_SAA failed to delete address record");
34507c478bd9Sstevel@tonic-gate 		mutex_enter(&ibcm_svc_info_lock);
34517c478bd9Sstevel@tonic-gate 		if (found->ar_waiters == 0) {	/* still no waiters */
34527c478bd9Sstevel@tonic-gate 			linkp = &ibcm_ar_list;
34537c478bd9Sstevel@tonic-gate 			tmp = *linkp;
34547c478bd9Sstevel@tonic-gate 			while (tmp != found) {
34557c478bd9Sstevel@tonic-gate 				linkp = &tmp->ar_link;
34567c478bd9Sstevel@tonic-gate 				tmp = *linkp;
34577c478bd9Sstevel@tonic-gate 			}
34587c478bd9Sstevel@tonic-gate 			*linkp = tmp->ar_link;
34597c478bd9Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(found->ar_hcap);
34607c478bd9Sstevel@tonic-gate 			kmem_free(srv_recp, sizeof (*srv_recp));
34617c478bd9Sstevel@tonic-gate 			cv_destroy(&found->ar_cv);
34627c478bd9Sstevel@tonic-gate 			kmem_free(found, sizeof (*found));
34637c478bd9Sstevel@tonic-gate 		} else {
34647c478bd9Sstevel@tonic-gate 			/* add service record back in for the waiters */
34657c478bd9Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
34667c478bd9Sstevel@tonic-gate 			status = ibcm_write_service_record(saa_handle, srv_recp,
34677c478bd9Sstevel@tonic-gate 			    IBMF_SAA_UPDATE);
34687c478bd9Sstevel@tonic-gate 			mutex_enter(&ibcm_svc_info_lock);
34697c478bd9Sstevel@tonic-gate 			if (status == IBT_SUCCESS)
34707c478bd9Sstevel@tonic-gate 				found->ar_flags = IBCM_AR_SUCCESS;
34717c478bd9Sstevel@tonic-gate 			else {
34727c478bd9Sstevel@tonic-gate 				found->ar_flags = IBCM_AR_FAILED;
34737c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34747c478bd9Sstevel@tonic-gate 				    "IBMF_SAA failed to write address record");
34757c478bd9Sstevel@tonic-gate 			}
34767c478bd9Sstevel@tonic-gate 			cv_broadcast(&found->ar_cv);
34777c478bd9Sstevel@tonic-gate 		}
34787c478bd9Sstevel@tonic-gate 	}
34797c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
34807c478bd9Sstevel@tonic-gate 	kmem_free(hdlp, sizeof (*hdlp));
34817c478bd9Sstevel@tonic-gate 	ibtl_cm_change_service_cnt(ibt_hdl, -1);
34827c478bd9Sstevel@tonic-gate 	return (status);
34837c478bd9Sstevel@tonic-gate }
34847c478bd9Sstevel@tonic-gate 
34857c478bd9Sstevel@tonic-gate ibt_status_t
ibt_query_ar(ib_gid_t * sgid,ibt_ar_t * queryp,ibt_ar_t * resultp)34867c478bd9Sstevel@tonic-gate ibt_query_ar(ib_gid_t *sgid, ibt_ar_t *queryp, ibt_ar_t *resultp)
34877c478bd9Sstevel@tonic-gate {
34887c478bd9Sstevel@tonic-gate 	sa_service_record_t	svcrec_req;
34897c478bd9Sstevel@tonic-gate 	sa_service_record_t	*svcrec_resp;
34907c478bd9Sstevel@tonic-gate 	void			*results_p;
34917c478bd9Sstevel@tonic-gate 	uint64_t		component_mask = 0;
34927c478bd9Sstevel@tonic-gate 	uint64_t		gid_ored;
34937c478bd9Sstevel@tonic-gate 	size_t			length;
34947c478bd9Sstevel@tonic-gate 	int			num_rec;
34957c478bd9Sstevel@tonic-gate 	int			i;
34967c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
34977c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
34987c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	cm_port;
34997c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
35007c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
35017c478bd9Sstevel@tonic-gate 
35027c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar(%p, %p)", queryp, resultp);
35037c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: sgid %llx:%llx",
35047c478bd9Sstevel@tonic-gate 	    (longlong_t)sgid->gid_prefix, (longlong_t)sgid->gid_guid);
35057c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: query_pkey %x", queryp->ar_pkey);
35067c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: query_gid %llx:%llx",
35077c478bd9Sstevel@tonic-gate 	    (longlong_t)queryp->ar_gid.gid_prefix,
35087c478bd9Sstevel@tonic-gate 	    (longlong_t)queryp->ar_gid.gid_guid);
35097c478bd9Sstevel@tonic-gate 
35107c478bd9Sstevel@tonic-gate 	/*
35117c478bd9Sstevel@tonic-gate 	 * If P_Key is 0, but GID is not, this query is invalid.
35127c478bd9Sstevel@tonic-gate 	 * If GID is 0, but P_Key is not, this query is invalid.
35137c478bd9Sstevel@tonic-gate 	 */
35147c478bd9Sstevel@tonic-gate 	gid_ored = queryp->ar_gid.gid_guid | queryp->ar_gid.gid_prefix;
35157c478bd9Sstevel@tonic-gate 	if ((queryp->ar_pkey == 0 && gid_ored != 0ULL) ||
35167c478bd9Sstevel@tonic-gate 	    (queryp->ar_pkey != 0 && gid_ored == 0ULL)) {
35177c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: GID/P_Key is not valid");
35187c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
35197c478bd9Sstevel@tonic-gate 	}
35207c478bd9Sstevel@tonic-gate 
35217c478bd9Sstevel@tonic-gate 	hcap = NULL;
35227c478bd9Sstevel@tonic-gate 	if (ibtl_cm_get_hca_port(*sgid, 0, &cm_port) != IBT_SUCCESS ||
35237c478bd9Sstevel@tonic-gate 	    (hcap = ibcm_find_hca_entry(cm_port.hp_hca_guid)) == NULL ||
35247c478bd9Sstevel@tonic-gate 	    (saa_handle = ibcm_get_saa_handle(hcap, cm_port.hp_port)) == NULL) {
35257c478bd9Sstevel@tonic-gate 		if (hcap != NULL)
35267c478bd9Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
35277c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: sgid is not valid");
35287c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
35297c478bd9Sstevel@tonic-gate 	}
35307c478bd9Sstevel@tonic-gate 
35317c478bd9Sstevel@tonic-gate 	bzero(&svcrec_req, sizeof (svcrec_req));
35327c478bd9Sstevel@tonic-gate 
35337c478bd9Sstevel@tonic-gate 	/* Is GID/P_Key Specified. */
35347c478bd9Sstevel@tonic-gate 	if (queryp->ar_pkey != 0) {	/* GID is non-zero from check above */
35357c478bd9Sstevel@tonic-gate 		svcrec_req.ServiceP_Key = queryp->ar_pkey;
35367c478bd9Sstevel@tonic-gate 		component_mask |= SA_SR_COMPMASK_PKEY;
35377c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: P_Key %X",
35387c478bd9Sstevel@tonic-gate 		    queryp->ar_pkey);
35397c478bd9Sstevel@tonic-gate 		svcrec_req.ServiceGID = queryp->ar_gid;
35407c478bd9Sstevel@tonic-gate 		component_mask |= SA_SR_COMPMASK_GID;
35417c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: GID %llX:%llX",
35427c478bd9Sstevel@tonic-gate 		    (longlong_t)queryp->ar_gid.gid_prefix,
35437c478bd9Sstevel@tonic-gate 		    (longlong_t)queryp->ar_gid.gid_guid);
35447c478bd9Sstevel@tonic-gate 	}
35457c478bd9Sstevel@tonic-gate 
35467c478bd9Sstevel@tonic-gate 	/* Is ServiceData Specified. */
35477c478bd9Sstevel@tonic-gate 	for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++) {
35487c478bd9Sstevel@tonic-gate 		if (queryp->ar_data[i] != 0) {
35497c478bd9Sstevel@tonic-gate 			bcopy(queryp->ar_data, svcrec_req.ServiceData,
35507c478bd9Sstevel@tonic-gate 			    IBCM_DAPL_ATS_NBYTES);
35517c478bd9Sstevel@tonic-gate 			component_mask |= 0xFFFF << 7;	/* all 16 Data8 */
35527c478bd9Sstevel@tonic-gate 							/* components */
35537c478bd9Sstevel@tonic-gate 			break;
35547c478bd9Sstevel@tonic-gate 		}
35557c478bd9Sstevel@tonic-gate 	}
35567c478bd9Sstevel@tonic-gate 
35577c478bd9Sstevel@tonic-gate 	/* Service Name */
35587c478bd9Sstevel@tonic-gate 	(void) strcpy((char *)svcrec_req.ServiceName, IBCM_DAPL_ATS_NAME);
35597c478bd9Sstevel@tonic-gate 	component_mask |= SA_SR_COMPMASK_NAME;
35607c478bd9Sstevel@tonic-gate 
35617c478bd9Sstevel@tonic-gate 	svcrec_req.ServiceID = IBCM_DAPL_ATS_SID;
35627c478bd9Sstevel@tonic-gate 	component_mask |= SA_SR_COMPMASK_ID;
35637c478bd9Sstevel@tonic-gate 
35647c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
35657c478bd9Sstevel@tonic-gate 	    "Perform SA Access: Mask: 0x%X", component_mask);
35667c478bd9Sstevel@tonic-gate 
35677c478bd9Sstevel@tonic-gate 	/*
35687c478bd9Sstevel@tonic-gate 	 * Call in SA Access retrieve routine to get Service Records.
35697c478bd9Sstevel@tonic-gate 	 *
35707c478bd9Sstevel@tonic-gate 	 * SA Access framework allocated memory for the "results_p".
35717c478bd9Sstevel@tonic-gate 	 * Make sure to deallocate once we are done with the results_p.
35727c478bd9Sstevel@tonic-gate 	 * The size of the buffer allocated will be as returned in
35737c478bd9Sstevel@tonic-gate 	 * "length" field.
35747c478bd9Sstevel@tonic-gate 	 */
35757c478bd9Sstevel@tonic-gate 	access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
35767c478bd9Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
35777c478bd9Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
35787c478bd9Sstevel@tonic-gate 	access_args.sq_template = &svcrec_req;
35797c478bd9Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_service_record_t);
35807c478bd9Sstevel@tonic-gate 	access_args.sq_callback = NULL;
35817c478bd9Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
35827c478bd9Sstevel@tonic-gate 
35837c478bd9Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
35847c478bd9Sstevel@tonic-gate 	    &results_p);
35857c478bd9Sstevel@tonic-gate 
35867c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
35877c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
35887c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: SA Access Failed");
35897c478bd9Sstevel@tonic-gate 		return (retval);
35907c478bd9Sstevel@tonic-gate 	}
35917c478bd9Sstevel@tonic-gate 
35927c478bd9Sstevel@tonic-gate 	num_rec = length / sizeof (sa_service_record_t);
35937c478bd9Sstevel@tonic-gate 
35947c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
35957c478bd9Sstevel@tonic-gate 	    "Found %d Service Records.", num_rec);
35967c478bd9Sstevel@tonic-gate 
35977c478bd9Sstevel@tonic-gate 	/* Validate the returned number of records. */
35987c478bd9Sstevel@tonic-gate 	if ((results_p != NULL) && (num_rec > 0)) {
35997c478bd9Sstevel@tonic-gate 		uint8_t		*b;
36007c478bd9Sstevel@tonic-gate 
36017c478bd9Sstevel@tonic-gate 		/* Just return info from the first service record. */
36027c478bd9Sstevel@tonic-gate 		svcrec_resp = (sa_service_record_t *)results_p;
36037c478bd9Sstevel@tonic-gate 
36047c478bd9Sstevel@tonic-gate 		/* The Service GID and Service ID */
36057c478bd9Sstevel@tonic-gate 		resultp->ar_gid = svcrec_resp->ServiceGID;
36067c478bd9Sstevel@tonic-gate 		resultp->ar_pkey = svcrec_resp->ServiceP_Key;
36077c478bd9Sstevel@tonic-gate 		bcopy(svcrec_resp->ServiceData,
36087c478bd9Sstevel@tonic-gate 		    resultp->ar_data, IBCM_DAPL_ATS_NBYTES);
36097c478bd9Sstevel@tonic-gate 
3610d3a82192SShantkumar Hiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
36117c478bd9Sstevel@tonic-gate 		    "Found: pkey %x dgid %llX:%llX", resultp->ar_pkey,
36127c478bd9Sstevel@tonic-gate 		    (longlong_t)resultp->ar_gid.gid_prefix,
36137c478bd9Sstevel@tonic-gate 		    (longlong_t)resultp->ar_gid.gid_guid);
36147c478bd9Sstevel@tonic-gate 		b = resultp->ar_data;
3615d3a82192SShantkumar Hiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar:"
36167c478bd9Sstevel@tonic-gate 		    " data %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
36177c478bd9Sstevel@tonic-gate 		    b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9],
36187c478bd9Sstevel@tonic-gate 		    b[10], b[11], b[12], b[13], b[14], b[15]);
36197c478bd9Sstevel@tonic-gate 
36207c478bd9Sstevel@tonic-gate 		/* Deallocate the memory for results_p. */
36217c478bd9Sstevel@tonic-gate 		kmem_free(results_p, length);
36227c478bd9Sstevel@tonic-gate 		if (num_rec > 1)
36237c478bd9Sstevel@tonic-gate 			retval = IBT_MULTIPLE_AR;
36247c478bd9Sstevel@tonic-gate 		else
36257c478bd9Sstevel@tonic-gate 			retval = IBT_SUCCESS;
36267c478bd9Sstevel@tonic-gate 	} else {
36277c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: "
36287c478bd9Sstevel@tonic-gate 		    "ibmf_sa_access found 0 matching records");
36297c478bd9Sstevel@tonic-gate 		retval = IBT_AR_NOT_REGISTERED;
36307c478bd9Sstevel@tonic-gate 	}
36317c478bd9Sstevel@tonic-gate 	return (retval);
36327c478bd9Sstevel@tonic-gate }
36337c478bd9Sstevel@tonic-gate 
36347c478bd9Sstevel@tonic-gate /* mark all ATS service records associated with the port */
36357c478bd9Sstevel@tonic-gate static void
ibcm_mark_ar(ib_guid_t hca_guid,uint8_t port)36367c478bd9Sstevel@tonic-gate ibcm_mark_ar(ib_guid_t hca_guid, uint8_t port)
36377c478bd9Sstevel@tonic-gate {
36387c478bd9Sstevel@tonic-gate 	ibcm_ar_t	*tmp;
36397c478bd9Sstevel@tonic-gate 
36407c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
36417c478bd9Sstevel@tonic-gate 	for (tmp = ibcm_ar_list; tmp != NULL; tmp = tmp->ar_link) {
3642cd03c4aeSagiri 		if (tmp->ar_hcap == NULL)
3643cd03c4aeSagiri 			continue;
36447c478bd9Sstevel@tonic-gate 		if (tmp->ar_hcap->hca_guid == hca_guid &&
36457c478bd9Sstevel@tonic-gate 		    tmp->ar_port == port) {
36467c478bd9Sstevel@tonic-gate 			/* even if it's busy, we mark it for rewrite */
36477c478bd9Sstevel@tonic-gate 			tmp->ar_rewrite_state = IBCM_REWRITE_NEEDED;
36487c478bd9Sstevel@tonic-gate 		}
36497c478bd9Sstevel@tonic-gate 	}
36507c478bd9Sstevel@tonic-gate }
36517c478bd9Sstevel@tonic-gate 
36527c478bd9Sstevel@tonic-gate /* rewrite all ATS service records */
36537c478bd9Sstevel@tonic-gate static int
ibcm_rewrite_ar(void)36547c478bd9Sstevel@tonic-gate ibcm_rewrite_ar(void)
36557c478bd9Sstevel@tonic-gate {
36567c478bd9Sstevel@tonic-gate 	ibcm_ar_t		*tmp;
36577c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
36587c478bd9Sstevel@tonic-gate 	sa_service_record_t	*srv_recp;
36597c478bd9Sstevel@tonic-gate 	ibt_status_t		rval;
36607c478bd9Sstevel@tonic-gate 	int			did_something = 0;
36617c478bd9Sstevel@tonic-gate 
36627c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
36637c478bd9Sstevel@tonic-gate check_for_work:
36647c478bd9Sstevel@tonic-gate 	for (tmp = ibcm_ar_list; tmp != NULL; tmp = tmp->ar_link) {
36657c478bd9Sstevel@tonic-gate 		if (tmp->ar_rewrite_state == IBCM_REWRITE_NEEDED) {
36667c478bd9Sstevel@tonic-gate 			tmp->ar_rewrite_state = IBCM_REWRITE_BUSY;
36677c478bd9Sstevel@tonic-gate 			saa_handle = tmp->ar_saa_handle;
36687c478bd9Sstevel@tonic-gate 			srv_recp = tmp->ar_srv_recp;
36697c478bd9Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
36707c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibcm_rewrite_ar: "
36717c478bd9Sstevel@tonic-gate 			    "rewriting ar @ %p", tmp);
36727c478bd9Sstevel@tonic-gate 			did_something = 1;
36737c478bd9Sstevel@tonic-gate 			rval = ibcm_write_service_record(saa_handle, srv_recp,
36747c478bd9Sstevel@tonic-gate 			    IBMF_SAA_UPDATE);
36757c478bd9Sstevel@tonic-gate 			if (rval != IBT_SUCCESS)
36767c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_ar: "
36777c478bd9Sstevel@tonic-gate 				    "ibcm_write_service_record failed: "
36787c478bd9Sstevel@tonic-gate 				    "status = %d", rval);
36797c478bd9Sstevel@tonic-gate 			mutex_enter(&ibcm_svc_info_lock);
36807c478bd9Sstevel@tonic-gate 			/* if it got marked again, then we want to rewrite */
36817c478bd9Sstevel@tonic-gate 			if (tmp->ar_rewrite_state == IBCM_REWRITE_BUSY)
36827c478bd9Sstevel@tonic-gate 				tmp->ar_rewrite_state = IBCM_REWRITE_IDLE;
36837c478bd9Sstevel@tonic-gate 			/* in case there was a waiter... */
36847c478bd9Sstevel@tonic-gate 			cv_broadcast(&ibcm_svc_info_cv);
36857c478bd9Sstevel@tonic-gate 			goto check_for_work;
36867c478bd9Sstevel@tonic-gate 		}
36877c478bd9Sstevel@tonic-gate 	}
36887c478bd9Sstevel@tonic-gate 	return (did_something);
36897c478bd9Sstevel@tonic-gate }
36907c478bd9Sstevel@tonic-gate 
36917c478bd9Sstevel@tonic-gate static void
ibcm_rewrite_svc_record(ibcm_svc_info_t * srv_hdl,ibcm_svc_bind_t * sbindp)36927c478bd9Sstevel@tonic-gate ibcm_rewrite_svc_record(ibcm_svc_info_t *srv_hdl, ibcm_svc_bind_t *sbindp)
36937c478bd9Sstevel@tonic-gate {
36947c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
36957c478bd9Sstevel@tonic-gate 	ib_svc_id_t		sid, start_sid, end_sid;
36967c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
36977c478bd9Sstevel@tonic-gate 	sa_service_record_t	srv_rec;
36987c478bd9Sstevel@tonic-gate 	ibt_status_t		rval;
36997c478bd9Sstevel@tonic-gate 
37007c478bd9Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
37017c478bd9Sstevel@tonic-gate 	if (hcap == NULL) {
37027c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record: "
37037c478bd9Sstevel@tonic-gate 		    "NO HCA found for HCA GUID %llX", sbindp->sbind_hcaguid);
37047c478bd9Sstevel@tonic-gate 		return;
37057c478bd9Sstevel@tonic-gate 	}
37067c478bd9Sstevel@tonic-gate 
37077c478bd9Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, sbindp->sbind_port);
37087c478bd9Sstevel@tonic-gate 	if (saa_handle == NULL) {
37097c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record: "
37107c478bd9Sstevel@tonic-gate 		    "saa_handle is NULL");
37117c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
37127c478bd9Sstevel@tonic-gate 		return;
37137c478bd9Sstevel@tonic-gate 	}
37147c478bd9Sstevel@tonic-gate 
37157c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_rewrite_svc_record: "
37167c478bd9Sstevel@tonic-gate 	    "rewriting svc '%s', port_guid = %llX", sbindp->sbind_name,
37177c478bd9Sstevel@tonic-gate 	    sbindp->sbind_gid.gid_guid);
37187c478bd9Sstevel@tonic-gate 
37197c478bd9Sstevel@tonic-gate 	bzero(&srv_rec, sizeof (srv_rec));
37207c478bd9Sstevel@tonic-gate 
37217c478bd9Sstevel@tonic-gate 	srv_rec.ServiceLease = sbindp->sbind_lease;
37227c478bd9Sstevel@tonic-gate 	srv_rec.ServiceP_Key = sbindp->sbind_pkey;
37237c478bd9Sstevel@tonic-gate 	srv_rec.ServiceKey_hi = sbindp->sbind_key[0];
37247c478bd9Sstevel@tonic-gate 	srv_rec.ServiceKey_lo = sbindp->sbind_key[1];
37257c478bd9Sstevel@tonic-gate 	(void) strcpy((char *)srv_rec.ServiceName, sbindp->sbind_name);
37267c478bd9Sstevel@tonic-gate 	srv_rec.ServiceGID = sbindp->sbind_gid;
37277c478bd9Sstevel@tonic-gate 
37287c478bd9Sstevel@tonic-gate 	bcopy(sbindp->sbind_data, srv_rec.ServiceData, IB_SVC_DATA_LEN);
37297c478bd9Sstevel@tonic-gate 
37307c478bd9Sstevel@tonic-gate 	/* insert srv record into the SA */
37317c478bd9Sstevel@tonic-gate 	start_sid = srv_hdl->svc_id;
37327c478bd9Sstevel@tonic-gate 	end_sid = start_sid + srv_hdl->svc_num_sids - 1;
37337c478bd9Sstevel@tonic-gate 	for (sid = start_sid; sid <= end_sid; sid++) {
37347c478bd9Sstevel@tonic-gate 		srv_rec.ServiceID = sid;
37357c478bd9Sstevel@tonic-gate 
37367c478bd9Sstevel@tonic-gate 		rval = ibcm_write_service_record(saa_handle, &srv_rec,
37377c478bd9Sstevel@tonic-gate 		    IBMF_SAA_UPDATE);
37387c478bd9Sstevel@tonic-gate 
37397c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_rewrite_svc_record: "
37407c478bd9Sstevel@tonic-gate 		    "ibcm_write_service_record, SvcId = %llX, "
37417c478bd9Sstevel@tonic-gate 		    "rval = %d", (longlong_t)sid, rval);
37427c478bd9Sstevel@tonic-gate 		if (rval != IBT_SUCCESS) {
37437c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record:"
37447c478bd9Sstevel@tonic-gate 			    " ibcm_write_service_record fails %d sid %llX",
37457c478bd9Sstevel@tonic-gate 			    rval, (longlong_t)sid);
37467c478bd9Sstevel@tonic-gate 		}
37477c478bd9Sstevel@tonic-gate 	}
37487c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
37497c478bd9Sstevel@tonic-gate }
37507c478bd9Sstevel@tonic-gate 
37517c478bd9Sstevel@tonic-gate /*
37527c478bd9Sstevel@tonic-gate  * Task to mark all service records as needing to be rewritten to the SM/SA.
37537c478bd9Sstevel@tonic-gate  * This task does not return until all of them have been rewritten.
37547c478bd9Sstevel@tonic-gate  */
37557c478bd9Sstevel@tonic-gate void
ibcm_service_record_rewrite_task(void * arg)37567c478bd9Sstevel@tonic-gate ibcm_service_record_rewrite_task(void *arg)
37577c478bd9Sstevel@tonic-gate {
37587c478bd9Sstevel@tonic-gate 	ibcm_port_up_t	*pup = (ibcm_port_up_t *)arg;
37597c478bd9Sstevel@tonic-gate 	ib_guid_t	hca_guid = pup->pup_hca_guid;
37607c478bd9Sstevel@tonic-gate 	uint8_t		port = pup->pup_port;
37617c478bd9Sstevel@tonic-gate 	ibcm_svc_info_t	*svcp;
37627c478bd9Sstevel@tonic-gate 	ibcm_svc_bind_t	*sbp;
37637c478bd9Sstevel@tonic-gate 	avl_tree_t	*avl_tree = &ibcm_svc_avl_tree;
37647c478bd9Sstevel@tonic-gate 	static int	task_is_running = 0;
37657c478bd9Sstevel@tonic-gate 
3766d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_service_record_rewrite_task STARTED "
37677c478bd9Sstevel@tonic-gate 	    "for hca_guid %llX, port %d", hca_guid, port);
37687c478bd9Sstevel@tonic-gate 
37697c478bd9Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
37707c478bd9Sstevel@tonic-gate 	ibcm_mark_ar(hca_guid, port);
37717c478bd9Sstevel@tonic-gate 	for (svcp = avl_first(avl_tree); svcp != NULL;
37727c478bd9Sstevel@tonic-gate 	    svcp = avl_walk(avl_tree, svcp, AVL_AFTER)) {
37737c478bd9Sstevel@tonic-gate 		sbp = svcp->svc_bind_list;
37747c478bd9Sstevel@tonic-gate 		while (sbp != NULL) {
37757c478bd9Sstevel@tonic-gate 			if (sbp->sbind_pkey != 0 &&
37767c478bd9Sstevel@tonic-gate 			    sbp->sbind_port == port &&
37777c478bd9Sstevel@tonic-gate 			    sbp->sbind_hcaguid == hca_guid) {
37787c478bd9Sstevel@tonic-gate 				/* even if it's busy, we mark it for rewrite */
37797c478bd9Sstevel@tonic-gate 				sbp->sbind_rewrite_state = IBCM_REWRITE_NEEDED;
37807c478bd9Sstevel@tonic-gate 			}
37817c478bd9Sstevel@tonic-gate 			sbp = sbp->sbind_link;
37827c478bd9Sstevel@tonic-gate 		}
37837c478bd9Sstevel@tonic-gate 	}
37847c478bd9Sstevel@tonic-gate 	if (task_is_running) {
37857c478bd9Sstevel@tonic-gate 		/* let the other task thread finish the work */
37867c478bd9Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
37877c478bd9Sstevel@tonic-gate 		return;
37887c478bd9Sstevel@tonic-gate 	}
37897c478bd9Sstevel@tonic-gate 	task_is_running = 1;
37907c478bd9Sstevel@tonic-gate 
37917c478bd9Sstevel@tonic-gate 	(void) ibcm_rewrite_ar();
37927c478bd9Sstevel@tonic-gate 
37937c478bd9Sstevel@tonic-gate check_for_work:
37947c478bd9Sstevel@tonic-gate 	for (svcp = avl_first(avl_tree); svcp != NULL;
37957c478bd9Sstevel@tonic-gate 	    svcp = avl_walk(avl_tree, svcp, AVL_AFTER)) {
37967c478bd9Sstevel@tonic-gate 		sbp = svcp->svc_bind_list;
37977c478bd9Sstevel@tonic-gate 		while (sbp != NULL) {
37987c478bd9Sstevel@tonic-gate 			if (sbp->sbind_rewrite_state == IBCM_REWRITE_NEEDED) {
37997c478bd9Sstevel@tonic-gate 				sbp->sbind_rewrite_state = IBCM_REWRITE_BUSY;
38007c478bd9Sstevel@tonic-gate 				mutex_exit(&ibcm_svc_info_lock);
38017c478bd9Sstevel@tonic-gate 				ibcm_rewrite_svc_record(svcp, sbp);
38027c478bd9Sstevel@tonic-gate 				mutex_enter(&ibcm_svc_info_lock);
38037c478bd9Sstevel@tonic-gate 				/* if it got marked again, we want to rewrite */
38047c478bd9Sstevel@tonic-gate 				if (sbp->sbind_rewrite_state ==
38057c478bd9Sstevel@tonic-gate 				    IBCM_REWRITE_BUSY)
38067c478bd9Sstevel@tonic-gate 					sbp->sbind_rewrite_state =
38077c478bd9Sstevel@tonic-gate 					    IBCM_REWRITE_IDLE;
38087c478bd9Sstevel@tonic-gate 				/* in case there was a waiter... */
38097c478bd9Sstevel@tonic-gate 				cv_broadcast(&ibcm_svc_info_cv);
38107c478bd9Sstevel@tonic-gate 				goto check_for_work;
38117c478bd9Sstevel@tonic-gate 			}
38127c478bd9Sstevel@tonic-gate 			sbp = sbp->sbind_link;
38137c478bd9Sstevel@tonic-gate 		}
38147c478bd9Sstevel@tonic-gate 	}
38157c478bd9Sstevel@tonic-gate 	/*
38167c478bd9Sstevel@tonic-gate 	 * If there were no service records to write, and we failed to
38177c478bd9Sstevel@tonic-gate 	 * have to rewrite any more ATS service records, then we're done.
38187c478bd9Sstevel@tonic-gate 	 */
38197c478bd9Sstevel@tonic-gate 	if (ibcm_rewrite_ar() != 0)
38207c478bd9Sstevel@tonic-gate 		goto check_for_work;
38217c478bd9Sstevel@tonic-gate 	task_is_running = 0;
38227c478bd9Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
38237c478bd9Sstevel@tonic-gate 
3824d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_service_record_rewrite_task DONE");
38257c478bd9Sstevel@tonic-gate 	kmem_free(pup, sizeof (ibcm_port_up_t));
38267c478bd9Sstevel@tonic-gate }
38277c478bd9Sstevel@tonic-gate 
3828f07a6d2aSShantkumar Hiremath ibt_status_t
ibt_ofuvcm_get_req_data(void * session_id,ibt_ofuvcm_req_data_t * req_data)3829f07a6d2aSShantkumar Hiremath ibt_ofuvcm_get_req_data(void *session_id, ibt_ofuvcm_req_data_t *req_data)
3830f07a6d2aSShantkumar Hiremath {
3831f07a6d2aSShantkumar Hiremath 	ibcm_state_data_t 	*statep = (ibcm_state_data_t *)session_id;
3832f07a6d2aSShantkumar Hiremath 	ibcm_req_msg_t 		*req_msgp;
3833f07a6d2aSShantkumar Hiremath 
3834f07a6d2aSShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_get_ofuvcm_req_data: session_id %p",
3835f07a6d2aSShantkumar Hiremath 	    session_id);
3836f07a6d2aSShantkumar Hiremath 	mutex_enter(&statep->state_mutex);
3837f07a6d2aSShantkumar Hiremath 	if ((statep->state != IBCM_STATE_REQ_RCVD) &&
3838f07a6d2aSShantkumar Hiremath 	    (statep->state != IBCM_STATE_MRA_SENT)) {
3839f07a6d2aSShantkumar Hiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_get_ofuvcm_req_data: Invalid "
3840f07a6d2aSShantkumar Hiremath 		    "State %x", statep->state);
3841f07a6d2aSShantkumar Hiremath 		mutex_exit(&statep->state_mutex);
3842f07a6d2aSShantkumar Hiremath 		return (IBT_CHAN_STATE_INVALID);
3843f07a6d2aSShantkumar Hiremath 	}
3844f07a6d2aSShantkumar Hiremath 	if (statep->mode == IBCM_ACTIVE_MODE) {
3845f07a6d2aSShantkumar Hiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_get_ofuvcm_req_data: Active mode "
3846f07a6d2aSShantkumar Hiremath 		    "not supported");
3847f07a6d2aSShantkumar Hiremath 		mutex_exit(&statep->state_mutex);
3848f07a6d2aSShantkumar Hiremath 		return (IBT_INVALID_PARAM);
3849f07a6d2aSShantkumar Hiremath 	}
3850f07a6d2aSShantkumar Hiremath 	ASSERT(statep->req_msgp);
3851f07a6d2aSShantkumar Hiremath 
3852f07a6d2aSShantkumar Hiremath 	/*
3853f07a6d2aSShantkumar Hiremath 	 * Fill in the additional req message values reqired for
3854f07a6d2aSShantkumar Hiremath 	 * RTR transition.
3855f07a6d2aSShantkumar Hiremath 	 * Should the PSN be same as the active side??
3856f07a6d2aSShantkumar Hiremath 	 */
3857f07a6d2aSShantkumar Hiremath 	req_msgp = (ibcm_req_msg_t *)statep->req_msgp;
3858f07a6d2aSShantkumar Hiremath 	req_data->req_rnr_nak_time = ibcm_default_rnr_nak_time;
3859f07a6d2aSShantkumar Hiremath 	req_data->req_path_mtu = req_msgp->req_mtu_plus >> 4;
3860f07a6d2aSShantkumar Hiremath 	req_data->req_rq_psn = b2h32(req_msgp->req_starting_psn_plus) >> 8;
3861f07a6d2aSShantkumar Hiremath 	mutex_exit(&statep->state_mutex);
3862f07a6d2aSShantkumar Hiremath 	return (IBT_SUCCESS);
3863f07a6d2aSShantkumar Hiremath }
3864f07a6d2aSShantkumar Hiremath 
3865f07a6d2aSShantkumar Hiremath ibt_status_t
ibt_ofuvcm_proceed(ibt_cm_event_type_t event,void * session_id,ibt_cm_status_t status,ibt_cm_proceed_reply_t * cm_event_data,void * priv_data,ibt_priv_data_len_t priv_data_len)3866f07a6d2aSShantkumar Hiremath ibt_ofuvcm_proceed(ibt_cm_event_type_t event, void *session_id,
3867f07a6d2aSShantkumar Hiremath     ibt_cm_status_t status, ibt_cm_proceed_reply_t *cm_event_data,
3868f07a6d2aSShantkumar Hiremath     void *priv_data, ibt_priv_data_len_t priv_data_len)
3869f07a6d2aSShantkumar Hiremath {
3870f07a6d2aSShantkumar Hiremath 	ibcm_state_data_t *statep = (ibcm_state_data_t *)session_id;
3871f07a6d2aSShantkumar Hiremath 	ibt_status_t		ret;
3872f07a6d2aSShantkumar Hiremath 
3873f07a6d2aSShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_ofuvcm_proceed chan 0x%p event %x "
3874f07a6d2aSShantkumar Hiremath 	    "status %x session_id %p", statep->channel, event, status,
3875f07a6d2aSShantkumar Hiremath 	    session_id);
3876f07a6d2aSShantkumar Hiremath 
3877f07a6d2aSShantkumar Hiremath 	IBTF_DPRINTF_L5(cmlog, "ibt_ofuvcm_proceed chan 0x%p "
3878f07a6d2aSShantkumar Hiremath 	    "cm_event_data %p, priv_data %p priv_data_len %x",
3879f07a6d2aSShantkumar Hiremath 	    statep->channel, cm_event_data, priv_data, priv_data_len);
3880f07a6d2aSShantkumar Hiremath 
3881f07a6d2aSShantkumar Hiremath 	/* validate session_id and status */
3882f07a6d2aSShantkumar Hiremath 	if ((statep == NULL) || (status == IBT_CM_DEFER)) {
3883f07a6d2aSShantkumar Hiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_ofuvcm_proceed : Invalid Args");
3884f07a6d2aSShantkumar Hiremath 		return (IBT_INVALID_PARAM);
3885f07a6d2aSShantkumar Hiremath 	}
3886f07a6d2aSShantkumar Hiremath 
3887f07a6d2aSShantkumar Hiremath 	if (event != IBT_CM_EVENT_REQ_RCV) {
3888f07a6d2aSShantkumar Hiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_ofuvcm_proceed : only for REQ_RCV");
3889f07a6d2aSShantkumar Hiremath 		return (IBT_INVALID_PARAM);
3890f07a6d2aSShantkumar Hiremath 	}
3891f07a6d2aSShantkumar Hiremath 	mutex_enter(&statep->state_mutex);
38929c468ea9SPramod Gunjikar 	statep->is_this_ofuv_chan = B_TRUE;
3893f07a6d2aSShantkumar Hiremath 	mutex_exit(&statep->state_mutex);
3894f07a6d2aSShantkumar Hiremath 
3895f07a6d2aSShantkumar Hiremath 	ret = ibt_cm_proceed(event, session_id, status, cm_event_data,
3896f07a6d2aSShantkumar Hiremath 	    priv_data, priv_data_len);
3897f07a6d2aSShantkumar Hiremath 	return (ret);
3898f07a6d2aSShantkumar Hiremath }
38997c478bd9Sstevel@tonic-gate 
39007c478bd9Sstevel@tonic-gate /*
39017c478bd9Sstevel@tonic-gate  * Function:
39027c478bd9Sstevel@tonic-gate  * 	ibt_cm_proceed
39037c478bd9Sstevel@tonic-gate  *
39047c478bd9Sstevel@tonic-gate  * Verifies the arguments and dispatches the cm state machine processing
39057c478bd9Sstevel@tonic-gate  * via taskq
39067c478bd9Sstevel@tonic-gate  */
39077c478bd9Sstevel@tonic-gate 
39087c478bd9Sstevel@tonic-gate ibt_status_t
ibt_cm_proceed(ibt_cm_event_type_t event,void * session_id,ibt_cm_status_t status,ibt_cm_proceed_reply_t * cm_event_data,void * priv_data,ibt_priv_data_len_t priv_data_len)39097c478bd9Sstevel@tonic-gate ibt_cm_proceed(ibt_cm_event_type_t event, void *session_id,
39107c478bd9Sstevel@tonic-gate     ibt_cm_status_t status, ibt_cm_proceed_reply_t *cm_event_data,
39117c478bd9Sstevel@tonic-gate     void *priv_data, ibt_priv_data_len_t priv_data_len)
39127c478bd9Sstevel@tonic-gate {
39137c478bd9Sstevel@tonic-gate 	ibcm_state_data_t *statep = (ibcm_state_data_t *)session_id;
39147c478bd9Sstevel@tonic-gate 	ibcm_proceed_targs_t	*proceed_targs;
39157c478bd9Sstevel@tonic-gate 	ibcm_proceed_error_t	proceed_error;
39167c478bd9Sstevel@tonic-gate 
39177c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_proceed chan 0x%p event %x status %x "
39187c478bd9Sstevel@tonic-gate 	    "session_id %p", statep->channel, event, status, session_id);
39197c478bd9Sstevel@tonic-gate 
39207c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed chan 0x%p cm_event_data %p, "
39217c478bd9Sstevel@tonic-gate 	    "priv_data %p priv_data_len %x", statep->channel, cm_event_data,
39227c478bd9Sstevel@tonic-gate 	    priv_data, priv_data_len);
39237c478bd9Sstevel@tonic-gate 
39247c478bd9Sstevel@tonic-gate 	/* validate session_id and status */
39257c478bd9Sstevel@tonic-gate 	if ((statep == NULL) || (status == IBT_CM_DEFER)) {
39267c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : Invalid Args");
39277c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
39287c478bd9Sstevel@tonic-gate 	}
39297c478bd9Sstevel@tonic-gate 
39307c478bd9Sstevel@tonic-gate 	/* If priv data len specified, then priv_data cannot be NULL */
39317c478bd9Sstevel@tonic-gate 	if ((priv_data_len > 0) && (priv_data == NULL))
39327c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
39337c478bd9Sstevel@tonic-gate 
39347c478bd9Sstevel@tonic-gate 	proceed_error = IBCM_PROCEED_INVALID_NONE;
39357c478bd9Sstevel@tonic-gate 
39367c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
39377c478bd9Sstevel@tonic-gate 	if (event == IBT_CM_EVENT_REQ_RCV) {
39387c478bd9Sstevel@tonic-gate 
39397c478bd9Sstevel@tonic-gate 		if ((statep->state != IBCM_STATE_REQ_RCVD) &&
39407c478bd9Sstevel@tonic-gate 		    (statep->state != IBCM_STATE_MRA_SENT))
39417c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39427c478bd9Sstevel@tonic-gate 		else if (priv_data_len > IBT_REP_PRIV_DATA_SZ)
39437c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39447c478bd9Sstevel@tonic-gate 
39457c478bd9Sstevel@tonic-gate 	} else if (event == IBT_CM_EVENT_REP_RCV) {
39467c478bd9Sstevel@tonic-gate 		if ((statep->state != IBCM_STATE_REP_RCVD) &&
39477c478bd9Sstevel@tonic-gate 		    (statep->state != IBCM_STATE_MRA_REP_SENT))
39487c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39497c478bd9Sstevel@tonic-gate 		else if (priv_data_len > IBT_RTU_PRIV_DATA_SZ)
39507c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39517c478bd9Sstevel@tonic-gate 	} else if (event == IBT_CM_EVENT_LAP_RCV) {
39527c478bd9Sstevel@tonic-gate 		if ((statep->ap_state != IBCM_AP_STATE_LAP_RCVD) &&
39537c478bd9Sstevel@tonic-gate 		    (statep->ap_state != IBCM_AP_STATE_MRA_LAP_SENT))
39547c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39557c478bd9Sstevel@tonic-gate 		else if (priv_data_len > IBT_APR_PRIV_DATA_SZ)
39567c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39577c478bd9Sstevel@tonic-gate 	} else if (event == IBT_CM_EVENT_CONN_CLOSED) {
39587c478bd9Sstevel@tonic-gate 		if (statep->state != IBCM_STATE_DREQ_RCVD)
39597c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39607c478bd9Sstevel@tonic-gate 		else if (priv_data_len > IBT_DREP_PRIV_DATA_SZ)
39617c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39627c478bd9Sstevel@tonic-gate 	} else {
39637c478bd9Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT;
39647c478bd9Sstevel@tonic-gate 	}
39657c478bd9Sstevel@tonic-gate 
39667c478bd9Sstevel@tonic-gate 	/* if there is an error, print an error message and return */
39677c478bd9Sstevel@tonic-gate 	if (proceed_error != IBCM_PROCEED_INVALID_NONE) {
39687c478bd9Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
39697c478bd9Sstevel@tonic-gate 		if (proceed_error == IBCM_PROCEED_INVALID_EVENT_STATE) {
39707c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39717c478bd9Sstevel@tonic-gate 			    "Invalid Event/State combination specified",
39727c478bd9Sstevel@tonic-gate 			    statep->channel);
39737c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
39747c478bd9Sstevel@tonic-gate 		} else if (proceed_error == IBCM_PROCEED_INVALID_PRIV_SZ) {
39757c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39767c478bd9Sstevel@tonic-gate 			    "Invalid Event/priv len combination specified",
39777c478bd9Sstevel@tonic-gate 			    statep->channel);
39787c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
39797c478bd9Sstevel@tonic-gate 		} else if (proceed_error == IBCM_PROCEED_INVALID_EVENT) {
39807c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39817c478bd9Sstevel@tonic-gate 			    "Invalid Event specified", statep->channel);
39827c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
39837c478bd9Sstevel@tonic-gate 		} else {
39847c478bd9Sstevel@tonic-gate 			ASSERT(proceed_error == IBCM_PROCEED_INVALID_LAP);
39857c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39867c478bd9Sstevel@tonic-gate 			    "IBT_CM_EVENT_LAP_RCV not supported",
39877c478bd9Sstevel@tonic-gate 			    statep->channel);
39887c478bd9Sstevel@tonic-gate 			/* UNTIL HCA DRIVER ENABLES AP SUPPORT, FAIL THE CALL */
39897c478bd9Sstevel@tonic-gate 			return (IBT_APM_NOT_SUPPORTED);
39907c478bd9Sstevel@tonic-gate 		}
39917c478bd9Sstevel@tonic-gate 	}
39927c478bd9Sstevel@tonic-gate 
39937c478bd9Sstevel@tonic-gate 
39947c478bd9Sstevel@tonic-gate 	/* wait until client's CM handler returns DEFER status back to CM */
39957c478bd9Sstevel@tonic-gate 
39967c478bd9Sstevel@tonic-gate 	while (statep->clnt_proceed == IBCM_BLOCK) {
39977c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed : chan 0x%p blocked for "
39987c478bd9Sstevel@tonic-gate 		    "return of client's cm handler", statep->channel);
39997c478bd9Sstevel@tonic-gate 		cv_wait(&statep->block_client_cv, &statep->state_mutex);
40007c478bd9Sstevel@tonic-gate 	}
40017c478bd9Sstevel@tonic-gate 
40027c478bd9Sstevel@tonic-gate 	if (statep->clnt_proceed == IBCM_FAIL) {
40037c478bd9Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
40047c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p Failed as "
40057c478bd9Sstevel@tonic-gate 		    "client returned non-DEFER status from cm handler",
40067c478bd9Sstevel@tonic-gate 		    statep->channel);
40077c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
40087c478bd9Sstevel@tonic-gate 	}
40097c478bd9Sstevel@tonic-gate 
40107c478bd9Sstevel@tonic-gate 	ASSERT(statep->clnt_proceed == IBCM_UNBLOCK);
40117c478bd9Sstevel@tonic-gate 	statep->clnt_proceed = IBCM_FAIL;
40127c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
40137c478bd9Sstevel@tonic-gate 
40147c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
40157c478bd9Sstevel@tonic-gate 
40167c478bd9Sstevel@tonic-gate 	/* the state machine processing is done in a separate thread */
40177c478bd9Sstevel@tonic-gate 
40187c478bd9Sstevel@tonic-gate 	/* proceed_targs is freed in ibcm_proceed_via_taskq */
40197c478bd9Sstevel@tonic-gate 	proceed_targs = kmem_alloc(sizeof (ibcm_proceed_targs_t),
40207c478bd9Sstevel@tonic-gate 	    KM_SLEEP);
40217c478bd9Sstevel@tonic-gate 
40227c478bd9Sstevel@tonic-gate 	proceed_targs->event  = event;
40237c478bd9Sstevel@tonic-gate 	proceed_targs->status = status;
40247c478bd9Sstevel@tonic-gate 	proceed_targs->priv_data_len = priv_data_len;
40257c478bd9Sstevel@tonic-gate 
40267c478bd9Sstevel@tonic-gate 	bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
40277c478bd9Sstevel@tonic-gate 
40287c478bd9Sstevel@tonic-gate 	proceed_targs->tst.rc.statep = statep;
40297c478bd9Sstevel@tonic-gate 	bcopy(cm_event_data, &proceed_targs->tst.rc.rc_cm_event_data,
40307c478bd9Sstevel@tonic-gate 	    sizeof (ibt_cm_proceed_reply_t));
40317c478bd9Sstevel@tonic-gate 
40327c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
40337c478bd9Sstevel@tonic-gate 
40347c478bd9Sstevel@tonic-gate 	(void) taskq_dispatch(ibcm_taskq, ibcm_proceed_via_taskq,
40357c478bd9Sstevel@tonic-gate 	    proceed_targs, TQ_SLEEP);
40367c478bd9Sstevel@tonic-gate 
40377c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
40387c478bd9Sstevel@tonic-gate }
40397c478bd9Sstevel@tonic-gate 
40407c478bd9Sstevel@tonic-gate /*
40417c478bd9Sstevel@tonic-gate  * Function:
40427c478bd9Sstevel@tonic-gate  * 	ibcm_proceed_via_taskq
40437c478bd9Sstevel@tonic-gate  *
40447c478bd9Sstevel@tonic-gate  * Called from taskq, dispatched by ibt_cm_proceed
40457c478bd9Sstevel@tonic-gate  * Completes the cm state processing for ibt_cm_proceed
40467c478bd9Sstevel@tonic-gate  */
40477c478bd9Sstevel@tonic-gate void
ibcm_proceed_via_taskq(void * targs)40487c478bd9Sstevel@tonic-gate ibcm_proceed_via_taskq(void *targs)
40497c478bd9Sstevel@tonic-gate {
40507c478bd9Sstevel@tonic-gate 	ibcm_proceed_targs_t	*proceed_targs = (ibcm_proceed_targs_t *)targs;
40517c478bd9Sstevel@tonic-gate 	ibcm_state_data_t *statep = proceed_targs->tst.rc.statep;
40527c478bd9Sstevel@tonic-gate 	ibt_cm_reason_t reject_reason;
40537c478bd9Sstevel@tonic-gate 	uint8_t arej_len;
40547c478bd9Sstevel@tonic-gate 	ibcm_status_t response;
40557c478bd9Sstevel@tonic-gate 	ibcm_clnt_reply_info_t clnt_info;
40567c478bd9Sstevel@tonic-gate 
40577c478bd9Sstevel@tonic-gate 	clnt_info.reply_event = &proceed_targs->tst.rc.rc_cm_event_data;
40587c478bd9Sstevel@tonic-gate 	clnt_info.priv_data = proceed_targs->priv_data;
40597c478bd9Sstevel@tonic-gate 	clnt_info.priv_data_len = proceed_targs->priv_data_len;
40607c478bd9Sstevel@tonic-gate 
40617c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_proceed_via_taskq chan 0x%p targs %x",
40627c478bd9Sstevel@tonic-gate 	    statep->channel, targs);
40637c478bd9Sstevel@tonic-gate 
40647c478bd9Sstevel@tonic-gate 	if (proceed_targs->event == IBT_CM_EVENT_REQ_RCV) {
40657c478bd9Sstevel@tonic-gate 		response =
40667c478bd9Sstevel@tonic-gate 		    ibcm_process_cep_req_cm_hdlr(statep, proceed_targs->status,
40677c478bd9Sstevel@tonic-gate 		    &clnt_info, &reject_reason, &arej_len,
40687c478bd9Sstevel@tonic-gate 		    (ibcm_req_msg_t *)statep->defer_cm_msg);
40697c478bd9Sstevel@tonic-gate 
40707c478bd9Sstevel@tonic-gate 		ibcm_handle_cep_req_response(statep, response, reject_reason,
40717c478bd9Sstevel@tonic-gate 		    arej_len);
40727c478bd9Sstevel@tonic-gate 
40737c478bd9Sstevel@tonic-gate 	} else if (proceed_targs->event == IBT_CM_EVENT_REP_RCV) {
40747c478bd9Sstevel@tonic-gate 		response =
40757c478bd9Sstevel@tonic-gate 		    ibcm_process_cep_rep_cm_hdlr(statep, proceed_targs->status,
40767c478bd9Sstevel@tonic-gate 		    &clnt_info, &reject_reason, &arej_len,
40777c478bd9Sstevel@tonic-gate 		    (ibcm_rep_msg_t *)statep->defer_cm_msg);
40787c478bd9Sstevel@tonic-gate 
40797c478bd9Sstevel@tonic-gate 		ibcm_handle_cep_rep_response(statep, response, reject_reason,
40807c478bd9Sstevel@tonic-gate 		    arej_len, (ibcm_rep_msg_t *)statep->defer_cm_msg);
40817c478bd9Sstevel@tonic-gate 
40827c478bd9Sstevel@tonic-gate 	} else if (proceed_targs->event == IBT_CM_EVENT_LAP_RCV) {
40837c478bd9Sstevel@tonic-gate 		ibcm_process_cep_lap_cm_hdlr(statep, proceed_targs->status,
40847c478bd9Sstevel@tonic-gate 		    &clnt_info, (ibcm_lap_msg_t *)statep->defer_cm_msg,
40857c478bd9Sstevel@tonic-gate 		    (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg));
40867c478bd9Sstevel@tonic-gate 
40877c478bd9Sstevel@tonic-gate 		ibcm_post_apr_mad(statep);
40887c478bd9Sstevel@tonic-gate 
40897c478bd9Sstevel@tonic-gate 	} else {
40907c478bd9Sstevel@tonic-gate 		ASSERT(proceed_targs->event == IBT_CM_EVENT_CONN_CLOSED);
40917c478bd9Sstevel@tonic-gate 		ibcm_handle_cep_dreq_response(statep, proceed_targs->priv_data,
40927c478bd9Sstevel@tonic-gate 		    proceed_targs->priv_data_len);
40937c478bd9Sstevel@tonic-gate 	}
40947c478bd9Sstevel@tonic-gate 
40957c478bd9Sstevel@tonic-gate 	kmem_free(targs, sizeof (ibcm_proceed_targs_t));
40967c478bd9Sstevel@tonic-gate }
40977c478bd9Sstevel@tonic-gate 
40987c478bd9Sstevel@tonic-gate /*
40997c478bd9Sstevel@tonic-gate  * Function:
41007c478bd9Sstevel@tonic-gate  * 	ibt_cm_ud_proceed
41017c478bd9Sstevel@tonic-gate  *
41027c478bd9Sstevel@tonic-gate  * Verifies the arguments and dispatches the cm state machine processing
41037c478bd9Sstevel@tonic-gate  * via taskq
41047c478bd9Sstevel@tonic-gate  */
41057c478bd9Sstevel@tonic-gate ibt_status_t
ibt_cm_ud_proceed(void * session_id,ibt_channel_hdl_t ud_channel,ibt_cm_status_t status,ibt_redirect_info_t * redirect_infop,void * priv_data,ibt_priv_data_len_t priv_data_len)41067c478bd9Sstevel@tonic-gate ibt_cm_ud_proceed(void *session_id, ibt_channel_hdl_t ud_channel,
41077c478bd9Sstevel@tonic-gate     ibt_cm_status_t status, ibt_redirect_info_t *redirect_infop,
41087c478bd9Sstevel@tonic-gate     void *priv_data, ibt_priv_data_len_t priv_data_len)
41097c478bd9Sstevel@tonic-gate {
41107c478bd9Sstevel@tonic-gate 	ibcm_ud_state_data_t *ud_statep = (ibcm_ud_state_data_t *)session_id;
41117c478bd9Sstevel@tonic-gate 	ibcm_proceed_targs_t	*proceed_targs;
41127c478bd9Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
41137c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
41147c478bd9Sstevel@tonic-gate 
41157c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_ud_proceed session_id %p "
41167c478bd9Sstevel@tonic-gate 	    "ud_channel %p ", session_id, ud_channel);
41177c478bd9Sstevel@tonic-gate 
41187c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_cm_ud_proceed status %x priv_data %p "
41197c478bd9Sstevel@tonic-gate 	    "priv_data_len %x",  status, priv_data, priv_data_len);
41207c478bd9Sstevel@tonic-gate 
41217c478bd9Sstevel@tonic-gate 	/* validate session_id and status */
41227c478bd9Sstevel@tonic-gate 	if ((ud_statep == NULL) || (status == IBT_CM_DEFER)) {
41237c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Invalid Args");
41247c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41257c478bd9Sstevel@tonic-gate 	}
41267c478bd9Sstevel@tonic-gate 
41277c478bd9Sstevel@tonic-gate 	/* If priv data len specified, then priv_data cannot be NULL */
41287c478bd9Sstevel@tonic-gate 	if ((priv_data_len > 0) && (priv_data == NULL))
41297c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41307c478bd9Sstevel@tonic-gate 
41317c478bd9Sstevel@tonic-gate 	if (priv_data_len > IBT_SIDR_REP_PRIV_DATA_SZ)
41327c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41337c478bd9Sstevel@tonic-gate 
41347c478bd9Sstevel@tonic-gate 	/* retrieve qpn and qkey from ud channel */
41357c478bd9Sstevel@tonic-gate 
41367c478bd9Sstevel@tonic-gate 	/* validate event and statep's state */
41377c478bd9Sstevel@tonic-gate 
41387c478bd9Sstevel@tonic-gate 	if (status == IBT_CM_ACCEPT) {
41397c478bd9Sstevel@tonic-gate 		retval = ibt_query_qp(ud_channel, &qp_attr);
41407c478bd9Sstevel@tonic-gate 		if ((retval != IBT_SUCCESS) ||
41417c478bd9Sstevel@tonic-gate 		    (qp_attr.qp_info.qp_trans != IBT_UD_SRV)) {
41427c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed: "
41437c478bd9Sstevel@tonic-gate 			    "Failed to retrieve QPN from the channel: %d",
41447c478bd9Sstevel@tonic-gate 			    retval);
41457c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
41467c478bd9Sstevel@tonic-gate 		}
41477c478bd9Sstevel@tonic-gate 	}
41487c478bd9Sstevel@tonic-gate 
41497c478bd9Sstevel@tonic-gate 
41507c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_statep->ud_state_mutex);
41517c478bd9Sstevel@tonic-gate 
41527c478bd9Sstevel@tonic-gate 	if (ud_statep->ud_state != IBCM_STATE_SIDR_REQ_RCVD) {
41537c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_statep->ud_state_mutex);
41547c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Invalid State "
41557c478bd9Sstevel@tonic-gate 		    "specified");
41567c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41577c478bd9Sstevel@tonic-gate 	}
41587c478bd9Sstevel@tonic-gate 
41597c478bd9Sstevel@tonic-gate 	/* wait until client's CM handler returns DEFER status back to CM */
41607c478bd9Sstevel@tonic-gate 
41617c478bd9Sstevel@tonic-gate 	while (ud_statep->ud_clnt_proceed == IBCM_BLOCK) {
41627c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_cm_ud_proceed : Blocked for return"
41637c478bd9Sstevel@tonic-gate 		    " of client's ud cm handler");
41647c478bd9Sstevel@tonic-gate 		cv_wait(&ud_statep->ud_block_client_cv,
41657c478bd9Sstevel@tonic-gate 		    &ud_statep->ud_state_mutex);
41667c478bd9Sstevel@tonic-gate 	}
41677c478bd9Sstevel@tonic-gate 
41687c478bd9Sstevel@tonic-gate 	if (ud_statep->ud_clnt_proceed == IBCM_FAIL) {
41697c478bd9Sstevel@tonic-gate 		mutex_exit(&ud_statep->ud_state_mutex);
41707c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Failed as client "
41717c478bd9Sstevel@tonic-gate 		    "returned non-DEFER status from cm handler");
41727c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41737c478bd9Sstevel@tonic-gate 	}
41747c478bd9Sstevel@tonic-gate 
41757c478bd9Sstevel@tonic-gate 	ASSERT(ud_statep->ud_clnt_proceed == IBCM_UNBLOCK);
41767c478bd9Sstevel@tonic-gate 	ud_statep->ud_clnt_proceed = IBCM_FAIL;
41777c478bd9Sstevel@tonic-gate 	mutex_exit(&ud_statep->ud_state_mutex);
41787c478bd9Sstevel@tonic-gate 
41797c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
41807c478bd9Sstevel@tonic-gate 
41817c478bd9Sstevel@tonic-gate 	/* the state machine processing is done in a separate thread */
41827c478bd9Sstevel@tonic-gate 
41837c478bd9Sstevel@tonic-gate 	/* proceed_targs is freed in ibcm_proceed_via_taskq */
4184934f0bccShiremath 	proceed_targs = kmem_zalloc(sizeof (ibcm_proceed_targs_t),
41857c478bd9Sstevel@tonic-gate 	    KM_SLEEP);
41867c478bd9Sstevel@tonic-gate 
41877c478bd9Sstevel@tonic-gate 	proceed_targs->status = status;
41887c478bd9Sstevel@tonic-gate 	proceed_targs->priv_data_len = priv_data_len;
41897c478bd9Sstevel@tonic-gate 
41907c478bd9Sstevel@tonic-gate 	bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
41917c478bd9Sstevel@tonic-gate 
41927c478bd9Sstevel@tonic-gate 	if (status == IBT_CM_ACCEPT) {
41937c478bd9Sstevel@tonic-gate 		proceed_targs->tst.ud.ud_qkey =
41947c478bd9Sstevel@tonic-gate 		    qp_attr.qp_info.qp_transport.ud.ud_qkey;
41957c478bd9Sstevel@tonic-gate 		proceed_targs->tst.ud.ud_qpn = qp_attr.qp_qpn;
41967c478bd9Sstevel@tonic-gate 	}
41977c478bd9Sstevel@tonic-gate 
41987c478bd9Sstevel@tonic-gate 	proceed_targs->tst.ud.ud_statep = ud_statep;
41997c478bd9Sstevel@tonic-gate 
42007c478bd9Sstevel@tonic-gate 	/* copy redirect info based on status */
42017c478bd9Sstevel@tonic-gate 	if (status == IBT_CM_REDIRECT)
42027c478bd9Sstevel@tonic-gate 		bcopy(redirect_infop, &proceed_targs->tst.ud.ud_redirect_info,
42037c478bd9Sstevel@tonic-gate 		    sizeof (ibt_redirect_info_t));
42047c478bd9Sstevel@tonic-gate 
42057c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
42067c478bd9Sstevel@tonic-gate 
42077c478bd9Sstevel@tonic-gate 	(void) taskq_dispatch(ibcm_taskq, ibcm_ud_proceed_via_taskq,
42087c478bd9Sstevel@tonic-gate 	    proceed_targs, TQ_SLEEP);
42097c478bd9Sstevel@tonic-gate 
42107c478bd9Sstevel@tonic-gate 	return (IBT_SUCCESS);
42117c478bd9Sstevel@tonic-gate }
42127c478bd9Sstevel@tonic-gate 
42137c478bd9Sstevel@tonic-gate /*
42147c478bd9Sstevel@tonic-gate  * Function:
42157c478bd9Sstevel@tonic-gate  * 	ibcm_ud_proceed_via_taskq
42167c478bd9Sstevel@tonic-gate  *
42177c478bd9Sstevel@tonic-gate  * Called from taskq, dispatched by ibt_cm_ud_proceed
42187c478bd9Sstevel@tonic-gate  * Completes the cm state processing for ibt_cm_ud_proceed
42197c478bd9Sstevel@tonic-gate  */
42207c478bd9Sstevel@tonic-gate void
ibcm_ud_proceed_via_taskq(void * targs)42217c478bd9Sstevel@tonic-gate ibcm_ud_proceed_via_taskq(void *targs)
42227c478bd9Sstevel@tonic-gate {
42237c478bd9Sstevel@tonic-gate 	ibcm_proceed_targs_t	*proceed_targs = (ibcm_proceed_targs_t *)targs;
42247c478bd9Sstevel@tonic-gate 	ibcm_ud_state_data_t	*ud_statep = proceed_targs->tst.ud.ud_statep;
42257c478bd9Sstevel@tonic-gate 	ibcm_ud_clnt_reply_info_t ud_clnt_info;
42267c478bd9Sstevel@tonic-gate 	ibt_sidr_status_t	sidr_status;
42277c478bd9Sstevel@tonic-gate 
42287c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_proceed_via_taskq(%p)", targs);
42297c478bd9Sstevel@tonic-gate 
42307c478bd9Sstevel@tonic-gate 	ud_clnt_info.ud_qpn  = proceed_targs->tst.ud.ud_qpn;
42317c478bd9Sstevel@tonic-gate 	ud_clnt_info.ud_qkey  = proceed_targs->tst.ud.ud_qkey;
42327c478bd9Sstevel@tonic-gate 	ud_clnt_info.priv_data = proceed_targs->priv_data;
42337c478bd9Sstevel@tonic-gate 	ud_clnt_info.priv_data_len = proceed_targs->priv_data_len;
42347c478bd9Sstevel@tonic-gate 	ud_clnt_info.redirect_infop = &proceed_targs->tst.ud.ud_redirect_info;
42357c478bd9Sstevel@tonic-gate 
42367c478bd9Sstevel@tonic-gate 	/* validate event and statep's state */
42377c478bd9Sstevel@tonic-gate 	ibcm_process_sidr_req_cm_hdlr(ud_statep, proceed_targs->status,
42387c478bd9Sstevel@tonic-gate 	    &ud_clnt_info, &sidr_status,
42397c478bd9Sstevel@tonic-gate 	    (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg));
42407c478bd9Sstevel@tonic-gate 
42417c478bd9Sstevel@tonic-gate 	ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
42427c478bd9Sstevel@tonic-gate 
42437c478bd9Sstevel@tonic-gate 	/* decr the statep ref cnt incremented in ibcm_process_sidr_req_msg */
42447c478bd9Sstevel@tonic-gate 	mutex_enter(&ud_statep->ud_state_mutex);
42457c478bd9Sstevel@tonic-gate 	IBCM_UD_REF_CNT_DECR(ud_statep);
42467c478bd9Sstevel@tonic-gate 	mutex_exit(&ud_statep->ud_state_mutex);
42477c478bd9Sstevel@tonic-gate 
42487c478bd9Sstevel@tonic-gate 	kmem_free(targs, sizeof (ibcm_proceed_targs_t));
42497c478bd9Sstevel@tonic-gate }
42507c478bd9Sstevel@tonic-gate 
42517c478bd9Sstevel@tonic-gate /*
42527c478bd9Sstevel@tonic-gate  * Function:
42537c478bd9Sstevel@tonic-gate  *	ibt_set_alt_path
42547c478bd9Sstevel@tonic-gate  * Input:
42557c478bd9Sstevel@tonic-gate  *	channel		Channel handle returned from ibt_alloc_rc_channel(9F).
42567c478bd9Sstevel@tonic-gate  *
42577c478bd9Sstevel@tonic-gate  *	mode		Execute in blocking or non blocking mode.
42587c478bd9Sstevel@tonic-gate  *
42597c478bd9Sstevel@tonic-gate  *	alt_path	A pointer to an ibt_alt_path_info_t as returned from an
42607c478bd9Sstevel@tonic-gate  *			ibt_get_alt_path(9F) call that specifies the new
42617c478bd9Sstevel@tonic-gate  *			alternate path.
42627c478bd9Sstevel@tonic-gate  *
42637c478bd9Sstevel@tonic-gate  *	priv_data       A pointer to a buffer specified by caller for the
42647c478bd9Sstevel@tonic-gate  *			private data in the outgoing CM Load Alternate Path
42657c478bd9Sstevel@tonic-gate  *			(LAP) message sent to the remote host. This can be NULL
42667c478bd9Sstevel@tonic-gate  *			if no private data is available to communicate to the
42677c478bd9Sstevel@tonic-gate  *			remote node.
42687c478bd9Sstevel@tonic-gate  *
42697c478bd9Sstevel@tonic-gate  *	priv_data_len   Length of valid data in priv_data, this should be less
42707c478bd9Sstevel@tonic-gate  *			than or equal to IBT_LAP_PRIV_DATA_SZ.
42717c478bd9Sstevel@tonic-gate  *
42727c478bd9Sstevel@tonic-gate  * Output:
42737c478bd9Sstevel@tonic-gate  *	ret_args	If called in blocking mode, points to a return argument
42747c478bd9Sstevel@tonic-gate  *			structure of type ibt_ap_returns_t.
42757c478bd9Sstevel@tonic-gate  *
42767c478bd9Sstevel@tonic-gate  * Returns:
42777c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS on Success else appropriate error.
42787c478bd9Sstevel@tonic-gate  * Description:
42797c478bd9Sstevel@tonic-gate  *	Load the specified alternate path. Causes the CM to send an LAP message
42807c478bd9Sstevel@tonic-gate  *	to the remote node.
42817c478bd9Sstevel@tonic-gate  *	Can only be called on a previously opened RC channel.
42827c478bd9Sstevel@tonic-gate  */
42837c478bd9Sstevel@tonic-gate ibt_status_t
ibt_set_alt_path(ibt_channel_hdl_t channel,ibt_execution_mode_t mode,ibt_alt_path_info_t * alt_path,void * priv_data,ibt_priv_data_len_t priv_data_len,ibt_ap_returns_t * ret_args)42847c478bd9Sstevel@tonic-gate ibt_set_alt_path(ibt_channel_hdl_t channel, ibt_execution_mode_t mode,
42857c478bd9Sstevel@tonic-gate     ibt_alt_path_info_t *alt_path, void *priv_data,
42867c478bd9Sstevel@tonic-gate     ibt_priv_data_len_t priv_data_len, ibt_ap_returns_t *ret_args)
42877c478bd9Sstevel@tonic-gate {
42887c478bd9Sstevel@tonic-gate 	ibmf_handle_t		ibmf_hdl;
42897c478bd9Sstevel@tonic-gate 	ibt_status_t		status = IBT_SUCCESS;
42907c478bd9Sstevel@tonic-gate 	ibcm_lap_msg_t		*lap_msgp;
42917c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
42927c478bd9Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
42937c478bd9Sstevel@tonic-gate 	uint8_t			port_no;
42947c478bd9Sstevel@tonic-gate 	ib_lid_t		alternate_slid;
42957c478bd9Sstevel@tonic-gate 	ibt_priv_data_len_t	len;
42967c478bd9Sstevel@tonic-gate 	ib_lid_t		base_lid;
42977c478bd9Sstevel@tonic-gate 	boolean_t		alt_grh;
42987c478bd9Sstevel@tonic-gate 
42997c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path(%p, %x, %p, %p, %x, %p)",
43007c478bd9Sstevel@tonic-gate 	    channel, mode, alt_path, priv_data, priv_data_len, ret_args);
43017c478bd9Sstevel@tonic-gate 
43027c478bd9Sstevel@tonic-gate 	/* validate channel */
43037c478bd9Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
43047c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: invalid channel");
43057c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
43067c478bd9Sstevel@tonic-gate 	}
43077c478bd9Sstevel@tonic-gate 
43087c478bd9Sstevel@tonic-gate 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
43097c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43107c478bd9Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel");
43117c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
43127c478bd9Sstevel@tonic-gate 	}
43137c478bd9Sstevel@tonic-gate 
43147c478bd9Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING) {
43157c478bd9Sstevel@tonic-gate 		if (ret_args != NULL) {
43167c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43177c478bd9Sstevel@tonic-gate 			    "ret_args should be NULL when called in "
43187c478bd9Sstevel@tonic-gate 			    "non-blocking mode");
43197c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
43207c478bd9Sstevel@tonic-gate 		}
43217c478bd9Sstevel@tonic-gate 	} else if (mode == IBT_BLOCKING) {
43227c478bd9Sstevel@tonic-gate 		if (ret_args == NULL) {
43237c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43247c478bd9Sstevel@tonic-gate 			    "ret_args should be Non-NULL when called in "
43257c478bd9Sstevel@tonic-gate 			    "blocking mode");
43267c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
43277c478bd9Sstevel@tonic-gate 		}
43287c478bd9Sstevel@tonic-gate 		if (ret_args->ap_priv_data_len > IBT_APR_PRIV_DATA_SZ) {
43297c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43307c478bd9Sstevel@tonic-gate 			    "expected private data length is too large");
43317c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
43327c478bd9Sstevel@tonic-gate 		}
43337c478bd9Sstevel@tonic-gate 		if ((ret_args->ap_priv_data_len > 0) &&
43347c478bd9Sstevel@tonic-gate 		    (ret_args->ap_priv_data == NULL)) {
43357c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43367c478bd9Sstevel@tonic-gate 			    "apr_priv_data_len > 0, but apr_priv_data NULL");
43377c478bd9Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
43387c478bd9Sstevel@tonic-gate 		}
43397c478bd9Sstevel@tonic-gate 	} else { /* any other mode is not valid for ibt_set_alt_path */
43407c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43417c478bd9Sstevel@tonic-gate 		    "invalid mode %x specified", mode);
43427c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
43437c478bd9Sstevel@tonic-gate 	}
43447c478bd9Sstevel@tonic-gate 
43457c478bd9Sstevel@tonic-gate 	if ((port_no = alt_path->ap_alt_cep_path.cep_hca_port_num) == 0)
43467c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
43477c478bd9Sstevel@tonic-gate 
43487c478bd9Sstevel@tonic-gate 	/* get the statep */
43497c478bd9Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
43507c478bd9Sstevel@tonic-gate 	if (statep == NULL) {
43517c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: statep NULL");
43527c478bd9Sstevel@tonic-gate 		return (IBT_CM_FAILURE);
43537c478bd9Sstevel@tonic-gate 	}
43547c478bd9Sstevel@tonic-gate 
43557c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
43567c478bd9Sstevel@tonic-gate 	IBCM_RELEASE_CHAN_PRIVATE(channel);
43577c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);
43587c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
43597c478bd9Sstevel@tonic-gate 
43607c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: statep %p", statep);
43617c478bd9Sstevel@tonic-gate 
43627c478bd9Sstevel@tonic-gate 	hcap = statep->hcap;
43637c478bd9Sstevel@tonic-gate 
43647c478bd9Sstevel@tonic-gate 	/* HCA must have been in active state. If not, it's a client bug */
43657c478bd9Sstevel@tonic-gate 	if (!IBCM_ACCESS_HCA_OK(hcap))
43667c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: hca in error state");
43677c478bd9Sstevel@tonic-gate 
43687c478bd9Sstevel@tonic-gate 	ASSERT(statep->cm_handler != NULL);
43697c478bd9Sstevel@tonic-gate 
43707c478bd9Sstevel@tonic-gate 	/* Check Alternate port */
43717c478bd9Sstevel@tonic-gate 	status = ibt_get_port_state_byguid(hcap->hca_guid, port_no, NULL,
43727c478bd9Sstevel@tonic-gate 	    &base_lid);
43737c478bd9Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
43747c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43757c478bd9Sstevel@tonic-gate 		    "ibt_get_port_state_byguid status %d ", status);
43767c478bd9Sstevel@tonic-gate 		mutex_enter(&statep->state_mutex);
43777c478bd9Sstevel@tonic-gate 		IBCM_REF_CNT_DECR(statep);
43787c478bd9Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
43797c478bd9Sstevel@tonic-gate 		return (status);
43807c478bd9Sstevel@tonic-gate 	}
43817c478bd9Sstevel@tonic-gate 
43827c478bd9Sstevel@tonic-gate 	if ((hcap->hca_port_info[port_no - 1].port_ibmf_hdl == NULL) &&
43837c478bd9Sstevel@tonic-gate 	    ((status = ibcm_hca_reinit_port(hcap, port_no - 1))
43847c478bd9Sstevel@tonic-gate 	    != IBT_SUCCESS)) {
43857c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43867c478bd9Sstevel@tonic-gate 		    "ibmf reg or callback setup failed during re-initialize");
43877c478bd9Sstevel@tonic-gate 		mutex_enter(&statep->state_mutex);
43887c478bd9Sstevel@tonic-gate 		IBCM_REF_CNT_DECR(statep);
43897c478bd9Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
43907c478bd9Sstevel@tonic-gate 		return (status);
43917c478bd9Sstevel@tonic-gate 	}
43927c478bd9Sstevel@tonic-gate 
43937c478bd9Sstevel@tonic-gate 	ibmf_hdl = statep->stored_reply_addr.ibmf_hdl;
43947c478bd9Sstevel@tonic-gate 
43957c478bd9Sstevel@tonic-gate 	alternate_slid = base_lid +
43967c478bd9Sstevel@tonic-gate 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_src_path;
43977c478bd9Sstevel@tonic-gate 
43987c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: alternate SLID = %x",
43997c478bd9Sstevel@tonic-gate 	    h2b16(alternate_slid));
44007c478bd9Sstevel@tonic-gate 
44019d3d2ed0Shiremath 	ibcm_lapr_enter();	/* limit how many run simultaneously */
44027c478bd9Sstevel@tonic-gate 
44037c478bd9Sstevel@tonic-gate 	/* Allocate MAD for LAP */
44047c478bd9Sstevel@tonic-gate 	if (statep->lapr_msg == NULL)
44057c478bd9Sstevel@tonic-gate 		if ((status = ibcm_alloc_out_msg(ibmf_hdl, &statep->lapr_msg,
44067c478bd9Sstevel@tonic-gate 		    MAD_METHOD_SEND)) != IBT_SUCCESS) {
44079d3d2ed0Shiremath 			ibcm_lapr_exit();
44087c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
44097c478bd9Sstevel@tonic-gate 			    "chan 0x%p ibcm_alloc_out_msg failed", channel);
44107c478bd9Sstevel@tonic-gate 			mutex_enter(&statep->state_mutex);
44117c478bd9Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
44127c478bd9Sstevel@tonic-gate 			mutex_exit(&statep->state_mutex);
44137c478bd9Sstevel@tonic-gate 			return (status);
44147c478bd9Sstevel@tonic-gate 		}
44157c478bd9Sstevel@tonic-gate 
44167c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
44177c478bd9Sstevel@tonic-gate 
44187c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: connection state is"
44197c478bd9Sstevel@tonic-gate 	    " %x", statep->state);
44207c478bd9Sstevel@tonic-gate 
44217c478bd9Sstevel@tonic-gate 	/* Check state */
44227c478bd9Sstevel@tonic-gate 	if ((statep->state != IBCM_STATE_ESTABLISHED) ||
44237c478bd9Sstevel@tonic-gate 	    (statep->ap_state != IBCM_AP_STATE_IDLE)) {
44247c478bd9Sstevel@tonic-gate 		IBCM_REF_CNT_DECR(statep);
44257c478bd9Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
44267c478bd9Sstevel@tonic-gate 		(void) ibcm_free_out_msg(ibmf_hdl, &statep->lapr_msg);
44279d3d2ed0Shiremath 		ibcm_lapr_exit();
44287c478bd9Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
44297c478bd9Sstevel@tonic-gate 	} else {
44307c478bd9Sstevel@tonic-gate 		/* Set to LAP Sent state */
44317c478bd9Sstevel@tonic-gate 		statep->ap_state = IBCM_AP_STATE_LAP_SENT;
44327c478bd9Sstevel@tonic-gate 		statep->ap_done = B_FALSE;
44337c478bd9Sstevel@tonic-gate 		statep->remaining_retry_cnt = statep->max_cm_retries;
44347c478bd9Sstevel@tonic-gate 		statep->timer_stored_state = statep->state;
44357c478bd9Sstevel@tonic-gate 		statep->timer_stored_ap_state = statep->ap_state;
44367c478bd9Sstevel@tonic-gate 		IBCM_REF_CNT_INCR(statep); /* for ibcm_post_lap_complete */
44377c478bd9Sstevel@tonic-gate 	}
44387c478bd9Sstevel@tonic-gate 
44397c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
44407c478bd9Sstevel@tonic-gate 
44417c478bd9Sstevel@tonic-gate 	/* No more failure returns below */
44427c478bd9Sstevel@tonic-gate 
44437c478bd9Sstevel@tonic-gate 	/* Allocate MAD for LAP */
44447c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_set_alt_path:"
44457c478bd9Sstevel@tonic-gate 	    " statep's mad addr = 0x%p", IBCM_OUT_HDRP(statep->lapr_msg));
44467c478bd9Sstevel@tonic-gate 
44477c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lap_msgp))
44487c478bd9Sstevel@tonic-gate 
44497c478bd9Sstevel@tonic-gate 	lap_msgp = (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
44507c478bd9Sstevel@tonic-gate 
44517c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_l_port_lid = h2b16(alternate_slid);
44527c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_r_port_lid =
44537c478bd9Sstevel@tonic-gate 	    h2b16(alt_path->ap_alt_cep_path.cep_adds_vect.av_dlid);
44547c478bd9Sstevel@tonic-gate 
44557c478bd9Sstevel@tonic-gate 	/* Fill in remote port gid */
44567c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_r_port_gid.gid_prefix =
44577c478bd9Sstevel@tonic-gate 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_prefix);
44587c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_r_port_gid.gid_guid =
44597c478bd9Sstevel@tonic-gate 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_guid);
44607c478bd9Sstevel@tonic-gate 
44617c478bd9Sstevel@tonic-gate 	/* Fill in local port gid */
44627c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_l_port_gid.gid_prefix =
44637c478bd9Sstevel@tonic-gate 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_prefix);
44647c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_l_port_gid.gid_guid =
44657c478bd9Sstevel@tonic-gate 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_guid);
44667c478bd9Sstevel@tonic-gate 
44677c478bd9Sstevel@tonic-gate 	alt_grh = alt_path->ap_alt_cep_path.cep_adds_vect.av_send_grh;
44687c478bd9Sstevel@tonic-gate 
44697c478bd9Sstevel@tonic-gate 	/* alternate_flow_label, and alternate srate, alternate traffic class */
44707c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_srate_plus =
44717c478bd9Sstevel@tonic-gate 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_srate & 0x3f;
44727c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_flow_label_plus = h2b32(((alt_grh == B_TRUE) ?
44737c478bd9Sstevel@tonic-gate 	    (alt_path->ap_alt_cep_path.cep_adds_vect.av_flow << 12) : 0) |
44747c478bd9Sstevel@tonic-gate 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_tclass);
44757c478bd9Sstevel@tonic-gate 
44767c478bd9Sstevel@tonic-gate 	/* Alternate hop limit, service level */
44777c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_hop_limit = (alt_grh == B_TRUE) ?
44786db9c6ddShiremath 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_hop : 1;
44797c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_sl_plus =
44807c478bd9Sstevel@tonic-gate 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_srvl << 4 |
44817c478bd9Sstevel@tonic-gate 	    ((alt_grh == B_FALSE) ? 0x8 : 0);
44827c478bd9Sstevel@tonic-gate 
44837c478bd9Sstevel@tonic-gate 	lap_msgp->lap_alt_local_acktime_plus = ibt_usec2ib(
44847c478bd9Sstevel@tonic-gate 	    (2 * statep->rc_alt_pkt_lt) +
44857c478bd9Sstevel@tonic-gate 	    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
44867c478bd9Sstevel@tonic-gate 
44877c478bd9Sstevel@tonic-gate 	lap_msgp->lap_local_comm_id = h2b32(statep->local_comid);
44887c478bd9Sstevel@tonic-gate 	lap_msgp->lap_remote_comm_id = h2b32(statep->remote_comid);
44897c478bd9Sstevel@tonic-gate 
44907c478bd9Sstevel@tonic-gate 	lap_msgp->lap_remote_qpn_eecn_plus =
44917c478bd9Sstevel@tonic-gate 	    h2b32((statep->remote_qpn << 8) |
44927c478bd9Sstevel@tonic-gate 	    ibt_usec2ib(ibcm_remote_response_time) << 3);
44937c478bd9Sstevel@tonic-gate 
44947c478bd9Sstevel@tonic-gate 	len = min(priv_data_len, IBT_LAP_PRIV_DATA_SZ);
44957c478bd9Sstevel@tonic-gate 	if ((len > 0) && priv_data) {
44967c478bd9Sstevel@tonic-gate 		bcopy(priv_data, lap_msgp->lap_private_data, len);
44977c478bd9Sstevel@tonic-gate 	}
44987c478bd9Sstevel@tonic-gate 
44997c478bd9Sstevel@tonic-gate 	/* only rc_alt_pkt_lt and ap_return_data fields are initialized */
45007c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
45017c478bd9Sstevel@tonic-gate 
45027c478bd9Sstevel@tonic-gate 	statep->rc_alt_pkt_lt = ibt_ib2usec(alt_path->ap_alt_pkt_lt);
45037c478bd9Sstevel@tonic-gate 
45047c478bd9Sstevel@tonic-gate 	/* return_data is filled up in the state machine code */
45057c478bd9Sstevel@tonic-gate 	statep->ap_return_data = ret_args;
45067c478bd9Sstevel@tonic-gate 
45077c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
45087c478bd9Sstevel@tonic-gate 
45097c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
45107c478bd9Sstevel@tonic-gate 	    h2b16(IBCM_INCOMING_LAP + IBCM_ATTR_BASE_ID);
45117c478bd9Sstevel@tonic-gate 
45127c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID =
45137c478bd9Sstevel@tonic-gate 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_LAP, statep->local_comid,
45147c478bd9Sstevel@tonic-gate 	    0));
45157c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path: statep %p, tid %llx",
45167c478bd9Sstevel@tonic-gate 	    statep, IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID);
45177c478bd9Sstevel@tonic-gate 
45187c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*lap_msgp))
45197c478bd9Sstevel@tonic-gate 
45207c478bd9Sstevel@tonic-gate 	/* Send LAP */
45217c478bd9Sstevel@tonic-gate 	ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_lap_complete,
45227c478bd9Sstevel@tonic-gate 	    statep);
45237c478bd9Sstevel@tonic-gate 
45247c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
45257c478bd9Sstevel@tonic-gate 
45267c478bd9Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
45277c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: blocking");
45287c478bd9Sstevel@tonic-gate 
45297c478bd9Sstevel@tonic-gate 		/* wait for APR */
45307c478bd9Sstevel@tonic-gate 		while (statep->ap_done != B_TRUE) {
45317c478bd9Sstevel@tonic-gate 			cv_wait(&statep->block_client_cv,
45327c478bd9Sstevel@tonic-gate 			    &statep->state_mutex);
45337c478bd9Sstevel@tonic-gate 		}
45347c478bd9Sstevel@tonic-gate 
45357c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done blocking");
45367c478bd9Sstevel@tonic-gate 
45377c478bd9Sstevel@tonic-gate 		/*
45387c478bd9Sstevel@tonic-gate 		 * In the case that ibt_set_alt_path fails,
45397c478bd9Sstevel@tonic-gate 		 * change retval to IBT_CM_FAILURE
45407c478bd9Sstevel@tonic-gate 		 */
45417c478bd9Sstevel@tonic-gate 		if (statep->ap_return_data->ap_status != IBT_CM_AP_LOADED)
45427c478bd9Sstevel@tonic-gate 			status = IBT_CM_FAILURE;
45437c478bd9Sstevel@tonic-gate 
45447c478bd9Sstevel@tonic-gate 	}
45457c478bd9Sstevel@tonic-gate 
45467c478bd9Sstevel@tonic-gate 	/* decrement the ref-count before leaving here */
45477c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
45487c478bd9Sstevel@tonic-gate 
45497c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
45507c478bd9Sstevel@tonic-gate 
45519d3d2ed0Shiremath 	ibcm_lapr_exit();
45529d3d2ed0Shiremath 
45537c478bd9Sstevel@tonic-gate 	/* If this message isn't seen then ibt_set_alt_path failed */
45547c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done");
45557c478bd9Sstevel@tonic-gate 
45567c478bd9Sstevel@tonic-gate 	return (status);
45577c478bd9Sstevel@tonic-gate }
45587c478bd9Sstevel@tonic-gate 
45597c478bd9Sstevel@tonic-gate 
45607c478bd9Sstevel@tonic-gate #ifdef DEBUG
45617c478bd9Sstevel@tonic-gate 
45627c478bd9Sstevel@tonic-gate /*
45637c478bd9Sstevel@tonic-gate  * ibcm_query_classport_info:
45647c478bd9Sstevel@tonic-gate  *	Query classportinfo
45657c478bd9Sstevel@tonic-gate  *
45667c478bd9Sstevel@tonic-gate  * INPUTS:
45677c478bd9Sstevel@tonic-gate  *	channel		- Channel that is associated with a statep
45687c478bd9Sstevel@tonic-gate  *
45697c478bd9Sstevel@tonic-gate  * RETURN VALUE: NONE
45707c478bd9Sstevel@tonic-gate  * This function is currently used to generate a valid get method classport
45717c478bd9Sstevel@tonic-gate  * info, and test CM functionality. There is no ibtl client interface to
45727c478bd9Sstevel@tonic-gate  * generate a classportinfo. It is possible that CM may use classportinfo
45737c478bd9Sstevel@tonic-gate  * from other nodes in the future, and most of the code below could be re-used.
45747c478bd9Sstevel@tonic-gate  */
45757c478bd9Sstevel@tonic-gate void
ibcm_query_classport_info(ibt_channel_hdl_t channel)45767c478bd9Sstevel@tonic-gate ibcm_query_classport_info(ibt_channel_hdl_t channel)
45777c478bd9Sstevel@tonic-gate {
45787c478bd9Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
45797c478bd9Sstevel@tonic-gate 	ibmf_msg_t		*msgp;
45807c478bd9Sstevel@tonic-gate 
4581d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_query_classport_info(%p)", channel);
45827c478bd9Sstevel@tonic-gate 
45837c478bd9Sstevel@tonic-gate 	/* validate channel, first */
45847c478bd9Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
45857c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info: "
45867c478bd9Sstevel@tonic-gate 		    "invalid channel (%p)", channel);
45877c478bd9Sstevel@tonic-gate 		return;
45887c478bd9Sstevel@tonic-gate 	}
45897c478bd9Sstevel@tonic-gate 
45907c478bd9Sstevel@tonic-gate 	/* get the statep */
45917c478bd9Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
45927c478bd9Sstevel@tonic-gate 
45937c478bd9Sstevel@tonic-gate 	/*
45947c478bd9Sstevel@tonic-gate 	 * This can happen, if the statep is already gone by a DREQ from
45957c478bd9Sstevel@tonic-gate 	 * the remote side
45967c478bd9Sstevel@tonic-gate 	 */
45977c478bd9Sstevel@tonic-gate 	if (statep == NULL) {
45987c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info: "
45997c478bd9Sstevel@tonic-gate 		    "statep NULL");
46007c478bd9Sstevel@tonic-gate 		return;
46017c478bd9Sstevel@tonic-gate 	}
46027c478bd9Sstevel@tonic-gate 
46037c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
46047c478bd9Sstevel@tonic-gate 	IBCM_RELEASE_CHAN_PRIVATE(channel);
46057c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);
46067c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
46077c478bd9Sstevel@tonic-gate 
46087c478bd9Sstevel@tonic-gate 	/* Debug/test code, so don't care about return status */
46097c478bd9Sstevel@tonic-gate 	(void) ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl, &msgp,
46107c478bd9Sstevel@tonic-gate 	    MAD_METHOD_GET);
46117c478bd9Sstevel@tonic-gate 
46127c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(msgp)->TransactionID = h2b64(ibcm_generate_tranid(
46137c478bd9Sstevel@tonic-gate 	    MAD_ATTR_ID_CLASSPORTINFO, statep->local_comid, 0));
46147c478bd9Sstevel@tonic-gate 	IBCM_OUT_HDRP(msgp)->AttributeID = h2b16(MAD_ATTR_ID_CLASSPORTINFO);
46157c478bd9Sstevel@tonic-gate 
46167c478bd9Sstevel@tonic-gate 	(void) ibcm_post_mad(msgp, &statep->stored_reply_addr, NULL, NULL);
46177c478bd9Sstevel@tonic-gate 
4618d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_query_classport_info(%p) "
46197c478bd9Sstevel@tonic-gate 	    "Get method MAD posted ", channel);
46207c478bd9Sstevel@tonic-gate 
46217c478bd9Sstevel@tonic-gate 	(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, &msgp);
46227c478bd9Sstevel@tonic-gate 
46237c478bd9Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
46247c478bd9Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
46257c478bd9Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
46267c478bd9Sstevel@tonic-gate }
46277c478bd9Sstevel@tonic-gate 
46287c478bd9Sstevel@tonic-gate static void
ibcm_print_reply_addr(ibt_channel_hdl_t channel,ibcm_mad_addr_t * cm_reply_addr)46297c478bd9Sstevel@tonic-gate ibcm_print_reply_addr(ibt_channel_hdl_t channel, ibcm_mad_addr_t *cm_reply_addr)
46307c478bd9Sstevel@tonic-gate {
46317c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: chan 0x%p, SLID %x, "
46327c478bd9Sstevel@tonic-gate 	    "DLID %x", channel, cm_reply_addr->rcvd_addr.ia_local_lid,
46337c478bd9Sstevel@tonic-gate 	    cm_reply_addr->rcvd_addr.ia_remote_lid);
46347c478bd9Sstevel@tonic-gate 
46357c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: QKEY %x, PKEY %x, "
46367c478bd9Sstevel@tonic-gate 	    "RQPN %x SL %x", cm_reply_addr->rcvd_addr.ia_q_key,
46377c478bd9Sstevel@tonic-gate 	    cm_reply_addr->rcvd_addr.ia_p_key,
46387c478bd9Sstevel@tonic-gate 	    cm_reply_addr->rcvd_addr.ia_remote_qno,
46397c478bd9Sstevel@tonic-gate 	    cm_reply_addr->rcvd_addr.ia_service_level);
46407c478bd9Sstevel@tonic-gate 
46417c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM SGID %llX:%llX ",
46427c478bd9Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_sender_gid.gid_prefix,
46437c478bd9Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_sender_gid.gid_guid);
46447c478bd9Sstevel@tonic-gate 
46457c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM DGID %llX:%llX",
46467c478bd9Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_recver_gid.gid_prefix,
46477c478bd9Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_recver_gid.gid_guid);
46487c478bd9Sstevel@tonic-gate 
46497c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM FL %x TC %x HL %x",
46507c478bd9Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_flow_label,
46517c478bd9Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_tclass,
46527c478bd9Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_hop_limit);
46537c478bd9Sstevel@tonic-gate }
46547c478bd9Sstevel@tonic-gate 
46557c478bd9Sstevel@tonic-gate #endif
46567c478bd9Sstevel@tonic-gate 
4657f07a6d2aSShantkumar Hiremath /* For MCG List search */
4658f07a6d2aSShantkumar Hiremath typedef struct ibcm_mcg_list_s {
4659f07a6d2aSShantkumar Hiremath 	struct ibcm_mcg_list_s	*ml_next;
4660f07a6d2aSShantkumar Hiremath 	ib_gid_t		ml_sgid;
4661f07a6d2aSShantkumar Hiremath 	ib_gid_t		ml_mgid;
4662f07a6d2aSShantkumar Hiremath 	ib_pkey_t		ml_pkey;
4663f07a6d2aSShantkumar Hiremath 	ib_qkey_t		ml_qkey;
4664f07a6d2aSShantkumar Hiremath 	uint_t			ml_refcnt;
4665f07a6d2aSShantkumar Hiremath 	uint8_t			ml_jstate;
4666f07a6d2aSShantkumar Hiremath } ibcm_mcg_list_t;
4667f07a6d2aSShantkumar Hiremath 
4668f07a6d2aSShantkumar Hiremath ibcm_mcg_list_t	*ibcm_mcglist = NULL;
4669f07a6d2aSShantkumar Hiremath 
4670f07a6d2aSShantkumar Hiremath _NOTE(MUTEX_PROTECTS_DATA(ibcm_mcglist_lock, ibcm_mcg_list_s))
4671f07a6d2aSShantkumar Hiremath _NOTE(MUTEX_PROTECTS_DATA(ibcm_mcglist_lock, ibcm_mcglist))
4672f07a6d2aSShantkumar Hiremath 
46737c478bd9Sstevel@tonic-gate typedef struct ibcm_join_mcg_tqarg_s {
46747c478bd9Sstevel@tonic-gate 	ib_gid_t		rgid;
46757c478bd9Sstevel@tonic-gate 	ibt_mcg_attr_t		mcg_attr;
46767c478bd9Sstevel@tonic-gate 	ibt_mcg_info_t		*mcg_infop;
46777c478bd9Sstevel@tonic-gate 	ibt_mcg_handler_t	func;
46787c478bd9Sstevel@tonic-gate 	void			*arg;
46797c478bd9Sstevel@tonic-gate } ibcm_join_mcg_tqarg_t;
46807c478bd9Sstevel@tonic-gate 
_NOTE(READ_ONLY_DATA (ibcm_join_mcg_tqarg_s))46817c478bd9Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_join_mcg_tqarg_s))
46827c478bd9Sstevel@tonic-gate 
4683f07a6d2aSShantkumar Hiremath void
4684f07a6d2aSShantkumar Hiremath ibcm_add_incr_mcg_entry(sa_mcmember_record_t *mcg_req,
4685f07a6d2aSShantkumar Hiremath     sa_mcmember_record_t *mcg_resp)
4686f07a6d2aSShantkumar Hiremath {
4687f07a6d2aSShantkumar Hiremath 	ibcm_mcg_list_t	*new = NULL;
4688f07a6d2aSShantkumar Hiremath 	ibcm_mcg_list_t	*head = NULL;
4689f07a6d2aSShantkumar Hiremath 
4690f07a6d2aSShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: MGID %llX:%llX"
4691f07a6d2aSShantkumar Hiremath 	    "\n SGID %llX:%llX, JState %X)", mcg_req->MGID.gid_prefix,
4692f07a6d2aSShantkumar Hiremath 	    mcg_req->MGID.gid_guid, mcg_req->PortGID.gid_prefix,
4693f07a6d2aSShantkumar Hiremath 	    mcg_req->PortGID.gid_guid, mcg_req->JoinState);
4694f07a6d2aSShantkumar Hiremath 
4695f07a6d2aSShantkumar Hiremath 	mutex_enter(&ibcm_mcglist_lock);
4696f07a6d2aSShantkumar Hiremath 	head = ibcm_mcglist;
4697f07a6d2aSShantkumar Hiremath 
4698f07a6d2aSShantkumar Hiremath 	while (head != NULL) {
4699f07a6d2aSShantkumar Hiremath 		if ((head->ml_mgid.gid_guid == mcg_resp->MGID.gid_guid) &&
4700f07a6d2aSShantkumar Hiremath 		    (head->ml_mgid.gid_prefix == mcg_resp->MGID.gid_prefix) &&
4701f07a6d2aSShantkumar Hiremath 		    (head->ml_sgid.gid_guid == mcg_resp->PortGID.gid_guid)) {
4702f07a6d2aSShantkumar Hiremath 			/* Increment the count */
4703f07a6d2aSShantkumar Hiremath 			head->ml_refcnt++;
4704f07a6d2aSShantkumar Hiremath 			/* OR the join_state value, we need this during leave */
4705f07a6d2aSShantkumar Hiremath 			head->ml_jstate |= mcg_req->JoinState;
4706f07a6d2aSShantkumar Hiremath 
4707f07a6d2aSShantkumar Hiremath 			IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: Entry "
4708f07a6d2aSShantkumar Hiremath 			    "FOUND: refcnt %d JState %X", head->ml_refcnt,
4709f07a6d2aSShantkumar Hiremath 			    head->ml_jstate);
4710f07a6d2aSShantkumar Hiremath 
4711f07a6d2aSShantkumar Hiremath 			mutex_exit(&ibcm_mcglist_lock);
4712f07a6d2aSShantkumar Hiremath 			return;
4713f07a6d2aSShantkumar Hiremath 		}
4714f07a6d2aSShantkumar Hiremath 		head = head->ml_next;
4715f07a6d2aSShantkumar Hiremath 	}
4716f07a6d2aSShantkumar Hiremath 	mutex_exit(&ibcm_mcglist_lock);
4717f07a6d2aSShantkumar Hiremath 
4718f07a6d2aSShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: Create NEW Entry ");
4719f07a6d2aSShantkumar Hiremath 
4720f07a6d2aSShantkumar Hiremath 	/* If we are here, either list is empty or match couldn't be found */
4721f07a6d2aSShantkumar Hiremath 	new = kmem_zalloc(sizeof (ibcm_mcg_list_t), KM_SLEEP);
4722f07a6d2aSShantkumar Hiremath 
4723f07a6d2aSShantkumar Hiremath 	mutex_enter(&ibcm_mcglist_lock);
4724f07a6d2aSShantkumar Hiremath 	/* Initialize the fields */
4725f07a6d2aSShantkumar Hiremath 	new->ml_sgid = mcg_resp->PortGID;
4726f07a6d2aSShantkumar Hiremath 	new->ml_mgid = mcg_resp->MGID;
4727f07a6d2aSShantkumar Hiremath 	new->ml_qkey = mcg_req->Q_Key;
4728f07a6d2aSShantkumar Hiremath 	new->ml_pkey = mcg_req->P_Key;
4729f07a6d2aSShantkumar Hiremath 	new->ml_refcnt = 1; /* As this is the first entry */
4730f07a6d2aSShantkumar Hiremath 	new->ml_jstate = mcg_req->JoinState;
4731f07a6d2aSShantkumar Hiremath 	new->ml_next = NULL;
4732f07a6d2aSShantkumar Hiremath 
4733f07a6d2aSShantkumar Hiremath 	new->ml_next = ibcm_mcglist;
4734f07a6d2aSShantkumar Hiremath 	ibcm_mcglist = new;
4735f07a6d2aSShantkumar Hiremath 	mutex_exit(&ibcm_mcglist_lock);
4736f07a6d2aSShantkumar Hiremath }
4737f07a6d2aSShantkumar Hiremath 
4738f07a6d2aSShantkumar Hiremath /*
4739f07a6d2aSShantkumar Hiremath  * ibcm_del_decr_mcg_entry
4740f07a6d2aSShantkumar Hiremath  *
4741f07a6d2aSShantkumar Hiremath  * Return value:
4742f07a6d2aSShantkumar Hiremath  * IBCM_SUCCESS		Entry found and ref_cnt is now zero. So go-ahead and
4743f07a6d2aSShantkumar Hiremath  * 			leave the MCG group. The return arg *jstate will have
4744f07a6d2aSShantkumar Hiremath  * 			a valid join_state value that needed to be used by
4745f07a6d2aSShantkumar Hiremath  * 			xxx_leave_mcg().
4746f07a6d2aSShantkumar Hiremath  * IBCM_LOOKUP_EXISTS	Entry found and ref_cnt is decremented but is NOT zero.
4747f07a6d2aSShantkumar Hiremath  * 			So do not leave the MCG group yet.
4748f07a6d2aSShantkumar Hiremath  * IBCM_LOOKUP_FAIL	Entry is NOT found.
4749f07a6d2aSShantkumar Hiremath  */
4750f07a6d2aSShantkumar Hiremath ibcm_status_t
ibcm_del_decr_mcg_entry(sa_mcmember_record_t * mcg_req,uint8_t * jstate)4751f07a6d2aSShantkumar Hiremath ibcm_del_decr_mcg_entry(sa_mcmember_record_t *mcg_req, uint8_t *jstate)
4752f07a6d2aSShantkumar Hiremath {
4753f07a6d2aSShantkumar Hiremath 	ibcm_mcg_list_t	*head, *prev;
4754f07a6d2aSShantkumar Hiremath 
4755f07a6d2aSShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_del_decr_mcg_entry: MGID %llX:%llX"
4756f07a6d2aSShantkumar Hiremath 	    "\n SGID %llX:%llX, JState %X)", mcg_req->MGID.gid_prefix,
4757f07a6d2aSShantkumar Hiremath 	    mcg_req->MGID.gid_guid, mcg_req->PortGID.gid_prefix,
4758f07a6d2aSShantkumar Hiremath 	    mcg_req->PortGID.gid_guid, mcg_req->JoinState);
4759f07a6d2aSShantkumar Hiremath 
4760f07a6d2aSShantkumar Hiremath 	*jstate = 0;
4761f07a6d2aSShantkumar Hiremath 
4762f07a6d2aSShantkumar Hiremath 	mutex_enter(&ibcm_mcglist_lock);
4763f07a6d2aSShantkumar Hiremath 	head = ibcm_mcglist;
4764f07a6d2aSShantkumar Hiremath 	prev = NULL;
4765f07a6d2aSShantkumar Hiremath 
4766f07a6d2aSShantkumar Hiremath 	while (head != NULL) {
4767f07a6d2aSShantkumar Hiremath 		if ((head->ml_mgid.gid_guid == mcg_req->MGID.gid_guid) &&
4768f07a6d2aSShantkumar Hiremath 		    (head->ml_mgid.gid_prefix == mcg_req->MGID.gid_prefix) &&
4769f07a6d2aSShantkumar Hiremath 		    (head->ml_sgid.gid_guid == mcg_req->PortGID.gid_guid)) {
4770f07a6d2aSShantkumar Hiremath 			if (!(head->ml_jstate & mcg_req->JoinState)) {
4771f07a6d2aSShantkumar Hiremath 				IBTF_DPRINTF_L2(cmlog, "ibcm_del_decr_mcg_entry"
4772f07a6d2aSShantkumar Hiremath 				    ": JoinState mismatch %X %X)",
4773f07a6d2aSShantkumar Hiremath 				    head->ml_jstate, mcg_req->JoinState);
4774f07a6d2aSShantkumar Hiremath 			}
4775f07a6d2aSShantkumar Hiremath 			/* Decrement the count */
4776f07a6d2aSShantkumar Hiremath 			head->ml_refcnt--;
4777f07a6d2aSShantkumar Hiremath 
4778f07a6d2aSShantkumar Hiremath 			if (head->ml_refcnt == 0) {
4779f07a6d2aSShantkumar Hiremath 				*jstate = head->ml_jstate;
4780f07a6d2aSShantkumar Hiremath 
4781f07a6d2aSShantkumar Hiremath 				IBTF_DPRINTF_L3(cmlog, "ibcm_del_decr_mcg_entry"
4782f07a6d2aSShantkumar Hiremath 				    ": refcnt is ZERO, so delete the entry ");
4783f07a6d2aSShantkumar Hiremath 				if ((head == ibcm_mcglist) || (prev == NULL)) {
4784f07a6d2aSShantkumar Hiremath 					ibcm_mcglist = head->ml_next;
4785f07a6d2aSShantkumar Hiremath 				} else if (prev != NULL) {
4786f07a6d2aSShantkumar Hiremath 					prev->ml_next = head->ml_next;
4787f07a6d2aSShantkumar Hiremath 				}
4788f07a6d2aSShantkumar Hiremath 				mutex_exit(&ibcm_mcglist_lock);
4789f07a6d2aSShantkumar Hiremath 
4790f07a6d2aSShantkumar Hiremath 				kmem_free(head, sizeof (ibcm_mcg_list_t));
4791f07a6d2aSShantkumar Hiremath 				return (IBCM_SUCCESS);
4792f07a6d2aSShantkumar Hiremath 			}
4793f07a6d2aSShantkumar Hiremath 			mutex_exit(&ibcm_mcglist_lock);
4794f07a6d2aSShantkumar Hiremath 			return (IBCM_LOOKUP_EXISTS);
4795f07a6d2aSShantkumar Hiremath 		}
4796f07a6d2aSShantkumar Hiremath 		prev = head;
4797f07a6d2aSShantkumar Hiremath 		head = head->ml_next;
4798f07a6d2aSShantkumar Hiremath 	}
4799f07a6d2aSShantkumar Hiremath 	mutex_exit(&ibcm_mcglist_lock);
4800f07a6d2aSShantkumar Hiremath 
4801f07a6d2aSShantkumar Hiremath 	/*
4802f07a6d2aSShantkumar Hiremath 	 * If we are here, something went wrong, we don't have the entry
4803f07a6d2aSShantkumar Hiremath 	 * for that MCG being joined.
4804f07a6d2aSShantkumar Hiremath 	 */
4805f07a6d2aSShantkumar Hiremath 	IBTF_DPRINTF_L2(cmlog, "ibcm_del_decr_mcg_entry: Match NOT "
4806f07a6d2aSShantkumar Hiremath 	    "Found ");
4807f07a6d2aSShantkumar Hiremath 
4808f07a6d2aSShantkumar Hiremath 	return (IBCM_LOOKUP_FAIL);
4809f07a6d2aSShantkumar Hiremath }
4810f07a6d2aSShantkumar Hiremath 
4811f07a6d2aSShantkumar Hiremath 
48127c478bd9Sstevel@tonic-gate /*
48137c478bd9Sstevel@tonic-gate  * Function:
48147c478bd9Sstevel@tonic-gate  *	ibt_join_mcg
48157c478bd9Sstevel@tonic-gate  * Input:
48167c478bd9Sstevel@tonic-gate  *	rgid		The request GID that defines the HCA port from which a
48177c478bd9Sstevel@tonic-gate  *			contact to SA Access is performed to add the specified
48187c478bd9Sstevel@tonic-gate  *			endport GID ((mcg_attr->mc_pgid) to a multicast group.
48197c478bd9Sstevel@tonic-gate  *			If mcg_attr->mc_pgid is null, then this (rgid) will be
48207c478bd9Sstevel@tonic-gate  *			treated as endport GID that is to be added to the
48217c478bd9Sstevel@tonic-gate  *			multicast group.
48227c478bd9Sstevel@tonic-gate  *
48237c478bd9Sstevel@tonic-gate  *	mcg_attr	A pointer to an ibt_mcg_attr_t structure that defines
48247c478bd9Sstevel@tonic-gate  *			the attributes of the desired multicast group to be
48257c478bd9Sstevel@tonic-gate  *			created or joined.
48267c478bd9Sstevel@tonic-gate  *
48277c478bd9Sstevel@tonic-gate  *	func		NULL or a pointer to a function to call when
48287c478bd9Sstevel@tonic-gate  *			ibt_join_mcg() completes. If 'func' is not NULL then
48297c478bd9Sstevel@tonic-gate  *			ibt_join_mcg() will return as soon as possible after
48307c478bd9Sstevel@tonic-gate  *			initiating the multicast group join/create process.
48317c478bd9Sstevel@tonic-gate  *			'func' is then called when the process completes.
48327c478bd9Sstevel@tonic-gate  *
48337c478bd9Sstevel@tonic-gate  *	arg		Argument to the 'func'.
48347c478bd9Sstevel@tonic-gate  *
48357c478bd9Sstevel@tonic-gate  * Output:
48367c478bd9Sstevel@tonic-gate  *	mcg_info_p	A pointer to the ibt_mcg_info_t structure, allocated
48377c478bd9Sstevel@tonic-gate  *			by the caller, where the attributes of the created or
48387c478bd9Sstevel@tonic-gate  *			joined multicast group are copied.
48397c478bd9Sstevel@tonic-gate  * Returns:
48407c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
48417c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
48427c478bd9Sstevel@tonic-gate  *	IBT_MCG_RECORDS_NOT_FOUND
48437c478bd9Sstevel@tonic-gate  *	IBT_INSUFF_RESOURCE
48447c478bd9Sstevel@tonic-gate  * Description:
48457c478bd9Sstevel@tonic-gate  *	Join a multicast group.  The first full member "join" causes the MCG
48467c478bd9Sstevel@tonic-gate  *	to be created.
48477c478bd9Sstevel@tonic-gate  */
48487c478bd9Sstevel@tonic-gate ibt_status_t
ibt_join_mcg(ib_gid_t rgid,ibt_mcg_attr_t * mcg_attr,ibt_mcg_info_t * mcg_info_p,ibt_mcg_handler_t func,void * arg)48497c478bd9Sstevel@tonic-gate ibt_join_mcg(ib_gid_t rgid, ibt_mcg_attr_t *mcg_attr,
48507c478bd9Sstevel@tonic-gate     ibt_mcg_info_t *mcg_info_p, ibt_mcg_handler_t func, void  *arg)
48517c478bd9Sstevel@tonic-gate {
48527c478bd9Sstevel@tonic-gate 	ibcm_join_mcg_tqarg_t	*mcg_tq;
48537c478bd9Sstevel@tonic-gate 	int			flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
48547c478bd9Sstevel@tonic-gate 
48557c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg(%llX:%llX, %p)", rgid.gid_prefix,
48567c478bd9Sstevel@tonic-gate 	    rgid.gid_guid, mcg_attr);
48577c478bd9Sstevel@tonic-gate 
48587c478bd9Sstevel@tonic-gate 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
48597c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Request GID is required");
48607c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
48617c478bd9Sstevel@tonic-gate 	}
48627c478bd9Sstevel@tonic-gate 
48637c478bd9Sstevel@tonic-gate 	if ((mcg_attr->mc_pkey == IB_PKEY_INVALID_LIMITED) ||
48647c478bd9Sstevel@tonic-gate 	    (mcg_attr->mc_pkey == IB_PKEY_INVALID_FULL)) {
48657c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Invalid P_Key specified");
48667c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
48677c478bd9Sstevel@tonic-gate 	}
48687c478bd9Sstevel@tonic-gate 
48697c478bd9Sstevel@tonic-gate 	if (mcg_attr->mc_join_state == 0) {
48707c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: JoinState not specified");
48717c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
48727c478bd9Sstevel@tonic-gate 	}
48737c478bd9Sstevel@tonic-gate 
48747c478bd9Sstevel@tonic-gate 	if (mcg_info_p == NULL) {
48757c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: mcg_info_p is NULL");
48767c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
48777c478bd9Sstevel@tonic-gate 	}
48787c478bd9Sstevel@tonic-gate 
48797c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mcg_tq))
48807c478bd9Sstevel@tonic-gate 
48817c478bd9Sstevel@tonic-gate 	mcg_tq = kmem_alloc(sizeof (ibcm_join_mcg_tqarg_t), flag);
48827c478bd9Sstevel@tonic-gate 	if (mcg_tq == NULL) {
48837c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: "
48847c478bd9Sstevel@tonic-gate 		    "Unable to allocate memory for local usage.");
48857c478bd9Sstevel@tonic-gate 		return (IBT_INSUFF_KERNEL_RESOURCE);
48867c478bd9Sstevel@tonic-gate 	}
48877c478bd9Sstevel@tonic-gate 
48887c478bd9Sstevel@tonic-gate 	mcg_tq->rgid = rgid;
48897c478bd9Sstevel@tonic-gate 	bcopy(mcg_attr, &mcg_tq->mcg_attr, sizeof (ibt_mcg_attr_t));
48907c478bd9Sstevel@tonic-gate 	mcg_tq->mcg_infop = mcg_info_p;
48917c478bd9Sstevel@tonic-gate 	mcg_tq->func = func;
48927c478bd9Sstevel@tonic-gate 	mcg_tq->arg = arg;
48937c478bd9Sstevel@tonic-gate 
48947c478bd9Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mcg_tq))
48957c478bd9Sstevel@tonic-gate 
48967c478bd9Sstevel@tonic-gate 	if (func != NULL) {	/* Non-Blocking */
48977c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg: Non-Blocking Call");
48987c478bd9Sstevel@tonic-gate 		if (taskq_dispatch(ibcm_taskq, ibcm_process_async_join_mcg,
4899*fc8ae2ecSToomas Soome 		    mcg_tq, TQ_NOSLEEP) == TASKQID_INVALID) {
49007c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Failed to "
49017c478bd9Sstevel@tonic-gate 			    "Dispatch the TaskQ");
49027c478bd9Sstevel@tonic-gate 			kmem_free(mcg_tq, sizeof (ibcm_join_mcg_tqarg_t));
49037c478bd9Sstevel@tonic-gate 			return (IBT_INSUFF_KERNEL_RESOURCE);
49047c478bd9Sstevel@tonic-gate 		} else
49057c478bd9Sstevel@tonic-gate 			return (IBT_SUCCESS);
49067c478bd9Sstevel@tonic-gate 	} else {		/* Blocking */
49077c478bd9Sstevel@tonic-gate 		return (ibcm_process_join_mcg(mcg_tq));
49087c478bd9Sstevel@tonic-gate 	}
49097c478bd9Sstevel@tonic-gate }
49107c478bd9Sstevel@tonic-gate 
49117c478bd9Sstevel@tonic-gate static void
ibcm_process_async_join_mcg(void * tq_arg)49127c478bd9Sstevel@tonic-gate ibcm_process_async_join_mcg(void *tq_arg)
49137c478bd9Sstevel@tonic-gate {
49147c478bd9Sstevel@tonic-gate 	(void) ibcm_process_join_mcg(tq_arg);
49157c478bd9Sstevel@tonic-gate }
49167c478bd9Sstevel@tonic-gate 
49177c478bd9Sstevel@tonic-gate static ibt_status_t
ibcm_process_join_mcg(void * taskq_arg)49187c478bd9Sstevel@tonic-gate ibcm_process_join_mcg(void *taskq_arg)
49197c478bd9Sstevel@tonic-gate {
49207c478bd9Sstevel@tonic-gate 	sa_mcmember_record_t	mcg_req;
49217c478bd9Sstevel@tonic-gate 	sa_mcmember_record_t	*mcg_resp;
49227c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
49237c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
49247c478bd9Sstevel@tonic-gate 	uint64_t		component_mask = 0;
49257c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
49267c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hca_port;
49277c478bd9Sstevel@tonic-gate 	uint_t			num_records;
49287c478bd9Sstevel@tonic-gate 	size_t			length;
49297c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
49307c478bd9Sstevel@tonic-gate 	ibcm_join_mcg_tqarg_t	*mcg_arg = (ibcm_join_mcg_tqarg_t *)taskq_arg;
49317c478bd9Sstevel@tonic-gate 	ibt_mcg_info_t		*mcg_info_p = mcg_arg->mcg_infop;
49327c478bd9Sstevel@tonic-gate 
49337c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg(%p)", mcg_arg);
49347c478bd9Sstevel@tonic-gate 
49357c478bd9Sstevel@tonic-gate 	retval = ibtl_cm_get_hca_port(mcg_arg->rgid, 0, &hca_port);
49367c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
49377c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: Failed to get "
49387c478bd9Sstevel@tonic-gate 		    "port info from specified RGID: status = %d", retval);
49397c478bd9Sstevel@tonic-gate 		goto ibcm_join_mcg_exit1;
49407c478bd9Sstevel@tonic-gate 	}
49417c478bd9Sstevel@tonic-gate 
49427c478bd9Sstevel@tonic-gate 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
49437c478bd9Sstevel@tonic-gate 
49447c478bd9Sstevel@tonic-gate 	if ((mcg_arg->mcg_attr.mc_pgid.gid_prefix == 0) ||
49457c478bd9Sstevel@tonic-gate 	    (mcg_arg->mcg_attr.mc_pgid.gid_guid == 0)) {
49467c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
49477c478bd9Sstevel@tonic-gate 		    "Request GID is Port GID");
49487c478bd9Sstevel@tonic-gate 		mcg_req.PortGID = mcg_arg->rgid;
49497c478bd9Sstevel@tonic-gate 	} else {
49507c478bd9Sstevel@tonic-gate 		mcg_req.PortGID = mcg_arg->mcg_attr.mc_pgid;
49517c478bd9Sstevel@tonic-gate 	}
49527c478bd9Sstevel@tonic-gate 	component_mask |= SA_MC_COMPMASK_PORTGID;
49537c478bd9Sstevel@tonic-gate 
49547c478bd9Sstevel@tonic-gate 	mcg_req.Q_Key = mcg_arg->mcg_attr.mc_qkey;
49557c478bd9Sstevel@tonic-gate 	mcg_req.P_Key = mcg_arg->mcg_attr.mc_pkey;
49567c478bd9Sstevel@tonic-gate 	mcg_req.JoinState = mcg_arg->mcg_attr.mc_join_state;
49577c478bd9Sstevel@tonic-gate 	mcg_req.TClass = mcg_arg->mcg_attr.mc_tclass;
49587c478bd9Sstevel@tonic-gate 	mcg_req.FlowLabel = mcg_arg->mcg_attr.mc_flow;
49597c478bd9Sstevel@tonic-gate 	mcg_req.SL = mcg_arg->mcg_attr.mc_sl;
49607c478bd9Sstevel@tonic-gate 
49617c478bd9Sstevel@tonic-gate 	component_mask |= SA_MC_COMPMASK_QKEY | SA_MC_COMPMASK_PKEY |
49627c478bd9Sstevel@tonic-gate 	    SA_MC_COMPMASK_JOINSTATE | SA_MC_COMPMASK_TCLASS |
49637c478bd9Sstevel@tonic-gate 	    SA_MC_COMPMASK_FLOWLABEL | SA_MC_COMPMASK_SL;
49647c478bd9Sstevel@tonic-gate 
49657c478bd9Sstevel@tonic-gate 	/* If client has specified MGID, use it else SA will assign one. */
49667c478bd9Sstevel@tonic-gate 	if ((mcg_arg->mcg_attr.mc_mgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
49677c478bd9Sstevel@tonic-gate 		mcg_req.MGID = mcg_arg->mcg_attr.mc_mgid;
49687c478bd9Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_MGID;
49697c478bd9Sstevel@tonic-gate 	}
49707c478bd9Sstevel@tonic-gate 
4971d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: ");
4972d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "PGID=%016llX:%016llX, ",
4973d3a82192SShantkumar Hiremath 	    mcg_req.PortGID.gid_prefix, mcg_req.PortGID.gid_guid);
4974d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "MGID=%016llX:%016llX",
4975d3a82192SShantkumar Hiremath 	    mcg_req.MGID.gid_prefix, mcg_req.MGID.gid_guid);
4976d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L3(cmlog, "JoinState = %X",
4977d3a82192SShantkumar Hiremath 	    mcg_arg->mcg_attr.mc_join_state);
4978d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L5(cmlog, "QKey %lX, PKey %lX",
4979d3a82192SShantkumar Hiremath 	    mcg_arg->mcg_attr.mc_qkey, mcg_arg->mcg_attr.mc_pkey);
4980d3a82192SShantkumar Hiremath 	IBTF_DPRINTF_L5(cmlog, "Scope %X, MLID %X",
4981d3a82192SShantkumar Hiremath 	    mcg_arg->mcg_attr.mc_scope, mcg_arg->mcg_attr.mc_mlid);
49827c478bd9Sstevel@tonic-gate 
49837c478bd9Sstevel@tonic-gate 	/* Is MTU specified. */
49847c478bd9Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_mtu_req.r_mtu) {
49857c478bd9Sstevel@tonic-gate 		mcg_req.MTU = mcg_arg->mcg_attr.mc_mtu_req.r_mtu;
49867c478bd9Sstevel@tonic-gate 		mcg_req.MTUSelector = mcg_arg->mcg_attr.mc_mtu_req.r_selector;
49877c478bd9Sstevel@tonic-gate 
49887c478bd9Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_MTUSELECTOR |
49897c478bd9Sstevel@tonic-gate 		    SA_MC_COMPMASK_MTU;
49907c478bd9Sstevel@tonic-gate 	}
49917c478bd9Sstevel@tonic-gate 
49927c478bd9Sstevel@tonic-gate 	/* Is RATE specified. */
49937c478bd9Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_rate_req.r_srate) {
49947c478bd9Sstevel@tonic-gate 		mcg_req.Rate = mcg_arg->mcg_attr.mc_rate_req.r_srate;
49957c478bd9Sstevel@tonic-gate 		mcg_req.RateSelector =
49967c478bd9Sstevel@tonic-gate 		    mcg_arg->mcg_attr.mc_rate_req.r_selector;
49977c478bd9Sstevel@tonic-gate 
49987c478bd9Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_RATESELECTOR |
49997c478bd9Sstevel@tonic-gate 		    SA_MC_COMPMASK_RATE;
50007c478bd9Sstevel@tonic-gate 	}
50017c478bd9Sstevel@tonic-gate 
50027c478bd9Sstevel@tonic-gate 	/* Is Packet Life Time specified. */
50037c478bd9Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_pkt_lt_req.p_pkt_lt) {
50047c478bd9Sstevel@tonic-gate 		mcg_req.Rate = mcg_arg->mcg_attr.mc_pkt_lt_req.p_pkt_lt;
50057c478bd9Sstevel@tonic-gate 		mcg_req.RateSelector =
50067c478bd9Sstevel@tonic-gate 		    mcg_arg->mcg_attr.mc_pkt_lt_req.p_selector;
50077c478bd9Sstevel@tonic-gate 
50087c478bd9Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_PKTLTSELECTOR |
50097c478bd9Sstevel@tonic-gate 		    SA_MC_COMPMASK_PKTLT;
50107c478bd9Sstevel@tonic-gate 	}
50117c478bd9Sstevel@tonic-gate 
50127c478bd9Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_hop) {
50137c478bd9Sstevel@tonic-gate 		mcg_req.HopLimit = mcg_arg->mcg_attr.mc_hop;
50147c478bd9Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_HOPLIMIT;
50157c478bd9Sstevel@tonic-gate 	}
50167c478bd9Sstevel@tonic-gate 
50177c478bd9Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_scope) {
50187c478bd9Sstevel@tonic-gate 		mcg_req.Scope = mcg_arg->mcg_attr.mc_scope;
50197c478bd9Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_SCOPE;
50207c478bd9Sstevel@tonic-gate 	}
50217c478bd9Sstevel@tonic-gate 
50227c478bd9Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_mlid) {
50237c478bd9Sstevel@tonic-gate 		mcg_req.MLID = mcg_arg->mcg_attr.mc_mlid;
50247c478bd9Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_MLID;
50257c478bd9Sstevel@tonic-gate 	}
50267c478bd9Sstevel@tonic-gate 
50277c478bd9Sstevel@tonic-gate 	/* Get SA Access Handle. */
50287c478bd9Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(hca_port.hp_hca_guid);
50297c478bd9Sstevel@tonic-gate 	if (hcap == NULL) {
50307c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: NO HCA found");
50317c478bd9Sstevel@tonic-gate 
50327c478bd9Sstevel@tonic-gate 		retval = IBT_HCA_BUSY_DETACHING;
50337c478bd9Sstevel@tonic-gate 		goto ibcm_join_mcg_exit1;
50347c478bd9Sstevel@tonic-gate 	}
50357c478bd9Sstevel@tonic-gate 
50367c478bd9Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, hca_port.hp_port);
50377c478bd9Sstevel@tonic-gate 	if (saa_handle == NULL) {
50387c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: SA Handle NULL");
50397c478bd9Sstevel@tonic-gate 
50407c478bd9Sstevel@tonic-gate 		retval = IBT_HCA_PORT_NOT_ACTIVE;
50417c478bd9Sstevel@tonic-gate 		goto ibcm_join_mcg_exit;
50427c478bd9Sstevel@tonic-gate 	}
50437c478bd9Sstevel@tonic-gate 
50447c478bd9Sstevel@tonic-gate 	if ((mcg_arg->mcg_attr.mc_pgid.gid_prefix != 0) &&
50457c478bd9Sstevel@tonic-gate 	    (mcg_arg->mcg_attr.mc_pgid.gid_guid != 0)) {
50467c478bd9Sstevel@tonic-gate 		retval = ibtl_cm_get_hca_port(mcg_arg->mcg_attr.mc_pgid, 0,
50477c478bd9Sstevel@tonic-gate 		    &hca_port);
50487c478bd9Sstevel@tonic-gate 		if (retval != IBT_SUCCESS) {
50497c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: Failed "
50507c478bd9Sstevel@tonic-gate 			    "to get PortInfo of specified PGID: status = %d",
50517c478bd9Sstevel@tonic-gate 			    retval);
50527c478bd9Sstevel@tonic-gate 			goto ibcm_join_mcg_exit1;
50537c478bd9Sstevel@tonic-gate 		}
50547c478bd9Sstevel@tonic-gate 	}
50557c478bd9Sstevel@tonic-gate 
50567c478bd9Sstevel@tonic-gate 	/* Contact SA Access */
50577c478bd9Sstevel@tonic-gate 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
50587c478bd9Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_UPDATE;
50597c478bd9Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
50607c478bd9Sstevel@tonic-gate 	access_args.sq_template = &mcg_req;
50617c478bd9Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
50627c478bd9Sstevel@tonic-gate 	access_args.sq_callback = NULL;
50637c478bd9Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
50647c478bd9Sstevel@tonic-gate 
50657c478bd9Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
50667c478bd9Sstevel@tonic-gate 	    (void **)&mcg_resp);
50677c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
50687c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: "
50697c478bd9Sstevel@tonic-gate 		    "SA Access Failed");
50707c478bd9Sstevel@tonic-gate 		goto ibcm_join_mcg_exit;
50717c478bd9Sstevel@tonic-gate 	}
50727c478bd9Sstevel@tonic-gate 
50737c478bd9Sstevel@tonic-gate 	num_records = length/sizeof (sa_mcmember_record_t);
50747c478bd9Sstevel@tonic-gate 
50757c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_join_mcg: "
50767c478bd9Sstevel@tonic-gate 	    "Found %d MCMember Records", num_records);
50777c478bd9Sstevel@tonic-gate 
50787c478bd9Sstevel@tonic-gate 	/* Validate the returned number of records. */
50797c478bd9Sstevel@tonic-gate 	if ((mcg_resp != NULL) && (num_records > 0)) {
50807c478bd9Sstevel@tonic-gate 		/* Update the return values. */
50817c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_dgid = mcg_resp->MGID;
50827c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_sgid = mcg_resp->PortGID;
50837c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_srate = mcg_resp->Rate;
50847c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_srvl = mcg_resp->SL;
50857c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_flow = mcg_resp->FlowLabel;
50867c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_tclass = mcg_resp->TClass;
50877c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_hop = mcg_resp->HopLimit;
50887c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_send_grh = B_TRUE;
50897c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_dlid = mcg_resp->MLID;
50907c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_mtu = mcg_resp->MTU;
50917c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_qkey = mcg_resp->Q_Key;
50927c478bd9Sstevel@tonic-gate 
50937c478bd9Sstevel@tonic-gate 		retval = ibt_pkey2index_byguid(hca_port.hp_hca_guid,
50947c478bd9Sstevel@tonic-gate 		    hca_port.hp_port, mcg_resp->P_Key, &mcg_info_p->mc_pkey_ix);
50957c478bd9Sstevel@tonic-gate 		if (retval != IBT_SUCCESS) {
50967c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
50977c478bd9Sstevel@tonic-gate 			    "Pkey2Index Conversion failed<%d>", retval);
50987c478bd9Sstevel@tonic-gate 			mcg_info_p->mc_pkey_ix = 0;
50997c478bd9Sstevel@tonic-gate 		}
51007c478bd9Sstevel@tonic-gate 
51017c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_scope = mcg_resp->Scope;
51027c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_pkt_lt = mcg_resp->PacketLifeTime;
51037c478bd9Sstevel@tonic-gate 
51047c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_port_num = hca_port.hp_port;
51057c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_sgid_ix = hca_port.hp_sgid_ix;
51067c478bd9Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_src_path = 0;
51077c478bd9Sstevel@tonic-gate 
5108f07a6d2aSShantkumar Hiremath 		/* Add or Incr the matching MCG entry. */
5109f07a6d2aSShantkumar Hiremath 		ibcm_add_incr_mcg_entry(&mcg_req, mcg_resp);
51107c478bd9Sstevel@tonic-gate 		/* Deallocate the memory allocated by SA for mcg_resp. */
51117c478bd9Sstevel@tonic-gate 		kmem_free(mcg_resp, length);
5112f07a6d2aSShantkumar Hiremath 
51137c478bd9Sstevel@tonic-gate 		retval = IBT_SUCCESS;
51147c478bd9Sstevel@tonic-gate 	} else {
51157c478bd9Sstevel@tonic-gate 		retval = IBT_MCG_RECORDS_NOT_FOUND;
51167c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
51177c478bd9Sstevel@tonic-gate 		    "MCG RECORDS NOT FOUND");
51187c478bd9Sstevel@tonic-gate 	}
51197c478bd9Sstevel@tonic-gate 
51207c478bd9Sstevel@tonic-gate ibcm_join_mcg_exit:
51217c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
51227c478bd9Sstevel@tonic-gate 
51237c478bd9Sstevel@tonic-gate ibcm_join_mcg_exit1:
51247c478bd9Sstevel@tonic-gate 	if (mcg_arg->func)
51257c478bd9Sstevel@tonic-gate 		(*(mcg_arg->func))(mcg_arg->arg, retval, mcg_info_p);
51267c478bd9Sstevel@tonic-gate 
51277c478bd9Sstevel@tonic-gate 	kmem_free(mcg_arg, sizeof (ibcm_join_mcg_tqarg_t));
51287c478bd9Sstevel@tonic-gate 
51297c478bd9Sstevel@tonic-gate 	return (retval);
51307c478bd9Sstevel@tonic-gate }
51317c478bd9Sstevel@tonic-gate 
51327c478bd9Sstevel@tonic-gate 
51337c478bd9Sstevel@tonic-gate /*
51347c478bd9Sstevel@tonic-gate  * Function:
51357c478bd9Sstevel@tonic-gate  *	ibt_leave_mcg
51367c478bd9Sstevel@tonic-gate  * Input:
51377c478bd9Sstevel@tonic-gate  *	rgid		The request GID that defines the HCA port upon which
51387c478bd9Sstevel@tonic-gate  *			to send the request to the Subnet Administrator, to
51397c478bd9Sstevel@tonic-gate  *			remove the specified port (port_gid) from the multicast
51407c478bd9Sstevel@tonic-gate  *			group.  If 'port_gid' is the Reserved GID (i.e.
51417c478bd9Sstevel@tonic-gate  *			port_gid.gid_prefix = 0 and port_gid.gid_guid = 0),
51427c478bd9Sstevel@tonic-gate  *			then the end-port associated with 'rgid' is removed
51437c478bd9Sstevel@tonic-gate  *			from the multicast group.
51447c478bd9Sstevel@tonic-gate  *
51457c478bd9Sstevel@tonic-gate  *	mc_gid		A multicast group GID as returned from ibt_join_mcg()
51467c478bd9Sstevel@tonic-gate  *			call.  This is optional, if not specified (i.e.
51477c478bd9Sstevel@tonic-gate  *			mc_gid.gid_prefix has 0xFF in its upper 8 bits to
51487c478bd9Sstevel@tonic-gate  *			identify this as being a multicast GID), then the
51497c478bd9Sstevel@tonic-gate  *			port is removed from all the multicast groups of
51507c478bd9Sstevel@tonic-gate  *			which it is a member.
51517c478bd9Sstevel@tonic-gate  *
51527c478bd9Sstevel@tonic-gate  *	port_gid	This is optional, if not the Reserved GID (gid_prefix
51537c478bd9Sstevel@tonic-gate  *			and gid_guid not equal to 0), then this specifies the
51547c478bd9Sstevel@tonic-gate  *			endport GID of the multicast group member being deleted
51557c478bd9Sstevel@tonic-gate  *			from the group. If it is the Reserved GID (gid_prefix
51567c478bd9Sstevel@tonic-gate  *			and gid_guid equal to 0) then the member endport GID is
51577c478bd9Sstevel@tonic-gate  *			determined from 'rgid'.
51587c478bd9Sstevel@tonic-gate  *
51597c478bd9Sstevel@tonic-gate  *	mc_join_state	The Join State attribute used when the group was joined
51607c478bd9Sstevel@tonic-gate  *			using ibt_join_mcg(). This Join State component must
51617c478bd9Sstevel@tonic-gate  *			contains at least one bit set to 1 in the same position
51627c478bd9Sstevel@tonic-gate  *			as that used during ibt_join_mcg(). i.e. the logical
51637c478bd9Sstevel@tonic-gate  *			AND of the two JoinState components is not all zeros.
51647c478bd9Sstevel@tonic-gate  *			This Join State component must not have some bits set
51657c478bd9Sstevel@tonic-gate  *			which are not set using ibt_join_mcg().
51667c478bd9Sstevel@tonic-gate  * Output:
51677c478bd9Sstevel@tonic-gate  *	None.
51687c478bd9Sstevel@tonic-gate  * Returns:
51697c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
51707c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
51717c478bd9Sstevel@tonic-gate  *	IBT_MC_GROUP_INVALID
51727c478bd9Sstevel@tonic-gate  *	IBT_INSUFF_RESOURCE
51737c478bd9Sstevel@tonic-gate  * Description:
51747c478bd9Sstevel@tonic-gate  *	The port associated with the port GID shall be removed from the
51757c478bd9Sstevel@tonic-gate  *	multicast group specified by MGID (mc_gid) or from all the multicast
51767c478bd9Sstevel@tonic-gate  *	groups of which it is a member if the MGID (mc_gid) is not specified.
51777c478bd9Sstevel@tonic-gate  *
51787c478bd9Sstevel@tonic-gate  *	The last full member to leave causes the destruction of the Multicast
51797c478bd9Sstevel@tonic-gate  *	Group.
51807c478bd9Sstevel@tonic-gate  */
51817c478bd9Sstevel@tonic-gate ibt_status_t
ibt_leave_mcg(ib_gid_t rgid,ib_gid_t mc_gid,ib_gid_t port_gid,uint8_t mc_join_state)51827c478bd9Sstevel@tonic-gate ibt_leave_mcg(ib_gid_t rgid, ib_gid_t mc_gid, ib_gid_t port_gid,
51837c478bd9Sstevel@tonic-gate     uint8_t mc_join_state)
51847c478bd9Sstevel@tonic-gate {
51857c478bd9Sstevel@tonic-gate 	sa_mcmember_record_t	mcg_req;
51867c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
51877c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
51887c478bd9Sstevel@tonic-gate 	uint64_t		component_mask = 0;
51897c478bd9Sstevel@tonic-gate 	int			sa_retval;
51907c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
5191f07a6d2aSShantkumar Hiremath 	ibcm_status_t		ret;
51927c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hca_port;
51937c478bd9Sstevel@tonic-gate 	size_t			length;
51947c478bd9Sstevel@tonic-gate 	void			*results_p;
51957c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
5196f07a6d2aSShantkumar Hiremath 	uint8_t			jstate = 0;
51977c478bd9Sstevel@tonic-gate 
51987c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg(%llX:%llX, %llX:%llX)",
51997c478bd9Sstevel@tonic-gate 	    rgid.gid_prefix, rgid.gid_guid, mc_gid.gid_prefix, mc_gid.gid_guid);
52007c478bd9Sstevel@tonic-gate 
52017c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg(%llX:%llX, 0x%X)",
52027c478bd9Sstevel@tonic-gate 	    port_gid.gid_prefix, port_gid.gid_guid, mc_join_state);
52037c478bd9Sstevel@tonic-gate 
52047c478bd9Sstevel@tonic-gate 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
52057c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: RequestGID is required");
52067c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
52077c478bd9Sstevel@tonic-gate 	}
52087c478bd9Sstevel@tonic-gate 
52097c478bd9Sstevel@tonic-gate 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
52107c478bd9Sstevel@tonic-gate 
52117c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: MGID: %llX%llX",
52127c478bd9Sstevel@tonic-gate 	    mc_gid.gid_prefix, mc_gid.gid_guid);
52137c478bd9Sstevel@tonic-gate 
52147c478bd9Sstevel@tonic-gate 	/* Validate MGID */
52157c478bd9Sstevel@tonic-gate 	if ((mc_gid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
52167c478bd9Sstevel@tonic-gate 		mcg_req.MGID = mc_gid;
52177c478bd9Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_MGID;
52187c478bd9Sstevel@tonic-gate 	} else if ((mc_gid.gid_prefix != 0) || (mc_gid.gid_guid != 0)) {
52197c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Invalid MGID specified");
52207c478bd9Sstevel@tonic-gate 		return (IBT_MC_MGID_INVALID);
52217c478bd9Sstevel@tonic-gate 	}
52227c478bd9Sstevel@tonic-gate 
52237c478bd9Sstevel@tonic-gate 	if ((port_gid.gid_prefix == 0) || (port_gid.gid_guid == 0)) {
52247c478bd9Sstevel@tonic-gate 		mcg_req.PortGID = rgid;
52257c478bd9Sstevel@tonic-gate 	} else {
52267c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Performing PROXY Leave");
52277c478bd9Sstevel@tonic-gate 		mcg_req.PortGID = port_gid;
52287c478bd9Sstevel@tonic-gate 	}
52297c478bd9Sstevel@tonic-gate 	component_mask |= SA_MC_COMPMASK_PORTGID;
52307c478bd9Sstevel@tonic-gate 
52317c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Port GID <%llX:%llX>",
52327c478bd9Sstevel@tonic-gate 	    mcg_req.PortGID.gid_prefix, mcg_req.PortGID.gid_guid);
52337c478bd9Sstevel@tonic-gate 
52347c478bd9Sstevel@tonic-gate 	/* Join State */
52357c478bd9Sstevel@tonic-gate 	mcg_req.JoinState = mc_join_state;
52367c478bd9Sstevel@tonic-gate 	component_mask |= SA_MC_COMPMASK_JOINSTATE;
52377c478bd9Sstevel@tonic-gate 
5238f07a6d2aSShantkumar Hiremath 	ret = ibcm_del_decr_mcg_entry(&mcg_req, &jstate);
5239f07a6d2aSShantkumar Hiremath 	if (ret == IBCM_LOOKUP_EXISTS) {
5240f07a6d2aSShantkumar Hiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Multiple JoinMCG record "
5241f07a6d2aSShantkumar Hiremath 		    " still exists, we shall leave for last leave_mcg call");
5242f07a6d2aSShantkumar Hiremath 		return (IBT_SUCCESS);
5243f07a6d2aSShantkumar Hiremath 	} else if (ret == IBCM_LOOKUP_FAIL) {
5244f07a6d2aSShantkumar Hiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: No Record found, "
5245f07a6d2aSShantkumar Hiremath 		    "continue with leave_mcg call");
5246f07a6d2aSShantkumar Hiremath 	} else if ((ret == IBCM_SUCCESS) && (jstate != 0)) {
5247f07a6d2aSShantkumar Hiremath 		/*
5248f07a6d2aSShantkumar Hiremath 		 * Update with cached "jstate", as this will be OR'ed of
5249f07a6d2aSShantkumar Hiremath 		 * all ibt_join_mcg() calls for this record.
5250f07a6d2aSShantkumar Hiremath 		 */
5251f07a6d2aSShantkumar Hiremath 		mcg_req.JoinState = jstate;
5252f07a6d2aSShantkumar Hiremath 	}
5253f07a6d2aSShantkumar Hiremath 
52547c478bd9Sstevel@tonic-gate 	retval = ibtl_cm_get_hca_port(rgid, 0, &hca_port);
52557c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
52567c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: Failed to get port info "
52577c478bd9Sstevel@tonic-gate 		    "from specified RGID : status = %d", retval);
52587c478bd9Sstevel@tonic-gate 		return (retval);
52597c478bd9Sstevel@tonic-gate 	}
52607c478bd9Sstevel@tonic-gate 
52617c478bd9Sstevel@tonic-gate 	/* Get SA Access Handle. */
52627c478bd9Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(hca_port.hp_hca_guid);
52637c478bd9Sstevel@tonic-gate 	if (hcap == NULL) {
52647c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: "
52657c478bd9Sstevel@tonic-gate 		    "NO HCA found");
52667c478bd9Sstevel@tonic-gate 		return (IBT_HCA_BUSY_DETACHING);
52677c478bd9Sstevel@tonic-gate 	}
52687c478bd9Sstevel@tonic-gate 
52697c478bd9Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, hca_port.hp_port);
52707c478bd9Sstevel@tonic-gate 	if (saa_handle == NULL) {
52717c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: saa_handle is NULL");
52727c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
52737c478bd9Sstevel@tonic-gate 		return (IBT_HCA_PORT_NOT_ACTIVE);
52747c478bd9Sstevel@tonic-gate 	}
52757c478bd9Sstevel@tonic-gate 
52767c478bd9Sstevel@tonic-gate 	/* Contact SA Access */
52777c478bd9Sstevel@tonic-gate 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
52787c478bd9Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_DELETE;
52797c478bd9Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
52807c478bd9Sstevel@tonic-gate 	access_args.sq_template = &mcg_req;
52817c478bd9Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
52827c478bd9Sstevel@tonic-gate 	access_args.sq_callback = NULL;
52837c478bd9Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
52847c478bd9Sstevel@tonic-gate 
52857c478bd9Sstevel@tonic-gate 	ibcm_sa_access_enter();
52867c478bd9Sstevel@tonic-gate 
52877c478bd9Sstevel@tonic-gate 	sa_retval = ibmf_sa_access(saa_handle, &access_args, 0, &length,
52887c478bd9Sstevel@tonic-gate 	    &results_p);
52897c478bd9Sstevel@tonic-gate 	if (sa_retval != IBMF_SUCCESS) {
52907c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: SA access Failed: %d",
52917c478bd9Sstevel@tonic-gate 		    sa_retval);
52927c478bd9Sstevel@tonic-gate 		(void) ibcm_ibmf_analyze_error(sa_retval);
52937c478bd9Sstevel@tonic-gate 		retval = IBT_MC_GROUP_INVALID;
52947c478bd9Sstevel@tonic-gate 	}
52957c478bd9Sstevel@tonic-gate 
52967c478bd9Sstevel@tonic-gate 	ibcm_sa_access_exit();
52977c478bd9Sstevel@tonic-gate 
52987c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
52997c478bd9Sstevel@tonic-gate 
53007c478bd9Sstevel@tonic-gate 	return (retval);
53017c478bd9Sstevel@tonic-gate }
53027c478bd9Sstevel@tonic-gate 
53037c478bd9Sstevel@tonic-gate 
53047c478bd9Sstevel@tonic-gate /*
53057c478bd9Sstevel@tonic-gate  * Function:
53067c478bd9Sstevel@tonic-gate  *	ibt_query_mcg
53077c478bd9Sstevel@tonic-gate  * Input:
53087c478bd9Sstevel@tonic-gate  *	rgid		The request GID that defines the HCA port upon which
53097c478bd9Sstevel@tonic-gate  *			to send the request to the Subnet Administrator, to
53107c478bd9Sstevel@tonic-gate  *			retrieve Multicast Records matching attributes as
53117c478bd9Sstevel@tonic-gate  *			specified through 'mcg_attr' argument.
53127c478bd9Sstevel@tonic-gate  *
53137c478bd9Sstevel@tonic-gate  *	mcg_attr	NULL or a pointer to an ibt_mcg_attr_t structure that
53147c478bd9Sstevel@tonic-gate  *			specifies MCG attributes that are to be matched.
53157c478bd9Sstevel@tonic-gate  *			Attributes that are not required can be wild carded
53167c478bd9Sstevel@tonic-gate  *			by specifying as '0'.
53177c478bd9Sstevel@tonic-gate  *
53187c478bd9Sstevel@tonic-gate  *	mcgs_max_num	The maximum number of matching multicast groups to
53197c478bd9Sstevel@tonic-gate  *			return.  If zero, then all available matching multicast
53207c478bd9Sstevel@tonic-gate  *			groups are returned.
53217c478bd9Sstevel@tonic-gate  * Output:
53227c478bd9Sstevel@tonic-gate  *	mcgs_info_p	The address of an ibt_mcg_info_t pointer, where
53237c478bd9Sstevel@tonic-gate  *			multicast group information is returned. The actual
53247c478bd9Sstevel@tonic-gate  *			number of entries filled in the array is returned in
53257c478bd9Sstevel@tonic-gate  *			entries_p.
53267c478bd9Sstevel@tonic-gate  *
53277c478bd9Sstevel@tonic-gate  *	entries_p	The number of ibt_mcg_attr_t entries returned.
53287c478bd9Sstevel@tonic-gate  * Returns:
53297c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
53307c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
53317c478bd9Sstevel@tonic-gate  *	IBT_MCG_RECORDS_NOT_FOUND
53327c478bd9Sstevel@tonic-gate  * Description:
53337c478bd9Sstevel@tonic-gate  *	Request information on multicast groups that match the parameters
53347c478bd9Sstevel@tonic-gate  *	specified in mcg_attr. Information on each multicast group is returned
53357c478bd9Sstevel@tonic-gate  *	to the caller in the form of an array of ibt_mcg_info_t.
53367c478bd9Sstevel@tonic-gate  *	ibt_query_mcg() allocates the memory for this array and returns a
53377c478bd9Sstevel@tonic-gate  *	pointer to the array (mcgs_p) and the number of entries in the array
53387c478bd9Sstevel@tonic-gate  *	(entries_p). This memory should be freed by the client using
53397c478bd9Sstevel@tonic-gate  *	ibt_free_mcg_info().
53407c478bd9Sstevel@tonic-gate  */
53417c478bd9Sstevel@tonic-gate ibt_status_t
ibt_query_mcg(ib_gid_t rgid,ibt_mcg_attr_t * mcg_attr,uint_t mcgs_max_num,ibt_mcg_info_t ** mcgs_info_p,uint_t * entries_p)53427c478bd9Sstevel@tonic-gate ibt_query_mcg(ib_gid_t rgid, ibt_mcg_attr_t *mcg_attr, uint_t mcgs_max_num,
53437c478bd9Sstevel@tonic-gate     ibt_mcg_info_t **mcgs_info_p, uint_t *entries_p)
53447c478bd9Sstevel@tonic-gate {
53457c478bd9Sstevel@tonic-gate 	sa_mcmember_record_t	mcg_req;
53467c478bd9Sstevel@tonic-gate 	sa_mcmember_record_t	*mcg_resp;
53477c478bd9Sstevel@tonic-gate 	ibt_mcg_info_t		*mcg_infop;
53487c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
53497c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
53507c478bd9Sstevel@tonic-gate 	uint64_t		component_mask = 0;
53517c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
53527c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hport;
53537c478bd9Sstevel@tonic-gate 	uint_t			num_records;
53547c478bd9Sstevel@tonic-gate 	size_t			length;
53557c478bd9Sstevel@tonic-gate 	void			*results_p;
53567c478bd9Sstevel@tonic-gate 	ib_gid_t		port_gid;
53577c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
53587c478bd9Sstevel@tonic-gate 
53597c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg(%p, %d)", mcg_attr, mcgs_max_num);
53607c478bd9Sstevel@tonic-gate 
53617c478bd9Sstevel@tonic-gate 	if ((entries_p == NULL) || (mcgs_info_p == NULL)) {
53627c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: "
53637c478bd9Sstevel@tonic-gate 		    "entries_p or mcgs_info_p is NULL");
53647c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
53657c478bd9Sstevel@tonic-gate 	}
53667c478bd9Sstevel@tonic-gate 
53677c478bd9Sstevel@tonic-gate 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
53687c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: RequestGID is required");
53697c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
53707c478bd9Sstevel@tonic-gate 	}
53717c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: Request GID <%llX:%llX>",
53727c478bd9Sstevel@tonic-gate 	    rgid.gid_prefix, rgid.gid_guid);
53737c478bd9Sstevel@tonic-gate 
53747c478bd9Sstevel@tonic-gate 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
53757c478bd9Sstevel@tonic-gate 	port_gid.gid_prefix = port_gid.gid_guid = 0;
53767c478bd9Sstevel@tonic-gate 
53777c478bd9Sstevel@tonic-gate 	if (mcg_attr != NULL) {
53787c478bd9Sstevel@tonic-gate 		port_gid = mcg_attr->mc_pgid;
53797c478bd9Sstevel@tonic-gate 
53807c478bd9Sstevel@tonic-gate 		if ((port_gid.gid_prefix != 0) && (port_gid.gid_guid != 0)) {
53817c478bd9Sstevel@tonic-gate 			mcg_req.PortGID = mcg_attr->mc_pgid;
53827c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_PORTGID;
53837c478bd9Sstevel@tonic-gate 
53847c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: PGID %llX:%llX",
53857c478bd9Sstevel@tonic-gate 			    port_gid.gid_prefix, port_gid.gid_guid);
53867c478bd9Sstevel@tonic-gate 		}
53877c478bd9Sstevel@tonic-gate 
53887c478bd9Sstevel@tonic-gate 		/* Is Q_Key specified. */
53897c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_qkey != 0) {
53907c478bd9Sstevel@tonic-gate 			mcg_req.Q_Key = mcg_attr->mc_qkey;
53917c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_QKEY;
53927c478bd9Sstevel@tonic-gate 		}
53937c478bd9Sstevel@tonic-gate 
53947c478bd9Sstevel@tonic-gate 		/* Is P_Key specified. */
53957c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_pkey != 0) {
53967c478bd9Sstevel@tonic-gate 			mcg_req.P_Key = mcg_attr->mc_pkey;
53977c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_PKEY;
53987c478bd9Sstevel@tonic-gate 		}
53997c478bd9Sstevel@tonic-gate 
54007c478bd9Sstevel@tonic-gate 		/* Is MGID specified. */
54017c478bd9Sstevel@tonic-gate 		if ((mcg_attr->mc_mgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
54027c478bd9Sstevel@tonic-gate 			mcg_req.MGID = mcg_attr->mc_mgid;
54037c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_MGID;
54047c478bd9Sstevel@tonic-gate 		}
54057c478bd9Sstevel@tonic-gate 
54067c478bd9Sstevel@tonic-gate 		/* Is MTU specified. */
54077c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_mtu_req.r_mtu) {
54087c478bd9Sstevel@tonic-gate 			mcg_req.MTU = mcg_attr->mc_mtu_req.r_mtu;
54097c478bd9Sstevel@tonic-gate 			mcg_req.MTUSelector = mcg_attr->mc_mtu_req.r_selector;
54107c478bd9Sstevel@tonic-gate 
54117c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_MTUSELECTOR |
54127c478bd9Sstevel@tonic-gate 			    SA_MC_COMPMASK_MTU;
54137c478bd9Sstevel@tonic-gate 		}
54147c478bd9Sstevel@tonic-gate 
54157c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_tclass) {
54167c478bd9Sstevel@tonic-gate 			mcg_req.TClass = mcg_attr->mc_tclass;
54177c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_TCLASS;
54187c478bd9Sstevel@tonic-gate 		}
54197c478bd9Sstevel@tonic-gate 
54207c478bd9Sstevel@tonic-gate 		/* Is RATE specified. */
54217c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_rate_req.r_srate) {
54227c478bd9Sstevel@tonic-gate 			mcg_req.Rate = mcg_attr->mc_rate_req.r_srate;
54237c478bd9Sstevel@tonic-gate 			mcg_req.RateSelector = mcg_attr->mc_rate_req.r_selector;
54247c478bd9Sstevel@tonic-gate 
54257c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_RATESELECTOR |
54267c478bd9Sstevel@tonic-gate 			    SA_MC_COMPMASK_RATE;
54277c478bd9Sstevel@tonic-gate 		}
54287c478bd9Sstevel@tonic-gate 
54297c478bd9Sstevel@tonic-gate 		/* Is Packet Life Time specified. */
54307c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_pkt_lt_req.p_pkt_lt) {
54317c478bd9Sstevel@tonic-gate 			mcg_req.Rate = mcg_attr->mc_pkt_lt_req.p_pkt_lt;
54327c478bd9Sstevel@tonic-gate 			mcg_req.RateSelector =
54337c478bd9Sstevel@tonic-gate 			    mcg_attr->mc_pkt_lt_req.p_selector;
54347c478bd9Sstevel@tonic-gate 
54357c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_PKTLTSELECTOR |
54367c478bd9Sstevel@tonic-gate 			    SA_MC_COMPMASK_PKTLT;
54377c478bd9Sstevel@tonic-gate 		}
54387c478bd9Sstevel@tonic-gate 
54397c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_hop) {
54407c478bd9Sstevel@tonic-gate 			mcg_req.HopLimit = mcg_attr->mc_hop;
54417c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_HOPLIMIT;
54427c478bd9Sstevel@tonic-gate 		}
54437c478bd9Sstevel@tonic-gate 
54447c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_flow) {
54457c478bd9Sstevel@tonic-gate 			mcg_req.FlowLabel = mcg_attr->mc_flow;
54467c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_FLOWLABEL;
54477c478bd9Sstevel@tonic-gate 		}
54487c478bd9Sstevel@tonic-gate 
54497c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_sl) {
54507c478bd9Sstevel@tonic-gate 			mcg_req.SL = mcg_attr->mc_sl;
54517c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_SL;
54527c478bd9Sstevel@tonic-gate 		}
54537c478bd9Sstevel@tonic-gate 
54547c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_scope) {
54557c478bd9Sstevel@tonic-gate 			mcg_req.Scope = mcg_attr->mc_scope;
54567c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_SCOPE;
54577c478bd9Sstevel@tonic-gate 		}
54587c478bd9Sstevel@tonic-gate 
54597c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_join_state) {
54607c478bd9Sstevel@tonic-gate 			mcg_req.JoinState = mcg_attr->mc_join_state;
54617c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_JOINSTATE;
54627c478bd9Sstevel@tonic-gate 		}
54637c478bd9Sstevel@tonic-gate 
54647c478bd9Sstevel@tonic-gate 		if (mcg_attr->mc_mlid) {
54657c478bd9Sstevel@tonic-gate 			mcg_req.MLID = mcg_attr->mc_mlid;
54667c478bd9Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_MLID;
54677c478bd9Sstevel@tonic-gate 		}
54687c478bd9Sstevel@tonic-gate 	}
54697c478bd9Sstevel@tonic-gate 
54707c478bd9Sstevel@tonic-gate 	retval = ibtl_cm_get_hca_port(rgid, 0, &hport);
54717c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
54727c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: Failed to get port info "
54737c478bd9Sstevel@tonic-gate 		    "from specified RGID : status = %d", retval);
54747c478bd9Sstevel@tonic-gate 		return (retval);
54757c478bd9Sstevel@tonic-gate 	}
54767c478bd9Sstevel@tonic-gate 
54777c478bd9Sstevel@tonic-gate 	/* Get SA Access Handle. */
54787c478bd9Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(hport.hp_hca_guid);
54797c478bd9Sstevel@tonic-gate 	if (hcap == NULL) {
54807c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: NO HCA found");
54817c478bd9Sstevel@tonic-gate 		return (IBT_HCA_BUSY_DETACHING);
54827c478bd9Sstevel@tonic-gate 	}
54837c478bd9Sstevel@tonic-gate 
54847c478bd9Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, hport.hp_port);
54857c478bd9Sstevel@tonic-gate 	if (saa_handle == NULL) {
54867c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: saa_handle is NULL");
54877c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
54887c478bd9Sstevel@tonic-gate 		return (IBT_HCA_PORT_NOT_ACTIVE);
54897c478bd9Sstevel@tonic-gate 	}
54907c478bd9Sstevel@tonic-gate 
54917c478bd9Sstevel@tonic-gate 	/* Contact SA Access */
54927c478bd9Sstevel@tonic-gate 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
54937c478bd9Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
54947c478bd9Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
54957c478bd9Sstevel@tonic-gate 	access_args.sq_template = &mcg_req;
54967c478bd9Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
54977c478bd9Sstevel@tonic-gate 	access_args.sq_callback = NULL;
54987c478bd9Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
54997c478bd9Sstevel@tonic-gate 
55007c478bd9Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
55017c478bd9Sstevel@tonic-gate 	    &results_p);
55027c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
55037c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: SA access Failed");
55047c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
55057c478bd9Sstevel@tonic-gate 		return (retval);
55067c478bd9Sstevel@tonic-gate 	}
55077c478bd9Sstevel@tonic-gate 
55087c478bd9Sstevel@tonic-gate 	num_records = length/sizeof (sa_mcmember_record_t);
55097c478bd9Sstevel@tonic-gate 
55107c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: Found %d MCMember Records",
55117c478bd9Sstevel@tonic-gate 	    num_records);
55127c478bd9Sstevel@tonic-gate 
55137c478bd9Sstevel@tonic-gate 	/* Validate the returned number of records. */
55147c478bd9Sstevel@tonic-gate 	if ((results_p != NULL) && (num_records > 0)) {
55157c478bd9Sstevel@tonic-gate 		uint_t	i;
55167c478bd9Sstevel@tonic-gate 
55177c478bd9Sstevel@tonic-gate 		/*
55187c478bd9Sstevel@tonic-gate 		 * If mcgs_max_num is zero, then return all records else
55197c478bd9Sstevel@tonic-gate 		 * return only requested number of records
55207c478bd9Sstevel@tonic-gate 		 */
55217c478bd9Sstevel@tonic-gate 		if ((mcgs_max_num != 0) && (num_records > mcgs_max_num)) {
55227c478bd9Sstevel@tonic-gate 			/* we are interested in only mcgs_max_num records */
55237c478bd9Sstevel@tonic-gate 			num_records = mcgs_max_num;
55247c478bd9Sstevel@tonic-gate 		}
55257c478bd9Sstevel@tonic-gate 
55267c478bd9Sstevel@tonic-gate 		/*
55277c478bd9Sstevel@tonic-gate 		 * The SGID returned in "mcg_info_p" buffer should be PortGID,
55287c478bd9Sstevel@tonic-gate 		 * (mcg_attr->mc_pgid), if 'mcg_attr->mc_pgid' was specified,
55297c478bd9Sstevel@tonic-gate 		 * else RequestGID (rgid) should be returned.
55307c478bd9Sstevel@tonic-gate 		 */
55317c478bd9Sstevel@tonic-gate 		if ((port_gid.gid_prefix != 0) && (port_gid.gid_guid != 0)) {
55327c478bd9Sstevel@tonic-gate 
55337c478bd9Sstevel@tonic-gate 			/* Get sgid_ix and port number of 'port_gid' */
55347c478bd9Sstevel@tonic-gate 			retval = ibtl_cm_get_hca_port(port_gid, 0, &hport);
55357c478bd9Sstevel@tonic-gate 			if (retval != IBT_SUCCESS) {
55367c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: "
55377c478bd9Sstevel@tonic-gate 				    "Failed to Get Portinfo for PortGID :"
55387c478bd9Sstevel@tonic-gate 				    "status = %d", retval);
55397c478bd9Sstevel@tonic-gate 				return (retval);
55407c478bd9Sstevel@tonic-gate 			}
55417c478bd9Sstevel@tonic-gate 		} else {
55427c478bd9Sstevel@tonic-gate 			/*
55437c478bd9Sstevel@tonic-gate 			 * The sgid_ix and port number related to RequestGID
55447c478bd9Sstevel@tonic-gate 			 * are already obtained at the beginning.
55457c478bd9Sstevel@tonic-gate 			 */
55467c478bd9Sstevel@tonic-gate 			port_gid = rgid;
55477c478bd9Sstevel@tonic-gate 		}
55487c478bd9Sstevel@tonic-gate 
55497c478bd9Sstevel@tonic-gate 		/*
55507c478bd9Sstevel@tonic-gate 		 * Allocate memory for return buffer, to be freed in
55517c478bd9Sstevel@tonic-gate 		 * ibt_free_mcg_info().
55527c478bd9Sstevel@tonic-gate 		 */
55537c478bd9Sstevel@tonic-gate 		mcg_infop = kmem_alloc((num_records * sizeof (ibt_mcg_info_t)),
55547c478bd9Sstevel@tonic-gate 		    KM_SLEEP);
55557c478bd9Sstevel@tonic-gate 
55567c478bd9Sstevel@tonic-gate 		*mcgs_info_p = mcg_infop;
55577c478bd9Sstevel@tonic-gate 		*entries_p = num_records;
55587c478bd9Sstevel@tonic-gate 
55597c478bd9Sstevel@tonic-gate 		/* Update the return values. */
55607c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_records; i++) {
55617c478bd9Sstevel@tonic-gate 
55627c478bd9Sstevel@tonic-gate 			mcg_resp = (sa_mcmember_record_t *)((uchar_t *)
55637c478bd9Sstevel@tonic-gate 			    results_p + i * sizeof (sa_mcmember_record_t));
55647c478bd9Sstevel@tonic-gate 
55657c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_dgid = mcg_resp->MGID;
55667c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_sgid = port_gid;
55677c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_srate = mcg_resp->Rate;
55687c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_srvl = mcg_resp->SL;
55697c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_flow = mcg_resp->FlowLabel;
55707c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_tclass = mcg_resp->TClass;
55717c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_hop = mcg_resp->HopLimit;
55727c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_port_num = hport.hp_port;
55737c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_send_grh = B_TRUE;
55747c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_dlid = mcg_resp->MLID;
55757c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_sgid_ix = hport.hp_sgid_ix;
55767c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_src_path = 0;
55777c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_mtu = mcg_resp->MTU;
55787c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_qkey = mcg_resp->Q_Key;
55797c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_scope = mcg_resp->Scope;
55807c478bd9Sstevel@tonic-gate 			mcg_infop[i].mc_pkt_lt = mcg_resp->PacketLifeTime;
55817c478bd9Sstevel@tonic-gate 
55827c478bd9Sstevel@tonic-gate 			if (ibt_pkey2index_byguid(hport.hp_hca_guid,
55837c478bd9Sstevel@tonic-gate 			    hport.hp_port, mcg_resp->P_Key,
55847c478bd9Sstevel@tonic-gate 			    &mcg_infop[i].mc_pkey_ix) != IBT_SUCCESS) {
55857c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: "
55867c478bd9Sstevel@tonic-gate 				    "Pkey2Index Conversion failed");
55877c478bd9Sstevel@tonic-gate 				mcg_infop[i].mc_pkey_ix = 0;
55887c478bd9Sstevel@tonic-gate 			}
55897c478bd9Sstevel@tonic-gate 		}
55907c478bd9Sstevel@tonic-gate 
55917c478bd9Sstevel@tonic-gate 		/*
55927c478bd9Sstevel@tonic-gate 		 * Deallocate the memory allocated by SA for results_p.
55937c478bd9Sstevel@tonic-gate 		 */
55947c478bd9Sstevel@tonic-gate 		kmem_free(results_p, length);
55957c478bd9Sstevel@tonic-gate 		retval = IBT_SUCCESS;
55967c478bd9Sstevel@tonic-gate 
55977c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: returning %d MCGRecords",
55987c478bd9Sstevel@tonic-gate 		    num_records);
55997c478bd9Sstevel@tonic-gate 
56007c478bd9Sstevel@tonic-gate 	} else {
56017c478bd9Sstevel@tonic-gate 		retval = IBT_MCG_RECORDS_NOT_FOUND;
56027c478bd9Sstevel@tonic-gate 		*entries_p = 0;
56037c478bd9Sstevel@tonic-gate 
56047c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: MCG RECORDS NOT FOUND");
56057c478bd9Sstevel@tonic-gate 	}
56067c478bd9Sstevel@tonic-gate 
56077c478bd9Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
56087c478bd9Sstevel@tonic-gate 
56097c478bd9Sstevel@tonic-gate 	return (retval);
56107c478bd9Sstevel@tonic-gate }
56117c478bd9Sstevel@tonic-gate 
56127c478bd9Sstevel@tonic-gate 
56137c478bd9Sstevel@tonic-gate /*
56147c478bd9Sstevel@tonic-gate  * ibt_free_mcg_info()
56157c478bd9Sstevel@tonic-gate  *	Free the memory allocated by successful ibt_query_mcg()
56167c478bd9Sstevel@tonic-gate  *
56177c478bd9Sstevel@tonic-gate  *	mcgs_info	Pointer returned by ibt_query_mcg().
56187c478bd9Sstevel@tonic-gate  *
56197c478bd9Sstevel@tonic-gate  *	entries		The number of ibt_mcg_info_t entries to free.
56207c478bd9Sstevel@tonic-gate  */
56217c478bd9Sstevel@tonic-gate void
ibt_free_mcg_info(ibt_mcg_info_t * mcgs_info,uint_t entries)56227c478bd9Sstevel@tonic-gate ibt_free_mcg_info(ibt_mcg_info_t *mcgs_info, uint_t entries)
56237c478bd9Sstevel@tonic-gate {
56247c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_free_mcg_info: "
56257c478bd9Sstevel@tonic-gate 	    "Free <%d> entries from 0x%p", entries, mcgs_info);
56267c478bd9Sstevel@tonic-gate 
56277c478bd9Sstevel@tonic-gate 	if ((mcgs_info != NULL) && (entries > 0))
56287c478bd9Sstevel@tonic-gate 		kmem_free(mcgs_info, entries * sizeof (ibt_mcg_info_t));
56297c478bd9Sstevel@tonic-gate 	else
56307c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_free_mcg_info: "
56317c478bd9Sstevel@tonic-gate 		    "ERROR: NULL buf pointer or length specified.");
56327c478bd9Sstevel@tonic-gate }
56337c478bd9Sstevel@tonic-gate 
56347c478bd9Sstevel@tonic-gate 
56357c478bd9Sstevel@tonic-gate /*
56367c478bd9Sstevel@tonic-gate  * Function:
56377c478bd9Sstevel@tonic-gate  *	ibt_gid_to_node_info()
56387c478bd9Sstevel@tonic-gate  * Input:
56397c478bd9Sstevel@tonic-gate  *	gid		Identifies the IB Node and port for which to obtain
56407c478bd9Sstevel@tonic-gate  *			Node information.
56417c478bd9Sstevel@tonic-gate  * Output:
56427c478bd9Sstevel@tonic-gate  *	node_info_p	A pointer to an ibt_node_info_t structure (allocated
56437c478bd9Sstevel@tonic-gate  *			by the caller) in which to return the node information.
56447c478bd9Sstevel@tonic-gate  * Returns:
56457c478bd9Sstevel@tonic-gate  *	IBT_SUCCESS
56467c478bd9Sstevel@tonic-gate  *	IBT_INVALID_PARAM
56477c478bd9Sstevel@tonic-gate  *	IBT_NODE_RECORDS_NOT_FOUND
56487c478bd9Sstevel@tonic-gate  *	IBT_NO_HCAS_AVAILABLE
56497c478bd9Sstevel@tonic-gate  * Description:
56507c478bd9Sstevel@tonic-gate  *	Retrieve Node Information for the specified GID.
56517c478bd9Sstevel@tonic-gate  */
56527c478bd9Sstevel@tonic-gate ibt_status_t
ibt_gid_to_node_info(ib_gid_t gid,ibt_node_info_t * node_info_p)56537c478bd9Sstevel@tonic-gate ibt_gid_to_node_info(ib_gid_t gid, ibt_node_info_t *node_info_p)
56547c478bd9Sstevel@tonic-gate {
56557c478bd9Sstevel@tonic-gate 	sa_node_record_t	nr_req, *nr_resp;
56567c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
56577c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
56587c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
56597c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hport;
56607c478bd9Sstevel@tonic-gate 	int			i, j;
56617c478bd9Sstevel@tonic-gate 	uint_t			num_rec;
56627c478bd9Sstevel@tonic-gate 	ib_guid_t		*guid_array = NULL;
56637c478bd9Sstevel@tonic-gate 	sa_path_record_t	*path;
56647c478bd9Sstevel@tonic-gate 	size_t			len;
56657c478bd9Sstevel@tonic-gate 	uint8_t			npaths;
56667c478bd9Sstevel@tonic-gate 	uint32_t		num_hcas = 0;
56677c478bd9Sstevel@tonic-gate 	ib_lid_t		node_lid;
56687c478bd9Sstevel@tonic-gate 	boolean_t		local_node = B_FALSE;
56697c478bd9Sstevel@tonic-gate 	void			*res_p;
56707c478bd9Sstevel@tonic-gate 	uint8_t			num_ports = 0;
56717c478bd9Sstevel@tonic-gate 
56727c478bd9Sstevel@tonic-gate 
56737c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info(%llX:%llX, %p)",
56747c478bd9Sstevel@tonic-gate 	    gid.gid_prefix, gid.gid_guid, node_info_p);
56757c478bd9Sstevel@tonic-gate 
56767c478bd9Sstevel@tonic-gate 	if ((gid.gid_prefix == 0) || (gid.gid_guid == 0)) {
56777c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: GID is required");
56787c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
56797c478bd9Sstevel@tonic-gate 	}
56807c478bd9Sstevel@tonic-gate 
56817c478bd9Sstevel@tonic-gate 	if (node_info_p == NULL) {
56827c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
56837c478bd9Sstevel@tonic-gate 		    "Return Buf (node_info_p) is NULL.");
56847c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
56857c478bd9Sstevel@tonic-gate 	}
56867c478bd9Sstevel@tonic-gate 
56877c478bd9Sstevel@tonic-gate 	/*
56887c478bd9Sstevel@tonic-gate 	 * If 'gid' is on local node, then get node lid (i.e. base lid of the
56897c478bd9Sstevel@tonic-gate 	 * associated port) info via ibtl_cm_get_hca_port() call.
56907c478bd9Sstevel@tonic-gate 	 */
56917c478bd9Sstevel@tonic-gate 	bzero(&hport, sizeof (ibtl_cm_hca_port_t));
56927c478bd9Sstevel@tonic-gate 	if (ibtl_cm_get_hca_port(gid, 0, &hport) == IBT_SUCCESS) {
56937c478bd9Sstevel@tonic-gate 
56947c478bd9Sstevel@tonic-gate 		hcap = ibcm_find_hca_entry(hport.hp_hca_guid);
56957c478bd9Sstevel@tonic-gate 		if (hcap == NULL) {
56967c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
56977c478bd9Sstevel@tonic-gate 			    "HCA(%llX) info not found", hport.hp_hca_guid);
56987c478bd9Sstevel@tonic-gate 			return (IBT_NO_HCAS_AVAILABLE);
56997c478bd9Sstevel@tonic-gate 		}
57007c478bd9Sstevel@tonic-gate 		num_ports = 1;
57017c478bd9Sstevel@tonic-gate 		num_hcas = 1;
57027c478bd9Sstevel@tonic-gate 		node_lid = hport.hp_base_lid;
57037c478bd9Sstevel@tonic-gate 		local_node = B_TRUE;
57047c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info: Local Node: "
57057c478bd9Sstevel@tonic-gate 		    "LID = 0x%X", node_lid);
57067c478bd9Sstevel@tonic-gate 	} else {
57077c478bd9Sstevel@tonic-gate 		/* Get the number of HCAs and their GUIDs */
57087c478bd9Sstevel@tonic-gate 		num_hcas = ibt_get_hca_list(&guid_array);
57097c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info: ibt_get_hca_list "
57107c478bd9Sstevel@tonic-gate 		    "returned %d hcas", num_hcas);
57117c478bd9Sstevel@tonic-gate 
57127c478bd9Sstevel@tonic-gate 		if (num_hcas == 0) {
57137c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
57147c478bd9Sstevel@tonic-gate 			    "NO HCA's Found on this system");
57157c478bd9Sstevel@tonic-gate 			return (IBT_NO_HCAS_AVAILABLE);
57167c478bd9Sstevel@tonic-gate 		}
57177c478bd9Sstevel@tonic-gate 	}
57187c478bd9Sstevel@tonic-gate 
57197c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_hcas; i++) {
57207c478bd9Sstevel@tonic-gate 		if (local_node == B_FALSE) {
57217c478bd9Sstevel@tonic-gate 			hcap = ibcm_find_hca_entry(guid_array[i]);
57227c478bd9Sstevel@tonic-gate 			if (hcap == NULL) {
57237c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
57247c478bd9Sstevel@tonic-gate 				    "HCA(%llX) info not found", guid_array[i]);
57257c478bd9Sstevel@tonic-gate 				retval = IBT_NO_HCAS_AVAILABLE;
57267c478bd9Sstevel@tonic-gate 				continue;
57277c478bd9Sstevel@tonic-gate 			}
57287c478bd9Sstevel@tonic-gate 			num_ports = hcap->hca_num_ports;
57297c478bd9Sstevel@tonic-gate 		}
57307c478bd9Sstevel@tonic-gate 
57317c478bd9Sstevel@tonic-gate 		for (j = 0; j < num_ports; j++) {
57327c478bd9Sstevel@tonic-gate 			uint8_t		port = 0;
57337c478bd9Sstevel@tonic-gate 
57347c478bd9Sstevel@tonic-gate 			if (local_node == B_TRUE)
57357c478bd9Sstevel@tonic-gate 				port = hport.hp_port;
57367c478bd9Sstevel@tonic-gate 			else
57377c478bd9Sstevel@tonic-gate 				port = j + 1;
57387c478bd9Sstevel@tonic-gate 
57397c478bd9Sstevel@tonic-gate 			/* Get SA Access Handle. */
57407c478bd9Sstevel@tonic-gate 			saa_handle = ibcm_get_saa_handle(hcap, port);
57417c478bd9Sstevel@tonic-gate 			if (saa_handle == NULL) {
57427c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
57437c478bd9Sstevel@tonic-gate 				    "Port %d of HCA (%llX) is NOT ACTIVE",
57447c478bd9Sstevel@tonic-gate 				    port, hport.hp_hca_guid);
57457c478bd9Sstevel@tonic-gate 				retval = IBT_NODE_RECORDS_NOT_FOUND;
57467c478bd9Sstevel@tonic-gate 				continue;
57477c478bd9Sstevel@tonic-gate 			}
57487c478bd9Sstevel@tonic-gate 
57497c478bd9Sstevel@tonic-gate 			if (local_node == B_FALSE) {
57507c478bd9Sstevel@tonic-gate 				ib_gid_t	sgid;
57517c478bd9Sstevel@tonic-gate 				int		sa_ret;
57527c478bd9Sstevel@tonic-gate 
57537c478bd9Sstevel@tonic-gate 				/*
57547c478bd9Sstevel@tonic-gate 				 * Check whether 'gid' and this port has same
57557c478bd9Sstevel@tonic-gate 				 * subnet prefix. If not, then there is no use
57567c478bd9Sstevel@tonic-gate 				 * in searching from this port.
57577c478bd9Sstevel@tonic-gate 				 */
57587c478bd9Sstevel@tonic-gate 				sgid = hcap->hca_port_info[j].port_sgid0;
57597c478bd9Sstevel@tonic-gate 				if (gid.gid_prefix != sgid.gid_prefix) {
57607c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L3(cmlog,
57617c478bd9Sstevel@tonic-gate 					    "ibt_gid_to_node_info:Sn_Prefix of "
57627c478bd9Sstevel@tonic-gate 					    "GID(%llX) and Port's(%llX) differ",
57637c478bd9Sstevel@tonic-gate 					    gid.gid_prefix, sgid.gid_prefix);
57647c478bd9Sstevel@tonic-gate 					retval = IBT_NODE_RECORDS_NOT_FOUND;
57657c478bd9Sstevel@tonic-gate 					continue;
57667c478bd9Sstevel@tonic-gate 				}
57677c478bd9Sstevel@tonic-gate 
57687c478bd9Sstevel@tonic-gate 				/*
57697c478bd9Sstevel@tonic-gate 				 * First Get Path Records for the specified DGID
57707c478bd9Sstevel@tonic-gate 				 * from this port (SGID). From Path Records,
57717c478bd9Sstevel@tonic-gate 				 * note down DLID, then use this DLID as Input
57727c478bd9Sstevel@tonic-gate 				 * attribute to get NodeRecords from SA Access.
57737c478bd9Sstevel@tonic-gate 				 */
57747c478bd9Sstevel@tonic-gate 				npaths = 1;
57757c478bd9Sstevel@tonic-gate 				path = NULL;
57767c478bd9Sstevel@tonic-gate 
57777c478bd9Sstevel@tonic-gate 				sa_ret = ibmf_saa_gid_to_pathrecords(saa_handle,
57787c478bd9Sstevel@tonic-gate 				    sgid, gid, 0, 0, B_TRUE, &npaths, 0, &len,
57797c478bd9Sstevel@tonic-gate 				    &path);
57807c478bd9Sstevel@tonic-gate 				if (sa_ret != IBMF_SUCCESS) {
57817c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
57827c478bd9Sstevel@tonic-gate 					    "ibt_gid_to_node_info: "
57837c478bd9Sstevel@tonic-gate 					    "ibmf_saa_gid_to_pathrecords() "
57847c478bd9Sstevel@tonic-gate 					    "returned error: %d ", sa_ret);
57857c478bd9Sstevel@tonic-gate 					retval =
57867c478bd9Sstevel@tonic-gate 					    ibcm_ibmf_analyze_error(sa_ret);
57877c478bd9Sstevel@tonic-gate 					continue;
57887c478bd9Sstevel@tonic-gate 				} else if ((npaths == 0) || (path == NULL)) {
57897c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L3(cmlog,
57907c478bd9Sstevel@tonic-gate 					    "ibt_gid_to_node_info: failed (%d) "
57917c478bd9Sstevel@tonic-gate 					    "to get path records for the DGID "
57927c478bd9Sstevel@tonic-gate 					    "0x%llX from SGID 0x%llX", sa_ret,
57937c478bd9Sstevel@tonic-gate 					    gid.gid_guid, sgid.gid_guid);
57947c478bd9Sstevel@tonic-gate 					retval = IBT_NODE_RECORDS_NOT_FOUND;
57957c478bd9Sstevel@tonic-gate 					continue;
57967c478bd9Sstevel@tonic-gate 				}
57977c478bd9Sstevel@tonic-gate 				node_lid = path->DLID;	/* LID */
57987c478bd9Sstevel@tonic-gate 
57997c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
58007c478bd9Sstevel@tonic-gate 				    "Remote Node: LID = 0x%X", node_lid);
58017c478bd9Sstevel@tonic-gate 
58027c478bd9Sstevel@tonic-gate 				/* Free SA_Access memory for path record. */
58037c478bd9Sstevel@tonic-gate 				kmem_free(path, len);
58047c478bd9Sstevel@tonic-gate 			}
58057c478bd9Sstevel@tonic-gate 
58067c478bd9Sstevel@tonic-gate 			/* Retrieve Node Records from SA Access. */
58077c478bd9Sstevel@tonic-gate 			bzero(&nr_req, sizeof (sa_node_record_t));
58087c478bd9Sstevel@tonic-gate 
58097c478bd9Sstevel@tonic-gate 			nr_req.LID = node_lid;	/* LID */
58107c478bd9Sstevel@tonic-gate 
58117c478bd9Sstevel@tonic-gate 			retval = ibcm_get_node_rec(saa_handle, &nr_req,
58127c478bd9Sstevel@tonic-gate 			    SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
58137c478bd9Sstevel@tonic-gate 			if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
58147c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
58157c478bd9Sstevel@tonic-gate 				    "failed (%d) to get Node records", retval);
58167c478bd9Sstevel@tonic-gate 				continue;
58177c478bd9Sstevel@tonic-gate 			} else if (retval != IBT_SUCCESS) {
58187c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
58197c478bd9Sstevel@tonic-gate 				    "failed (%d) to get Node records", retval);
58207c478bd9Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
58217c478bd9Sstevel@tonic-gate 				goto gid_to_ni_exit;
58227c478bd9Sstevel@tonic-gate 			}
58237c478bd9Sstevel@tonic-gate 
58247c478bd9Sstevel@tonic-gate 			num_rec = len/sizeof (sa_node_record_t);
58257c478bd9Sstevel@tonic-gate 			nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
58267c478bd9Sstevel@tonic-gate 
58277c478bd9Sstevel@tonic-gate 			/* Validate the returned number of records. */
58287c478bd9Sstevel@tonic-gate 			if ((nr_resp != NULL) && (num_rec > 0)) {
58297c478bd9Sstevel@tonic-gate 
58307c478bd9Sstevel@tonic-gate 				IBCM_DUMP_NODE_REC(nr_resp);
58317c478bd9Sstevel@tonic-gate 
58327c478bd9Sstevel@tonic-gate 				_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
58337c478bd9Sstevel@tonic-gate 				    *node_info_p))
58347c478bd9Sstevel@tonic-gate 
58357c478bd9Sstevel@tonic-gate 				node_info_p->n_sys_img_guid =
58367c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.SystemImageGUID;
58377c478bd9Sstevel@tonic-gate 				node_info_p->n_node_guid =
58387c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.NodeGUID;
58397c478bd9Sstevel@tonic-gate 				node_info_p->n_port_guid =
58407c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.PortGUID;
58417c478bd9Sstevel@tonic-gate 				node_info_p->n_dev_id =
58427c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.DeviceID;
58437c478bd9Sstevel@tonic-gate 				node_info_p->n_revision =
58447c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.Revision;
58457c478bd9Sstevel@tonic-gate 				node_info_p->n_vendor_id =
58467c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.VendorID;
58477c478bd9Sstevel@tonic-gate 				node_info_p->n_num_ports =
58487c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.NumPorts;
58497c478bd9Sstevel@tonic-gate 				node_info_p->n_port_num =
58507c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.LocalPortNum;
58517c478bd9Sstevel@tonic-gate 				node_info_p->n_node_type =
58527c478bd9Sstevel@tonic-gate 				    nr_resp->NodeInfo.NodeType;
58537c478bd9Sstevel@tonic-gate 				(void) strncpy(node_info_p->n_description,
58547c478bd9Sstevel@tonic-gate 				    (char *)&nr_resp->NodeDescription, 64);
58557c478bd9Sstevel@tonic-gate 
58567c478bd9Sstevel@tonic-gate 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
58577c478bd9Sstevel@tonic-gate 				    *node_info_p))
58587c478bd9Sstevel@tonic-gate 
58597c478bd9Sstevel@tonic-gate 				/*
58607c478bd9Sstevel@tonic-gate 				 * Deallocate the memory allocated by SA for
58617c478bd9Sstevel@tonic-gate 				 * 'nr_resp'.
58627c478bd9Sstevel@tonic-gate 				 */
58637c478bd9Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
58647c478bd9Sstevel@tonic-gate 				kmem_free(nr_resp, len);
58657c478bd9Sstevel@tonic-gate 				retval = IBT_SUCCESS;
58667c478bd9Sstevel@tonic-gate 
58677c478bd9Sstevel@tonic-gate 				goto gid_to_ni_exit;
58687c478bd9Sstevel@tonic-gate 			} else {
58697c478bd9Sstevel@tonic-gate 				retval = IBT_NODE_RECORDS_NOT_FOUND;
58707c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
58717c478bd9Sstevel@tonic-gate 				    "Node Records NOT found - PortGUID %016llX",
58727c478bd9Sstevel@tonic-gate 				    gid.gid_guid);
58737c478bd9Sstevel@tonic-gate 			}
58747c478bd9Sstevel@tonic-gate 		}
58757c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
58767c478bd9Sstevel@tonic-gate 
58777c478bd9Sstevel@tonic-gate 		if (local_node == B_TRUE)
58787c478bd9Sstevel@tonic-gate 			break;
58797c478bd9Sstevel@tonic-gate 	}
58807c478bd9Sstevel@tonic-gate 
58817c478bd9Sstevel@tonic-gate gid_to_ni_exit:
58827c478bd9Sstevel@tonic-gate 	if (guid_array)
58837c478bd9Sstevel@tonic-gate 		ibt_free_hca_list(guid_array, num_hcas);
58847c478bd9Sstevel@tonic-gate 
58857c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: done. Status %d", retval);
58867c478bd9Sstevel@tonic-gate 
58877c478bd9Sstevel@tonic-gate 	return (retval);
58887c478bd9Sstevel@tonic-gate }
58897c478bd9Sstevel@tonic-gate 
58907c478bd9Sstevel@tonic-gate 
589176c04273SRajkumar Sivaprakasam ibt_status_t
ibcm_get_node_rec(ibmf_saa_handle_t saa_handle,sa_node_record_t * nr_req,uint64_t component_mask,void * result_p,size_t * len)58927c478bd9Sstevel@tonic-gate ibcm_get_node_rec(ibmf_saa_handle_t saa_handle, sa_node_record_t *nr_req,
58937c478bd9Sstevel@tonic-gate     uint64_t component_mask, void *result_p, size_t *len)
58947c478bd9Sstevel@tonic-gate {
58957c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t  args;
58967c478bd9Sstevel@tonic-gate 	size_t			length;
58977c478bd9Sstevel@tonic-gate 	ibt_status_t		retval;
58987c478bd9Sstevel@tonic-gate 
58997c478bd9Sstevel@tonic-gate 	args.sq_attr_id = SA_NODERECORD_ATTRID;
59007c478bd9Sstevel@tonic-gate 	args.sq_template = nr_req;
59017c478bd9Sstevel@tonic-gate 	args.sq_access_type = IBMF_SAA_RETRIEVE;
59027c478bd9Sstevel@tonic-gate 	args.sq_template_length = sizeof (sa_node_record_t);
59037c478bd9Sstevel@tonic-gate 	args.sq_component_mask = component_mask;
59047c478bd9Sstevel@tonic-gate 	args.sq_callback = NULL;
59057c478bd9Sstevel@tonic-gate 	args.sq_callback_arg = NULL;
59067c478bd9Sstevel@tonic-gate 
59077c478bd9Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &args, &length, result_p);
59087c478bd9Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
59097c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_get_node_rec: SA Call Failed");
59107c478bd9Sstevel@tonic-gate 		return (retval);
59117c478bd9Sstevel@tonic-gate 	}
59127c478bd9Sstevel@tonic-gate 
59137c478bd9Sstevel@tonic-gate 	*len = length;
59147c478bd9Sstevel@tonic-gate 
59157c478bd9Sstevel@tonic-gate 	/* Validate the returned number of records. */
59167c478bd9Sstevel@tonic-gate 	if ((result_p != NULL) && (length > 0)) {
59177c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibcm_get_node_rec: Node Records FOUND");
59187c478bd9Sstevel@tonic-gate 
59197c478bd9Sstevel@tonic-gate 		/* Got it, done!. */
59207c478bd9Sstevel@tonic-gate 		return (IBT_SUCCESS);
59217c478bd9Sstevel@tonic-gate 	} else {
59227c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_get_node_rec: Node Rec NOT found");
59237c478bd9Sstevel@tonic-gate 		return (IBT_NODE_RECORDS_NOT_FOUND);
59247c478bd9Sstevel@tonic-gate 	}
59257c478bd9Sstevel@tonic-gate }
59267c478bd9Sstevel@tonic-gate 
59277c478bd9Sstevel@tonic-gate 
59287c478bd9Sstevel@tonic-gate /*
59297c478bd9Sstevel@tonic-gate  * Function:
593017a2b317SBill Taylor  *	ibt_lid_to_node_info()
593117a2b317SBill Taylor  * Input:
593217a2b317SBill Taylor  *	lid		Identifies the IB Node and port for which to obtain
593317a2b317SBill Taylor  *			Node information.
593417a2b317SBill Taylor  * Output:
593517a2b317SBill Taylor  *	node_info_p	A pointer to an ibt_node_info_t structure (allocated
593617a2b317SBill Taylor  *			by the caller) in which to return the node information.
593717a2b317SBill Taylor  * Returns:
593817a2b317SBill Taylor  *	IBT_SUCCESS
593917a2b317SBill Taylor  *	IBT_INVALID_PARAM
594017a2b317SBill Taylor  *	IBT_NODE_RECORDS_NOT_FOUND
594117a2b317SBill Taylor  *	IBT_NO_HCAS_AVAILABLE
594217a2b317SBill Taylor  * Description:
594317a2b317SBill Taylor  *	Retrieve Node Information for the specified LID.
594417a2b317SBill Taylor  */
594517a2b317SBill Taylor ibt_status_t
ibt_lid_to_node_info(ib_lid_t lid,ibt_node_info_t * node_info_p)594617a2b317SBill Taylor ibt_lid_to_node_info(ib_lid_t lid, ibt_node_info_t *node_info_p)
594717a2b317SBill Taylor {
594817a2b317SBill Taylor 	ibt_status_t	retval;
594917a2b317SBill Taylor 	ibcm_hca_info_t	*hcap;
595017a2b317SBill Taylor 	uint8_t		i, j;
595117a2b317SBill Taylor 	ib_guid_t	*guid_array = NULL;
595217a2b317SBill Taylor 	uint_t		num_hcas = 0;
595317a2b317SBill Taylor 
595417a2b317SBill Taylor 
595517a2b317SBill Taylor 	IBTF_DPRINTF_L4(cmlog, "ibt_lid_to_node_info(0x%lX, %p)",
595617a2b317SBill Taylor 	    lid, node_info_p);
595717a2b317SBill Taylor 
595817a2b317SBill Taylor 	if ((lid == 0) || (node_info_p == NULL)) {
595917a2b317SBill Taylor 		IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
596017a2b317SBill Taylor 		    "Lid is zero, or node_info_p is NULL.");
596117a2b317SBill Taylor 		return (IBT_INVALID_PARAM);
596217a2b317SBill Taylor 	}
596317a2b317SBill Taylor 
596417a2b317SBill Taylor 	/* Get the number of HCAs and their GUIDs */
596517a2b317SBill Taylor 	num_hcas = ibt_get_hca_list(&guid_array);
596617a2b317SBill Taylor 	IBTF_DPRINTF_L4(cmlog, "ibt_lid_to_node_info: ibt_get_hca_list "
596717a2b317SBill Taylor 	    "returned %d hcas", num_hcas);
596817a2b317SBill Taylor 
596917a2b317SBill Taylor 	if (num_hcas == 0) {
597017a2b317SBill Taylor 		IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
597117a2b317SBill Taylor 		    "NO HCA's Found on this system");
597217a2b317SBill Taylor 		return (IBT_NO_HCAS_AVAILABLE);
597317a2b317SBill Taylor 	}
597417a2b317SBill Taylor 
597517a2b317SBill Taylor 	for (i = 0; i < num_hcas; i++) {
597617a2b317SBill Taylor 		hcap = ibcm_find_hca_entry(guid_array[i]);
597717a2b317SBill Taylor 		if (hcap == NULL) {
597817a2b317SBill Taylor 			IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
597917a2b317SBill Taylor 			    "HCA(%llX) info not found", guid_array[i]);
598017a2b317SBill Taylor 			retval = IBT_NO_HCAS_AVAILABLE;
598117a2b317SBill Taylor 			continue;
598217a2b317SBill Taylor 		}
598317a2b317SBill Taylor 
598417a2b317SBill Taylor 		for (j = 0; j < hcap->hca_num_ports; j++) {
598517a2b317SBill Taylor 			uint8_t			port;
598617a2b317SBill Taylor 			ibmf_saa_handle_t	saa_handle;
598717a2b317SBill Taylor 			uint_t			num_rec;
598817a2b317SBill Taylor 			size_t			len;
598917a2b317SBill Taylor 			void			*res_p;
599017a2b317SBill Taylor 			sa_node_record_t	nr_req, *nr_resp;
599117a2b317SBill Taylor 
599217a2b317SBill Taylor 			port = j + 1;
599317a2b317SBill Taylor 
599417a2b317SBill Taylor 			/* Get SA Access Handle. */
599517a2b317SBill Taylor 			saa_handle = ibcm_get_saa_handle(hcap, port);
599617a2b317SBill Taylor 			if (saa_handle == NULL) {
599717a2b317SBill Taylor 				IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
599817a2b317SBill Taylor 				    "Port %d of HCA (%llX) is NOT ACTIVE",
599917a2b317SBill Taylor 				    port, guid_array[i]);
600017a2b317SBill Taylor 				retval = IBT_NODE_RECORDS_NOT_FOUND;
600117a2b317SBill Taylor 				continue;
600217a2b317SBill Taylor 			}
600317a2b317SBill Taylor 
600417a2b317SBill Taylor 			/* Retrieve Node Records from SA Access. */
600517a2b317SBill Taylor 			bzero(&nr_req, sizeof (sa_node_record_t));
600617a2b317SBill Taylor 
600717a2b317SBill Taylor 			nr_req.LID = lid;	/* LID */
600817a2b317SBill Taylor 
600917a2b317SBill Taylor 			retval = ibcm_get_node_rec(saa_handle, &nr_req,
601017a2b317SBill Taylor 			    SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
601117a2b317SBill Taylor 			if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
601217a2b317SBill Taylor 				IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
601317a2b317SBill Taylor 				    "failed (%d) to get Node records", retval);
601417a2b317SBill Taylor 				continue;
601517a2b317SBill Taylor 			} else if (retval != IBT_SUCCESS) {
601617a2b317SBill Taylor 				IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
601717a2b317SBill Taylor 				    "failed (%d) to get Node records", retval);
601817a2b317SBill Taylor 				ibcm_dec_hca_acc_cnt(hcap);
601917a2b317SBill Taylor 				goto lid_to_ni_exit;
602017a2b317SBill Taylor 			}
602117a2b317SBill Taylor 
602217a2b317SBill Taylor 			num_rec = len/sizeof (sa_node_record_t);
602317a2b317SBill Taylor 			nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
602417a2b317SBill Taylor 
602517a2b317SBill Taylor 			/* Validate the returned number of records. */
602617a2b317SBill Taylor 			if ((nr_resp != NULL) && (num_rec > 0)) {
602717a2b317SBill Taylor 
602817a2b317SBill Taylor 				IBCM_DUMP_NODE_REC(nr_resp);
602917a2b317SBill Taylor 
603017a2b317SBill Taylor 				_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
603117a2b317SBill Taylor 				    *node_info_p))
603217a2b317SBill Taylor 
603317a2b317SBill Taylor 				node_info_p->n_sys_img_guid =
603417a2b317SBill Taylor 				    nr_resp->NodeInfo.SystemImageGUID;
603517a2b317SBill Taylor 				node_info_p->n_node_guid =
603617a2b317SBill Taylor 				    nr_resp->NodeInfo.NodeGUID;
603717a2b317SBill Taylor 				node_info_p->n_port_guid =
603817a2b317SBill Taylor 				    nr_resp->NodeInfo.PortGUID;
603917a2b317SBill Taylor 				node_info_p->n_dev_id =
604017a2b317SBill Taylor 				    nr_resp->NodeInfo.DeviceID;
604117a2b317SBill Taylor 				node_info_p->n_revision =
604217a2b317SBill Taylor 				    nr_resp->NodeInfo.Revision;
604317a2b317SBill Taylor 				node_info_p->n_vendor_id =
604417a2b317SBill Taylor 				    nr_resp->NodeInfo.VendorID;
604517a2b317SBill Taylor 				node_info_p->n_num_ports =
604617a2b317SBill Taylor 				    nr_resp->NodeInfo.NumPorts;
604717a2b317SBill Taylor 				node_info_p->n_port_num =
604817a2b317SBill Taylor 				    nr_resp->NodeInfo.LocalPortNum;
604917a2b317SBill Taylor 				node_info_p->n_node_type =
605017a2b317SBill Taylor 				    nr_resp->NodeInfo.NodeType;
605117a2b317SBill Taylor 				(void) strncpy(node_info_p->n_description,
605217a2b317SBill Taylor 				    (char *)&nr_resp->NodeDescription, 64);
605317a2b317SBill Taylor 
605417a2b317SBill Taylor 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
605517a2b317SBill Taylor 				    *node_info_p))
605617a2b317SBill Taylor 
605717a2b317SBill Taylor 				/*
605817a2b317SBill Taylor 				 * Deallocate the memory allocated by SA for
605917a2b317SBill Taylor 				 * 'nr_resp'.
606017a2b317SBill Taylor 				 */
606117a2b317SBill Taylor 				ibcm_dec_hca_acc_cnt(hcap);
606217a2b317SBill Taylor 				kmem_free(nr_resp, len);
606317a2b317SBill Taylor 				retval = IBT_SUCCESS;
606417a2b317SBill Taylor 
606517a2b317SBill Taylor 				goto lid_to_ni_exit;
606617a2b317SBill Taylor 			} else {
606717a2b317SBill Taylor 				retval = IBT_NODE_RECORDS_NOT_FOUND;
606817a2b317SBill Taylor 				IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
606917a2b317SBill Taylor 				    "Node Records NOT found - LID 0x%lX",
607017a2b317SBill Taylor 				    lid);
607117a2b317SBill Taylor 			}
607217a2b317SBill Taylor 		}
607317a2b317SBill Taylor 		ibcm_dec_hca_acc_cnt(hcap);
607417a2b317SBill Taylor 	}
607517a2b317SBill Taylor 
607617a2b317SBill Taylor lid_to_ni_exit:
607717a2b317SBill Taylor 	if (guid_array)
607817a2b317SBill Taylor 		ibt_free_hca_list(guid_array, num_hcas);
607917a2b317SBill Taylor 
608017a2b317SBill Taylor 	IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: done. Status %d", retval);
608117a2b317SBill Taylor 
608217a2b317SBill Taylor 	return (retval);
608317a2b317SBill Taylor }
608417a2b317SBill Taylor 
608517a2b317SBill Taylor /*
608617a2b317SBill Taylor  * Function:
60877c478bd9Sstevel@tonic-gate  *	ibt_get_companion_port_gids()
60887c478bd9Sstevel@tonic-gate  * Description:
60897c478bd9Sstevel@tonic-gate  *	Get list of GID's available on a companion port(s) of the specified
60907c478bd9Sstevel@tonic-gate  *	GID or list of GIDs available on a specified Node GUID/SystemImage GUID.
60917c478bd9Sstevel@tonic-gate  */
60927c478bd9Sstevel@tonic-gate ibt_status_t
ibt_get_companion_port_gids(ib_gid_t gid,ib_guid_t hca_guid,ib_guid_t sysimg_guid,ib_gid_t ** gids_p,uint_t * num_gids_p)60937c478bd9Sstevel@tonic-gate ibt_get_companion_port_gids(ib_gid_t gid, ib_guid_t hca_guid,
60947c478bd9Sstevel@tonic-gate     ib_guid_t sysimg_guid, ib_gid_t **gids_p, uint_t *num_gids_p)
60957c478bd9Sstevel@tonic-gate {
60967c478bd9Sstevel@tonic-gate 	sa_node_record_t	nr_req, *nr_resp;
60977c478bd9Sstevel@tonic-gate 	void			*res_p;
60987c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
60997c478bd9Sstevel@tonic-gate 	int			sa_ret;
6100448978d3Shiremath 	ibt_status_t		retval = IBT_SUCCESS;
61017c478bd9Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
61027c478bd9Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hport;
61037c478bd9Sstevel@tonic-gate 	int			i, j;
61047c478bd9Sstevel@tonic-gate 	uint_t			num_rec;
61057c478bd9Sstevel@tonic-gate 	ib_guid_t		*guid_array = NULL;
61067c478bd9Sstevel@tonic-gate 	sa_path_record_t	*path;
61077c478bd9Sstevel@tonic-gate 	size_t			len;
61087c478bd9Sstevel@tonic-gate 	uint8_t			npaths;
61097c478bd9Sstevel@tonic-gate 	uint32_t		num_hcas = 0;
61107c478bd9Sstevel@tonic-gate 	boolean_t		local_node = B_FALSE;
61117c478bd9Sstevel@tonic-gate 	boolean_t		local_hca = B_FALSE;
61127c478bd9Sstevel@tonic-gate 	ib_guid_t		h_guid = hca_guid;
61137c478bd9Sstevel@tonic-gate 	ib_gid_t		*gidp = NULL, *t_gidp = NULL;
611424b28d04Shiremath 	int			multi_hca_loop = 0;
61157c478bd9Sstevel@tonic-gate 
61167c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids(%llX:%llX, %llX, "
61177c478bd9Sstevel@tonic-gate 	    "%llX)", gid.gid_prefix, gid.gid_guid, hca_guid, sysimg_guid);
61187c478bd9Sstevel@tonic-gate 
61197c478bd9Sstevel@tonic-gate 	if (((gid.gid_prefix == 0) || (gid.gid_guid == 0)) && (hca_guid == 0) &&
61207c478bd9Sstevel@tonic-gate 	    (sysimg_guid == 0)) {
61217c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61227c478bd9Sstevel@tonic-gate 		    "Null Input attribute specified.");
61237c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
61247c478bd9Sstevel@tonic-gate 	}
61257c478bd9Sstevel@tonic-gate 
61267c478bd9Sstevel@tonic-gate 	if ((num_gids_p == NULL) || (gids_p == NULL)) {
61277c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61287c478bd9Sstevel@tonic-gate 		    "num_gids_p or gids_p is NULL");
61297c478bd9Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
61307c478bd9Sstevel@tonic-gate 	}
61317c478bd9Sstevel@tonic-gate 
61327c478bd9Sstevel@tonic-gate 	*num_gids_p = 0;
61337c478bd9Sstevel@tonic-gate 
61347c478bd9Sstevel@tonic-gate 	/* Get the number of HCAs and their GUIDs */
61357c478bd9Sstevel@tonic-gate 	if ((num_hcas = ibt_get_hca_list(&guid_array)) == 0) {
61367c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61377c478bd9Sstevel@tonic-gate 		    "NO HCA's Found on this system");
61387c478bd9Sstevel@tonic-gate 		return (IBT_NO_HCAS_AVAILABLE);
61397c478bd9Sstevel@tonic-gate 	}
61407c478bd9Sstevel@tonic-gate 
61417c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids: "
61427c478bd9Sstevel@tonic-gate 	    "ibt_get_hca_list() returned %d hcas", num_hcas);
61437c478bd9Sstevel@tonic-gate 
61447c478bd9Sstevel@tonic-gate 	/*
61457c478bd9Sstevel@tonic-gate 	 * If 'gid' is on local node, then get node lid (i.e. base lid of the
61467c478bd9Sstevel@tonic-gate 	 * associated port) info via ibtl_cm_get_hca_port() call.
61477c478bd9Sstevel@tonic-gate 	 */
61487c478bd9Sstevel@tonic-gate 	bzero(&hport, sizeof (ibtl_cm_hca_port_t));
61497c478bd9Sstevel@tonic-gate 	if ((gid.gid_prefix != 0) && (gid.gid_guid != 0) &&
61507c478bd9Sstevel@tonic-gate 	    (ibtl_cm_get_hca_port(gid, 0, &hport) == IBT_SUCCESS)) {
61517c478bd9Sstevel@tonic-gate 
61527c478bd9Sstevel@tonic-gate 		if ((hca_guid != 0) && (hca_guid != hport.hp_hca_guid)) {
61537c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61547c478bd9Sstevel@tonic-gate 			    "Invalid GID<->HCAGUID combination specified.");
61557c478bd9Sstevel@tonic-gate 			retval = IBT_INVALID_PARAM;
61567c478bd9Sstevel@tonic-gate 			goto get_comp_pgid_exit;
61577c478bd9Sstevel@tonic-gate 		}
61587c478bd9Sstevel@tonic-gate 		h_guid = hport.hp_hca_guid;
61597c478bd9Sstevel@tonic-gate 		local_node = B_TRUE;
61607c478bd9Sstevel@tonic-gate 
61617c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids: "
61627c478bd9Sstevel@tonic-gate 		    "Local Node: HCA (0x%llX)", h_guid);
61637c478bd9Sstevel@tonic-gate 	} else if (h_guid) {	/* Is specified HCA GUID - local? */
61647c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_hcas; i++) {
61657c478bd9Sstevel@tonic-gate 			if (h_guid == guid_array[i]) {
61667c478bd9Sstevel@tonic-gate 				local_hca = B_TRUE;
61677c478bd9Sstevel@tonic-gate 				break;
61687c478bd9Sstevel@tonic-gate 			}
61697c478bd9Sstevel@tonic-gate 		}
61707c478bd9Sstevel@tonic-gate 	} else if (sysimg_guid) { /* Is specified SystemImage GUID - local? */
61717c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_hcas; i++) {
61727c478bd9Sstevel@tonic-gate 			ibt_status_t	ret;
61737c478bd9Sstevel@tonic-gate 			ibt_hca_attr_t	hca_attr;
61747c478bd9Sstevel@tonic-gate 
61757c478bd9Sstevel@tonic-gate 			ret = ibt_query_hca_byguid(guid_array[i], &hca_attr);
61767c478bd9Sstevel@tonic-gate 			if (ret != IBT_SUCCESS) {
61777c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
61787c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: HCA(%llX) "
61797c478bd9Sstevel@tonic-gate 				    "info not found", guid_array[i]);
61807c478bd9Sstevel@tonic-gate 				retval = IBT_NO_HCAS_AVAILABLE;
61817c478bd9Sstevel@tonic-gate 				continue;
61827c478bd9Sstevel@tonic-gate 			}
61837c478bd9Sstevel@tonic-gate 			if (hca_attr.hca_si_guid == sysimg_guid) {
61847c478bd9Sstevel@tonic-gate 				if ((hca_guid != 0) &&
61857c478bd9Sstevel@tonic-gate 				    (hca_guid != hca_attr.hca_node_guid)) {
61867c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
61877c478bd9Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
61887c478bd9Sstevel@tonic-gate 					    "Invalid SysImg<->HCA GUID "
61897c478bd9Sstevel@tonic-gate 					    "combination specified.");
61907c478bd9Sstevel@tonic-gate 					retval = IBT_INVALID_PARAM;
61917c478bd9Sstevel@tonic-gate 					goto get_comp_pgid_exit;
61927c478bd9Sstevel@tonic-gate 				}
61937c478bd9Sstevel@tonic-gate 				local_hca = B_TRUE;
61947c478bd9Sstevel@tonic-gate 				h_guid = hca_attr.hca_node_guid;
61957c478bd9Sstevel@tonic-gate 				break;
61967c478bd9Sstevel@tonic-gate 			}
61977c478bd9Sstevel@tonic-gate 		}
61987c478bd9Sstevel@tonic-gate 	}
61997c478bd9Sstevel@tonic-gate 
62007c478bd9Sstevel@tonic-gate 	if ((local_node == B_TRUE) || (local_hca == B_TRUE)) {
62017c478bd9Sstevel@tonic-gate 		retval = ibtl_cm_get_local_comp_gids(h_guid, gid, gids_p,
62027c478bd9Sstevel@tonic-gate 		    num_gids_p);
62037c478bd9Sstevel@tonic-gate 		goto get_comp_pgid_exit;
62047c478bd9Sstevel@tonic-gate 	}
62057c478bd9Sstevel@tonic-gate 
620624b28d04Shiremath get_comp_for_multihca:
62077c478bd9Sstevel@tonic-gate 	/* We will be here, if request is for remote node */
62087c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_hcas; i++) {
62097c478bd9Sstevel@tonic-gate 		int		multism;
62105c42ea03Shiremath 		uint_t		count = 0;
62117c478bd9Sstevel@tonic-gate 		int		multi_sm_loop = 0;
62127c478bd9Sstevel@tonic-gate 		uint_t		k = 0, l;
62137c478bd9Sstevel@tonic-gate 
62147c478bd9Sstevel@tonic-gate 		hcap = ibcm_find_hca_entry(guid_array[i]);
62157c478bd9Sstevel@tonic-gate 		if (hcap == NULL) {
62167c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
62177c478bd9Sstevel@tonic-gate 			    "HCA(%llX) info not found", guid_array[i]);
62187c478bd9Sstevel@tonic-gate 			retval = IBT_NO_HCAS_AVAILABLE;
62197c478bd9Sstevel@tonic-gate 			continue;
62207c478bd9Sstevel@tonic-gate 		}
62217c478bd9Sstevel@tonic-gate 
62227c478bd9Sstevel@tonic-gate 		/* 1 - MultiSM, 0 - Single SM */
62237c478bd9Sstevel@tonic-gate 		multism = ibtl_cm_is_multi_sm(guid_array[i]);
62247c478bd9Sstevel@tonic-gate 
62257c478bd9Sstevel@tonic-gate 		for (j = 0; j < hcap->hca_num_ports; j++) {
62267c478bd9Sstevel@tonic-gate 			ib_gid_t	sgid;
62277c478bd9Sstevel@tonic-gate 			uint64_t	c_mask = 0;
62287c478bd9Sstevel@tonic-gate 			ib_guid_t	pg;
62297c478bd9Sstevel@tonic-gate 			uint_t		port = j;
62307c478bd9Sstevel@tonic-gate 
62317c478bd9Sstevel@tonic-gate get_comp_for_multism:
62327c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
62337c478bd9Sstevel@tonic-gate 			    "Port %d, HCA %llX, MultiSM= %d, Loop=%d",
62347c478bd9Sstevel@tonic-gate 			    port + 1, h_guid, multism, multi_sm_loop);
62357c478bd9Sstevel@tonic-gate 
62367c478bd9Sstevel@tonic-gate 			/* Get SA Access Handle. */
62377c478bd9Sstevel@tonic-gate 			saa_handle = ibcm_get_saa_handle(hcap, port + 1);
62387c478bd9Sstevel@tonic-gate 			if (saa_handle == NULL) {
62397c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
62407c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
6241448978d3Shiremath 				    "Port (%d)  - NOT ACTIVE", port + 1);
6242448978d3Shiremath 				retval = IBT_GIDS_NOT_FOUND;
62437c478bd9Sstevel@tonic-gate 				continue;
62447c478bd9Sstevel@tonic-gate 			}
62457c478bd9Sstevel@tonic-gate 
62467c478bd9Sstevel@tonic-gate 			/*
62477c478bd9Sstevel@tonic-gate 			 * Check whether 'gid' and this port has same subnet
62487c478bd9Sstevel@tonic-gate 			 * prefix. If not, then there is no use in searching
62497c478bd9Sstevel@tonic-gate 			 * from this port.
62507c478bd9Sstevel@tonic-gate 			 */
62517c478bd9Sstevel@tonic-gate 			sgid = hcap->hca_port_info[port].port_sgid0;
625224b28d04Shiremath 			if ((h_guid == 0) && (gid.gid_prefix != 0) &&
625324b28d04Shiremath 			    (multi_sm_loop == 0) &&
62547c478bd9Sstevel@tonic-gate 			    (gid.gid_prefix != sgid.gid_prefix)) {
62557c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
62567c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: SnPrefix of "
62577c478bd9Sstevel@tonic-gate 				    "GID(%llX) and Port SN_Pfx(%llX) differ",
62587c478bd9Sstevel@tonic-gate 				    gid.gid_prefix, sgid.gid_prefix);
6259448978d3Shiremath 				retval = IBT_GIDS_NOT_FOUND;
62607c478bd9Sstevel@tonic-gate 				continue;
62617c478bd9Sstevel@tonic-gate 			}
62627c478bd9Sstevel@tonic-gate 
62637c478bd9Sstevel@tonic-gate 			/*
62647c478bd9Sstevel@tonic-gate 			 * If HCA GUID or System Image GUID is specified, then
62657c478bd9Sstevel@tonic-gate 			 * we can achieve our goal sooner!.
62667c478bd9Sstevel@tonic-gate 			 */
62677c478bd9Sstevel@tonic-gate 			if ((h_guid == 0) && (sysimg_guid == 0)) {
62687c478bd9Sstevel@tonic-gate 				/* So only GID info is provided. */
62697c478bd9Sstevel@tonic-gate 
62707c478bd9Sstevel@tonic-gate 				/*
62717c478bd9Sstevel@tonic-gate 				 * First Get Path Records for the specified DGID
62727c478bd9Sstevel@tonic-gate 				 * from this port (SGID). From Path Records,
62737c478bd9Sstevel@tonic-gate 				 * note down DLID, then use this DLID as Input
62747c478bd9Sstevel@tonic-gate 				 * attribute to get NodeRecords.
62757c478bd9Sstevel@tonic-gate 				 */
62767c478bd9Sstevel@tonic-gate 				npaths = 1;
62777c478bd9Sstevel@tonic-gate 				path = NULL;
62787c478bd9Sstevel@tonic-gate 
62797c478bd9Sstevel@tonic-gate 				sa_ret = ibmf_saa_gid_to_pathrecords(saa_handle,
62807c478bd9Sstevel@tonic-gate 				    sgid, gid, 0, 0, B_TRUE, &npaths, 0, &len,
62817c478bd9Sstevel@tonic-gate 				    &path);
62827c478bd9Sstevel@tonic-gate 				if (sa_ret != IBMF_SUCCESS) {
62837c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
62847c478bd9Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
62857c478bd9Sstevel@tonic-gate 					    "ibmf_saa_gid_to_pathrecords() "
62867c478bd9Sstevel@tonic-gate 					    "returned error: %d ", sa_ret);
62877c478bd9Sstevel@tonic-gate 					retval =
62887c478bd9Sstevel@tonic-gate 					    ibcm_ibmf_analyze_error(sa_ret);
62897c478bd9Sstevel@tonic-gate 					ibcm_dec_hca_acc_cnt(hcap);
62907c478bd9Sstevel@tonic-gate 					goto get_comp_pgid_exit;
62917c478bd9Sstevel@tonic-gate 				} else if ((npaths == 0) || (path == NULL)) {
62927c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
62937c478bd9Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
62947c478bd9Sstevel@tonic-gate 					    "failed (%d) to get path records "
62957c478bd9Sstevel@tonic-gate 					    "for the DGID (0x%llX) from SGID "
62967c478bd9Sstevel@tonic-gate 					    "(0x%llX)", sa_ret, gid.gid_guid,
62977c478bd9Sstevel@tonic-gate 					    sgid.gid_guid);
6298448978d3Shiremath 					retval = IBT_GIDS_NOT_FOUND;
62997c478bd9Sstevel@tonic-gate 					continue;
63007c478bd9Sstevel@tonic-gate 				}
630124b28d04Shiremath 
630224b28d04Shiremath 				bzero(&nr_req, sizeof (sa_node_record_t));
63037c478bd9Sstevel@tonic-gate 				nr_req.LID = path->DLID;	/* LID */
63047c478bd9Sstevel@tonic-gate 
63057c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog,
63067c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
63077c478bd9Sstevel@tonic-gate 				    "Remote Node: LID = 0x%X", nr_req.LID);
63087c478bd9Sstevel@tonic-gate 
63097c478bd9Sstevel@tonic-gate 				/* Free SA_Access memory for path record. */
63107c478bd9Sstevel@tonic-gate 				kmem_free(path, len);
63117c478bd9Sstevel@tonic-gate 
63127c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog,
63137c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: SAA Call: "
63147c478bd9Sstevel@tonic-gate 				    "based on LID ");
63157c478bd9Sstevel@tonic-gate 
63167c478bd9Sstevel@tonic-gate 				retval = ibcm_get_node_rec(saa_handle, &nr_req,
63177c478bd9Sstevel@tonic-gate 				    SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
63187c478bd9Sstevel@tonic-gate 				if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
63197c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
63207c478bd9Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
63217c478bd9Sstevel@tonic-gate 					    "failed (%d) to get Node records",
63227c478bd9Sstevel@tonic-gate 					    retval);
63237c478bd9Sstevel@tonic-gate 					continue;
63247c478bd9Sstevel@tonic-gate 				} else if (retval != IBT_SUCCESS) {
63257c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
63267c478bd9Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
63277c478bd9Sstevel@tonic-gate 					    "failed (%d) to get Node records",
63287c478bd9Sstevel@tonic-gate 					    retval);
63297c478bd9Sstevel@tonic-gate 					ibcm_dec_hca_acc_cnt(hcap);
63307c478bd9Sstevel@tonic-gate 					goto get_comp_pgid_exit;
63317c478bd9Sstevel@tonic-gate 				}
63327c478bd9Sstevel@tonic-gate 
63337c478bd9Sstevel@tonic-gate 				nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
63347c478bd9Sstevel@tonic-gate 				/* Note down HCA GUID info. */
63357c478bd9Sstevel@tonic-gate 				h_guid = nr_resp->NodeInfo.NodeGUID;
63367c478bd9Sstevel@tonic-gate 
63377c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog,
63387c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
63397c478bd9Sstevel@tonic-gate 				    "Remote HCA GUID: 0x%llX", h_guid);
63407c478bd9Sstevel@tonic-gate 
63417c478bd9Sstevel@tonic-gate 				IBCM_DUMP_NODE_REC(nr_resp);
63427c478bd9Sstevel@tonic-gate 
63437c478bd9Sstevel@tonic-gate 				kmem_free(res_p, len);
63447c478bd9Sstevel@tonic-gate 			}
63457c478bd9Sstevel@tonic-gate 
634624b28d04Shiremath 			bzero(&nr_req, sizeof (sa_node_record_t));
63477c478bd9Sstevel@tonic-gate 			if (h_guid != 0) {
63487c478bd9Sstevel@tonic-gate 				nr_req.NodeInfo.NodeGUID = h_guid;
63497c478bd9Sstevel@tonic-gate 				c_mask = SA_NODEINFO_COMPMASK_NODEGUID;
63507c478bd9Sstevel@tonic-gate 			}
63517c478bd9Sstevel@tonic-gate 
63527c478bd9Sstevel@tonic-gate 			if (sysimg_guid != 0) {
63537c478bd9Sstevel@tonic-gate 				nr_req.NodeInfo.SystemImageGUID = sysimg_guid;
63547c478bd9Sstevel@tonic-gate 				c_mask |= SA_NODEINFO_COMPMASK_SYSIMAGEGUID;
63557c478bd9Sstevel@tonic-gate 			}
63567c478bd9Sstevel@tonic-gate 
63577c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
63587c478bd9Sstevel@tonic-gate 			    "SAA Call: CMASK= 0x%llX", c_mask);
63597c478bd9Sstevel@tonic-gate 
63607c478bd9Sstevel@tonic-gate 			retval = ibcm_get_node_rec(saa_handle, &nr_req, c_mask,
63617c478bd9Sstevel@tonic-gate 			    &res_p, &len);
63627c478bd9Sstevel@tonic-gate 			if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
63637c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog,
63647c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
63657c478bd9Sstevel@tonic-gate 				    "failed (%d) to get Node records", retval);
63667c478bd9Sstevel@tonic-gate 				continue;
63677c478bd9Sstevel@tonic-gate 			} else if (retval != IBT_SUCCESS) {
63687c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
63697c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: Error: (%d) "
63707c478bd9Sstevel@tonic-gate 				    "while getting Node records", retval);
63717c478bd9Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
63727c478bd9Sstevel@tonic-gate 				goto get_comp_pgid_exit;
63737c478bd9Sstevel@tonic-gate 			}
63747c478bd9Sstevel@tonic-gate 
63757c478bd9Sstevel@tonic-gate 			num_rec = len/sizeof (sa_node_record_t);
63767c478bd9Sstevel@tonic-gate 
63777c478bd9Sstevel@tonic-gate 			/* We will be here, only if we found some NodeRec */
63787c478bd9Sstevel@tonic-gate 			if (gid.gid_prefix && gid.gid_guid) {
63797c478bd9Sstevel@tonic-gate 				nr_resp = (sa_node_record_t *)res_p;
63807c478bd9Sstevel@tonic-gate 				for (l = 0; l < num_rec; l++, nr_resp++) {
63817c478bd9Sstevel@tonic-gate 					pg = nr_resp->NodeInfo.PortGUID;
63827c478bd9Sstevel@tonic-gate 					if (gid.gid_guid != pg)
63837c478bd9Sstevel@tonic-gate 						count++;
63847c478bd9Sstevel@tonic-gate 				}
63857c478bd9Sstevel@tonic-gate 			} else {
63867c478bd9Sstevel@tonic-gate 				count = num_rec;
63877c478bd9Sstevel@tonic-gate 			}
63887c478bd9Sstevel@tonic-gate 
63897c478bd9Sstevel@tonic-gate 			if (count != 0) {
63907c478bd9Sstevel@tonic-gate 				if (multi_sm_loop == 1) {
63917c478bd9Sstevel@tonic-gate 					count += k;
63927c478bd9Sstevel@tonic-gate 					t_gidp = kmem_zalloc(count *
63937c478bd9Sstevel@tonic-gate 					    sizeof (ib_gid_t), KM_SLEEP);
63947c478bd9Sstevel@tonic-gate 
63957c478bd9Sstevel@tonic-gate 					if ((k != 0) && (gidp != NULL)) {
63967c478bd9Sstevel@tonic-gate 						bcopy(gidp, t_gidp,
63977c478bd9Sstevel@tonic-gate 						    k * sizeof (ib_gid_t));
63987c478bd9Sstevel@tonic-gate 						kmem_free(gidp,
63997c478bd9Sstevel@tonic-gate 						    k * sizeof (ib_gid_t));
64007c478bd9Sstevel@tonic-gate 					}
64017c478bd9Sstevel@tonic-gate 					gidp = t_gidp;
64027c478bd9Sstevel@tonic-gate 				} else {
64037c478bd9Sstevel@tonic-gate 					gidp = kmem_zalloc(count *
64047c478bd9Sstevel@tonic-gate 					    sizeof (ib_gid_t), KM_SLEEP);
64057c478bd9Sstevel@tonic-gate 				}
64067c478bd9Sstevel@tonic-gate 				*num_gids_p = count;
64077c478bd9Sstevel@tonic-gate 				*gids_p = gidp;
64087c478bd9Sstevel@tonic-gate 
64097c478bd9Sstevel@tonic-gate 				nr_resp = (sa_node_record_t *)res_p;
64107c478bd9Sstevel@tonic-gate 				for (l = 0; l < num_rec; l++, nr_resp++) {
64117c478bd9Sstevel@tonic-gate 					IBCM_DUMP_NODE_REC(nr_resp);
64127c478bd9Sstevel@tonic-gate 
64137c478bd9Sstevel@tonic-gate 					pg = nr_resp->NodeInfo.PortGUID;
64147c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L4(cmlog,
64157c478bd9Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
64167c478bd9Sstevel@tonic-gate 					    "PortGID %llX", pg);
64177c478bd9Sstevel@tonic-gate 
64187c478bd9Sstevel@tonic-gate 					if (pg != gid.gid_guid) {
64197c478bd9Sstevel@tonic-gate 						gidp[k].gid_prefix =
64207c478bd9Sstevel@tonic-gate 						    sgid.gid_prefix;
64217c478bd9Sstevel@tonic-gate 						gidp[k].gid_guid = pg;
64227c478bd9Sstevel@tonic-gate 
64237c478bd9Sstevel@tonic-gate 						IBTF_DPRINTF_L3(cmlog,
64247c478bd9Sstevel@tonic-gate 						    "ibt_get_companion_pgids: "
64257c478bd9Sstevel@tonic-gate 						    "GID[%d] = %llX:%llX", k,
64267c478bd9Sstevel@tonic-gate 						    gidp[k].gid_prefix,
64277c478bd9Sstevel@tonic-gate 						    gidp[k].gid_guid);
64287c478bd9Sstevel@tonic-gate 
64297c478bd9Sstevel@tonic-gate 						k++;
64307c478bd9Sstevel@tonic-gate 						if (k == count)
64317c478bd9Sstevel@tonic-gate 							break;
64327c478bd9Sstevel@tonic-gate 					}
64337c478bd9Sstevel@tonic-gate 				}
64347c478bd9Sstevel@tonic-gate 				retval = IBT_SUCCESS;	/* done!. */
643524b28d04Shiremath 				kmem_free(res_p, len);
643624b28d04Shiremath 				ibcm_dec_hca_acc_cnt(hcap);
643724b28d04Shiremath 				goto get_comp_pgid_exit;
64387c478bd9Sstevel@tonic-gate 			} else {
64397c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
64407c478bd9Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
64417c478bd9Sstevel@tonic-gate 				    "Companion PortGIDs not available");
64427c478bd9Sstevel@tonic-gate 				retval = IBT_GIDS_NOT_FOUND;
64437c478bd9Sstevel@tonic-gate 			}
64447c478bd9Sstevel@tonic-gate 			/* Deallocate the memory for 'res_p'. */
64457c478bd9Sstevel@tonic-gate 			kmem_free(res_p, len);
64467c478bd9Sstevel@tonic-gate 
64477c478bd9Sstevel@tonic-gate 			/*
64487c478bd9Sstevel@tonic-gate 			 * If we are on MultiSM setup, then we need to lookout
64497c478bd9Sstevel@tonic-gate 			 * from that subnet port too.
64507c478bd9Sstevel@tonic-gate 			 */
64517c478bd9Sstevel@tonic-gate 			if (multism) {
64527c478bd9Sstevel@tonic-gate 				/* break if already searched both the subnet */
64537c478bd9Sstevel@tonic-gate 				if (multi_sm_loop == 1)
64547c478bd9Sstevel@tonic-gate 					break;
64557c478bd9Sstevel@tonic-gate 
64567c478bd9Sstevel@tonic-gate 				port = (j == 0) ? 1 : 0;
64577c478bd9Sstevel@tonic-gate 				multi_sm_loop = 1;
64587c478bd9Sstevel@tonic-gate 				goto get_comp_for_multism;
64597c478bd9Sstevel@tonic-gate 			} else {
64607c478bd9Sstevel@tonic-gate 				break;
64617c478bd9Sstevel@tonic-gate 			}
64627c478bd9Sstevel@tonic-gate 		}
64637c478bd9Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
646424b28d04Shiremath 
646524b28d04Shiremath 		/*
646624b28d04Shiremath 		 * We may be on dual HCA with dual SM configured system.  And
646724b28d04Shiremath 		 * the input attr GID was visible from second HCA. So in order
646824b28d04Shiremath 		 * to get the companion portgid we need to re-look from the
646924b28d04Shiremath 		 * first HCA ports.
647024b28d04Shiremath 		 */
647124b28d04Shiremath 		if ((num_hcas > 1) && (i > 0) && (h_guid != 0) &&
647224b28d04Shiremath 		    (multi_hca_loop != 1)) {
647324b28d04Shiremath 			multi_hca_loop = 1;
647424b28d04Shiremath 			goto get_comp_for_multihca;
647524b28d04Shiremath 		}
64767c478bd9Sstevel@tonic-gate 	}
6477448978d3Shiremath 	if (*num_gids_p == 0)
6478448978d3Shiremath 		retval = IBT_GIDS_NOT_FOUND;
64797c478bd9Sstevel@tonic-gate 
64807c478bd9Sstevel@tonic-gate get_comp_pgid_exit:
64817c478bd9Sstevel@tonic-gate 	if (guid_array)
64827c478bd9Sstevel@tonic-gate 		ibt_free_hca_list(guid_array, num_hcas);
64837c478bd9Sstevel@tonic-gate 
64847c478bd9Sstevel@tonic-gate 	if ((retval != IBT_SUCCESS) && (*num_gids_p != 0)) {
64857c478bd9Sstevel@tonic-gate 		retval = IBT_SUCCESS;
64867c478bd9Sstevel@tonic-gate 	}
64877c478bd9Sstevel@tonic-gate 
64887c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: done. Status %d, "
64897c478bd9Sstevel@tonic-gate 	    "Found %d GIDs", retval, *num_gids_p);
64907c478bd9Sstevel@tonic-gate 
64917c478bd9Sstevel@tonic-gate 	return (retval);
64927c478bd9Sstevel@tonic-gate }
64937c478bd9Sstevel@tonic-gate 
6494015f8fffShiremath /* RDMA IP CM Support routines */
6495015f8fffShiremath ibt_status_t
ibt_get_src_ip(ibt_srcip_attr_t * sattr,ibt_srcip_info_t ** src_info_p,uint_t * entries_p)649617a2b317SBill Taylor ibt_get_src_ip(ibt_srcip_attr_t *sattr, ibt_srcip_info_t **src_info_p,
649717a2b317SBill Taylor     uint_t *entries_p)
6498015f8fffShiremath {
649917a2b317SBill Taylor 	ibt_srcip_info_t	*s_ip;
6500015f8fffShiremath 	ibcm_arp_ip_t		*ipp;
6501015f8fffShiremath 	ibcm_arp_ibd_insts_t	ibds;
650217a2b317SBill Taylor 	uint8_t			i, j;
650317a2b317SBill Taylor 	uint_t			count;
6504015f8fffShiremath 	ibt_status_t		retval = IBT_SUCCESS;
6505015f8fffShiremath 
650617a2b317SBill Taylor 	IBTF_DPRINTF_L4(cmlog, "ibt_get_src_ip(%p, %p, %p)",
650717a2b317SBill Taylor 	    sattr, src_info_p, entries_p);
6508015f8fffShiremath 
650917a2b317SBill Taylor 	if (sattr == NULL || entries_p == NULL) {
651017a2b317SBill Taylor 		IBTF_DPRINTF_L3(cmlog, "ibt_get_src_ip: Invalid I/P Args.");
651117a2b317SBill Taylor 		return (IBT_INVALID_PARAM);
651217a2b317SBill Taylor 	}
651317a2b317SBill Taylor 
651417a2b317SBill Taylor 	if (sattr->sip_gid.gid_prefix == 0 || sattr->sip_gid.gid_guid == 0) {
6515015f8fffShiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_get_src_ip: Invalid GID.");
6516015f8fffShiremath 		return (IBT_INVALID_PARAM);
6517015f8fffShiremath 	}
6518015f8fffShiremath 
651917a2b317SBill Taylor 	/* TBD: Zoneid */
652017a2b317SBill Taylor 	retval = ibcm_arp_get_ibds(&ibds, sattr->sip_family);
6521015f8fffShiremath 	if (retval != IBT_SUCCESS) {
6522015f8fffShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_get_src_ip: ibcm_arp_get_ibds "
6523015f8fffShiremath 		    "failed to get IBD Instances: ret 0x%x", retval);
6524015f8fffShiremath 		goto get_src_ip_end;
6525015f8fffShiremath 	}
6526015f8fffShiremath 
652717a2b317SBill Taylor 	count = 0;
6528015f8fffShiremath 	for (i = 0, ipp = ibds.ibcm_arp_ip; i < ibds.ibcm_arp_ibd_cnt;
6529015f8fffShiremath 	    i++, ipp++) {
65309c468ea9SPramod Gunjikar 		if (ipp->ip_inet_family == AF_UNSPEC)
65319c468ea9SPramod Gunjikar 			continue;
653217a2b317SBill Taylor 		if (ipp->ip_port_gid.gid_prefix == sattr->sip_gid.gid_prefix &&
653317a2b317SBill Taylor 		    ipp->ip_port_gid.gid_guid == sattr->sip_gid.gid_guid) {
653417a2b317SBill Taylor 			if ((sattr->sip_pkey) &&
653517a2b317SBill Taylor 			    (ipp->ip_pkey != sattr->sip_pkey))
6536015f8fffShiremath 				continue;
653717a2b317SBill Taylor 
653817a2b317SBill Taylor 			if ((sattr->sip_zoneid != ALL_ZONES) &&
653917a2b317SBill Taylor 			    (sattr->sip_zoneid != ipp->ip_zoneid))
654017a2b317SBill Taylor 				continue;
654117a2b317SBill Taylor 
654217a2b317SBill Taylor 			count++;
6543015f8fffShiremath 			break;
6544015f8fffShiremath 		}
6545015f8fffShiremath 	}
6546015f8fffShiremath 
654717a2b317SBill Taylor 	if (count) {
654817a2b317SBill Taylor 		/*
654917a2b317SBill Taylor 		 * Allocate memory for return buffer, to be freed by
655017a2b317SBill Taylor 		 * ibt_free_srcip_info().
655117a2b317SBill Taylor 		 */
655217a2b317SBill Taylor 		s_ip = kmem_alloc((count * sizeof (ibt_srcip_info_t)),
655317a2b317SBill Taylor 		    KM_SLEEP);
655417a2b317SBill Taylor 
655517a2b317SBill Taylor 		*src_info_p = s_ip;
655617a2b317SBill Taylor 		*entries_p = count;
655717a2b317SBill Taylor 
655817a2b317SBill Taylor 		j = 0;
655917a2b317SBill Taylor 		for (i = 0, ipp = ibds.ibcm_arp_ip; i < ibds.ibcm_arp_ibd_cnt;
656017a2b317SBill Taylor 		    i++, ipp++) {
656117a2b317SBill Taylor 			if (ipp->ip_inet_family == AF_UNSPEC)
656217a2b317SBill Taylor 				continue;
656317a2b317SBill Taylor 			if ((ipp->ip_port_gid.gid_prefix ==
656417a2b317SBill Taylor 			    sattr->sip_gid.gid_prefix) &&
656517a2b317SBill Taylor 			    (ipp->ip_port_gid.gid_guid ==
656617a2b317SBill Taylor 			    sattr->sip_gid.gid_guid)) {
656717a2b317SBill Taylor 				if ((sattr->sip_pkey) &&
656817a2b317SBill Taylor 				    (ipp->ip_pkey != sattr->sip_pkey))
656917a2b317SBill Taylor 					continue;
657017a2b317SBill Taylor 
657117a2b317SBill Taylor 				if ((sattr->sip_zoneid != ALL_ZONES) &&
657217a2b317SBill Taylor 				    (sattr->sip_zoneid != ipp->ip_zoneid))
657317a2b317SBill Taylor 					continue;
657417a2b317SBill Taylor 
657517a2b317SBill Taylor 				_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s_ip))
657617a2b317SBill Taylor 				s_ip[j].ip_addr.family = ipp->ip_inet_family;
657717a2b317SBill Taylor 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s_ip))
657817a2b317SBill Taylor 				if (s_ip[j].ip_addr.family == AF_INET) {
657917a2b317SBill Taylor 					bcopy(&ipp->ip_cm_sin.sin_addr,
658017a2b317SBill Taylor 					    &s_ip[j].ip_addr.un.ip4addr,
6581015f8fffShiremath 					    sizeof (in_addr_t));
658217a2b317SBill Taylor 				} else if (s_ip[j].ip_addr.family == AF_INET6) {
658317a2b317SBill Taylor 					bcopy(&ipp->ip_cm_sin6.sin6_addr,
658417a2b317SBill Taylor 					    &s_ip[j].ip_addr.un.ip6addr,
6585015f8fffShiremath 					    sizeof (in6_addr_t));
658617a2b317SBill Taylor 					/* TBD: scope_id */
6587015f8fffShiremath 				}
658817a2b317SBill Taylor 				IBCM_PRINT_IP("ibt_get_src_ip",
658917a2b317SBill Taylor 				    &s_ip[j].ip_addr);
659017a2b317SBill Taylor 				j++;
659117a2b317SBill Taylor 			}
659217a2b317SBill Taylor 		}
659317a2b317SBill Taylor 	} else {
659417a2b317SBill Taylor 		retval = IBT_SRC_IP_NOT_FOUND;
6595015f8fffShiremath 	}
6596015f8fffShiremath 
6597015f8fffShiremath get_src_ip_end:
65981cfa752fSRamaswamy Tummala 	ibcm_arp_free_ibds(&ibds);
6599015f8fffShiremath 	return (retval);
6600015f8fffShiremath }
6601015f8fffShiremath 
660217a2b317SBill Taylor /*
660317a2b317SBill Taylor  * ibt_free_srcip_info()
660417a2b317SBill Taylor  *	Free the memory allocated by successful ibt_get_src_ip()
660517a2b317SBill Taylor  *
660617a2b317SBill Taylor  *	src_info	Pointer returned by ibt_get_src_ip().
660717a2b317SBill Taylor  *
660817a2b317SBill Taylor  *	entries		The number of ibt_ip_addr_t entries to free.
660917a2b317SBill Taylor  */
661017a2b317SBill Taylor void
ibt_free_srcip_info(ibt_srcip_info_t * src_info,uint_t entries)661117a2b317SBill Taylor ibt_free_srcip_info(ibt_srcip_info_t *src_info, uint_t entries)
661217a2b317SBill Taylor {
661317a2b317SBill Taylor 	IBTF_DPRINTF_L3(cmlog, "ibt_free_srcip_info: "
661417a2b317SBill Taylor 	    "Free <%d> entries from 0x%p", entries, src_info);
661517a2b317SBill Taylor 
661617a2b317SBill Taylor 	if ((src_info != NULL) && (entries > 0))
661717a2b317SBill Taylor 		kmem_free(src_info, entries * sizeof (ibt_srcip_info_t));
661817a2b317SBill Taylor 	else
661917a2b317SBill Taylor 		IBTF_DPRINTF_L2(cmlog, "ibt_free_srcip_info: "
662017a2b317SBill Taylor 		    "ERROR: NULL buf pointer or ZERO length specified.");
662117a2b317SBill Taylor }
662217a2b317SBill Taylor 
662317a2b317SBill Taylor 
6624015f8fffShiremath ib_svc_id_t
ibt_get_ip_sid(uint8_t protocol_num,in_port_t dst_port)6625015f8fffShiremath ibt_get_ip_sid(uint8_t protocol_num, in_port_t dst_port)
6626015f8fffShiremath {
6627015f8fffShiremath 	ib_svc_id_t	sid;
6628015f8fffShiremath 
6629015f8fffShiremath 	IBTF_DPRINTF_L4(cmlog, "ibt_get_ip_sid(%X, %lX)", protocol_num,
6630015f8fffShiremath 	    dst_port);
6631015f8fffShiremath 
6632015f8fffShiremath 	/*
6633015f8fffShiremath 	 * If protocol_num is non-zero, then formulate the SID and return it.
6634015f8fffShiremath 	 * If protocol_num is zero, then we need to assign a locally generated
6635015f8fffShiremath 	 * IP SID with IB_SID_IPADDR_PREFIX.
6636015f8fffShiremath 	 */
6637015f8fffShiremath 	if (protocol_num) {
6638015f8fffShiremath 		sid = IB_SID_IPADDR_PREFIX | protocol_num << 16 | dst_port;
6639015f8fffShiremath 	} else {
6640015f8fffShiremath 		sid = ibcm_alloc_ip_sid();
6641015f8fffShiremath 	}
6642015f8fffShiremath 
6643015f8fffShiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_sid: SID: 0x%016llX", sid);
6644015f8fffShiremath 	return (sid);
6645015f8fffShiremath }
6646015f8fffShiremath 
6647015f8fffShiremath ibt_status_t
ibt_release_ip_sid(ib_svc_id_t ip_sid)6648015f8fffShiremath ibt_release_ip_sid(ib_svc_id_t ip_sid)
6649015f8fffShiremath {
6650015f8fffShiremath 	IBTF_DPRINTF_L4(cmlog, "ibt_release_ip_sid(%llX)", ip_sid);
6651015f8fffShiremath 
6652015f8fffShiremath 	if (((ip_sid & IB_SID_IPADDR_PREFIX_MASK) != 0) ||
6653015f8fffShiremath 	    (!(ip_sid & IB_SID_IPADDR_PREFIX))) {
6654015f8fffShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_release_ip_sid(0x%016llX): ERROR: "
6655015f8fffShiremath 		    "Called for Non-RDMA IP SID", ip_sid);
6656015f8fffShiremath 		return (IBT_INVALID_PARAM);
6657015f8fffShiremath 	}
6658015f8fffShiremath 
6659015f8fffShiremath 	/*
6660015f8fffShiremath 	 * If protocol_num in ip_sid are all ZEROs, then this SID is allocated
6661015f8fffShiremath 	 * by IBTF. If not, then the specified ip_sid is invalid.
6662015f8fffShiremath 	 */
6663015f8fffShiremath 	if (ip_sid & IB_SID_IPADDR_IPNUM_MASK) {
6664015f8fffShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_release_ip_sid(0x%016llX): ERROR: "
6665015f8fffShiremath 		    "Called for Non-IBTF assigned RDMA IP SID", ip_sid);
6666015f8fffShiremath 		return (IBT_INVALID_PARAM);
6667015f8fffShiremath 	}
6668015f8fffShiremath 
6669015f8fffShiremath 	ibcm_free_ip_sid(ip_sid);
6670015f8fffShiremath 
6671015f8fffShiremath 	return (IBT_SUCCESS);
6672015f8fffShiremath }
6673015f8fffShiremath 
6674015f8fffShiremath 
6675015f8fffShiremath uint8_t
ibt_get_ip_protocol_num(ib_svc_id_t sid)6676015f8fffShiremath ibt_get_ip_protocol_num(ib_svc_id_t sid)
6677015f8fffShiremath {
6678015f8fffShiremath 	return ((sid & IB_SID_IPADDR_IPNUM_MASK) >> 16);
6679015f8fffShiremath }
6680015f8fffShiremath 
6681015f8fffShiremath in_port_t
ibt_get_ip_dst_port(ib_svc_id_t sid)6682015f8fffShiremath ibt_get_ip_dst_port(ib_svc_id_t sid)
6683015f8fffShiremath {
6684015f8fffShiremath 	return (sid & IB_SID_IPADDR_PORTNUM_MASK);
6685015f8fffShiremath }
6686015f8fffShiremath 
6687015f8fffShiremath _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibt_ip_cm_info_t))
6688015f8fffShiremath _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_ip_pvtdata_t))
6689015f8fffShiremath 
6690015f8fffShiremath ibt_status_t
ibt_format_ip_private_data(ibt_ip_cm_info_t * ip_cm_info,ibt_priv_data_len_t priv_data_len,void * priv_data_p)6691015f8fffShiremath ibt_format_ip_private_data(ibt_ip_cm_info_t *ip_cm_info,
6692015f8fffShiremath     ibt_priv_data_len_t priv_data_len, void *priv_data_p)
6693015f8fffShiremath {
66947fce3d37Shiremath 	ibcm_ip_pvtdata_t	ip_data;
6695015f8fffShiremath 
6696015f8fffShiremath 	IBTF_DPRINTF_L4(cmlog, "ibt_format_ip_private_data(%p, %d, %p)",
6697015f8fffShiremath 	    ip_cm_info, priv_data_len, priv_data_p);
6698015f8fffShiremath 
6699015f8fffShiremath 	if ((ip_cm_info == NULL) || (priv_data_p == NULL) ||
6700015f8fffShiremath 	    (priv_data_len < IBT_IP_HDR_PRIV_DATA_SZ)) {
6701015f8fffShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_format_ip_private_data: ERROR "
6702015f8fffShiremath 		    "Invalid Inputs.");
6703015f8fffShiremath 		return (IBT_INVALID_PARAM);
6704015f8fffShiremath 	}
6705015f8fffShiremath 
67067fce3d37Shiremath 	bzero(&ip_data, sizeof (ibcm_ip_pvtdata_t));
67077fce3d37Shiremath 	ip_data.ip_srcport = ip_cm_info->src_port; /* Source Port */
6708015f8fffShiremath 
6709d3a82192SShantkumar Hiremath 	IBCM_PRINT_IP("format_ip_pvt: src", &ip_cm_info->src_addr);
6710d3a82192SShantkumar Hiremath 	IBCM_PRINT_IP("format_ip_pvt: dst", &ip_cm_info->dst_addr);
6711015f8fffShiremath 	/* IPV = 0x4, if IP-Addr are IPv4 format, else 0x6 for IPv6 */
6712015f8fffShiremath 	if (ip_cm_info->src_addr.family == AF_INET) {
67137fce3d37Shiremath 		ip_data.ip_ipv = IBT_CM_IP_IPV_V4;
67147fce3d37Shiremath 		ip_data.ip_srcv4 = ip_cm_info->src_addr.un.ip4addr;
67157fce3d37Shiremath 		ip_data.ip_dstv4 = ip_cm_info->dst_addr.un.ip4addr;
6716015f8fffShiremath 	} else if (ip_cm_info->src_addr.family == AF_INET6) {
67177fce3d37Shiremath 		ip_data.ip_ipv = IBT_CM_IP_IPV_V6;
6718015f8fffShiremath 		bcopy(&ip_cm_info->src_addr.un.ip6addr,
67197fce3d37Shiremath 		    &ip_data.ip_srcv6, sizeof (in6_addr_t));
6720015f8fffShiremath 		bcopy(&ip_cm_info->dst_addr.un.ip6addr,
67217fce3d37Shiremath 		    &ip_data.ip_dstv6, sizeof (in6_addr_t));
6722015f8fffShiremath 	} else {
6723015f8fffShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_format_ip_private_data: ERROR "
6724015f8fffShiremath 		    "IP Addr needs to be either AF_INET or AF_INET6 family.");
6725015f8fffShiremath 		return (IBT_INVALID_PARAM);
6726015f8fffShiremath 	}
6727015f8fffShiremath 
67287fce3d37Shiremath 	ip_data.ip_MajV = IBT_CM_IP_MAJ_VER;
67297fce3d37Shiremath 	ip_data.ip_MinV = IBT_CM_IP_MIN_VER;
67307fce3d37Shiremath 
67317fce3d37Shiremath 	bcopy(&ip_data, priv_data_p, IBT_IP_HDR_PRIV_DATA_SZ);
6732015f8fffShiremath 
6733015f8fffShiremath 	return (IBT_SUCCESS);
6734015f8fffShiremath }
6735015f8fffShiremath 
6736015f8fffShiremath 
6737015f8fffShiremath ibt_status_t
ibt_get_ip_data(ibt_priv_data_len_t priv_data_len,void * priv_data,ibt_ip_cm_info_t * ip_cm_infop)6738015f8fffShiremath ibt_get_ip_data(ibt_priv_data_len_t priv_data_len, void *priv_data,
6739015f8fffShiremath     ibt_ip_cm_info_t *ip_cm_infop)
6740015f8fffShiremath {
67417fce3d37Shiremath 	ibcm_ip_pvtdata_t	ip_data;
6742015f8fffShiremath 
6743015f8fffShiremath 	IBTF_DPRINTF_L4(cmlog, "ibt_get_ip_data(%d, %p, %p)",
6744015f8fffShiremath 	    priv_data_len, priv_data, ip_cm_infop);
6745015f8fffShiremath 
6746015f8fffShiremath 	if ((ip_cm_infop == NULL) || (priv_data == NULL) ||
6747015f8fffShiremath 	    (priv_data_len < IBT_IP_HDR_PRIV_DATA_SZ)) {
6748015f8fffShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_data: ERROR Invalid Inputs");
6749015f8fffShiremath 		return (IBT_INVALID_PARAM);
6750015f8fffShiremath 	}
6751015f8fffShiremath 
67527fce3d37Shiremath 	bcopy(priv_data, &ip_data, IBT_IP_HDR_PRIV_DATA_SZ);
67537fce3d37Shiremath 	ip_cm_infop->src_port = ip_data.ip_srcport; /* Source Port */
6754015f8fffShiremath 
6755015f8fffShiremath 	/* IPV = 0x4, if IP Address are IPv4 format, else 0x6 for IPv6 */
67567fce3d37Shiremath 	if (ip_data.ip_ipv == IBT_CM_IP_IPV_V4) {
6757015f8fffShiremath 		/* Copy IPv4 Addr */
6758d3a82192SShantkumar Hiremath 		ip_cm_infop->src_addr.family = ip_cm_infop->dst_addr.family =
6759d3a82192SShantkumar Hiremath 		    AF_INET;
67607fce3d37Shiremath 		ip_cm_infop->src_addr.un.ip4addr = ip_data.ip_srcv4;
67617fce3d37Shiremath 		ip_cm_infop->dst_addr.un.ip4addr = ip_data.ip_dstv4;
67627fce3d37Shiremath 	} else if (ip_data.ip_ipv == IBT_CM_IP_IPV_V6) {
6763015f8fffShiremath 		/* Copy IPv6 Addr */
6764d3a82192SShantkumar Hiremath 		ip_cm_infop->src_addr.family = ip_cm_infop->dst_addr.family =
6765d3a82192SShantkumar Hiremath 		    AF_INET6;
67667fce3d37Shiremath 		bcopy(&ip_data.ip_srcv6, &ip_cm_infop->src_addr.un.ip6addr,
6767015f8fffShiremath 		    sizeof (in6_addr_t));
67687fce3d37Shiremath 		bcopy(&ip_data.ip_dstv6, &ip_cm_infop->dst_addr.un.ip6addr,
6769015f8fffShiremath 		    sizeof (in6_addr_t));
6770015f8fffShiremath 	} else {
6771015f8fffShiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_data: ERROR: IP Addr needs"
6772015f8fffShiremath 		    " to be either AF_INET or AF_INET6 family.");
6773015f8fffShiremath 		return (IBT_INVALID_PARAM);
6774015f8fffShiremath 	}
6775d3a82192SShantkumar Hiremath 	IBCM_PRINT_IP("ibt_get_ip_data: src", &ip_cm_infop->src_addr);
6776d3a82192SShantkumar Hiremath 	IBCM_PRINT_IP("ibt_get_ip_data: dst", &ip_cm_infop->dst_addr);
6777015f8fffShiremath 
6778015f8fffShiremath 	return (IBT_SUCCESS);
6779015f8fffShiremath }
6780015f8fffShiremath 
67817c478bd9Sstevel@tonic-gate 
67827c478bd9Sstevel@tonic-gate /* Routines for warlock */
67837c478bd9Sstevel@tonic-gate 
67847c478bd9Sstevel@tonic-gate /* ARGSUSED */
67857c478bd9Sstevel@tonic-gate static void
ibcm_dummy_mcg_handler(void * arg,ibt_status_t retval,ibt_mcg_info_t * minfo)67867c478bd9Sstevel@tonic-gate ibcm_dummy_mcg_handler(void *arg, ibt_status_t retval, ibt_mcg_info_t *minfo)
67877c478bd9Sstevel@tonic-gate {
67887c478bd9Sstevel@tonic-gate 	ibcm_join_mcg_tqarg_t	dummy_mcg;
67897c478bd9Sstevel@tonic-gate 
67907c478bd9Sstevel@tonic-gate 	dummy_mcg.func = ibcm_dummy_mcg_handler;
67917c478bd9Sstevel@tonic-gate 
67927c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_mcg_handler: "
67937c478bd9Sstevel@tonic-gate 	    "dummy_mcg.func %p", dummy_mcg.func);
67947c478bd9Sstevel@tonic-gate }
67957c478bd9Sstevel@tonic-gate 
67967c478bd9Sstevel@tonic-gate 
67977c478bd9Sstevel@tonic-gate /* ARGSUSED */
67987c478bd9Sstevel@tonic-gate static void
ibcm_dummy_recycle_rc_handler(ibt_status_t retval,void * arg)67997c478bd9Sstevel@tonic-gate ibcm_dummy_recycle_rc_handler(ibt_status_t retval, void *arg)
68007c478bd9Sstevel@tonic-gate {
68017c478bd9Sstevel@tonic-gate 	ibcm_taskq_recycle_arg_t	dummy_rc_recycle;
68027c478bd9Sstevel@tonic-gate 
68037c478bd9Sstevel@tonic-gate 	dummy_rc_recycle.func = ibcm_dummy_recycle_rc_handler;
68047c478bd9Sstevel@tonic-gate 
68057c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_recycle_rc_handler: "
68067c478bd9Sstevel@tonic-gate 	    "dummy_rc_recycle.func %p", dummy_rc_recycle.func);
68077c478bd9Sstevel@tonic-gate }
68087c478bd9Sstevel@tonic-gate 
68097c478bd9Sstevel@tonic-gate 
68107c478bd9Sstevel@tonic-gate /* ARGSUSED */
68117c478bd9Sstevel@tonic-gate static ibt_cm_status_t
ibcm_dummy_ud_handler(void * priv,ibt_cm_ud_event_t * event,ibt_cm_ud_return_args_t * ret_args,void * priv_data,ibt_priv_data_len_t len)68127c478bd9Sstevel@tonic-gate ibcm_dummy_ud_handler(void *priv, ibt_cm_ud_event_t *event,
68137c478bd9Sstevel@tonic-gate     ibt_cm_ud_return_args_t *ret_args,
68147c478bd9Sstevel@tonic-gate     void *priv_data, ibt_priv_data_len_t len)
68157c478bd9Sstevel@tonic-gate {
68167c478bd9Sstevel@tonic-gate 	/*
68177c478bd9Sstevel@tonic-gate 	 * Let warlock see that ibcm_local_handler_s::actual_cm_handler
68187c478bd9Sstevel@tonic-gate 	 * points to this routine.
68197c478bd9Sstevel@tonic-gate 	 */
68207c478bd9Sstevel@tonic-gate 	ibcm_local_handler_t	p;
68217c478bd9Sstevel@tonic-gate 	ibcm_ud_state_data_t	dummy_ud;
68227c478bd9Sstevel@tonic-gate 
68237c478bd9Sstevel@tonic-gate 	p.actual_cm_handler = ibcm_dummy_ud_handler;
68247c478bd9Sstevel@tonic-gate 	dummy_ud.ud_cm_handler = ibcm_dummy_ud_handler;
68257c478bd9Sstevel@tonic-gate 
68267c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_ud_handler: p.actual_cm_handler %p"
68277c478bd9Sstevel@tonic-gate 	    "dummy_ud.ud_cm_handler %p", p.actual_cm_handler,
68287c478bd9Sstevel@tonic-gate 	    dummy_ud.ud_cm_handler);
68297c478bd9Sstevel@tonic-gate 	/*
68307c478bd9Sstevel@tonic-gate 	 * Call all routines that the client's callback routine could call.
68317c478bd9Sstevel@tonic-gate 	 */
68327c478bd9Sstevel@tonic-gate 
68337c478bd9Sstevel@tonic-gate 	return (IBT_CM_ACCEPT);
68347c478bd9Sstevel@tonic-gate }
68357c478bd9Sstevel@tonic-gate 
68367c478bd9Sstevel@tonic-gate /* ARGSUSED */
68377c478bd9Sstevel@tonic-gate static ibt_cm_status_t
ibcm_dummy_rc_handler(void * priv,ibt_cm_event_t * event,ibt_cm_return_args_t * ret_args,void * priv_data,ibt_priv_data_len_t len)68387c478bd9Sstevel@tonic-gate ibcm_dummy_rc_handler(void *priv, ibt_cm_event_t *event,
68397c478bd9Sstevel@tonic-gate     ibt_cm_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
68407c478bd9Sstevel@tonic-gate {
68417c478bd9Sstevel@tonic-gate 	ibcm_state_data_t	dummy_rc;
68427c478bd9Sstevel@tonic-gate 
68437c478bd9Sstevel@tonic-gate 	dummy_rc.cm_handler = ibcm_dummy_rc_handler;
68447c478bd9Sstevel@tonic-gate 
68457c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_rc_handler: "
68467c478bd9Sstevel@tonic-gate 	    "dummy_ud.ud_cm_handler %p", dummy_rc.cm_handler);
68477c478bd9Sstevel@tonic-gate 	/*
68487c478bd9Sstevel@tonic-gate 	 * Call all routines that the client's callback routine could call.
68497c478bd9Sstevel@tonic-gate 	 */
68507c478bd9Sstevel@tonic-gate 
68517c478bd9Sstevel@tonic-gate 	return (IBT_CM_ACCEPT);
68527c478bd9Sstevel@tonic-gate }
6853