xref: /onnv-gate/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_ti.c (revision 12965:b65a8427f8fe)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51495Shiremath  * Common Development and Distribution License (the "License").
61495Shiremath  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
2212064SShantkumar.Hiremath@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <sys/ib/mgt/ibcm/ibcm_impl.h>
260Sstevel@tonic-gate #include <sys/ib/ibtl/ibti.h>
274703Shiremath #include <sys/ib/mgt/ibcm/ibcm_arp.h>
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * ibcm_ti.c
310Sstevel@tonic-gate  *	These routines implement the Communication Manager's interfaces to IBTL.
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate /* CM rc recycle task args structure definition */
350Sstevel@tonic-gate typedef struct ibcm_taskq_recycle_arg_s {
360Sstevel@tonic-gate 	ibt_channel_hdl_t	rc_chan;
370Sstevel@tonic-gate 	ibt_cep_flags_t		control;
380Sstevel@tonic-gate 	uint8_t			hca_port_num;
390Sstevel@tonic-gate 	ibt_recycle_handler_t	func;
400Sstevel@tonic-gate 	void			*arg;
410Sstevel@tonic-gate } ibcm_taskq_recycle_arg_t;
420Sstevel@tonic-gate 
430Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_taskq_recycle_arg_s))
440Sstevel@tonic-gate 
450Sstevel@tonic-gate static ibt_status_t	ibcm_init_reply_addr(ibcm_hca_info_t *hcap,
460Sstevel@tonic-gate     ibcm_mad_addr_t *reply_addr, ibt_chan_open_args_t *chan_args,
470Sstevel@tonic-gate     ibt_chan_open_flags_t flags, ib_time_t *cm_pkt_lt, ib_lid_t prim_slid);
480Sstevel@tonic-gate static void		ibcm_process_abort_via_taskq(void *args);
490Sstevel@tonic-gate static ibt_status_t	ibcm_process_rc_recycle_ret(void *recycle_arg);
500Sstevel@tonic-gate static ibt_status_t	ibcm_process_join_mcg(void *taskq_arg);
510Sstevel@tonic-gate static void		ibcm_process_async_join_mcg(void *tq_arg);
520Sstevel@tonic-gate 
539891SRajkumar.Sivaprakasam@Sun.COM ibt_status_t ibcm_get_node_rec(ibmf_saa_handle_t, sa_node_record_t *,
540Sstevel@tonic-gate     uint64_t c_mask, void *, size_t *);
550Sstevel@tonic-gate 
563241Shiremath static ibt_status_t ibcm_close_rc_channel(ibt_channel_hdl_t channel,
573241Shiremath     ibcm_state_data_t *statep, ibt_execution_mode_t mode);
583241Shiremath 
590Sstevel@tonic-gate /* Address Record management definitions */
600Sstevel@tonic-gate #define	IBCM_DAPL_ATS_NAME	"DAPL Address Translation Service"
610Sstevel@tonic-gate #define	IBCM_DAPL_ATS_SID	0x10000CE100415453ULL
620Sstevel@tonic-gate #define	IBCM_DAPL_ATS_NBYTES	16
630Sstevel@tonic-gate ibcm_svc_info_t *ibcm_ar_svcinfop;
640Sstevel@tonic-gate ibcm_ar_t	*ibcm_ar_list;
650Sstevel@tonic-gate 
663241Shiremath /*
673241Shiremath  * Tunable parameter to turnoff the overriding of pi_path_mtu value.
683241Shiremath  *	1 	By default override the path record's pi_path_mtu value to
693241Shiremath  *		IB_MTU_1K for all RC channels. This is done only for the
703241Shiremath  *		channels established on Tavor HCA and the path's pi_path_mtu
713241Shiremath  *		is greater than IB_MTU_1K.
723241Shiremath  *	0	Do not override, use pi_path_mtu by default.
733241Shiremath  */
743241Shiremath int	ibcm_override_path_mtu = 1;
753241Shiremath 
760Sstevel@tonic-gate #ifdef DEBUG
770Sstevel@tonic-gate static void	ibcm_print_reply_addr(ibt_channel_hdl_t channel,
780Sstevel@tonic-gate 		    ibcm_mad_addr_t *cm_reply_addr);
790Sstevel@tonic-gate #endif
800Sstevel@tonic-gate 
810Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_hdl}))
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /* access is controlled between ibcm_sm.c and ibcm_ti.c by CVs */
840Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Serialized access by CV", {ibt_rc_returns_t
850Sstevel@tonic-gate     ibt_ud_returns_t ibt_ap_returns_t ibt_ar_t}))
860Sstevel@tonic-gate 
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate  * Typically, clients initialize these args in one api call, and use in
890Sstevel@tonic-gate  * another api
900Sstevel@tonic-gate  */
910Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Expected usage of ibtl api by client",
920Sstevel@tonic-gate     {ibt_path_info_s ibt_cep_path_s ibt_adds_vect_s ibt_mcg_info_s ib_gid_s
930Sstevel@tonic-gate     ibt_ud_dest_attr_s ibt_ud_dest_s ibt_srv_data_s ibt_redirect_info_s}))
940Sstevel@tonic-gate 
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate  * ibt_open_rc_channel()
970Sstevel@tonic-gate  *	ibt_open_rc_channel opens a communication channel on the specified
980Sstevel@tonic-gate  *	channel to the specified service. For connection service type qp's
990Sstevel@tonic-gate  *	the CM initiates the CEP to establish the connection and transitions
1000Sstevel@tonic-gate  *	the QP/EEC to the "Ready to send" State modifying the QP/EEC's
1010Sstevel@tonic-gate  *	attributes as necessary.
1020Sstevel@tonic-gate  *	The implementation of this function assumes that alt path is different
1030Sstevel@tonic-gate  *	from primary path. It is assumed that the Path functions ensure that.
1040Sstevel@tonic-gate  *
1050Sstevel@tonic-gate  * RETURN VALUES:
1060Sstevel@tonic-gate  *	IBT_SUCCESS	on success (or respective failure on error)
1070Sstevel@tonic-gate  */
1080Sstevel@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)1090Sstevel@tonic-gate ibt_open_rc_channel(ibt_channel_hdl_t channel, ibt_chan_open_flags_t flags,
1100Sstevel@tonic-gate     ibt_execution_mode_t mode, ibt_chan_open_args_t *chan_args,
1110Sstevel@tonic-gate     ibt_rc_returns_t *ret_args)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate 	/* all fields that are related to REQ MAD formation */
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	ib_pkey_t		prim_pkey;
1160Sstevel@tonic-gate 	ib_lid_t		primary_slid, alternate_slid;
1170Sstevel@tonic-gate 	ib_qpn_t		local_qpn = 0;
1180Sstevel@tonic-gate 	ib_guid_t		hca_guid;
1190Sstevel@tonic-gate 	ib_qkey_t		local_qkey = 0;
1200Sstevel@tonic-gate 	ib_eecn_t		local_eecn = 0;
1210Sstevel@tonic-gate 	ib_eecn_t		remote_eecn = 0;
1220Sstevel@tonic-gate 	boolean_t		primary_grh;
1230Sstevel@tonic-gate 	boolean_t		alternate_grh = B_FALSE;
1240Sstevel@tonic-gate 	ib_lid_t		base_lid;
1250Sstevel@tonic-gate 	ib_com_id_t		local_comid;
1263241Shiremath 	ibmf_msg_t		*ibmf_msg, *ibmf_msg_dreq;
1270Sstevel@tonic-gate 	ibcm_req_msg_t		*req_msgp;
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	uint8_t			rdma_in, rdma_out;
1300Sstevel@tonic-gate 	uint8_t			cm_retries;
1310Sstevel@tonic-gate 	uint64_t		local_cm_proc_time;	/* In usec */
1320Sstevel@tonic-gate 	uint8_t			local_cm_resp_time;	/* IB time */
1330Sstevel@tonic-gate 	uint64_t		remote_cm_resp_time;	/* In usec */
1340Sstevel@tonic-gate 	uint32_t		starting_psn = 0;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	/* CM path related fields */
1370Sstevel@tonic-gate 	ibmf_handle_t		ibmf_hdl;
1380Sstevel@tonic-gate 	ibcm_qp_list_t		*cm_qp_entry;
1390Sstevel@tonic-gate 	ibcm_mad_addr_t		cm_reply_addr;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	uint8_t			cm_pkt_lt;
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	/* Local args for ibtl/internal CM functions called within */
1440Sstevel@tonic-gate 	ibt_status_t		status;
1450Sstevel@tonic-gate 	ibcm_status_t		lkup_status;
1460Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_query_attr;
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	/* Other misc local args */
1490Sstevel@tonic-gate 	ibt_priv_data_len_t	len;
1500Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
1510Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
1520Sstevel@tonic-gate 	uint8_t			port_no;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel(chan %p, %X, %x, %p, %p)",
1550Sstevel@tonic-gate 	    channel, flags, mode, chan_args, ret_args);
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
1580Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: invalid channel");
1590Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
1600Sstevel@tonic-gate 	}
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	/* cm handler should always be specified */
1630Sstevel@tonic-gate 	if (chan_args->oc_cm_handler == NULL) {
1641093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
1650Sstevel@tonic-gate 		    "CM handler is not be specified", channel);
1660Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING) {
1700Sstevel@tonic-gate 		if (ret_args != NULL) {
1710Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1721093Shiremath 			    " ret_args should be NULL when called in "
1730Sstevel@tonic-gate 			    "non-blocking mode", channel);
1740Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1750Sstevel@tonic-gate 		}
1760Sstevel@tonic-gate 	} else if (mode == IBT_BLOCKING) {
1770Sstevel@tonic-gate 		if (ret_args == NULL) {
1780Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1791093Shiremath 			    " ret_args should be Non-NULL when called in "
1800Sstevel@tonic-gate 			    "blocking mode", channel);
1810Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1820Sstevel@tonic-gate 		}
1830Sstevel@tonic-gate 		if (ret_args->rc_priv_data_len > IBT_REP_PRIV_DATA_SZ) {
1840Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1851093Shiremath 			    " private data length is too large", channel);
1860Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1870Sstevel@tonic-gate 		}
1880Sstevel@tonic-gate 		if ((ret_args->rc_priv_data_len > 0) &&
1890Sstevel@tonic-gate 		    (ret_args->rc_priv_data == NULL)) {
1900Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
1911093Shiremath 			    " rc_priv_data_len > 0, but rc_priv_data NULL",
1920Sstevel@tonic-gate 			    channel);
1930Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
1940Sstevel@tonic-gate 		}
1950Sstevel@tonic-gate 	} else { /* any other mode is not valid for ibt_open_rc_channel */
1961093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
1970Sstevel@tonic-gate 		    "invalid mode %x specified", channel, mode);
1980Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
1990Sstevel@tonic-gate 	}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	/*
2020Sstevel@tonic-gate 	 * XXX: no support yet for ibt_chan_open_flags_t - IBT_OCHAN_DUP
2030Sstevel@tonic-gate 	 */
2040Sstevel@tonic-gate 	if (flags & IBT_OCHAN_DUP) {
2051093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2060Sstevel@tonic-gate 		    "Unsupported Flags specified: 0x%X", channel, flags);
2070Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2080Sstevel@tonic-gate 	}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	if ((flags & IBT_OCHAN_REDIRECTED) &&
2110Sstevel@tonic-gate 	    (flags & IBT_OCHAN_PORT_REDIRECTED)) {
2121093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2130Sstevel@tonic-gate 		    "Illegal to specify IBT_OCHAN_REDIRECTED and "
2140Sstevel@tonic-gate 		    "IBT_OCHAN_PORT_REDIRECTED flags together", channel);
2150Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2160Sstevel@tonic-gate 	}
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	if (((flags & IBT_OCHAN_REDIRECTED) &&
2190Sstevel@tonic-gate 	    (chan_args->oc_cm_redirect_info == NULL)) ||
2200Sstevel@tonic-gate 	    ((flags & IBT_OCHAN_PORT_REDIRECTED) &&
2210Sstevel@tonic-gate 	    (chan_args->oc_cm_cep_path == NULL))) {
2221093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2230Sstevel@tonic-gate 		    "Redirect flag specified, but respective arg is NULL",
2240Sstevel@tonic-gate 		    channel);
2250Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	if ((flags & IBT_OCHAN_REDIRECTED) &&
2290Sstevel@tonic-gate 	    (chan_args->oc_cm_redirect_info->rdi_dlid == 0) &&
2300Sstevel@tonic-gate 	    (chan_args->oc_cm_redirect_info->rdi_gid.gid_guid == 0)) {
2311093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2320Sstevel@tonic-gate 		    "Either rdi_dlid or rdi_gid must be specified for"
2330Sstevel@tonic-gate 		    " IBT_OCHAN_REDIRECTED", channel);
2340Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	/* primary dlid and hca_port_num should never be zero */
2380Sstevel@tonic-gate 	port_no = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	if ((IBCM_PRIM_ADDS_VECT(chan_args).av_dlid == 0) && (port_no == 0)) {
2411093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2420Sstevel@tonic-gate 		    "Primary Path's information is not valid", channel);
2430Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2440Sstevel@tonic-gate 	}
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	/* validate SID */
2470Sstevel@tonic-gate 	if (chan_args->oc_path->pi_sid == 0) {
2481093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2490Sstevel@tonic-gate 		    "ERROR: Service ID in path information is 0", channel);
2500Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2510Sstevel@tonic-gate 	}
2529349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p  SID %llX",
2539349SShantkumar.Hiremath@Sun.COM 	    channel, chan_args->oc_path->pi_sid);
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	/* validate rnr_retry_cnt (enum has more than 3 bits) */
2560Sstevel@tonic-gate 	if ((uint_t)chan_args->oc_path_rnr_retry_cnt > IBT_RNR_INFINITE_RETRY) {
2571093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2580Sstevel@tonic-gate 		    "ERROR: oc_path_rnr_retry_cnt(%d) is out of range",
2590Sstevel@tonic-gate 		    channel, chan_args->oc_path_rnr_retry_cnt);
2600Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
2610Sstevel@tonic-gate 	}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	/*
2640Sstevel@tonic-gate 	 * Ensure that client is not re-using a QP that is still associated
2650Sstevel@tonic-gate 	 * with a statep
2660Sstevel@tonic-gate 	 */
2670Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
2680Sstevel@tonic-gate 	if (statep != NULL) {
2690Sstevel@tonic-gate 		IBCM_RELEASE_CHAN_PRIVATE(channel);
2701093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2710Sstevel@tonic-gate 		    "Channel being re-used on active side", channel);
2720Sstevel@tonic-gate 		return (IBT_CHAN_IN_USE);
2730Sstevel@tonic-gate 	}
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	/* Get GUID from Channel */
2760Sstevel@tonic-gate 	hca_guid = ibt_channel_to_hca_guid(channel);
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	/* validate QP's hca guid with that from primary path  */
2790Sstevel@tonic-gate 	if (hca_guid != chan_args->oc_path->pi_hca_guid) {
2801093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2810Sstevel@tonic-gate 		    "GUID from Channel and primary path don't match", channel);
2820Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2830Sstevel@tonic-gate 		    "Channel GUID %llX primary path GUID %llX", channel,
2840Sstevel@tonic-gate 		    hca_guid, chan_args->oc_path->pi_hca_guid);
2850Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
2860Sstevel@tonic-gate 	}
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
2890Sstevel@tonic-gate 	    "Local HCA GUID %llX", channel, hca_guid);
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	status = ibt_query_qp(channel, &qp_query_attr);
2920Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
2931093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
2940Sstevel@tonic-gate 		    "ibt_query_qp failed %d", channel, status);
2950Sstevel@tonic-gate 		return (status);
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	/* If client specified "no port change on QP" */
2990Sstevel@tonic-gate 	if ((qp_query_attr.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
3000Sstevel@tonic-gate 	    port_no) && (flags & IBT_OCHAN_PORT_FIXED)) {
3011093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3020Sstevel@tonic-gate 		    "chan port %d and path port %d does not match", channel,
3030Sstevel@tonic-gate 		    qp_query_attr.qp_info.qp_transport.rc.rc_path. \
3040Sstevel@tonic-gate 		    cep_hca_port_num, port_no);
3050Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
3060Sstevel@tonic-gate 	}
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	if (qp_query_attr.qp_info.qp_trans != IBT_RC_SRV) {
3091093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3100Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel",
3110Sstevel@tonic-gate 		    channel);
3120Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	/* Check if QP is in INIT state or not */
3160Sstevel@tonic-gate 	if (qp_query_attr.qp_info.qp_state != IBT_STATE_INIT) {
3171093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3180Sstevel@tonic-gate 		    "QP is not in INIT state %x", channel,
3190Sstevel@tonic-gate 		    qp_query_attr.qp_info.qp_state);
3200Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
3210Sstevel@tonic-gate 	}
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	local_qpn = qp_query_attr.qp_qpn;
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p Active QPN 0x%x",
3260Sstevel@tonic-gate 	    channel, local_qpn);
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate #ifdef	NO_EEC_SUPPORT_YET
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	if (flags & IBT_OCHAN_RDC_EXISTS) {
3310Sstevel@tonic-gate 		ibt_eec_query_attr_t	eec_query_attr;
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 		local_qkey = qp_query_attr.qp_info.qp_transport.rd_qkey;
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: RD");
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 		status = ibt_query_eec(channel, &eec_query_attr);
3380Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
3390Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
3401093Shiremath 			    " ibt_query_eec failed %d", channel, status);
3410Sstevel@tonic-gate 			return (status);
3420Sstevel@tonic-gate 		}
3430Sstevel@tonic-gate 		local_eecn = eec_query_attr.eec_eecn;
3440Sstevel@tonic-gate 	}
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate #endif
3476709Shiremath 	if (chan_args->oc_path->pi_prim_pkt_lt > ibcm_max_ib_pkt_lt) {
3486709Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3496709Shiremath 		    "Huge PktLifeTime %d, Max is %d", channel,
3506709Shiremath 		    chan_args->oc_path->pi_prim_pkt_lt, ibcm_max_ib_pkt_lt);
3516709Shiremath 		return (IBT_PATH_PKT_LT_TOO_HIGH);
3526709Shiremath 	}
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	/* If no HCA found return failure */
3550Sstevel@tonic-gate 	if ((hcap = ibcm_find_hca_entry(hca_guid)) == NULL) {
3560Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3570Sstevel@tonic-gate 		    "hcap is NULL. Probably hca is not in active state",
3580Sstevel@tonic-gate 		    channel);
3590Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
3600Sstevel@tonic-gate 	}
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	rdma_out = chan_args->oc_rdma_ra_out;
3630Sstevel@tonic-gate 	rdma_in = chan_args->oc_rdma_ra_in;
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	if ((rdma_in > hcap->hca_max_rdma_in_qp) ||
3660Sstevel@tonic-gate 	    (rdma_out > hcap->hca_max_rdma_out_qp)) {
3671093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3686709Shiremath 		    "rdma in %d/out %d values exceed hca limits(%d/%d)",
3696709Shiremath 		    channel, rdma_in, rdma_out, hcap->hca_max_rdma_in_qp,
3706709Shiremath 		    hcap->hca_max_rdma_out_qp);
3710Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
3720Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 
3751093Shiremath 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
3760Sstevel@tonic-gate 	    "rdma_in %d rdma_out %d", channel, rdma_in, rdma_out);
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	status = ibt_get_port_state_byguid(hcap->hca_guid, port_no,
3790Sstevel@tonic-gate 	    NULL, &base_lid);
3800Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
3811093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3820Sstevel@tonic-gate 		    "primary port_num %d not active", channel, port_no);
3830Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
3840Sstevel@tonic-gate 		return (status);
3850Sstevel@tonic-gate 	}
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	/* Validate P_KEY Index */
3880Sstevel@tonic-gate 	status = ibt_index2pkey_byguid(hcap->hca_guid, port_no,
3890Sstevel@tonic-gate 	    IBCM_PRIM_CEP_PATH(chan_args).cep_pkey_ix, &prim_pkey);
3900Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
3910Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
3920Sstevel@tonic-gate 		    "Invalid Primary PKeyIx %x", channel,
3930Sstevel@tonic-gate 		    IBCM_PRIM_CEP_PATH(chan_args).cep_pkey_ix);
3940Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
3950Sstevel@tonic-gate 		return (status);
3960Sstevel@tonic-gate 	}
3970Sstevel@tonic-gate 
3981093Shiremath 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
3990Sstevel@tonic-gate 	    "primary_port_num %d primary_pkey 0x%x", channel, port_no,
4000Sstevel@tonic-gate 	    prim_pkey);
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	if ((hcap->hca_port_info[port_no - 1].port_ibmf_hdl == NULL) &&
4030Sstevel@tonic-gate 	    ((status = ibcm_hca_reinit_port(hcap, port_no - 1))
4040Sstevel@tonic-gate 	    != IBT_SUCCESS)) {
4051093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4060Sstevel@tonic-gate 		    "ibmf reg or callback setup failed during re-initialize",
4070Sstevel@tonic-gate 		    channel);
4080Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
4090Sstevel@tonic-gate 		return (status);
4100Sstevel@tonic-gate 	}
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	ibmf_hdl = hcap->hca_port_info[port_no - 1].port_ibmf_hdl;
4130Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
4140Sstevel@tonic-gate 	    "primary ibmf_hdl = 0x%p", channel, ibmf_hdl);
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	primary_slid = base_lid + IBCM_PRIM_ADDS_VECT(chan_args).av_src_path;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: channel 0x%p "
4190Sstevel@tonic-gate 	    "primary SLID = %x", channel, primary_slid);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	/* check first if alternate path exists or not as it is OPTIONAL */
4220Sstevel@tonic-gate 	if (IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num != 0) {
4230Sstevel@tonic-gate 		uint8_t	alt_port_no;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 		alt_port_no = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 		if (chan_args->oc_path->pi_alt_pkt_lt > ibcm_max_ib_pkt_lt) {
4280Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4290Sstevel@tonic-gate 			    "Huge Alt Pkt lt %d", channel,
4300Sstevel@tonic-gate 			    chan_args->oc_path->pi_alt_pkt_lt);
4310Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
4320Sstevel@tonic-gate 			return (IBT_PATH_PKT_LT_TOO_HIGH);
4330Sstevel@tonic-gate 		}
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 		if (port_no != alt_port_no) {
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 			status = ibt_get_port_state_byguid(hcap->hca_guid,
4380Sstevel@tonic-gate 			    alt_port_no, NULL, &base_lid);
4390Sstevel@tonic-gate 			if (status != IBT_SUCCESS) {
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
4420Sstevel@tonic-gate 				    "chan 0x%p alt_port_num %d inactive %d",
4430Sstevel@tonic-gate 				    channel, alt_port_no, status);
4440Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
4450Sstevel@tonic-gate 				return (status);
4460Sstevel@tonic-gate 			}
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 		}
4490Sstevel@tonic-gate 		alternate_slid =
4500Sstevel@tonic-gate 		    base_lid + IBCM_ALT_ADDS_VECT(chan_args).av_src_path;
4510Sstevel@tonic-gate 
4526709Shiremath 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
4530Sstevel@tonic-gate 		    "alternate SLID = %x", channel, alternate_slid);
4540Sstevel@tonic-gate 	}
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	/*
4570Sstevel@tonic-gate 	 * only pkey needs to be zero'ed, because all other fields are set in
4580Sstevel@tonic-gate 	 * in ibcm_init_reply_addr. But, let's bzero the complete struct for
4590Sstevel@tonic-gate 	 * any future modifications.
4600Sstevel@tonic-gate 	 */
4610Sstevel@tonic-gate 	bzero(&cm_reply_addr, sizeof (cm_reply_addr));
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	/* Initialize the MAD destination address in stored_reply_addr */
4640Sstevel@tonic-gate 	if ((status = ibcm_init_reply_addr(hcap, &cm_reply_addr, chan_args,
4650Sstevel@tonic-gate 	    flags, &cm_pkt_lt, primary_slid)) != IBT_SUCCESS) {
4660Sstevel@tonic-gate 
4671093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4680Sstevel@tonic-gate 		    "ibcm_init_reply_addr failed status %d ", channel, status);
4690Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
4700Sstevel@tonic-gate 		return (status);
4710Sstevel@tonic-gate 	}
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	/* Initialize the pkey for CM MAD communication */
4750Sstevel@tonic-gate 	if (cm_reply_addr.rcvd_addr.ia_p_key == 0)
4760Sstevel@tonic-gate 		cm_reply_addr.rcvd_addr.ia_p_key = prim_pkey;
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate #ifdef DEBUG
4790Sstevel@tonic-gate 	ibcm_print_reply_addr(channel, &cm_reply_addr);
4800Sstevel@tonic-gate #endif
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	/* Retrieve an ibmf qp for sending CM MADs */
4830Sstevel@tonic-gate 	if ((cm_qp_entry = ibcm_find_qp(hcap, port_no,
4840Sstevel@tonic-gate 	    cm_reply_addr.rcvd_addr.ia_p_key)) == NULL) {
4851093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
4860Sstevel@tonic-gate 		    "unable to allocate ibmf qp for CM MADs", channel);
4870Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
4880Sstevel@tonic-gate 		return (IBT_INSUFF_RESOURCE);
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
4930Sstevel@tonic-gate 		ibcm_release_qp(cm_qp_entry);
4940Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
4950Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
4960Sstevel@tonic-gate 		    " Unable to allocate comid", channel);
4970Sstevel@tonic-gate 		return (IBT_INSUFF_KERNEL_RESOURCE);
4980Sstevel@tonic-gate 	}
4990Sstevel@tonic-gate 
5003241Shiremath 	/* allocate an IBMF mad buffer (REQ) */
5010Sstevel@tonic-gate 	if ((status = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg,
5020Sstevel@tonic-gate 	    MAD_METHOD_SEND)) != IBT_SUCCESS) {
5030Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
5040Sstevel@tonic-gate 		    "chan 0x%p ibcm_alloc_out_msg failed", channel);
5050Sstevel@tonic-gate 		ibcm_release_qp(cm_qp_entry);
5060Sstevel@tonic-gate 		ibcm_free_comid(hcap, local_comid);
5070Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
5080Sstevel@tonic-gate 		return (status);
5090Sstevel@tonic-gate 	}
5100Sstevel@tonic-gate 
5113241Shiremath 	/* allocate an IBMF mad buffer (DREQ) */
5123241Shiremath 	if ((status = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg_dreq,
5133241Shiremath 	    MAD_METHOD_SEND)) != IBT_SUCCESS) {
5143241Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
5153241Shiremath 		    "chan 0x%p ibcm_alloc_out_msg failed", channel);
5163241Shiremath 		(void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg);
5173241Shiremath 		ibcm_release_qp(cm_qp_entry);
5183241Shiremath 		ibcm_free_comid(hcap, local_comid);
5193241Shiremath 		ibcm_dec_hca_acc_cnt(hcap);
5203241Shiremath 		return (status);
5213241Shiremath 	}
5223241Shiremath 
5230Sstevel@tonic-gate 	/* Init to Init, if QP's port does not match with path information */
5240Sstevel@tonic-gate 	if (qp_query_attr.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
5250Sstevel@tonic-gate 	    IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num) {
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 		ibt_qp_info_t		qp_info;
5280Sstevel@tonic-gate 		ibt_cep_modify_flags_t	cep_flags;
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5310Sstevel@tonic-gate 		    "chan 0x%p chan port %d", channel,
5320Sstevel@tonic-gate 		    qp_query_attr.qp_info.qp_transport.rc.rc_path.\
5330Sstevel@tonic-gate 		    cep_hca_port_num);
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5360Sstevel@tonic-gate 		    "chan 0x%p path port %d", channel, port_no);
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 		bzero(&qp_info, sizeof (qp_info));
5390Sstevel@tonic-gate 		/* For now, set it to RC type */
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 		qp_info.qp_trans = IBT_RC_SRV;
5420Sstevel@tonic-gate 		qp_info.qp_state = IBT_STATE_INIT;
5430Sstevel@tonic-gate 		qp_info.qp_transport.rc.rc_path.cep_hca_port_num = port_no;
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 		cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 		status = ibt_modify_qp(channel, cep_flags, &qp_info, NULL);
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
5500Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
5510Sstevel@tonic-gate 			    "chan 0x%p ibt_modify_qp() = %d", channel, status);
5520Sstevel@tonic-gate 			ibcm_release_qp(cm_qp_entry);
5530Sstevel@tonic-gate 			ibcm_free_comid(hcap, local_comid);
5540Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
5550Sstevel@tonic-gate 			(void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg);
5563241Shiremath 			(void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg_dreq);
5570Sstevel@tonic-gate 			return (status);
5580Sstevel@tonic-gate 		} else
5590Sstevel@tonic-gate 			IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
5600Sstevel@tonic-gate 			    "chan 0x%p ibt_modify_qp() = %d", channel, status);
5610Sstevel@tonic-gate 	}
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	/* allocate ibcm_state_data_t before grabbing the WRITER lock */
5640Sstevel@tonic-gate 	statep = kmem_zalloc(sizeof (ibcm_state_data_t), KM_SLEEP);
5650Sstevel@tonic-gate 	rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
5660Sstevel@tonic-gate 	lkup_status = ibcm_lookup_msg(IBCM_OUTGOING_REQ, local_comid, 0, 0,
5670Sstevel@tonic-gate 	    hcap, &statep);
5680Sstevel@tonic-gate 	rw_exit(&hcap->hca_state_rwlock);
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	/* CM should be seeing this for the first time */
5710Sstevel@tonic-gate 	ASSERT(lkup_status == IBCM_LOOKUP_NEW);
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	/* Increment the hca's resource count */
5740Sstevel@tonic-gate 	ibcm_inc_hca_res_cnt(hcap);
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 	/* Once a resource created on hca, no need to hold the acc cnt */
5770Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	statep->timerid = 0;
5820Sstevel@tonic-gate 	statep->local_hca_guid = hca_guid;
5830Sstevel@tonic-gate 	statep->local_qpn = local_qpn;
5840Sstevel@tonic-gate 	statep->stored_reply_addr.cm_qp_entry = cm_qp_entry;
5850Sstevel@tonic-gate 	statep->prim_port = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
5860Sstevel@tonic-gate 	statep->alt_port = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	/* Save "statep" as channel's CM private data.  */
5900Sstevel@tonic-gate 	statep->channel = channel;
5910Sstevel@tonic-gate 	IBCM_SET_CHAN_PRIVATE(statep->channel, statep);
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	statep->stored_msg = ibmf_msg;
5943241Shiremath 	statep->dreq_msg = ibmf_msg_dreq;
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*req_msgp))
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	/* Start filling in the REQ MAD */
5990Sstevel@tonic-gate 	req_msgp = (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6000Sstevel@tonic-gate 	req_msgp->req_local_comm_id = h2b32(local_comid);
6010Sstevel@tonic-gate 	req_msgp->req_svc_id = h2b64(chan_args->oc_path->pi_sid);
6020Sstevel@tonic-gate 	req_msgp->req_local_ca_guid = h2b64(hca_guid);
6030Sstevel@tonic-gate 	req_msgp->req_local_qkey = h2b32(local_qkey);	/* for EEC/RD */
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	/* Bytes 32-35 are req_local_qpn and req_off_resp_resources */
6060Sstevel@tonic-gate 	req_msgp->req_local_qpn_plus = h2b32(local_qpn << 8 | rdma_in);
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate 	/* Bytes 36-39 are req_local_eec_no and req_off_initiator_depth */
6090Sstevel@tonic-gate 	req_msgp->req_local_eec_no_plus = h2b32(local_eecn << 8 | rdma_out);
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 	if (flags & IBT_OCHAN_REMOTE_CM_TM)
6120Sstevel@tonic-gate 		remote_cm_resp_time = chan_args->oc_remote_cm_time;
6130Sstevel@tonic-gate 	else
6140Sstevel@tonic-gate 		remote_cm_resp_time = ibcm_remote_response_time;
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	/*
6170Sstevel@tonic-gate 	 * Bytes 40-43 - remote_eecn, remote_cm_resp_time, tran_type,
6180Sstevel@tonic-gate 	 * IBT_CM_FLOW_CONTROL is always set by default.
6190Sstevel@tonic-gate 	 */
6200Sstevel@tonic-gate 	req_msgp->req_remote_eecn_plus = h2b32(
6210Sstevel@tonic-gate 	    remote_eecn << 8 | (ibt_usec2ib(remote_cm_resp_time) & 0x1f) << 3 |
6220Sstevel@tonic-gate 	    IBT_RC_SRV << 1 | IBT_CM_FLOW_CONTROL);
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 	if (flags & IBT_OCHAN_LOCAL_CM_TM)
6250Sstevel@tonic-gate 		local_cm_proc_time = chan_args->oc_local_cm_time;
6260Sstevel@tonic-gate 	else
6270Sstevel@tonic-gate 		local_cm_proc_time = ibcm_local_processing_time;
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate 	local_cm_resp_time = ibt_usec2ib(local_cm_proc_time +
6300Sstevel@tonic-gate 	    2 * ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt) +
6310Sstevel@tonic-gate 	    ibcm_sw_delay);
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	/* save retry count */
6340Sstevel@tonic-gate 	statep->cep_retry_cnt = chan_args->oc_path_retry_cnt;
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	if (flags & IBT_OCHAN_STARTING_PSN)
6370Sstevel@tonic-gate 		starting_psn = chan_args->oc_starting_psn;
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate 	if (local_cm_resp_time > 0x1f)
6400Sstevel@tonic-gate 		local_cm_resp_time = 0x1f;
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	/* Bytes 44-47 are req_starting_psn, local_cm_resp_time and retry_cnt */
6430Sstevel@tonic-gate 	req_msgp->req_starting_psn_plus = h2b32(starting_psn << 8 |
6440Sstevel@tonic-gate 	    local_cm_resp_time << 3 | statep->cep_retry_cnt);
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6470Sstevel@tonic-gate 	    "Prim Pkt lt (IB time) 0x%x", channel,
6480Sstevel@tonic-gate 	    chan_args->oc_path->pi_prim_pkt_lt);
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6510Sstevel@tonic-gate 	    "local_cm_proc_time(usec) %d ", channel, local_cm_proc_time);
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6540Sstevel@tonic-gate 	    "local_cm_resp_time(ib_time) %d", channel, local_cm_resp_time);
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
6570Sstevel@tonic-gate 	    "remote_cm_resp_time (usec) %d", channel, remote_cm_resp_time);
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 	statep->starting_psn = starting_psn;
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	/* Pkey - bytes 48-49 */
6620Sstevel@tonic-gate 	req_msgp->req_part_key = h2b16(prim_pkey);
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	if (flags & IBT_OCHAN_CM_RETRY)
6650Sstevel@tonic-gate 		cm_retries = chan_args->oc_cm_retry_cnt;
6660Sstevel@tonic-gate 	else
6670Sstevel@tonic-gate 		cm_retries = ibcm_max_retries;
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 	statep->max_cm_retries = statep->remaining_retry_cnt = cm_retries;
6700Sstevel@tonic-gate 	req_msgp->req_max_cm_retries_plus = statep->max_cm_retries << 4;
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 	/*
6730Sstevel@tonic-gate 	 * Check whether SRQ is associated with this Channel, if yes, then
6740Sstevel@tonic-gate 	 * set the SRQ Exists bit in the REQ.
6750Sstevel@tonic-gate 	 */
6760Sstevel@tonic-gate 	if (qp_query_attr.qp_srq != NULL) {
6770Sstevel@tonic-gate 		req_msgp->req_max_cm_retries_plus |= (1 << 3);
6780Sstevel@tonic-gate 	}
6790Sstevel@tonic-gate 
6803241Shiremath 	/*
6813241Shiremath 	 * By default on Tavor, we override the PathMTU to 1K.
6823241Shiremath 	 * To turn this off, set ibcm_override_path_mtu = 0.
6833241Shiremath 	 */
6843241Shiremath 	if (ibcm_override_path_mtu && IBCM_IS_HCA_TAVOR(hcap) &&
6853241Shiremath 	    (chan_args->oc_path->pi_path_mtu > IB_MTU_1K)) {
6863241Shiremath 		req_msgp->req_mtu_plus = IB_MTU_1K << 4 |
6873241Shiremath 		    chan_args->oc_path_rnr_retry_cnt;
6883241Shiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p PathMTU"
6899913SShantkumar.Hiremath@Sun.COM 		    " overridden to IB_MTU_1K(%d) from %d", channel, IB_MTU_1K,
6903241Shiremath 		    chan_args->oc_path->pi_path_mtu);
6913241Shiremath 	} else
6923241Shiremath 		req_msgp->req_mtu_plus = chan_args->oc_path->pi_path_mtu << 4 |
6933241Shiremath 		    chan_args->oc_path_rnr_retry_cnt;
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p CM retry cnt %d"
6961093Shiremath 	    " staring PSN %x", channel, cm_retries, starting_psn);
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate #ifdef	NO_EEC_SUPPORT_YET
7000Sstevel@tonic-gate 	if (flags & IBT_OCHAN_RDC_EXISTS)
7010Sstevel@tonic-gate 		req_msgp->req_mtu_plus |= 8;
7020Sstevel@tonic-gate #endif
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate 	/* Initialize the "primary" port stuff next - bytes 52-95 */
7050Sstevel@tonic-gate 	req_msgp->req_primary_l_port_lid = h2b16(primary_slid);
7060Sstevel@tonic-gate 	req_msgp->req_primary_r_port_lid =
7070Sstevel@tonic-gate 	    h2b16(IBCM_PRIM_ADDS_VECT(chan_args).av_dlid);
7080Sstevel@tonic-gate 	req_msgp->req_primary_l_port_gid.gid_prefix =
7090Sstevel@tonic-gate 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_sgid.gid_prefix);
7100Sstevel@tonic-gate 	req_msgp->req_primary_l_port_gid.gid_guid =
7110Sstevel@tonic-gate 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_sgid.gid_guid);
7120Sstevel@tonic-gate 	req_msgp->req_primary_r_port_gid.gid_prefix =
7130Sstevel@tonic-gate 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_prefix);
7140Sstevel@tonic-gate 	req_msgp->req_primary_r_port_gid.gid_guid =
7150Sstevel@tonic-gate 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid);
7160Sstevel@tonic-gate 	primary_grh = IBCM_PRIM_ADDS_VECT(chan_args).av_send_grh;
7170Sstevel@tonic-gate 
7181093Shiremath 	statep->remote_hca_guid = /* not correct, but helpful for debugging */
7191093Shiremath 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid;
7201093Shiremath 
7210Sstevel@tonic-gate 	/* Bytes 88-91 - primary_flowlbl, and primary_srate */
7220Sstevel@tonic-gate 	req_msgp->req_primary_flow_label_plus =
7230Sstevel@tonic-gate 	    h2b32(((primary_grh == B_TRUE) ?
7240Sstevel@tonic-gate 	    (IBCM_PRIM_ADDS_VECT(chan_args).av_flow << 12) : 0) |
7250Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_srate);
7260Sstevel@tonic-gate 	req_msgp->req_primary_traffic_class = (primary_grh == B_TRUE) ?
7270Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_tclass : 0;
7280Sstevel@tonic-gate 	req_msgp->req_primary_hop_limit = (primary_grh == B_TRUE) ?
7294970Shiremath 	    IBCM_PRIM_ADDS_VECT(chan_args).av_hop : 1;
7300Sstevel@tonic-gate 	req_msgp->req_primary_sl_plus =
7310Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_srvl << 4 |
7320Sstevel@tonic-gate 	    ((primary_grh == B_TRUE) ? 0 : 8);
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	req_msgp->req_primary_localtime_plus =
7350Sstevel@tonic-gate 	    ibt_usec2ib((2 * ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt)) +
7360Sstevel@tonic-gate 	    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan %p statep %p",
7390Sstevel@tonic-gate 	    channel, statep);
7400Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7410Sstevel@tonic-gate 	    "active hca_ack_delay (usec) %d", channel,
7420Sstevel@tonic-gate 	    req_msgp->req_primary_localtime_plus);
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7450Sstevel@tonic-gate 	    "Sent primary cep timeout (IB Time) %d", channel,
7460Sstevel@tonic-gate 	    hcap->hca_ack_delay);
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p prim_dlid %x ",
7490Sstevel@tonic-gate 	    channel, IBCM_PRIM_ADDS_VECT(chan_args).av_dlid);
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
7521093Shiremath 	    "prim GID %llX:%llX", channel,
7531093Shiremath 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_prefix,
7540Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid);
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	/* Initialize the "alternate" port stuff - optional */
7570Sstevel@tonic-gate 	if (chan_args->oc_path->pi_alt_cep_path.cep_hca_port_num != 0) {
7580Sstevel@tonic-gate 		ib_gid_t	tmp_gid;
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 		req_msgp->req_alt_l_port_lid = h2b16(alternate_slid);
7610Sstevel@tonic-gate 		req_msgp->req_alt_r_port_lid =
7620Sstevel@tonic-gate 		    h2b16(IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
7630Sstevel@tonic-gate 		/*
7640Sstevel@tonic-gate 		 * doing all this as req_alt_r/l_port_gid is at offset
7650Sstevel@tonic-gate 		 * 100, 116 which is not divisible by 8
7660Sstevel@tonic-gate 		 */
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 		tmp_gid.gid_prefix =
7690Sstevel@tonic-gate 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix);
7700Sstevel@tonic-gate 		tmp_gid.gid_guid =
7710Sstevel@tonic-gate 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
7720Sstevel@tonic-gate 		bcopy(&tmp_gid, &req_msgp->req_alt_r_port_gid[0],
7730Sstevel@tonic-gate 		    sizeof (ib_gid_t));
7740Sstevel@tonic-gate 		tmp_gid.gid_prefix =
7750Sstevel@tonic-gate 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_sgid.gid_prefix);
7760Sstevel@tonic-gate 		tmp_gid.gid_guid =
7770Sstevel@tonic-gate 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_sgid.gid_guid);
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 		bcopy(&tmp_gid, &req_msgp->req_alt_l_port_gid[0],
7800Sstevel@tonic-gate 		    sizeof (ib_gid_t));
7810Sstevel@tonic-gate 		alternate_grh = IBCM_ALT_ADDS_VECT(chan_args).av_send_grh;
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 		/* Bytes 132-135 - alternate_flow_label, and alternate srate */
7840Sstevel@tonic-gate 		req_msgp->req_alt_flow_label_plus = h2b32(
7850Sstevel@tonic-gate 		    (((alternate_grh == B_TRUE) ?
7860Sstevel@tonic-gate 		    (IBCM_ALT_ADDS_VECT(chan_args).av_flow << 12) : 0) |
7870Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_srate));
7880Sstevel@tonic-gate 		req_msgp->req_alt_traffic_class = (alternate_grh == B_TRUE) ?
7890Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_tclass : 0;
7900Sstevel@tonic-gate 		req_msgp->req_alt_hop_limit = (alternate_grh == B_TRUE) ?
7914970Shiremath 		    IBCM_ALT_ADDS_VECT(chan_args).av_hop : 1;
7920Sstevel@tonic-gate 		req_msgp->req_alt_sl_plus =
7930Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_srvl << 4 |
7940Sstevel@tonic-gate 		    ((alternate_grh == B_TRUE) ? 0 : 8);
7950Sstevel@tonic-gate 		req_msgp->req_alt_localtime_plus = ibt_usec2ib((2 *
7960Sstevel@tonic-gate 		    ibt_ib2usec(chan_args->oc_path->pi_alt_pkt_lt)) +
7970Sstevel@tonic-gate 		    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
7980Sstevel@tonic-gate 
7990Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
8000Sstevel@tonic-gate 		    "alt_dlid %x ", channel,
8010Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
8041093Shiremath 		    "alt GID %llX:%llX", channel,
8051093Shiremath 		    IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix,
8060Sstevel@tonic-gate 		    IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
8070Sstevel@tonic-gate 	}
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	len = min(chan_args->oc_priv_data_len, IBT_REQ_PRIV_DATA_SZ);
8100Sstevel@tonic-gate 	if ((len > 0) && chan_args->oc_priv_data)
8110Sstevel@tonic-gate 		bcopy(chan_args->oc_priv_data, req_msgp->req_private_data, len);
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*req_msgp))
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	/* return_data is filled up in the state machine code */
8160Sstevel@tonic-gate 	if (ret_args != NULL) {
8170Sstevel@tonic-gate 		statep->open_return_data = ret_args;
8180Sstevel@tonic-gate 	}
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	/* initialize some statep fields here */
8210Sstevel@tonic-gate 	statep->mode = IBCM_ACTIVE_MODE;
8220Sstevel@tonic-gate 	statep->hcap = hcap;
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	statep->cm_handler = chan_args->oc_cm_handler;
8250Sstevel@tonic-gate 	statep->state_cm_private = chan_args->oc_cm_clnt_private;
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate 	statep->pkt_life_time =
8280Sstevel@tonic-gate 	    ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt);
8290Sstevel@tonic-gate 
8301093Shiremath 	statep->timer_value = ibt_ib2usec(ibt_usec2ib(
8311093Shiremath 	    2 * ibt_ib2usec(cm_pkt_lt) + remote_cm_resp_time));
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 	/* Initialize statep->stored_reply_addr */
8340Sstevel@tonic-gate 	statep->stored_reply_addr.ibmf_hdl = ibmf_hdl;
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 	/* Initialize stored reply addr fields */
8370Sstevel@tonic-gate 	statep->stored_reply_addr.grh_hdr = cm_reply_addr.grh_hdr;
8380Sstevel@tonic-gate 	statep->stored_reply_addr.rcvd_addr = cm_reply_addr.rcvd_addr;
8390Sstevel@tonic-gate 	statep->stored_reply_addr.grh_exists = cm_reply_addr.grh_exists;
8400Sstevel@tonic-gate 	statep->stored_reply_addr.port_num = cm_reply_addr.port_num;
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 	/*
8430Sstevel@tonic-gate 	 * The IPD on local/active side is calculated by path functions,
8440Sstevel@tonic-gate 	 * hence available in the args of ibt_open_rc_channel
8450Sstevel@tonic-gate 	 */
8460Sstevel@tonic-gate 	statep->local_srate = IBCM_PRIM_ADDS_VECT(chan_args).av_srate;
8470Sstevel@tonic-gate 	statep->local_alt_srate = IBCM_ALT_ADDS_VECT(chan_args).av_srate;
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	/* Store the source path bits for primary and alt paths */
8500Sstevel@tonic-gate 	statep->prim_src_path_bits = IBCM_PRIM_ADDS_VECT(chan_args).av_src_path;
8510Sstevel@tonic-gate 	statep->alt_src_path_bits = IBCM_ALT_ADDS_VECT(chan_args).av_src_path;
8520Sstevel@tonic-gate 
8531093Shiremath 	statep->open_flow = 1;
8540Sstevel@tonic-gate 	statep->open_done = B_FALSE;
8550Sstevel@tonic-gate 	statep->state = statep->timer_stored_state = IBCM_STATE_REQ_SENT;
8561093Shiremath 	IBCM_REF_CNT_INCR(statep);	/* Decremented before return */
8571093Shiremath 	IBCM_REF_CNT_INCR(statep);	/* Decremented after REQ is posted */
8580Sstevel@tonic-gate 	statep->send_mad_flags |= IBCM_REQ_POST_BUSY;
8590Sstevel@tonic-gate 
86011369SPramod.Gunjikar@Sun.COM 	/*
86111369SPramod.Gunjikar@Sun.COM 	 * Skip moving channel to error state during close, for OFUV clients.
86211369SPramod.Gunjikar@Sun.COM 	 * OFUV clients transition the channel to error state by itself.
86311369SPramod.Gunjikar@Sun.COM 	 */
86411369SPramod.Gunjikar@Sun.COM 	if (flags & IBT_OCHAN_OFUV)
86511369SPramod.Gunjikar@Sun.COM 		statep->is_this_ofuv_chan = B_TRUE;
86611369SPramod.Gunjikar@Sun.COM 
8670Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
8680Sstevel@tonic-gate 	    h2b16(IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID);
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->stored_msg)->TransactionID =
8710Sstevel@tonic-gate 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_REQ, statep->local_comid,
8720Sstevel@tonic-gate 	    0));
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
8750Sstevel@tonic-gate 
87611369SPramod.Gunjikar@Sun.COM 	ibtl_cm_chan_is_opening(channel);
87711369SPramod.Gunjikar@Sun.COM 
8781093Shiremath 	ibcm_open_enqueue(statep);
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate 		/* wait for REQ/REP/RTU */
8850Sstevel@tonic-gate 		while (statep->open_done != B_TRUE) {
8860Sstevel@tonic-gate 			cv_wait(&statep->block_client_cv, &statep->state_mutex);
8870Sstevel@tonic-gate 		}
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 		/*
8900Sstevel@tonic-gate 		 * In the case that open_channel() fails because of a
8910Sstevel@tonic-gate 		 * REJ or timeout, change retval to IBT_CM_FAILURE
8920Sstevel@tonic-gate 		 */
89312064SShantkumar.Hiremath@Sun.COM 		if (statep->open_return_data->rc_status != IBT_CM_ACCEPT) {
8940Sstevel@tonic-gate 			status = IBT_CM_FAILURE;
89512064SShantkumar.Hiremath@Sun.COM 			ibtl_cm_chan_open_is_aborted(channel);
89612064SShantkumar.Hiremath@Sun.COM 		}
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p "
8990Sstevel@tonic-gate 		    "ret status %d cm status %d", channel, status,
9000Sstevel@tonic-gate 		    statep->open_return_data->rc_status);
9010Sstevel@tonic-gate 	}
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 	/* decrement the ref-count before leaving here */
9040Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_open_rc_channel: chan 0x%p done", channel);
9090Sstevel@tonic-gate 	return (status);
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate /*
9130Sstevel@tonic-gate  * ibcm_init_reply_addr:
9140Sstevel@tonic-gate  *
9150Sstevel@tonic-gate  * The brief description of functionality below.
9160Sstevel@tonic-gate  *
9170Sstevel@tonic-gate  * For IBT_OCHAN_PORT_REDIRECTED (ie., port redirected case):
9180Sstevel@tonic-gate  *	Build CM path from chan_args->oc_cm_cep_path
9190Sstevel@tonic-gate  *	Set CM pkt lt (ie.,life time) to chan_args->oc_cm_pkt_lt
9200Sstevel@tonic-gate  *
9210Sstevel@tonic-gate  * For IBT_OCHAN_REDIRECTED (ie., port and CM redirected case):
9220Sstevel@tonic-gate  *	If Redirect LID is specified,
9230Sstevel@tonic-gate  *		If Redirect GID is not specified or specified to be on the same
9240Sstevel@tonic-gate  *		    subnet, then
9250Sstevel@tonic-gate  *			Build CM path from chan_args->oc_cm_redirect_info
9260Sstevel@tonic-gate  *			Set CM pkt lt to subnet timeout
9270Sstevel@tonic-gate  *		Else (ie., GID specified, but on a different subnet)
9280Sstevel@tonic-gate  *			Do a path lookup to build CM Path and set CM pkt lt
9290Sstevel@tonic-gate  *
9300Sstevel@tonic-gate  */
9310Sstevel@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)9320Sstevel@tonic-gate ibcm_init_reply_addr(ibcm_hca_info_t *hcap, ibcm_mad_addr_t *reply_addr,
9330Sstevel@tonic-gate     ibt_chan_open_args_t *chan_args, ibt_chan_open_flags_t flags,
9340Sstevel@tonic-gate     ib_time_t *cm_pkt_lt, ib_lid_t prim_slid)
9350Sstevel@tonic-gate {
9360Sstevel@tonic-gate 	ibt_adds_vect_t	*cm_adds;
9370Sstevel@tonic-gate 	ibt_path_info_t	path;
9380Sstevel@tonic-gate 	boolean_t	cm_grh;
9390Sstevel@tonic-gate 	ibt_status_t	status;
9400Sstevel@tonic-gate 
9410Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_init_reply_addr:");
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*reply_addr))
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 	/*
9460Sstevel@tonic-gate 	 * sending side CM lid/gid/port num are not based on any redirect
9470Sstevel@tonic-gate 	 * params. These values are set to primary RC path lid/gid/port num.
9480Sstevel@tonic-gate 	 * In the future, these values can be set based on framework policy
9490Sstevel@tonic-gate 	 * decisions ensuring reachability.
9500Sstevel@tonic-gate 	 */
9510Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_sender_gid =
9520Sstevel@tonic-gate 	    IBCM_PRIM_ADDS_VECT(chan_args).av_sgid;
9530Sstevel@tonic-gate 	reply_addr->rcvd_addr.ia_local_lid = prim_slid;
9540Sstevel@tonic-gate 	reply_addr->port_num = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate 	if (flags & IBT_OCHAN_PORT_REDIRECTED) {
9570Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
9580Sstevel@tonic-gate 		    "IBT_OCHAN_PORT_REDIRECTED specified");
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate 		status = ibt_index2pkey_byguid(hcap->hca_guid,
9610Sstevel@tonic-gate 		    chan_args->oc_cm_cep_path->cep_hca_port_num,
9620Sstevel@tonic-gate 		    chan_args->oc_cm_cep_path->cep_pkey_ix,
9630Sstevel@tonic-gate 		    &reply_addr->rcvd_addr.ia_p_key);
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
9660Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_init_rely_addr: Invalid "
9670Sstevel@tonic-gate 			    "CM PKeyIx %x port_num %x",
9680Sstevel@tonic-gate 			    chan_args->oc_cm_cep_path->cep_pkey_ix,
9690Sstevel@tonic-gate 			    chan_args->oc_cm_cep_path->cep_hca_port_num);
9700Sstevel@tonic-gate 			return (status);
9710Sstevel@tonic-gate 		}
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 		cm_adds = &(chan_args->oc_cm_cep_path->cep_adds_vect);
9740Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: dlid = %x",
9750Sstevel@tonic-gate 		    cm_adds->av_dlid);
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_q_key = IB_GSI_QKEY;
9780Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_remote_qno = 1;
9790Sstevel@tonic-gate 		*cm_pkt_lt = chan_args->oc_cm_pkt_lt;
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 	} else if (flags & IBT_OCHAN_REDIRECTED) {
9820Sstevel@tonic-gate 		ibt_redirect_info_t	*redirect_info;
9830Sstevel@tonic-gate 		ibt_hca_portinfo_t	*port_infop;
9840Sstevel@tonic-gate 		uint_t			psize, nports;
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
9870Sstevel@tonic-gate 		    "IBT_OCHAN_REDIRECTED specified");
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 		redirect_info = chan_args->oc_cm_redirect_info;
9900Sstevel@tonic-gate 
9911093Shiremath 		if ((redirect_info->rdi_gid.gid_prefix == 0) ||
9921093Shiremath 		    (redirect_info->rdi_gid.gid_guid == 0)) {
9931093Shiremath 			IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
9941093Shiremath 			    "ERROR: Re-direct GID value NOT Provided.");
9951093Shiremath 			return (IBT_INVALID_PARAM);
9961093Shiremath 		}
9971093Shiremath 
9980Sstevel@tonic-gate 		/* As per spec definition 1.1, it's always IB_GSI_QKEY */
9990Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_q_key = redirect_info->rdi_qkey;
10000Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_remote_qno = redirect_info->rdi_qpn;
10010Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_p_key = redirect_info->rdi_pkey;
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 		/*
10041093Shiremath 		 * if LID is non-zero in classportinfo then use classportinfo
10051093Shiremath 		 * fields to form CM MAD destination address.
10060Sstevel@tonic-gate 		 */
10071093Shiremath 		if (redirect_info->rdi_dlid != 0) {
10080Sstevel@tonic-gate 			status = ibtl_cm_query_hca_ports_byguid(hcap->hca_guid,
10090Sstevel@tonic-gate 			    reply_addr->port_num, &port_infop, &nports, &psize);
10100Sstevel@tonic-gate 			if ((status != IBT_SUCCESS) || (nports == 0)) {
10110Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
10120Sstevel@tonic-gate 				    "Query Ports Failed: %d", status);
10130Sstevel@tonic-gate 				return (status);
10140Sstevel@tonic-gate 			} else if (port_infop->p_subnet_timeout >
10155752Shiremath 			    ibcm_max_ib_pkt_lt) {
10160Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
10170Sstevel@tonic-gate 				    "large subnet timeout %x port_no %x",
10180Sstevel@tonic-gate 				    port_infop->p_subnet_timeout,
10190Sstevel@tonic-gate 				    reply_addr->port_num);
10200Sstevel@tonic-gate 				ibt_free_portinfo(port_infop, psize);
10210Sstevel@tonic-gate 				return (IBT_PATH_PKT_LT_TOO_HIGH);
10220Sstevel@tonic-gate 			} else {
10230Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibcm_init_reply_addr: "
10240Sstevel@tonic-gate 				    "subnet timeout %x port_no %x",
10250Sstevel@tonic-gate 				    port_infop->p_subnet_timeout,
10260Sstevel@tonic-gate 				    reply_addr->port_num);
10270Sstevel@tonic-gate 
10280Sstevel@tonic-gate 				*cm_pkt_lt =
10290Sstevel@tonic-gate 				    ibt_ib2usec(min(ibcm_max_ib_mad_pkt_lt,
10300Sstevel@tonic-gate 				    port_infop->p_subnet_timeout));
10310Sstevel@tonic-gate 
10320Sstevel@tonic-gate 				ibt_free_portinfo(port_infop, psize);
10330Sstevel@tonic-gate 			}
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate 			reply_addr->rcvd_addr.ia_remote_lid =
10360Sstevel@tonic-gate 			    redirect_info->rdi_dlid;
10370Sstevel@tonic-gate 			reply_addr->rcvd_addr.ia_service_level =
10380Sstevel@tonic-gate 			    redirect_info->rdi_sl;
10391093Shiremath 			reply_addr->grh_exists = B_TRUE;
10401093Shiremath 			reply_addr->grh_hdr.ig_recver_gid =
10411093Shiremath 			    redirect_info->rdi_gid;
10421093Shiremath 			reply_addr->grh_hdr.ig_tclass =
10431093Shiremath 			    redirect_info->rdi_tclass;
10441093Shiremath 			reply_addr->grh_hdr.ig_flow_label =
10451093Shiremath 			    redirect_info->rdi_flow;
10461093Shiremath 
10471093Shiremath 			/* Classportinfo doesn't have hoplimit field */
10484970Shiremath 			reply_addr->grh_hdr.ig_hop_limit = 1;
10490Sstevel@tonic-gate 			return (IBT_SUCCESS);
10500Sstevel@tonic-gate 
10511093Shiremath 		} else {
10520Sstevel@tonic-gate 			ibt_path_attr_t	path_attr;
10530Sstevel@tonic-gate 			ib_gid_t	path_dgid[1];
10540Sstevel@tonic-gate 
10550Sstevel@tonic-gate 			/*
10560Sstevel@tonic-gate 			 * If GID is specified, and LID is zero in classportinfo
10571093Shiremath 			 * do a path lookup using specified GID, Pkey,
10580Sstevel@tonic-gate 			 * in classportinfo
10590Sstevel@tonic-gate 			 */
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 			bzero(&path_attr, sizeof (path_attr));
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 			path_attr.pa_dgids = &path_dgid[0];
10640Sstevel@tonic-gate 			path_attr.pa_dgids[0] = redirect_info->rdi_gid;
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 			/*
10670Sstevel@tonic-gate 			 * use reply_addr below, as sender_gid in reply_addr
10680Sstevel@tonic-gate 			 * may have been set above based on some policy decision
10690Sstevel@tonic-gate 			 * for originating end point for CM MADs above
10700Sstevel@tonic-gate 			 */
10710Sstevel@tonic-gate 			path_attr.pa_sgid = reply_addr->grh_hdr.ig_sender_gid;
10720Sstevel@tonic-gate 			path_attr.pa_num_dgids = 1;
10730Sstevel@tonic-gate 			path_attr.pa_pkey = redirect_info->rdi_pkey;
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 			if ((status = ibt_get_paths(ibcm_ibt_handle,
10761093Shiremath 			    IBT_PATH_PKEY, &path_attr, 1, &path, NULL)) !=
10770Sstevel@tonic-gate 			    IBT_SUCCESS)
10780Sstevel@tonic-gate 				return (status);
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 			/* Initialize cm_adds */
10810Sstevel@tonic-gate 			cm_adds = &path.pi_prim_cep_path.cep_adds_vect;
10820Sstevel@tonic-gate 			*cm_pkt_lt = path.pi_prim_pkt_lt;
10830Sstevel@tonic-gate 		}
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate 	} else	{ /* cm_pkey initialized in ibt_open_rc_channel */
10860Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_q_key = IB_GSI_QKEY;
10870Sstevel@tonic-gate 		reply_addr->rcvd_addr.ia_remote_qno = 1;
10880Sstevel@tonic-gate 		*cm_pkt_lt = chan_args->oc_path->pi_prim_pkt_lt;
10890Sstevel@tonic-gate 		cm_adds = &(IBCM_PRIM_ADDS_VECT(chan_args));
10900Sstevel@tonic-gate 	}
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	cm_grh = cm_adds->av_send_grh;
10940Sstevel@tonic-gate 	reply_addr->grh_exists = cm_grh;
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate 	reply_addr->rcvd_addr.ia_remote_lid =
10970Sstevel@tonic-gate 	    cm_adds->av_dlid;
10980Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_recver_gid =
10990Sstevel@tonic-gate 	    cm_adds->av_dgid;
11000Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_flow_label =
11010Sstevel@tonic-gate 	    cm_adds->av_flow & IB_GRH_FLOW_LABEL_MASK;
11020Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_tclass =
11030Sstevel@tonic-gate 	    (cm_grh == B_TRUE) ? cm_adds->av_tclass : 0;
11040Sstevel@tonic-gate 	reply_addr->grh_hdr.ig_hop_limit =
11054970Shiremath 	    (cm_grh == B_TRUE) ? cm_adds->av_hop : 1;
11060Sstevel@tonic-gate 	reply_addr->rcvd_addr.ia_service_level =
11070Sstevel@tonic-gate 	    cm_adds->av_srvl;
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*reply_addr))
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate 	return (IBT_SUCCESS);
11120Sstevel@tonic-gate }
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate /*
11160Sstevel@tonic-gate  * ibt_prime_close_rc_channel()
11170Sstevel@tonic-gate  *	It allocates resources required for close channel operation, so
11180Sstevel@tonic-gate  *	ibt_close_rc_channel can be called from interrupt routine.
11190Sstevel@tonic-gate  *
11200Sstevel@tonic-gate  * INPUTS:
11210Sstevel@tonic-gate  *	channel			The address of an ibt_channel_t struct that
11220Sstevel@tonic-gate  *				specifies the channel to open.
11230Sstevel@tonic-gate  *
11240Sstevel@tonic-gate  * RETURN VALUES:
11250Sstevel@tonic-gate  *	IBT_SUCCESS	on success(or respective failure on error)
11260Sstevel@tonic-gate  *
11270Sstevel@tonic-gate  * Clients are typically expected to call this function in established state
11280Sstevel@tonic-gate  */
11290Sstevel@tonic-gate ibt_status_t
ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)11300Sstevel@tonic-gate ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)
11310Sstevel@tonic-gate {
11320Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
11330Sstevel@tonic-gate 	ibt_status_t		status = IBT_SUCCESS;
11340Sstevel@tonic-gate 
11350Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_prime_close_rc_channel(%p)", channel);
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	/* validate channel, first */
11380Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
11391093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11400Sstevel@tonic-gate 		    "invalid channel", channel);
11410Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
11420Sstevel@tonic-gate 	}
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
11451093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11460Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel",
11470Sstevel@tonic-gate 		    channel);
11480Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
11490Sstevel@tonic-gate 	}
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 	/* get the statep */
11520Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	/*
11550Sstevel@tonic-gate 	 * This can happen, if the statep is already gone by a DREQ from
11560Sstevel@tonic-gate 	 * the remote side
11570Sstevel@tonic-gate 	 */
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate 	if (statep == NULL) {
11601093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11610Sstevel@tonic-gate 		    "statep NULL", channel);
11620Sstevel@tonic-gate 		return (IBT_SUCCESS);
11630Sstevel@tonic-gate 	}
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
11660Sstevel@tonic-gate 	IBCM_RELEASE_CHAN_PRIVATE(channel);
11670Sstevel@tonic-gate 	if (statep->state != IBCM_STATE_ESTABLISHED) {
11680Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
11690Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
11700Sstevel@tonic-gate 	}
11710Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);
11720Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_prime_close_rc_channel: chan 0x%p statep %p"
11731093Shiremath 	    " state %x", channel, statep, statep->state);
11740Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
11750Sstevel@tonic-gate 
11760Sstevel@tonic-gate 	/* clients could pre-allocate dreq mad, even before connection est */
11770Sstevel@tonic-gate 	if (statep->dreq_msg == NULL)
11780Sstevel@tonic-gate 		status = ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl,
11790Sstevel@tonic-gate 		    &statep->dreq_msg, MAD_METHOD_SEND);
11800Sstevel@tonic-gate 
11810Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
11820Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
11830Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
11860Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
11870Sstevel@tonic-gate 		    "ibcm_alloc_out_msg failed ", channel);
11880Sstevel@tonic-gate 		return (status);
11890Sstevel@tonic-gate 	}
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	/* If this message isn't seen then ibt_prime_close_rc_channel failed */
11920Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_prime_close_rc_channel: chan 0x%p done",
11930Sstevel@tonic-gate 	    channel);
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate 	return (IBT_SUCCESS);
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate 
11980Sstevel@tonic-gate /*
11990Sstevel@tonic-gate  * ibt_close_rc_channel()
12000Sstevel@tonic-gate  *	It closes an established channel.
12010Sstevel@tonic-gate  *
12020Sstevel@tonic-gate  * RETURN VALUES:
12030Sstevel@tonic-gate  *	IBT_SUCCESS	on success(or respective failure on error)
12040Sstevel@tonic-gate  */
12050Sstevel@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)12060Sstevel@tonic-gate ibt_close_rc_channel(ibt_channel_hdl_t channel, ibt_execution_mode_t mode,
12070Sstevel@tonic-gate     void *priv_data, ibt_priv_data_len_t priv_data_len, uint8_t *ret_status,
12080Sstevel@tonic-gate     void *ret_priv_data, ibt_priv_data_len_t *ret_priv_data_len_p)
12090Sstevel@tonic-gate {
12100Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
12110Sstevel@tonic-gate 
12120Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel(%p, %x, %p, %d, %p)",
12130Sstevel@tonic-gate 	    channel, mode, priv_data, priv_data_len,
12140Sstevel@tonic-gate 	    (ret_priv_data_len_p == NULL) ? 0 : *ret_priv_data_len_p);
12150Sstevel@tonic-gate 
12160Sstevel@tonic-gate 	/* validate channel, first */
12170Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
12180Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12190Sstevel@tonic-gate 		    "invalid channel", channel);
12200Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
12210Sstevel@tonic-gate 	}
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
12241093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12250Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel",
12260Sstevel@tonic-gate 		    channel);
12270Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
12280Sstevel@tonic-gate 	}
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
12310Sstevel@tonic-gate 		/* valid only for BLOCKING MODE */
12320Sstevel@tonic-gate 		if ((ret_priv_data_len_p != NULL) &&
12330Sstevel@tonic-gate 		    (*ret_priv_data_len_p > IBT_DREP_PRIV_DATA_SZ)) {
12340Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p"
12351093Shiremath 			    " private data len %d is too large", channel,
12360Sstevel@tonic-gate 			    *ret_priv_data_len_p);
12370Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
12380Sstevel@tonic-gate 		}
12390Sstevel@tonic-gate 	} else if ((mode != IBT_NONBLOCKING) && (mode != IBT_NOCALLBACKS)) {
12401093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12410Sstevel@tonic-gate 		    "invalid mode %x specified", channel, mode);
12420Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
12430Sstevel@tonic-gate 	}
12440Sstevel@tonic-gate 
12453241Shiremath 	if (ibtl_cm_is_chan_closing(channel) ||
12463241Shiremath 	    ibtl_cm_is_chan_closed(channel)) {
12473241Shiremath 		if (ret_status)
12483241Shiremath 			*ret_status = IBT_CM_CLOSED_ALREADY;
12493241Shiremath 
12503241Shiremath 		/* No private data to return to the client */
12513241Shiremath 		if (ret_priv_data_len_p != NULL)
12523241Shiremath 			*ret_priv_data_len_p = 0;
12533241Shiremath 
12545214Sagiri 		if ((mode == IBT_BLOCKING) ||
12555214Sagiri 		    (mode == IBT_NOCALLBACKS)) {
12565214Sagiri 			IBCM_GET_CHAN_PRIVATE(channel, statep);
12575214Sagiri 			if (statep == NULL)
12585214Sagiri 				return (IBT_SUCCESS);
12595214Sagiri 			mutex_enter(&statep->state_mutex);
12605214Sagiri 			IBCM_RELEASE_CHAN_PRIVATE(channel);
12615214Sagiri 			IBCM_REF_CNT_INCR(statep);
12625214Sagiri 			while (statep->close_done != B_TRUE)
12635214Sagiri 				cv_wait(&statep->block_client_cv,
12645214Sagiri 				    &statep->state_mutex);
12655214Sagiri 			IBCM_REF_CNT_DECR(statep);
12665214Sagiri 			mutex_exit(&statep->state_mutex);
12675214Sagiri 		}
12685214Sagiri 
12693241Shiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel: chan 0x%p "
12703241Shiremath 		    "already marked for closing", channel);
12713241Shiremath 
12723241Shiremath 		return (IBT_SUCCESS);
12733241Shiremath 	}
12743241Shiremath 
12750Sstevel@tonic-gate 	/* get the statep */
12760Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
12770Sstevel@tonic-gate 	if (statep == NULL) {
12780Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12790Sstevel@tonic-gate 		    "statep NULL", channel);
12800Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
12810Sstevel@tonic-gate 	}
12820Sstevel@tonic-gate 
12830Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
12843241Shiremath 
12853241Shiremath 	if (statep->dreq_msg == NULL) {
12864703Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
12873241Shiremath 		    "Fatal Error: dreq_msg is NULL", channel);
12883241Shiremath 		IBCM_RELEASE_CHAN_PRIVATE(channel);
12893241Shiremath 		mutex_exit(&statep->state_mutex);
12903241Shiremath 		return (IBT_CHAN_STATE_INVALID);
12913241Shiremath 	}
12923241Shiremath 
12933241Shiremath 	if ((ret_priv_data == NULL) || (ret_priv_data_len_p == NULL)) {
12943241Shiremath 		statep->close_ret_priv_data = NULL;
12953241Shiremath 		statep->close_ret_priv_data_len = NULL;
12963241Shiremath 	} else {
12973241Shiremath 		statep->close_ret_priv_data = ret_priv_data;
12983241Shiremath 		statep->close_ret_priv_data_len = ret_priv_data_len_p;
12993241Shiremath 	}
13003241Shiremath 
13013241Shiremath 	priv_data_len = min(priv_data_len, IBT_DREQ_PRIV_DATA_SZ);
13023241Shiremath 	if ((priv_data != NULL) && (priv_data_len > 0)) {
13033241Shiremath 		bcopy(priv_data, ((ibcm_dreq_msg_t *)
13043241Shiremath 		    IBCM_OUT_MSGP(statep->dreq_msg))->dreq_private_data,
13053241Shiremath 		    priv_data_len);
13063241Shiremath 	}
13073241Shiremath 	statep->close_ret_status = ret_status;
13083241Shiremath 
13090Sstevel@tonic-gate 	IBCM_RELEASE_CHAN_PRIVATE(channel);
13100Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);
13113241Shiremath 
13123241Shiremath 	if (mode != IBT_NONBLOCKING) {
13133241Shiremath 		return (ibcm_close_rc_channel(channel, statep, mode));
13143241Shiremath 	}
13153241Shiremath 
13163241Shiremath 	/* IBT_NONBLOCKING */
13173241Shiremath 	ibcm_close_enqueue(statep);
13180Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
13190Sstevel@tonic-gate 
13203241Shiremath 	return (IBT_SUCCESS);
13213241Shiremath }
13223241Shiremath 
13233241Shiremath void
ibcm_close_start(ibcm_state_data_t * statep)13243241Shiremath ibcm_close_start(ibcm_state_data_t *statep)
13253241Shiremath {
13263241Shiremath 	mutex_enter(&statep->state_mutex);
13273241Shiremath 	(void) ibcm_close_rc_channel(statep->channel, statep, IBT_NONBLOCKING);
13283241Shiremath }
13293241Shiremath 
13303241Shiremath static
13313241Shiremath ibt_status_t
ibcm_close_rc_channel(ibt_channel_hdl_t channel,ibcm_state_data_t * statep,ibt_execution_mode_t mode)13323241Shiremath ibcm_close_rc_channel(ibt_channel_hdl_t channel, ibcm_state_data_t *statep,
13333241Shiremath     ibt_execution_mode_t mode)
13343241Shiremath {
13353241Shiremath 	ibcm_hca_info_t		*hcap;
13363241Shiremath 
13373241Shiremath 	_NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex));
13383241Shiremath 	ASSERT(MUTEX_HELD(&statep->state_mutex));
13393241Shiremath 
13403241Shiremath 	IBTF_DPRINTF_L3(cmlog, "ibcm_close_rc_channel: chan 0x%p statep %p",
13410Sstevel@tonic-gate 	    channel, statep);
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 	hcap = statep->hcap;
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate 	/* HCA must have been in active state. If not, it's a client bug */
13460Sstevel@tonic-gate 	if (!IBCM_ACCESS_HCA_OK(hcap)) {
13473241Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibcm_close_rc_channel: chan 0x%p "
13480Sstevel@tonic-gate 		    "hcap 0x%p not active", channel, hcap);
13490Sstevel@tonic-gate 		IBCM_REF_CNT_DECR(statep);
13500Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
13510Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
13520Sstevel@tonic-gate 	}
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 	if (statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) {
13550Sstevel@tonic-gate 		while (statep->cep_in_rts == IBCM_BLOCK)
13560Sstevel@tonic-gate 			cv_wait(&statep->block_mad_cv, &statep->state_mutex);
13570Sstevel@tonic-gate 	}
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 	/* Do TRANSIENT_DREQ check after TRANSIENT_ESTABLISHED check */
13600Sstevel@tonic-gate 	while (statep->state == IBCM_STATE_TRANSIENT_DREQ_SENT)
13610Sstevel@tonic-gate 		cv_wait(&statep->block_mad_cv, &statep->state_mutex);
13620Sstevel@tonic-gate 
13633241Shiremath 	IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: chan 0x%p "
13640Sstevel@tonic-gate 	    "connection state is %x", channel, statep->state);
13650Sstevel@tonic-gate 
13660Sstevel@tonic-gate 	/* If state is in pre-established states, abort the connection est */
13670Sstevel@tonic-gate 	if (statep->state != IBCM_STATE_ESTABLISHED) {
13681093Shiremath 		statep->cm_retries++;	/* ensure connection trace is dumped */
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate 		/* No DREP private data possible */
13713241Shiremath 		if (statep->close_ret_priv_data_len != NULL)
13723241Shiremath 			*statep->close_ret_priv_data_len = 0;
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 		/*
13750Sstevel@tonic-gate 		 * If waiting for a response mad, then cancel the timer,
13760Sstevel@tonic-gate 		 * and delete the connection
13770Sstevel@tonic-gate 		 */
13780Sstevel@tonic-gate 		if (statep->state == IBCM_STATE_REQ_SENT ||
13790Sstevel@tonic-gate 		    statep->state == IBCM_STATE_REP_SENT ||
13800Sstevel@tonic-gate 		    statep->state == IBCM_STATE_REP_WAIT ||
13810Sstevel@tonic-gate 		    statep->state == IBCM_STATE_MRA_REP_RCVD) {
13820Sstevel@tonic-gate 			timeout_id_t		timer_val = statep->timerid;
13830Sstevel@tonic-gate 			ibcm_conn_state_t	old_state;
13840Sstevel@tonic-gate 
13853241Shiremath 			IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
13860Sstevel@tonic-gate 			    "chan 0x%p connection aborted in state %x", channel,
13870Sstevel@tonic-gate 			    statep->state);
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 			old_state = statep->state;
13900Sstevel@tonic-gate 			statep->state = IBCM_STATE_DELETE;
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate 			if (mode == IBT_NONBLOCKING) {
13930Sstevel@tonic-gate 				if (taskq_dispatch(ibcm_taskq,
13940Sstevel@tonic-gate 				    ibcm_process_abort_via_taskq, statep,
13950Sstevel@tonic-gate 				    TQ_NOSLEEP) == 0) {
13960Sstevel@tonic-gate 
13970Sstevel@tonic-gate 					IBCM_REF_CNT_DECR(statep);
13980Sstevel@tonic-gate 					statep->state = old_state;
13990Sstevel@tonic-gate 					mutex_exit(&statep->state_mutex);
14000Sstevel@tonic-gate 					return (IBT_INSUFF_KERNEL_RESOURCE);
14010Sstevel@tonic-gate 				}	/* if taskq_dispatch succeeds */
14020Sstevel@tonic-gate 				/* Cancel the timer */
14030Sstevel@tonic-gate 				statep->timerid = 0;
14040Sstevel@tonic-gate 				mutex_exit(&statep->state_mutex);
14050Sstevel@tonic-gate 			} else {
14060Sstevel@tonic-gate 				/* Cancel the timer */
14070Sstevel@tonic-gate 				statep->timerid = 0;
14080Sstevel@tonic-gate 				mutex_exit(&statep->state_mutex);
14090Sstevel@tonic-gate 				(void) taskq_dispatch(ibcm_taskq,
14100Sstevel@tonic-gate 				    ibcm_process_abort_via_taskq, statep,
14110Sstevel@tonic-gate 				    TQ_SLEEP);
14120Sstevel@tonic-gate 			}
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate 			/* cancel the currently running timer */
14150Sstevel@tonic-gate 			if (timer_val != 0)
14160Sstevel@tonic-gate 				(void) untimeout(timer_val);
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate 			/* wait until cm handler returns for BLOCKING cases */
14193241Shiremath 			mutex_enter(&statep->state_mutex);
14200Sstevel@tonic-gate 			if ((mode == IBT_BLOCKING) ||
14210Sstevel@tonic-gate 			    (mode == IBT_NOCALLBACKS)) {
14220Sstevel@tonic-gate 				while (statep->close_done != B_TRUE)
14230Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
14240Sstevel@tonic-gate 					    &statep->state_mutex);
14250Sstevel@tonic-gate 			}
14260Sstevel@tonic-gate 
14273241Shiremath 			if (statep->close_ret_status)
14283241Shiremath 				*statep->close_ret_status = IBT_CM_CLOSED_ABORT;
14293241Shiremath 			mutex_exit(&statep->state_mutex);
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 			/*
14320Sstevel@tonic-gate 			 * It would ideal to post a REJ MAD, but that would
14330Sstevel@tonic-gate 			 * be non-conformance to spec. Hence, delete the state
14340Sstevel@tonic-gate 			 * data. Assuming that happens quickly, any retransmits
14350Sstevel@tonic-gate 			 * from the remote are replied by CM with reject
14360Sstevel@tonic-gate 			 * reason " no valid com id". That would stop remote
14370Sstevel@tonic-gate 			 * sending any more MADs.
14380Sstevel@tonic-gate 			 */
14390Sstevel@tonic-gate 			ibcm_delete_state_data(statep);
14400Sstevel@tonic-gate 			return (IBT_SUCCESS);
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 		/* if CM busy in cm handler, wait until cm handler returns */
14430Sstevel@tonic-gate 		} else if (statep->state == IBCM_STATE_REQ_RCVD ||
14440Sstevel@tonic-gate 		    statep->state == IBCM_STATE_REP_RCVD ||
14450Sstevel@tonic-gate 		    statep->state == IBCM_STATE_MRA_SENT ||
14460Sstevel@tonic-gate 		    statep->state == IBCM_STATE_MRA_REP_SENT) {
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate 			/* take control of statep */
14490Sstevel@tonic-gate 			statep->abort_flag |= IBCM_ABORT_CLIENT;
14500Sstevel@tonic-gate 
14513241Shiremath 			IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
14520Sstevel@tonic-gate 			    "chan 0x%p connection aborted in state = %x",
14530Sstevel@tonic-gate 			    channel, statep->state);
14540Sstevel@tonic-gate 
14550Sstevel@tonic-gate 			/*
14560Sstevel@tonic-gate 			 * wait until state machine modifies qp state to error,
14570Sstevel@tonic-gate 			 * including disassociating statep and QP
14580Sstevel@tonic-gate 			 */
14590Sstevel@tonic-gate 			if ((mode == IBT_BLOCKING) || (mode == IBT_NOCALLBACKS))
14600Sstevel@tonic-gate 				while (statep->close_done != B_TRUE)
14610Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
14620Sstevel@tonic-gate 					    &statep->state_mutex);
14630Sstevel@tonic-gate 
14640Sstevel@tonic-gate 			/* a sanity setting */
14650Sstevel@tonic-gate 			if (mode == IBT_NOCALLBACKS)
14660Sstevel@tonic-gate 				statep->cm_handler = NULL;
14670Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 			/*
14700Sstevel@tonic-gate 			 * In rare situations, connection attempt could be
14710Sstevel@tonic-gate 			 * terminated for some other reason, before abort is
14720Sstevel@tonic-gate 			 * processed, but CM still returns ret_status as abort
14730Sstevel@tonic-gate 			 */
14743241Shiremath 			if (statep->close_ret_status)
14753241Shiremath 				*statep->close_ret_status = IBT_CM_CLOSED_ABORT;
14763241Shiremath 			mutex_exit(&statep->state_mutex);
14770Sstevel@tonic-gate 
14780Sstevel@tonic-gate 			/*
14790Sstevel@tonic-gate 			 * REJ MAD is posted by the CM state machine for this
14800Sstevel@tonic-gate 			 * case, hence state structure is deleted in the
14810Sstevel@tonic-gate 			 * state machine processing.
14820Sstevel@tonic-gate 			 */
14830Sstevel@tonic-gate 			return (IBT_SUCCESS);
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 		} else if ((statep->state == IBCM_STATE_TIMEWAIT) ||
14860Sstevel@tonic-gate 		    (statep->state == IBCM_STATE_DELETE)) {
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 			/* State already in timewait, so no return priv data */
14890Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
14900Sstevel@tonic-gate 
14910Sstevel@tonic-gate 			/* The teardown has already been done */
14923241Shiremath 			if (statep->close_ret_status)
14933241Shiremath 				*statep->close_ret_status =
14943241Shiremath 				    IBT_CM_CLOSED_ALREADY;
14953241Shiremath 			mutex_exit(&statep->state_mutex);
14960Sstevel@tonic-gate 
14970Sstevel@tonic-gate 			return (IBT_SUCCESS);
14980Sstevel@tonic-gate 
14990Sstevel@tonic-gate 		} else if ((statep->state == IBCM_STATE_DREQ_RCVD) ||
15000Sstevel@tonic-gate 		    (statep->state == IBCM_STATE_DREQ_SENT) ||
15010Sstevel@tonic-gate 		    (statep->state == IBCM_STATE_DREP_RCVD) ||
15020Sstevel@tonic-gate 		    ((statep->state == IBCM_STATE_TIMED_OUT) &&
15030Sstevel@tonic-gate 		    (statep->timedout_state == IBCM_STATE_DREQ_SENT))) {
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 			/*
15060Sstevel@tonic-gate 			 * Either the remote or local client has already
15070Sstevel@tonic-gate 			 * initiated the teardown.  IBCM_STATE_DREP_RCVD is
15080Sstevel@tonic-gate 			 * possible, if CM initiated teardown without client's
15090Sstevel@tonic-gate 			 * knowledge, for stale handling, etc.,
15100Sstevel@tonic-gate 			 */
15110Sstevel@tonic-gate 			if (mode == IBT_NOCALLBACKS) {
15120Sstevel@tonic-gate 				if (statep->close_nocb_state == IBCM_UNBLOCK) {
15130Sstevel@tonic-gate 					statep->close_nocb_state = IBCM_FAIL;
15140Sstevel@tonic-gate 					/* enable free qp after return */
15150Sstevel@tonic-gate 					ibtl_cm_chan_is_closing(
15160Sstevel@tonic-gate 					    statep->channel);
15170Sstevel@tonic-gate 				} else while (statep->close_nocb_state ==
15180Sstevel@tonic-gate 				    IBCM_BLOCK)
15190Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
15200Sstevel@tonic-gate 					    &statep->state_mutex);
15210Sstevel@tonic-gate 				statep->cm_handler = NULL; /* sanity setting */
15223241Shiremath 				if (statep->close_ret_status)
15233241Shiremath 					*statep->close_ret_status =
15243241Shiremath 					    IBT_CM_CLOSED_ALREADY;
15250Sstevel@tonic-gate 			} else if (mode == IBT_BLOCKING) {
15260Sstevel@tonic-gate 				/* wait until state is moved to timewait */
15270Sstevel@tonic-gate 				while (statep->close_done != B_TRUE)
15280Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
15290Sstevel@tonic-gate 					    &statep->state_mutex);
15300Sstevel@tonic-gate 			}
15310Sstevel@tonic-gate 
15320Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
15330Sstevel@tonic-gate 			mutex_exit(&statep->state_mutex);
15340Sstevel@tonic-gate 
15350Sstevel@tonic-gate 			/* ret_status is set in state machine code */
15360Sstevel@tonic-gate 			return (IBT_SUCCESS);
15370Sstevel@tonic-gate 
15380Sstevel@tonic-gate 		} else if (statep->state == IBCM_STATE_TIMED_OUT) {
15390Sstevel@tonic-gate 
15400Sstevel@tonic-gate 			if ((mode == IBT_BLOCKING) ||
15410Sstevel@tonic-gate 			    (mode == IBT_NOCALLBACKS)) {
15420Sstevel@tonic-gate 
15430Sstevel@tonic-gate 				/*
15440Sstevel@tonic-gate 				 * wait until cm handler invocation and
15450Sstevel@tonic-gate 				 * disassociation between statep and channel
15460Sstevel@tonic-gate 				 * is complete
15470Sstevel@tonic-gate 				 */
15480Sstevel@tonic-gate 				while (statep->close_done != B_TRUE)
15490Sstevel@tonic-gate 					cv_wait(&statep->block_client_cv,
15500Sstevel@tonic-gate 					    &statep->state_mutex);
15510Sstevel@tonic-gate 			}
15520Sstevel@tonic-gate 
15533241Shiremath 			if (statep->close_ret_status)
15543241Shiremath 				*statep->close_ret_status = IBT_CM_CLOSED_ABORT;
15550Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
15560Sstevel@tonic-gate 			mutex_exit(&statep->state_mutex);
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate 			return (IBT_SUCCESS);
15590Sstevel@tonic-gate 		} else {
15600Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
15610Sstevel@tonic-gate 			mutex_exit(&statep->state_mutex);
15620Sstevel@tonic-gate 
15630Sstevel@tonic-gate 			return (IBT_CM_FAILURE);
15640Sstevel@tonic-gate 		}
15650Sstevel@tonic-gate 	}
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 	ASSERT(statep->close_nocb_state != IBCM_BLOCK);
15680Sstevel@tonic-gate 
15690Sstevel@tonic-gate 	if (mode == IBT_NOCALLBACKS) {
15700Sstevel@tonic-gate 		statep->close_nocb_state = IBCM_FAIL;
15710Sstevel@tonic-gate 		statep->cm_handler = NULL;
15720Sstevel@tonic-gate 		ibtl_cm_chan_is_closing(statep->channel);
15733241Shiremath 		IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: "
15740Sstevel@tonic-gate 		    "NOCALLBACKS on in statep = %p", statep);
15750Sstevel@tonic-gate 	}
15764703Shiremath 
15771093Shiremath 	if (statep->state != IBCM_STATE_ESTABLISHED) {
15781093Shiremath 		goto lost_race;
15791093Shiremath 	}
15800Sstevel@tonic-gate 
15810Sstevel@tonic-gate 	/*
15820Sstevel@tonic-gate 	 * Cancel/wait for any pending ibt_set_alt_path, and
15830Sstevel@tonic-gate 	 * release state mutex
15840Sstevel@tonic-gate 	 */
15850Sstevel@tonic-gate 	ibcm_sync_lapr_idle(statep);
15860Sstevel@tonic-gate 
15871093Shiremath 	ibcm_close_enter();
15881093Shiremath 
15891093Shiremath 	mutex_enter(&statep->state_mutex);
15901093Shiremath 	if (statep->state != IBCM_STATE_ESTABLISHED) {
15911093Shiremath 		ibcm_close_exit();
15921093Shiremath 		goto lost_race;
15931093Shiremath 	}
15941093Shiremath 
15951093Shiremath 	statep->state = IBCM_STATE_TRANSIENT_DREQ_SENT;
15961093Shiremath 	statep->timerid = 0;
15971093Shiremath 	statep->close_done = B_FALSE;
15981093Shiremath 	statep->close_flow = 1;
15991093Shiremath 	mutex_exit(&statep->state_mutex);
16001093Shiremath 
16011093Shiremath 	ibcm_post_dreq_mad(statep);
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
16040Sstevel@tonic-gate 
16051093Shiremath lost_race:
16060Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
16070Sstevel@tonic-gate 
16080Sstevel@tonic-gate 		/* wait for DREP */
16090Sstevel@tonic-gate 		while (statep->close_done != B_TRUE)
16100Sstevel@tonic-gate 			cv_wait(&statep->block_client_cv,
16110Sstevel@tonic-gate 			    &statep->state_mutex);
16120Sstevel@tonic-gate 
16133241Shiremath 		IBTF_DPRINTF_L4(cmlog, "ibcm_close_rc_channel: chan 0x%p "
16140Sstevel@tonic-gate 		    "done blocking", channel);
16150Sstevel@tonic-gate 	}
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
16180Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate 	/* If this message isn't seen then ibt_close_rc_channel failed */
16213241Shiremath 	IBTF_DPRINTF_L5(cmlog, "ibcm_close_rc_channel: chan 0x%p done",
16220Sstevel@tonic-gate 	    channel);
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate 	return (IBT_SUCCESS);
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate 
16270Sstevel@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)16280Sstevel@tonic-gate ibt_recycle_rc(ibt_channel_hdl_t rc_chan, ibt_cep_flags_t control,
16290Sstevel@tonic-gate     uint8_t hca_port_num, ibt_recycle_handler_t func, void *arg)
16300Sstevel@tonic-gate {
16310Sstevel@tonic-gate 	ibcm_state_data_t		*statep;
16320Sstevel@tonic-gate 	ibcm_taskq_recycle_arg_t	*ibcm_tq_recycle_arg;
16330Sstevel@tonic-gate 	ibt_qp_query_attr_t		qp_attr;
16340Sstevel@tonic-gate 	ibt_status_t			retval;
16350Sstevel@tonic-gate 
16360Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_recycle_rc (%p, 0x%X, %d, %p, %p)", rc_chan,
16370Sstevel@tonic-gate 	    control, hca_port_num, func, arg);
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(rc_chan)) {
16400Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_recycle_rc: invalid channel");
16410Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
16420Sstevel@tonic-gate 	}
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate 	/* check qp state */
16450Sstevel@tonic-gate 	retval = ibt_query_qp(rc_chan, &qp_attr);
16460Sstevel@tonic-gate 
16470Sstevel@tonic-gate 	if (retval != IBT_SUCCESS)
16480Sstevel@tonic-gate 		return (retval);
16490Sstevel@tonic-gate 
16500Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_trans != IBT_RC_SRV)
16510Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
16520Sstevel@tonic-gate 
16530Sstevel@tonic-gate 	if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR)
16540Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
16570Sstevel@tonic-gate 
16580Sstevel@tonic-gate 	ibcm_tq_recycle_arg = kmem_alloc(sizeof (ibcm_taskq_recycle_arg_t),
16590Sstevel@tonic-gate 	    KM_SLEEP);
16600Sstevel@tonic-gate 
16610Sstevel@tonic-gate 	ibcm_tq_recycle_arg->rc_chan		= rc_chan;
16620Sstevel@tonic-gate 	ibcm_tq_recycle_arg->control		= control;
16630Sstevel@tonic-gate 	ibcm_tq_recycle_arg->hca_port_num	= hca_port_num;
16640Sstevel@tonic-gate 	ibcm_tq_recycle_arg->func		= func;
16650Sstevel@tonic-gate 	ibcm_tq_recycle_arg->arg		= arg;
16660Sstevel@tonic-gate 
16670Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(rc_chan, statep);
16700Sstevel@tonic-gate 
16710Sstevel@tonic-gate 	/*
16720Sstevel@tonic-gate 	 * If non-blocking ie., func specified and channel has not yet completed
16730Sstevel@tonic-gate 	 * the timewait, then schedule the work for later
16740Sstevel@tonic-gate 	 */
16750Sstevel@tonic-gate 	if ((func != NULL) && (statep != NULL)) {
16760Sstevel@tonic-gate 		IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
16770Sstevel@tonic-gate 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
16780Sstevel@tonic-gate 		statep->recycle_arg = ibcm_tq_recycle_arg;
16790Sstevel@tonic-gate 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
16800Sstevel@tonic-gate 		return (IBT_SUCCESS);
16810Sstevel@tonic-gate 	}
16820Sstevel@tonic-gate 
16830Sstevel@tonic-gate 	/*
16840Sstevel@tonic-gate 	 * if blocking ie., func specified, and channel has not yet completed
16850Sstevel@tonic-gate 	 * the timewait, then block until the channel completes the timewait
16860Sstevel@tonic-gate 	 */
16870Sstevel@tonic-gate 	if (statep != NULL)
16880Sstevel@tonic-gate 		IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
16890Sstevel@tonic-gate 	IBCM_WAIT_CHAN_PRIVATE(rc_chan);
16900Sstevel@tonic-gate 
16910Sstevel@tonic-gate 	if (func) {	/* NON BLOCKING case. Taskq for QP state change */
16920Sstevel@tonic-gate 		(void) taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
16930Sstevel@tonic-gate 		    ibcm_tq_recycle_arg, TQ_SLEEP);
16940Sstevel@tonic-gate 		return (IBT_SUCCESS);
16950Sstevel@tonic-gate 	} else	/* BLOCKING case */
16960Sstevel@tonic-gate 		return (ibcm_process_rc_recycle_ret(ibcm_tq_recycle_arg));
16970Sstevel@tonic-gate }
16980Sstevel@tonic-gate 
16990Sstevel@tonic-gate void
ibcm_process_rc_recycle(void * recycle_arg)17000Sstevel@tonic-gate ibcm_process_rc_recycle(void *recycle_arg)
17010Sstevel@tonic-gate {
17020Sstevel@tonic-gate 	(void) ibcm_process_rc_recycle_ret(recycle_arg);
17030Sstevel@tonic-gate }
17040Sstevel@tonic-gate 
17050Sstevel@tonic-gate static ibt_status_t
ibcm_process_rc_recycle_ret(void * recycle_arg)17060Sstevel@tonic-gate ibcm_process_rc_recycle_ret(void *recycle_arg)
17070Sstevel@tonic-gate {
17080Sstevel@tonic-gate 	ibt_qp_info_t			qp_info;
17090Sstevel@tonic-gate 	ibt_status_t			ibt_status = IBT_SUCCESS;
17100Sstevel@tonic-gate 	ibt_cep_modify_flags_t		cep_flags;
17110Sstevel@tonic-gate 	ibt_qp_query_attr_t		qp_attr;
17120Sstevel@tonic-gate 	ibcm_taskq_recycle_arg_t	*ibcm_tq_recycle_arg =
17130Sstevel@tonic-gate 	    (ibcm_taskq_recycle_arg_t *)recycle_arg;
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate 	/* QP must have been in error state */
17160Sstevel@tonic-gate 	ibt_status = ibt_query_qp(ibcm_tq_recycle_arg->rc_chan, &qp_attr);
17170Sstevel@tonic-gate 	if (ibt_status != IBT_SUCCESS)
17180Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17190Sstevel@tonic-gate 		    "chanp %p ibt_query_qp() = %d",
17200Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->rc_chan, ibt_status);
17210Sstevel@tonic-gate 	else {
17220Sstevel@tonic-gate 		/* perform the QP state change from ERROR to RESET */
17230Sstevel@tonic-gate 		bzero(&qp_info, sizeof (qp_info));
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate 		qp_info.qp_trans = IBT_RC_SRV;
17260Sstevel@tonic-gate 		qp_info.qp_state = IBT_STATE_RESET;
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 		/* Call modify_qp to move to RESET state */
17290Sstevel@tonic-gate 		ibt_status = ibt_modify_qp(ibcm_tq_recycle_arg->rc_chan,
17300Sstevel@tonic-gate 		    IBT_CEP_SET_STATE, &qp_info, NULL);
17310Sstevel@tonic-gate 
17320Sstevel@tonic-gate 		if (ibt_status != IBT_SUCCESS)
17330Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17340Sstevel@tonic-gate 			    "chanp %p ibt_modify_qp() = %d for ERROR to RESET",
17350Sstevel@tonic-gate 			    ibcm_tq_recycle_arg->rc_chan, ibt_status);
17360Sstevel@tonic-gate 	}
17370Sstevel@tonic-gate 
17380Sstevel@tonic-gate 	if (ibt_status == IBT_SUCCESS) {
17390Sstevel@tonic-gate 
17400Sstevel@tonic-gate 		qp_info.qp_state = IBT_STATE_INIT;
17410Sstevel@tonic-gate 
17420Sstevel@tonic-gate 		/* set flags for all mandatory args from RESET to INIT */
17430Sstevel@tonic-gate 		cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
17440Sstevel@tonic-gate 		cep_flags |= IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W;
17450Sstevel@tonic-gate 		cep_flags |= IBT_CEP_SET_ATOMIC;
17460Sstevel@tonic-gate 
17470Sstevel@tonic-gate 		qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
17480Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->hca_port_num;
17490Sstevel@tonic-gate 		qp_info.qp_flags |=
17500Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->control & IBT_CEP_RDMA_RD;
17510Sstevel@tonic-gate 		qp_info.qp_flags |=
17520Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->control & IBT_CEP_RDMA_WR;
17530Sstevel@tonic-gate 		qp_info.qp_flags |=
17540Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->control & IBT_CEP_ATOMIC;
17550Sstevel@tonic-gate 
17560Sstevel@tonic-gate 		/* Always use the existing pkey */
17570Sstevel@tonic-gate 		qp_info.qp_transport.rc.rc_path.cep_pkey_ix =
17580Sstevel@tonic-gate 		    qp_attr. qp_info.qp_transport.rc.rc_path.cep_pkey_ix;
17590Sstevel@tonic-gate 
17600Sstevel@tonic-gate 		/* Call modify_qp to move to INIT state */
17610Sstevel@tonic-gate 		ibt_status = ibt_modify_qp(ibcm_tq_recycle_arg->rc_chan,
17620Sstevel@tonic-gate 		    cep_flags, &qp_info, NULL);
17630Sstevel@tonic-gate 
17640Sstevel@tonic-gate 		if (ibt_status != IBT_SUCCESS)
17650Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
17660Sstevel@tonic-gate 			    "chanp %p ibt_modify_qp() = %d for RESET to INIT",
17670Sstevel@tonic-gate 			    ibcm_tq_recycle_arg->rc_chan, ibt_status);
17680Sstevel@tonic-gate 	}
17690Sstevel@tonic-gate 
17700Sstevel@tonic-gate 	/* Change the QP CM state to indicate QP being re-used */
17710Sstevel@tonic-gate 	if (ibt_status == IBT_SUCCESS)
17720Sstevel@tonic-gate 		ibtl_cm_chan_is_reused(ibcm_tq_recycle_arg->rc_chan);
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate 	/* Call func, if defined */
17750Sstevel@tonic-gate 	if (ibcm_tq_recycle_arg->func)
17760Sstevel@tonic-gate 		(*(ibcm_tq_recycle_arg->func))(ibt_status,
17770Sstevel@tonic-gate 		    ibcm_tq_recycle_arg->arg);
17780Sstevel@tonic-gate 
17790Sstevel@tonic-gate 	kmem_free(ibcm_tq_recycle_arg, sizeof (ibcm_taskq_recycle_arg_t));
17800Sstevel@tonic-gate 
17810Sstevel@tonic-gate 	return (ibt_status);
17820Sstevel@tonic-gate }
17830Sstevel@tonic-gate 
17840Sstevel@tonic-gate static void
ibcm_process_abort_via_taskq(void * args)17850Sstevel@tonic-gate ibcm_process_abort_via_taskq(void *args)
17860Sstevel@tonic-gate {
17870Sstevel@tonic-gate 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate 	ibcm_process_abort(statep);
17900Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
17910Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
17920Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
17930Sstevel@tonic-gate }
17940Sstevel@tonic-gate 
17950Sstevel@tonic-gate /*
17960Sstevel@tonic-gate  * Local UD CM Handler's private data, used during ibt_request_ud_dest() in
17970Sstevel@tonic-gate  * Non-Blocking mode operations.
17980Sstevel@tonic-gate  */
17990Sstevel@tonic-gate typedef struct ibcm_local_handler_s {
18000Sstevel@tonic-gate 	ibt_cm_ud_handler_t	actual_cm_handler;
18010Sstevel@tonic-gate 	void			*actual_cm_private;
18020Sstevel@tonic-gate 	ibt_ud_dest_t		*dest_hdl;
18030Sstevel@tonic-gate } ibcm_local_handler_t;
18040Sstevel@tonic-gate 
_NOTE(READ_ONLY_DATA (ibcm_local_handler_s))18050Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_local_handler_s))
18060Sstevel@tonic-gate 
18070Sstevel@tonic-gate /*
18080Sstevel@tonic-gate  * Local UD CM Handler, used when ibt_alloc_ud_dest() is issued in
18090Sstevel@tonic-gate  * NON-Blocking mode.
18100Sstevel@tonic-gate  *
18110Sstevel@tonic-gate  * Out here, we update the UD Destination handle with
18120Sstevel@tonic-gate  * the obtained DQPN and QKey (from SIDR REP) and invokes actual client
18130Sstevel@tonic-gate  * handler that was specified by the client.
18140Sstevel@tonic-gate  */
18150Sstevel@tonic-gate static ibt_cm_status_t
18160Sstevel@tonic-gate ibcm_local_cm_handler(void *priv, ibt_cm_ud_event_t *event,
18170Sstevel@tonic-gate     ibt_cm_ud_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
18180Sstevel@tonic-gate {
18190Sstevel@tonic-gate 	ibcm_local_handler_t	*handler_priv = (ibcm_local_handler_t *)priv;
18200Sstevel@tonic-gate 
18210Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_local_cm_handler: event %d",
18220Sstevel@tonic-gate 	    event->cm_type);
18230Sstevel@tonic-gate 
18240Sstevel@tonic-gate 	ASSERT(handler_priv != NULL);
18250Sstevel@tonic-gate 
18260Sstevel@tonic-gate 	switch (event->cm_type) {
18270Sstevel@tonic-gate 	case IBT_CM_UD_EVENT_SIDR_REP:
18280Sstevel@tonic-gate 		/* Update QPN & QKey from event into destination handle. */
18290Sstevel@tonic-gate 		if (handler_priv->dest_hdl != NULL) {
18300Sstevel@tonic-gate 			handler_priv->dest_hdl->ud_dst_qpn =
18310Sstevel@tonic-gate 			    event->cm_event.sidr_rep.srep_remote_qpn;
18320Sstevel@tonic-gate 			handler_priv->dest_hdl->ud_qkey =
18330Sstevel@tonic-gate 			    event->cm_event.sidr_rep.srep_remote_qkey;
18340Sstevel@tonic-gate 		}
18350Sstevel@tonic-gate 
18360Sstevel@tonic-gate 		/* Invoke the client handler - inform only, so ignore retval */
18370Sstevel@tonic-gate 		(void) handler_priv->actual_cm_handler(
18380Sstevel@tonic-gate 		    handler_priv->actual_cm_private, event, ret_args, priv_data,
18390Sstevel@tonic-gate 		    len);
18400Sstevel@tonic-gate 
18410Sstevel@tonic-gate 		/* Free memory allocated for local handler's private data. */
18420Sstevel@tonic-gate 		if (handler_priv != NULL)
18430Sstevel@tonic-gate 			kmem_free(handler_priv, sizeof (*handler_priv));
18440Sstevel@tonic-gate 
18450Sstevel@tonic-gate 		break;
18460Sstevel@tonic-gate 	default:
18470Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_local_cm_handler: ERROR");
18480Sstevel@tonic-gate 		break;
18490Sstevel@tonic-gate 	}
18500Sstevel@tonic-gate 
18510Sstevel@tonic-gate 	return (IBT_CM_ACCEPT);
18520Sstevel@tonic-gate }
18530Sstevel@tonic-gate 
18540Sstevel@tonic-gate 
18550Sstevel@tonic-gate /* Validate the input UD destination attributes.  */
18560Sstevel@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)18570Sstevel@tonic-gate ibcm_validate_dqpn_data(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
18580Sstevel@tonic-gate     ibt_ud_returns_t *ret_args)
18590Sstevel@tonic-gate {
18600Sstevel@tonic-gate 	/* cm handler must always be specified */
18610Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING && attr->ud_cm_handler == NULL) {
18620Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18630Sstevel@tonic-gate 		    "CM handler is not specified ");
18640Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
18650Sstevel@tonic-gate 	}
18660Sstevel@tonic-gate 
18670Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING) {
18680Sstevel@tonic-gate 		if (ret_args != NULL) {
18690Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18700Sstevel@tonic-gate 			    "ret_args should be NULL when called in "
18710Sstevel@tonic-gate 			    "non-blocking mode");
18720Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
18730Sstevel@tonic-gate 		}
18740Sstevel@tonic-gate 	} else if (mode == IBT_BLOCKING) {
18750Sstevel@tonic-gate 		if (ret_args == NULL) {
18760Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18770Sstevel@tonic-gate 			    "ret_args should be Non-NULL when called in "
18780Sstevel@tonic-gate 			    "blocking mode");
18790Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
18800Sstevel@tonic-gate 		}
18810Sstevel@tonic-gate 	} else {
18820Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18830Sstevel@tonic-gate 		    "invalid mode %x specified ", mode);
18840Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
18850Sstevel@tonic-gate 	}
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate 	if (attr->ud_sid == 0) {
18880Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18890Sstevel@tonic-gate 		    "ServiceID must be specified. ");
18900Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
18910Sstevel@tonic-gate 	}
18920Sstevel@tonic-gate 
18930Sstevel@tonic-gate 	if (attr->ud_addr == NULL) {
18940Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
18950Sstevel@tonic-gate 		    "Address Info NULL");
18960Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
18970Sstevel@tonic-gate 	}
18980Sstevel@tonic-gate 
18990Sstevel@tonic-gate 	/* Validate SGID */
19000Sstevel@tonic-gate 	if ((attr->ud_addr->av_sgid.gid_prefix == 0) ||
19010Sstevel@tonic-gate 	    (attr->ud_addr->av_sgid.gid_guid == 0)) {
19020Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: Invalid SGID");
19030Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
19040Sstevel@tonic-gate 	}
19050Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_validate_dqpn_data: SGID<%llX:%llX>",
19060Sstevel@tonic-gate 	    attr->ud_addr->av_sgid.gid_prefix,
19070Sstevel@tonic-gate 	    attr->ud_addr->av_sgid.gid_guid);
19080Sstevel@tonic-gate 
19090Sstevel@tonic-gate 	/* Validate DGID */
19100Sstevel@tonic-gate 	if ((attr->ud_addr->av_dgid.gid_prefix == 0) ||
19110Sstevel@tonic-gate 	    (attr->ud_addr->av_dgid.gid_guid == 0)) {
19120Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: Invalid DGID");
19130Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
19140Sstevel@tonic-gate 	}
19150Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_validate_dqpn_data: DGID<%llX:%llX>",
19160Sstevel@tonic-gate 	    attr->ud_addr->av_dgid.gid_prefix,
19170Sstevel@tonic-gate 	    attr->ud_addr->av_dgid.gid_guid);
19180Sstevel@tonic-gate 
19190Sstevel@tonic-gate 	return (IBT_SUCCESS);
19200Sstevel@tonic-gate }
19210Sstevel@tonic-gate 
19220Sstevel@tonic-gate 
19230Sstevel@tonic-gate /* Perform SIDR to retrieve DQPN and QKey.  */
19240Sstevel@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)19250Sstevel@tonic-gate ibcm_ud_get_dqpn(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
19260Sstevel@tonic-gate     ibt_ud_returns_t *ret_args)
19270Sstevel@tonic-gate {
19280Sstevel@tonic-gate 	ibt_status_t		retval;
19290Sstevel@tonic-gate 	ib_pkey_t		ud_pkey;
19300Sstevel@tonic-gate 	ibmf_handle_t		ibmf_hdl;
19310Sstevel@tonic-gate 	ibmf_msg_t		*ibmf_msg;
19320Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
19330Sstevel@tonic-gate 	ibcm_sidr_req_msg_t	*sidr_req_msgp;
19340Sstevel@tonic-gate 	ibcm_ud_state_data_t	*ud_statep;
19350Sstevel@tonic-gate 	ibtl_cm_hca_port_t	port;
19360Sstevel@tonic-gate 	ibcm_sidr_srch_t	sidr_entry;
19370Sstevel@tonic-gate 	ibcm_qp_list_t		*cm_qp_entry;
19380Sstevel@tonic-gate 
19390Sstevel@tonic-gate 	/* Retrieve HCA GUID value from the available SGID info. */
19400Sstevel@tonic-gate 	retval = ibtl_cm_get_hca_port(attr->ud_addr->av_sgid, 0, &port);
19410Sstevel@tonic-gate 	if ((retval != IBT_SUCCESS) || (port.hp_port == 0)) {
19420Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19430Sstevel@tonic-gate 		    "ibtl_cm_get_hca_port failed: %d", retval);
19440Sstevel@tonic-gate 		return (retval);
19450Sstevel@tonic-gate 	}
19460Sstevel@tonic-gate 
19470Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: "
19480Sstevel@tonic-gate 	    "HCA GUID:%llX, port_num:%d", port.hp_hca_guid, port.hp_port);
19490Sstevel@tonic-gate 
19500Sstevel@tonic-gate 	/* Lookup the HCA info for this GUID */
19510Sstevel@tonic-gate 	if ((hcap = ibcm_find_hca_entry(port.hp_hca_guid)) == NULL) {
19520Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: hcap is NULL");
19530Sstevel@tonic-gate 		return (IBT_HCA_INVALID);
19540Sstevel@tonic-gate 	}
19550Sstevel@tonic-gate 
19560Sstevel@tonic-gate 	/* Return failure if the HCA device or Port is not operational */
19570Sstevel@tonic-gate 
19580Sstevel@tonic-gate 	if ((retval = ibt_get_port_state_byguid(port.hp_hca_guid, port.hp_port,
19590Sstevel@tonic-gate 	    NULL, NULL)) != IBT_SUCCESS) {
19600Sstevel@tonic-gate 		/* Device Port is not in good state, don't use it. */
19610Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: Invalid "
19620Sstevel@tonic-gate 		    "port specified or port not active");
19630Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
19640Sstevel@tonic-gate 		return (retval);
19650Sstevel@tonic-gate 	}
19660Sstevel@tonic-gate 
19670Sstevel@tonic-gate 	retval = ibt_index2pkey_byguid(port.hp_hca_guid, port.hp_port,
19680Sstevel@tonic-gate 	    attr->ud_pkey_ix, &ud_pkey);
19690Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
19700Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19710Sstevel@tonic-gate 		    "Failed to convert index2pkey: %d", retval);
19720Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
19730Sstevel@tonic-gate 		return (retval);
19740Sstevel@tonic-gate 	}
19750Sstevel@tonic-gate 
19760Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(sidr_entry))
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate 	/* Allocate a new request id */
19790Sstevel@tonic-gate 	if (ibcm_alloc_reqid(hcap, &sidr_entry.srch_req_id) == IBCM_FAILURE) {
19800Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19810Sstevel@tonic-gate 		    "no req id available");
19820Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
19830Sstevel@tonic-gate 		return (IBT_INSUFF_KERNEL_RESOURCE);
19840Sstevel@tonic-gate 	}
19850Sstevel@tonic-gate 
19860Sstevel@tonic-gate 	if ((hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl == NULL) &&
19870Sstevel@tonic-gate 	    ((retval = ibcm_hca_reinit_port(hcap, port.hp_port - 1))
19880Sstevel@tonic-gate 	    != IBT_SUCCESS)) {
19890Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
19900Sstevel@tonic-gate 		    "ibmf reg or callback setup failed during re-initialize");
19910Sstevel@tonic-gate 		return (retval);
19920Sstevel@tonic-gate 	}
19930Sstevel@tonic-gate 
19940Sstevel@tonic-gate 	ibmf_hdl = hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl;
19950Sstevel@tonic-gate 
19960Sstevel@tonic-gate 	/* find the ibmf QP to post the SIDR REQ */
19970Sstevel@tonic-gate 	if ((cm_qp_entry = ibcm_find_qp(hcap, port.hp_port, ud_pkey)) ==
19980Sstevel@tonic-gate 	    NULL) {
19990Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF QP allocation"
20000Sstevel@tonic-gate 		    " failed");
20010Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
20020Sstevel@tonic-gate 		return (IBT_INSUFF_RESOURCE);
20030Sstevel@tonic-gate 	}
20040Sstevel@tonic-gate 
20050Sstevel@tonic-gate 	if ((retval = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg, MAD_METHOD_SEND))
20060Sstevel@tonic-gate 	    != IBT_SUCCESS) {
20070Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF MSG allocation"
20080Sstevel@tonic-gate 		    " failed");
20090Sstevel@tonic-gate 		ibcm_release_qp(cm_qp_entry);
20100Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
20110Sstevel@tonic-gate 		return (retval);
20120Sstevel@tonic-gate 	}
20130Sstevel@tonic-gate 
20140Sstevel@tonic-gate 	sidr_entry.srch_lid = port.hp_base_lid;
20150Sstevel@tonic-gate 	sidr_entry.srch_gid = attr->ud_addr->av_sgid;
20160Sstevel@tonic-gate 	sidr_entry.srch_grh_exists = attr->ud_addr->av_send_grh;
20170Sstevel@tonic-gate 	sidr_entry.srch_mode = IBCM_ACTIVE_MODE;
20180Sstevel@tonic-gate 
20190Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(sidr_entry))
20200Sstevel@tonic-gate 
20210Sstevel@tonic-gate 	/* do various allocations needed here */
20220Sstevel@tonic-gate 	rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
20230Sstevel@tonic-gate 
20240Sstevel@tonic-gate 	(void) ibcm_find_sidr_entry(&sidr_entry, hcap, &ud_statep,
20250Sstevel@tonic-gate 	    IBCM_FLAG_ADD);
20260Sstevel@tonic-gate 	rw_exit(&hcap->hca_sidr_list_lock);
20270Sstevel@tonic-gate 
20280Sstevel@tonic-gate 	/* Increment hca's resource count */
20290Sstevel@tonic-gate 	ibcm_inc_hca_res_cnt(hcap);
20300Sstevel@tonic-gate 
20310Sstevel@tonic-gate 	/* After a resource created on hca, no need to hold the acc cnt */
20320Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
20330Sstevel@tonic-gate 
20340Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
20350Sstevel@tonic-gate 
20360Sstevel@tonic-gate 	/* Initialize some ud_statep fields */
20370Sstevel@tonic-gate 	ud_statep->ud_stored_msg = ibmf_msg;
20380Sstevel@tonic-gate 	ud_statep->ud_svc_id = attr->ud_sid;
20390Sstevel@tonic-gate 	ud_statep->ud_pkt_life_time =
20400Sstevel@tonic-gate 	    ibt_ib2usec(attr->ud_pkt_lt);
20410Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.cm_qp_entry = cm_qp_entry;
20420Sstevel@tonic-gate 
20430Sstevel@tonic-gate 	/* set remaining retry cnt */
20440Sstevel@tonic-gate 	ud_statep->ud_remaining_retry_cnt = ud_statep->ud_max_cm_retries;
20450Sstevel@tonic-gate 
20460Sstevel@tonic-gate 	/*
20470Sstevel@tonic-gate 	 * Get UD handler and corresponding args which is pass it back
20480Sstevel@tonic-gate 	 * as first argument for the handler.
20490Sstevel@tonic-gate 	 */
20500Sstevel@tonic-gate 	ud_statep->ud_state_cm_private = attr->ud_cm_private;
20510Sstevel@tonic-gate 
20520Sstevel@tonic-gate 	if (mode == IBT_BLOCKING)
20530Sstevel@tonic-gate 		ud_statep->ud_return_data = ret_args;
20540Sstevel@tonic-gate 	else
20550Sstevel@tonic-gate 		ud_statep->ud_cm_handler = attr->ud_cm_handler;
20560Sstevel@tonic-gate 
20570Sstevel@tonic-gate 	/* Initialize the fields of ud_statep->ud_stored_reply_addr */
20580Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_exists = attr->ud_addr->av_send_grh;
20590Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.ibmf_hdl = ibmf_hdl;
20600Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_hop_limit =
20610Sstevel@tonic-gate 	    attr->ud_addr->av_hop;
20620Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_sender_gid =
20630Sstevel@tonic-gate 	    attr->ud_addr->av_sgid;
20640Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_recver_gid =
20650Sstevel@tonic-gate 	    attr->ud_addr->av_dgid;
20660Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_tclass =
20670Sstevel@tonic-gate 	    attr->ud_addr->av_tclass;
20680Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_flow_label =
20690Sstevel@tonic-gate 	    attr->ud_addr->av_flow & IB_GRH_FLOW_LABEL_MASK;
20700Sstevel@tonic-gate 
20710Sstevel@tonic-gate 	/* needs to be derived based on the base LID and path bits */
20720Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_local_lid =
20730Sstevel@tonic-gate 	    port.hp_base_lid;
20740Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_lid =
20750Sstevel@tonic-gate 	    attr->ud_addr->av_dlid;
20760Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_p_key = ud_pkey;
20770Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_q_key = IB_GSI_QKEY;
20780Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_service_level =
20790Sstevel@tonic-gate 	    attr->ud_addr->av_srvl;
20800Sstevel@tonic-gate 
20810Sstevel@tonic-gate 	/*
20820Sstevel@tonic-gate 	 * This may be enchanced later, to use a remote qno based on past
20830Sstevel@tonic-gate 	 * redirect rej mad responses. This would be the place to specify
20840Sstevel@tonic-gate 	 * appropriate remote qno
20850Sstevel@tonic-gate 	 */
20860Sstevel@tonic-gate 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_qno = 1;
20870Sstevel@tonic-gate 
20880Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
20890Sstevel@tonic-gate 
20900Sstevel@tonic-gate 	/* Initialize the SIDR REQ message fields */
20910Sstevel@tonic-gate 	sidr_req_msgp =
20920Sstevel@tonic-gate 	    (ibcm_sidr_req_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
20930Sstevel@tonic-gate 
20940Sstevel@tonic-gate 	sidr_req_msgp->sidr_req_request_id = h2b32(ud_statep->ud_req_id);
20950Sstevel@tonic-gate 	sidr_req_msgp->sidr_req_service_id = h2b64(attr->ud_sid);
20960Sstevel@tonic-gate 	sidr_req_msgp->sidr_req_pkey = h2b16(ud_pkey);
20970Sstevel@tonic-gate 	IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
20980Sstevel@tonic-gate 	    h2b16(IBCM_INCOMING_SIDR_REQ + IBCM_ATTR_BASE_ID);
20990Sstevel@tonic-gate 
21000Sstevel@tonic-gate 	if ((attr->ud_priv_data != NULL) && (attr->ud_priv_data_len > 0)) {
21010Sstevel@tonic-gate 		bcopy(attr->ud_priv_data, sidr_req_msgp->sidr_req_private_data,
21020Sstevel@tonic-gate 		    min(attr->ud_priv_data_len, IBT_SIDR_REQ_PRIV_DATA_SZ));
21030Sstevel@tonic-gate 	}
21040Sstevel@tonic-gate 
21050Sstevel@tonic-gate 	/* Send out the SIDR REQ message */
21060Sstevel@tonic-gate 	ud_statep->ud_state = IBCM_STATE_SIDR_REQ_SENT;
21070Sstevel@tonic-gate 	ud_statep->ud_timer_stored_state = IBCM_STATE_SIDR_REQ_SENT;
21080Sstevel@tonic-gate 	IBCM_UD_REF_CNT_INCR(ud_statep); /* for non-blocking SIDR REQ post */
21090Sstevel@tonic-gate 	ud_statep->ud_timer_value = ibt_ib2usec(ibcm_max_sidr_rep_proctime) +
21100Sstevel@tonic-gate 	    (ud_statep->ud_pkt_life_time * 2);
21110Sstevel@tonic-gate 
21120Sstevel@tonic-gate 	IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID =
21130Sstevel@tonic-gate 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_SIDR_REQ,
21140Sstevel@tonic-gate 	    ud_statep->ud_req_id, 0));
21150Sstevel@tonic-gate 
21160Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: timer_value in HZ = %x",
21170Sstevel@tonic-gate 	    ud_statep->ud_timer_value);
21180Sstevel@tonic-gate 
21190Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
21200Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
21210Sstevel@tonic-gate 
21220Sstevel@tonic-gate 	ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
21230Sstevel@tonic-gate 	    ibcm_post_sidr_req_complete, ud_statep);
21240Sstevel@tonic-gate 
21250Sstevel@tonic-gate 	mutex_enter(&ud_statep->ud_state_mutex);
21260Sstevel@tonic-gate 
21270Sstevel@tonic-gate 	/* Wait for SIDR_REP */
21280Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
21290Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: blocking");
21300Sstevel@tonic-gate 
21310Sstevel@tonic-gate 		while (ud_statep->ud_blocking_done != B_TRUE) {
21320Sstevel@tonic-gate 			cv_wait(&ud_statep->ud_block_client_cv,
21330Sstevel@tonic-gate 			    &ud_statep->ud_state_mutex);
21340Sstevel@tonic-gate 		}
21350Sstevel@tonic-gate 
21360Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: finished blocking");
21370Sstevel@tonic-gate 
21380Sstevel@tonic-gate 		if (ret_args->ud_status == IBT_CM_SREP_QPN_VALID) {
21390Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: DQPN = %x, "
21400Sstevel@tonic-gate 			    "status = %x, QKey = %x", ret_args->ud_dqpn,
21410Sstevel@tonic-gate 			    ret_args->ud_status, ret_args->ud_qkey);
21420Sstevel@tonic-gate 
21430Sstevel@tonic-gate 		} else {
21440Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: Status<%x>",
21450Sstevel@tonic-gate 			    ret_args->ud_status);
21460Sstevel@tonic-gate 			retval = IBT_CM_FAILURE;
21470Sstevel@tonic-gate 		}
21480Sstevel@tonic-gate 	}
21490Sstevel@tonic-gate 
21500Sstevel@tonic-gate 	IBCM_UD_REF_CNT_DECR(ud_statep);
21510Sstevel@tonic-gate 	mutex_exit(&ud_statep->ud_state_mutex);
21520Sstevel@tonic-gate 
21530Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: done");
21540Sstevel@tonic-gate 
21550Sstevel@tonic-gate 	return (retval);
21560Sstevel@tonic-gate }
21570Sstevel@tonic-gate 
21580Sstevel@tonic-gate 
21590Sstevel@tonic-gate /*
21600Sstevel@tonic-gate  * Function:
21610Sstevel@tonic-gate  *	ibt_request_ud_dest
21620Sstevel@tonic-gate  * Input:
21630Sstevel@tonic-gate  *	ud_dest		A previously allocated UD destination handle.
21640Sstevel@tonic-gate  *	mode		This function can execute in blocking or non blocking
21650Sstevel@tonic-gate  *			modes.
21660Sstevel@tonic-gate  *	attr		UD destination attributes to be modified.
21670Sstevel@tonic-gate  * Output:
21680Sstevel@tonic-gate  *	ud_ret_args	If the function is called in blocking mode, ud_ret_args
21690Sstevel@tonic-gate  *			should be a pointer to an ibt_ud_returns_t struct.
21700Sstevel@tonic-gate  * Returns:
21710Sstevel@tonic-gate  *	IBT_SUCCESS
21720Sstevel@tonic-gate  * Description:
21730Sstevel@tonic-gate  *	Modify a previously allocated UD destination handle based on the
21740Sstevel@tonic-gate  *	results of doing the SIDR protocol.
21750Sstevel@tonic-gate  */
21760Sstevel@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)21770Sstevel@tonic-gate ibt_request_ud_dest(ibt_ud_dest_hdl_t ud_dest, ibt_execution_mode_t mode,
21780Sstevel@tonic-gate     ibt_ud_dest_attr_t *attr, ibt_ud_returns_t *ud_ret_args)
21790Sstevel@tonic-gate {
21800Sstevel@tonic-gate 	ibt_status_t		retval;
21810Sstevel@tonic-gate 	ibt_ud_dest_t		*ud_destp;
21820Sstevel@tonic-gate 	ibcm_local_handler_t	*local_handler_priv = NULL;
21830Sstevel@tonic-gate 
21840Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_request_ud_dest(%p, %x, %p, %p)",
21850Sstevel@tonic-gate 	    ud_dest, mode, attr, ud_ret_args);
21860Sstevel@tonic-gate 
21870Sstevel@tonic-gate 	retval = ibcm_validate_dqpn_data(attr, mode, ud_ret_args);
21880Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
21890Sstevel@tonic-gate 		return (retval);
21900Sstevel@tonic-gate 	}
21910Sstevel@tonic-gate 
21920Sstevel@tonic-gate 	ud_destp = ud_dest;
21930Sstevel@tonic-gate 
21940Sstevel@tonic-gate 	/* Allocate an Address handle. */
21950Sstevel@tonic-gate 	retval = ibt_modify_ah(ud_destp->ud_dest_hca, ud_destp->ud_ah,
21960Sstevel@tonic-gate 	    attr->ud_addr);
21970Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
21980Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
21990Sstevel@tonic-gate 		    "Address Handle Modification failed: %d", retval);
22000Sstevel@tonic-gate 		return (retval);
22010Sstevel@tonic-gate 	}
22020Sstevel@tonic-gate 
22030Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING) {
22040Sstevel@tonic-gate 		/*
22050Sstevel@tonic-gate 		 * In NON-BLOCKING mode, and we need to update the destination
22060Sstevel@tonic-gate 		 * handle with the DQPN and QKey that are obtained from
22070Sstevel@tonic-gate 		 * SIDR REP, hook-up our own handler, so that we can catch
22080Sstevel@tonic-gate 		 * the event, and we ourselves call the actual client's
22090Sstevel@tonic-gate 		 * ud_cm_handler, in our handler.
22100Sstevel@tonic-gate 		 */
22110Sstevel@tonic-gate 
22120Sstevel@tonic-gate 		/* Allocate memory for local handler's private data. */
22130Sstevel@tonic-gate 		local_handler_priv =
22140Sstevel@tonic-gate 		    kmem_alloc(sizeof (*local_handler_priv), KM_SLEEP);
22150Sstevel@tonic-gate 
22160Sstevel@tonic-gate 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*local_handler_priv))
22170Sstevel@tonic-gate 
22180Sstevel@tonic-gate 		local_handler_priv->actual_cm_handler = attr->ud_cm_handler;
22190Sstevel@tonic-gate 		local_handler_priv->actual_cm_private = attr->ud_cm_private;
22200Sstevel@tonic-gate 		local_handler_priv->dest_hdl = ud_destp;
22210Sstevel@tonic-gate 
22220Sstevel@tonic-gate 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*local_handler_priv))
22230Sstevel@tonic-gate 
22240Sstevel@tonic-gate 		attr->ud_cm_handler = ibcm_local_cm_handler;
22250Sstevel@tonic-gate 		attr->ud_cm_private = local_handler_priv;
22260Sstevel@tonic-gate 	}
22270Sstevel@tonic-gate 
22280Sstevel@tonic-gate 	/* In order to get DQPN and Destination QKey, perform SIDR */
22290Sstevel@tonic-gate 	retval = ibcm_ud_get_dqpn(attr, mode, ud_ret_args);
22300Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
22310Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
22320Sstevel@tonic-gate 		    "Failed to get DQPN: %d", retval);
22330Sstevel@tonic-gate 
22340Sstevel@tonic-gate 		/* Free memory allocated for local handler's private data. */
22350Sstevel@tonic-gate 		if (local_handler_priv != NULL)
22360Sstevel@tonic-gate 			kmem_free(local_handler_priv,
22370Sstevel@tonic-gate 			    sizeof (*local_handler_priv));
22380Sstevel@tonic-gate 		return (retval);
22390Sstevel@tonic-gate 	}
22400Sstevel@tonic-gate 
22410Sstevel@tonic-gate 	/*
22420Sstevel@tonic-gate 	 * Fill in the dqpn and dqkey as obtained from ud_ret_args,
22430Sstevel@tonic-gate 	 * values will be valid only on BLOCKING mode.
22440Sstevel@tonic-gate 	 */
22450Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
22460Sstevel@tonic-gate 		ud_destp->ud_dst_qpn = ud_ret_args->ud_dqpn;
22470Sstevel@tonic-gate 		ud_destp->ud_qkey = ud_ret_args->ud_qkey;
22480Sstevel@tonic-gate 	}
22490Sstevel@tonic-gate 
22500Sstevel@tonic-gate 	return (retval);
22510Sstevel@tonic-gate }
22520Sstevel@tonic-gate 
22530Sstevel@tonic-gate /*
22540Sstevel@tonic-gate  * Function:
22550Sstevel@tonic-gate  *	ibt_ud_get_dqpn
22560Sstevel@tonic-gate  * Input:
22570Sstevel@tonic-gate  *	attr		A pointer to an ibt_ud_dest_attr_t struct that are
22580Sstevel@tonic-gate  *			required for SIDR REQ message. Not specified attributes
22590Sstevel@tonic-gate  *			should be set to "NULL" or "0".
22600Sstevel@tonic-gate  *			ud_sid, ud_addr and ud_pkt_lt must be specified.
22610Sstevel@tonic-gate  *	mode		This function can execute in blocking or non blocking
22620Sstevel@tonic-gate  *			modes.
22630Sstevel@tonic-gate  * Output:
22640Sstevel@tonic-gate  *	returns		If the function is called in blocking mode, returns
22650Sstevel@tonic-gate  *			should be a pointer to an ibt_ud_returns_t struct.
22660Sstevel@tonic-gate  * Return:
22670Sstevel@tonic-gate  *	IBT_SUCCESS	on success or respective failure on error.
22680Sstevel@tonic-gate  * Description:
22690Sstevel@tonic-gate  *	Finds the destination QPN at the specified destination that the
22700Sstevel@tonic-gate  *	specified service can be reached on. The IBTF CM initiates the
22710Sstevel@tonic-gate  *	service ID resolution protocol (SIDR) to determine a destination QPN.
22720Sstevel@tonic-gate  *
22730Sstevel@tonic-gate  * NOTE: SIDR_REQ is initiated from active side.
22740Sstevel@tonic-gate  */
22750Sstevel@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)22760Sstevel@tonic-gate ibt_ud_get_dqpn(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
22770Sstevel@tonic-gate     ibt_ud_returns_t *returns)
22780Sstevel@tonic-gate {
22790Sstevel@tonic-gate 	ibt_status_t		retval;
22800Sstevel@tonic-gate 
22810Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_ud_get_dqpn(%p, %x, %p)",
22820Sstevel@tonic-gate 	    attr, mode, returns);
22830Sstevel@tonic-gate 
22840Sstevel@tonic-gate 	retval = ibcm_validate_dqpn_data(attr, mode, returns);
22850Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
22860Sstevel@tonic-gate 		return (retval);
22870Sstevel@tonic-gate 	}
22880Sstevel@tonic-gate 
22890Sstevel@tonic-gate 	return (ibcm_ud_get_dqpn(attr, mode, returns));
22900Sstevel@tonic-gate }
22910Sstevel@tonic-gate 
22920Sstevel@tonic-gate 
22930Sstevel@tonic-gate /*
22940Sstevel@tonic-gate  * ibt_cm_delay:
22950Sstevel@tonic-gate  *	A client CM handler function can call this function
22960Sstevel@tonic-gate  *	to extend its response time to a CM event.
22970Sstevel@tonic-gate  * INPUTS:
22980Sstevel@tonic-gate  *	flags		Indicates what CM message processing is being delayed
22990Sstevel@tonic-gate  *			by the CM handler, valid values are:
23000Sstevel@tonic-gate  *				IBT_CM_DELAY_REQ
23010Sstevel@tonic-gate  *				IBT_CM_DELAY_REP
23020Sstevel@tonic-gate  *				IBT_CM_DELAY_LAP
23030Sstevel@tonic-gate  *	cm_session_id	The session ID that was passed to client srv_handler
23040Sstevel@tonic-gate  *			by the CM
23050Sstevel@tonic-gate  *	service_time	The extended service time
23060Sstevel@tonic-gate  *	priv_data	Vendor specific data to be sent in the CM generated
23070Sstevel@tonic-gate  *			MRA message. Should be NULL if not specified.
23080Sstevel@tonic-gate  *	len		The number of bytes of data specified by priv_data.
23090Sstevel@tonic-gate  *
23100Sstevel@tonic-gate  * RETURN VALUES:
23110Sstevel@tonic-gate  *	IBT_SUCCESS	on success (or respective failure on error)
23120Sstevel@tonic-gate  */
23130Sstevel@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)23140Sstevel@tonic-gate ibt_cm_delay(ibt_cmdelay_flags_t flags, void *cm_session_id,
23150Sstevel@tonic-gate     clock_t service_time, void *priv_data, ibt_priv_data_len_t len)
23160Sstevel@tonic-gate {
23170Sstevel@tonic-gate 	uint8_t			msg_typ = 0;
23180Sstevel@tonic-gate 	ibcm_mra_msg_t		*mra_msgp;
23190Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
23200Sstevel@tonic-gate 	ibt_status_t		status;
23210Sstevel@tonic-gate 
23221093Shiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_delay(0x%x, %p, 0x%x)",
23230Sstevel@tonic-gate 	    flags, cm_session_id, service_time);
23240Sstevel@tonic-gate 
23250Sstevel@tonic-gate 	/*
23260Sstevel@tonic-gate 	 * Make sure channel is associated with a statep
23270Sstevel@tonic-gate 	 */
23280Sstevel@tonic-gate 	statep = (ibcm_state_data_t *)cm_session_id;
23290Sstevel@tonic-gate 
23300Sstevel@tonic-gate 	if (statep == NULL) {
23310Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: statep NULL");
23320Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
23330Sstevel@tonic-gate 	}
23340Sstevel@tonic-gate 
23350Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_cm_delay: statep %p", statep);
23360Sstevel@tonic-gate 
23370Sstevel@tonic-gate 	/* Allocate an ibmf msg for mra, if not allocated yet */
23380Sstevel@tonic-gate 	if (statep->mra_msg == NULL) {
23390Sstevel@tonic-gate 		if ((status = ibcm_alloc_out_msg(
23400Sstevel@tonic-gate 		    statep->stored_reply_addr.ibmf_hdl, &statep->mra_msg,
23410Sstevel@tonic-gate 		    MAD_METHOD_SEND)) != IBT_SUCCESS) {
23420Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: chan 0x%p"
23430Sstevel@tonic-gate 			    "IBMF MSG allocation failed", statep->channel);
23440Sstevel@tonic-gate 			return (status);
23450Sstevel@tonic-gate 		}
23460Sstevel@tonic-gate 	}
23470Sstevel@tonic-gate 
23480Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mra_msgp))
23490Sstevel@tonic-gate 
23500Sstevel@tonic-gate 	mra_msgp = (ibcm_mra_msg_t *)IBCM_OUT_MSGP(statep->mra_msg);
23510Sstevel@tonic-gate 	mra_msgp->mra_local_comm_id = h2b32(statep->local_comid);
23520Sstevel@tonic-gate 	mra_msgp->mra_remote_comm_id = h2b32(statep->remote_comid);
23530Sstevel@tonic-gate 
23540Sstevel@tonic-gate 	/* fill in rest of MRA's fields - Message MRAed and Service Timeout */
23550Sstevel@tonic-gate 	if (flags == IBT_CM_DELAY_REQ) {
23560Sstevel@tonic-gate 		msg_typ = IBT_CM_MRA_TYPE_REQ;
23570Sstevel@tonic-gate 	} else if (flags == IBT_CM_DELAY_REP) {
23580Sstevel@tonic-gate 		msg_typ = IBT_CM_MRA_TYPE_REP;
23590Sstevel@tonic-gate 	} else if (flags == IBT_CM_DELAY_LAP) {
23600Sstevel@tonic-gate 		msg_typ = IBT_CM_MRA_TYPE_LAP;
23610Sstevel@tonic-gate 	}
23620Sstevel@tonic-gate 
23630Sstevel@tonic-gate 	mra_msgp->mra_message_type_plus = msg_typ << 6;
23640Sstevel@tonic-gate 	mra_msgp->mra_service_timeout_plus = ibt_usec2ib(service_time) << 3;
23650Sstevel@tonic-gate 
23660Sstevel@tonic-gate 	len = min(len, IBT_MRA_PRIV_DATA_SZ);
23670Sstevel@tonic-gate 	if (priv_data && (len > 0))
23680Sstevel@tonic-gate 		bcopy(priv_data, mra_msgp->mra_private_data, len);
23690Sstevel@tonic-gate 
23700Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->mra_msg)->AttributeID =
23710Sstevel@tonic-gate 	    h2b16(IBCM_INCOMING_MRA + IBCM_ATTR_BASE_ID);
23720Sstevel@tonic-gate 
23730Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mra_msgp))
23740Sstevel@tonic-gate 
23750Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
23760Sstevel@tonic-gate 
23770Sstevel@tonic-gate 	if ((statep->mode == IBCM_ACTIVE_MODE) &&
23780Sstevel@tonic-gate 	    (statep->state == IBCM_STATE_REP_RCVD)) {
23790Sstevel@tonic-gate 		statep->state = IBCM_STATE_MRA_REP_SENT;
23800Sstevel@tonic-gate 	} else if (statep->mode == IBCM_PASSIVE_MODE) {
2381401Shiremath 		if (statep->state == IBCM_STATE_REQ_RCVD) {
23820Sstevel@tonic-gate 			statep->state = IBCM_STATE_MRA_SENT;
2383401Shiremath 		} else if (statep->ap_state == IBCM_AP_STATE_LAP_RCVD) {
23840Sstevel@tonic-gate 			statep->ap_state = IBCM_AP_STATE_MRA_LAP_RCVD;
2385401Shiremath 		} else {
23861093Shiremath 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
2387401Shiremath 			    "/ap_state/mode %x, %x, %x", statep->state,
2388401Shiremath 			    statep->ap_state, statep->mode);
2389401Shiremath 			mutex_exit(&statep->state_mutex);
2390401Shiremath 			return (IBT_CHAN_STATE_INVALID);
23910Sstevel@tonic-gate 		}
23920Sstevel@tonic-gate 	} else {
23931093Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
23940Sstevel@tonic-gate 		    "/ap_state/mode %x, %x, %x", statep->state,
23950Sstevel@tonic-gate 		    statep->ap_state, statep->mode);
23960Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
23970Sstevel@tonic-gate 
23980Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
23990Sstevel@tonic-gate 	}
2400401Shiremath 	/* service time is usecs, stale_clock is nsecs */
2401557Shiremath 	statep->stale_clock = gethrtime() +
2402557Shiremath 	    (hrtime_t)ibt_ib2usec(ibt_usec2ib(service_time)) * (1000 *
2403401Shiremath 	    statep->max_cm_retries);
24040Sstevel@tonic-gate 
24050Sstevel@tonic-gate 	statep->send_mad_flags |= IBCM_MRA_POST_BUSY;
24060Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);	/* for ibcm_post_mra_complete */
24070Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
24080Sstevel@tonic-gate 
24090Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->mra_msg)->TransactionID =
24104703Shiremath 	    IBCM_OUT_HDRP(statep->stored_msg)->TransactionID;
24110Sstevel@tonic-gate 
24120Sstevel@tonic-gate 	/* post the MRA mad in blocking mode, as no timers involved */
24130Sstevel@tonic-gate 	ibcm_post_rc_mad(statep, statep->mra_msg, ibcm_post_mra_complete,
24140Sstevel@tonic-gate 	    statep);
24151093Shiremath 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_MRA);
24160Sstevel@tonic-gate 	/* If this message isn't seen then ibt_cm_delay failed */
24171093Shiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_delay: done !!");
24180Sstevel@tonic-gate 
24190Sstevel@tonic-gate 	return (IBT_SUCCESS);
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate 
24220Sstevel@tonic-gate 
24230Sstevel@tonic-gate /*
24240Sstevel@tonic-gate  * ibt_register_service()
24250Sstevel@tonic-gate  *	Register a service with the IBCM
24260Sstevel@tonic-gate  *
24270Sstevel@tonic-gate  * INPUTS:
24280Sstevel@tonic-gate  *	ibt_hdl		The IBT client handle returned to the client
24290Sstevel@tonic-gate  *			on an ibt_attach() call.
24300Sstevel@tonic-gate  *
24310Sstevel@tonic-gate  *	srv		The address of a ibt_srv_desc_t that describes
24320Sstevel@tonic-gate  *			the service, containing the following:
24330Sstevel@tonic-gate  *
24340Sstevel@tonic-gate  *		sd_ud_handler	The Service CM UD event Handler.
24350Sstevel@tonic-gate  *		sd_handler	The Service CM RC/UC/RD event Handler.
24360Sstevel@tonic-gate  *		sd_flags	Service flags (peer-to-peer, or not).
24370Sstevel@tonic-gate  *
24380Sstevel@tonic-gate  *	sid		This tells CM if the service is local (sid is 0) or
24390Sstevel@tonic-gate  *			wellknown (sid is the starting service id of the range).
24400Sstevel@tonic-gate  *
24410Sstevel@tonic-gate  *	num_sids	The number of contiguous service-ids to reserve.
24420Sstevel@tonic-gate  *
24430Sstevel@tonic-gate  *	srv_hdl		The address of a service identification handle, used
24440Sstevel@tonic-gate  *			to deregister a service, and to bind GIDs to.
24450Sstevel@tonic-gate  *
24460Sstevel@tonic-gate  *	ret_sid		The address to store the Service ID return value.
24470Sstevel@tonic-gate  *			If num_sids > 1, ret_sid is the first Service ID
24480Sstevel@tonic-gate  *			in the range.
24490Sstevel@tonic-gate  *
24500Sstevel@tonic-gate  * ibt_register_service() returns:
24510Sstevel@tonic-gate  *	IBT_SUCCESS		- added a service successfully.
24520Sstevel@tonic-gate  *	IBT_INVALID_PARAM	- invalid input parameter.
24530Sstevel@tonic-gate  *	IBT_CM_FAILURE		- failed to add the service.
24540Sstevel@tonic-gate  *	IBT_CM_SERVICE_EXISTS	- service already exists.
24550Sstevel@tonic-gate  *	IBT_INSUFF_KERNEL_RESOURCE - ran out of local service ids (should
24560Sstevel@tonic-gate  *				     never happen).
24570Sstevel@tonic-gate  */
24580Sstevel@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)24590Sstevel@tonic-gate ibt_register_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_desc_t *srv,
24600Sstevel@tonic-gate     ib_svc_id_t sid, int num_sids, ibt_srv_hdl_t *srv_hdl, ib_svc_id_t *ret_sid)
24610Sstevel@tonic-gate {
24620Sstevel@tonic-gate 	ibcm_svc_info_t		*svcinfop;
24630Sstevel@tonic-gate 
24649349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L2(cmlog, "ibt_register_service(%p (%s), %p, 0x%llX, %d)",
24659349SShantkumar.Hiremath@Sun.COM 	    ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv, (longlong_t)sid,
24669349SShantkumar.Hiremath@Sun.COM 	    num_sids);
24670Sstevel@tonic-gate 
24680Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*svcinfop))
24690Sstevel@tonic-gate 
24700Sstevel@tonic-gate 	*srv_hdl = NULL;
24710Sstevel@tonic-gate 
24720Sstevel@tonic-gate 	if (num_sids <= 0) {
24730Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24740Sstevel@tonic-gate 		    "Invalid number of service-ids specified (%d)", num_sids);
24750Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
24760Sstevel@tonic-gate 	}
24770Sstevel@tonic-gate 
24780Sstevel@tonic-gate 	if (sid == 0) {
24790Sstevel@tonic-gate 		if (ret_sid == NULL)
24800Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
24810Sstevel@tonic-gate 		sid = ibcm_alloc_local_sids(num_sids);
24820Sstevel@tonic-gate 		if (sid == 0)
24830Sstevel@tonic-gate 			return (IBT_INSUFF_KERNEL_RESOURCE);
24840Sstevel@tonic-gate 
24850Sstevel@tonic-gate 	/* Make sure that the ServiceId specified is not of LOCAL AGN type. */
24860Sstevel@tonic-gate 	} else if ((sid & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL) {
24870Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24880Sstevel@tonic-gate 		    "Invalid non-LOCAL SID specified: 0x%llX",
24890Sstevel@tonic-gate 		    (longlong_t)sid);
24900Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
24910Sstevel@tonic-gate 	}
24920Sstevel@tonic-gate 
24930Sstevel@tonic-gate 	svcinfop = ibcm_create_svc_entry(sid, num_sids);
24940Sstevel@tonic-gate 
24950Sstevel@tonic-gate 	if (svcinfop == NULL) {
24960Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
24970Sstevel@tonic-gate 		    "Service-ID 0x%llx already registered", (longlong_t)sid);
24980Sstevel@tonic-gate 		return (IBT_CM_SERVICE_EXISTS);
24990Sstevel@tonic-gate 	}
25000Sstevel@tonic-gate 
25010Sstevel@tonic-gate 	/*
25020Sstevel@tonic-gate 	 * 'sid' and 'num_sids' are filled in ibcm_create_svc_entry()
25030Sstevel@tonic-gate 	 */
25040Sstevel@tonic-gate 	svcinfop->svc_flags = srv->sd_flags;
25050Sstevel@tonic-gate 	svcinfop->svc_rc_handler = srv->sd_handler;
25060Sstevel@tonic-gate 	svcinfop->svc_ud_handler = srv->sd_ud_handler;
25070Sstevel@tonic-gate 
25080Sstevel@tonic-gate 	if (ret_sid != NULL)
25090Sstevel@tonic-gate 		*ret_sid = sid;
25100Sstevel@tonic-gate 
25110Sstevel@tonic-gate 	*srv_hdl = svcinfop;
25120Sstevel@tonic-gate 
25130Sstevel@tonic-gate 	ibtl_cm_change_service_cnt(ibt_hdl, num_sids);
25140Sstevel@tonic-gate 
25150Sstevel@tonic-gate 	/* If this message isn't seen, then ibt_register_service failed. */
25160Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_register_service: done (%p, %llX)",
25170Sstevel@tonic-gate 	    svcinfop, sid);
25180Sstevel@tonic-gate 
25190Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*svcinfop))
25200Sstevel@tonic-gate 
25210Sstevel@tonic-gate 	return (IBT_SUCCESS);
25220Sstevel@tonic-gate }
25230Sstevel@tonic-gate 
25240Sstevel@tonic-gate 
25250Sstevel@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)25260Sstevel@tonic-gate ibcm_write_service_record(ibmf_saa_handle_t saa_handle,
25270Sstevel@tonic-gate     sa_service_record_t *srv_recp, ibmf_saa_access_type_t saa_type)
25280Sstevel@tonic-gate {
25290Sstevel@tonic-gate 	int	rval;
25300Sstevel@tonic-gate 	int	retry;
25310Sstevel@tonic-gate 
25320Sstevel@tonic-gate 	ibcm_sa_access_enter();
25330Sstevel@tonic-gate 	for (retry = 0; retry < ibcm_max_sa_retries; retry++) {
25340Sstevel@tonic-gate 		rval = ibmf_saa_update_service_record(
25350Sstevel@tonic-gate 		    saa_handle, srv_recp, saa_type, 0);
25360Sstevel@tonic-gate 		if (rval != IBMF_TRANS_TIMEOUT) {
25370Sstevel@tonic-gate 			break;
25380Sstevel@tonic-gate 		}
25390Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
25400Sstevel@tonic-gate 		    "ibmf_saa_update_service_record timed out"
25410Sstevel@tonic-gate 		    " SID = %llX, rval = %d, saa_type = %d",
25420Sstevel@tonic-gate 		    (longlong_t)srv_recp->ServiceID, rval, saa_type);
25430Sstevel@tonic-gate 		delay(ibcm_sa_timeout_delay);
25440Sstevel@tonic-gate 	}
25450Sstevel@tonic-gate 	ibcm_sa_access_exit();
25460Sstevel@tonic-gate 
25470Sstevel@tonic-gate 	if (rval != IBMF_SUCCESS) {
25480Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
25490Sstevel@tonic-gate 		    "ibmf_saa_update_service_record() : Failed - %d", rval);
25500Sstevel@tonic-gate 		return (ibcm_ibmf_analyze_error(rval));
25510Sstevel@tonic-gate 	} else
25520Sstevel@tonic-gate 		return (IBT_SUCCESS);
25530Sstevel@tonic-gate }
25540Sstevel@tonic-gate 
25550Sstevel@tonic-gate 
25560Sstevel@tonic-gate static void
ibcm_rem_stale_srec(ibmf_saa_handle_t saa_handle,sa_service_record_t * srec)25570Sstevel@tonic-gate ibcm_rem_stale_srec(ibmf_saa_handle_t saa_handle, sa_service_record_t *srec)
25580Sstevel@tonic-gate {
25590Sstevel@tonic-gate 	ibt_status_t		retval;
25600Sstevel@tonic-gate 	uint_t			num_found;
25610Sstevel@tonic-gate 	size_t			length;
25620Sstevel@tonic-gate 	sa_service_record_t	*srv_resp;
25630Sstevel@tonic-gate 	void			*results_p;
25640Sstevel@tonic-gate 	uint_t			i;
25650Sstevel@tonic-gate 	uint64_t		component_mask;
25660Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
25670Sstevel@tonic-gate 
25680Sstevel@tonic-gate 	component_mask =
25690Sstevel@tonic-gate 	    SA_SR_COMPMASK_PKEY | SA_SR_COMPMASK_NAME | SA_SR_COMPMASK_GID;
25700Sstevel@tonic-gate 
25710Sstevel@tonic-gate 	/* Call in SA Access retrieve routine to get Service Records. */
25720Sstevel@tonic-gate 	access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
25730Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
25740Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
25750Sstevel@tonic-gate 	access_args.sq_template = srec;
25760Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_service_record_t);
25770Sstevel@tonic-gate 	access_args.sq_callback = NULL;
25780Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
25790Sstevel@tonic-gate 
25800Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
25810Sstevel@tonic-gate 	    &results_p);
25820Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
25830Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
25840Sstevel@tonic-gate 		    "SA Access Failure");
25850Sstevel@tonic-gate 		return;
25860Sstevel@tonic-gate 	}
25870Sstevel@tonic-gate 
25880Sstevel@tonic-gate 	num_found = length / sizeof (sa_service_record_t);
25890Sstevel@tonic-gate 
25900Sstevel@tonic-gate 	if (num_found)
25910Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
25920Sstevel@tonic-gate 		    "Found %d matching Service Records.", num_found);
25930Sstevel@tonic-gate 
25940Sstevel@tonic-gate 	/* Validate the returned number of records. */
25950Sstevel@tonic-gate 	if ((results_p != NULL) && (num_found > 0)) {
25960Sstevel@tonic-gate 
25970Sstevel@tonic-gate 		/* Remove all the records. */
25980Sstevel@tonic-gate 		for (i = 0; i < num_found; i++) {
25990Sstevel@tonic-gate 
26000Sstevel@tonic-gate 			srv_resp = (sa_service_record_t *)
26010Sstevel@tonic-gate 			    ((uchar_t *)results_p +
26020Sstevel@tonic-gate 			    i * sizeof (sa_service_record_t));
26030Sstevel@tonic-gate 
26040Sstevel@tonic-gate 			/*
26050Sstevel@tonic-gate 			 * Found some matching records, but check out whether
26060Sstevel@tonic-gate 			 * this Record is really stale or just happens to match
26070Sstevel@tonic-gate 			 * the current session records. If yes, don't remove it.
26080Sstevel@tonic-gate 			 */
26090Sstevel@tonic-gate 			mutex_enter(&ibcm_svc_info_lock);
26100Sstevel@tonic-gate 			if (ibcm_find_svc_entry(srv_resp->ServiceID) != NULL) {
26110Sstevel@tonic-gate 				/* This record is NOT STALE. */
26120Sstevel@tonic-gate 				mutex_exit(&ibcm_svc_info_lock);
26130Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
26140Sstevel@tonic-gate 				    "This is not Stale, it's an active record");
26150Sstevel@tonic-gate 				continue;
26160Sstevel@tonic-gate 			}
26170Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
26180Sstevel@tonic-gate 
26190Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
26200Sstevel@tonic-gate 			    "Removing Stale Rec: %s, %llX",
26210Sstevel@tonic-gate 			    srv_resp->ServiceName, srv_resp->ServiceID);
26220Sstevel@tonic-gate 
26230Sstevel@tonic-gate 			IBCM_DUMP_SERVICE_REC(srv_resp);
26240Sstevel@tonic-gate 
26250Sstevel@tonic-gate 			/*
26260Sstevel@tonic-gate 			 * Remove the Service Record Entry from SA.
26270Sstevel@tonic-gate 			 *
26280Sstevel@tonic-gate 			 * Get ServiceID info from Response Buf, other
26290Sstevel@tonic-gate 			 * attributes are already filled-in.
26300Sstevel@tonic-gate 			 */
26310Sstevel@tonic-gate 
26320Sstevel@tonic-gate 			 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srec->ServiceID))
26330Sstevel@tonic-gate 
26340Sstevel@tonic-gate 			srec->ServiceID = srv_resp->ServiceID;
26350Sstevel@tonic-gate 
26360Sstevel@tonic-gate 			 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srec->ServiceID))
26370Sstevel@tonic-gate 
26380Sstevel@tonic-gate 			(void) ibcm_write_service_record(saa_handle, srec,
26390Sstevel@tonic-gate 			    IBMF_SAA_DELETE);
26400Sstevel@tonic-gate 		}
26410Sstevel@tonic-gate 
26420Sstevel@tonic-gate 		/* Deallocate the memory for results_p. */
26430Sstevel@tonic-gate 		kmem_free(results_p, length);
26440Sstevel@tonic-gate 	}
26450Sstevel@tonic-gate }
26460Sstevel@tonic-gate 
26470Sstevel@tonic-gate 
26480Sstevel@tonic-gate 
26490Sstevel@tonic-gate /*
26500Sstevel@tonic-gate  * ibt_bind_service()
26510Sstevel@tonic-gate  *	Register a service with the IBCM
26520Sstevel@tonic-gate  *
26530Sstevel@tonic-gate  * INPUTS:
26540Sstevel@tonic-gate  *	srv_hdl		The service id handle returned to the client
26550Sstevel@tonic-gate  *			on an ibt_service_register() call.
26560Sstevel@tonic-gate  *
26570Sstevel@tonic-gate  *	gid		The GID to which to bind the service.
26580Sstevel@tonic-gate  *
26590Sstevel@tonic-gate  *	srv_bind	The address of a ibt_srv_bind_t that describes
26600Sstevel@tonic-gate  *			the service record.  This should be NULL if there
26610Sstevel@tonic-gate  *			is to be no service record.  This contains:
26620Sstevel@tonic-gate  *
26630Sstevel@tonic-gate  *		sb_lease	Lease period
26640Sstevel@tonic-gate  *		sb_pkey		Partition
26650Sstevel@tonic-gate  *		sb_name		pointer to ASCII string Service Name,
26660Sstevel@tonic-gate  *				NULL terminated.
26670Sstevel@tonic-gate  *		sb_key[]	Key to secure the service record.
26680Sstevel@tonic-gate  *		sb_data		Service Data structure (64-byte)
26690Sstevel@tonic-gate  *
26700Sstevel@tonic-gate  *	cm_private	First argument of Service handler.
26710Sstevel@tonic-gate  *
26720Sstevel@tonic-gate  *	sb_hdl_p	The address of a service bind handle, used
26730Sstevel@tonic-gate  *			to undo the service binding.
26740Sstevel@tonic-gate  *
26750Sstevel@tonic-gate  * ibt_bind_service() returns:
26760Sstevel@tonic-gate  *	IBT_SUCCESS		- added a service successfully.
26770Sstevel@tonic-gate  *	IBT_INVALID_PARAM	- invalid input parameter.
26780Sstevel@tonic-gate  *	IBT_CM_FAILURE		- failed to add the service.
26790Sstevel@tonic-gate  *	IBT_CM_SERVICE_EXISTS	- service already exists.
26800Sstevel@tonic-gate  */
26810Sstevel@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)26820Sstevel@tonic-gate ibt_bind_service(ibt_srv_hdl_t srv_hdl, ib_gid_t gid, ibt_srv_bind_t *srv_bind,
26830Sstevel@tonic-gate     void *cm_private, ibt_sbind_hdl_t *sb_hdl_p)
26840Sstevel@tonic-gate {
26850Sstevel@tonic-gate 	ibt_status_t		status;
26860Sstevel@tonic-gate 	ibtl_cm_hca_port_t	port;
26870Sstevel@tonic-gate 	ibcm_svc_bind_t		*sbindp, *sbp;
26880Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
26890Sstevel@tonic-gate 	ib_svc_id_t		sid, start_sid, end_sid;
26900Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
26910Sstevel@tonic-gate 	sa_service_record_t	srv_rec;
26920Sstevel@tonic-gate 	uint16_t		pkey_ix;
26930Sstevel@tonic-gate 
26940Sstevel@tonic-gate 	if (sb_hdl_p != NULL)
26950Sstevel@tonic-gate 		*sb_hdl_p = NULL;	/* return value for error cases */
26960Sstevel@tonic-gate 
26970Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: srv_hdl %p, gid (%llX:%llX)",
26980Sstevel@tonic-gate 	    srv_hdl, (longlong_t)gid.gid_prefix, (longlong_t)gid.gid_guid);
26990Sstevel@tonic-gate 
27000Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sbindp))
27010Sstevel@tonic-gate 
27020Sstevel@tonic-gate 	/* Call ibtl_cm_get_hca_port to get the port number and the HCA GUID. */
27030Sstevel@tonic-gate 	if ((status = ibtl_cm_get_hca_port(gid, 0, &port)) != IBT_SUCCESS) {
27040Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27050Sstevel@tonic-gate 		    "ibtl_cm_get_hca_port failed: %d", status);
27060Sstevel@tonic-gate 		return (status);
27070Sstevel@tonic-gate 	}
27080Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: Port:%d HCA GUID:%llX",
27090Sstevel@tonic-gate 	    port.hp_port, port.hp_hca_guid);
27100Sstevel@tonic-gate 
27110Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(port.hp_hca_guid);
27120Sstevel@tonic-gate 	if (hcap == NULL) {
27130Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: NO HCA found");
27140Sstevel@tonic-gate 		return (IBT_HCA_BUSY_DETACHING);
27150Sstevel@tonic-gate 	}
27160Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: hcap = %p", hcap);
27170Sstevel@tonic-gate 
27180Sstevel@tonic-gate 	if (srv_bind != NULL) {
27190Sstevel@tonic-gate 		saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
27200Sstevel@tonic-gate 		if (saa_handle == NULL) {
27210Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27220Sstevel@tonic-gate 			    "saa_handle is NULL");
27230Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
27240Sstevel@tonic-gate 			return (IBT_HCA_PORT_NOT_ACTIVE);
27250Sstevel@tonic-gate 		}
27260Sstevel@tonic-gate 		if (srv_bind->sb_pkey == 0) {
27270Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27280Sstevel@tonic-gate 			    "P_Key must not be 0");
27290Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
27300Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
27310Sstevel@tonic-gate 		}
27320Sstevel@tonic-gate 		if (strlen(srv_bind->sb_name) >= IB_SVC_NAME_LEN) {
27330Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27340Sstevel@tonic-gate 			    "Service Name is too long");
27350Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
27360Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
27370Sstevel@tonic-gate 		} else
27380Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_bind_service: "
27390Sstevel@tonic-gate 			    "Service Name='%s'", srv_bind->sb_name);
27400Sstevel@tonic-gate 		status = ibt_pkey2index_byguid(port.hp_hca_guid,
27410Sstevel@tonic-gate 		    port.hp_port, srv_bind->sb_pkey, &pkey_ix);
27420Sstevel@tonic-gate 		if (status != IBT_SUCCESS) {
27430Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27440Sstevel@tonic-gate 			    "P_Key 0x%x not found in P_Key_Table",
27450Sstevel@tonic-gate 			    srv_bind->sb_pkey);
27460Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
27470Sstevel@tonic-gate 			return (status);
27480Sstevel@tonic-gate 		}
27490Sstevel@tonic-gate 	}
27500Sstevel@tonic-gate 
27510Sstevel@tonic-gate 	/* assume success - allocate before locking */
27520Sstevel@tonic-gate 	sbindp = kmem_zalloc(sizeof (*sbindp), KM_SLEEP);
27530Sstevel@tonic-gate 	sbindp->sbind_cm_private = cm_private;
27540Sstevel@tonic-gate 	sbindp->sbind_gid = gid;
27550Sstevel@tonic-gate 	sbindp->sbind_hcaguid = port.hp_hca_guid;
27560Sstevel@tonic-gate 	sbindp->sbind_port = port.hp_port;
27570Sstevel@tonic-gate 
27580Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
27590Sstevel@tonic-gate 
27600Sstevel@tonic-gate 	sbp = srv_hdl->svc_bind_list;
27610Sstevel@tonic-gate 	while (sbp != NULL) {
27620Sstevel@tonic-gate 		if (sbp->sbind_gid.gid_guid == gid.gid_guid &&
27630Sstevel@tonic-gate 		    sbp->sbind_gid.gid_prefix == gid.gid_prefix) {
27640Sstevel@tonic-gate 			if (srv_bind == NULL ||
27650Sstevel@tonic-gate 			    srv_bind->sb_pkey == sbp->sbind_pkey) {
27660Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
27671495Shiremath 				    "failed: GID %llX:%llX and PKEY %x is "
27686709Shiremath 				    "already bound", gid.gid_prefix,
27696709Shiremath 				    gid.gid_guid, sbp->sbind_pkey);
27700Sstevel@tonic-gate 				mutex_exit(&ibcm_svc_info_lock);
27710Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
27720Sstevel@tonic-gate 				kmem_free(sbindp, sizeof (*sbindp));
27730Sstevel@tonic-gate 				return (IBT_CM_SERVICE_EXISTS);
27740Sstevel@tonic-gate 			}
27750Sstevel@tonic-gate 		}
27760Sstevel@tonic-gate 		sbp = sbp->sbind_link;
27770Sstevel@tonic-gate 	}
27780Sstevel@tonic-gate 	/* no entry found */
27790Sstevel@tonic-gate 
27800Sstevel@tonic-gate 	sbindp->sbind_link = srv_hdl->svc_bind_list;
27810Sstevel@tonic-gate 	srv_hdl->svc_bind_list = sbindp;
27820Sstevel@tonic-gate 
27830Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
27840Sstevel@tonic-gate 
27850Sstevel@tonic-gate 	if (srv_bind != NULL) {
27860Sstevel@tonic-gate 		bzero(&srv_rec, sizeof (srv_rec));
27870Sstevel@tonic-gate 
27880Sstevel@tonic-gate 		srv_rec.ServiceLease =
27890Sstevel@tonic-gate 		    sbindp->sbind_lease = srv_bind->sb_lease;
27900Sstevel@tonic-gate 		srv_rec.ServiceP_Key =
27910Sstevel@tonic-gate 		    sbindp->sbind_pkey = srv_bind->sb_pkey;
27920Sstevel@tonic-gate 		srv_rec.ServiceKey_hi =
27930Sstevel@tonic-gate 		    sbindp->sbind_key[0] = srv_bind->sb_key[0];
27940Sstevel@tonic-gate 		srv_rec.ServiceKey_lo =
27950Sstevel@tonic-gate 		    sbindp->sbind_key[1] = srv_bind->sb_key[1];
27960Sstevel@tonic-gate 		(void) strcpy(sbindp->sbind_name, srv_bind->sb_name);
27970Sstevel@tonic-gate 		(void) strcpy((char *)srv_rec.ServiceName, srv_bind->sb_name);
27980Sstevel@tonic-gate 		srv_rec.ServiceGID = gid;
27990Sstevel@tonic-gate 
28000Sstevel@tonic-gate 		/*
28010Sstevel@tonic-gate 		 * Find out whether we have any stale Local Service records
28020Sstevel@tonic-gate 		 * matching the current attributes.  If yes, we shall try to
28030Sstevel@tonic-gate 		 * remove them from SA using the current request's ServiceKey.
28040Sstevel@tonic-gate 		 *
28050Sstevel@tonic-gate 		 * We will perform this operation only for Local Services, as
28060Sstevel@tonic-gate 		 * it is handled by SA automatically for WellKnown Services.
28070Sstevel@tonic-gate 		 *
28080Sstevel@tonic-gate 		 * Ofcourse, clients can specify NOT to do this clean-up by
28090Sstevel@tonic-gate 		 * setting IBT_SBIND_NO_CLEANUP flag (srv_bind->sb_flag).
28100Sstevel@tonic-gate 		 */
28110Sstevel@tonic-gate 		if ((srv_hdl->svc_id & IB_SID_AGN_LOCAL) &&
28120Sstevel@tonic-gate 		    (!(srv_bind->sb_flag & IBT_SBIND_NO_CLEANUP))) {
28130Sstevel@tonic-gate 			ibcm_rem_stale_srec(saa_handle, &srv_rec);
28140Sstevel@tonic-gate 		}
28150Sstevel@tonic-gate 
28160Sstevel@tonic-gate 		/* Handle endianess for service data. */
28170Sstevel@tonic-gate 		ibcm_swizzle_from_srv(&srv_bind->sb_data, sbindp->sbind_data);
28180Sstevel@tonic-gate 
28190Sstevel@tonic-gate 		bcopy(sbindp->sbind_data, srv_rec.ServiceData, IB_SVC_DATA_LEN);
28200Sstevel@tonic-gate 
28210Sstevel@tonic-gate 		/* insert srv record into the SA */
28220Sstevel@tonic-gate 		start_sid = srv_hdl->svc_id;
28230Sstevel@tonic-gate 		end_sid = start_sid + srv_hdl->svc_num_sids - 1;
28240Sstevel@tonic-gate 		for (sid = start_sid; sid <= end_sid; sid++) {
28250Sstevel@tonic-gate 
28260Sstevel@tonic-gate 			srv_rec.ServiceID = sid;
28270Sstevel@tonic-gate 
28280Sstevel@tonic-gate 			IBCM_DUMP_SERVICE_REC(&srv_rec);
28290Sstevel@tonic-gate 
28300Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: "
28310Sstevel@tonic-gate 			    "ibmf_saa_write_service_record, SvcId = %llX",
28320Sstevel@tonic-gate 			    (longlong_t)sid);
28330Sstevel@tonic-gate 
28340Sstevel@tonic-gate 			status = ibcm_write_service_record(saa_handle, &srv_rec,
28350Sstevel@tonic-gate 			    IBMF_SAA_UPDATE);
28360Sstevel@tonic-gate 			if (status != IBT_SUCCESS) {
28370Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_bind_service:"
28380Sstevel@tonic-gate 				    " ibcm_write_service_record fails %d, "
28390Sstevel@tonic-gate 				    "sid %llX", status, (longlong_t)sid);
28400Sstevel@tonic-gate 
28410Sstevel@tonic-gate 				if (sid != start_sid) {
28420Sstevel@tonic-gate 					/*
28430Sstevel@tonic-gate 					 * Bind failed while bind SID other than
28440Sstevel@tonic-gate 					 * first in the sid_range.  So we need
28450Sstevel@tonic-gate 					 * to unbind those, which are passed.
28460Sstevel@tonic-gate 					 *
28470Sstevel@tonic-gate 					 * Need to increment svc count to
28480Sstevel@tonic-gate 					 * compensate for ibt_unbind_service().
28490Sstevel@tonic-gate 					 */
28500Sstevel@tonic-gate 					ibcm_inc_hca_svc_cnt(hcap);
28510Sstevel@tonic-gate 					ibcm_dec_hca_acc_cnt(hcap);
28520Sstevel@tonic-gate 
28530Sstevel@tonic-gate 					(void) ibt_unbind_service(srv_hdl,
28540Sstevel@tonic-gate 					    sbindp);
28550Sstevel@tonic-gate 				} else {
28560Sstevel@tonic-gate 					ibcm_svc_bind_t		**sbpp;
28570Sstevel@tonic-gate 
28580Sstevel@tonic-gate 					/*
28590Sstevel@tonic-gate 					 * Bind failed for the first SID or the
28600Sstevel@tonic-gate 					 * only SID in question, then no need
28610Sstevel@tonic-gate 					 * to unbind, just free memory and
28620Sstevel@tonic-gate 					 * return error.
28630Sstevel@tonic-gate 					 */
28640Sstevel@tonic-gate 					mutex_enter(&ibcm_svc_info_lock);
28650Sstevel@tonic-gate 
28660Sstevel@tonic-gate 					sbpp = &srv_hdl->svc_bind_list;
28670Sstevel@tonic-gate 					sbp = *sbpp;
28680Sstevel@tonic-gate 					while (sbp != NULL) {
28690Sstevel@tonic-gate 						if (sbp == sbindp) {
28700Sstevel@tonic-gate 							*sbpp = sbp->sbind_link;
28710Sstevel@tonic-gate 							break;
28720Sstevel@tonic-gate 						}
28730Sstevel@tonic-gate 						sbpp = &sbp->sbind_link;
28740Sstevel@tonic-gate 						sbp = *sbpp;
28750Sstevel@tonic-gate 					}
28760Sstevel@tonic-gate 					mutex_exit(&ibcm_svc_info_lock);
28770Sstevel@tonic-gate 					ibcm_dec_hca_acc_cnt(hcap);
28780Sstevel@tonic-gate 
28790Sstevel@tonic-gate 					kmem_free(sbindp, sizeof (*sbindp));
28800Sstevel@tonic-gate 				}
28810Sstevel@tonic-gate 				return (status);
28820Sstevel@tonic-gate 			}
28830Sstevel@tonic-gate 		}
28840Sstevel@tonic-gate 	}
28850Sstevel@tonic-gate 	ibcm_inc_hca_svc_cnt(hcap);
28860Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
28870Sstevel@tonic-gate 
28880Sstevel@tonic-gate 	/* If this message isn't seen then ibt_bind_service failed */
28891093Shiremath 	IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: DONE (%p, %llX:%llX)",
28900Sstevel@tonic-gate 	    srv_hdl, gid.gid_prefix, gid.gid_guid);
28910Sstevel@tonic-gate 
28920Sstevel@tonic-gate 	if (sb_hdl_p != NULL)
28930Sstevel@tonic-gate 		*sb_hdl_p = sbindp;
28940Sstevel@tonic-gate 
28950Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sbindp))
28960Sstevel@tonic-gate 
28970Sstevel@tonic-gate 	return (IBT_SUCCESS);
28980Sstevel@tonic-gate }
28990Sstevel@tonic-gate 
29000Sstevel@tonic-gate ibt_status_t
ibt_unbind_service(ibt_srv_hdl_t srv_hdl,ibt_sbind_hdl_t sbindp)29010Sstevel@tonic-gate ibt_unbind_service(ibt_srv_hdl_t srv_hdl, ibt_sbind_hdl_t sbindp)
29020Sstevel@tonic-gate {
29030Sstevel@tonic-gate 	ib_svc_id_t	sid, end_sid;
29040Sstevel@tonic-gate 	ibt_status_t	rval;
29050Sstevel@tonic-gate 	ibcm_hca_info_t	*hcap;
29060Sstevel@tonic-gate 	ibcm_svc_bind_t	*sbp, **sbpp;
29070Sstevel@tonic-gate 
29080Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service(%p, %p)",
29090Sstevel@tonic-gate 	    srv_hdl, sbindp);
29100Sstevel@tonic-gate 
29110Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
29120Sstevel@tonic-gate 
29130Sstevel@tonic-gate 	/* If there is a service on hca, respective hcap cannot go away */
29140Sstevel@tonic-gate 	ASSERT(hcap != NULL);
29150Sstevel@tonic-gate 
29160Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
29170Sstevel@tonic-gate 
29180Sstevel@tonic-gate 	sbpp = &srv_hdl->svc_bind_list;
29190Sstevel@tonic-gate 	sbp = *sbpp;
29200Sstevel@tonic-gate 	while (sbp != NULL) {
29210Sstevel@tonic-gate 		if (sbp == sbindp) {
29220Sstevel@tonic-gate 			*sbpp = sbp->sbind_link;
29230Sstevel@tonic-gate 			break;
29240Sstevel@tonic-gate 		}
29250Sstevel@tonic-gate 		sbpp = &sbp->sbind_link;
29260Sstevel@tonic-gate 		sbp = *sbpp;
29270Sstevel@tonic-gate 	}
29280Sstevel@tonic-gate 	sid = srv_hdl->svc_id;
29290Sstevel@tonic-gate 	end_sid = srv_hdl->svc_id + srv_hdl->svc_num_sids - 1;
29300Sstevel@tonic-gate 	if (sbp != NULL)
29310Sstevel@tonic-gate 		while (sbp->sbind_rewrite_state == IBCM_REWRITE_BUSY)
29320Sstevel@tonic-gate 			cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
29330Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
29340Sstevel@tonic-gate 
29350Sstevel@tonic-gate 	if (sbp == NULL) {
29360Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29370Sstevel@tonic-gate 		    "service binding not found: srv_hdl %p, srv_bind %p",
29380Sstevel@tonic-gate 		    srv_hdl, sbindp);
29390Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
29400Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
29410Sstevel@tonic-gate 	}
29420Sstevel@tonic-gate 
29430Sstevel@tonic-gate 	if (sbindp->sbind_pkey != 0) {	/* Are there service records? */
29440Sstevel@tonic-gate 		ibtl_cm_hca_port_t	port;
29450Sstevel@tonic-gate 		sa_service_record_t	srv_rec;
29460Sstevel@tonic-gate 		ibmf_saa_handle_t	saa_handle;
29470Sstevel@tonic-gate 		ibt_status_t		status;
29480Sstevel@tonic-gate 
29490Sstevel@tonic-gate 		/* get the default SGID of the port */
29500Sstevel@tonic-gate 		if ((status = ibtl_cm_get_hca_port(sbindp->sbind_gid, 0, &port))
29510Sstevel@tonic-gate 		    != IBT_SUCCESS) {
29520Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29530Sstevel@tonic-gate 			    "ibtl_cm_get_hca_port failed: %d", status);
29540Sstevel@tonic-gate 			/* we're done, but there may be stale service records */
29550Sstevel@tonic-gate 			goto done;
29560Sstevel@tonic-gate 		}
29570Sstevel@tonic-gate 
29580Sstevel@tonic-gate 		saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
29590Sstevel@tonic-gate 		if (saa_handle == NULL) {
29600Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29610Sstevel@tonic-gate 			    "saa_handle is NULL");
29620Sstevel@tonic-gate 			/* we're done, but there may be stale service records */
29630Sstevel@tonic-gate 			goto done;
29640Sstevel@tonic-gate 		}
29650Sstevel@tonic-gate 
29660Sstevel@tonic-gate 		/* Fill in fields of srv_rec */
29670Sstevel@tonic-gate 		bzero(&srv_rec, sizeof (srv_rec));
29680Sstevel@tonic-gate 
29690Sstevel@tonic-gate 		srv_rec.ServiceP_Key = sbindp->sbind_pkey;
29700Sstevel@tonic-gate 		srv_rec.ServiceKey_hi = sbindp->sbind_key[0];
29710Sstevel@tonic-gate 		srv_rec.ServiceKey_lo = sbindp->sbind_key[1];
29720Sstevel@tonic-gate 		srv_rec.ServiceGID = sbindp->sbind_gid;
29730Sstevel@tonic-gate 		(void) strcpy((char *)srv_rec.ServiceName, sbindp->sbind_name);
29740Sstevel@tonic-gate 
29750Sstevel@tonic-gate 		while (sid <= end_sid) {
29760Sstevel@tonic-gate 
29770Sstevel@tonic-gate 			srv_rec.ServiceID = sid;
29780Sstevel@tonic-gate 			IBCM_DUMP_SERVICE_REC(&srv_rec);
29790Sstevel@tonic-gate 
29800Sstevel@tonic-gate 			rval = ibcm_write_service_record(saa_handle, &srv_rec,
29810Sstevel@tonic-gate 			    IBMF_SAA_DELETE);
29820Sstevel@tonic-gate 
29830Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibt_unbind_service: "
29840Sstevel@tonic-gate 			    "ibcm_write_service_record rval = %d, SID %llx",
29850Sstevel@tonic-gate 			    rval, sid);
29860Sstevel@tonic-gate 			if (rval != IBT_SUCCESS) {
29870Sstevel@tonic-gate 				/* this is not considered a reason to fail */
29880Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
29890Sstevel@tonic-gate 				    "ibcm_write_service_record fails %d, "
29900Sstevel@tonic-gate 				    "sid %llx", rval, sid);
29910Sstevel@tonic-gate 			}
29920Sstevel@tonic-gate 			sid++;
29930Sstevel@tonic-gate 		}
29940Sstevel@tonic-gate 	}
29950Sstevel@tonic-gate done:
29960Sstevel@tonic-gate 	ibcm_dec_hca_svc_cnt(hcap);
29970Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
29980Sstevel@tonic-gate 	kmem_free(sbindp, sizeof (*sbindp));
29990Sstevel@tonic-gate 
30000Sstevel@tonic-gate 	/* If this message isn't seen then ibt_unbind_service failed */
30010Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: done !!");
30020Sstevel@tonic-gate 
30030Sstevel@tonic-gate 	return (IBT_SUCCESS);
30040Sstevel@tonic-gate }
30050Sstevel@tonic-gate 
30060Sstevel@tonic-gate /*
30070Sstevel@tonic-gate  * Simply pull off each binding from the list and unbind it.
30080Sstevel@tonic-gate  * If any of the unbind calls fail, we fail.
30090Sstevel@tonic-gate  */
30100Sstevel@tonic-gate ibt_status_t
ibt_unbind_all_services(ibt_srv_hdl_t srv_hdl)30110Sstevel@tonic-gate ibt_unbind_all_services(ibt_srv_hdl_t srv_hdl)
30120Sstevel@tonic-gate {
30130Sstevel@tonic-gate 	ibt_status_t	status;
30140Sstevel@tonic-gate 	ibcm_svc_bind_t	*sbp;
30150Sstevel@tonic-gate 
30160Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
30170Sstevel@tonic-gate 	sbp = NULL;
30180Sstevel@tonic-gate 
30190Sstevel@tonic-gate 	/* this compare keeps the loop from being infinite */
30200Sstevel@tonic-gate 	while (sbp != srv_hdl->svc_bind_list) {
30210Sstevel@tonic-gate 		sbp = srv_hdl->svc_bind_list;
30220Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
30230Sstevel@tonic-gate 		status = ibt_unbind_service(srv_hdl, sbp);
30240Sstevel@tonic-gate 		if (status != IBT_SUCCESS)
30250Sstevel@tonic-gate 			return (status);
30260Sstevel@tonic-gate 		mutex_enter(&ibcm_svc_info_lock);
30270Sstevel@tonic-gate 		if (srv_hdl->svc_bind_list == NULL)
30280Sstevel@tonic-gate 			break;
30290Sstevel@tonic-gate 	}
30300Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
30310Sstevel@tonic-gate 	return (IBT_SUCCESS);
30320Sstevel@tonic-gate }
30330Sstevel@tonic-gate 
30340Sstevel@tonic-gate /*
30350Sstevel@tonic-gate  * ibt_deregister_service()
30360Sstevel@tonic-gate  *	Deregister a service with the IBCM
30370Sstevel@tonic-gate  *
30380Sstevel@tonic-gate  * INPUTS:
30390Sstevel@tonic-gate  *	ibt_hdl		The IBT client handle returned to the client
30400Sstevel@tonic-gate  *			on an ibt_attach() call.
30410Sstevel@tonic-gate  *
30420Sstevel@tonic-gate  *	srv_hdl		The address of a service identification handle, used
30430Sstevel@tonic-gate  *			to de-register a service.
30440Sstevel@tonic-gate  * RETURN VALUES:
30450Sstevel@tonic-gate  *	IBT_SUCCESS	on success (or respective failure on error)
30460Sstevel@tonic-gate  */
30470Sstevel@tonic-gate ibt_status_t
ibt_deregister_service(ibt_clnt_hdl_t ibt_hdl,ibt_srv_hdl_t srv_hdl)30480Sstevel@tonic-gate ibt_deregister_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_hdl_t srv_hdl)
30490Sstevel@tonic-gate {
30500Sstevel@tonic-gate 	ibcm_svc_info_t		*svcp;
30510Sstevel@tonic-gate 	ibcm_svc_lookup_t	svc;
30520Sstevel@tonic-gate 
30539349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(%p (%s), %p)",
30549349SShantkumar.Hiremath@Sun.COM 	    ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), srv_hdl);
30550Sstevel@tonic-gate 
30560Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
30570Sstevel@tonic-gate 
30580Sstevel@tonic-gate 	if (srv_hdl->svc_bind_list != NULL) {
30590Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service:"
30600Sstevel@tonic-gate 		    " srv_hdl %p still has bindings", srv_hdl);
30610Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
30620Sstevel@tonic-gate 		return (IBT_CM_SERVICE_BUSY);
30630Sstevel@tonic-gate 	}
30640Sstevel@tonic-gate 	svc.sid = srv_hdl->svc_id;
30650Sstevel@tonic-gate 	svc.num_sids = 1;
3066401Shiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_deregister_service: SID 0x%llX, numsids %d",
3067401Shiremath 	    srv_hdl->svc_id, srv_hdl->svc_num_sids);
3068401Shiremath 
30690Sstevel@tonic-gate #ifdef __lock_lint
30700Sstevel@tonic-gate 	ibcm_svc_compare(NULL, NULL);
30710Sstevel@tonic-gate #endif
30720Sstevel@tonic-gate 	svcp = avl_find(&ibcm_svc_avl_tree, &svc, NULL);
30730Sstevel@tonic-gate 	if (svcp != srv_hdl) {
30740Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
30750Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(): "
30760Sstevel@tonic-gate 		    "srv_hdl %p not found", srv_hdl);
30770Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
30780Sstevel@tonic-gate 	}
30790Sstevel@tonic-gate 	avl_remove(&ibcm_svc_avl_tree, svcp);
30800Sstevel@tonic-gate 
30810Sstevel@tonic-gate 	/* wait for active REQ/SREQ handling to be done */
30820Sstevel@tonic-gate 	svcp->svc_to_delete = 1;
30830Sstevel@tonic-gate 	while (svcp->svc_ref_cnt != 0)
30840Sstevel@tonic-gate 		cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
30850Sstevel@tonic-gate 
30860Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
30870Sstevel@tonic-gate 
30880Sstevel@tonic-gate 	if ((srv_hdl->svc_id & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL)
30890Sstevel@tonic-gate 		ibcm_free_local_sids(srv_hdl->svc_id, srv_hdl->svc_num_sids);
30900Sstevel@tonic-gate 
30910Sstevel@tonic-gate 	ibtl_cm_change_service_cnt(ibt_hdl, -srv_hdl->svc_num_sids);
30920Sstevel@tonic-gate 	kmem_free(srv_hdl, sizeof (*srv_hdl));
30930Sstevel@tonic-gate 
30940Sstevel@tonic-gate 	/* If this message isn't seen then ibt_deregister_service failed */
30950Sstevel@tonic-gate 	IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service: done !!");
30960Sstevel@tonic-gate 
30970Sstevel@tonic-gate 	return (IBT_SUCCESS);
30980Sstevel@tonic-gate }
30990Sstevel@tonic-gate 
31000Sstevel@tonic-gate ibcm_status_t
ibcm_ar_init(void)31010Sstevel@tonic-gate ibcm_ar_init(void)
31020Sstevel@tonic-gate {
31030Sstevel@tonic-gate 	ib_svc_id_t	sid = IBCM_DAPL_ATS_SID;
31040Sstevel@tonic-gate 	ibcm_svc_info_t *tmp_svcp;
31050Sstevel@tonic-gate 
31060Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_ar_init()");
31070Sstevel@tonic-gate 
31080Sstevel@tonic-gate 	/* remove this special SID from the pool of available SIDs */
31090Sstevel@tonic-gate 	if ((tmp_svcp = ibcm_create_svc_entry(sid, 1)) == NULL) {
31109349SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L3(cmlog, "ibcm_ar_init: "
31110Sstevel@tonic-gate 		    "DAPL ATS SID 0x%llx already registered", (longlong_t)sid);
31120Sstevel@tonic-gate 		return (IBCM_FAILURE);
31130Sstevel@tonic-gate 	}
31140Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
31150Sstevel@tonic-gate 	ibcm_ar_svcinfop = tmp_svcp;
31160Sstevel@tonic-gate 	ibcm_ar_list = NULL;	/* no address records registered yet */
31170Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
31180Sstevel@tonic-gate 	return (IBCM_SUCCESS);
31190Sstevel@tonic-gate }
31200Sstevel@tonic-gate 
31210Sstevel@tonic-gate ibcm_status_t
ibcm_ar_fini(void)31220Sstevel@tonic-gate ibcm_ar_fini(void)
31230Sstevel@tonic-gate {
31240Sstevel@tonic-gate 	ibcm_ar_t	*ar_list;
31250Sstevel@tonic-gate 	ibcm_svc_info_t	*tmp_svcp;
31260Sstevel@tonic-gate 
31270Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
31280Sstevel@tonic-gate 	ar_list = ibcm_ar_list;
31290Sstevel@tonic-gate 
31300Sstevel@tonic-gate 	if (ar_list == NULL &&
31310Sstevel@tonic-gate 	    avl_numnodes(&ibcm_svc_avl_tree) == 1 &&
31320Sstevel@tonic-gate 	    avl_first(&ibcm_svc_avl_tree) == ibcm_ar_svcinfop) {
31330Sstevel@tonic-gate 		avl_remove(&ibcm_svc_avl_tree, ibcm_ar_svcinfop);
31340Sstevel@tonic-gate 		tmp_svcp = ibcm_ar_svcinfop;
31350Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
31360Sstevel@tonic-gate 		kmem_free(tmp_svcp, sizeof (*ibcm_ar_svcinfop));
31370Sstevel@tonic-gate 		return (IBCM_SUCCESS);
31380Sstevel@tonic-gate 	}
31390Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
31400Sstevel@tonic-gate 	return (IBCM_FAILURE);
31410Sstevel@tonic-gate }
31420Sstevel@tonic-gate 
31430Sstevel@tonic-gate 
31440Sstevel@tonic-gate /*
31450Sstevel@tonic-gate  * Return to the caller:
31460Sstevel@tonic-gate  *	IBT_SUCCESS		Found a perfect match.
31470Sstevel@tonic-gate  *				*arpp is set to the record.
31480Sstevel@tonic-gate  *	IBT_INCONSISTENT_AR	Found a record that's inconsistent.
31490Sstevel@tonic-gate  *	IBT_AR_NOT_REGISTERED	Found no record with same GID/pkey and
31500Sstevel@tonic-gate  *				found no record with same data.
31510Sstevel@tonic-gate  */
31520Sstevel@tonic-gate static ibt_status_t
ibcm_search_ar(ibt_ar_t * arp,ibcm_ar_t ** arpp)31530Sstevel@tonic-gate ibcm_search_ar(ibt_ar_t *arp, ibcm_ar_t **arpp)
31540Sstevel@tonic-gate {
31550Sstevel@tonic-gate 	ibcm_ar_t	*tmp;
31560Sstevel@tonic-gate 	int		i;
31570Sstevel@tonic-gate 
31580Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
31590Sstevel@tonic-gate 	tmp = ibcm_ar_list;
31600Sstevel@tonic-gate 	while (tmp != NULL) {
31610Sstevel@tonic-gate 		if (tmp->ar.ar_gid.gid_prefix == arp->ar_gid.gid_prefix &&
31620Sstevel@tonic-gate 		    tmp->ar.ar_gid.gid_guid == arp->ar_gid.gid_guid &&
31630Sstevel@tonic-gate 		    tmp->ar.ar_pkey == arp->ar_pkey) {
31640Sstevel@tonic-gate 			for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++)
31650Sstevel@tonic-gate 				if (tmp->ar.ar_data[i] != arp->ar_data[i])
31660Sstevel@tonic-gate 					return (IBT_INCONSISTENT_AR);
31670Sstevel@tonic-gate 			*arpp = tmp;
31680Sstevel@tonic-gate 			return (IBT_SUCCESS);
31690Sstevel@tonic-gate 		} else {
31700Sstevel@tonic-gate 			/* if all the data bytes match, we have inconsistency */
31710Sstevel@tonic-gate 			for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++)
31720Sstevel@tonic-gate 				if (tmp->ar.ar_data[i] != arp->ar_data[i])
31730Sstevel@tonic-gate 					break;
31740Sstevel@tonic-gate 			if (i == IBCM_DAPL_ATS_NBYTES)
31750Sstevel@tonic-gate 				return (IBT_INCONSISTENT_AR);
31760Sstevel@tonic-gate 			/* try next address record */
31770Sstevel@tonic-gate 		}
31780Sstevel@tonic-gate 		tmp = tmp->ar_link;
31790Sstevel@tonic-gate 	}
31800Sstevel@tonic-gate 	return (IBT_AR_NOT_REGISTERED);
31810Sstevel@tonic-gate }
31820Sstevel@tonic-gate 
31830Sstevel@tonic-gate ibt_status_t
ibt_register_ar(ibt_clnt_hdl_t ibt_hdl,ibt_ar_t * arp)31840Sstevel@tonic-gate ibt_register_ar(ibt_clnt_hdl_t ibt_hdl, ibt_ar_t *arp)
31850Sstevel@tonic-gate {
31860Sstevel@tonic-gate 	ibcm_ar_t		*found;
31870Sstevel@tonic-gate 	ibcm_ar_t		*tmp;
31880Sstevel@tonic-gate 	ibt_status_t		status;
31890Sstevel@tonic-gate 	ibt_status_t		s1, s2;
31900Sstevel@tonic-gate 	char			*s;
31910Sstevel@tonic-gate 	ibcm_ar_ref_t		*hdlp;
31920Sstevel@tonic-gate 	ibcm_ar_t		*new;
31930Sstevel@tonic-gate 	ibcm_ar_t		**linkp;
31940Sstevel@tonic-gate 	ibtl_cm_hca_port_t	cm_port;
31950Sstevel@tonic-gate 	uint16_t		pkey_ix;
31960Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
31970Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
31980Sstevel@tonic-gate 	sa_service_record_t	*srv_recp;
31990Sstevel@tonic-gate 	uint64_t		gid_ored;
32000Sstevel@tonic-gate 
32019349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibt_register_ar: PKey 0x%X GID %llX:%llX",
32020Sstevel@tonic-gate 	    arp->ar_pkey, (longlong_t)arp->ar_gid.gid_prefix,
32030Sstevel@tonic-gate 	    (longlong_t)arp->ar_gid.gid_guid);
32040Sstevel@tonic-gate 
32050Sstevel@tonic-gate 	/*
32060Sstevel@tonic-gate 	 * If P_Key is 0, but GID is not, this query is invalid.
32070Sstevel@tonic-gate 	 * If GID is 0, but P_Key is not, this query is invalid.
32080Sstevel@tonic-gate 	 */
32090Sstevel@tonic-gate 	gid_ored = arp->ar_gid.gid_guid | arp->ar_gid.gid_prefix;
32100Sstevel@tonic-gate 	if ((arp->ar_pkey == 0 && gid_ored != 0ULL) ||
32110Sstevel@tonic-gate 	    (arp->ar_pkey != 0 && gid_ored == 0ULL)) {
32120Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
32130Sstevel@tonic-gate 		    "GID/P_Key is not valid");
32140Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
32150Sstevel@tonic-gate 	}
32160Sstevel@tonic-gate 
32170Sstevel@tonic-gate 	/* assume success, so these might be needed */
32180Sstevel@tonic-gate 	hdlp = kmem_alloc(sizeof (*hdlp), KM_SLEEP);
32192974Srm78299 	new = kmem_zalloc(sizeof (*new), KM_SLEEP);
32200Sstevel@tonic-gate 
32210Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
32220Sstevel@tonic-gate 	/* search for existing GID/pkey (there can be at most 1) */
32230Sstevel@tonic-gate 	status = ibcm_search_ar(arp, &found);
32240Sstevel@tonic-gate 	if (status == IBT_INCONSISTENT_AR) {
32250Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
32260Sstevel@tonic-gate 		kmem_free(new, sizeof (*new));
32270Sstevel@tonic-gate 		kmem_free(hdlp, sizeof (*hdlp));
32280Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
32290Sstevel@tonic-gate 		    "address record is inconsistent with a known one");
32300Sstevel@tonic-gate 		return (IBT_INCONSISTENT_AR);
32310Sstevel@tonic-gate 	} else if (status == IBT_SUCCESS) {
32320Sstevel@tonic-gate 		if (found->ar_flags == IBCM_AR_INITING) {
32330Sstevel@tonic-gate 			found->ar_waiters++;
32340Sstevel@tonic-gate 			cv_wait(&found->ar_cv, &ibcm_svc_info_lock);
32350Sstevel@tonic-gate 			found->ar_waiters--;
32360Sstevel@tonic-gate 		}
32370Sstevel@tonic-gate 		if (found->ar_flags == IBCM_AR_FAILED) {
32380Sstevel@tonic-gate 			if (found->ar_waiters == 0) {
32390Sstevel@tonic-gate 				cv_destroy(&found->ar_cv);
32400Sstevel@tonic-gate 				kmem_free(found, sizeof (*found));
32410Sstevel@tonic-gate 			}
32420Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
32430Sstevel@tonic-gate 			kmem_free(new, sizeof (*new));
32440Sstevel@tonic-gate 			kmem_free(hdlp, sizeof (*hdlp));
32450Sstevel@tonic-gate 			return (ibt_get_module_failure(IBT_FAILURE_IBCM, 0));
32460Sstevel@tonic-gate 		}
32470Sstevel@tonic-gate 		hdlp->ar_ibt_hdl = ibt_hdl;
32480Sstevel@tonic-gate 		hdlp->ar_ref_link = found->ar_ibt_hdl_list;
32490Sstevel@tonic-gate 		found->ar_ibt_hdl_list = hdlp;
32500Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
32510Sstevel@tonic-gate 		kmem_free(new, sizeof (*new));
32520Sstevel@tonic-gate 		ibtl_cm_change_service_cnt(ibt_hdl, 1);
32530Sstevel@tonic-gate 		return (IBT_SUCCESS);
32540Sstevel@tonic-gate 	} else {
32550Sstevel@tonic-gate 		ASSERT(status == IBT_AR_NOT_REGISTERED);
32560Sstevel@tonic-gate 	}
32570Sstevel@tonic-gate 	hdlp->ar_ref_link = NULL;
32580Sstevel@tonic-gate 	hdlp->ar_ibt_hdl = ibt_hdl;
32590Sstevel@tonic-gate 	new->ar_ibt_hdl_list = hdlp;
32600Sstevel@tonic-gate 	new->ar = *arp;
32610Sstevel@tonic-gate 	new->ar_flags = IBCM_AR_INITING;
32620Sstevel@tonic-gate 	new->ar_waiters = 0;
32630Sstevel@tonic-gate 	cv_init(&new->ar_cv, NULL, CV_DEFAULT, NULL);
32640Sstevel@tonic-gate 	new->ar_link = ibcm_ar_list;
32650Sstevel@tonic-gate 	ibcm_ar_list = new;
32660Sstevel@tonic-gate 
32670Sstevel@tonic-gate 	/* verify GID/pkey is valid for a local port, etc. */
32680Sstevel@tonic-gate 	hcap = NULL;
32690Sstevel@tonic-gate 	if ((s1 = ibtl_cm_get_hca_port(arp->ar_gid, 0, &cm_port))
32704703Shiremath 	    != IBT_SUCCESS ||
32710Sstevel@tonic-gate 	    (s2 = ibt_pkey2index_byguid(cm_port.hp_hca_guid, cm_port.hp_port,
32724703Shiremath 	    arp->ar_pkey, &pkey_ix)) != IBT_SUCCESS ||
32730Sstevel@tonic-gate 	    (hcap = ibcm_find_hca_entry(cm_port.hp_hca_guid)) == NULL) {
32740Sstevel@tonic-gate 		cv_destroy(&new->ar_cv);
32750Sstevel@tonic-gate 		ibcm_ar_list = new->ar_link;
32760Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
32770Sstevel@tonic-gate 		kmem_free(new, sizeof (*new));
32780Sstevel@tonic-gate 		kmem_free(hdlp, sizeof (*hdlp));
32790Sstevel@tonic-gate 		status = IBT_INVALID_PARAM;
32800Sstevel@tonic-gate 		if (s1 == IBT_HCA_PORT_NOT_ACTIVE) {
32810Sstevel@tonic-gate 			s = "PORT DOWN";
32820Sstevel@tonic-gate 			status = IBT_HCA_PORT_NOT_ACTIVE;
32830Sstevel@tonic-gate 		} else if (s1 != IBT_SUCCESS)
32840Sstevel@tonic-gate 			s = "GID not found";
32850Sstevel@tonic-gate 		else if (s2 != IBT_SUCCESS)
32860Sstevel@tonic-gate 			s = "PKEY not found";
32870Sstevel@tonic-gate 		else
32880Sstevel@tonic-gate 			s = "CM could not find its HCA entry";
32890Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: %s, status = %d",
32900Sstevel@tonic-gate 		    s, status);
32910Sstevel@tonic-gate 		return (status);
32920Sstevel@tonic-gate 	}
32930Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
32940Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, cm_port.hp_port);
32950Sstevel@tonic-gate 
32960Sstevel@tonic-gate 	/* create service record */
32970Sstevel@tonic-gate 	srv_recp = kmem_zalloc(sizeof (*srv_recp), KM_SLEEP);
32980Sstevel@tonic-gate 	srv_recp->ServiceLease = 0xFFFFFFFF;	/* infinite */
32990Sstevel@tonic-gate 	srv_recp->ServiceP_Key = arp->ar_pkey;
33000Sstevel@tonic-gate 	srv_recp->ServiceKey_hi = 0xDA410000ULL;	/* DAPL */
33010Sstevel@tonic-gate 	srv_recp->ServiceKey_lo = 0xA7500000ULL;	/* ATS */
33020Sstevel@tonic-gate 	(void) strcpy((char *)srv_recp->ServiceName, IBCM_DAPL_ATS_NAME);
33030Sstevel@tonic-gate 	srv_recp->ServiceGID = arp->ar_gid;
33040Sstevel@tonic-gate 	bcopy(arp->ar_data, srv_recp->ServiceData, IBCM_DAPL_ATS_NBYTES);
33050Sstevel@tonic-gate 	srv_recp->ServiceID = IBCM_DAPL_ATS_SID;
33060Sstevel@tonic-gate 
33070Sstevel@tonic-gate 	/* insert service record into the SA */
33080Sstevel@tonic-gate 
33090Sstevel@tonic-gate 	IBCM_DUMP_SERVICE_REC(srv_recp);
33100Sstevel@tonic-gate 
33110Sstevel@tonic-gate 	if (saa_handle != NULL)
33120Sstevel@tonic-gate 		status = ibcm_write_service_record(saa_handle, srv_recp,
33130Sstevel@tonic-gate 		    IBMF_SAA_UPDATE);
33140Sstevel@tonic-gate 	else
33150Sstevel@tonic-gate 		status = IBT_HCA_PORT_NOT_ACTIVE;
33160Sstevel@tonic-gate 
33170Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
33180Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: sa access fails %d, "
33190Sstevel@tonic-gate 		    "sid %llX", status, (longlong_t)srv_recp->ServiceID);
33200Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: FAILED for gid "
33210Sstevel@tonic-gate 		    "%llX:%llX pkey 0x%X", (longlong_t)arp->ar_gid.gid_prefix,
33220Sstevel@tonic-gate 		    (longlong_t)arp->ar_gid.gid_guid, arp->ar_pkey);
33230Sstevel@tonic-gate 
33240Sstevel@tonic-gate 		kmem_free(srv_recp, sizeof (*srv_recp));
33250Sstevel@tonic-gate 		kmem_free(hdlp, sizeof (*hdlp));
33260Sstevel@tonic-gate 
33270Sstevel@tonic-gate 		mutex_enter(&ibcm_svc_info_lock);
33280Sstevel@tonic-gate 		linkp = &ibcm_ar_list;
33290Sstevel@tonic-gate 		tmp = *linkp;
33300Sstevel@tonic-gate 		while (tmp != NULL) {
33310Sstevel@tonic-gate 			if (tmp == new) {
33320Sstevel@tonic-gate 				*linkp = new->ar_link;
33330Sstevel@tonic-gate 				break;
33340Sstevel@tonic-gate 			}
33350Sstevel@tonic-gate 			linkp = &tmp->ar_link;
33360Sstevel@tonic-gate 			tmp = *linkp;
33370Sstevel@tonic-gate 		}
33380Sstevel@tonic-gate 		if (new->ar_waiters > 0) {
33390Sstevel@tonic-gate 			new->ar_flags = IBCM_AR_FAILED;
33400Sstevel@tonic-gate 			cv_broadcast(&new->ar_cv);
33410Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
33420Sstevel@tonic-gate 		} else {
33430Sstevel@tonic-gate 			cv_destroy(&new->ar_cv);
33440Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
33450Sstevel@tonic-gate 			kmem_free(new, sizeof (*new));
33460Sstevel@tonic-gate 		}
33470Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
33480Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
33490Sstevel@tonic-gate 		    "IBMF_SAA failed to write address record");
33500Sstevel@tonic-gate 	} else {					/* SUCCESS */
33510Sstevel@tonic-gate 		uint8_t		*b;
33520Sstevel@tonic-gate 
33539349SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L3(cmlog, "ibt_register_ar: SUCCESS for gid "
33540Sstevel@tonic-gate 		    "%llx:%llx pkey %x", (longlong_t)arp->ar_gid.gid_prefix,
33550Sstevel@tonic-gate 		    (longlong_t)arp->ar_gid.gid_guid, arp->ar_pkey);
33560Sstevel@tonic-gate 		b = arp->ar_data;
33570Sstevel@tonic-gate 
33589349SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L3(cmlog, "ibt_register_ar:"
33590Sstevel@tonic-gate 		    " data %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
33600Sstevel@tonic-gate 		    b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9],
33610Sstevel@tonic-gate 		    b[10], b[11], b[12], b[13], b[14], b[15]);
33620Sstevel@tonic-gate 		mutex_enter(&ibcm_svc_info_lock);
33630Sstevel@tonic-gate 		new->ar_srv_recp = srv_recp;
33640Sstevel@tonic-gate 		new->ar_saa_handle = saa_handle;
33650Sstevel@tonic-gate 		new->ar_port = cm_port.hp_port;
33660Sstevel@tonic-gate 		new->ar_hcap = hcap;
33670Sstevel@tonic-gate 		new->ar_flags = IBCM_AR_SUCCESS;
33680Sstevel@tonic-gate 		if (new->ar_waiters > 0)
33690Sstevel@tonic-gate 			cv_broadcast(&new->ar_cv);
33700Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
33710Sstevel@tonic-gate 		ibtl_cm_change_service_cnt(ibt_hdl, 1);
33720Sstevel@tonic-gate 		/* do not call ibcm_dec_hca_acc_cnt(hcap) until deregister */
33730Sstevel@tonic-gate 	}
33740Sstevel@tonic-gate 	return (status);
33750Sstevel@tonic-gate }
33760Sstevel@tonic-gate 
33770Sstevel@tonic-gate ibt_status_t
ibt_deregister_ar(ibt_clnt_hdl_t ibt_hdl,ibt_ar_t * arp)33780Sstevel@tonic-gate ibt_deregister_ar(ibt_clnt_hdl_t ibt_hdl, ibt_ar_t *arp)
33790Sstevel@tonic-gate {
33800Sstevel@tonic-gate 	ibcm_ar_t		*found;
33810Sstevel@tonic-gate 	ibcm_ar_t		*tmp;
33820Sstevel@tonic-gate 	ibcm_ar_t		**linkp;
33830Sstevel@tonic-gate 	ibcm_ar_ref_t		*hdlp;
33840Sstevel@tonic-gate 	ibcm_ar_ref_t		**hdlpp;
33850Sstevel@tonic-gate 	ibt_status_t		status;
33860Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
33870Sstevel@tonic-gate 	sa_service_record_t	*srv_recp;
33880Sstevel@tonic-gate 	uint64_t		gid_ored;
33890Sstevel@tonic-gate 
33909349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibt_deregister_ar: pkey %x", arp->ar_pkey);
33919349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibt_deregister_ar: gid %llx:%llx",
33920Sstevel@tonic-gate 	    (longlong_t)arp->ar_gid.gid_prefix,
33930Sstevel@tonic-gate 	    (longlong_t)arp->ar_gid.gid_guid);
33940Sstevel@tonic-gate 
33950Sstevel@tonic-gate 	/*
33960Sstevel@tonic-gate 	 * If P_Key is 0, but GID is not, this query is invalid.
33970Sstevel@tonic-gate 	 * If GID is 0, but P_Key is not, this query is invalid.
33980Sstevel@tonic-gate 	 */
33990Sstevel@tonic-gate 	gid_ored = arp->ar_gid.gid_guid | arp->ar_gid.gid_prefix;
34000Sstevel@tonic-gate 	if ((arp->ar_pkey == 0 && gid_ored != 0ULL) ||
34010Sstevel@tonic-gate 	    (arp->ar_pkey != 0 && gid_ored == 0ULL)) {
34020Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34030Sstevel@tonic-gate 		    "GID/P_Key is not valid");
34040Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
34050Sstevel@tonic-gate 	}
34060Sstevel@tonic-gate 
34070Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
34080Sstevel@tonic-gate 	/* search for existing GID/pkey (there can be at most 1) */
34090Sstevel@tonic-gate 	status = ibcm_search_ar(arp, &found);
34100Sstevel@tonic-gate 	if (status == IBT_INCONSISTENT_AR || status == IBT_AR_NOT_REGISTERED) {
34110Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
34120Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34130Sstevel@tonic-gate 		    "address record not found");
34140Sstevel@tonic-gate 		return (IBT_AR_NOT_REGISTERED);
34150Sstevel@tonic-gate 	}
34160Sstevel@tonic-gate 	ASSERT(status == IBT_SUCCESS);
34170Sstevel@tonic-gate 
34180Sstevel@tonic-gate 	hdlpp = &found->ar_ibt_hdl_list;
34190Sstevel@tonic-gate 	hdlp = *hdlpp;
34200Sstevel@tonic-gate 	while (hdlp != NULL) {
34210Sstevel@tonic-gate 		if (hdlp->ar_ibt_hdl == ibt_hdl)
34220Sstevel@tonic-gate 			break;
34230Sstevel@tonic-gate 		hdlpp = &hdlp->ar_ref_link;
34240Sstevel@tonic-gate 		hdlp = *hdlpp;
34250Sstevel@tonic-gate 	}
34260Sstevel@tonic-gate 	if (hdlp == NULL) {	/* could not find ibt_hdl on list */
34270Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
34280Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34290Sstevel@tonic-gate 		    "address record found, but not for this client");
34300Sstevel@tonic-gate 		return (IBT_AR_NOT_REGISTERED);
34310Sstevel@tonic-gate 	}
34320Sstevel@tonic-gate 	*hdlpp = hdlp->ar_ref_link;	/* remove ref for this client */
34330Sstevel@tonic-gate 	if (found->ar_ibt_hdl_list == NULL && found->ar_waiters == 0) {
34340Sstevel@tonic-gate 		/* last entry was removed */
34350Sstevel@tonic-gate 		found->ar_flags = IBCM_AR_INITING; /* hold off register_ar */
34360Sstevel@tonic-gate 		saa_handle = found->ar_saa_handle;
34370Sstevel@tonic-gate 		srv_recp = found->ar_srv_recp;
34380Sstevel@tonic-gate 
34390Sstevel@tonic-gate 		/* wait if this service record is being rewritten */
34400Sstevel@tonic-gate 		while (found->ar_rewrite_state == IBCM_REWRITE_BUSY)
34410Sstevel@tonic-gate 			cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
34420Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
34430Sstevel@tonic-gate 
34440Sstevel@tonic-gate 		/* remove service record */
34450Sstevel@tonic-gate 		status = ibcm_write_service_record(saa_handle, srv_recp,
34460Sstevel@tonic-gate 		    IBMF_SAA_DELETE);
34470Sstevel@tonic-gate 		if (status != IBT_SUCCESS)
34480Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34490Sstevel@tonic-gate 			    "IBMF_SAA failed to delete address record");
34500Sstevel@tonic-gate 		mutex_enter(&ibcm_svc_info_lock);
34510Sstevel@tonic-gate 		if (found->ar_waiters == 0) {	/* still no waiters */
34520Sstevel@tonic-gate 			linkp = &ibcm_ar_list;
34530Sstevel@tonic-gate 			tmp = *linkp;
34540Sstevel@tonic-gate 			while (tmp != found) {
34550Sstevel@tonic-gate 				linkp = &tmp->ar_link;
34560Sstevel@tonic-gate 				tmp = *linkp;
34570Sstevel@tonic-gate 			}
34580Sstevel@tonic-gate 			*linkp = tmp->ar_link;
34590Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(found->ar_hcap);
34600Sstevel@tonic-gate 			kmem_free(srv_recp, sizeof (*srv_recp));
34610Sstevel@tonic-gate 			cv_destroy(&found->ar_cv);
34620Sstevel@tonic-gate 			kmem_free(found, sizeof (*found));
34630Sstevel@tonic-gate 		} else {
34640Sstevel@tonic-gate 			/* add service record back in for the waiters */
34650Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
34660Sstevel@tonic-gate 			status = ibcm_write_service_record(saa_handle, srv_recp,
34670Sstevel@tonic-gate 			    IBMF_SAA_UPDATE);
34680Sstevel@tonic-gate 			mutex_enter(&ibcm_svc_info_lock);
34690Sstevel@tonic-gate 			if (status == IBT_SUCCESS)
34700Sstevel@tonic-gate 				found->ar_flags = IBCM_AR_SUCCESS;
34710Sstevel@tonic-gate 			else {
34720Sstevel@tonic-gate 				found->ar_flags = IBCM_AR_FAILED;
34730Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
34740Sstevel@tonic-gate 				    "IBMF_SAA failed to write address record");
34750Sstevel@tonic-gate 			}
34760Sstevel@tonic-gate 			cv_broadcast(&found->ar_cv);
34770Sstevel@tonic-gate 		}
34780Sstevel@tonic-gate 	}
34790Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
34800Sstevel@tonic-gate 	kmem_free(hdlp, sizeof (*hdlp));
34810Sstevel@tonic-gate 	ibtl_cm_change_service_cnt(ibt_hdl, -1);
34820Sstevel@tonic-gate 	return (status);
34830Sstevel@tonic-gate }
34840Sstevel@tonic-gate 
34850Sstevel@tonic-gate ibt_status_t
ibt_query_ar(ib_gid_t * sgid,ibt_ar_t * queryp,ibt_ar_t * resultp)34860Sstevel@tonic-gate ibt_query_ar(ib_gid_t *sgid, ibt_ar_t *queryp, ibt_ar_t *resultp)
34870Sstevel@tonic-gate {
34880Sstevel@tonic-gate 	sa_service_record_t	svcrec_req;
34890Sstevel@tonic-gate 	sa_service_record_t	*svcrec_resp;
34900Sstevel@tonic-gate 	void			*results_p;
34910Sstevel@tonic-gate 	uint64_t		component_mask = 0;
34920Sstevel@tonic-gate 	uint64_t		gid_ored;
34930Sstevel@tonic-gate 	size_t			length;
34940Sstevel@tonic-gate 	int			num_rec;
34950Sstevel@tonic-gate 	int			i;
34960Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
34970Sstevel@tonic-gate 	ibt_status_t		retval;
34980Sstevel@tonic-gate 	ibtl_cm_hca_port_t	cm_port;
34990Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
35000Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
35010Sstevel@tonic-gate 
35020Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar(%p, %p)", queryp, resultp);
35030Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: sgid %llx:%llx",
35040Sstevel@tonic-gate 	    (longlong_t)sgid->gid_prefix, (longlong_t)sgid->gid_guid);
35050Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: query_pkey %x", queryp->ar_pkey);
35060Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: query_gid %llx:%llx",
35070Sstevel@tonic-gate 	    (longlong_t)queryp->ar_gid.gid_prefix,
35080Sstevel@tonic-gate 	    (longlong_t)queryp->ar_gid.gid_guid);
35090Sstevel@tonic-gate 
35100Sstevel@tonic-gate 	/*
35110Sstevel@tonic-gate 	 * If P_Key is 0, but GID is not, this query is invalid.
35120Sstevel@tonic-gate 	 * If GID is 0, but P_Key is not, this query is invalid.
35130Sstevel@tonic-gate 	 */
35140Sstevel@tonic-gate 	gid_ored = queryp->ar_gid.gid_guid | queryp->ar_gid.gid_prefix;
35150Sstevel@tonic-gate 	if ((queryp->ar_pkey == 0 && gid_ored != 0ULL) ||
35160Sstevel@tonic-gate 	    (queryp->ar_pkey != 0 && gid_ored == 0ULL)) {
35170Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: GID/P_Key is not valid");
35180Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
35190Sstevel@tonic-gate 	}
35200Sstevel@tonic-gate 
35210Sstevel@tonic-gate 	hcap = NULL;
35220Sstevel@tonic-gate 	if (ibtl_cm_get_hca_port(*sgid, 0, &cm_port) != IBT_SUCCESS ||
35230Sstevel@tonic-gate 	    (hcap = ibcm_find_hca_entry(cm_port.hp_hca_guid)) == NULL ||
35240Sstevel@tonic-gate 	    (saa_handle = ibcm_get_saa_handle(hcap, cm_port.hp_port)) == NULL) {
35250Sstevel@tonic-gate 		if (hcap != NULL)
35260Sstevel@tonic-gate 			ibcm_dec_hca_acc_cnt(hcap);
35270Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: sgid is not valid");
35280Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
35290Sstevel@tonic-gate 	}
35300Sstevel@tonic-gate 
35310Sstevel@tonic-gate 	bzero(&svcrec_req, sizeof (svcrec_req));
35320Sstevel@tonic-gate 
35330Sstevel@tonic-gate 	/* Is GID/P_Key Specified. */
35340Sstevel@tonic-gate 	if (queryp->ar_pkey != 0) {	/* GID is non-zero from check above */
35350Sstevel@tonic-gate 		svcrec_req.ServiceP_Key = queryp->ar_pkey;
35360Sstevel@tonic-gate 		component_mask |= SA_SR_COMPMASK_PKEY;
35370Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: P_Key %X",
35380Sstevel@tonic-gate 		    queryp->ar_pkey);
35390Sstevel@tonic-gate 		svcrec_req.ServiceGID = queryp->ar_gid;
35400Sstevel@tonic-gate 		component_mask |= SA_SR_COMPMASK_GID;
35410Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: GID %llX:%llX",
35420Sstevel@tonic-gate 		    (longlong_t)queryp->ar_gid.gid_prefix,
35430Sstevel@tonic-gate 		    (longlong_t)queryp->ar_gid.gid_guid);
35440Sstevel@tonic-gate 	}
35450Sstevel@tonic-gate 
35460Sstevel@tonic-gate 	/* Is ServiceData Specified. */
35470Sstevel@tonic-gate 	for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++) {
35480Sstevel@tonic-gate 		if (queryp->ar_data[i] != 0) {
35490Sstevel@tonic-gate 			bcopy(queryp->ar_data, svcrec_req.ServiceData,
35500Sstevel@tonic-gate 			    IBCM_DAPL_ATS_NBYTES);
35510Sstevel@tonic-gate 			component_mask |= 0xFFFF << 7;	/* all 16 Data8 */
35520Sstevel@tonic-gate 							/* components */
35530Sstevel@tonic-gate 			break;
35540Sstevel@tonic-gate 		}
35550Sstevel@tonic-gate 	}
35560Sstevel@tonic-gate 
35570Sstevel@tonic-gate 	/* Service Name */
35580Sstevel@tonic-gate 	(void) strcpy((char *)svcrec_req.ServiceName, IBCM_DAPL_ATS_NAME);
35590Sstevel@tonic-gate 	component_mask |= SA_SR_COMPMASK_NAME;
35600Sstevel@tonic-gate 
35610Sstevel@tonic-gate 	svcrec_req.ServiceID = IBCM_DAPL_ATS_SID;
35620Sstevel@tonic-gate 	component_mask |= SA_SR_COMPMASK_ID;
35630Sstevel@tonic-gate 
35640Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
35650Sstevel@tonic-gate 	    "Perform SA Access: Mask: 0x%X", component_mask);
35660Sstevel@tonic-gate 
35670Sstevel@tonic-gate 	/*
35680Sstevel@tonic-gate 	 * Call in SA Access retrieve routine to get Service Records.
35690Sstevel@tonic-gate 	 *
35700Sstevel@tonic-gate 	 * SA Access framework allocated memory for the "results_p".
35710Sstevel@tonic-gate 	 * Make sure to deallocate once we are done with the results_p.
35720Sstevel@tonic-gate 	 * The size of the buffer allocated will be as returned in
35730Sstevel@tonic-gate 	 * "length" field.
35740Sstevel@tonic-gate 	 */
35750Sstevel@tonic-gate 	access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
35760Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
35770Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
35780Sstevel@tonic-gate 	access_args.sq_template = &svcrec_req;
35790Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_service_record_t);
35800Sstevel@tonic-gate 	access_args.sq_callback = NULL;
35810Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
35820Sstevel@tonic-gate 
35830Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
35840Sstevel@tonic-gate 	    &results_p);
35850Sstevel@tonic-gate 
35860Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
35870Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
35880Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: SA Access Failed");
35890Sstevel@tonic-gate 		return (retval);
35900Sstevel@tonic-gate 	}
35910Sstevel@tonic-gate 
35920Sstevel@tonic-gate 	num_rec = length / sizeof (sa_service_record_t);
35930Sstevel@tonic-gate 
35940Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
35950Sstevel@tonic-gate 	    "Found %d Service Records.", num_rec);
35960Sstevel@tonic-gate 
35970Sstevel@tonic-gate 	/* Validate the returned number of records. */
35980Sstevel@tonic-gate 	if ((results_p != NULL) && (num_rec > 0)) {
35990Sstevel@tonic-gate 		uint8_t		*b;
36000Sstevel@tonic-gate 
36010Sstevel@tonic-gate 		/* Just return info from the first service record. */
36020Sstevel@tonic-gate 		svcrec_resp = (sa_service_record_t *)results_p;
36030Sstevel@tonic-gate 
36040Sstevel@tonic-gate 		/* The Service GID and Service ID */
36050Sstevel@tonic-gate 		resultp->ar_gid = svcrec_resp->ServiceGID;
36060Sstevel@tonic-gate 		resultp->ar_pkey = svcrec_resp->ServiceP_Key;
36070Sstevel@tonic-gate 		bcopy(svcrec_resp->ServiceData,
36080Sstevel@tonic-gate 		    resultp->ar_data, IBCM_DAPL_ATS_NBYTES);
36090Sstevel@tonic-gate 
36109349SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
36110Sstevel@tonic-gate 		    "Found: pkey %x dgid %llX:%llX", resultp->ar_pkey,
36120Sstevel@tonic-gate 		    (longlong_t)resultp->ar_gid.gid_prefix,
36130Sstevel@tonic-gate 		    (longlong_t)resultp->ar_gid.gid_guid);
36140Sstevel@tonic-gate 		b = resultp->ar_data;
36159349SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar:"
36160Sstevel@tonic-gate 		    " data %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
36170Sstevel@tonic-gate 		    b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9],
36180Sstevel@tonic-gate 		    b[10], b[11], b[12], b[13], b[14], b[15]);
36190Sstevel@tonic-gate 
36200Sstevel@tonic-gate 		/* Deallocate the memory for results_p. */
36210Sstevel@tonic-gate 		kmem_free(results_p, length);
36220Sstevel@tonic-gate 		if (num_rec > 1)
36230Sstevel@tonic-gate 			retval = IBT_MULTIPLE_AR;
36240Sstevel@tonic-gate 		else
36250Sstevel@tonic-gate 			retval = IBT_SUCCESS;
36260Sstevel@tonic-gate 	} else {
36270Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: "
36280Sstevel@tonic-gate 		    "ibmf_sa_access found 0 matching records");
36290Sstevel@tonic-gate 		retval = IBT_AR_NOT_REGISTERED;
36300Sstevel@tonic-gate 	}
36310Sstevel@tonic-gate 	return (retval);
36320Sstevel@tonic-gate }
36330Sstevel@tonic-gate 
36340Sstevel@tonic-gate /* mark all ATS service records associated with the port */
36350Sstevel@tonic-gate static void
ibcm_mark_ar(ib_guid_t hca_guid,uint8_t port)36360Sstevel@tonic-gate ibcm_mark_ar(ib_guid_t hca_guid, uint8_t port)
36370Sstevel@tonic-gate {
36380Sstevel@tonic-gate 	ibcm_ar_t	*tmp;
36390Sstevel@tonic-gate 
36400Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
36410Sstevel@tonic-gate 	for (tmp = ibcm_ar_list; tmp != NULL; tmp = tmp->ar_link) {
36425724Sagiri 		if (tmp->ar_hcap == NULL)
36435724Sagiri 			continue;
36440Sstevel@tonic-gate 		if (tmp->ar_hcap->hca_guid == hca_guid &&
36450Sstevel@tonic-gate 		    tmp->ar_port == port) {
36460Sstevel@tonic-gate 			/* even if it's busy, we mark it for rewrite */
36470Sstevel@tonic-gate 			tmp->ar_rewrite_state = IBCM_REWRITE_NEEDED;
36480Sstevel@tonic-gate 		}
36490Sstevel@tonic-gate 	}
36500Sstevel@tonic-gate }
36510Sstevel@tonic-gate 
36520Sstevel@tonic-gate /* rewrite all ATS service records */
36530Sstevel@tonic-gate static int
ibcm_rewrite_ar(void)36540Sstevel@tonic-gate ibcm_rewrite_ar(void)
36550Sstevel@tonic-gate {
36560Sstevel@tonic-gate 	ibcm_ar_t		*tmp;
36570Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
36580Sstevel@tonic-gate 	sa_service_record_t	*srv_recp;
36590Sstevel@tonic-gate 	ibt_status_t		rval;
36600Sstevel@tonic-gate 	int			did_something = 0;
36610Sstevel@tonic-gate 
36620Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
36630Sstevel@tonic-gate check_for_work:
36640Sstevel@tonic-gate 	for (tmp = ibcm_ar_list; tmp != NULL; tmp = tmp->ar_link) {
36650Sstevel@tonic-gate 		if (tmp->ar_rewrite_state == IBCM_REWRITE_NEEDED) {
36660Sstevel@tonic-gate 			tmp->ar_rewrite_state = IBCM_REWRITE_BUSY;
36670Sstevel@tonic-gate 			saa_handle = tmp->ar_saa_handle;
36680Sstevel@tonic-gate 			srv_recp = tmp->ar_srv_recp;
36690Sstevel@tonic-gate 			mutex_exit(&ibcm_svc_info_lock);
36700Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibcm_rewrite_ar: "
36710Sstevel@tonic-gate 			    "rewriting ar @ %p", tmp);
36720Sstevel@tonic-gate 			did_something = 1;
36730Sstevel@tonic-gate 			rval = ibcm_write_service_record(saa_handle, srv_recp,
36740Sstevel@tonic-gate 			    IBMF_SAA_UPDATE);
36750Sstevel@tonic-gate 			if (rval != IBT_SUCCESS)
36760Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_ar: "
36770Sstevel@tonic-gate 				    "ibcm_write_service_record failed: "
36780Sstevel@tonic-gate 				    "status = %d", rval);
36790Sstevel@tonic-gate 			mutex_enter(&ibcm_svc_info_lock);
36800Sstevel@tonic-gate 			/* if it got marked again, then we want to rewrite */
36810Sstevel@tonic-gate 			if (tmp->ar_rewrite_state == IBCM_REWRITE_BUSY)
36820Sstevel@tonic-gate 				tmp->ar_rewrite_state = IBCM_REWRITE_IDLE;
36830Sstevel@tonic-gate 			/* in case there was a waiter... */
36840Sstevel@tonic-gate 			cv_broadcast(&ibcm_svc_info_cv);
36850Sstevel@tonic-gate 			goto check_for_work;
36860Sstevel@tonic-gate 		}
36870Sstevel@tonic-gate 	}
36880Sstevel@tonic-gate 	return (did_something);
36890Sstevel@tonic-gate }
36900Sstevel@tonic-gate 
36910Sstevel@tonic-gate static void
ibcm_rewrite_svc_record(ibcm_svc_info_t * srv_hdl,ibcm_svc_bind_t * sbindp)36920Sstevel@tonic-gate ibcm_rewrite_svc_record(ibcm_svc_info_t *srv_hdl, ibcm_svc_bind_t *sbindp)
36930Sstevel@tonic-gate {
36940Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
36950Sstevel@tonic-gate 	ib_svc_id_t		sid, start_sid, end_sid;
36960Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
36970Sstevel@tonic-gate 	sa_service_record_t	srv_rec;
36980Sstevel@tonic-gate 	ibt_status_t		rval;
36990Sstevel@tonic-gate 
37000Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
37010Sstevel@tonic-gate 	if (hcap == NULL) {
37020Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record: "
37030Sstevel@tonic-gate 		    "NO HCA found for HCA GUID %llX", sbindp->sbind_hcaguid);
37040Sstevel@tonic-gate 		return;
37050Sstevel@tonic-gate 	}
37060Sstevel@tonic-gate 
37070Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, sbindp->sbind_port);
37080Sstevel@tonic-gate 	if (saa_handle == NULL) {
37090Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record: "
37100Sstevel@tonic-gate 		    "saa_handle is NULL");
37110Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
37120Sstevel@tonic-gate 		return;
37130Sstevel@tonic-gate 	}
37140Sstevel@tonic-gate 
37150Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_rewrite_svc_record: "
37160Sstevel@tonic-gate 	    "rewriting svc '%s', port_guid = %llX", sbindp->sbind_name,
37170Sstevel@tonic-gate 	    sbindp->sbind_gid.gid_guid);
37180Sstevel@tonic-gate 
37190Sstevel@tonic-gate 	bzero(&srv_rec, sizeof (srv_rec));
37200Sstevel@tonic-gate 
37210Sstevel@tonic-gate 	srv_rec.ServiceLease = sbindp->sbind_lease;
37220Sstevel@tonic-gate 	srv_rec.ServiceP_Key = sbindp->sbind_pkey;
37230Sstevel@tonic-gate 	srv_rec.ServiceKey_hi = sbindp->sbind_key[0];
37240Sstevel@tonic-gate 	srv_rec.ServiceKey_lo = sbindp->sbind_key[1];
37250Sstevel@tonic-gate 	(void) strcpy((char *)srv_rec.ServiceName, sbindp->sbind_name);
37260Sstevel@tonic-gate 	srv_rec.ServiceGID = sbindp->sbind_gid;
37270Sstevel@tonic-gate 
37280Sstevel@tonic-gate 	bcopy(sbindp->sbind_data, srv_rec.ServiceData, IB_SVC_DATA_LEN);
37290Sstevel@tonic-gate 
37300Sstevel@tonic-gate 	/* insert srv record into the SA */
37310Sstevel@tonic-gate 	start_sid = srv_hdl->svc_id;
37320Sstevel@tonic-gate 	end_sid = start_sid + srv_hdl->svc_num_sids - 1;
37330Sstevel@tonic-gate 	for (sid = start_sid; sid <= end_sid; sid++) {
37340Sstevel@tonic-gate 		srv_rec.ServiceID = sid;
37350Sstevel@tonic-gate 
37360Sstevel@tonic-gate 		rval = ibcm_write_service_record(saa_handle, &srv_rec,
37370Sstevel@tonic-gate 		    IBMF_SAA_UPDATE);
37380Sstevel@tonic-gate 
37390Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibcm_rewrite_svc_record: "
37400Sstevel@tonic-gate 		    "ibcm_write_service_record, SvcId = %llX, "
37410Sstevel@tonic-gate 		    "rval = %d", (longlong_t)sid, rval);
37420Sstevel@tonic-gate 		if (rval != IBT_SUCCESS) {
37430Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record:"
37440Sstevel@tonic-gate 			    " ibcm_write_service_record fails %d sid %llX",
37450Sstevel@tonic-gate 			    rval, (longlong_t)sid);
37460Sstevel@tonic-gate 		}
37470Sstevel@tonic-gate 	}
37480Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
37490Sstevel@tonic-gate }
37500Sstevel@tonic-gate 
37510Sstevel@tonic-gate /*
37520Sstevel@tonic-gate  * Task to mark all service records as needing to be rewritten to the SM/SA.
37530Sstevel@tonic-gate  * This task does not return until all of them have been rewritten.
37540Sstevel@tonic-gate  */
37550Sstevel@tonic-gate void
ibcm_service_record_rewrite_task(void * arg)37560Sstevel@tonic-gate ibcm_service_record_rewrite_task(void *arg)
37570Sstevel@tonic-gate {
37580Sstevel@tonic-gate 	ibcm_port_up_t	*pup = (ibcm_port_up_t *)arg;
37590Sstevel@tonic-gate 	ib_guid_t	hca_guid = pup->pup_hca_guid;
37600Sstevel@tonic-gate 	uint8_t		port = pup->pup_port;
37610Sstevel@tonic-gate 	ibcm_svc_info_t	*svcp;
37620Sstevel@tonic-gate 	ibcm_svc_bind_t	*sbp;
37630Sstevel@tonic-gate 	avl_tree_t	*avl_tree = &ibcm_svc_avl_tree;
37640Sstevel@tonic-gate 	static int	task_is_running = 0;
37650Sstevel@tonic-gate 
37669349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibcm_service_record_rewrite_task STARTED "
37670Sstevel@tonic-gate 	    "for hca_guid %llX, port %d", hca_guid, port);
37680Sstevel@tonic-gate 
37690Sstevel@tonic-gate 	mutex_enter(&ibcm_svc_info_lock);
37700Sstevel@tonic-gate 	ibcm_mark_ar(hca_guid, port);
37710Sstevel@tonic-gate 	for (svcp = avl_first(avl_tree); svcp != NULL;
37720Sstevel@tonic-gate 	    svcp = avl_walk(avl_tree, svcp, AVL_AFTER)) {
37730Sstevel@tonic-gate 		sbp = svcp->svc_bind_list;
37740Sstevel@tonic-gate 		while (sbp != NULL) {
37750Sstevel@tonic-gate 			if (sbp->sbind_pkey != 0 &&
37760Sstevel@tonic-gate 			    sbp->sbind_port == port &&
37770Sstevel@tonic-gate 			    sbp->sbind_hcaguid == hca_guid) {
37780Sstevel@tonic-gate 				/* even if it's busy, we mark it for rewrite */
37790Sstevel@tonic-gate 				sbp->sbind_rewrite_state = IBCM_REWRITE_NEEDED;
37800Sstevel@tonic-gate 			}
37810Sstevel@tonic-gate 			sbp = sbp->sbind_link;
37820Sstevel@tonic-gate 		}
37830Sstevel@tonic-gate 	}
37840Sstevel@tonic-gate 	if (task_is_running) {
37850Sstevel@tonic-gate 		/* let the other task thread finish the work */
37860Sstevel@tonic-gate 		mutex_exit(&ibcm_svc_info_lock);
37870Sstevel@tonic-gate 		return;
37880Sstevel@tonic-gate 	}
37890Sstevel@tonic-gate 	task_is_running = 1;
37900Sstevel@tonic-gate 
37910Sstevel@tonic-gate 	(void) ibcm_rewrite_ar();
37920Sstevel@tonic-gate 
37930Sstevel@tonic-gate check_for_work:
37940Sstevel@tonic-gate 	for (svcp = avl_first(avl_tree); svcp != NULL;
37950Sstevel@tonic-gate 	    svcp = avl_walk(avl_tree, svcp, AVL_AFTER)) {
37960Sstevel@tonic-gate 		sbp = svcp->svc_bind_list;
37970Sstevel@tonic-gate 		while (sbp != NULL) {
37980Sstevel@tonic-gate 			if (sbp->sbind_rewrite_state == IBCM_REWRITE_NEEDED) {
37990Sstevel@tonic-gate 				sbp->sbind_rewrite_state = IBCM_REWRITE_BUSY;
38000Sstevel@tonic-gate 				mutex_exit(&ibcm_svc_info_lock);
38010Sstevel@tonic-gate 				ibcm_rewrite_svc_record(svcp, sbp);
38020Sstevel@tonic-gate 				mutex_enter(&ibcm_svc_info_lock);
38030Sstevel@tonic-gate 				/* if it got marked again, we want to rewrite */
38040Sstevel@tonic-gate 				if (sbp->sbind_rewrite_state ==
38050Sstevel@tonic-gate 				    IBCM_REWRITE_BUSY)
38060Sstevel@tonic-gate 					sbp->sbind_rewrite_state =
38070Sstevel@tonic-gate 					    IBCM_REWRITE_IDLE;
38080Sstevel@tonic-gate 				/* in case there was a waiter... */
38090Sstevel@tonic-gate 				cv_broadcast(&ibcm_svc_info_cv);
38100Sstevel@tonic-gate 				goto check_for_work;
38110Sstevel@tonic-gate 			}
38120Sstevel@tonic-gate 			sbp = sbp->sbind_link;
38130Sstevel@tonic-gate 		}
38140Sstevel@tonic-gate 	}
38150Sstevel@tonic-gate 	/*
38160Sstevel@tonic-gate 	 * If there were no service records to write, and we failed to
38170Sstevel@tonic-gate 	 * have to rewrite any more ATS service records, then we're done.
38180Sstevel@tonic-gate 	 */
38190Sstevel@tonic-gate 	if (ibcm_rewrite_ar() != 0)
38200Sstevel@tonic-gate 		goto check_for_work;
38210Sstevel@tonic-gate 	task_is_running = 0;
38220Sstevel@tonic-gate 	mutex_exit(&ibcm_svc_info_lock);
38230Sstevel@tonic-gate 
38249349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibcm_service_record_rewrite_task DONE");
38250Sstevel@tonic-gate 	kmem_free(pup, sizeof (ibcm_port_up_t));
38260Sstevel@tonic-gate }
38270Sstevel@tonic-gate 
38289913SShantkumar.Hiremath@Sun.COM ibt_status_t
ibt_ofuvcm_get_req_data(void * session_id,ibt_ofuvcm_req_data_t * req_data)38299913SShantkumar.Hiremath@Sun.COM ibt_ofuvcm_get_req_data(void *session_id, ibt_ofuvcm_req_data_t *req_data)
38309913SShantkumar.Hiremath@Sun.COM {
38319913SShantkumar.Hiremath@Sun.COM 	ibcm_state_data_t 	*statep = (ibcm_state_data_t *)session_id;
38329913SShantkumar.Hiremath@Sun.COM 	ibcm_req_msg_t 		*req_msgp;
38339913SShantkumar.Hiremath@Sun.COM 
38349913SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibt_get_ofuvcm_req_data: session_id %p",
38359913SShantkumar.Hiremath@Sun.COM 	    session_id);
38369913SShantkumar.Hiremath@Sun.COM 	mutex_enter(&statep->state_mutex);
38379913SShantkumar.Hiremath@Sun.COM 	if ((statep->state != IBCM_STATE_REQ_RCVD) &&
38389913SShantkumar.Hiremath@Sun.COM 	    (statep->state != IBCM_STATE_MRA_SENT)) {
38399913SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L2(cmlog, "ibt_get_ofuvcm_req_data: Invalid "
38409913SShantkumar.Hiremath@Sun.COM 		    "State %x", statep->state);
38419913SShantkumar.Hiremath@Sun.COM 		mutex_exit(&statep->state_mutex);
38429913SShantkumar.Hiremath@Sun.COM 		return (IBT_CHAN_STATE_INVALID);
38439913SShantkumar.Hiremath@Sun.COM 	}
38449913SShantkumar.Hiremath@Sun.COM 	if (statep->mode == IBCM_ACTIVE_MODE) {
38459913SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L2(cmlog, "ibt_get_ofuvcm_req_data: Active mode "
38469913SShantkumar.Hiremath@Sun.COM 		    "not supported");
38479913SShantkumar.Hiremath@Sun.COM 		mutex_exit(&statep->state_mutex);
38489913SShantkumar.Hiremath@Sun.COM 		return (IBT_INVALID_PARAM);
38499913SShantkumar.Hiremath@Sun.COM 	}
38509913SShantkumar.Hiremath@Sun.COM 	ASSERT(statep->req_msgp);
38519913SShantkumar.Hiremath@Sun.COM 
38529913SShantkumar.Hiremath@Sun.COM 	/*
38539913SShantkumar.Hiremath@Sun.COM 	 * Fill in the additional req message values reqired for
38549913SShantkumar.Hiremath@Sun.COM 	 * RTR transition.
38559913SShantkumar.Hiremath@Sun.COM 	 * Should the PSN be same as the active side??
38569913SShantkumar.Hiremath@Sun.COM 	 */
38579913SShantkumar.Hiremath@Sun.COM 	req_msgp = (ibcm_req_msg_t *)statep->req_msgp;
38589913SShantkumar.Hiremath@Sun.COM 	req_data->req_rnr_nak_time = ibcm_default_rnr_nak_time;
38599913SShantkumar.Hiremath@Sun.COM 	req_data->req_path_mtu = req_msgp->req_mtu_plus >> 4;
38609913SShantkumar.Hiremath@Sun.COM 	req_data->req_rq_psn = b2h32(req_msgp->req_starting_psn_plus) >> 8;
38619913SShantkumar.Hiremath@Sun.COM 	mutex_exit(&statep->state_mutex);
38629913SShantkumar.Hiremath@Sun.COM 	return (IBT_SUCCESS);
38639913SShantkumar.Hiremath@Sun.COM }
38649913SShantkumar.Hiremath@Sun.COM 
38659913SShantkumar.Hiremath@Sun.COM 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)38669913SShantkumar.Hiremath@Sun.COM ibt_ofuvcm_proceed(ibt_cm_event_type_t event, void *session_id,
38679913SShantkumar.Hiremath@Sun.COM     ibt_cm_status_t status, ibt_cm_proceed_reply_t *cm_event_data,
38689913SShantkumar.Hiremath@Sun.COM     void *priv_data, ibt_priv_data_len_t priv_data_len)
38699913SShantkumar.Hiremath@Sun.COM {
38709913SShantkumar.Hiremath@Sun.COM 	ibcm_state_data_t *statep = (ibcm_state_data_t *)session_id;
38719913SShantkumar.Hiremath@Sun.COM 	ibt_status_t		ret;
38729913SShantkumar.Hiremath@Sun.COM 
38739913SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibt_ofuvcm_proceed chan 0x%p event %x "
38749913SShantkumar.Hiremath@Sun.COM 	    "status %x session_id %p", statep->channel, event, status,
38759913SShantkumar.Hiremath@Sun.COM 	    session_id);
38769913SShantkumar.Hiremath@Sun.COM 
38779913SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L5(cmlog, "ibt_ofuvcm_proceed chan 0x%p "
38789913SShantkumar.Hiremath@Sun.COM 	    "cm_event_data %p, priv_data %p priv_data_len %x",
38799913SShantkumar.Hiremath@Sun.COM 	    statep->channel, cm_event_data, priv_data, priv_data_len);
38809913SShantkumar.Hiremath@Sun.COM 
38819913SShantkumar.Hiremath@Sun.COM 	/* validate session_id and status */
38829913SShantkumar.Hiremath@Sun.COM 	if ((statep == NULL) || (status == IBT_CM_DEFER)) {
38839913SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L2(cmlog, "ibt_ofuvcm_proceed : Invalid Args");
38849913SShantkumar.Hiremath@Sun.COM 		return (IBT_INVALID_PARAM);
38859913SShantkumar.Hiremath@Sun.COM 	}
38869913SShantkumar.Hiremath@Sun.COM 
38879913SShantkumar.Hiremath@Sun.COM 	if (event != IBT_CM_EVENT_REQ_RCV) {
38889913SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L2(cmlog, "ibt_ofuvcm_proceed : only for REQ_RCV");
38899913SShantkumar.Hiremath@Sun.COM 		return (IBT_INVALID_PARAM);
38909913SShantkumar.Hiremath@Sun.COM 	}
38919913SShantkumar.Hiremath@Sun.COM 	mutex_enter(&statep->state_mutex);
389211369SPramod.Gunjikar@Sun.COM 	statep->is_this_ofuv_chan = B_TRUE;
38939913SShantkumar.Hiremath@Sun.COM 	mutex_exit(&statep->state_mutex);
38949913SShantkumar.Hiremath@Sun.COM 
38959913SShantkumar.Hiremath@Sun.COM 	ret = ibt_cm_proceed(event, session_id, status, cm_event_data,
38969913SShantkumar.Hiremath@Sun.COM 	    priv_data, priv_data_len);
38979913SShantkumar.Hiremath@Sun.COM 	return (ret);
38989913SShantkumar.Hiremath@Sun.COM }
38990Sstevel@tonic-gate 
39000Sstevel@tonic-gate /*
39010Sstevel@tonic-gate  * Function:
39020Sstevel@tonic-gate  * 	ibt_cm_proceed
39030Sstevel@tonic-gate  *
39040Sstevel@tonic-gate  * Verifies the arguments and dispatches the cm state machine processing
39050Sstevel@tonic-gate  * via taskq
39060Sstevel@tonic-gate  */
39070Sstevel@tonic-gate 
39080Sstevel@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)39090Sstevel@tonic-gate ibt_cm_proceed(ibt_cm_event_type_t event, void *session_id,
39100Sstevel@tonic-gate     ibt_cm_status_t status, ibt_cm_proceed_reply_t *cm_event_data,
39110Sstevel@tonic-gate     void *priv_data, ibt_priv_data_len_t priv_data_len)
39120Sstevel@tonic-gate {
39130Sstevel@tonic-gate 	ibcm_state_data_t *statep = (ibcm_state_data_t *)session_id;
39140Sstevel@tonic-gate 	ibcm_proceed_targs_t	*proceed_targs;
39150Sstevel@tonic-gate 	ibcm_proceed_error_t	proceed_error;
39160Sstevel@tonic-gate 
39170Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_proceed chan 0x%p event %x status %x "
39180Sstevel@tonic-gate 	    "session_id %p", statep->channel, event, status, session_id);
39190Sstevel@tonic-gate 
39200Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed chan 0x%p cm_event_data %p, "
39210Sstevel@tonic-gate 	    "priv_data %p priv_data_len %x", statep->channel, cm_event_data,
39220Sstevel@tonic-gate 	    priv_data, priv_data_len);
39230Sstevel@tonic-gate 
39240Sstevel@tonic-gate 	/* validate session_id and status */
39250Sstevel@tonic-gate 	if ((statep == NULL) || (status == IBT_CM_DEFER)) {
39260Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : Invalid Args");
39270Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
39280Sstevel@tonic-gate 	}
39290Sstevel@tonic-gate 
39300Sstevel@tonic-gate 	/* If priv data len specified, then priv_data cannot be NULL */
39310Sstevel@tonic-gate 	if ((priv_data_len > 0) && (priv_data == NULL))
39320Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
39330Sstevel@tonic-gate 
39340Sstevel@tonic-gate 	proceed_error = IBCM_PROCEED_INVALID_NONE;
39350Sstevel@tonic-gate 
39360Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
39370Sstevel@tonic-gate 	if (event == IBT_CM_EVENT_REQ_RCV) {
39380Sstevel@tonic-gate 
39390Sstevel@tonic-gate 		if ((statep->state != IBCM_STATE_REQ_RCVD) &&
39400Sstevel@tonic-gate 		    (statep->state != IBCM_STATE_MRA_SENT))
39410Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39420Sstevel@tonic-gate 		else if (priv_data_len > IBT_REP_PRIV_DATA_SZ)
39430Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39440Sstevel@tonic-gate 
39450Sstevel@tonic-gate 	} else if (event == IBT_CM_EVENT_REP_RCV) {
39460Sstevel@tonic-gate 		if ((statep->state != IBCM_STATE_REP_RCVD) &&
39470Sstevel@tonic-gate 		    (statep->state != IBCM_STATE_MRA_REP_SENT))
39480Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39490Sstevel@tonic-gate 		else if (priv_data_len > IBT_RTU_PRIV_DATA_SZ)
39500Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39510Sstevel@tonic-gate 	} else if (event == IBT_CM_EVENT_LAP_RCV) {
39520Sstevel@tonic-gate 		if ((statep->ap_state != IBCM_AP_STATE_LAP_RCVD) &&
39530Sstevel@tonic-gate 		    (statep->ap_state != IBCM_AP_STATE_MRA_LAP_SENT))
39540Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39550Sstevel@tonic-gate 		else if (priv_data_len > IBT_APR_PRIV_DATA_SZ)
39560Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39570Sstevel@tonic-gate 	} else if (event == IBT_CM_EVENT_CONN_CLOSED) {
39580Sstevel@tonic-gate 		if (statep->state != IBCM_STATE_DREQ_RCVD)
39590Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
39600Sstevel@tonic-gate 		else if (priv_data_len > IBT_DREP_PRIV_DATA_SZ)
39610Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
39620Sstevel@tonic-gate 	} else {
39630Sstevel@tonic-gate 			proceed_error = IBCM_PROCEED_INVALID_EVENT;
39640Sstevel@tonic-gate 	}
39650Sstevel@tonic-gate 
39660Sstevel@tonic-gate 	/* if there is an error, print an error message and return */
39670Sstevel@tonic-gate 	if (proceed_error != IBCM_PROCEED_INVALID_NONE) {
39680Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
39690Sstevel@tonic-gate 		if (proceed_error == IBCM_PROCEED_INVALID_EVENT_STATE) {
39700Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39710Sstevel@tonic-gate 			    "Invalid Event/State combination specified",
39720Sstevel@tonic-gate 			    statep->channel);
39730Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
39740Sstevel@tonic-gate 		} else if (proceed_error == IBCM_PROCEED_INVALID_PRIV_SZ) {
39750Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39760Sstevel@tonic-gate 			    "Invalid Event/priv len combination specified",
39770Sstevel@tonic-gate 			    statep->channel);
39780Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
39790Sstevel@tonic-gate 		} else if (proceed_error == IBCM_PROCEED_INVALID_EVENT) {
39800Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39810Sstevel@tonic-gate 			    "Invalid Event specified", statep->channel);
39820Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
39830Sstevel@tonic-gate 		} else {
39840Sstevel@tonic-gate 			ASSERT(proceed_error == IBCM_PROCEED_INVALID_LAP);
39850Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
39860Sstevel@tonic-gate 			    "IBT_CM_EVENT_LAP_RCV not supported",
39870Sstevel@tonic-gate 			    statep->channel);
39880Sstevel@tonic-gate 			/* UNTIL HCA DRIVER ENABLES AP SUPPORT, FAIL THE CALL */
39890Sstevel@tonic-gate 			return (IBT_APM_NOT_SUPPORTED);
39900Sstevel@tonic-gate 		}
39910Sstevel@tonic-gate 	}
39920Sstevel@tonic-gate 
39930Sstevel@tonic-gate 
39940Sstevel@tonic-gate 	/* wait until client's CM handler returns DEFER status back to CM */
39950Sstevel@tonic-gate 
39960Sstevel@tonic-gate 	while (statep->clnt_proceed == IBCM_BLOCK) {
39970Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed : chan 0x%p blocked for "
39980Sstevel@tonic-gate 		    "return of client's cm handler", statep->channel);
39990Sstevel@tonic-gate 		cv_wait(&statep->block_client_cv, &statep->state_mutex);
40000Sstevel@tonic-gate 	}
40010Sstevel@tonic-gate 
40020Sstevel@tonic-gate 	if (statep->clnt_proceed == IBCM_FAIL) {
40030Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
40040Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p Failed as "
40050Sstevel@tonic-gate 		    "client returned non-DEFER status from cm handler",
40060Sstevel@tonic-gate 		    statep->channel);
40070Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
40080Sstevel@tonic-gate 	}
40090Sstevel@tonic-gate 
40100Sstevel@tonic-gate 	ASSERT(statep->clnt_proceed == IBCM_UNBLOCK);
40110Sstevel@tonic-gate 	statep->clnt_proceed = IBCM_FAIL;
40120Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
40130Sstevel@tonic-gate 
40140Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
40150Sstevel@tonic-gate 
40160Sstevel@tonic-gate 	/* the state machine processing is done in a separate thread */
40170Sstevel@tonic-gate 
40180Sstevel@tonic-gate 	/* proceed_targs is freed in ibcm_proceed_via_taskq */
40190Sstevel@tonic-gate 	proceed_targs = kmem_alloc(sizeof (ibcm_proceed_targs_t),
40200Sstevel@tonic-gate 	    KM_SLEEP);
40210Sstevel@tonic-gate 
40220Sstevel@tonic-gate 	proceed_targs->event  = event;
40230Sstevel@tonic-gate 	proceed_targs->status = status;
40240Sstevel@tonic-gate 	proceed_targs->priv_data_len = priv_data_len;
40250Sstevel@tonic-gate 
40260Sstevel@tonic-gate 	bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
40270Sstevel@tonic-gate 
40280Sstevel@tonic-gate 	proceed_targs->tst.rc.statep = statep;
40290Sstevel@tonic-gate 	bcopy(cm_event_data, &proceed_targs->tst.rc.rc_cm_event_data,
40300Sstevel@tonic-gate 	    sizeof (ibt_cm_proceed_reply_t));
40310Sstevel@tonic-gate 
40320Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
40330Sstevel@tonic-gate 
40340Sstevel@tonic-gate 	(void) taskq_dispatch(ibcm_taskq, ibcm_proceed_via_taskq,
40350Sstevel@tonic-gate 	    proceed_targs, TQ_SLEEP);
40360Sstevel@tonic-gate 
40370Sstevel@tonic-gate 	return (IBT_SUCCESS);
40380Sstevel@tonic-gate }
40390Sstevel@tonic-gate 
40400Sstevel@tonic-gate /*
40410Sstevel@tonic-gate  * Function:
40420Sstevel@tonic-gate  * 	ibcm_proceed_via_taskq
40430Sstevel@tonic-gate  *
40440Sstevel@tonic-gate  * Called from taskq, dispatched by ibt_cm_proceed
40450Sstevel@tonic-gate  * Completes the cm state processing for ibt_cm_proceed
40460Sstevel@tonic-gate  */
40470Sstevel@tonic-gate void
ibcm_proceed_via_taskq(void * targs)40480Sstevel@tonic-gate ibcm_proceed_via_taskq(void *targs)
40490Sstevel@tonic-gate {
40500Sstevel@tonic-gate 	ibcm_proceed_targs_t	*proceed_targs = (ibcm_proceed_targs_t *)targs;
40510Sstevel@tonic-gate 	ibcm_state_data_t *statep = proceed_targs->tst.rc.statep;
40520Sstevel@tonic-gate 	ibt_cm_reason_t reject_reason;
40530Sstevel@tonic-gate 	uint8_t arej_len;
40540Sstevel@tonic-gate 	ibcm_status_t response;
40550Sstevel@tonic-gate 	ibcm_clnt_reply_info_t clnt_info;
40560Sstevel@tonic-gate 
40570Sstevel@tonic-gate 	clnt_info.reply_event = &proceed_targs->tst.rc.rc_cm_event_data;
40580Sstevel@tonic-gate 	clnt_info.priv_data = proceed_targs->priv_data;
40590Sstevel@tonic-gate 	clnt_info.priv_data_len = proceed_targs->priv_data_len;
40600Sstevel@tonic-gate 
40610Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_proceed_via_taskq chan 0x%p targs %x",
40620Sstevel@tonic-gate 	    statep->channel, targs);
40630Sstevel@tonic-gate 
40640Sstevel@tonic-gate 	if (proceed_targs->event == IBT_CM_EVENT_REQ_RCV) {
40650Sstevel@tonic-gate 		response =
40660Sstevel@tonic-gate 		    ibcm_process_cep_req_cm_hdlr(statep, proceed_targs->status,
40670Sstevel@tonic-gate 		    &clnt_info, &reject_reason, &arej_len,
40680Sstevel@tonic-gate 		    (ibcm_req_msg_t *)statep->defer_cm_msg);
40690Sstevel@tonic-gate 
40700Sstevel@tonic-gate 		ibcm_handle_cep_req_response(statep, response, reject_reason,
40710Sstevel@tonic-gate 		    arej_len);
40720Sstevel@tonic-gate 
40730Sstevel@tonic-gate 	} else if (proceed_targs->event == IBT_CM_EVENT_REP_RCV) {
40740Sstevel@tonic-gate 		response =
40750Sstevel@tonic-gate 		    ibcm_process_cep_rep_cm_hdlr(statep, proceed_targs->status,
40760Sstevel@tonic-gate 		    &clnt_info, &reject_reason, &arej_len,
40770Sstevel@tonic-gate 		    (ibcm_rep_msg_t *)statep->defer_cm_msg);
40780Sstevel@tonic-gate 
40790Sstevel@tonic-gate 		ibcm_handle_cep_rep_response(statep, response, reject_reason,
40800Sstevel@tonic-gate 		    arej_len, (ibcm_rep_msg_t *)statep->defer_cm_msg);
40810Sstevel@tonic-gate 
40820Sstevel@tonic-gate 	} else if (proceed_targs->event == IBT_CM_EVENT_LAP_RCV) {
40830Sstevel@tonic-gate 		ibcm_process_cep_lap_cm_hdlr(statep, proceed_targs->status,
40840Sstevel@tonic-gate 		    &clnt_info, (ibcm_lap_msg_t *)statep->defer_cm_msg,
40850Sstevel@tonic-gate 		    (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg));
40860Sstevel@tonic-gate 
40870Sstevel@tonic-gate 		ibcm_post_apr_mad(statep);
40880Sstevel@tonic-gate 
40890Sstevel@tonic-gate 	} else {
40900Sstevel@tonic-gate 		ASSERT(proceed_targs->event == IBT_CM_EVENT_CONN_CLOSED);
40910Sstevel@tonic-gate 		ibcm_handle_cep_dreq_response(statep, proceed_targs->priv_data,
40920Sstevel@tonic-gate 		    proceed_targs->priv_data_len);
40930Sstevel@tonic-gate 	}
40940Sstevel@tonic-gate 
40950Sstevel@tonic-gate 	kmem_free(targs, sizeof (ibcm_proceed_targs_t));
40960Sstevel@tonic-gate }
40970Sstevel@tonic-gate 
40980Sstevel@tonic-gate /*
40990Sstevel@tonic-gate  * Function:
41000Sstevel@tonic-gate  * 	ibt_cm_ud_proceed
41010Sstevel@tonic-gate  *
41020Sstevel@tonic-gate  * Verifies the arguments and dispatches the cm state machine processing
41030Sstevel@tonic-gate  * via taskq
41040Sstevel@tonic-gate  */
41050Sstevel@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)41060Sstevel@tonic-gate ibt_cm_ud_proceed(void *session_id, ibt_channel_hdl_t ud_channel,
41070Sstevel@tonic-gate     ibt_cm_status_t status, ibt_redirect_info_t *redirect_infop,
41080Sstevel@tonic-gate     void *priv_data, ibt_priv_data_len_t priv_data_len)
41090Sstevel@tonic-gate {
41100Sstevel@tonic-gate 	ibcm_ud_state_data_t *ud_statep = (ibcm_ud_state_data_t *)session_id;
41110Sstevel@tonic-gate 	ibcm_proceed_targs_t	*proceed_targs;
41120Sstevel@tonic-gate 	ibt_qp_query_attr_t	qp_attr;
41130Sstevel@tonic-gate 	ibt_status_t		retval;
41140Sstevel@tonic-gate 
41150Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_ud_proceed session_id %p "
41160Sstevel@tonic-gate 	    "ud_channel %p ", session_id, ud_channel);
41170Sstevel@tonic-gate 
41180Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_cm_ud_proceed status %x priv_data %p "
41190Sstevel@tonic-gate 	    "priv_data_len %x",  status, priv_data, priv_data_len);
41200Sstevel@tonic-gate 
41210Sstevel@tonic-gate 	/* validate session_id and status */
41220Sstevel@tonic-gate 	if ((ud_statep == NULL) || (status == IBT_CM_DEFER)) {
41230Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Invalid Args");
41240Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41250Sstevel@tonic-gate 	}
41260Sstevel@tonic-gate 
41270Sstevel@tonic-gate 	/* If priv data len specified, then priv_data cannot be NULL */
41280Sstevel@tonic-gate 	if ((priv_data_len > 0) && (priv_data == NULL))
41290Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41300Sstevel@tonic-gate 
41310Sstevel@tonic-gate 	if (priv_data_len > IBT_SIDR_REP_PRIV_DATA_SZ)
41320Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41330Sstevel@tonic-gate 
41340Sstevel@tonic-gate 	/* retrieve qpn and qkey from ud channel */
41350Sstevel@tonic-gate 
41360Sstevel@tonic-gate 	/* validate event and statep's state */
41370Sstevel@tonic-gate 
41380Sstevel@tonic-gate 	if (status == IBT_CM_ACCEPT) {
41390Sstevel@tonic-gate 		retval = ibt_query_qp(ud_channel, &qp_attr);
41400Sstevel@tonic-gate 		if ((retval != IBT_SUCCESS) ||
41410Sstevel@tonic-gate 		    (qp_attr.qp_info.qp_trans != IBT_UD_SRV)) {
41420Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed: "
41430Sstevel@tonic-gate 			    "Failed to retrieve QPN from the channel: %d",
41440Sstevel@tonic-gate 			    retval);
41450Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
41460Sstevel@tonic-gate 		}
41470Sstevel@tonic-gate 	}
41480Sstevel@tonic-gate 
41490Sstevel@tonic-gate 
41500Sstevel@tonic-gate 	mutex_enter(&ud_statep->ud_state_mutex);
41510Sstevel@tonic-gate 
41520Sstevel@tonic-gate 	if (ud_statep->ud_state != IBCM_STATE_SIDR_REQ_RCVD) {
41530Sstevel@tonic-gate 		mutex_exit(&ud_statep->ud_state_mutex);
41540Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Invalid State "
41550Sstevel@tonic-gate 		    "specified");
41560Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41570Sstevel@tonic-gate 	}
41580Sstevel@tonic-gate 
41590Sstevel@tonic-gate 	/* wait until client's CM handler returns DEFER status back to CM */
41600Sstevel@tonic-gate 
41610Sstevel@tonic-gate 	while (ud_statep->ud_clnt_proceed == IBCM_BLOCK) {
41620Sstevel@tonic-gate 		IBTF_DPRINTF_L5(cmlog, "ibt_cm_ud_proceed : Blocked for return"
41630Sstevel@tonic-gate 		    " of client's ud cm handler");
41640Sstevel@tonic-gate 		cv_wait(&ud_statep->ud_block_client_cv,
41650Sstevel@tonic-gate 		    &ud_statep->ud_state_mutex);
41660Sstevel@tonic-gate 	}
41670Sstevel@tonic-gate 
41680Sstevel@tonic-gate 	if (ud_statep->ud_clnt_proceed == IBCM_FAIL) {
41690Sstevel@tonic-gate 		mutex_exit(&ud_statep->ud_state_mutex);
41700Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Failed as client "
41710Sstevel@tonic-gate 		    "returned non-DEFER status from cm handler");
41720Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
41730Sstevel@tonic-gate 	}
41740Sstevel@tonic-gate 
41750Sstevel@tonic-gate 	ASSERT(ud_statep->ud_clnt_proceed == IBCM_UNBLOCK);
41760Sstevel@tonic-gate 	ud_statep->ud_clnt_proceed = IBCM_FAIL;
41770Sstevel@tonic-gate 	mutex_exit(&ud_statep->ud_state_mutex);
41780Sstevel@tonic-gate 
41790Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
41800Sstevel@tonic-gate 
41810Sstevel@tonic-gate 	/* the state machine processing is done in a separate thread */
41820Sstevel@tonic-gate 
41830Sstevel@tonic-gate 	/* proceed_targs is freed in ibcm_proceed_via_taskq */
41843241Shiremath 	proceed_targs = kmem_zalloc(sizeof (ibcm_proceed_targs_t),
41850Sstevel@tonic-gate 	    KM_SLEEP);
41860Sstevel@tonic-gate 
41870Sstevel@tonic-gate 	proceed_targs->status = status;
41880Sstevel@tonic-gate 	proceed_targs->priv_data_len = priv_data_len;
41890Sstevel@tonic-gate 
41900Sstevel@tonic-gate 	bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
41910Sstevel@tonic-gate 
41920Sstevel@tonic-gate 	if (status == IBT_CM_ACCEPT) {
41930Sstevel@tonic-gate 		proceed_targs->tst.ud.ud_qkey =
41940Sstevel@tonic-gate 		    qp_attr.qp_info.qp_transport.ud.ud_qkey;
41950Sstevel@tonic-gate 		proceed_targs->tst.ud.ud_qpn = qp_attr.qp_qpn;
41960Sstevel@tonic-gate 	}
41970Sstevel@tonic-gate 
41980Sstevel@tonic-gate 	proceed_targs->tst.ud.ud_statep = ud_statep;
41990Sstevel@tonic-gate 
42000Sstevel@tonic-gate 	/* copy redirect info based on status */
42010Sstevel@tonic-gate 	if (status == IBT_CM_REDIRECT)
42020Sstevel@tonic-gate 		bcopy(redirect_infop, &proceed_targs->tst.ud.ud_redirect_info,
42030Sstevel@tonic-gate 		    sizeof (ibt_redirect_info_t));
42040Sstevel@tonic-gate 
42050Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
42060Sstevel@tonic-gate 
42070Sstevel@tonic-gate 	(void) taskq_dispatch(ibcm_taskq, ibcm_ud_proceed_via_taskq,
42080Sstevel@tonic-gate 	    proceed_targs, TQ_SLEEP);
42090Sstevel@tonic-gate 
42100Sstevel@tonic-gate 	return (IBT_SUCCESS);
42110Sstevel@tonic-gate }
42120Sstevel@tonic-gate 
42130Sstevel@tonic-gate /*
42140Sstevel@tonic-gate  * Function:
42150Sstevel@tonic-gate  * 	ibcm_ud_proceed_via_taskq
42160Sstevel@tonic-gate  *
42170Sstevel@tonic-gate  * Called from taskq, dispatched by ibt_cm_ud_proceed
42180Sstevel@tonic-gate  * Completes the cm state processing for ibt_cm_ud_proceed
42190Sstevel@tonic-gate  */
42200Sstevel@tonic-gate void
ibcm_ud_proceed_via_taskq(void * targs)42210Sstevel@tonic-gate ibcm_ud_proceed_via_taskq(void *targs)
42220Sstevel@tonic-gate {
42230Sstevel@tonic-gate 	ibcm_proceed_targs_t	*proceed_targs = (ibcm_proceed_targs_t *)targs;
42240Sstevel@tonic-gate 	ibcm_ud_state_data_t	*ud_statep = proceed_targs->tst.ud.ud_statep;
42250Sstevel@tonic-gate 	ibcm_ud_clnt_reply_info_t ud_clnt_info;
42260Sstevel@tonic-gate 	ibt_sidr_status_t	sidr_status;
42270Sstevel@tonic-gate 
42280Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_proceed_via_taskq(%p)", targs);
42290Sstevel@tonic-gate 
42300Sstevel@tonic-gate 	ud_clnt_info.ud_qpn  = proceed_targs->tst.ud.ud_qpn;
42310Sstevel@tonic-gate 	ud_clnt_info.ud_qkey  = proceed_targs->tst.ud.ud_qkey;
42320Sstevel@tonic-gate 	ud_clnt_info.priv_data = proceed_targs->priv_data;
42330Sstevel@tonic-gate 	ud_clnt_info.priv_data_len = proceed_targs->priv_data_len;
42340Sstevel@tonic-gate 	ud_clnt_info.redirect_infop = &proceed_targs->tst.ud.ud_redirect_info;
42350Sstevel@tonic-gate 
42360Sstevel@tonic-gate 	/* validate event and statep's state */
42370Sstevel@tonic-gate 	ibcm_process_sidr_req_cm_hdlr(ud_statep, proceed_targs->status,
42380Sstevel@tonic-gate 	    &ud_clnt_info, &sidr_status,
42390Sstevel@tonic-gate 	    (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg));
42400Sstevel@tonic-gate 
42410Sstevel@tonic-gate 	ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
42420Sstevel@tonic-gate 
42430Sstevel@tonic-gate 	/* decr the statep ref cnt incremented in ibcm_process_sidr_req_msg */
42440Sstevel@tonic-gate 	mutex_enter(&ud_statep->ud_state_mutex);
42450Sstevel@tonic-gate 	IBCM_UD_REF_CNT_DECR(ud_statep);
42460Sstevel@tonic-gate 	mutex_exit(&ud_statep->ud_state_mutex);
42470Sstevel@tonic-gate 
42480Sstevel@tonic-gate 	kmem_free(targs, sizeof (ibcm_proceed_targs_t));
42490Sstevel@tonic-gate }
42500Sstevel@tonic-gate 
42510Sstevel@tonic-gate /*
42520Sstevel@tonic-gate  * Function:
42530Sstevel@tonic-gate  *	ibt_set_alt_path
42540Sstevel@tonic-gate  * Input:
42550Sstevel@tonic-gate  *	channel		Channel handle returned from ibt_alloc_rc_channel(9F).
42560Sstevel@tonic-gate  *
42570Sstevel@tonic-gate  *	mode		Execute in blocking or non blocking mode.
42580Sstevel@tonic-gate  *
42590Sstevel@tonic-gate  *	alt_path	A pointer to an ibt_alt_path_info_t as returned from an
42600Sstevel@tonic-gate  *			ibt_get_alt_path(9F) call that specifies the new
42610Sstevel@tonic-gate  *			alternate path.
42620Sstevel@tonic-gate  *
42630Sstevel@tonic-gate  *	priv_data       A pointer to a buffer specified by caller for the
42640Sstevel@tonic-gate  *			private data in the outgoing CM Load Alternate Path
42650Sstevel@tonic-gate  *			(LAP) message sent to the remote host. This can be NULL
42660Sstevel@tonic-gate  *			if no private data is available to communicate to the
42670Sstevel@tonic-gate  *			remote node.
42680Sstevel@tonic-gate  *
42690Sstevel@tonic-gate  *	priv_data_len   Length of valid data in priv_data, this should be less
42700Sstevel@tonic-gate  *			than or equal to IBT_LAP_PRIV_DATA_SZ.
42710Sstevel@tonic-gate  *
42720Sstevel@tonic-gate  * Output:
42730Sstevel@tonic-gate  *	ret_args	If called in blocking mode, points to a return argument
42740Sstevel@tonic-gate  *			structure of type ibt_ap_returns_t.
42750Sstevel@tonic-gate  *
42760Sstevel@tonic-gate  * Returns:
42770Sstevel@tonic-gate  *	IBT_SUCCESS on Success else appropriate error.
42780Sstevel@tonic-gate  * Description:
42790Sstevel@tonic-gate  *	Load the specified alternate path. Causes the CM to send an LAP message
42800Sstevel@tonic-gate  *	to the remote node.
42810Sstevel@tonic-gate  *	Can only be called on a previously opened RC channel.
42820Sstevel@tonic-gate  */
42830Sstevel@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)42840Sstevel@tonic-gate ibt_set_alt_path(ibt_channel_hdl_t channel, ibt_execution_mode_t mode,
42850Sstevel@tonic-gate     ibt_alt_path_info_t *alt_path, void *priv_data,
42860Sstevel@tonic-gate     ibt_priv_data_len_t priv_data_len, ibt_ap_returns_t *ret_args)
42870Sstevel@tonic-gate {
42880Sstevel@tonic-gate 	ibmf_handle_t		ibmf_hdl;
42890Sstevel@tonic-gate 	ibt_status_t		status = IBT_SUCCESS;
42900Sstevel@tonic-gate 	ibcm_lap_msg_t		*lap_msgp;
42910Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
42920Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
42930Sstevel@tonic-gate 	uint8_t			port_no;
42940Sstevel@tonic-gate 	ib_lid_t		alternate_slid;
42950Sstevel@tonic-gate 	ibt_priv_data_len_t	len;
42960Sstevel@tonic-gate 	ib_lid_t		base_lid;
42970Sstevel@tonic-gate 	boolean_t		alt_grh;
42980Sstevel@tonic-gate 
42990Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path(%p, %x, %p, %p, %x, %p)",
43000Sstevel@tonic-gate 	    channel, mode, alt_path, priv_data, priv_data_len, ret_args);
43010Sstevel@tonic-gate 
43020Sstevel@tonic-gate 	/* validate channel */
43030Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
43040Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: invalid channel");
43050Sstevel@tonic-gate 		return (IBT_CHAN_HDL_INVALID);
43060Sstevel@tonic-gate 	}
43070Sstevel@tonic-gate 
43080Sstevel@tonic-gate 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
43090Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43100Sstevel@tonic-gate 		    "Invalid Channel type: Applicable only to RC Channel");
43110Sstevel@tonic-gate 		return (IBT_CHAN_SRV_TYPE_INVALID);
43120Sstevel@tonic-gate 	}
43130Sstevel@tonic-gate 
43140Sstevel@tonic-gate 	if (mode == IBT_NONBLOCKING) {
43150Sstevel@tonic-gate 		if (ret_args != NULL) {
43160Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43170Sstevel@tonic-gate 			    "ret_args should be NULL when called in "
43180Sstevel@tonic-gate 			    "non-blocking mode");
43190Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
43200Sstevel@tonic-gate 		}
43210Sstevel@tonic-gate 	} else if (mode == IBT_BLOCKING) {
43220Sstevel@tonic-gate 		if (ret_args == NULL) {
43230Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43240Sstevel@tonic-gate 			    "ret_args should be Non-NULL when called in "
43250Sstevel@tonic-gate 			    "blocking mode");
43260Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
43270Sstevel@tonic-gate 		}
43280Sstevel@tonic-gate 		if (ret_args->ap_priv_data_len > IBT_APR_PRIV_DATA_SZ) {
43290Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43300Sstevel@tonic-gate 			    "expected private data length is too large");
43310Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
43320Sstevel@tonic-gate 		}
43330Sstevel@tonic-gate 		if ((ret_args->ap_priv_data_len > 0) &&
43340Sstevel@tonic-gate 		    (ret_args->ap_priv_data == NULL)) {
43350Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43360Sstevel@tonic-gate 			    "apr_priv_data_len > 0, but apr_priv_data NULL");
43370Sstevel@tonic-gate 			return (IBT_INVALID_PARAM);
43380Sstevel@tonic-gate 		}
43390Sstevel@tonic-gate 	} else { /* any other mode is not valid for ibt_set_alt_path */
43400Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43410Sstevel@tonic-gate 		    "invalid mode %x specified", mode);
43420Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
43430Sstevel@tonic-gate 	}
43440Sstevel@tonic-gate 
43450Sstevel@tonic-gate 	if ((port_no = alt_path->ap_alt_cep_path.cep_hca_port_num) == 0)
43460Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
43470Sstevel@tonic-gate 
43480Sstevel@tonic-gate 	/* get the statep */
43490Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
43500Sstevel@tonic-gate 	if (statep == NULL) {
43510Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: statep NULL");
43520Sstevel@tonic-gate 		return (IBT_CM_FAILURE);
43530Sstevel@tonic-gate 	}
43540Sstevel@tonic-gate 
43550Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
43560Sstevel@tonic-gate 	IBCM_RELEASE_CHAN_PRIVATE(channel);
43570Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);
43580Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
43590Sstevel@tonic-gate 
43600Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: statep %p", statep);
43610Sstevel@tonic-gate 
43620Sstevel@tonic-gate 	hcap = statep->hcap;
43630Sstevel@tonic-gate 
43640Sstevel@tonic-gate 	/* HCA must have been in active state. If not, it's a client bug */
43650Sstevel@tonic-gate 	if (!IBCM_ACCESS_HCA_OK(hcap))
43660Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: hca in error state");
43670Sstevel@tonic-gate 
43680Sstevel@tonic-gate 	ASSERT(statep->cm_handler != NULL);
43690Sstevel@tonic-gate 
43700Sstevel@tonic-gate 	/* Check Alternate port */
43710Sstevel@tonic-gate 	status = ibt_get_port_state_byguid(hcap->hca_guid, port_no, NULL,
43720Sstevel@tonic-gate 	    &base_lid);
43730Sstevel@tonic-gate 	if (status != IBT_SUCCESS) {
43740Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43750Sstevel@tonic-gate 		    "ibt_get_port_state_byguid status %d ", status);
43760Sstevel@tonic-gate 		mutex_enter(&statep->state_mutex);
43770Sstevel@tonic-gate 		IBCM_REF_CNT_DECR(statep);
43780Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
43790Sstevel@tonic-gate 		return (status);
43800Sstevel@tonic-gate 	}
43810Sstevel@tonic-gate 
43820Sstevel@tonic-gate 	if ((hcap->hca_port_info[port_no - 1].port_ibmf_hdl == NULL) &&
43830Sstevel@tonic-gate 	    ((status = ibcm_hca_reinit_port(hcap, port_no - 1))
43840Sstevel@tonic-gate 	    != IBT_SUCCESS)) {
43850Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
43860Sstevel@tonic-gate 		    "ibmf reg or callback setup failed during re-initialize");
43870Sstevel@tonic-gate 		mutex_enter(&statep->state_mutex);
43880Sstevel@tonic-gate 		IBCM_REF_CNT_DECR(statep);
43890Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
43900Sstevel@tonic-gate 		return (status);
43910Sstevel@tonic-gate 	}
43920Sstevel@tonic-gate 
43930Sstevel@tonic-gate 	ibmf_hdl = statep->stored_reply_addr.ibmf_hdl;
43940Sstevel@tonic-gate 
43950Sstevel@tonic-gate 	alternate_slid = base_lid +
43960Sstevel@tonic-gate 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_src_path;
43970Sstevel@tonic-gate 
43980Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: alternate SLID = %x",
43990Sstevel@tonic-gate 	    h2b16(alternate_slid));
44000Sstevel@tonic-gate 
44011093Shiremath 	ibcm_lapr_enter();	/* limit how many run simultaneously */
44020Sstevel@tonic-gate 
44030Sstevel@tonic-gate 	/* Allocate MAD for LAP */
44040Sstevel@tonic-gate 	if (statep->lapr_msg == NULL)
44050Sstevel@tonic-gate 		if ((status = ibcm_alloc_out_msg(ibmf_hdl, &statep->lapr_msg,
44060Sstevel@tonic-gate 		    MAD_METHOD_SEND)) != IBT_SUCCESS) {
44071093Shiremath 			ibcm_lapr_exit();
44080Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
44090Sstevel@tonic-gate 			    "chan 0x%p ibcm_alloc_out_msg failed", channel);
44100Sstevel@tonic-gate 			mutex_enter(&statep->state_mutex);
44110Sstevel@tonic-gate 			IBCM_REF_CNT_DECR(statep);
44120Sstevel@tonic-gate 			mutex_exit(&statep->state_mutex);
44130Sstevel@tonic-gate 			return (status);
44140Sstevel@tonic-gate 		}
44150Sstevel@tonic-gate 
44160Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
44170Sstevel@tonic-gate 
44180Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: connection state is"
44190Sstevel@tonic-gate 	    " %x", statep->state);
44200Sstevel@tonic-gate 
44210Sstevel@tonic-gate 	/* Check state */
44220Sstevel@tonic-gate 	if ((statep->state != IBCM_STATE_ESTABLISHED) ||
44230Sstevel@tonic-gate 	    (statep->ap_state != IBCM_AP_STATE_IDLE)) {
44240Sstevel@tonic-gate 		IBCM_REF_CNT_DECR(statep);
44250Sstevel@tonic-gate 		mutex_exit(&statep->state_mutex);
44260Sstevel@tonic-gate 		(void) ibcm_free_out_msg(ibmf_hdl, &statep->lapr_msg);
44271093Shiremath 		ibcm_lapr_exit();
44280Sstevel@tonic-gate 		return (IBT_CHAN_STATE_INVALID);
44290Sstevel@tonic-gate 	} else {
44300Sstevel@tonic-gate 		/* Set to LAP Sent state */
44310Sstevel@tonic-gate 		statep->ap_state = IBCM_AP_STATE_LAP_SENT;
44320Sstevel@tonic-gate 		statep->ap_done = B_FALSE;
44330Sstevel@tonic-gate 		statep->remaining_retry_cnt = statep->max_cm_retries;
44340Sstevel@tonic-gate 		statep->timer_stored_state = statep->state;
44350Sstevel@tonic-gate 		statep->timer_stored_ap_state = statep->ap_state;
44360Sstevel@tonic-gate 		IBCM_REF_CNT_INCR(statep); /* for ibcm_post_lap_complete */
44370Sstevel@tonic-gate 	}
44380Sstevel@tonic-gate 
44390Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
44400Sstevel@tonic-gate 
44410Sstevel@tonic-gate 	/* No more failure returns below */
44420Sstevel@tonic-gate 
44430Sstevel@tonic-gate 	/* Allocate MAD for LAP */
44440Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibt_set_alt_path:"
44450Sstevel@tonic-gate 	    " statep's mad addr = 0x%p", IBCM_OUT_HDRP(statep->lapr_msg));
44460Sstevel@tonic-gate 
44470Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lap_msgp))
44480Sstevel@tonic-gate 
44490Sstevel@tonic-gate 	lap_msgp = (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
44500Sstevel@tonic-gate 
44510Sstevel@tonic-gate 	lap_msgp->lap_alt_l_port_lid = h2b16(alternate_slid);
44520Sstevel@tonic-gate 	lap_msgp->lap_alt_r_port_lid =
44530Sstevel@tonic-gate 	    h2b16(alt_path->ap_alt_cep_path.cep_adds_vect.av_dlid);
44540Sstevel@tonic-gate 
44550Sstevel@tonic-gate 	/* Fill in remote port gid */
44560Sstevel@tonic-gate 	lap_msgp->lap_alt_r_port_gid.gid_prefix =
44570Sstevel@tonic-gate 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_prefix);
44580Sstevel@tonic-gate 	lap_msgp->lap_alt_r_port_gid.gid_guid =
44590Sstevel@tonic-gate 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_guid);
44600Sstevel@tonic-gate 
44610Sstevel@tonic-gate 	/* Fill in local port gid */
44620Sstevel@tonic-gate 	lap_msgp->lap_alt_l_port_gid.gid_prefix =
44630Sstevel@tonic-gate 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_prefix);
44640Sstevel@tonic-gate 	lap_msgp->lap_alt_l_port_gid.gid_guid =
44650Sstevel@tonic-gate 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_guid);
44660Sstevel@tonic-gate 
44670Sstevel@tonic-gate 	alt_grh = alt_path->ap_alt_cep_path.cep_adds_vect.av_send_grh;
44680Sstevel@tonic-gate 
44690Sstevel@tonic-gate 	/* alternate_flow_label, and alternate srate, alternate traffic class */
44700Sstevel@tonic-gate 	lap_msgp->lap_alt_srate_plus =
44710Sstevel@tonic-gate 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_srate & 0x3f;
44720Sstevel@tonic-gate 	lap_msgp->lap_alt_flow_label_plus = h2b32(((alt_grh == B_TRUE) ?
44730Sstevel@tonic-gate 	    (alt_path->ap_alt_cep_path.cep_adds_vect.av_flow << 12) : 0) |
44740Sstevel@tonic-gate 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_tclass);
44750Sstevel@tonic-gate 
44760Sstevel@tonic-gate 	/* Alternate hop limit, service level */
44770Sstevel@tonic-gate 	lap_msgp->lap_alt_hop_limit = (alt_grh == B_TRUE) ?
44784970Shiremath 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_hop : 1;
44790Sstevel@tonic-gate 	lap_msgp->lap_alt_sl_plus =
44800Sstevel@tonic-gate 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_srvl << 4 |
44810Sstevel@tonic-gate 	    ((alt_grh == B_FALSE) ? 0x8 : 0);
44820Sstevel@tonic-gate 
44830Sstevel@tonic-gate 	lap_msgp->lap_alt_local_acktime_plus = ibt_usec2ib(
44840Sstevel@tonic-gate 	    (2 * statep->rc_alt_pkt_lt) +
44850Sstevel@tonic-gate 	    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
44860Sstevel@tonic-gate 
44870Sstevel@tonic-gate 	lap_msgp->lap_local_comm_id = h2b32(statep->local_comid);
44880Sstevel@tonic-gate 	lap_msgp->lap_remote_comm_id = h2b32(statep->remote_comid);
44890Sstevel@tonic-gate 
44900Sstevel@tonic-gate 	lap_msgp->lap_remote_qpn_eecn_plus =
44910Sstevel@tonic-gate 	    h2b32((statep->remote_qpn << 8) |
44920Sstevel@tonic-gate 	    ibt_usec2ib(ibcm_remote_response_time) << 3);
44930Sstevel@tonic-gate 
44940Sstevel@tonic-gate 	len = min(priv_data_len, IBT_LAP_PRIV_DATA_SZ);
44950Sstevel@tonic-gate 	if ((len > 0) && priv_data) {
44960Sstevel@tonic-gate 		bcopy(priv_data, lap_msgp->lap_private_data, len);
44970Sstevel@tonic-gate 	}
44980Sstevel@tonic-gate 
44990Sstevel@tonic-gate 	/* only rc_alt_pkt_lt and ap_return_data fields are initialized */
45000Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
45010Sstevel@tonic-gate 
45020Sstevel@tonic-gate 	statep->rc_alt_pkt_lt = ibt_ib2usec(alt_path->ap_alt_pkt_lt);
45030Sstevel@tonic-gate 
45040Sstevel@tonic-gate 	/* return_data is filled up in the state machine code */
45050Sstevel@tonic-gate 	statep->ap_return_data = ret_args;
45060Sstevel@tonic-gate 
45070Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
45080Sstevel@tonic-gate 
45090Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
45100Sstevel@tonic-gate 	    h2b16(IBCM_INCOMING_LAP + IBCM_ATTR_BASE_ID);
45110Sstevel@tonic-gate 
45120Sstevel@tonic-gate 	IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID =
45130Sstevel@tonic-gate 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_LAP, statep->local_comid,
45140Sstevel@tonic-gate 	    0));
45150Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path: statep %p, tid %llx",
45160Sstevel@tonic-gate 	    statep, IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID);
45170Sstevel@tonic-gate 
45180Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*lap_msgp))
45190Sstevel@tonic-gate 
45200Sstevel@tonic-gate 	/* Send LAP */
45210Sstevel@tonic-gate 	ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_lap_complete,
45220Sstevel@tonic-gate 	    statep);
45230Sstevel@tonic-gate 
45240Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
45250Sstevel@tonic-gate 
45260Sstevel@tonic-gate 	if (mode == IBT_BLOCKING) {
45270Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: blocking");
45280Sstevel@tonic-gate 
45290Sstevel@tonic-gate 		/* wait for APR */
45300Sstevel@tonic-gate 		while (statep->ap_done != B_TRUE) {
45310Sstevel@tonic-gate 			cv_wait(&statep->block_client_cv,
45320Sstevel@tonic-gate 			    &statep->state_mutex);
45330Sstevel@tonic-gate 		}
45340Sstevel@tonic-gate 
45350Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done blocking");
45360Sstevel@tonic-gate 
45370Sstevel@tonic-gate 		/*
45380Sstevel@tonic-gate 		 * In the case that ibt_set_alt_path fails,
45390Sstevel@tonic-gate 		 * change retval to IBT_CM_FAILURE
45400Sstevel@tonic-gate 		 */
45410Sstevel@tonic-gate 		if (statep->ap_return_data->ap_status != IBT_CM_AP_LOADED)
45420Sstevel@tonic-gate 			status = IBT_CM_FAILURE;
45430Sstevel@tonic-gate 
45440Sstevel@tonic-gate 	}
45450Sstevel@tonic-gate 
45460Sstevel@tonic-gate 	/* decrement the ref-count before leaving here */
45470Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
45480Sstevel@tonic-gate 
45490Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
45500Sstevel@tonic-gate 
45511093Shiremath 	ibcm_lapr_exit();
45521093Shiremath 
45530Sstevel@tonic-gate 	/* If this message isn't seen then ibt_set_alt_path failed */
45540Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done");
45550Sstevel@tonic-gate 
45560Sstevel@tonic-gate 	return (status);
45570Sstevel@tonic-gate }
45580Sstevel@tonic-gate 
45590Sstevel@tonic-gate 
45600Sstevel@tonic-gate #ifdef DEBUG
45610Sstevel@tonic-gate 
45620Sstevel@tonic-gate /*
45630Sstevel@tonic-gate  * ibcm_query_classport_info:
45640Sstevel@tonic-gate  *	Query classportinfo
45650Sstevel@tonic-gate  *
45660Sstevel@tonic-gate  * INPUTS:
45670Sstevel@tonic-gate  *	channel		- Channel that is associated with a statep
45680Sstevel@tonic-gate  *
45690Sstevel@tonic-gate  * RETURN VALUE: NONE
45700Sstevel@tonic-gate  * This function is currently used to generate a valid get method classport
45710Sstevel@tonic-gate  * info, and test CM functionality. There is no ibtl client interface to
45720Sstevel@tonic-gate  * generate a classportinfo. It is possible that CM may use classportinfo
45730Sstevel@tonic-gate  * from other nodes in the future, and most of the code below could be re-used.
45740Sstevel@tonic-gate  */
45750Sstevel@tonic-gate void
ibcm_query_classport_info(ibt_channel_hdl_t channel)45760Sstevel@tonic-gate ibcm_query_classport_info(ibt_channel_hdl_t channel)
45770Sstevel@tonic-gate {
45780Sstevel@tonic-gate 	ibcm_state_data_t	*statep;
45790Sstevel@tonic-gate 	ibmf_msg_t		*msgp;
45800Sstevel@tonic-gate 
45819349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibcm_query_classport_info(%p)", channel);
45820Sstevel@tonic-gate 
45830Sstevel@tonic-gate 	/* validate channel, first */
45840Sstevel@tonic-gate 	if (IBCM_INVALID_CHANNEL(channel)) {
45850Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info: "
45860Sstevel@tonic-gate 		    "invalid channel (%p)", channel);
45870Sstevel@tonic-gate 		return;
45880Sstevel@tonic-gate 	}
45890Sstevel@tonic-gate 
45900Sstevel@tonic-gate 	/* get the statep */
45910Sstevel@tonic-gate 	IBCM_GET_CHAN_PRIVATE(channel, statep);
45920Sstevel@tonic-gate 
45930Sstevel@tonic-gate 	/*
45940Sstevel@tonic-gate 	 * This can happen, if the statep is already gone by a DREQ from
45950Sstevel@tonic-gate 	 * the remote side
45960Sstevel@tonic-gate 	 */
45970Sstevel@tonic-gate 	if (statep == NULL) {
45980Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info: "
45990Sstevel@tonic-gate 		    "statep NULL");
46000Sstevel@tonic-gate 		return;
46010Sstevel@tonic-gate 	}
46020Sstevel@tonic-gate 
46030Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
46040Sstevel@tonic-gate 	IBCM_RELEASE_CHAN_PRIVATE(channel);
46050Sstevel@tonic-gate 	IBCM_REF_CNT_INCR(statep);
46060Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
46070Sstevel@tonic-gate 
46080Sstevel@tonic-gate 	/* Debug/test code, so don't care about return status */
46090Sstevel@tonic-gate 	(void) ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl, &msgp,
46100Sstevel@tonic-gate 	    MAD_METHOD_GET);
46110Sstevel@tonic-gate 
46120Sstevel@tonic-gate 	IBCM_OUT_HDRP(msgp)->TransactionID = h2b64(ibcm_generate_tranid(
46130Sstevel@tonic-gate 	    MAD_ATTR_ID_CLASSPORTINFO, statep->local_comid, 0));
46140Sstevel@tonic-gate 	IBCM_OUT_HDRP(msgp)->AttributeID = h2b16(MAD_ATTR_ID_CLASSPORTINFO);
46150Sstevel@tonic-gate 
46160Sstevel@tonic-gate 	(void) ibcm_post_mad(msgp, &statep->stored_reply_addr, NULL, NULL);
46170Sstevel@tonic-gate 
46189349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibcm_query_classport_info(%p) "
46190Sstevel@tonic-gate 	    "Get method MAD posted ", channel);
46200Sstevel@tonic-gate 
46210Sstevel@tonic-gate 	(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, &msgp);
46220Sstevel@tonic-gate 
46230Sstevel@tonic-gate 	mutex_enter(&statep->state_mutex);
46240Sstevel@tonic-gate 	IBCM_REF_CNT_DECR(statep);
46250Sstevel@tonic-gate 	mutex_exit(&statep->state_mutex);
46260Sstevel@tonic-gate }
46270Sstevel@tonic-gate 
46280Sstevel@tonic-gate static void
ibcm_print_reply_addr(ibt_channel_hdl_t channel,ibcm_mad_addr_t * cm_reply_addr)46290Sstevel@tonic-gate ibcm_print_reply_addr(ibt_channel_hdl_t channel, ibcm_mad_addr_t *cm_reply_addr)
46300Sstevel@tonic-gate {
46310Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: chan 0x%p, SLID %x, "
46320Sstevel@tonic-gate 	    "DLID %x", channel, cm_reply_addr->rcvd_addr.ia_local_lid,
46330Sstevel@tonic-gate 	    cm_reply_addr->rcvd_addr.ia_remote_lid);
46340Sstevel@tonic-gate 
46350Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: QKEY %x, PKEY %x, "
46360Sstevel@tonic-gate 	    "RQPN %x SL %x", cm_reply_addr->rcvd_addr.ia_q_key,
46370Sstevel@tonic-gate 	    cm_reply_addr->rcvd_addr.ia_p_key,
46380Sstevel@tonic-gate 	    cm_reply_addr->rcvd_addr.ia_remote_qno,
46390Sstevel@tonic-gate 	    cm_reply_addr->rcvd_addr.ia_service_level);
46400Sstevel@tonic-gate 
46410Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM SGID %llX:%llX ",
46420Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_sender_gid.gid_prefix,
46430Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_sender_gid.gid_guid);
46440Sstevel@tonic-gate 
46450Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM DGID %llX:%llX",
46460Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_recver_gid.gid_prefix,
46470Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_recver_gid.gid_guid);
46480Sstevel@tonic-gate 
46490Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM FL %x TC %x HL %x",
46500Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_flow_label,
46510Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_tclass,
46520Sstevel@tonic-gate 	    cm_reply_addr->grh_hdr.ig_hop_limit);
46530Sstevel@tonic-gate }
46540Sstevel@tonic-gate 
46550Sstevel@tonic-gate #endif
46560Sstevel@tonic-gate 
46579913SShantkumar.Hiremath@Sun.COM /* For MCG List search */
46589913SShantkumar.Hiremath@Sun.COM typedef struct ibcm_mcg_list_s {
46599913SShantkumar.Hiremath@Sun.COM 	struct ibcm_mcg_list_s	*ml_next;
46609913SShantkumar.Hiremath@Sun.COM 	ib_gid_t		ml_sgid;
46619913SShantkumar.Hiremath@Sun.COM 	ib_gid_t		ml_mgid;
46629913SShantkumar.Hiremath@Sun.COM 	ib_pkey_t		ml_pkey;
46639913SShantkumar.Hiremath@Sun.COM 	ib_qkey_t		ml_qkey;
46649913SShantkumar.Hiremath@Sun.COM 	uint_t			ml_refcnt;
46659913SShantkumar.Hiremath@Sun.COM 	uint8_t			ml_jstate;
46669913SShantkumar.Hiremath@Sun.COM } ibcm_mcg_list_t;
46679913SShantkumar.Hiremath@Sun.COM 
46689913SShantkumar.Hiremath@Sun.COM ibcm_mcg_list_t	*ibcm_mcglist = NULL;
46699913SShantkumar.Hiremath@Sun.COM 
46709913SShantkumar.Hiremath@Sun.COM _NOTE(MUTEX_PROTECTS_DATA(ibcm_mcglist_lock, ibcm_mcg_list_s))
46719913SShantkumar.Hiremath@Sun.COM _NOTE(MUTEX_PROTECTS_DATA(ibcm_mcglist_lock, ibcm_mcglist))
46729913SShantkumar.Hiremath@Sun.COM 
46730Sstevel@tonic-gate typedef struct ibcm_join_mcg_tqarg_s {
46740Sstevel@tonic-gate 	ib_gid_t		rgid;
46750Sstevel@tonic-gate 	ibt_mcg_attr_t		mcg_attr;
46760Sstevel@tonic-gate 	ibt_mcg_info_t		*mcg_infop;
46770Sstevel@tonic-gate 	ibt_mcg_handler_t	func;
46780Sstevel@tonic-gate 	void			*arg;
46790Sstevel@tonic-gate } ibcm_join_mcg_tqarg_t;
46800Sstevel@tonic-gate 
_NOTE(READ_ONLY_DATA (ibcm_join_mcg_tqarg_s))46810Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_join_mcg_tqarg_s))
46820Sstevel@tonic-gate 
46839913SShantkumar.Hiremath@Sun.COM void
46849913SShantkumar.Hiremath@Sun.COM ibcm_add_incr_mcg_entry(sa_mcmember_record_t *mcg_req,
46859913SShantkumar.Hiremath@Sun.COM     sa_mcmember_record_t *mcg_resp)
46869913SShantkumar.Hiremath@Sun.COM {
46879913SShantkumar.Hiremath@Sun.COM 	ibcm_mcg_list_t	*new = NULL;
46889913SShantkumar.Hiremath@Sun.COM 	ibcm_mcg_list_t	*head = NULL;
46899913SShantkumar.Hiremath@Sun.COM 
46909913SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: MGID %llX:%llX"
46919913SShantkumar.Hiremath@Sun.COM 	    "\n SGID %llX:%llX, JState %X)", mcg_req->MGID.gid_prefix,
46929913SShantkumar.Hiremath@Sun.COM 	    mcg_req->MGID.gid_guid, mcg_req->PortGID.gid_prefix,
46939913SShantkumar.Hiremath@Sun.COM 	    mcg_req->PortGID.gid_guid, mcg_req->JoinState);
46949913SShantkumar.Hiremath@Sun.COM 
46959913SShantkumar.Hiremath@Sun.COM 	mutex_enter(&ibcm_mcglist_lock);
46969913SShantkumar.Hiremath@Sun.COM 	head = ibcm_mcglist;
46979913SShantkumar.Hiremath@Sun.COM 
46989913SShantkumar.Hiremath@Sun.COM 	while (head != NULL) {
46999913SShantkumar.Hiremath@Sun.COM 		if ((head->ml_mgid.gid_guid == mcg_resp->MGID.gid_guid) &&
47009913SShantkumar.Hiremath@Sun.COM 		    (head->ml_mgid.gid_prefix == mcg_resp->MGID.gid_prefix) &&
47019913SShantkumar.Hiremath@Sun.COM 		    (head->ml_sgid.gid_guid == mcg_resp->PortGID.gid_guid)) {
47029913SShantkumar.Hiremath@Sun.COM 			/* Increment the count */
47039913SShantkumar.Hiremath@Sun.COM 			head->ml_refcnt++;
47049913SShantkumar.Hiremath@Sun.COM 			/* OR the join_state value, we need this during leave */
47059913SShantkumar.Hiremath@Sun.COM 			head->ml_jstate |= mcg_req->JoinState;
47069913SShantkumar.Hiremath@Sun.COM 
47079913SShantkumar.Hiremath@Sun.COM 			IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: Entry "
47089913SShantkumar.Hiremath@Sun.COM 			    "FOUND: refcnt %d JState %X", head->ml_refcnt,
47099913SShantkumar.Hiremath@Sun.COM 			    head->ml_jstate);
47109913SShantkumar.Hiremath@Sun.COM 
47119913SShantkumar.Hiremath@Sun.COM 			mutex_exit(&ibcm_mcglist_lock);
47129913SShantkumar.Hiremath@Sun.COM 			return;
47139913SShantkumar.Hiremath@Sun.COM 		}
47149913SShantkumar.Hiremath@Sun.COM 		head = head->ml_next;
47159913SShantkumar.Hiremath@Sun.COM 	}
47169913SShantkumar.Hiremath@Sun.COM 	mutex_exit(&ibcm_mcglist_lock);
47179913SShantkumar.Hiremath@Sun.COM 
47189913SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibcm_add_incr_mcg_entry: Create NEW Entry ");
47199913SShantkumar.Hiremath@Sun.COM 
47209913SShantkumar.Hiremath@Sun.COM 	/* If we are here, either list is empty or match couldn't be found */
47219913SShantkumar.Hiremath@Sun.COM 	new = kmem_zalloc(sizeof (ibcm_mcg_list_t), KM_SLEEP);
47229913SShantkumar.Hiremath@Sun.COM 
47239913SShantkumar.Hiremath@Sun.COM 	mutex_enter(&ibcm_mcglist_lock);
47249913SShantkumar.Hiremath@Sun.COM 	/* Initialize the fields */
47259913SShantkumar.Hiremath@Sun.COM 	new->ml_sgid = mcg_resp->PortGID;
47269913SShantkumar.Hiremath@Sun.COM 	new->ml_mgid = mcg_resp->MGID;
47279913SShantkumar.Hiremath@Sun.COM 	new->ml_qkey = mcg_req->Q_Key;
47289913SShantkumar.Hiremath@Sun.COM 	new->ml_pkey = mcg_req->P_Key;
47299913SShantkumar.Hiremath@Sun.COM 	new->ml_refcnt = 1; /* As this is the first entry */
47309913SShantkumar.Hiremath@Sun.COM 	new->ml_jstate = mcg_req->JoinState;
47319913SShantkumar.Hiremath@Sun.COM 	new->ml_next = NULL;
47329913SShantkumar.Hiremath@Sun.COM 
47339913SShantkumar.Hiremath@Sun.COM 	new->ml_next = ibcm_mcglist;
47349913SShantkumar.Hiremath@Sun.COM 	ibcm_mcglist = new;
47359913SShantkumar.Hiremath@Sun.COM 	mutex_exit(&ibcm_mcglist_lock);
47369913SShantkumar.Hiremath@Sun.COM }
47379913SShantkumar.Hiremath@Sun.COM 
47389913SShantkumar.Hiremath@Sun.COM /*
47399913SShantkumar.Hiremath@Sun.COM  * ibcm_del_decr_mcg_entry
47409913SShantkumar.Hiremath@Sun.COM  *
47419913SShantkumar.Hiremath@Sun.COM  * Return value:
47429913SShantkumar.Hiremath@Sun.COM  * IBCM_SUCCESS		Entry found and ref_cnt is now zero. So go-ahead and
47439913SShantkumar.Hiremath@Sun.COM  * 			leave the MCG group. The return arg *jstate will have
47449913SShantkumar.Hiremath@Sun.COM  * 			a valid join_state value that needed to be used by
47459913SShantkumar.Hiremath@Sun.COM  * 			xxx_leave_mcg().
47469913SShantkumar.Hiremath@Sun.COM  * IBCM_LOOKUP_EXISTS	Entry found and ref_cnt is decremented but is NOT zero.
47479913SShantkumar.Hiremath@Sun.COM  * 			So do not leave the MCG group yet.
47489913SShantkumar.Hiremath@Sun.COM  * IBCM_LOOKUP_FAIL	Entry is NOT found.
47499913SShantkumar.Hiremath@Sun.COM  */
47509913SShantkumar.Hiremath@Sun.COM ibcm_status_t
ibcm_del_decr_mcg_entry(sa_mcmember_record_t * mcg_req,uint8_t * jstate)47519913SShantkumar.Hiremath@Sun.COM ibcm_del_decr_mcg_entry(sa_mcmember_record_t *mcg_req, uint8_t *jstate)
47529913SShantkumar.Hiremath@Sun.COM {
47539913SShantkumar.Hiremath@Sun.COM 	ibcm_mcg_list_t	*head, *prev;
47549913SShantkumar.Hiremath@Sun.COM 
47559913SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibcm_del_decr_mcg_entry: MGID %llX:%llX"
47569913SShantkumar.Hiremath@Sun.COM 	    "\n SGID %llX:%llX, JState %X)", mcg_req->MGID.gid_prefix,
47579913SShantkumar.Hiremath@Sun.COM 	    mcg_req->MGID.gid_guid, mcg_req->PortGID.gid_prefix,
47589913SShantkumar.Hiremath@Sun.COM 	    mcg_req->PortGID.gid_guid, mcg_req->JoinState);
47599913SShantkumar.Hiremath@Sun.COM 
47609913SShantkumar.Hiremath@Sun.COM 	*jstate = 0;
47619913SShantkumar.Hiremath@Sun.COM 
47629913SShantkumar.Hiremath@Sun.COM 	mutex_enter(&ibcm_mcglist_lock);
47639913SShantkumar.Hiremath@Sun.COM 	head = ibcm_mcglist;
47649913SShantkumar.Hiremath@Sun.COM 	prev = NULL;
47659913SShantkumar.Hiremath@Sun.COM 
47669913SShantkumar.Hiremath@Sun.COM 	while (head != NULL) {
47679913SShantkumar.Hiremath@Sun.COM 		if ((head->ml_mgid.gid_guid == mcg_req->MGID.gid_guid) &&
47689913SShantkumar.Hiremath@Sun.COM 		    (head->ml_mgid.gid_prefix == mcg_req->MGID.gid_prefix) &&
47699913SShantkumar.Hiremath@Sun.COM 		    (head->ml_sgid.gid_guid == mcg_req->PortGID.gid_guid)) {
47709913SShantkumar.Hiremath@Sun.COM 			if (!(head->ml_jstate & mcg_req->JoinState)) {
47719913SShantkumar.Hiremath@Sun.COM 				IBTF_DPRINTF_L2(cmlog, "ibcm_del_decr_mcg_entry"
47729913SShantkumar.Hiremath@Sun.COM 				    ": JoinState mismatch %X %X)",
47739913SShantkumar.Hiremath@Sun.COM 				    head->ml_jstate, mcg_req->JoinState);
47749913SShantkumar.Hiremath@Sun.COM 			}
47759913SShantkumar.Hiremath@Sun.COM 			/* Decrement the count */
47769913SShantkumar.Hiremath@Sun.COM 			head->ml_refcnt--;
47779913SShantkumar.Hiremath@Sun.COM 
47789913SShantkumar.Hiremath@Sun.COM 			if (head->ml_refcnt == 0) {
47799913SShantkumar.Hiremath@Sun.COM 				*jstate = head->ml_jstate;
47809913SShantkumar.Hiremath@Sun.COM 
47819913SShantkumar.Hiremath@Sun.COM 				IBTF_DPRINTF_L3(cmlog, "ibcm_del_decr_mcg_entry"
47829913SShantkumar.Hiremath@Sun.COM 				    ": refcnt is ZERO, so delete the entry ");
47839913SShantkumar.Hiremath@Sun.COM 				if ((head == ibcm_mcglist) || (prev == NULL)) {
47849913SShantkumar.Hiremath@Sun.COM 					ibcm_mcglist = head->ml_next;
47859913SShantkumar.Hiremath@Sun.COM 				} else if (prev != NULL) {
47869913SShantkumar.Hiremath@Sun.COM 					prev->ml_next = head->ml_next;
47879913SShantkumar.Hiremath@Sun.COM 				}
47889913SShantkumar.Hiremath@Sun.COM 				mutex_exit(&ibcm_mcglist_lock);
47899913SShantkumar.Hiremath@Sun.COM 
47909913SShantkumar.Hiremath@Sun.COM 				kmem_free(head, sizeof (ibcm_mcg_list_t));
47919913SShantkumar.Hiremath@Sun.COM 				return (IBCM_SUCCESS);
47929913SShantkumar.Hiremath@Sun.COM 			}
47939913SShantkumar.Hiremath@Sun.COM 			mutex_exit(&ibcm_mcglist_lock);
47949913SShantkumar.Hiremath@Sun.COM 			return (IBCM_LOOKUP_EXISTS);
47959913SShantkumar.Hiremath@Sun.COM 		}
47969913SShantkumar.Hiremath@Sun.COM 		prev = head;
47979913SShantkumar.Hiremath@Sun.COM 		head = head->ml_next;
47989913SShantkumar.Hiremath@Sun.COM 	}
47999913SShantkumar.Hiremath@Sun.COM 	mutex_exit(&ibcm_mcglist_lock);
48009913SShantkumar.Hiremath@Sun.COM 
48019913SShantkumar.Hiremath@Sun.COM 	/*
48029913SShantkumar.Hiremath@Sun.COM 	 * If we are here, something went wrong, we don't have the entry
48039913SShantkumar.Hiremath@Sun.COM 	 * for that MCG being joined.
48049913SShantkumar.Hiremath@Sun.COM 	 */
48059913SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L2(cmlog, "ibcm_del_decr_mcg_entry: Match NOT "
48069913SShantkumar.Hiremath@Sun.COM 	    "Found ");
48079913SShantkumar.Hiremath@Sun.COM 
48089913SShantkumar.Hiremath@Sun.COM 	return (IBCM_LOOKUP_FAIL);
48099913SShantkumar.Hiremath@Sun.COM }
48109913SShantkumar.Hiremath@Sun.COM 
48119913SShantkumar.Hiremath@Sun.COM 
48120Sstevel@tonic-gate /*
48130Sstevel@tonic-gate  * Function:
48140Sstevel@tonic-gate  *	ibt_join_mcg
48150Sstevel@tonic-gate  * Input:
48160Sstevel@tonic-gate  *	rgid		The request GID that defines the HCA port from which a
48170Sstevel@tonic-gate  *			contact to SA Access is performed to add the specified
48180Sstevel@tonic-gate  *			endport GID ((mcg_attr->mc_pgid) to a multicast group.
48190Sstevel@tonic-gate  *			If mcg_attr->mc_pgid is null, then this (rgid) will be
48200Sstevel@tonic-gate  *			treated as endport GID that is to be added to the
48210Sstevel@tonic-gate  *			multicast group.
48220Sstevel@tonic-gate  *
48230Sstevel@tonic-gate  *	mcg_attr	A pointer to an ibt_mcg_attr_t structure that defines
48240Sstevel@tonic-gate  *			the attributes of the desired multicast group to be
48250Sstevel@tonic-gate  *			created or joined.
48260Sstevel@tonic-gate  *
48270Sstevel@tonic-gate  *	func		NULL or a pointer to a function to call when
48280Sstevel@tonic-gate  *			ibt_join_mcg() completes. If 'func' is not NULL then
48290Sstevel@tonic-gate  *			ibt_join_mcg() will return as soon as possible after
48300Sstevel@tonic-gate  *			initiating the multicast group join/create process.
48310Sstevel@tonic-gate  *			'func' is then called when the process completes.
48320Sstevel@tonic-gate  *
48330Sstevel@tonic-gate  *	arg		Argument to the 'func'.
48340Sstevel@tonic-gate  *
48350Sstevel@tonic-gate  * Output:
48360Sstevel@tonic-gate  *	mcg_info_p	A pointer to the ibt_mcg_info_t structure, allocated
48370Sstevel@tonic-gate  *			by the caller, where the attributes of the created or
48380Sstevel@tonic-gate  *			joined multicast group are copied.
48390Sstevel@tonic-gate  * Returns:
48400Sstevel@tonic-gate  *	IBT_SUCCESS
48410Sstevel@tonic-gate  *	IBT_INVALID_PARAM
48420Sstevel@tonic-gate  *	IBT_MCG_RECORDS_NOT_FOUND
48430Sstevel@tonic-gate  *	IBT_INSUFF_RESOURCE
48440Sstevel@tonic-gate  * Description:
48450Sstevel@tonic-gate  *	Join a multicast group.  The first full member "join" causes the MCG
48460Sstevel@tonic-gate  *	to be created.
48470Sstevel@tonic-gate  */
48480Sstevel@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)48490Sstevel@tonic-gate ibt_join_mcg(ib_gid_t rgid, ibt_mcg_attr_t *mcg_attr,
48500Sstevel@tonic-gate     ibt_mcg_info_t *mcg_info_p, ibt_mcg_handler_t func, void  *arg)
48510Sstevel@tonic-gate {
48520Sstevel@tonic-gate 	ibcm_join_mcg_tqarg_t	*mcg_tq;
48530Sstevel@tonic-gate 	int			flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
48540Sstevel@tonic-gate 
48550Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg(%llX:%llX, %p)", rgid.gid_prefix,
48560Sstevel@tonic-gate 	    rgid.gid_guid, mcg_attr);
48570Sstevel@tonic-gate 
48580Sstevel@tonic-gate 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
48590Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Request GID is required");
48600Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
48610Sstevel@tonic-gate 	}
48620Sstevel@tonic-gate 
48630Sstevel@tonic-gate 	if ((mcg_attr->mc_pkey == IB_PKEY_INVALID_LIMITED) ||
48640Sstevel@tonic-gate 	    (mcg_attr->mc_pkey == IB_PKEY_INVALID_FULL)) {
48650Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Invalid P_Key specified");
48660Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
48670Sstevel@tonic-gate 	}
48680Sstevel@tonic-gate 
48690Sstevel@tonic-gate 	if (mcg_attr->mc_join_state == 0) {
48700Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: JoinState not specified");
48710Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
48720Sstevel@tonic-gate 	}
48730Sstevel@tonic-gate 
48740Sstevel@tonic-gate 	if (mcg_info_p == NULL) {
48750Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: mcg_info_p is NULL");
48760Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
48770Sstevel@tonic-gate 	}
48780Sstevel@tonic-gate 
48790Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mcg_tq))
48800Sstevel@tonic-gate 
48810Sstevel@tonic-gate 	mcg_tq = kmem_alloc(sizeof (ibcm_join_mcg_tqarg_t), flag);
48820Sstevel@tonic-gate 	if (mcg_tq == NULL) {
48830Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: "
48840Sstevel@tonic-gate 		    "Unable to allocate memory for local usage.");
48850Sstevel@tonic-gate 		return (IBT_INSUFF_KERNEL_RESOURCE);
48860Sstevel@tonic-gate 	}
48870Sstevel@tonic-gate 
48880Sstevel@tonic-gate 	mcg_tq->rgid = rgid;
48890Sstevel@tonic-gate 	bcopy(mcg_attr, &mcg_tq->mcg_attr, sizeof (ibt_mcg_attr_t));
48900Sstevel@tonic-gate 	mcg_tq->mcg_infop = mcg_info_p;
48910Sstevel@tonic-gate 	mcg_tq->func = func;
48920Sstevel@tonic-gate 	mcg_tq->arg = arg;
48930Sstevel@tonic-gate 
48940Sstevel@tonic-gate 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mcg_tq))
48950Sstevel@tonic-gate 
48960Sstevel@tonic-gate 	if (func != NULL) {	/* Non-Blocking */
48970Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg: Non-Blocking Call");
48980Sstevel@tonic-gate 		if (taskq_dispatch(ibcm_taskq, ibcm_process_async_join_mcg,
48990Sstevel@tonic-gate 		    mcg_tq, TQ_NOSLEEP) == 0) {
49000Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Failed to "
49010Sstevel@tonic-gate 			    "Dispatch the TaskQ");
49020Sstevel@tonic-gate 			kmem_free(mcg_tq, sizeof (ibcm_join_mcg_tqarg_t));
49030Sstevel@tonic-gate 			return (IBT_INSUFF_KERNEL_RESOURCE);
49040Sstevel@tonic-gate 		} else
49050Sstevel@tonic-gate 			return (IBT_SUCCESS);
49060Sstevel@tonic-gate 	} else {		/* Blocking */
49070Sstevel@tonic-gate 		return (ibcm_process_join_mcg(mcg_tq));
49080Sstevel@tonic-gate 	}
49090Sstevel@tonic-gate }
49100Sstevel@tonic-gate 
49110Sstevel@tonic-gate static void
ibcm_process_async_join_mcg(void * tq_arg)49120Sstevel@tonic-gate ibcm_process_async_join_mcg(void *tq_arg)
49130Sstevel@tonic-gate {
49140Sstevel@tonic-gate 	(void) ibcm_process_join_mcg(tq_arg);
49150Sstevel@tonic-gate }
49160Sstevel@tonic-gate 
49170Sstevel@tonic-gate static ibt_status_t
ibcm_process_join_mcg(void * taskq_arg)49180Sstevel@tonic-gate ibcm_process_join_mcg(void *taskq_arg)
49190Sstevel@tonic-gate {
49200Sstevel@tonic-gate 	sa_mcmember_record_t	mcg_req;
49210Sstevel@tonic-gate 	sa_mcmember_record_t	*mcg_resp;
49220Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
49230Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
49240Sstevel@tonic-gate 	uint64_t		component_mask = 0;
49250Sstevel@tonic-gate 	ibt_status_t		retval;
49260Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hca_port;
49270Sstevel@tonic-gate 	uint_t			num_records;
49280Sstevel@tonic-gate 	size_t			length;
49290Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
49300Sstevel@tonic-gate 	ibcm_join_mcg_tqarg_t	*mcg_arg = (ibcm_join_mcg_tqarg_t *)taskq_arg;
49310Sstevel@tonic-gate 	ibt_mcg_info_t		*mcg_info_p = mcg_arg->mcg_infop;
49320Sstevel@tonic-gate 
49330Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg(%p)", mcg_arg);
49340Sstevel@tonic-gate 
49350Sstevel@tonic-gate 	retval = ibtl_cm_get_hca_port(mcg_arg->rgid, 0, &hca_port);
49360Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
49370Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: Failed to get "
49380Sstevel@tonic-gate 		    "port info from specified RGID: status = %d", retval);
49390Sstevel@tonic-gate 		goto ibcm_join_mcg_exit1;
49400Sstevel@tonic-gate 	}
49410Sstevel@tonic-gate 
49420Sstevel@tonic-gate 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
49430Sstevel@tonic-gate 
49440Sstevel@tonic-gate 	if ((mcg_arg->mcg_attr.mc_pgid.gid_prefix == 0) ||
49450Sstevel@tonic-gate 	    (mcg_arg->mcg_attr.mc_pgid.gid_guid == 0)) {
49460Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
49470Sstevel@tonic-gate 		    "Request GID is Port GID");
49480Sstevel@tonic-gate 		mcg_req.PortGID = mcg_arg->rgid;
49490Sstevel@tonic-gate 	} else {
49500Sstevel@tonic-gate 		mcg_req.PortGID = mcg_arg->mcg_attr.mc_pgid;
49510Sstevel@tonic-gate 	}
49520Sstevel@tonic-gate 	component_mask |= SA_MC_COMPMASK_PORTGID;
49530Sstevel@tonic-gate 
49540Sstevel@tonic-gate 	mcg_req.Q_Key = mcg_arg->mcg_attr.mc_qkey;
49550Sstevel@tonic-gate 	mcg_req.P_Key = mcg_arg->mcg_attr.mc_pkey;
49560Sstevel@tonic-gate 	mcg_req.JoinState = mcg_arg->mcg_attr.mc_join_state;
49570Sstevel@tonic-gate 	mcg_req.TClass = mcg_arg->mcg_attr.mc_tclass;
49580Sstevel@tonic-gate 	mcg_req.FlowLabel = mcg_arg->mcg_attr.mc_flow;
49590Sstevel@tonic-gate 	mcg_req.SL = mcg_arg->mcg_attr.mc_sl;
49600Sstevel@tonic-gate 
49610Sstevel@tonic-gate 	component_mask |= SA_MC_COMPMASK_QKEY | SA_MC_COMPMASK_PKEY |
49620Sstevel@tonic-gate 	    SA_MC_COMPMASK_JOINSTATE | SA_MC_COMPMASK_TCLASS |
49630Sstevel@tonic-gate 	    SA_MC_COMPMASK_FLOWLABEL | SA_MC_COMPMASK_SL;
49640Sstevel@tonic-gate 
49650Sstevel@tonic-gate 	/* If client has specified MGID, use it else SA will assign one. */
49660Sstevel@tonic-gate 	if ((mcg_arg->mcg_attr.mc_mgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
49670Sstevel@tonic-gate 		mcg_req.MGID = mcg_arg->mcg_attr.mc_mgid;
49680Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_MGID;
49690Sstevel@tonic-gate 	}
49700Sstevel@tonic-gate 
49719349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: ");
49729349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "PGID=%016llX:%016llX, ",
49739349SShantkumar.Hiremath@Sun.COM 	    mcg_req.PortGID.gid_prefix, mcg_req.PortGID.gid_guid);
49749349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "MGID=%016llX:%016llX",
49759349SShantkumar.Hiremath@Sun.COM 	    mcg_req.MGID.gid_prefix, mcg_req.MGID.gid_guid);
49769349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L3(cmlog, "JoinState = %X",
49779349SShantkumar.Hiremath@Sun.COM 	    mcg_arg->mcg_attr.mc_join_state);
49789349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L5(cmlog, "QKey %lX, PKey %lX",
49799349SShantkumar.Hiremath@Sun.COM 	    mcg_arg->mcg_attr.mc_qkey, mcg_arg->mcg_attr.mc_pkey);
49809349SShantkumar.Hiremath@Sun.COM 	IBTF_DPRINTF_L5(cmlog, "Scope %X, MLID %X",
49819349SShantkumar.Hiremath@Sun.COM 	    mcg_arg->mcg_attr.mc_scope, mcg_arg->mcg_attr.mc_mlid);
49820Sstevel@tonic-gate 
49830Sstevel@tonic-gate 	/* Is MTU specified. */
49840Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_mtu_req.r_mtu) {
49850Sstevel@tonic-gate 		mcg_req.MTU = mcg_arg->mcg_attr.mc_mtu_req.r_mtu;
49860Sstevel@tonic-gate 		mcg_req.MTUSelector = mcg_arg->mcg_attr.mc_mtu_req.r_selector;
49870Sstevel@tonic-gate 
49880Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_MTUSELECTOR |
49890Sstevel@tonic-gate 		    SA_MC_COMPMASK_MTU;
49900Sstevel@tonic-gate 	}
49910Sstevel@tonic-gate 
49920Sstevel@tonic-gate 	/* Is RATE specified. */
49930Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_rate_req.r_srate) {
49940Sstevel@tonic-gate 		mcg_req.Rate = mcg_arg->mcg_attr.mc_rate_req.r_srate;
49950Sstevel@tonic-gate 		mcg_req.RateSelector =
49960Sstevel@tonic-gate 		    mcg_arg->mcg_attr.mc_rate_req.r_selector;
49970Sstevel@tonic-gate 
49980Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_RATESELECTOR |
49990Sstevel@tonic-gate 		    SA_MC_COMPMASK_RATE;
50000Sstevel@tonic-gate 	}
50010Sstevel@tonic-gate 
50020Sstevel@tonic-gate 	/* Is Packet Life Time specified. */
50030Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_pkt_lt_req.p_pkt_lt) {
50040Sstevel@tonic-gate 		mcg_req.Rate = mcg_arg->mcg_attr.mc_pkt_lt_req.p_pkt_lt;
50050Sstevel@tonic-gate 		mcg_req.RateSelector =
50060Sstevel@tonic-gate 		    mcg_arg->mcg_attr.mc_pkt_lt_req.p_selector;
50070Sstevel@tonic-gate 
50080Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_PKTLTSELECTOR |
50090Sstevel@tonic-gate 		    SA_MC_COMPMASK_PKTLT;
50100Sstevel@tonic-gate 	}
50110Sstevel@tonic-gate 
50120Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_hop) {
50130Sstevel@tonic-gate 		mcg_req.HopLimit = mcg_arg->mcg_attr.mc_hop;
50140Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_HOPLIMIT;
50150Sstevel@tonic-gate 	}
50160Sstevel@tonic-gate 
50170Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_scope) {
50180Sstevel@tonic-gate 		mcg_req.Scope = mcg_arg->mcg_attr.mc_scope;
50190Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_SCOPE;
50200Sstevel@tonic-gate 	}
50210Sstevel@tonic-gate 
50220Sstevel@tonic-gate 	if (mcg_arg->mcg_attr.mc_mlid) {
50230Sstevel@tonic-gate 		mcg_req.MLID = mcg_arg->mcg_attr.mc_mlid;
50240Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_MLID;
50250Sstevel@tonic-gate 	}
50260Sstevel@tonic-gate 
50270Sstevel@tonic-gate 	/* Get SA Access Handle. */
50280Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(hca_port.hp_hca_guid);
50290Sstevel@tonic-gate 	if (hcap == NULL) {
50300Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: NO HCA found");
50310Sstevel@tonic-gate 
50320Sstevel@tonic-gate 		retval = IBT_HCA_BUSY_DETACHING;
50330Sstevel@tonic-gate 		goto ibcm_join_mcg_exit1;
50340Sstevel@tonic-gate 	}
50350Sstevel@tonic-gate 
50360Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, hca_port.hp_port);
50370Sstevel@tonic-gate 	if (saa_handle == NULL) {
50380Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: SA Handle NULL");
50390Sstevel@tonic-gate 
50400Sstevel@tonic-gate 		retval = IBT_HCA_PORT_NOT_ACTIVE;
50410Sstevel@tonic-gate 		goto ibcm_join_mcg_exit;
50420Sstevel@tonic-gate 	}
50430Sstevel@tonic-gate 
50440Sstevel@tonic-gate 	if ((mcg_arg->mcg_attr.mc_pgid.gid_prefix != 0) &&
50450Sstevel@tonic-gate 	    (mcg_arg->mcg_attr.mc_pgid.gid_guid != 0)) {
50460Sstevel@tonic-gate 		retval = ibtl_cm_get_hca_port(mcg_arg->mcg_attr.mc_pgid, 0,
50470Sstevel@tonic-gate 		    &hca_port);
50480Sstevel@tonic-gate 		if (retval != IBT_SUCCESS) {
50490Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: Failed "
50500Sstevel@tonic-gate 			    "to get PortInfo of specified PGID: status = %d",
50510Sstevel@tonic-gate 			    retval);
50520Sstevel@tonic-gate 			goto ibcm_join_mcg_exit1;
50530Sstevel@tonic-gate 		}
50540Sstevel@tonic-gate 	}
50550Sstevel@tonic-gate 
50560Sstevel@tonic-gate 	/* Contact SA Access */
50570Sstevel@tonic-gate 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
50580Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_UPDATE;
50590Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
50600Sstevel@tonic-gate 	access_args.sq_template = &mcg_req;
50610Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
50620Sstevel@tonic-gate 	access_args.sq_callback = NULL;
50630Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
50640Sstevel@tonic-gate 
50650Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
50660Sstevel@tonic-gate 	    (void **)&mcg_resp);
50670Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
50680Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: "
50690Sstevel@tonic-gate 		    "SA Access Failed");
50700Sstevel@tonic-gate 		goto ibcm_join_mcg_exit;
50710Sstevel@tonic-gate 	}
50720Sstevel@tonic-gate 
50730Sstevel@tonic-gate 	num_records = length/sizeof (sa_mcmember_record_t);
50740Sstevel@tonic-gate 
50750Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_join_mcg: "
50760Sstevel@tonic-gate 	    "Found %d MCMember Records", num_records);
50770Sstevel@tonic-gate 
50780Sstevel@tonic-gate 	/* Validate the returned number of records. */
50790Sstevel@tonic-gate 	if ((mcg_resp != NULL) && (num_records > 0)) {
50800Sstevel@tonic-gate 		/* Update the return values. */
50810Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_dgid = mcg_resp->MGID;
50820Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_sgid = mcg_resp->PortGID;
50830Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_srate = mcg_resp->Rate;
50840Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_srvl = mcg_resp->SL;
50850Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_flow = mcg_resp->FlowLabel;
50860Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_tclass = mcg_resp->TClass;
50870Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_hop = mcg_resp->HopLimit;
50880Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_send_grh = B_TRUE;
50890Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_dlid = mcg_resp->MLID;
50900Sstevel@tonic-gate 		mcg_info_p->mc_mtu = mcg_resp->MTU;
50910Sstevel@tonic-gate 		mcg_info_p->mc_qkey = mcg_resp->Q_Key;
50920Sstevel@tonic-gate 
50930Sstevel@tonic-gate 		retval = ibt_pkey2index_byguid(hca_port.hp_hca_guid,
50940Sstevel@tonic-gate 		    hca_port.hp_port, mcg_resp->P_Key, &mcg_info_p->mc_pkey_ix);
50950Sstevel@tonic-gate 		if (retval != IBT_SUCCESS) {
50960Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
50970Sstevel@tonic-gate 			    "Pkey2Index Conversion failed<%d>", retval);
50980Sstevel@tonic-gate 			mcg_info_p->mc_pkey_ix = 0;
50990Sstevel@tonic-gate 		}
51000Sstevel@tonic-gate 
51010Sstevel@tonic-gate 		mcg_info_p->mc_scope = mcg_resp->Scope;
51020Sstevel@tonic-gate 		mcg_info_p->mc_pkt_lt = mcg_resp->PacketLifeTime;
51030Sstevel@tonic-gate 
51040Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_port_num = hca_port.hp_port;
51050Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_sgid_ix = hca_port.hp_sgid_ix;
51060Sstevel@tonic-gate 		mcg_info_p->mc_adds_vect.av_src_path = 0;
51070Sstevel@tonic-gate 
51089913SShantkumar.Hiremath@Sun.COM 		/* Add or Incr the matching MCG entry. */
51099913SShantkumar.Hiremath@Sun.COM 		ibcm_add_incr_mcg_entry(&mcg_req, mcg_resp);
51100Sstevel@tonic-gate 		/* Deallocate the memory allocated by SA for mcg_resp. */
51110Sstevel@tonic-gate 		kmem_free(mcg_resp, length);
51129913SShantkumar.Hiremath@Sun.COM 
51130Sstevel@tonic-gate 		retval = IBT_SUCCESS;
51140Sstevel@tonic-gate 	} else {
51150Sstevel@tonic-gate 		retval = IBT_MCG_RECORDS_NOT_FOUND;
51160Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
51170Sstevel@tonic-gate 		    "MCG RECORDS NOT FOUND");
51180Sstevel@tonic-gate 	}
51190Sstevel@tonic-gate 
51200Sstevel@tonic-gate ibcm_join_mcg_exit:
51210Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
51220Sstevel@tonic-gate 
51230Sstevel@tonic-gate ibcm_join_mcg_exit1:
51240Sstevel@tonic-gate 	if (mcg_arg->func)
51250Sstevel@tonic-gate 		(*(mcg_arg->func))(mcg_arg->arg, retval, mcg_info_p);
51260Sstevel@tonic-gate 
51270Sstevel@tonic-gate 	kmem_free(mcg_arg, sizeof (ibcm_join_mcg_tqarg_t));
51280Sstevel@tonic-gate 
51290Sstevel@tonic-gate 	return (retval);
51300Sstevel@tonic-gate }
51310Sstevel@tonic-gate 
51320Sstevel@tonic-gate 
51330Sstevel@tonic-gate /*
51340Sstevel@tonic-gate  * Function:
51350Sstevel@tonic-gate  *	ibt_leave_mcg
51360Sstevel@tonic-gate  * Input:
51370Sstevel@tonic-gate  *	rgid		The request GID that defines the HCA port upon which
51380Sstevel@tonic-gate  *			to send the request to the Subnet Administrator, to
51390Sstevel@tonic-gate  *			remove the specified port (port_gid) from the multicast
51400Sstevel@tonic-gate  *			group.  If 'port_gid' is the Reserved GID (i.e.
51410Sstevel@tonic-gate  *			port_gid.gid_prefix = 0 and port_gid.gid_guid = 0),
51420Sstevel@tonic-gate  *			then the end-port associated with 'rgid' is removed
51430Sstevel@tonic-gate  *			from the multicast group.
51440Sstevel@tonic-gate  *
51450Sstevel@tonic-gate  *	mc_gid		A multicast group GID as returned from ibt_join_mcg()
51460Sstevel@tonic-gate  *			call.  This is optional, if not specified (i.e.
51470Sstevel@tonic-gate  *			mc_gid.gid_prefix has 0xFF in its upper 8 bits to
51480Sstevel@tonic-gate  *			identify this as being a multicast GID), then the
51490Sstevel@tonic-gate  *			port is removed from all the multicast groups of
51500Sstevel@tonic-gate  *			which it is a member.
51510Sstevel@tonic-gate  *
51520Sstevel@tonic-gate  *	port_gid	This is optional, if not the Reserved GID (gid_prefix
51530Sstevel@tonic-gate  *			and gid_guid not equal to 0), then this specifies the
51540Sstevel@tonic-gate  *			endport GID of the multicast group member being deleted
51550Sstevel@tonic-gate  *			from the group. If it is the Reserved GID (gid_prefix
51560Sstevel@tonic-gate  *			and gid_guid equal to 0) then the member endport GID is
51570Sstevel@tonic-gate  *			determined from 'rgid'.
51580Sstevel@tonic-gate  *
51590Sstevel@tonic-gate  *	mc_join_state	The Join State attribute used when the group was joined
51600Sstevel@tonic-gate  *			using ibt_join_mcg(). This Join State component must
51610Sstevel@tonic-gate  *			contains at least one bit set to 1 in the same position
51620Sstevel@tonic-gate  *			as that used during ibt_join_mcg(). i.e. the logical
51630Sstevel@tonic-gate  *			AND of the two JoinState components is not all zeros.
51640Sstevel@tonic-gate  *			This Join State component must not have some bits set
51650Sstevel@tonic-gate  *			which are not set using ibt_join_mcg().
51660Sstevel@tonic-gate  * Output:
51670Sstevel@tonic-gate  *	None.
51680Sstevel@tonic-gate  * Returns:
51690Sstevel@tonic-gate  *	IBT_SUCCESS
51700Sstevel@tonic-gate  *	IBT_INVALID_PARAM
51710Sstevel@tonic-gate  *	IBT_MC_GROUP_INVALID
51720Sstevel@tonic-gate  *	IBT_INSUFF_RESOURCE
51730Sstevel@tonic-gate  * Description:
51740Sstevel@tonic-gate  *	The port associated with the port GID shall be removed from the
51750Sstevel@tonic-gate  *	multicast group specified by MGID (mc_gid) or from all the multicast
51760Sstevel@tonic-gate  *	groups of which it is a member if the MGID (mc_gid) is not specified.
51770Sstevel@tonic-gate  *
51780Sstevel@tonic-gate  *	The last full member to leave causes the destruction of the Multicast
51790Sstevel@tonic-gate  *	Group.
51800Sstevel@tonic-gate  */
51810Sstevel@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)51820Sstevel@tonic-gate ibt_leave_mcg(ib_gid_t rgid, ib_gid_t mc_gid, ib_gid_t port_gid,
51830Sstevel@tonic-gate     uint8_t mc_join_state)
51840Sstevel@tonic-gate {
51850Sstevel@tonic-gate 	sa_mcmember_record_t	mcg_req;
51860Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
51870Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
51880Sstevel@tonic-gate 	uint64_t		component_mask = 0;
51890Sstevel@tonic-gate 	int			sa_retval;
51900Sstevel@tonic-gate 	ibt_status_t		retval;
51919913SShantkumar.Hiremath@Sun.COM 	ibcm_status_t		ret;
51920Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hca_port;
51930Sstevel@tonic-gate 	size_t			length;
51940Sstevel@tonic-gate 	void			*results_p;
51950Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
51969913SShantkumar.Hiremath@Sun.COM 	uint8_t			jstate = 0;
51970Sstevel@tonic-gate 
51980Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg(%llX:%llX, %llX:%llX)",
51990Sstevel@tonic-gate 	    rgid.gid_prefix, rgid.gid_guid, mc_gid.gid_prefix, mc_gid.gid_guid);
52000Sstevel@tonic-gate 
52010Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg(%llX:%llX, 0x%X)",
52020Sstevel@tonic-gate 	    port_gid.gid_prefix, port_gid.gid_guid, mc_join_state);
52030Sstevel@tonic-gate 
52040Sstevel@tonic-gate 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
52050Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: RequestGID is required");
52060Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
52070Sstevel@tonic-gate 	}
52080Sstevel@tonic-gate 
52090Sstevel@tonic-gate 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
52100Sstevel@tonic-gate 
52110Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: MGID: %llX%llX",
52120Sstevel@tonic-gate 	    mc_gid.gid_prefix, mc_gid.gid_guid);
52130Sstevel@tonic-gate 
52140Sstevel@tonic-gate 	/* Validate MGID */
52150Sstevel@tonic-gate 	if ((mc_gid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
52160Sstevel@tonic-gate 		mcg_req.MGID = mc_gid;
52170Sstevel@tonic-gate 		component_mask |= SA_MC_COMPMASK_MGID;
52180Sstevel@tonic-gate 	} else if ((mc_gid.gid_prefix != 0) || (mc_gid.gid_guid != 0)) {
52190Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Invalid MGID specified");
52200Sstevel@tonic-gate 		return (IBT_MC_MGID_INVALID);
52210Sstevel@tonic-gate 	}
52220Sstevel@tonic-gate 
52230Sstevel@tonic-gate 	if ((port_gid.gid_prefix == 0) || (port_gid.gid_guid == 0)) {
52240Sstevel@tonic-gate 		mcg_req.PortGID = rgid;
52250Sstevel@tonic-gate 	} else {
52260Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Performing PROXY Leave");
52270Sstevel@tonic-gate 		mcg_req.PortGID = port_gid;
52280Sstevel@tonic-gate 	}
52290Sstevel@tonic-gate 	component_mask |= SA_MC_COMPMASK_PORTGID;
52300Sstevel@tonic-gate 
52310Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Port GID <%llX:%llX>",
52320Sstevel@tonic-gate 	    mcg_req.PortGID.gid_prefix, mcg_req.PortGID.gid_guid);
52330Sstevel@tonic-gate 
52340Sstevel@tonic-gate 	/* Join State */
52350Sstevel@tonic-gate 	mcg_req.JoinState = mc_join_state;
52360Sstevel@tonic-gate 	component_mask |= SA_MC_COMPMASK_JOINSTATE;
52370Sstevel@tonic-gate 
52389913SShantkumar.Hiremath@Sun.COM 	ret = ibcm_del_decr_mcg_entry(&mcg_req, &jstate);
52399913SShantkumar.Hiremath@Sun.COM 	if (ret == IBCM_LOOKUP_EXISTS) {
52409913SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Multiple JoinMCG record "
52419913SShantkumar.Hiremath@Sun.COM 		    " still exists, we shall leave for last leave_mcg call");
52429913SShantkumar.Hiremath@Sun.COM 		return (IBT_SUCCESS);
52439913SShantkumar.Hiremath@Sun.COM 	} else if (ret == IBCM_LOOKUP_FAIL) {
52449913SShantkumar.Hiremath@Sun.COM 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: No Record found, "
52459913SShantkumar.Hiremath@Sun.COM 		    "continue with leave_mcg call");
52469913SShantkumar.Hiremath@Sun.COM 	} else if ((ret == IBCM_SUCCESS) && (jstate != 0)) {
52479913SShantkumar.Hiremath@Sun.COM 		/*
52489913SShantkumar.Hiremath@Sun.COM 		 * Update with cached "jstate", as this will be OR'ed of
52499913SShantkumar.Hiremath@Sun.COM 		 * all ibt_join_mcg() calls for this record.
52509913SShantkumar.Hiremath@Sun.COM 		 */
52519913SShantkumar.Hiremath@Sun.COM 		mcg_req.JoinState = jstate;
52529913SShantkumar.Hiremath@Sun.COM 	}
52539913SShantkumar.Hiremath@Sun.COM 
52540Sstevel@tonic-gate 	retval = ibtl_cm_get_hca_port(rgid, 0, &hca_port);
52550Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
52560Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: Failed to get port info "
52570Sstevel@tonic-gate 		    "from specified RGID : status = %d", retval);
52580Sstevel@tonic-gate 		return (retval);
52590Sstevel@tonic-gate 	}
52600Sstevel@tonic-gate 
52610Sstevel@tonic-gate 	/* Get SA Access Handle. */
52620Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(hca_port.hp_hca_guid);
52630Sstevel@tonic-gate 	if (hcap == NULL) {
52640Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: "
52650Sstevel@tonic-gate 		    "NO HCA found");
52660Sstevel@tonic-gate 		return (IBT_HCA_BUSY_DETACHING);
52670Sstevel@tonic-gate 	}
52680Sstevel@tonic-gate 
52690Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, hca_port.hp_port);
52700Sstevel@tonic-gate 	if (saa_handle == NULL) {
52710Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: saa_handle is NULL");
52720Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
52730Sstevel@tonic-gate 		return (IBT_HCA_PORT_NOT_ACTIVE);
52740Sstevel@tonic-gate 	}
52750Sstevel@tonic-gate 
52760Sstevel@tonic-gate 	/* Contact SA Access */
52770Sstevel@tonic-gate 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
52780Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_DELETE;
52790Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
52800Sstevel@tonic-gate 	access_args.sq_template = &mcg_req;
52810Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
52820Sstevel@tonic-gate 	access_args.sq_callback = NULL;
52830Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
52840Sstevel@tonic-gate 
52850Sstevel@tonic-gate 	ibcm_sa_access_enter();
52860Sstevel@tonic-gate 
52870Sstevel@tonic-gate 	sa_retval = ibmf_sa_access(saa_handle, &access_args, 0, &length,
52880Sstevel@tonic-gate 	    &results_p);
52890Sstevel@tonic-gate 	if (sa_retval != IBMF_SUCCESS) {
52900Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: SA access Failed: %d",
52910Sstevel@tonic-gate 		    sa_retval);
52920Sstevel@tonic-gate 		(void) ibcm_ibmf_analyze_error(sa_retval);
52930Sstevel@tonic-gate 		retval = IBT_MC_GROUP_INVALID;
52940Sstevel@tonic-gate 	}
52950Sstevel@tonic-gate 
52960Sstevel@tonic-gate 	ibcm_sa_access_exit();
52970Sstevel@tonic-gate 
52980Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
52990Sstevel@tonic-gate 
53000Sstevel@tonic-gate 	return (retval);
53010Sstevel@tonic-gate }
53020Sstevel@tonic-gate 
53030Sstevel@tonic-gate 
53040Sstevel@tonic-gate /*
53050Sstevel@tonic-gate  * Function:
53060Sstevel@tonic-gate  *	ibt_query_mcg
53070Sstevel@tonic-gate  * Input:
53080Sstevel@tonic-gate  *	rgid		The request GID that defines the HCA port upon which
53090Sstevel@tonic-gate  *			to send the request to the Subnet Administrator, to
53100Sstevel@tonic-gate  *			retrieve Multicast Records matching attributes as
53110Sstevel@tonic-gate  *			specified through 'mcg_attr' argument.
53120Sstevel@tonic-gate  *
53130Sstevel@tonic-gate  *	mcg_attr	NULL or a pointer to an ibt_mcg_attr_t structure that
53140Sstevel@tonic-gate  *			specifies MCG attributes that are to be matched.
53150Sstevel@tonic-gate  *			Attributes that are not required can be wild carded
53160Sstevel@tonic-gate  *			by specifying as '0'.
53170Sstevel@tonic-gate  *
53180Sstevel@tonic-gate  *	mcgs_max_num	The maximum number of matching multicast groups to
53190Sstevel@tonic-gate  *			return.  If zero, then all available matching multicast
53200Sstevel@tonic-gate  *			groups are returned.
53210Sstevel@tonic-gate  * Output:
53220Sstevel@tonic-gate  *	mcgs_info_p	The address of an ibt_mcg_info_t pointer, where
53230Sstevel@tonic-gate  *			multicast group information is returned. The actual
53240Sstevel@tonic-gate  *			number of entries filled in the array is returned in
53250Sstevel@tonic-gate  *			entries_p.
53260Sstevel@tonic-gate  *
53270Sstevel@tonic-gate  *	entries_p	The number of ibt_mcg_attr_t entries returned.
53280Sstevel@tonic-gate  * Returns:
53290Sstevel@tonic-gate  *	IBT_SUCCESS
53300Sstevel@tonic-gate  *	IBT_INVALID_PARAM
53310Sstevel@tonic-gate  *	IBT_MCG_RECORDS_NOT_FOUND
53320Sstevel@tonic-gate  * Description:
53330Sstevel@tonic-gate  *	Request information on multicast groups that match the parameters
53340Sstevel@tonic-gate  *	specified in mcg_attr. Information on each multicast group is returned
53350Sstevel@tonic-gate  *	to the caller in the form of an array of ibt_mcg_info_t.
53360Sstevel@tonic-gate  *	ibt_query_mcg() allocates the memory for this array and returns a
53370Sstevel@tonic-gate  *	pointer to the array (mcgs_p) and the number of entries in the array
53380Sstevel@tonic-gate  *	(entries_p). This memory should be freed by the client using
53390Sstevel@tonic-gate  *	ibt_free_mcg_info().
53400Sstevel@tonic-gate  */
53410Sstevel@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)53420Sstevel@tonic-gate ibt_query_mcg(ib_gid_t rgid, ibt_mcg_attr_t *mcg_attr, uint_t mcgs_max_num,
53430Sstevel@tonic-gate     ibt_mcg_info_t **mcgs_info_p, uint_t *entries_p)
53440Sstevel@tonic-gate {
53450Sstevel@tonic-gate 	sa_mcmember_record_t	mcg_req;
53460Sstevel@tonic-gate 	sa_mcmember_record_t	*mcg_resp;
53470Sstevel@tonic-gate 	ibt_mcg_info_t		*mcg_infop;
53480Sstevel@tonic-gate 	ibmf_saa_access_args_t	access_args;
53490Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
53500Sstevel@tonic-gate 	uint64_t		component_mask = 0;
53510Sstevel@tonic-gate 	ibt_status_t		retval;
53520Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hport;
53530Sstevel@tonic-gate 	uint_t			num_records;
53540Sstevel@tonic-gate 	size_t			length;
53550Sstevel@tonic-gate 	void			*results_p;
53560Sstevel@tonic-gate 	ib_gid_t		port_gid;
53570Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
53580Sstevel@tonic-gate 
53590Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg(%p, %d)", mcg_attr, mcgs_max_num);
53600Sstevel@tonic-gate 
53610Sstevel@tonic-gate 	if ((entries_p == NULL) || (mcgs_info_p == NULL)) {
53620Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: "
53630Sstevel@tonic-gate 		    "entries_p or mcgs_info_p is NULL");
53640Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
53650Sstevel@tonic-gate 	}
53660Sstevel@tonic-gate 
53670Sstevel@tonic-gate 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
53680Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: RequestGID is required");
53690Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
53700Sstevel@tonic-gate 	}
53710Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: Request GID <%llX:%llX>",
53720Sstevel@tonic-gate 	    rgid.gid_prefix, rgid.gid_guid);
53730Sstevel@tonic-gate 
53740Sstevel@tonic-gate 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
53750Sstevel@tonic-gate 	port_gid.gid_prefix = port_gid.gid_guid = 0;
53760Sstevel@tonic-gate 
53770Sstevel@tonic-gate 	if (mcg_attr != NULL) {
53780Sstevel@tonic-gate 		port_gid = mcg_attr->mc_pgid;
53790Sstevel@tonic-gate 
53800Sstevel@tonic-gate 		if ((port_gid.gid_prefix != 0) && (port_gid.gid_guid != 0)) {
53810Sstevel@tonic-gate 			mcg_req.PortGID = mcg_attr->mc_pgid;
53820Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_PORTGID;
53830Sstevel@tonic-gate 
53840Sstevel@tonic-gate 			IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: PGID %llX:%llX",
53850Sstevel@tonic-gate 			    port_gid.gid_prefix, port_gid.gid_guid);
53860Sstevel@tonic-gate 		}
53870Sstevel@tonic-gate 
53880Sstevel@tonic-gate 		/* Is Q_Key specified. */
53890Sstevel@tonic-gate 		if (mcg_attr->mc_qkey != 0) {
53900Sstevel@tonic-gate 			mcg_req.Q_Key = mcg_attr->mc_qkey;
53910Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_QKEY;
53920Sstevel@tonic-gate 		}
53930Sstevel@tonic-gate 
53940Sstevel@tonic-gate 		/* Is P_Key specified. */
53950Sstevel@tonic-gate 		if (mcg_attr->mc_pkey != 0) {
53960Sstevel@tonic-gate 			mcg_req.P_Key = mcg_attr->mc_pkey;
53970Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_PKEY;
53980Sstevel@tonic-gate 		}
53990Sstevel@tonic-gate 
54000Sstevel@tonic-gate 		/* Is MGID specified. */
54010Sstevel@tonic-gate 		if ((mcg_attr->mc_mgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
54020Sstevel@tonic-gate 			mcg_req.MGID = mcg_attr->mc_mgid;
54030Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_MGID;
54040Sstevel@tonic-gate 		}
54050Sstevel@tonic-gate 
54060Sstevel@tonic-gate 		/* Is MTU specified. */
54070Sstevel@tonic-gate 		if (mcg_attr->mc_mtu_req.r_mtu) {
54080Sstevel@tonic-gate 			mcg_req.MTU = mcg_attr->mc_mtu_req.r_mtu;
54090Sstevel@tonic-gate 			mcg_req.MTUSelector = mcg_attr->mc_mtu_req.r_selector;
54100Sstevel@tonic-gate 
54110Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_MTUSELECTOR |
54120Sstevel@tonic-gate 			    SA_MC_COMPMASK_MTU;
54130Sstevel@tonic-gate 		}
54140Sstevel@tonic-gate 
54150Sstevel@tonic-gate 		if (mcg_attr->mc_tclass) {
54160Sstevel@tonic-gate 			mcg_req.TClass = mcg_attr->mc_tclass;
54170Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_TCLASS;
54180Sstevel@tonic-gate 		}
54190Sstevel@tonic-gate 
54200Sstevel@tonic-gate 		/* Is RATE specified. */
54210Sstevel@tonic-gate 		if (mcg_attr->mc_rate_req.r_srate) {
54220Sstevel@tonic-gate 			mcg_req.Rate = mcg_attr->mc_rate_req.r_srate;
54230Sstevel@tonic-gate 			mcg_req.RateSelector = mcg_attr->mc_rate_req.r_selector;
54240Sstevel@tonic-gate 
54250Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_RATESELECTOR |
54260Sstevel@tonic-gate 			    SA_MC_COMPMASK_RATE;
54270Sstevel@tonic-gate 		}
54280Sstevel@tonic-gate 
54290Sstevel@tonic-gate 		/* Is Packet Life Time specified. */
54300Sstevel@tonic-gate 		if (mcg_attr->mc_pkt_lt_req.p_pkt_lt) {
54310Sstevel@tonic-gate 			mcg_req.Rate = mcg_attr->mc_pkt_lt_req.p_pkt_lt;
54320Sstevel@tonic-gate 			mcg_req.RateSelector =
54330Sstevel@tonic-gate 			    mcg_attr->mc_pkt_lt_req.p_selector;
54340Sstevel@tonic-gate 
54350Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_PKTLTSELECTOR |
54360Sstevel@tonic-gate 			    SA_MC_COMPMASK_PKTLT;
54370Sstevel@tonic-gate 		}
54380Sstevel@tonic-gate 
54390Sstevel@tonic-gate 		if (mcg_attr->mc_hop) {
54400Sstevel@tonic-gate 			mcg_req.HopLimit = mcg_attr->mc_hop;
54410Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_HOPLIMIT;
54420Sstevel@tonic-gate 		}
54430Sstevel@tonic-gate 
54440Sstevel@tonic-gate 		if (mcg_attr->mc_flow) {
54450Sstevel@tonic-gate 			mcg_req.FlowLabel = mcg_attr->mc_flow;
54460Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_FLOWLABEL;
54470Sstevel@tonic-gate 		}
54480Sstevel@tonic-gate 
54490Sstevel@tonic-gate 		if (mcg_attr->mc_sl) {
54500Sstevel@tonic-gate 			mcg_req.SL = mcg_attr->mc_sl;
54510Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_SL;
54520Sstevel@tonic-gate 		}
54530Sstevel@tonic-gate 
54540Sstevel@tonic-gate 		if (mcg_attr->mc_scope) {
54550Sstevel@tonic-gate 			mcg_req.Scope = mcg_attr->mc_scope;
54560Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_SCOPE;
54570Sstevel@tonic-gate 		}
54580Sstevel@tonic-gate 
54590Sstevel@tonic-gate 		if (mcg_attr->mc_join_state) {
54600Sstevel@tonic-gate 			mcg_req.JoinState = mcg_attr->mc_join_state;
54610Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_JOINSTATE;
54620Sstevel@tonic-gate 		}
54630Sstevel@tonic-gate 
54640Sstevel@tonic-gate 		if (mcg_attr->mc_mlid) {
54650Sstevel@tonic-gate 			mcg_req.MLID = mcg_attr->mc_mlid;
54660Sstevel@tonic-gate 			component_mask |= SA_MC_COMPMASK_MLID;
54670Sstevel@tonic-gate 		}
54680Sstevel@tonic-gate 	}
54690Sstevel@tonic-gate 
54700Sstevel@tonic-gate 	retval = ibtl_cm_get_hca_port(rgid, 0, &hport);
54710Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
54720Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: Failed to get port info "
54730Sstevel@tonic-gate 		    "from specified RGID : status = %d", retval);
54740Sstevel@tonic-gate 		return (retval);
54750Sstevel@tonic-gate 	}
54760Sstevel@tonic-gate 
54770Sstevel@tonic-gate 	/* Get SA Access Handle. */
54780Sstevel@tonic-gate 	hcap = ibcm_find_hca_entry(hport.hp_hca_guid);
54790Sstevel@tonic-gate 	if (hcap == NULL) {
54800Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: NO HCA found");
54810Sstevel@tonic-gate 		return (IBT_HCA_BUSY_DETACHING);
54820Sstevel@tonic-gate 	}
54830Sstevel@tonic-gate 
54840Sstevel@tonic-gate 	saa_handle = ibcm_get_saa_handle(hcap, hport.hp_port);
54850Sstevel@tonic-gate 	if (saa_handle == NULL) {
54860Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: saa_handle is NULL");
54870Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
54880Sstevel@tonic-gate 		return (IBT_HCA_PORT_NOT_ACTIVE);
54890Sstevel@tonic-gate 	}
54900Sstevel@tonic-gate 
54910Sstevel@tonic-gate 	/* Contact SA Access */
54920Sstevel@tonic-gate 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
54930Sstevel@tonic-gate 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
54940Sstevel@tonic-gate 	access_args.sq_component_mask = component_mask;
54950Sstevel@tonic-gate 	access_args.sq_template = &mcg_req;
54960Sstevel@tonic-gate 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
54970Sstevel@tonic-gate 	access_args.sq_callback = NULL;
54980Sstevel@tonic-gate 	access_args.sq_callback_arg = NULL;
54990Sstevel@tonic-gate 
55000Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
55010Sstevel@tonic-gate 	    &results_p);
55020Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
55030Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: SA access Failed");
55040Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
55050Sstevel@tonic-gate 		return (retval);
55060Sstevel@tonic-gate 	}
55070Sstevel@tonic-gate 
55080Sstevel@tonic-gate 	num_records = length/sizeof (sa_mcmember_record_t);
55090Sstevel@tonic-gate 
55100Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: Found %d MCMember Records",
55110Sstevel@tonic-gate 	    num_records);
55120Sstevel@tonic-gate 
55130Sstevel@tonic-gate 	/* Validate the returned number of records. */
55140Sstevel@tonic-gate 	if ((results_p != NULL) && (num_records > 0)) {
55150Sstevel@tonic-gate 		uint_t	i;
55160Sstevel@tonic-gate 
55170Sstevel@tonic-gate 		/*
55180Sstevel@tonic-gate 		 * If mcgs_max_num is zero, then return all records else
55190Sstevel@tonic-gate 		 * return only requested number of records
55200Sstevel@tonic-gate 		 */
55210Sstevel@tonic-gate 		if ((mcgs_max_num != 0) && (num_records > mcgs_max_num)) {
55220Sstevel@tonic-gate 			/* we are interested in only mcgs_max_num records */
55230Sstevel@tonic-gate 			num_records = mcgs_max_num;
55240Sstevel@tonic-gate 		}
55250Sstevel@tonic-gate 
55260Sstevel@tonic-gate 		/*
55270Sstevel@tonic-gate 		 * The SGID returned in "mcg_info_p" buffer should be PortGID,
55280Sstevel@tonic-gate 		 * (mcg_attr->mc_pgid), if 'mcg_attr->mc_pgid' was specified,
55290Sstevel@tonic-gate 		 * else RequestGID (rgid) should be returned.
55300Sstevel@tonic-gate 		 */
55310Sstevel@tonic-gate 		if ((port_gid.gid_prefix != 0) && (port_gid.gid_guid != 0)) {
55320Sstevel@tonic-gate 
55330Sstevel@tonic-gate 			/* Get sgid_ix and port number of 'port_gid' */
55340Sstevel@tonic-gate 			retval = ibtl_cm_get_hca_port(port_gid, 0, &hport);
55350Sstevel@tonic-gate 			if (retval != IBT_SUCCESS) {
55360Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: "
55370Sstevel@tonic-gate 				    "Failed to Get Portinfo for PortGID :"
55380Sstevel@tonic-gate 				    "status = %d", retval);
55390Sstevel@tonic-gate 				return (retval);
55400Sstevel@tonic-gate 			}
55410Sstevel@tonic-gate 		} else {
55420Sstevel@tonic-gate 			/*
55430Sstevel@tonic-gate 			 * The sgid_ix and port number related to RequestGID
55440Sstevel@tonic-gate 			 * are already obtained at the beginning.
55450Sstevel@tonic-gate 			 */
55460Sstevel@tonic-gate 			port_gid = rgid;
55470Sstevel@tonic-gate 		}
55480Sstevel@tonic-gate 
55490Sstevel@tonic-gate 		/*
55500Sstevel@tonic-gate 		 * Allocate memory for return buffer, to be freed in
55510Sstevel@tonic-gate 		 * ibt_free_mcg_info().
55520Sstevel@tonic-gate 		 */
55530Sstevel@tonic-gate 		mcg_infop = kmem_alloc((num_records * sizeof (ibt_mcg_info_t)),
55540Sstevel@tonic-gate 		    KM_SLEEP);
55550Sstevel@tonic-gate 
55560Sstevel@tonic-gate 		*mcgs_info_p = mcg_infop;
55570Sstevel@tonic-gate 		*entries_p = num_records;
55580Sstevel@tonic-gate 
55590Sstevel@tonic-gate 		/* Update the return values. */
55600Sstevel@tonic-gate 		for (i = 0; i < num_records; i++) {
55610Sstevel@tonic-gate 
55620Sstevel@tonic-gate 			mcg_resp = (sa_mcmember_record_t *)((uchar_t *)
55630Sstevel@tonic-gate 			    results_p + i * sizeof (sa_mcmember_record_t));
55640Sstevel@tonic-gate 
55650Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_dgid = mcg_resp->MGID;
55660Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_sgid = port_gid;
55670Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_srate = mcg_resp->Rate;
55680Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_srvl = mcg_resp->SL;
55690Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_flow = mcg_resp->FlowLabel;
55700Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_tclass = mcg_resp->TClass;
55710Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_hop = mcg_resp->HopLimit;
55720Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_port_num = hport.hp_port;
55730Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_send_grh = B_TRUE;
55740Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_dlid = mcg_resp->MLID;
55750Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_sgid_ix = hport.hp_sgid_ix;
55760Sstevel@tonic-gate 			mcg_infop[i].mc_adds_vect.av_src_path = 0;
55770Sstevel@tonic-gate 			mcg_infop[i].mc_mtu = mcg_resp->MTU;
55780Sstevel@tonic-gate 			mcg_infop[i].mc_qkey = mcg_resp->Q_Key;
55790Sstevel@tonic-gate 			mcg_infop[i].mc_scope = mcg_resp->Scope;
55800Sstevel@tonic-gate 			mcg_infop[i].mc_pkt_lt = mcg_resp->PacketLifeTime;
55810Sstevel@tonic-gate 
55820Sstevel@tonic-gate 			if (ibt_pkey2index_byguid(hport.hp_hca_guid,
55830Sstevel@tonic-gate 			    hport.hp_port, mcg_resp->P_Key,
55840Sstevel@tonic-gate 			    &mcg_infop[i].mc_pkey_ix) != IBT_SUCCESS) {
55850Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: "
55860Sstevel@tonic-gate 				    "Pkey2Index Conversion failed");
55870Sstevel@tonic-gate 				mcg_infop[i].mc_pkey_ix = 0;
55880Sstevel@tonic-gate 			}
55890Sstevel@tonic-gate 		}
55900Sstevel@tonic-gate 
55910Sstevel@tonic-gate 		/*
55920Sstevel@tonic-gate 		 * Deallocate the memory allocated by SA for results_p.
55930Sstevel@tonic-gate 		 */
55940Sstevel@tonic-gate 		kmem_free(results_p, length);
55950Sstevel@tonic-gate 		retval = IBT_SUCCESS;
55960Sstevel@tonic-gate 
55970Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: returning %d MCGRecords",
55980Sstevel@tonic-gate 		    num_records);
55990Sstevel@tonic-gate 
56000Sstevel@tonic-gate 	} else {
56010Sstevel@tonic-gate 		retval = IBT_MCG_RECORDS_NOT_FOUND;
56020Sstevel@tonic-gate 		*entries_p = 0;
56030Sstevel@tonic-gate 
56040Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: MCG RECORDS NOT FOUND");
56050Sstevel@tonic-gate 	}
56060Sstevel@tonic-gate 
56070Sstevel@tonic-gate 	ibcm_dec_hca_acc_cnt(hcap);
56080Sstevel@tonic-gate 
56090Sstevel@tonic-gate 	return (retval);
56100Sstevel@tonic-gate }
56110Sstevel@tonic-gate 
56120Sstevel@tonic-gate 
56130Sstevel@tonic-gate /*
56140Sstevel@tonic-gate  * ibt_free_mcg_info()
56150Sstevel@tonic-gate  *	Free the memory allocated by successful ibt_query_mcg()
56160Sstevel@tonic-gate  *
56170Sstevel@tonic-gate  *	mcgs_info	Pointer returned by ibt_query_mcg().
56180Sstevel@tonic-gate  *
56190Sstevel@tonic-gate  *	entries		The number of ibt_mcg_info_t entries to free.
56200Sstevel@tonic-gate  */
56210Sstevel@tonic-gate void
ibt_free_mcg_info(ibt_mcg_info_t * mcgs_info,uint_t entries)56220Sstevel@tonic-gate ibt_free_mcg_info(ibt_mcg_info_t *mcgs_info, uint_t entries)
56230Sstevel@tonic-gate {
56240Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_free_mcg_info: "
56250Sstevel@tonic-gate 	    "Free <%d> entries from 0x%p", entries, mcgs_info);
56260Sstevel@tonic-gate 
56270Sstevel@tonic-gate 	if ((mcgs_info != NULL) && (entries > 0))
56280Sstevel@tonic-gate 		kmem_free(mcgs_info, entries * sizeof (ibt_mcg_info_t));
56290Sstevel@tonic-gate 	else
56300Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_free_mcg_info: "
56310Sstevel@tonic-gate 		    "ERROR: NULL buf pointer or length specified.");
56320Sstevel@tonic-gate }
56330Sstevel@tonic-gate 
56340Sstevel@tonic-gate 
56350Sstevel@tonic-gate /*
56360Sstevel@tonic-gate  * Function:
56370Sstevel@tonic-gate  *	ibt_gid_to_node_info()
56380Sstevel@tonic-gate  * Input:
56390Sstevel@tonic-gate  *	gid		Identifies the IB Node and port for which to obtain
56400Sstevel@tonic-gate  *			Node information.
56410Sstevel@tonic-gate  * Output:
56420Sstevel@tonic-gate  *	node_info_p	A pointer to an ibt_node_info_t structure (allocated
56430Sstevel@tonic-gate  *			by the caller) in which to return the node information.
56440Sstevel@tonic-gate  * Returns:
56450Sstevel@tonic-gate  *	IBT_SUCCESS
56460Sstevel@tonic-gate  *	IBT_INVALID_PARAM
56470Sstevel@tonic-gate  *	IBT_NODE_RECORDS_NOT_FOUND
56480Sstevel@tonic-gate  *	IBT_NO_HCAS_AVAILABLE
56490Sstevel@tonic-gate  * Description:
56500Sstevel@tonic-gate  *	Retrieve Node Information for the specified GID.
56510Sstevel@tonic-gate  */
56520Sstevel@tonic-gate ibt_status_t
ibt_gid_to_node_info(ib_gid_t gid,ibt_node_info_t * node_info_p)56530Sstevel@tonic-gate ibt_gid_to_node_info(ib_gid_t gid, ibt_node_info_t *node_info_p)
56540Sstevel@tonic-gate {
56550Sstevel@tonic-gate 	sa_node_record_t	nr_req, *nr_resp;
56560Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
56570Sstevel@tonic-gate 	ibt_status_t		retval;
56580Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
56590Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hport;
56600Sstevel@tonic-gate 	int			i, j;
56610Sstevel@tonic-gate 	uint_t			num_rec;
56620Sstevel@tonic-gate 	ib_guid_t		*guid_array = NULL;
56630Sstevel@tonic-gate 	sa_path_record_t	*path;
56640Sstevel@tonic-gate 	size_t			len;
56650Sstevel@tonic-gate 	uint8_t			npaths;
56660Sstevel@tonic-gate 	uint32_t		num_hcas = 0;
56670Sstevel@tonic-gate 	ib_lid_t		node_lid;
56680Sstevel@tonic-gate 	boolean_t		local_node = B_FALSE;
56690Sstevel@tonic-gate 	void			*res_p;
56700Sstevel@tonic-gate 	uint8_t			num_ports = 0;
56710Sstevel@tonic-gate 
56720Sstevel@tonic-gate 
56730Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info(%llX:%llX, %p)",
56740Sstevel@tonic-gate 	    gid.gid_prefix, gid.gid_guid, node_info_p);
56750Sstevel@tonic-gate 
56760Sstevel@tonic-gate 	if ((gid.gid_prefix == 0) || (gid.gid_guid == 0)) {
56770Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: GID is required");
56780Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
56790Sstevel@tonic-gate 	}
56800Sstevel@tonic-gate 
56810Sstevel@tonic-gate 	if (node_info_p == NULL) {
56820Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
56830Sstevel@tonic-gate 		    "Return Buf (node_info_p) is NULL.");
56840Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
56850Sstevel@tonic-gate 	}
56860Sstevel@tonic-gate 
56870Sstevel@tonic-gate 	/*
56880Sstevel@tonic-gate 	 * If 'gid' is on local node, then get node lid (i.e. base lid of the
56890Sstevel@tonic-gate 	 * associated port) info via ibtl_cm_get_hca_port() call.
56900Sstevel@tonic-gate 	 */
56910Sstevel@tonic-gate 	bzero(&hport, sizeof (ibtl_cm_hca_port_t));
56920Sstevel@tonic-gate 	if (ibtl_cm_get_hca_port(gid, 0, &hport) == IBT_SUCCESS) {
56930Sstevel@tonic-gate 
56940Sstevel@tonic-gate 		hcap = ibcm_find_hca_entry(hport.hp_hca_guid);
56950Sstevel@tonic-gate 		if (hcap == NULL) {
56960Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
56970Sstevel@tonic-gate 			    "HCA(%llX) info not found", hport.hp_hca_guid);
56980Sstevel@tonic-gate 			return (IBT_NO_HCAS_AVAILABLE);
56990Sstevel@tonic-gate 		}
57000Sstevel@tonic-gate 		num_ports = 1;
57010Sstevel@tonic-gate 		num_hcas = 1;
57020Sstevel@tonic-gate 		node_lid = hport.hp_base_lid;
57030Sstevel@tonic-gate 		local_node = B_TRUE;
57040Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info: Local Node: "
57050Sstevel@tonic-gate 		    "LID = 0x%X", node_lid);
57060Sstevel@tonic-gate 	} else {
57070Sstevel@tonic-gate 		/* Get the number of HCAs and their GUIDs */
57080Sstevel@tonic-gate 		num_hcas = ibt_get_hca_list(&guid_array);
57090Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info: ibt_get_hca_list "
57100Sstevel@tonic-gate 		    "returned %d hcas", num_hcas);
57110Sstevel@tonic-gate 
57120Sstevel@tonic-gate 		if (num_hcas == 0) {
57130Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
57140Sstevel@tonic-gate 			    "NO HCA's Found on this system");
57150Sstevel@tonic-gate 			return (IBT_NO_HCAS_AVAILABLE);
57160Sstevel@tonic-gate 		}
57170Sstevel@tonic-gate 	}
57180Sstevel@tonic-gate 
57190Sstevel@tonic-gate 	for (i = 0; i < num_hcas; i++) {
57200Sstevel@tonic-gate 		if (local_node == B_FALSE) {
57210Sstevel@tonic-gate 			hcap = ibcm_find_hca_entry(guid_array[i]);
57220Sstevel@tonic-gate 			if (hcap == NULL) {
57230Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
57240Sstevel@tonic-gate 				    "HCA(%llX) info not found", guid_array[i]);
57250Sstevel@tonic-gate 				retval = IBT_NO_HCAS_AVAILABLE;
57260Sstevel@tonic-gate 				continue;
57270Sstevel@tonic-gate 			}
57280Sstevel@tonic-gate 			num_ports = hcap->hca_num_ports;
57290Sstevel@tonic-gate 		}
57300Sstevel@tonic-gate 
57310Sstevel@tonic-gate 		for (j = 0; j < num_ports; j++) {
57320Sstevel@tonic-gate 			uint8_t		port = 0;
57330Sstevel@tonic-gate 
57340Sstevel@tonic-gate 			if (local_node == B_TRUE)
57350Sstevel@tonic-gate 				port = hport.hp_port;
57360Sstevel@tonic-gate 			else
57370Sstevel@tonic-gate 				port = j + 1;
57380Sstevel@tonic-gate 
57390Sstevel@tonic-gate 			/* Get SA Access Handle. */
57400Sstevel@tonic-gate 			saa_handle = ibcm_get_saa_handle(hcap, port);
57410Sstevel@tonic-gate 			if (saa_handle == NULL) {
57420Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
57430Sstevel@tonic-gate 				    "Port %d of HCA (%llX) is NOT ACTIVE",
57440Sstevel@tonic-gate 				    port, hport.hp_hca_guid);
57450Sstevel@tonic-gate 				retval = IBT_NODE_RECORDS_NOT_FOUND;
57460Sstevel@tonic-gate 				continue;
57470Sstevel@tonic-gate 			}
57480Sstevel@tonic-gate 
57490Sstevel@tonic-gate 			if (local_node == B_FALSE) {
57500Sstevel@tonic-gate 				ib_gid_t	sgid;
57510Sstevel@tonic-gate 				int		sa_ret;
57520Sstevel@tonic-gate 
57530Sstevel@tonic-gate 				/*
57540Sstevel@tonic-gate 				 * Check whether 'gid' and this port has same
57550Sstevel@tonic-gate 				 * subnet prefix. If not, then there is no use
57560Sstevel@tonic-gate 				 * in searching from this port.
57570Sstevel@tonic-gate 				 */
57580Sstevel@tonic-gate 				sgid = hcap->hca_port_info[j].port_sgid0;
57590Sstevel@tonic-gate 				if (gid.gid_prefix != sgid.gid_prefix) {
57600Sstevel@tonic-gate 					IBTF_DPRINTF_L3(cmlog,
57610Sstevel@tonic-gate 					    "ibt_gid_to_node_info:Sn_Prefix of "
57620Sstevel@tonic-gate 					    "GID(%llX) and Port's(%llX) differ",
57630Sstevel@tonic-gate 					    gid.gid_prefix, sgid.gid_prefix);
57640Sstevel@tonic-gate 					retval = IBT_NODE_RECORDS_NOT_FOUND;
57650Sstevel@tonic-gate 					continue;
57660Sstevel@tonic-gate 				}
57670Sstevel@tonic-gate 
57680Sstevel@tonic-gate 				/*
57690Sstevel@tonic-gate 				 * First Get Path Records for the specified DGID
57700Sstevel@tonic-gate 				 * from this port (SGID). From Path Records,
57710Sstevel@tonic-gate 				 * note down DLID, then use this DLID as Input
57720Sstevel@tonic-gate 				 * attribute to get NodeRecords from SA Access.
57730Sstevel@tonic-gate 				 */
57740Sstevel@tonic-gate 				npaths = 1;
57750Sstevel@tonic-gate 				path = NULL;
57760Sstevel@tonic-gate 
57770Sstevel@tonic-gate 				sa_ret = ibmf_saa_gid_to_pathrecords(saa_handle,
57780Sstevel@tonic-gate 				    sgid, gid, 0, 0, B_TRUE, &npaths, 0, &len,
57790Sstevel@tonic-gate 				    &path);
57800Sstevel@tonic-gate 				if (sa_ret != IBMF_SUCCESS) {
57810Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
57820Sstevel@tonic-gate 					    "ibt_gid_to_node_info: "
57830Sstevel@tonic-gate 					    "ibmf_saa_gid_to_pathrecords() "
57840Sstevel@tonic-gate 					    "returned error: %d ", sa_ret);
57850Sstevel@tonic-gate 					retval =
57860Sstevel@tonic-gate 					    ibcm_ibmf_analyze_error(sa_ret);
57870Sstevel@tonic-gate 					continue;
57880Sstevel@tonic-gate 				} else if ((npaths == 0) || (path == NULL)) {
57890Sstevel@tonic-gate 					IBTF_DPRINTF_L3(cmlog,
57900Sstevel@tonic-gate 					    "ibt_gid_to_node_info: failed (%d) "
57910Sstevel@tonic-gate 					    "to get path records for the DGID "
57920Sstevel@tonic-gate 					    "0x%llX from SGID 0x%llX", sa_ret,
57930Sstevel@tonic-gate 					    gid.gid_guid, sgid.gid_guid);
57940Sstevel@tonic-gate 					retval = IBT_NODE_RECORDS_NOT_FOUND;
57950Sstevel@tonic-gate 					continue;
57960Sstevel@tonic-gate 				}
57970Sstevel@tonic-gate 				node_lid = path->DLID;	/* LID */
57980Sstevel@tonic-gate 
57990Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
58000Sstevel@tonic-gate 				    "Remote Node: LID = 0x%X", node_lid);
58010Sstevel@tonic-gate 
58020Sstevel@tonic-gate 				/* Free SA_Access memory for path record. */
58030Sstevel@tonic-gate 				kmem_free(path, len);
58040Sstevel@tonic-gate 			}
58050Sstevel@tonic-gate 
58060Sstevel@tonic-gate 			/* Retrieve Node Records from SA Access. */
58070Sstevel@tonic-gate 			bzero(&nr_req, sizeof (sa_node_record_t));
58080Sstevel@tonic-gate 
58090Sstevel@tonic-gate 			nr_req.LID = node_lid;	/* LID */
58100Sstevel@tonic-gate 
58110Sstevel@tonic-gate 			retval = ibcm_get_node_rec(saa_handle, &nr_req,
58120Sstevel@tonic-gate 			    SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
58130Sstevel@tonic-gate 			if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
58140Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
58150Sstevel@tonic-gate 				    "failed (%d) to get Node records", retval);
58160Sstevel@tonic-gate 				continue;
58170Sstevel@tonic-gate 			} else if (retval != IBT_SUCCESS) {
58180Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
58190Sstevel@tonic-gate 				    "failed (%d) to get Node records", retval);
58200Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
58210Sstevel@tonic-gate 				goto gid_to_ni_exit;
58220Sstevel@tonic-gate 			}
58230Sstevel@tonic-gate 
58240Sstevel@tonic-gate 			num_rec = len/sizeof (sa_node_record_t);
58250Sstevel@tonic-gate 			nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
58260Sstevel@tonic-gate 
58270Sstevel@tonic-gate 			/* Validate the returned number of records. */
58280Sstevel@tonic-gate 			if ((nr_resp != NULL) && (num_rec > 0)) {
58290Sstevel@tonic-gate 
58300Sstevel@tonic-gate 				IBCM_DUMP_NODE_REC(nr_resp);
58310Sstevel@tonic-gate 
58320Sstevel@tonic-gate 				_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
58330Sstevel@tonic-gate 				    *node_info_p))
58340Sstevel@tonic-gate 
58350Sstevel@tonic-gate 				node_info_p->n_sys_img_guid =
58360Sstevel@tonic-gate 				    nr_resp->NodeInfo.SystemImageGUID;
58370Sstevel@tonic-gate 				node_info_p->n_node_guid =
58380Sstevel@tonic-gate 				    nr_resp->NodeInfo.NodeGUID;
58390Sstevel@tonic-gate 				node_info_p->n_port_guid =
58400Sstevel@tonic-gate 				    nr_resp->NodeInfo.PortGUID;
58410Sstevel@tonic-gate 				node_info_p->n_dev_id =
58420Sstevel@tonic-gate 				    nr_resp->NodeInfo.DeviceID;
58430Sstevel@tonic-gate 				node_info_p->n_revision =
58440Sstevel@tonic-gate 				    nr_resp->NodeInfo.Revision;
58450Sstevel@tonic-gate 				node_info_p->n_vendor_id =
58460Sstevel@tonic-gate 				    nr_resp->NodeInfo.VendorID;
58470Sstevel@tonic-gate 				node_info_p->n_num_ports =
58480Sstevel@tonic-gate 				    nr_resp->NodeInfo.NumPorts;
58490Sstevel@tonic-gate 				node_info_p->n_port_num =
58500Sstevel@tonic-gate 				    nr_resp->NodeInfo.LocalPortNum;
58510Sstevel@tonic-gate 				node_info_p->n_node_type =
58520Sstevel@tonic-gate 				    nr_resp->NodeInfo.NodeType;
58530Sstevel@tonic-gate 				(void) strncpy(node_info_p->n_description,
58540Sstevel@tonic-gate 				    (char *)&nr_resp->NodeDescription, 64);
58550Sstevel@tonic-gate 
58560Sstevel@tonic-gate 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
58570Sstevel@tonic-gate 				    *node_info_p))
58580Sstevel@tonic-gate 
58590Sstevel@tonic-gate 				/*
58600Sstevel@tonic-gate 				 * Deallocate the memory allocated by SA for
58610Sstevel@tonic-gate 				 * 'nr_resp'.
58620Sstevel@tonic-gate 				 */
58630Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
58640Sstevel@tonic-gate 				kmem_free(nr_resp, len);
58650Sstevel@tonic-gate 				retval = IBT_SUCCESS;
58660Sstevel@tonic-gate 
58670Sstevel@tonic-gate 				goto gid_to_ni_exit;
58680Sstevel@tonic-gate 			} else {
58690Sstevel@tonic-gate 				retval = IBT_NODE_RECORDS_NOT_FOUND;
58700Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
58710Sstevel@tonic-gate 				    "Node Records NOT found - PortGUID %016llX",
58720Sstevel@tonic-gate 				    gid.gid_guid);
58730Sstevel@tonic-gate 			}
58740Sstevel@tonic-gate 		}
58750Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
58760Sstevel@tonic-gate 
58770Sstevel@tonic-gate 		if (local_node == B_TRUE)
58780Sstevel@tonic-gate 			break;
58790Sstevel@tonic-gate 	}
58800Sstevel@tonic-gate 
58810Sstevel@tonic-gate gid_to_ni_exit:
58820Sstevel@tonic-gate 	if (guid_array)
58830Sstevel@tonic-gate 		ibt_free_hca_list(guid_array, num_hcas);
58840Sstevel@tonic-gate 
58850Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: done. Status %d", retval);
58860Sstevel@tonic-gate 
58870Sstevel@tonic-gate 	return (retval);
58880Sstevel@tonic-gate }
58890Sstevel@tonic-gate 
58900Sstevel@tonic-gate 
58919891SRajkumar.Sivaprakasam@Sun.COM 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)58920Sstevel@tonic-gate ibcm_get_node_rec(ibmf_saa_handle_t saa_handle, sa_node_record_t *nr_req,
58930Sstevel@tonic-gate     uint64_t component_mask, void *result_p, size_t *len)
58940Sstevel@tonic-gate {
58950Sstevel@tonic-gate 	ibmf_saa_access_args_t  args;
58960Sstevel@tonic-gate 	size_t			length;
58970Sstevel@tonic-gate 	ibt_status_t		retval;
58980Sstevel@tonic-gate 
58990Sstevel@tonic-gate 	args.sq_attr_id = SA_NODERECORD_ATTRID;
59000Sstevel@tonic-gate 	args.sq_template = nr_req;
59010Sstevel@tonic-gate 	args.sq_access_type = IBMF_SAA_RETRIEVE;
59020Sstevel@tonic-gate 	args.sq_template_length = sizeof (sa_node_record_t);
59030Sstevel@tonic-gate 	args.sq_component_mask = component_mask;
59040Sstevel@tonic-gate 	args.sq_callback = NULL;
59050Sstevel@tonic-gate 	args.sq_callback_arg = NULL;
59060Sstevel@tonic-gate 
59070Sstevel@tonic-gate 	retval = ibcm_contact_sa_access(saa_handle, &args, &length, result_p);
59080Sstevel@tonic-gate 	if (retval != IBT_SUCCESS) {
59090Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_get_node_rec: SA Call Failed");
59100Sstevel@tonic-gate 		return (retval);
59110Sstevel@tonic-gate 	}
59120Sstevel@tonic-gate 
59130Sstevel@tonic-gate 	*len = length;
59140Sstevel@tonic-gate 
59150Sstevel@tonic-gate 	/* Validate the returned number of records. */
59160Sstevel@tonic-gate 	if ((result_p != NULL) && (length > 0)) {
59170Sstevel@tonic-gate 		IBTF_DPRINTF_L3(cmlog, "ibcm_get_node_rec: Node Records FOUND");
59180Sstevel@tonic-gate 
59190Sstevel@tonic-gate 		/* Got it, done!. */
59200Sstevel@tonic-gate 		return (IBT_SUCCESS);
59210Sstevel@tonic-gate 	} else {
59220Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibcm_get_node_rec: Node Rec NOT found");
59230Sstevel@tonic-gate 		return (IBT_NODE_RECORDS_NOT_FOUND);
59240Sstevel@tonic-gate 	}
59250Sstevel@tonic-gate }
59260Sstevel@tonic-gate 
59270Sstevel@tonic-gate 
59280Sstevel@tonic-gate /*
59290Sstevel@tonic-gate  * Function:
5930*12965SWilliam.Taylor@Oracle.COM  *	ibt_lid_to_node_info()
5931*12965SWilliam.Taylor@Oracle.COM  * Input:
5932*12965SWilliam.Taylor@Oracle.COM  *	lid		Identifies the IB Node and port for which to obtain
5933*12965SWilliam.Taylor@Oracle.COM  *			Node information.
5934*12965SWilliam.Taylor@Oracle.COM  * Output:
5935*12965SWilliam.Taylor@Oracle.COM  *	node_info_p	A pointer to an ibt_node_info_t structure (allocated
5936*12965SWilliam.Taylor@Oracle.COM  *			by the caller) in which to return the node information.
5937*12965SWilliam.Taylor@Oracle.COM  * Returns:
5938*12965SWilliam.Taylor@Oracle.COM  *	IBT_SUCCESS
5939*12965SWilliam.Taylor@Oracle.COM  *	IBT_INVALID_PARAM
5940*12965SWilliam.Taylor@Oracle.COM  *	IBT_NODE_RECORDS_NOT_FOUND
5941*12965SWilliam.Taylor@Oracle.COM  *	IBT_NO_HCAS_AVAILABLE
5942*12965SWilliam.Taylor@Oracle.COM  * Description:
5943*12965SWilliam.Taylor@Oracle.COM  *	Retrieve Node Information for the specified LID.
5944*12965SWilliam.Taylor@Oracle.COM  */
5945*12965SWilliam.Taylor@Oracle.COM ibt_status_t
ibt_lid_to_node_info(ib_lid_t lid,ibt_node_info_t * node_info_p)5946*12965SWilliam.Taylor@Oracle.COM ibt_lid_to_node_info(ib_lid_t lid, ibt_node_info_t *node_info_p)
5947*12965SWilliam.Taylor@Oracle.COM {
5948*12965SWilliam.Taylor@Oracle.COM 	ibt_status_t	retval;
5949*12965SWilliam.Taylor@Oracle.COM 	ibcm_hca_info_t	*hcap;
5950*12965SWilliam.Taylor@Oracle.COM 	uint8_t		i, j;
5951*12965SWilliam.Taylor@Oracle.COM 	ib_guid_t	*guid_array = NULL;
5952*12965SWilliam.Taylor@Oracle.COM 	uint_t		num_hcas = 0;
5953*12965SWilliam.Taylor@Oracle.COM 
5954*12965SWilliam.Taylor@Oracle.COM 
5955*12965SWilliam.Taylor@Oracle.COM 	IBTF_DPRINTF_L4(cmlog, "ibt_lid_to_node_info(0x%lX, %p)",
5956*12965SWilliam.Taylor@Oracle.COM 	    lid, node_info_p);
5957*12965SWilliam.Taylor@Oracle.COM 
5958*12965SWilliam.Taylor@Oracle.COM 	if ((lid == 0) || (node_info_p == NULL)) {
5959*12965SWilliam.Taylor@Oracle.COM 		IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
5960*12965SWilliam.Taylor@Oracle.COM 		    "Lid is zero, or node_info_p is NULL.");
5961*12965SWilliam.Taylor@Oracle.COM 		return (IBT_INVALID_PARAM);
5962*12965SWilliam.Taylor@Oracle.COM 	}
5963*12965SWilliam.Taylor@Oracle.COM 
5964*12965SWilliam.Taylor@Oracle.COM 	/* Get the number of HCAs and their GUIDs */
5965*12965SWilliam.Taylor@Oracle.COM 	num_hcas = ibt_get_hca_list(&guid_array);
5966*12965SWilliam.Taylor@Oracle.COM 	IBTF_DPRINTF_L4(cmlog, "ibt_lid_to_node_info: ibt_get_hca_list "
5967*12965SWilliam.Taylor@Oracle.COM 	    "returned %d hcas", num_hcas);
5968*12965SWilliam.Taylor@Oracle.COM 
5969*12965SWilliam.Taylor@Oracle.COM 	if (num_hcas == 0) {
5970*12965SWilliam.Taylor@Oracle.COM 		IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
5971*12965SWilliam.Taylor@Oracle.COM 		    "NO HCA's Found on this system");
5972*12965SWilliam.Taylor@Oracle.COM 		return (IBT_NO_HCAS_AVAILABLE);
5973*12965SWilliam.Taylor@Oracle.COM 	}
5974*12965SWilliam.Taylor@Oracle.COM 
5975*12965SWilliam.Taylor@Oracle.COM 	for (i = 0; i < num_hcas; i++) {
5976*12965SWilliam.Taylor@Oracle.COM 		hcap = ibcm_find_hca_entry(guid_array[i]);
5977*12965SWilliam.Taylor@Oracle.COM 		if (hcap == NULL) {
5978*12965SWilliam.Taylor@Oracle.COM 			IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
5979*12965SWilliam.Taylor@Oracle.COM 			    "HCA(%llX) info not found", guid_array[i]);
5980*12965SWilliam.Taylor@Oracle.COM 			retval = IBT_NO_HCAS_AVAILABLE;
5981*12965SWilliam.Taylor@Oracle.COM 			continue;
5982*12965SWilliam.Taylor@Oracle.COM 		}
5983*12965SWilliam.Taylor@Oracle.COM 
5984*12965SWilliam.Taylor@Oracle.COM 		for (j = 0; j < hcap->hca_num_ports; j++) {
5985*12965SWilliam.Taylor@Oracle.COM 			uint8_t			port;
5986*12965SWilliam.Taylor@Oracle.COM 			ibmf_saa_handle_t	saa_handle;
5987*12965SWilliam.Taylor@Oracle.COM 			uint_t			num_rec;
5988*12965SWilliam.Taylor@Oracle.COM 			size_t			len;
5989*12965SWilliam.Taylor@Oracle.COM 			void			*res_p;
5990*12965SWilliam.Taylor@Oracle.COM 			sa_node_record_t	nr_req, *nr_resp;
5991*12965SWilliam.Taylor@Oracle.COM 
5992*12965SWilliam.Taylor@Oracle.COM 			port = j + 1;
5993*12965SWilliam.Taylor@Oracle.COM 
5994*12965SWilliam.Taylor@Oracle.COM 			/* Get SA Access Handle. */
5995*12965SWilliam.Taylor@Oracle.COM 			saa_handle = ibcm_get_saa_handle(hcap, port);
5996*12965SWilliam.Taylor@Oracle.COM 			if (saa_handle == NULL) {
5997*12965SWilliam.Taylor@Oracle.COM 				IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
5998*12965SWilliam.Taylor@Oracle.COM 				    "Port %d of HCA (%llX) is NOT ACTIVE",
5999*12965SWilliam.Taylor@Oracle.COM 				    port, guid_array[i]);
6000*12965SWilliam.Taylor@Oracle.COM 				retval = IBT_NODE_RECORDS_NOT_FOUND;
6001*12965SWilliam.Taylor@Oracle.COM 				continue;
6002*12965SWilliam.Taylor@Oracle.COM 			}
6003*12965SWilliam.Taylor@Oracle.COM 
6004*12965SWilliam.Taylor@Oracle.COM 			/* Retrieve Node Records from SA Access. */
6005*12965SWilliam.Taylor@Oracle.COM 			bzero(&nr_req, sizeof (sa_node_record_t));
6006*12965SWilliam.Taylor@Oracle.COM 
6007*12965SWilliam.Taylor@Oracle.COM 			nr_req.LID = lid;	/* LID */
6008*12965SWilliam.Taylor@Oracle.COM 
6009*12965SWilliam.Taylor@Oracle.COM 			retval = ibcm_get_node_rec(saa_handle, &nr_req,
6010*12965SWilliam.Taylor@Oracle.COM 			    SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
6011*12965SWilliam.Taylor@Oracle.COM 			if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
6012*12965SWilliam.Taylor@Oracle.COM 				IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
6013*12965SWilliam.Taylor@Oracle.COM 				    "failed (%d) to get Node records", retval);
6014*12965SWilliam.Taylor@Oracle.COM 				continue;
6015*12965SWilliam.Taylor@Oracle.COM 			} else if (retval != IBT_SUCCESS) {
6016*12965SWilliam.Taylor@Oracle.COM 				IBTF_DPRINTF_L2(cmlog, "ibt_lid_to_node_info: "
6017*12965SWilliam.Taylor@Oracle.COM 				    "failed (%d) to get Node records", retval);
6018*12965SWilliam.Taylor@Oracle.COM 				ibcm_dec_hca_acc_cnt(hcap);
6019*12965SWilliam.Taylor@Oracle.COM 				goto lid_to_ni_exit;
6020*12965SWilliam.Taylor@Oracle.COM 			}
6021*12965SWilliam.Taylor@Oracle.COM 
6022*12965SWilliam.Taylor@Oracle.COM 			num_rec = len/sizeof (sa_node_record_t);
6023*12965SWilliam.Taylor@Oracle.COM 			nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
6024*12965SWilliam.Taylor@Oracle.COM 
6025*12965SWilliam.Taylor@Oracle.COM 			/* Validate the returned number of records. */
6026*12965SWilliam.Taylor@Oracle.COM 			if ((nr_resp != NULL) && (num_rec > 0)) {
6027*12965SWilliam.Taylor@Oracle.COM 
6028*12965SWilliam.Taylor@Oracle.COM 				IBCM_DUMP_NODE_REC(nr_resp);
6029*12965SWilliam.Taylor@Oracle.COM 
6030*12965SWilliam.Taylor@Oracle.COM 				_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
6031*12965SWilliam.Taylor@Oracle.COM 				    *node_info_p))
6032*12965SWilliam.Taylor@Oracle.COM 
6033*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_sys_img_guid =
6034*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.SystemImageGUID;
6035*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_node_guid =
6036*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.NodeGUID;
6037*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_port_guid =
6038*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.PortGUID;
6039*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_dev_id =
6040*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.DeviceID;
6041*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_revision =
6042*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.Revision;
6043*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_vendor_id =
6044*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.VendorID;
6045*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_num_ports =
6046*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.NumPorts;
6047*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_port_num =
6048*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.LocalPortNum;
6049*12965SWilliam.Taylor@Oracle.COM 				node_info_p->n_node_type =
6050*12965SWilliam.Taylor@Oracle.COM 				    nr_resp->NodeInfo.NodeType;
6051*12965SWilliam.Taylor@Oracle.COM 				(void) strncpy(node_info_p->n_description,
6052*12965SWilliam.Taylor@Oracle.COM 				    (char *)&nr_resp->NodeDescription, 64);
6053*12965SWilliam.Taylor@Oracle.COM 
6054*12965SWilliam.Taylor@Oracle.COM 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
6055*12965SWilliam.Taylor@Oracle.COM 				    *node_info_p))
6056*12965SWilliam.Taylor@Oracle.COM 
6057*12965SWilliam.Taylor@Oracle.COM 				/*
6058*12965SWilliam.Taylor@Oracle.COM 				 * Deallocate the memory allocated by SA for
6059*12965SWilliam.Taylor@Oracle.COM 				 * 'nr_resp'.
6060*12965SWilliam.Taylor@Oracle.COM 				 */
6061*12965SWilliam.Taylor@Oracle.COM 				ibcm_dec_hca_acc_cnt(hcap);
6062*12965SWilliam.Taylor@Oracle.COM 				kmem_free(nr_resp, len);
6063*12965SWilliam.Taylor@Oracle.COM 				retval = IBT_SUCCESS;
6064*12965SWilliam.Taylor@Oracle.COM 
6065*12965SWilliam.Taylor@Oracle.COM 				goto lid_to_ni_exit;
6066*12965SWilliam.Taylor@Oracle.COM 			} else {
6067*12965SWilliam.Taylor@Oracle.COM 				retval = IBT_NODE_RECORDS_NOT_FOUND;
6068*12965SWilliam.Taylor@Oracle.COM 				IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: "
6069*12965SWilliam.Taylor@Oracle.COM 				    "Node Records NOT found - LID 0x%lX",
6070*12965SWilliam.Taylor@Oracle.COM 				    lid);
6071*12965SWilliam.Taylor@Oracle.COM 			}
6072*12965SWilliam.Taylor@Oracle.COM 		}
6073*12965SWilliam.Taylor@Oracle.COM 		ibcm_dec_hca_acc_cnt(hcap);
6074*12965SWilliam.Taylor@Oracle.COM 	}
6075*12965SWilliam.Taylor@Oracle.COM 
6076*12965SWilliam.Taylor@Oracle.COM lid_to_ni_exit:
6077*12965SWilliam.Taylor@Oracle.COM 	if (guid_array)
6078*12965SWilliam.Taylor@Oracle.COM 		ibt_free_hca_list(guid_array, num_hcas);
6079*12965SWilliam.Taylor@Oracle.COM 
6080*12965SWilliam.Taylor@Oracle.COM 	IBTF_DPRINTF_L3(cmlog, "ibt_lid_to_node_info: done. Status %d", retval);
6081*12965SWilliam.Taylor@Oracle.COM 
6082*12965SWilliam.Taylor@Oracle.COM 	return (retval);
6083*12965SWilliam.Taylor@Oracle.COM }
6084*12965SWilliam.Taylor@Oracle.COM 
6085*12965SWilliam.Taylor@Oracle.COM /*
6086*12965SWilliam.Taylor@Oracle.COM  * Function:
60870Sstevel@tonic-gate  *	ibt_get_companion_port_gids()
60880Sstevel@tonic-gate  * Description:
60890Sstevel@tonic-gate  *	Get list of GID's available on a companion port(s) of the specified
60900Sstevel@tonic-gate  *	GID or list of GIDs available on a specified Node GUID/SystemImage GUID.
60910Sstevel@tonic-gate  */
60920Sstevel@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)60930Sstevel@tonic-gate ibt_get_companion_port_gids(ib_gid_t gid, ib_guid_t hca_guid,
60940Sstevel@tonic-gate     ib_guid_t sysimg_guid, ib_gid_t **gids_p, uint_t *num_gids_p)
60950Sstevel@tonic-gate {
60960Sstevel@tonic-gate 	sa_node_record_t	nr_req, *nr_resp;
60970Sstevel@tonic-gate 	void			*res_p;
60980Sstevel@tonic-gate 	ibmf_saa_handle_t	saa_handle;
60990Sstevel@tonic-gate 	int			sa_ret;
61001495Shiremath 	ibt_status_t		retval = IBT_SUCCESS;
61010Sstevel@tonic-gate 	ibcm_hca_info_t		*hcap;
61020Sstevel@tonic-gate 	ibtl_cm_hca_port_t	hport;
61030Sstevel@tonic-gate 	int			i, j;
61040Sstevel@tonic-gate 	uint_t			num_rec;
61050Sstevel@tonic-gate 	ib_guid_t		*guid_array = NULL;
61060Sstevel@tonic-gate 	sa_path_record_t	*path;
61070Sstevel@tonic-gate 	size_t			len;
61080Sstevel@tonic-gate 	uint8_t			npaths;
61090Sstevel@tonic-gate 	uint32_t		num_hcas = 0;
61100Sstevel@tonic-gate 	boolean_t		local_node = B_FALSE;
61110Sstevel@tonic-gate 	boolean_t		local_hca = B_FALSE;
61120Sstevel@tonic-gate 	ib_guid_t		h_guid = hca_guid;
61130Sstevel@tonic-gate 	ib_gid_t		*gidp = NULL, *t_gidp = NULL;
6114401Shiremath 	int			multi_hca_loop = 0;
61150Sstevel@tonic-gate 
61160Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids(%llX:%llX, %llX, "
61170Sstevel@tonic-gate 	    "%llX)", gid.gid_prefix, gid.gid_guid, hca_guid, sysimg_guid);
61180Sstevel@tonic-gate 
61190Sstevel@tonic-gate 	if (((gid.gid_prefix == 0) || (gid.gid_guid == 0)) && (hca_guid == 0) &&
61200Sstevel@tonic-gate 	    (sysimg_guid == 0)) {
61210Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61220Sstevel@tonic-gate 		    "Null Input attribute specified.");
61230Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
61240Sstevel@tonic-gate 	}
61250Sstevel@tonic-gate 
61260Sstevel@tonic-gate 	if ((num_gids_p == NULL) || (gids_p == NULL)) {
61270Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61280Sstevel@tonic-gate 		    "num_gids_p or gids_p is NULL");
61290Sstevel@tonic-gate 		return (IBT_INVALID_PARAM);
61300Sstevel@tonic-gate 	}
61310Sstevel@tonic-gate 
61320Sstevel@tonic-gate 	*num_gids_p = 0;
61330Sstevel@tonic-gate 
61340Sstevel@tonic-gate 	/* Get the number of HCAs and their GUIDs */
61350Sstevel@tonic-gate 	if ((num_hcas = ibt_get_hca_list(&guid_array)) == 0) {
61360Sstevel@tonic-gate 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61370Sstevel@tonic-gate 		    "NO HCA's Found on this system");
61380Sstevel@tonic-gate 		return (IBT_NO_HCAS_AVAILABLE);
61390Sstevel@tonic-gate 	}
61400Sstevel@tonic-gate 
61410Sstevel@tonic-gate 	IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids: "
61420Sstevel@tonic-gate 	    "ibt_get_hca_list() returned %d hcas", num_hcas);
61430Sstevel@tonic-gate 
61440Sstevel@tonic-gate 	/*
61450Sstevel@tonic-gate 	 * If 'gid' is on local node, then get node lid (i.e. base lid of the
61460Sstevel@tonic-gate 	 * associated port) info via ibtl_cm_get_hca_port() call.
61470Sstevel@tonic-gate 	 */
61480Sstevel@tonic-gate 	bzero(&hport, sizeof (ibtl_cm_hca_port_t));
61490Sstevel@tonic-gate 	if ((gid.gid_prefix != 0) && (gid.gid_guid != 0) &&
61500Sstevel@tonic-gate 	    (ibtl_cm_get_hca_port(gid, 0, &hport) == IBT_SUCCESS)) {
61510Sstevel@tonic-gate 
61520Sstevel@tonic-gate 		if ((hca_guid != 0) && (hca_guid != hport.hp_hca_guid)) {
61530Sstevel@tonic-gate 			IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
61540Sstevel@tonic-gate 			    "Invalid GID<->HCAGUID combination specified.");
61550Sstevel@tonic-gate 			retval = IBT_INVALID_PARAM;
61560Sstevel@tonic-gate 			goto get_comp_pgid_exit;
61570Sstevel@tonic-gate 		}
61580Sstevel@tonic-gate 		h_guid = hport.hp_hca_guid;
61590Sstevel@tonic-gate 		local_node = B_TRUE;
61600Sstevel@tonic-gate 
61610Sstevel@tonic-gate 		IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids: "
61620Sstevel@tonic-gate 		    "Local Node: HCA (0x%llX)", h_guid);
61630Sstevel@tonic-gate 	} else if (h_guid) {	/* Is specified HCA GUID - local? */
61640Sstevel@tonic-gate 		for (i = 0; i < num_hcas; i++) {
61650Sstevel@tonic-gate 			if (h_guid == guid_array[i]) {
61660Sstevel@tonic-gate 				local_hca = B_TRUE;
61670Sstevel@tonic-gate 				break;
61680Sstevel@tonic-gate 			}
61690Sstevel@tonic-gate 		}
61700Sstevel@tonic-gate 	} else if (sysimg_guid) { /* Is specified SystemImage GUID - local? */
61710Sstevel@tonic-gate 		for (i = 0; i < num_hcas; i++) {
61720Sstevel@tonic-gate 			ibt_status_t	ret;
61730Sstevel@tonic-gate 			ibt_hca_attr_t	hca_attr;
61740Sstevel@tonic-gate 
61750Sstevel@tonic-gate 			ret = ibt_query_hca_byguid(guid_array[i], &hca_attr);
61760Sstevel@tonic-gate 			if (ret != IBT_SUCCESS) {
61770Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
61780Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: HCA(%llX) "
61790Sstevel@tonic-gate 				    "info not found", guid_array[i]);
61800Sstevel@tonic-gate 				retval = IBT_NO_HCAS_AVAILABLE;
61810Sstevel@tonic-gate 				continue;
61820Sstevel@tonic-gate 			}
61830Sstevel@tonic-gate 			if (hca_attr.hca_si_guid == sysimg_guid) {
61840Sstevel@tonic-gate 				if ((hca_guid != 0) &&
61850Sstevel@tonic-gate 				    (hca_guid != hca_attr.hca_node_guid)) {
61860Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
61870Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
61880Sstevel@tonic-gate 					    "Invalid SysImg<->HCA GUID "
61890Sstevel@tonic-gate 					    "combination specified.");
61900Sstevel@tonic-gate 					retval = IBT_INVALID_PARAM;
61910Sstevel@tonic-gate 					goto get_comp_pgid_exit;
61920Sstevel@tonic-gate 				}
61930Sstevel@tonic-gate 				local_hca = B_TRUE;
61940Sstevel@tonic-gate 				h_guid = hca_attr.hca_node_guid;
61950Sstevel@tonic-gate 				break;
61960Sstevel@tonic-gate 			}
61970Sstevel@tonic-gate 		}
61980Sstevel@tonic-gate 	}
61990Sstevel@tonic-gate 
62000Sstevel@tonic-gate 	if ((local_node == B_TRUE) || (local_hca == B_TRUE)) {
62010Sstevel@tonic-gate 		retval = ibtl_cm_get_local_comp_gids(h_guid, gid, gids_p,
62020Sstevel@tonic-gate 		    num_gids_p);
62030Sstevel@tonic-gate 		goto get_comp_pgid_exit;
62040Sstevel@tonic-gate 	}
62050Sstevel@tonic-gate 
6206401Shiremath get_comp_for_multihca:
62070Sstevel@tonic-gate 	/* We will be here, if request is for remote node */
62080Sstevel@tonic-gate 	for (i = 0; i < num_hcas; i++) {
62090Sstevel@tonic-gate 		int		multism;
62106709Shiremath 		uint_t		count = 0;
62110Sstevel@tonic-gate 		int		multi_sm_loop = 0;
62120Sstevel@tonic-gate 		uint_t		k = 0, l;
62130Sstevel@tonic-gate 
62140Sstevel@tonic-gate 		hcap = ibcm_find_hca_entry(guid_array[i]);
62150Sstevel@tonic-gate 		if (hcap == NULL) {
62160Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
62170Sstevel@tonic-gate 			    "HCA(%llX) info not found", guid_array[i]);
62180Sstevel@tonic-gate 			retval = IBT_NO_HCAS_AVAILABLE;
62190Sstevel@tonic-gate 			continue;
62200Sstevel@tonic-gate 		}
62210Sstevel@tonic-gate 
62220Sstevel@tonic-gate 		/* 1 - MultiSM, 0 - Single SM */
62230Sstevel@tonic-gate 		multism = ibtl_cm_is_multi_sm(guid_array[i]);
62240Sstevel@tonic-gate 
62250Sstevel@tonic-gate 		for (j = 0; j < hcap->hca_num_ports; j++) {
62260Sstevel@tonic-gate 			ib_gid_t	sgid;
62270Sstevel@tonic-gate 			uint64_t	c_mask = 0;
62280Sstevel@tonic-gate 			ib_guid_t	pg;
62290Sstevel@tonic-gate 			uint_t		port = j;
62300Sstevel@tonic-gate 
62310Sstevel@tonic-gate get_comp_for_multism:
62320Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
62330Sstevel@tonic-gate 			    "Port %d, HCA %llX, MultiSM= %d, Loop=%d",
62340Sstevel@tonic-gate 			    port + 1, h_guid, multism, multi_sm_loop);
62350Sstevel@tonic-gate 
62360Sstevel@tonic-gate 			/* Get SA Access Handle. */
62370Sstevel@tonic-gate 			saa_handle = ibcm_get_saa_handle(hcap, port + 1);
62380Sstevel@tonic-gate 			if (saa_handle == NULL) {
62390Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
62400Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
62411495Shiremath 				    "Port (%d)  - NOT ACTIVE", port + 1);
62421495Shiremath 				retval = IBT_GIDS_NOT_FOUND;
62430Sstevel@tonic-gate 				continue;
62440Sstevel@tonic-gate 			}
62450Sstevel@tonic-gate 
62460Sstevel@tonic-gate 			/*
62470Sstevel@tonic-gate 			 * Check whether 'gid' and this port has same subnet
62480Sstevel@tonic-gate 			 * prefix. If not, then there is no use in searching
62490Sstevel@tonic-gate 			 * from this port.
62500Sstevel@tonic-gate 			 */
62510Sstevel@tonic-gate 			sgid = hcap->hca_port_info[port].port_sgid0;
6252401Shiremath 			if ((h_guid == 0) && (gid.gid_prefix != 0) &&
6253401Shiremath 			    (multi_sm_loop == 0) &&
62540Sstevel@tonic-gate 			    (gid.gid_prefix != sgid.gid_prefix)) {
62550Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
62560Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: SnPrefix of "
62570Sstevel@tonic-gate 				    "GID(%llX) and Port SN_Pfx(%llX) differ",
62580Sstevel@tonic-gate 				    gid.gid_prefix, sgid.gid_prefix);
62591495Shiremath 				retval = IBT_GIDS_NOT_FOUND;
62600Sstevel@tonic-gate 				continue;
62610Sstevel@tonic-gate 			}
62620Sstevel@tonic-gate 
62630Sstevel@tonic-gate 			/*
62640Sstevel@tonic-gate 			 * If HCA GUID or System Image GUID is specified, then
62650Sstevel@tonic-gate 			 * we can achieve our goal sooner!.
62660Sstevel@tonic-gate 			 */
62670Sstevel@tonic-gate 			if ((h_guid == 0) && (sysimg_guid == 0)) {
62680Sstevel@tonic-gate 				/* So only GID info is provided. */
62690Sstevel@tonic-gate 
62700Sstevel@tonic-gate 				/*
62710Sstevel@tonic-gate 				 * First Get Path Records for the specified DGID
62720Sstevel@tonic-gate 				 * from this port (SGID). From Path Records,
62730Sstevel@tonic-gate 				 * note down DLID, then use this DLID as Input
62740Sstevel@tonic-gate 				 * attribute to get NodeRecords.
62750Sstevel@tonic-gate 				 */
62760Sstevel@tonic-gate 				npaths = 1;
62770Sstevel@tonic-gate 				path = NULL;
62780Sstevel@tonic-gate 
62790Sstevel@tonic-gate 				sa_ret = ibmf_saa_gid_to_pathrecords(saa_handle,
62800Sstevel@tonic-gate 				    sgid, gid, 0, 0, B_TRUE, &npaths, 0, &len,
62810Sstevel@tonic-gate 				    &path);
62820Sstevel@tonic-gate 				if (sa_ret != IBMF_SUCCESS) {
62830Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
62840Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
62850Sstevel@tonic-gate 					    "ibmf_saa_gid_to_pathrecords() "
62860Sstevel@tonic-gate 					    "returned error: %d ", sa_ret);
62870Sstevel@tonic-gate 					retval =
62880Sstevel@tonic-gate 					    ibcm_ibmf_analyze_error(sa_ret);
62890Sstevel@tonic-gate 					ibcm_dec_hca_acc_cnt(hcap);
62900Sstevel@tonic-gate 					goto get_comp_pgid_exit;
62910Sstevel@tonic-gate 				} else if ((npaths == 0) || (path == NULL)) {
62920Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
62930Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
62940Sstevel@tonic-gate 					    "failed (%d) to get path records "
62950Sstevel@tonic-gate 					    "for the DGID (0x%llX) from SGID "
62960Sstevel@tonic-gate 					    "(0x%llX)", sa_ret, gid.gid_guid,
62970Sstevel@tonic-gate 					    sgid.gid_guid);
62981495Shiremath 					retval = IBT_GIDS_NOT_FOUND;
62990Sstevel@tonic-gate 					continue;
63000Sstevel@tonic-gate 				}
6301401Shiremath 
6302401Shiremath 				bzero(&nr_req, sizeof (sa_node_record_t));
63030Sstevel@tonic-gate 				nr_req.LID = path->DLID;	/* LID */
63040Sstevel@tonic-gate 
63050Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog,
63060Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
63070Sstevel@tonic-gate 				    "Remote Node: LID = 0x%X", nr_req.LID);
63080Sstevel@tonic-gate 
63090Sstevel@tonic-gate 				/* Free SA_Access memory for path record. */
63100Sstevel@tonic-gate 				kmem_free(path, len);
63110Sstevel@tonic-gate 
63120Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog,
63130Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: SAA Call: "
63140Sstevel@tonic-gate 				    "based on LID ");
63150Sstevel@tonic-gate 
63160Sstevel@tonic-gate 				retval = ibcm_get_node_rec(saa_handle, &nr_req,
63170Sstevel@tonic-gate 				    SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
63180Sstevel@tonic-gate 				if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
63190Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
63200Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
63210Sstevel@tonic-gate 					    "failed (%d) to get Node records",
63220Sstevel@tonic-gate 					    retval);
63230Sstevel@tonic-gate 					continue;
63240Sstevel@tonic-gate 				} else if (retval != IBT_SUCCESS) {
63250Sstevel@tonic-gate 					IBTF_DPRINTF_L2(cmlog,
63260Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
63270Sstevel@tonic-gate 					    "failed (%d) to get Node records",
63280Sstevel@tonic-gate 					    retval);
63290Sstevel@tonic-gate 					ibcm_dec_hca_acc_cnt(hcap);
63300Sstevel@tonic-gate 					goto get_comp_pgid_exit;
63310Sstevel@tonic-gate 				}
63320Sstevel@tonic-gate 
63330Sstevel@tonic-gate 				nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
63340Sstevel@tonic-gate 				/* Note down HCA GUID info. */
63350Sstevel@tonic-gate 				h_guid = nr_resp->NodeInfo.NodeGUID;
63360Sstevel@tonic-gate 
63370Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog,
63380Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
63390Sstevel@tonic-gate 				    "Remote HCA GUID: 0x%llX", h_guid);
63400Sstevel@tonic-gate 
63410Sstevel@tonic-gate 				IBCM_DUMP_NODE_REC(nr_resp);
63420Sstevel@tonic-gate 
63430Sstevel@tonic-gate 				kmem_free(res_p, len);
63440Sstevel@tonic-gate 			}
63450Sstevel@tonic-gate 
6346401Shiremath 			bzero(&nr_req, sizeof (sa_node_record_t));
63470Sstevel@tonic-gate 			if (h_guid != 0) {
63480Sstevel@tonic-gate 				nr_req.NodeInfo.NodeGUID = h_guid;
63490Sstevel@tonic-gate 				c_mask = SA_NODEINFO_COMPMASK_NODEGUID;
63500Sstevel@tonic-gate 			}
63510Sstevel@tonic-gate 
63520Sstevel@tonic-gate 			if (sysimg_guid != 0) {
63530Sstevel@tonic-gate 				nr_req.NodeInfo.SystemImageGUID = sysimg_guid;
63540Sstevel@tonic-gate 				c_mask |= SA_NODEINFO_COMPMASK_SYSIMAGEGUID;
63550Sstevel@tonic-gate 			}
63560Sstevel@tonic-gate 
63570Sstevel@tonic-gate 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
63580Sstevel@tonic-gate 			    "SAA Call: CMASK= 0x%llX", c_mask);
63590Sstevel@tonic-gate 
63600Sstevel@tonic-gate 			retval = ibcm_get_node_rec(saa_handle, &nr_req, c_mask,
63610Sstevel@tonic-gate 			    &res_p, &len);
63620Sstevel@tonic-gate 			if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
63630Sstevel@tonic-gate 				IBTF_DPRINTF_L3(cmlog,
63640Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
63650Sstevel@tonic-gate 				    "failed (%d) to get Node records", retval);
63660Sstevel@tonic-gate 				continue;
63670Sstevel@tonic-gate 			} else if (retval != IBT_SUCCESS) {
63680Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
63690Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: Error: (%d) "
63700Sstevel@tonic-gate 				    "while getting Node records", retval);
63710Sstevel@tonic-gate 				ibcm_dec_hca_acc_cnt(hcap);
63720Sstevel@tonic-gate 				goto get_comp_pgid_exit;
63730Sstevel@tonic-gate 			}
63740Sstevel@tonic-gate 
63750Sstevel@tonic-gate 			num_rec = len/sizeof (sa_node_record_t);
63760Sstevel@tonic-gate 
63770Sstevel@tonic-gate 			/* We will be here, only if we found some NodeRec */
63780Sstevel@tonic-gate 			if (gid.gid_prefix && gid.gid_guid) {
63790Sstevel@tonic-gate 				nr_resp = (sa_node_record_t *)res_p;
63800Sstevel@tonic-gate 				for (l = 0; l < num_rec; l++, nr_resp++) {
63810Sstevel@tonic-gate 					pg = nr_resp->NodeInfo.PortGUID;
63820Sstevel@tonic-gate 					if (gid.gid_guid != pg)
63830Sstevel@tonic-gate 						count++;
63840Sstevel@tonic-gate 				}
63850Sstevel@tonic-gate 			} else {
63860Sstevel@tonic-gate 				count = num_rec;
63870Sstevel@tonic-gate 			}
63880Sstevel@tonic-gate 
63890Sstevel@tonic-gate 			if (count != 0) {
63900Sstevel@tonic-gate 				if (multi_sm_loop == 1) {
63910Sstevel@tonic-gate 					count += k;
63920Sstevel@tonic-gate 					t_gidp = kmem_zalloc(count *
63930Sstevel@tonic-gate 					    sizeof (ib_gid_t), KM_SLEEP);
63940Sstevel@tonic-gate 
63950Sstevel@tonic-gate 					if ((k != 0) && (gidp != NULL)) {
63960Sstevel@tonic-gate 						bcopy(gidp, t_gidp,
63970Sstevel@tonic-gate 						    k * sizeof (ib_gid_t));
63980Sstevel@tonic-gate 						kmem_free(gidp,
63990Sstevel@tonic-gate 						    k * sizeof (ib_gid_t));
64000Sstevel@tonic-gate 					}
64010Sstevel@tonic-gate 					gidp = t_gidp;
64020Sstevel@tonic-gate 				} else {
64030Sstevel@tonic-gate 					gidp = kmem_zalloc(count *
64040Sstevel@tonic-gate 					    sizeof (ib_gid_t), KM_SLEEP);
64050Sstevel@tonic-gate 				}
64060Sstevel@tonic-gate 				*num_gids_p = count;
64070Sstevel@tonic-gate 				*gids_p = gidp;
64080Sstevel@tonic-gate 
64090Sstevel@tonic-gate 				nr_resp = (sa_node_record_t *)res_p;
64100Sstevel@tonic-gate 				for (l = 0; l < num_rec; l++, nr_resp++) {
64110Sstevel@tonic-gate 					IBCM_DUMP_NODE_REC(nr_resp);
64120Sstevel@tonic-gate 
64130Sstevel@tonic-gate 					pg = nr_resp->NodeInfo.PortGUID;
64140Sstevel@tonic-gate 					IBTF_DPRINTF_L4(cmlog,
64150Sstevel@tonic-gate 					    "ibt_get_companion_port_gids: "
64160Sstevel@tonic-gate 					    "PortGID %llX", pg);
64170Sstevel@tonic-gate 
64180Sstevel@tonic-gate 					if (pg != gid.gid_guid) {
64190Sstevel@tonic-gate 						gidp[k].gid_prefix =
64200Sstevel@tonic-gate 						    sgid.gid_prefix;
64210Sstevel@tonic-gate 						gidp[k].gid_guid = pg;
64220Sstevel@tonic-gate 
64230Sstevel@tonic-gate 						IBTF_DPRINTF_L3(cmlog,
64240Sstevel@tonic-gate 						    "ibt_get_companion_pgids: "
64250Sstevel@tonic-gate 						    "GID[%d] = %llX:%llX", k,
64260Sstevel@tonic-gate 						    gidp[k].gid_prefix,
64270Sstevel@tonic-gate 						    gidp[k].gid_guid);
64280Sstevel@tonic-gate 
64290Sstevel@tonic-gate 						k++;
64300Sstevel@tonic-gate 						if (k == count)
64310Sstevel@tonic-gate 							break;
64320Sstevel@tonic-gate 					}
64330Sstevel@tonic-gate 				}
64340Sstevel@tonic-gate 				retval = IBT_SUCCESS;	/* done!. */
6435401Shiremath 				kmem_free(res_p, len);
6436401Shiremath 				ibcm_dec_hca_acc_cnt(hcap);
6437401Shiremath 				goto get_comp_pgid_exit;
64380Sstevel@tonic-gate 			} else {
64390Sstevel@tonic-gate 				IBTF_DPRINTF_L2(cmlog,
64400Sstevel@tonic-gate 				    "ibt_get_companion_port_gids: "
64410Sstevel@tonic-gate 				    "Companion PortGIDs not available");
64420Sstevel@tonic-gate 				retval = IBT_GIDS_NOT_FOUND;
64430Sstevel@tonic-gate 			}
64440Sstevel@tonic-gate 			/* Deallocate the memory for 'res_p'. */
64450Sstevel@tonic-gate 			kmem_free(res_p, len);
64460Sstevel@tonic-gate 
64470Sstevel@tonic-gate 			/*
64480Sstevel@tonic-gate 			 * If we are on MultiSM setup, then we need to lookout
64490Sstevel@tonic-gate 			 * from that subnet port too.
64500Sstevel@tonic-gate 			 */
64510Sstevel@tonic-gate 			if (multism) {
64520Sstevel@tonic-gate 				/* break if already searched both the subnet */
64530Sstevel@tonic-gate 				if (multi_sm_loop == 1)
64540Sstevel@tonic-gate 					break;
64550Sstevel@tonic-gate 
64560Sstevel@tonic-gate 				port = (j == 0) ? 1 : 0;
64570Sstevel@tonic-gate 				multi_sm_loop = 1;
64580Sstevel@tonic-gate 				goto get_comp_for_multism;
64590Sstevel@tonic-gate 			} else {
64600Sstevel@tonic-gate 				break;
64610Sstevel@tonic-gate 			}
64620Sstevel@tonic-gate 		}
64630Sstevel@tonic-gate 		ibcm_dec_hca_acc_cnt(hcap);
6464401Shiremath 
6465401Shiremath 		/*
6466401Shiremath 		 * We may be on dual HCA with dual SM configured system.  And
6467401Shiremath 		 * the input attr GID was visible from second HCA. So in order
6468401Shiremath 		 * to get the companion portgid we need to re-look from the
6469401Shiremath 		 * first HCA ports.
6470401Shiremath 		 */
6471401Shiremath 		if ((num_hcas > 1) && (i > 0) && (h_guid != 0) &&
6472401Shiremath 		    (multi_hca_loop != 1)) {
6473401Shiremath 			multi_hca_loop = 1;
6474401Shiremath 			goto get_comp_for_multihca;
6475401Shiremath 		}
64760Sstevel@tonic-gate 	}
64771495Shiremath 	if (*num_gids_p == 0)
64781495Shiremath 		retval = IBT_GIDS_NOT_FOUND;
64790Sstevel@tonic-gate 
64800Sstevel@tonic-gate get_comp_pgid_exit:
64810Sstevel@tonic-gate 	if (guid_array)
64820Sstevel@tonic-gate 		ibt_free_hca_list(guid_array, num_hcas);
64830Sstevel@tonic-gate 
64840Sstevel@tonic-gate 	if ((retval != IBT_SUCCESS) && (*num_gids_p != 0)) {
64850Sstevel@tonic-gate 		retval = IBT_SUCCESS;
64860Sstevel@tonic-gate 	}
64870Sstevel@tonic-gate 
64880Sstevel@tonic-gate 	IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: done. Status %d, "
64890Sstevel@tonic-gate 	    "Found %d GIDs", retval, *num_gids_p);
64900Sstevel@tonic-gate 
64910Sstevel@tonic-gate 	return (retval);
64920Sstevel@tonic-gate }
64930Sstevel@tonic-gate 
64944703Shiremath /* RDMA IP CM Support routines */
64954703Shiremath ibt_status_t
ibt_get_src_ip(ibt_srcip_attr_t * sattr,ibt_srcip_info_t ** src_info_p,uint_t * entries_p)6496*12965SWilliam.Taylor@Oracle.COM ibt_get_src_ip(ibt_srcip_attr_t *sattr, ibt_srcip_info_t **src_info_p,
6497*12965SWilliam.Taylor@Oracle.COM     uint_t *entries_p)
64984703Shiremath {
6499*12965SWilliam.Taylor@Oracle.COM 	ibt_srcip_info_t	*s_ip;
65004703Shiremath 	ibcm_arp_ip_t		*ipp;
65014703Shiremath 	ibcm_arp_ibd_insts_t	ibds;
6502*12965SWilliam.Taylor@Oracle.COM 	uint8_t			i, j;
6503*12965SWilliam.Taylor@Oracle.COM 	uint_t			count;
65044703Shiremath 	ibt_status_t		retval = IBT_SUCCESS;
65054703Shiremath 
6506*12965SWilliam.Taylor@Oracle.COM 	IBTF_DPRINTF_L4(cmlog, "ibt_get_src_ip(%p, %p, %p)",
6507*12965SWilliam.Taylor@Oracle.COM 	    sattr, src_info_p, entries_p);
6508*12965SWilliam.Taylor@Oracle.COM 
6509*12965SWilliam.Taylor@Oracle.COM 	if (sattr == NULL || entries_p == NULL) {
6510*12965SWilliam.Taylor@Oracle.COM 		IBTF_DPRINTF_L3(cmlog, "ibt_get_src_ip: Invalid I/P Args.");
6511*12965SWilliam.Taylor@Oracle.COM 		return (IBT_INVALID_PARAM);
6512*12965SWilliam.Taylor@Oracle.COM 	}
6513*12965SWilliam.Taylor@Oracle.COM 
6514*12965SWilliam.Taylor@Oracle.COM 	if (sattr->sip_gid.gid_prefix == 0 || sattr->sip_gid.gid_guid == 0) {
65154703Shiremath 		IBTF_DPRINTF_L3(cmlog, "ibt_get_src_ip: Invalid GID.");
65164703Shiremath 		return (IBT_INVALID_PARAM);
65174703Shiremath 	}
65184703Shiremath 
6519*12965SWilliam.Taylor@Oracle.COM 	/* TBD: Zoneid */
6520*12965SWilliam.Taylor@Oracle.COM 	retval = ibcm_arp_get_ibds(&ibds, sattr->sip_family);
65214703Shiremath 	if (retval != IBT_SUCCESS) {
65224703Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_get_src_ip: ibcm_arp_get_ibds "
65234703Shiremath 		    "failed to get IBD Instances: ret 0x%x", retval);
65244703Shiremath 		goto get_src_ip_end;
65254703Shiremath 	}
65264703Shiremath 
6527*12965SWilliam.Taylor@Oracle.COM 	count = 0;
65284703Shiremath 	for (i = 0, ipp = ibds.ibcm_arp_ip; i < ibds.ibcm_arp_ibd_cnt;
65294703Shiremath 	    i++, ipp++) {
653011369SPramod.Gunjikar@Sun.COM 		if (ipp->ip_inet_family == AF_UNSPEC)
653111369SPramod.Gunjikar@Sun.COM 			continue;
6532*12965SWilliam.Taylor@Oracle.COM 		if (ipp->ip_port_gid.gid_prefix == sattr->sip_gid.gid_prefix &&
6533*12965SWilliam.Taylor@Oracle.COM 		    ipp->ip_port_gid.gid_guid == sattr->sip_gid.gid_guid) {
6534*12965SWilliam.Taylor@Oracle.COM 			if ((sattr->sip_pkey) &&
6535*12965SWilliam.Taylor@Oracle.COM 			    (ipp->ip_pkey != sattr->sip_pkey))
6536*12965SWilliam.Taylor@Oracle.COM 				continue;
6537*12965SWilliam.Taylor@Oracle.COM 
6538*12965SWilliam.Taylor@Oracle.COM 			if ((sattr->sip_zoneid != ALL_ZONES) &&
6539*12965SWilliam.Taylor@Oracle.COM 			    (sattr->sip_zoneid != ipp->ip_zoneid))
6540*12965SWilliam.Taylor@Oracle.COM 				continue;
6541*12965SWilliam.Taylor@Oracle.COM 
6542*12965SWilliam.Taylor@Oracle.COM 			count++;
65434703Shiremath 			break;
65444703Shiremath 		}
65454703Shiremath 	}
65464703Shiremath 
6547*12965SWilliam.Taylor@Oracle.COM 	if (count) {
6548*12965SWilliam.Taylor@Oracle.COM 		/*
6549*12965SWilliam.Taylor@Oracle.COM 		 * Allocate memory for return buffer, to be freed by
6550*12965SWilliam.Taylor@Oracle.COM 		 * ibt_free_srcip_info().
6551*12965SWilliam.Taylor@Oracle.COM 		 */
6552*12965SWilliam.Taylor@Oracle.COM 		s_ip = kmem_alloc((count * sizeof (ibt_srcip_info_t)),
6553*12965SWilliam.Taylor@Oracle.COM 		    KM_SLEEP);
6554*12965SWilliam.Taylor@Oracle.COM 
6555*12965SWilliam.Taylor@Oracle.COM 		*src_info_p = s_ip;
6556*12965SWilliam.Taylor@Oracle.COM 		*entries_p = count;
6557*12965SWilliam.Taylor@Oracle.COM 
6558*12965SWilliam.Taylor@Oracle.COM 		j = 0;
6559*12965SWilliam.Taylor@Oracle.COM 		for (i = 0, ipp = ibds.ibcm_arp_ip; i < ibds.ibcm_arp_ibd_cnt;
6560*12965SWilliam.Taylor@Oracle.COM 		    i++, ipp++) {
6561*12965SWilliam.Taylor@Oracle.COM 			if (ipp->ip_inet_family == AF_UNSPEC)
6562*12965SWilliam.Taylor@Oracle.COM 				continue;
6563*12965SWilliam.Taylor@Oracle.COM 			if ((ipp->ip_port_gid.gid_prefix ==
6564*12965SWilliam.Taylor@Oracle.COM 			    sattr->sip_gid.gid_prefix) &&
6565*12965SWilliam.Taylor@Oracle.COM 			    (ipp->ip_port_gid.gid_guid ==
6566*12965SWilliam.Taylor@Oracle.COM 			    sattr->sip_gid.gid_guid)) {
6567*12965SWilliam.Taylor@Oracle.COM 				if ((sattr->sip_pkey) &&
6568*12965SWilliam.Taylor@Oracle.COM 				    (ipp->ip_pkey != sattr->sip_pkey))
6569*12965SWilliam.Taylor@Oracle.COM 					continue;
6570*12965SWilliam.Taylor@Oracle.COM 
6571*12965SWilliam.Taylor@Oracle.COM 				if ((sattr->sip_zoneid != ALL_ZONES) &&
6572*12965SWilliam.Taylor@Oracle.COM 				    (sattr->sip_zoneid != ipp->ip_zoneid))
6573*12965SWilliam.Taylor@Oracle.COM 					continue;
6574*12965SWilliam.Taylor@Oracle.COM 
6575*12965SWilliam.Taylor@Oracle.COM 				_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s_ip))
6576*12965SWilliam.Taylor@Oracle.COM 				s_ip[j].ip_addr.family = ipp->ip_inet_family;
6577*12965SWilliam.Taylor@Oracle.COM 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s_ip))
6578*12965SWilliam.Taylor@Oracle.COM 				if (s_ip[j].ip_addr.family == AF_INET) {
6579*12965SWilliam.Taylor@Oracle.COM 					bcopy(&ipp->ip_cm_sin.sin_addr,
6580*12965SWilliam.Taylor@Oracle.COM 					    &s_ip[j].ip_addr.un.ip4addr,
6581*12965SWilliam.Taylor@Oracle.COM 					    sizeof (in_addr_t));
6582*12965SWilliam.Taylor@Oracle.COM 				} else if (s_ip[j].ip_addr.family == AF_INET6) {
6583*12965SWilliam.Taylor@Oracle.COM 					bcopy(&ipp->ip_cm_sin6.sin6_addr,
6584*12965SWilliam.Taylor@Oracle.COM 					    &s_ip[j].ip_addr.un.ip6addr,
6585*12965SWilliam.Taylor@Oracle.COM 					    sizeof (in6_addr_t));
6586*12965SWilliam.Taylor@Oracle.COM 					/* TBD: scope_id */
6587*12965SWilliam.Taylor@Oracle.COM 				}
6588*12965SWilliam.Taylor@Oracle.COM 				IBCM_PRINT_IP("ibt_get_src_ip",
6589*12965SWilliam.Taylor@Oracle.COM 				    &s_ip[j].ip_addr);
6590*12965SWilliam.Taylor@Oracle.COM 				j++;
6591*12965SWilliam.Taylor@Oracle.COM 			}
6592*12965SWilliam.Taylor@Oracle.COM 		}
65934703Shiremath 	} else {
6594*12965SWilliam.Taylor@Oracle.COM 		retval = IBT_SRC_IP_NOT_FOUND;
65954703Shiremath 	}
65964703Shiremath 
65974703Shiremath get_src_ip_end:
659812163SRamaswamy.Tummala@Sun.COM 	ibcm_arp_free_ibds(&ibds);
65994703Shiremath 	return (retval);
66004703Shiremath }
66014703Shiremath 
6602*12965SWilliam.Taylor@Oracle.COM /*
6603*12965SWilliam.Taylor@Oracle.COM  * ibt_free_srcip_info()
6604*12965SWilliam.Taylor@Oracle.COM  *	Free the memory allocated by successful ibt_get_src_ip()
6605*12965SWilliam.Taylor@Oracle.COM  *
6606*12965SWilliam.Taylor@Oracle.COM  *	src_info	Pointer returned by ibt_get_src_ip().
6607*12965SWilliam.Taylor@Oracle.COM  *
6608*12965SWilliam.Taylor@Oracle.COM  *	entries		The number of ibt_ip_addr_t entries to free.
6609*12965SWilliam.Taylor@Oracle.COM  */
6610*12965SWilliam.Taylor@Oracle.COM void
ibt_free_srcip_info(ibt_srcip_info_t * src_info,uint_t entries)6611*12965SWilliam.Taylor@Oracle.COM ibt_free_srcip_info(ibt_srcip_info_t *src_info, uint_t entries)
6612*12965SWilliam.Taylor@Oracle.COM {
6613*12965SWilliam.Taylor@Oracle.COM 	IBTF_DPRINTF_L3(cmlog, "ibt_free_srcip_info: "
6614*12965SWilliam.Taylor@Oracle.COM 	    "Free <%d> entries from 0x%p", entries, src_info);
6615*12965SWilliam.Taylor@Oracle.COM 
6616*12965SWilliam.Taylor@Oracle.COM 	if ((src_info != NULL) && (entries > 0))
6617*12965SWilliam.Taylor@Oracle.COM 		kmem_free(src_info, entries * sizeof (ibt_srcip_info_t));
6618*12965SWilliam.Taylor@Oracle.COM 	else
6619*12965SWilliam.Taylor@Oracle.COM 		IBTF_DPRINTF_L2(cmlog, "ibt_free_srcip_info: "
6620*12965SWilliam.Taylor@Oracle.COM 		    "ERROR: NULL buf pointer or ZERO length specified.");
6621*12965SWilliam.Taylor@Oracle.COM }
6622*12965SWilliam.Taylor@Oracle.COM 
6623*12965SWilliam.Taylor@Oracle.COM 
66244703Shiremath ib_svc_id_t
ibt_get_ip_sid(uint8_t protocol_num,in_port_t dst_port)66254703Shiremath ibt_get_ip_sid(uint8_t protocol_num, in_port_t dst_port)
66264703Shiremath {
66274703Shiremath 	ib_svc_id_t	sid;
66284703Shiremath 
66294703Shiremath 	IBTF_DPRINTF_L4(cmlog, "ibt_get_ip_sid(%X, %lX)", protocol_num,
66304703Shiremath 	    dst_port);
66314703Shiremath 
66324703Shiremath 	/*
66334703Shiremath 	 * If protocol_num is non-zero, then formulate the SID and return it.
66344703Shiremath 	 * If protocol_num is zero, then we need to assign a locally generated
66354703Shiremath 	 * IP SID with IB_SID_IPADDR_PREFIX.
66364703Shiremath 	 */
66374703Shiremath 	if (protocol_num) {
66384703Shiremath 		sid = IB_SID_IPADDR_PREFIX | protocol_num << 16 | dst_port;
66394703Shiremath 	} else {
66404703Shiremath 		sid = ibcm_alloc_ip_sid();
66414703Shiremath 	}
66424703Shiremath 
66434703Shiremath 	IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_sid: SID: 0x%016llX", sid);
66444703Shiremath 	return (sid);
66454703Shiremath }
66464703Shiremath 
66474703Shiremath ibt_status_t
ibt_release_ip_sid(ib_svc_id_t ip_sid)66484703Shiremath ibt_release_ip_sid(ib_svc_id_t ip_sid)
66494703Shiremath {
66504703Shiremath 	IBTF_DPRINTF_L4(cmlog, "ibt_release_ip_sid(%llX)", ip_sid);
66514703Shiremath 
66524703Shiremath 	if (((ip_sid & IB_SID_IPADDR_PREFIX_MASK) != 0) ||
66534703Shiremath 	    (!(ip_sid & IB_SID_IPADDR_PREFIX))) {
66544703Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_release_ip_sid(0x%016llX): ERROR: "
66554703Shiremath 		    "Called for Non-RDMA IP SID", ip_sid);
66564703Shiremath 		return (IBT_INVALID_PARAM);
66574703Shiremath 	}
66584703Shiremath 
66594703Shiremath 	/*
66604703Shiremath 	 * If protocol_num in ip_sid are all ZEROs, then this SID is allocated
66614703Shiremath 	 * by IBTF. If not, then the specified ip_sid is invalid.
66624703Shiremath 	 */
66634703Shiremath 	if (ip_sid & IB_SID_IPADDR_IPNUM_MASK) {
66644703Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_release_ip_sid(0x%016llX): ERROR: "
66654703Shiremath 		    "Called for Non-IBTF assigned RDMA IP SID", ip_sid);
66664703Shiremath 		return (IBT_INVALID_PARAM);
66674703Shiremath 	}
66684703Shiremath 
66694703Shiremath 	ibcm_free_ip_sid(ip_sid);
66704703Shiremath 
66714703Shiremath 	return (IBT_SUCCESS);
66724703Shiremath }
66734703Shiremath 
66744703Shiremath 
66754703Shiremath uint8_t
ibt_get_ip_protocol_num(ib_svc_id_t sid)66764703Shiremath ibt_get_ip_protocol_num(ib_svc_id_t sid)
66774703Shiremath {
66784703Shiremath 	return ((sid & IB_SID_IPADDR_IPNUM_MASK) >> 16);
66794703Shiremath }
66804703Shiremath 
66814703Shiremath in_port_t
ibt_get_ip_dst_port(ib_svc_id_t sid)66824703Shiremath ibt_get_ip_dst_port(ib_svc_id_t sid)
66834703Shiremath {
66844703Shiremath 	return (sid & IB_SID_IPADDR_PORTNUM_MASK);
66854703Shiremath }
66864703Shiremath 
66874703Shiremath _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibt_ip_cm_info_t))
66884703Shiremath _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_ip_pvtdata_t))
66894703Shiremath 
66904703Shiremath 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)66914703Shiremath ibt_format_ip_private_data(ibt_ip_cm_info_t *ip_cm_info,
66924703Shiremath     ibt_priv_data_len_t priv_data_len, void *priv_data_p)
66934703Shiremath {
66946243Shiremath 	ibcm_ip_pvtdata_t	ip_data;
66954703Shiremath 
66964703Shiremath 	IBTF_DPRINTF_L4(cmlog, "ibt_format_ip_private_data(%p, %d, %p)",
66974703Shiremath 	    ip_cm_info, priv_data_len, priv_data_p);
66984703Shiremath 
66994703Shiremath 	if ((ip_cm_info == NULL) || (priv_data_p == NULL) ||
67004703Shiremath 	    (priv_data_len < IBT_IP_HDR_PRIV_DATA_SZ)) {
67014703Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_format_ip_private_data: ERROR "
67024703Shiremath 		    "Invalid Inputs.");
67034703Shiremath 		return (IBT_INVALID_PARAM);
67044703Shiremath 	}
67054703Shiremath 
67066243Shiremath 	bzero(&ip_data, sizeof (ibcm_ip_pvtdata_t));
67076243Shiremath 	ip_data.ip_srcport = ip_cm_info->src_port; /* Source Port */
67084703Shiremath 
67099349SShantkumar.Hiremath@Sun.COM 	IBCM_PRINT_IP("format_ip_pvt: src", &ip_cm_info->src_addr);
67109349SShantkumar.Hiremath@Sun.COM 	IBCM_PRINT_IP("format_ip_pvt: dst", &ip_cm_info->dst_addr);
67114703Shiremath 	/* IPV = 0x4, if IP-Addr are IPv4 format, else 0x6 for IPv6 */
67124703Shiremath 	if (ip_cm_info->src_addr.family == AF_INET) {
67136243Shiremath 		ip_data.ip_ipv = IBT_CM_IP_IPV_V4;
67146243Shiremath 		ip_data.ip_srcv4 = ip_cm_info->src_addr.un.ip4addr;
67156243Shiremath 		ip_data.ip_dstv4 = ip_cm_info->dst_addr.un.ip4addr;
67164703Shiremath 	} else if (ip_cm_info->src_addr.family == AF_INET6) {
67176243Shiremath 		ip_data.ip_ipv = IBT_CM_IP_IPV_V6;
67184703Shiremath 		bcopy(&ip_cm_info->src_addr.un.ip6addr,
67196243Shiremath 		    &ip_data.ip_srcv6, sizeof (in6_addr_t));
67204703Shiremath 		bcopy(&ip_cm_info->dst_addr.un.ip6addr,
67216243Shiremath 		    &ip_data.ip_dstv6, sizeof (in6_addr_t));
67224703Shiremath 	} else {
67234703Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_format_ip_private_data: ERROR "
67244703Shiremath 		    "IP Addr needs to be either AF_INET or AF_INET6 family.");
67254703Shiremath 		return (IBT_INVALID_PARAM);
67264703Shiremath 	}
67274703Shiremath 
67286243Shiremath 	ip_data.ip_MajV = IBT_CM_IP_MAJ_VER;
67296243Shiremath 	ip_data.ip_MinV = IBT_CM_IP_MIN_VER;
67306243Shiremath 
67316243Shiremath 	bcopy(&ip_data, priv_data_p, IBT_IP_HDR_PRIV_DATA_SZ);
67324703Shiremath 
67334703Shiremath 	return (IBT_SUCCESS);
67344703Shiremath }
67354703Shiremath 
67364703Shiremath 
67374703Shiremath 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)67384703Shiremath ibt_get_ip_data(ibt_priv_data_len_t priv_data_len, void *priv_data,
67394703Shiremath     ibt_ip_cm_info_t *ip_cm_infop)
67404703Shiremath {
67416243Shiremath 	ibcm_ip_pvtdata_t	ip_data;
67424703Shiremath 
67434703Shiremath 	IBTF_DPRINTF_L4(cmlog, "ibt_get_ip_data(%d, %p, %p)",
67444703Shiremath 	    priv_data_len, priv_data, ip_cm_infop);
67454703Shiremath 
67464703Shiremath 	if ((ip_cm_infop == NULL) || (priv_data == NULL) ||
67474703Shiremath 	    (priv_data_len < IBT_IP_HDR_PRIV_DATA_SZ)) {
67484703Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_data: ERROR Invalid Inputs");
67494703Shiremath 		return (IBT_INVALID_PARAM);
67504703Shiremath 	}
67514703Shiremath 
67526243Shiremath 	bcopy(priv_data, &ip_data, IBT_IP_HDR_PRIV_DATA_SZ);
67536243Shiremath 	ip_cm_infop->src_port = ip_data.ip_srcport; /* Source Port */
67544703Shiremath 
67554703Shiremath 	/* IPV = 0x4, if IP Address are IPv4 format, else 0x6 for IPv6 */
67566243Shiremath 	if (ip_data.ip_ipv == IBT_CM_IP_IPV_V4) {
67574703Shiremath 		/* Copy IPv4 Addr */
67589349SShantkumar.Hiremath@Sun.COM 		ip_cm_infop->src_addr.family = ip_cm_infop->dst_addr.family =
67599349SShantkumar.Hiremath@Sun.COM 		    AF_INET;
67606243Shiremath 		ip_cm_infop->src_addr.un.ip4addr = ip_data.ip_srcv4;
67616243Shiremath 		ip_cm_infop->dst_addr.un.ip4addr = ip_data.ip_dstv4;
67626243Shiremath 	} else if (ip_data.ip_ipv == IBT_CM_IP_IPV_V6) {
67634703Shiremath 		/* Copy IPv6 Addr */
67649349SShantkumar.Hiremath@Sun.COM 		ip_cm_infop->src_addr.family = ip_cm_infop->dst_addr.family =
67659349SShantkumar.Hiremath@Sun.COM 		    AF_INET6;
67666243Shiremath 		bcopy(&ip_data.ip_srcv6, &ip_cm_infop->src_addr.un.ip6addr,
67674703Shiremath 		    sizeof (in6_addr_t));
67686243Shiremath 		bcopy(&ip_data.ip_dstv6, &ip_cm_infop->dst_addr.un.ip6addr,
67694703Shiremath 		    sizeof (in6_addr_t));
67704703Shiremath 	} else {
67714703Shiremath 		IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_data: ERROR: IP Addr needs"
67724703Shiremath 		    " to be either AF_INET or AF_INET6 family.");
67734703Shiremath 		return (IBT_INVALID_PARAM);
67744703Shiremath 	}
67759349SShantkumar.Hiremath@Sun.COM 	IBCM_PRINT_IP("ibt_get_ip_data: src", &ip_cm_infop->src_addr);
67769349SShantkumar.Hiremath@Sun.COM 	IBCM_PRINT_IP("ibt_get_ip_data: dst", &ip_cm_infop->dst_addr);
67774703Shiremath 
67784703Shiremath 	return (IBT_SUCCESS);
67794703Shiremath }
67804703Shiremath 
67810Sstevel@tonic-gate 
67820Sstevel@tonic-gate /* Routines for warlock */
67830Sstevel@tonic-gate 
67840Sstevel@tonic-gate /* ARGSUSED */
67850Sstevel@tonic-gate static void
ibcm_dummy_mcg_handler(void * arg,ibt_status_t retval,ibt_mcg_info_t * minfo)67860Sstevel@tonic-gate ibcm_dummy_mcg_handler(void *arg, ibt_status_t retval, ibt_mcg_info_t *minfo)
67870Sstevel@tonic-gate {
67880Sstevel@tonic-gate 	ibcm_join_mcg_tqarg_t	dummy_mcg;
67890Sstevel@tonic-gate 
67900Sstevel@tonic-gate 	dummy_mcg.func = ibcm_dummy_mcg_handler;
67910Sstevel@tonic-gate 
67920Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_mcg_handler: "
67930Sstevel@tonic-gate 	    "dummy_mcg.func %p", dummy_mcg.func);
67940Sstevel@tonic-gate }
67950Sstevel@tonic-gate 
67960Sstevel@tonic-gate 
67970Sstevel@tonic-gate /* ARGSUSED */
67980Sstevel@tonic-gate static void
ibcm_dummy_recycle_rc_handler(ibt_status_t retval,void * arg)67990Sstevel@tonic-gate ibcm_dummy_recycle_rc_handler(ibt_status_t retval, void *arg)
68000Sstevel@tonic-gate {
68010Sstevel@tonic-gate 	ibcm_taskq_recycle_arg_t	dummy_rc_recycle;
68020Sstevel@tonic-gate 
68030Sstevel@tonic-gate 	dummy_rc_recycle.func = ibcm_dummy_recycle_rc_handler;
68040Sstevel@tonic-gate 
68050Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_recycle_rc_handler: "
68060Sstevel@tonic-gate 	    "dummy_rc_recycle.func %p", dummy_rc_recycle.func);
68070Sstevel@tonic-gate }
68080Sstevel@tonic-gate 
68090Sstevel@tonic-gate 
68100Sstevel@tonic-gate /* ARGSUSED */
68110Sstevel@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)68120Sstevel@tonic-gate ibcm_dummy_ud_handler(void *priv, ibt_cm_ud_event_t *event,
68130Sstevel@tonic-gate     ibt_cm_ud_return_args_t *ret_args,
68140Sstevel@tonic-gate     void *priv_data, ibt_priv_data_len_t len)
68150Sstevel@tonic-gate {
68160Sstevel@tonic-gate 	/*
68170Sstevel@tonic-gate 	 * Let warlock see that ibcm_local_handler_s::actual_cm_handler
68180Sstevel@tonic-gate 	 * points to this routine.
68190Sstevel@tonic-gate 	 */
68200Sstevel@tonic-gate 	ibcm_local_handler_t	p;
68210Sstevel@tonic-gate 	ibcm_ud_state_data_t	dummy_ud;
68220Sstevel@tonic-gate 
68230Sstevel@tonic-gate 	p.actual_cm_handler = ibcm_dummy_ud_handler;
68240Sstevel@tonic-gate 	dummy_ud.ud_cm_handler = ibcm_dummy_ud_handler;
68250Sstevel@tonic-gate 
68260Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_ud_handler: p.actual_cm_handler %p"
68270Sstevel@tonic-gate 	    "dummy_ud.ud_cm_handler %p", p.actual_cm_handler,
68280Sstevel@tonic-gate 	    dummy_ud.ud_cm_handler);
68290Sstevel@tonic-gate 	/*
68300Sstevel@tonic-gate 	 * Call all routines that the client's callback routine could call.
68310Sstevel@tonic-gate 	 */
68320Sstevel@tonic-gate 
68330Sstevel@tonic-gate 	return (IBT_CM_ACCEPT);
68340Sstevel@tonic-gate }
68350Sstevel@tonic-gate 
68360Sstevel@tonic-gate /* ARGSUSED */
68370Sstevel@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)68380Sstevel@tonic-gate ibcm_dummy_rc_handler(void *priv, ibt_cm_event_t *event,
68390Sstevel@tonic-gate     ibt_cm_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
68400Sstevel@tonic-gate {
68410Sstevel@tonic-gate 	ibcm_state_data_t	dummy_rc;
68420Sstevel@tonic-gate 
68430Sstevel@tonic-gate 	dummy_rc.cm_handler = ibcm_dummy_rc_handler;
68440Sstevel@tonic-gate 
68450Sstevel@tonic-gate 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_rc_handler: "
68460Sstevel@tonic-gate 	    "dummy_ud.ud_cm_handler %p", dummy_rc.cm_handler);
68470Sstevel@tonic-gate 	/*
68480Sstevel@tonic-gate 	 * Call all routines that the client's callback routine could call.
68490Sstevel@tonic-gate 	 */
68500Sstevel@tonic-gate 
68510Sstevel@tonic-gate 	return (IBT_CM_ACCEPT);
68520Sstevel@tonic-gate }
6853