xref: /illumos-gate/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_ti.c (revision 102439229bb71fe7a6c06721496138c39863ecea)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/ib/mgt/ibcm/ibcm_impl.h>
29 #include <sys/ib/ibtl/ibti.h>
30 
31 /*
32  * ibcm_ti.c
33  *	These routines implement the Communication Manager's interfaces to IBTL.
34  */
35 
36 /* CM rc recycle task args structure definition */
37 typedef struct ibcm_taskq_recycle_arg_s {
38 	ibt_channel_hdl_t	rc_chan;
39 	ibt_cep_flags_t		control;
40 	uint8_t			hca_port_num;
41 	ibt_recycle_handler_t	func;
42 	void			*arg;
43 } ibcm_taskq_recycle_arg_t;
44 
45 _NOTE(READ_ONLY_DATA(ibcm_taskq_recycle_arg_s))
46 
47 static ibt_status_t	ibcm_init_reply_addr(ibcm_hca_info_t *hcap,
48     ibcm_mad_addr_t *reply_addr, ibt_chan_open_args_t *chan_args,
49     ibt_chan_open_flags_t flags, ib_time_t *cm_pkt_lt, ib_lid_t prim_slid);
50 static void		ibcm_process_abort_via_taskq(void *args);
51 static ibt_status_t	ibcm_process_rc_recycle_ret(void *recycle_arg);
52 static ibt_status_t	ibcm_process_join_mcg(void *taskq_arg);
53 static void		ibcm_process_async_join_mcg(void *tq_arg);
54 
55 static ibt_status_t ibcm_get_node_rec(ibmf_saa_handle_t, sa_node_record_t *,
56     uint64_t c_mask, void *, size_t *);
57 
58 /* Address Record management definitions */
59 #define	IBCM_DAPL_ATS_NAME	"DAPL Address Translation Service"
60 #define	IBCM_DAPL_ATS_SID	0x10000CE100415453ULL
61 #define	IBCM_DAPL_ATS_NBYTES	16
62 ibcm_svc_info_t *ibcm_ar_svcinfop;
63 ibcm_ar_t	*ibcm_ar_list;
64 
65 #ifdef DEBUG
66 static void	ibcm_print_reply_addr(ibt_channel_hdl_t channel,
67 		    ibcm_mad_addr_t *cm_reply_addr);
68 #endif
69 
70 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_hdl}))
71 
72 /* access is controlled between ibcm_sm.c and ibcm_ti.c by CVs */
73 _NOTE(SCHEME_PROTECTS_DATA("Serialized access by CV", {ibt_rc_returns_t
74     ibt_ud_returns_t ibt_ap_returns_t ibt_ar_t}))
75 
76 /*
77  * Typically, clients initialize these args in one api call, and use in
78  * another api
79  */
80 _NOTE(SCHEME_PROTECTS_DATA("Expected usage of ibtl api by client",
81     {ibt_path_info_s ibt_cep_path_s ibt_adds_vect_s ibt_mcg_info_s ib_gid_s
82     ibt_ud_dest_attr_s ibt_ud_dest_s ibt_srv_data_s ibt_redirect_info_s}))
83 
84 /*
85  * ibt_open_rc_channel()
86  *	ibt_open_rc_channel opens a communication channel on the specified
87  *	channel to the specified service. For connection service type qp's
88  *	the CM initiates the CEP to establish the connection and transitions
89  *	the QP/EEC to the "Ready to send" State modifying the QP/EEC's
90  *	attributes as necessary.
91  *	The implementation of this function assumes that alt path is different
92  *	from primary path. It is assumed that the Path functions ensure that.
93  *
94  * RETURN VALUES:
95  *	IBT_SUCCESS	on success (or respective failure on error)
96  */
97 ibt_status_t
98 ibt_open_rc_channel(ibt_channel_hdl_t channel, ibt_chan_open_flags_t flags,
99     ibt_execution_mode_t mode, ibt_chan_open_args_t *chan_args,
100     ibt_rc_returns_t *ret_args)
101 {
102 	/* all fields that are related to REQ MAD formation */
103 
104 	ib_pkey_t		prim_pkey;
105 	ib_lid_t		primary_slid, alternate_slid;
106 	ib_qpn_t		local_qpn = 0;
107 	ib_guid_t		hca_guid;
108 	ib_qkey_t		local_qkey = 0;
109 	ib_eecn_t		local_eecn = 0;
110 	ib_eecn_t		remote_eecn = 0;
111 	boolean_t		primary_grh;
112 	boolean_t		alternate_grh = B_FALSE;
113 	ib_lid_t		base_lid;
114 	ib_com_id_t		local_comid;
115 	ibmf_msg_t		*ibmf_msg;
116 	ibcm_req_msg_t		*req_msgp;
117 
118 	uint8_t			rdma_in, rdma_out;
119 	uint8_t			cm_retries;
120 	uint64_t		local_cm_proc_time;	/* In usec */
121 	uint8_t			local_cm_resp_time;	/* IB time */
122 	uint64_t		remote_cm_resp_time;	/* In usec */
123 	uint32_t		starting_psn = 0;
124 
125 	/* CM path related fields */
126 	ibmf_handle_t		ibmf_hdl;
127 	ibcm_qp_list_t		*cm_qp_entry;
128 	ibcm_mad_addr_t		cm_reply_addr;
129 
130 	uint8_t			cm_pkt_lt;
131 
132 	/* Local args for ibtl/internal CM functions called within */
133 	ibt_status_t		status;
134 	ibcm_status_t		lkup_status;
135 	ibt_qp_query_attr_t	qp_query_attr;
136 
137 	/* Other misc local args */
138 	ibt_priv_data_len_t	len;
139 	ibcm_hca_info_t		*hcap;
140 	ibcm_state_data_t	*statep;
141 	uint8_t			port_no;
142 
143 	IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel(chan %p, %X, %x, %p, %p)",
144 	    channel, flags, mode, chan_args, ret_args);
145 
146 	if (IBCM_INVALID_CHANNEL(channel)) {
147 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: invalid channel");
148 		return (IBT_CHAN_HDL_INVALID);
149 	}
150 
151 	/* cm handler should always be specified */
152 	if (chan_args->oc_cm_handler == NULL) {
153 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
154 		    "CM handler is not be specified", channel);
155 		return (IBT_INVALID_PARAM);
156 	}
157 
158 	if (mode == IBT_NONBLOCKING) {
159 		if (ret_args != NULL) {
160 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
161 			    " ret_args should be NULL when called in "
162 			    "non-blocking mode", channel);
163 			return (IBT_INVALID_PARAM);
164 		}
165 	} else if (mode == IBT_BLOCKING) {
166 		if (ret_args == NULL) {
167 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
168 			    " ret_args should be Non-NULL when called in "
169 			    "blocking mode", channel);
170 			return (IBT_INVALID_PARAM);
171 		}
172 		if (ret_args->rc_priv_data_len > IBT_REP_PRIV_DATA_SZ) {
173 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
174 			    " private data length is too large", channel);
175 			return (IBT_INVALID_PARAM);
176 		}
177 		if ((ret_args->rc_priv_data_len > 0) &&
178 		    (ret_args->rc_priv_data == NULL)) {
179 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
180 			    " rc_priv_data_len > 0, but rc_priv_data NULL",
181 			    channel);
182 			return (IBT_INVALID_PARAM);
183 		}
184 	} else { /* any other mode is not valid for ibt_open_rc_channel */
185 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
186 		    "invalid mode %x specified", channel, mode);
187 		return (IBT_INVALID_PARAM);
188 	}
189 
190 	/*
191 	 * XXX: no support yet for ibt_chan_open_flags_t - IBT_OCHAN_DUP
192 	 */
193 	if (flags & IBT_OCHAN_DUP) {
194 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
195 		    "Unsupported Flags specified: 0x%X", channel, flags);
196 		return (IBT_INVALID_PARAM);
197 	}
198 
199 	if ((flags & IBT_OCHAN_REDIRECTED) &&
200 	    (flags & IBT_OCHAN_PORT_REDIRECTED)) {
201 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
202 		    "Illegal to specify IBT_OCHAN_REDIRECTED and "
203 		    "IBT_OCHAN_PORT_REDIRECTED flags together", channel);
204 		return (IBT_INVALID_PARAM);
205 	}
206 
207 	if (((flags & IBT_OCHAN_REDIRECTED) &&
208 	    (chan_args->oc_cm_redirect_info == NULL)) ||
209 	    ((flags & IBT_OCHAN_PORT_REDIRECTED) &&
210 	    (chan_args->oc_cm_cep_path == NULL))) {
211 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
212 		    "Redirect flag specified, but respective arg is NULL",
213 		    channel);
214 		return (IBT_INVALID_PARAM);
215 	}
216 
217 	if ((flags & IBT_OCHAN_REDIRECTED) &&
218 	    (chan_args->oc_cm_redirect_info->rdi_dlid == 0) &&
219 	    (chan_args->oc_cm_redirect_info->rdi_gid.gid_guid == 0)) {
220 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
221 		    "Either rdi_dlid or rdi_gid must be specified for"
222 		    " IBT_OCHAN_REDIRECTED", channel);
223 		return (IBT_INVALID_PARAM);
224 	}
225 
226 	/* primary dlid and hca_port_num should never be zero */
227 	port_no = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
228 
229 	if ((IBCM_PRIM_ADDS_VECT(chan_args).av_dlid == 0) && (port_no == 0)) {
230 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
231 		    "Primary Path's information is not valid", channel);
232 		return (IBT_INVALID_PARAM);
233 	}
234 
235 	/* validate SID */
236 	if (chan_args->oc_path->pi_sid == 0) {
237 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
238 		    "ERROR: Service ID in path information is 0", channel);
239 		return (IBT_INVALID_PARAM);
240 	}
241 
242 	/* validate rnr_retry_cnt (enum has more than 3 bits) */
243 	if ((uint_t)chan_args->oc_path_rnr_retry_cnt > IBT_RNR_INFINITE_RETRY) {
244 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
245 		    "ERROR: oc_path_rnr_retry_cnt(%d) is out of range",
246 		    channel, chan_args->oc_path_rnr_retry_cnt);
247 		return (IBT_INVALID_PARAM);
248 	}
249 
250 	/*
251 	 * Ensure that client is not re-using a QP that is still associated
252 	 * with a statep
253 	 */
254 	IBCM_GET_CHAN_PRIVATE(channel, statep);
255 	if (statep != NULL) {
256 		IBCM_RELEASE_CHAN_PRIVATE(channel);
257 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
258 		    "Channel being re-used on active side", channel);
259 		return (IBT_CHAN_IN_USE);
260 	}
261 
262 	/* Get GUID from Channel */
263 	hca_guid = ibt_channel_to_hca_guid(channel);
264 
265 	/* validate QP's hca guid with that from primary path  */
266 	if (hca_guid != chan_args->oc_path->pi_hca_guid) {
267 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
268 		    "GUID from Channel and primary path don't match", channel);
269 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
270 		    "Channel GUID %llX primary path GUID %llX", channel,
271 		    hca_guid, chan_args->oc_path->pi_hca_guid);
272 		return (IBT_CHAN_HDL_INVALID);
273 	}
274 
275 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
276 	    "Local HCA GUID %llX", channel, hca_guid);
277 
278 	status = ibt_query_qp(channel, &qp_query_attr);
279 	if (status != IBT_SUCCESS) {
280 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
281 		    "ibt_query_qp failed %d", channel, status);
282 		return (status);
283 	}
284 
285 	/* If client specified "no port change on QP" */
286 	if ((qp_query_attr.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
287 	    port_no) && (flags & IBT_OCHAN_PORT_FIXED)) {
288 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
289 		    "chan port %d and path port %d does not match", channel,
290 		    qp_query_attr.qp_info.qp_transport.rc.rc_path. \
291 		    cep_hca_port_num, port_no);
292 		return (IBT_INVALID_PARAM);
293 	}
294 
295 	if (qp_query_attr.qp_info.qp_trans != IBT_RC_SRV) {
296 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
297 		    "Invalid Channel type: Applicable only to RC Channel",
298 		    channel);
299 		return (IBT_CHAN_SRV_TYPE_INVALID);
300 	}
301 
302 	/* Check if QP is in INIT state or not */
303 	if (qp_query_attr.qp_info.qp_state != IBT_STATE_INIT) {
304 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
305 		    "QP is not in INIT state %x", channel,
306 		    qp_query_attr.qp_info.qp_state);
307 		return (IBT_CHAN_STATE_INVALID);
308 	}
309 
310 	local_qpn = qp_query_attr.qp_qpn;
311 
312 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p Active QPN 0x%x",
313 	    channel, local_qpn);
314 
315 #ifdef	NO_EEC_SUPPORT_YET
316 
317 	if (flags & IBT_OCHAN_RDC_EXISTS) {
318 		ibt_eec_query_attr_t	eec_query_attr;
319 
320 		local_qkey = qp_query_attr.qp_info.qp_transport.rd_qkey;
321 
322 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: RD");
323 
324 		status = ibt_query_eec(channel, &eec_query_attr);
325 		if (status != IBT_SUCCESS) {
326 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
327 			    " ibt_query_eec failed %d", channel, status);
328 			return (status);
329 		}
330 		local_eecn = eec_query_attr.eec_eecn;
331 	}
332 
333 #endif
334 
335 	/* If no HCA found return failure */
336 	if ((hcap = ibcm_find_hca_entry(hca_guid)) == NULL) {
337 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
338 		    "hcap is NULL. Probably hca is not in active state",
339 		    channel);
340 		return (IBT_CHAN_HDL_INVALID);
341 	}
342 
343 	rdma_out = chan_args->oc_rdma_ra_out;
344 	rdma_in = chan_args->oc_rdma_ra_in;
345 
346 	if ((rdma_in > hcap->hca_max_rdma_in_qp) ||
347 	    (rdma_out > hcap->hca_max_rdma_out_qp)) {
348 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
349 		    "rdma in %d/out %d values exceed hca limits", channel,
350 		    rdma_in, rdma_out);
351 		ibcm_dec_hca_acc_cnt(hcap);
352 		return (IBT_INVALID_PARAM);
353 	}
354 
355 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
356 	    "rdma_in %d rdma_out %d", channel, rdma_in, rdma_out);
357 
358 	if (chan_args->oc_path->pi_prim_pkt_lt > ibcm_max_ib_pkt_lt) {
359 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
360 		    "Huge Primary Pkt lt %d", channel,
361 		    chan_args->oc_path->pi_prim_pkt_lt);
362 		ibcm_dec_hca_acc_cnt(hcap);
363 		return (IBT_PATH_PKT_LT_TOO_HIGH);
364 	}
365 
366 	status = ibt_get_port_state_byguid(hcap->hca_guid, port_no,
367 	    NULL, &base_lid);
368 	if (status != IBT_SUCCESS) {
369 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
370 		    "primary port_num %d not active", channel, port_no);
371 		ibcm_dec_hca_acc_cnt(hcap);
372 		return (status);
373 	}
374 
375 	/* Validate P_KEY Index */
376 	status = ibt_index2pkey_byguid(hcap->hca_guid, port_no,
377 	    IBCM_PRIM_CEP_PATH(chan_args).cep_pkey_ix, &prim_pkey);
378 	if (status != IBT_SUCCESS) {
379 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
380 		    "Invalid Primary PKeyIx %x", channel,
381 		    IBCM_PRIM_CEP_PATH(chan_args).cep_pkey_ix);
382 		ibcm_dec_hca_acc_cnt(hcap);
383 		return (status);
384 	}
385 
386 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
387 	    "primary_port_num %d primary_pkey 0x%x", channel, port_no,
388 	    prim_pkey);
389 
390 	if ((hcap->hca_port_info[port_no - 1].port_ibmf_hdl == NULL) &&
391 	    ((status = ibcm_hca_reinit_port(hcap, port_no - 1))
392 	    != IBT_SUCCESS)) {
393 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
394 		    "ibmf reg or callback setup failed during re-initialize",
395 		    channel);
396 		ibcm_dec_hca_acc_cnt(hcap);
397 		return (status);
398 	}
399 
400 	ibmf_hdl = hcap->hca_port_info[port_no - 1].port_ibmf_hdl;
401 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
402 	    "primary ibmf_hdl = 0x%p", channel, ibmf_hdl);
403 
404 
405 	primary_slid = base_lid + IBCM_PRIM_ADDS_VECT(chan_args).av_src_path;
406 
407 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: channel 0x%p "
408 	    "primary SLID = %x", channel, primary_slid);
409 
410 	/* check first if alternate path exists or not as it is OPTIONAL */
411 	if (IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num != 0) {
412 		uint8_t	alt_port_no;
413 
414 		alt_port_no = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
415 
416 		if (chan_args->oc_path->pi_alt_pkt_lt > ibcm_max_ib_pkt_lt) {
417 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
418 			    "Huge Alt Pkt lt %d", channel,
419 			    chan_args->oc_path->pi_alt_pkt_lt);
420 			ibcm_dec_hca_acc_cnt(hcap);
421 			return (IBT_PATH_PKT_LT_TOO_HIGH);
422 		}
423 
424 		if (port_no != alt_port_no) {
425 
426 			status = ibt_get_port_state_byguid(hcap->hca_guid,
427 			    alt_port_no, NULL, &base_lid);
428 			if (status != IBT_SUCCESS) {
429 
430 				IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
431 				    "chan 0x%p alt_port_num %d inactive %d",
432 				    channel, alt_port_no, status);
433 				ibcm_dec_hca_acc_cnt(hcap);
434 				return (status);
435 			}
436 
437 		}
438 		alternate_slid =
439 		    base_lid + IBCM_ALT_ADDS_VECT(chan_args).av_src_path;
440 
441 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan %0xp "
442 		    "alternate SLID = %x", channel, alternate_slid);
443 	}
444 
445 	/*
446 	 * only pkey needs to be zero'ed, because all other fields are set in
447 	 * in ibcm_init_reply_addr. But, let's bzero the complete struct for
448 	 * any future modifications.
449 	 */
450 	bzero(&cm_reply_addr, sizeof (cm_reply_addr));
451 
452 	/* Initialize the MAD destination address in stored_reply_addr */
453 	if ((status = ibcm_init_reply_addr(hcap, &cm_reply_addr, chan_args,
454 	    flags, &cm_pkt_lt, primary_slid)) != IBT_SUCCESS) {
455 
456 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
457 		    "ibcm_init_reply_addr failed status %d ", channel, status);
458 		ibcm_dec_hca_acc_cnt(hcap);
459 		return (status);
460 	}
461 
462 
463 	/* Initialize the pkey for CM MAD communication */
464 	if (cm_reply_addr.rcvd_addr.ia_p_key == 0)
465 		cm_reply_addr.rcvd_addr.ia_p_key = prim_pkey;
466 
467 #ifdef DEBUG
468 	ibcm_print_reply_addr(channel, &cm_reply_addr);
469 #endif
470 
471 	/* Retrieve an ibmf qp for sending CM MADs */
472 	if ((cm_qp_entry = ibcm_find_qp(hcap, port_no,
473 	    cm_reply_addr.rcvd_addr.ia_p_key)) == NULL) {
474 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p "
475 		    "unable to allocate ibmf qp for CM MADs", channel);
476 		ibcm_dec_hca_acc_cnt(hcap);
477 		return (IBT_INSUFF_RESOURCE);
478 	}
479 
480 
481 	if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
482 		ibcm_release_qp(cm_qp_entry);
483 		ibcm_dec_hca_acc_cnt(hcap);
484 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan 0x%p"
485 		    " Unable to allocate comid", channel);
486 		return (IBT_INSUFF_KERNEL_RESOURCE);
487 	}
488 
489 	/* allocate an IBMF mad buffer */
490 	if ((status = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg,
491 	    MAD_METHOD_SEND)) != IBT_SUCCESS) {
492 		IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
493 		    "chan 0x%p ibcm_alloc_out_msg failed", channel);
494 		ibcm_release_qp(cm_qp_entry);
495 		ibcm_free_comid(hcap, local_comid);
496 		ibcm_dec_hca_acc_cnt(hcap);
497 		return (status);
498 	}
499 
500 	/* Init to Init, if QP's port does not match with path information */
501 	if (qp_query_attr.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
502 	    IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num) {
503 
504 		ibt_qp_info_t		qp_info;
505 		ibt_cep_modify_flags_t	cep_flags;
506 
507 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
508 		    "chan 0x%p chan port %d", channel,
509 		    qp_query_attr.qp_info.qp_transport.rc.rc_path.\
510 		    cep_hca_port_num);
511 
512 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
513 		    "chan 0x%p path port %d", channel, port_no);
514 
515 		bzero(&qp_info, sizeof (qp_info));
516 		/* For now, set it to RC type */
517 
518 		qp_info.qp_trans = IBT_RC_SRV;
519 		qp_info.qp_state = IBT_STATE_INIT;
520 		qp_info.qp_transport.rc.rc_path.cep_hca_port_num = port_no;
521 
522 		cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
523 
524 		status = ibt_modify_qp(channel, cep_flags, &qp_info, NULL);
525 
526 		if (status != IBT_SUCCESS) {
527 			IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: "
528 			    "chan 0x%p ibt_modify_qp() = %d", channel, status);
529 			ibcm_release_qp(cm_qp_entry);
530 			ibcm_free_comid(hcap, local_comid);
531 			ibcm_dec_hca_acc_cnt(hcap);
532 			(void) ibcm_free_out_msg(ibmf_hdl, &ibmf_msg);
533 			return (status);
534 		} else
535 			IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: "
536 			    "chan 0x%p ibt_modify_qp() = %d", channel, status);
537 	}
538 
539 	/* allocate ibcm_state_data_t before grabbing the WRITER lock */
540 	statep = kmem_zalloc(sizeof (ibcm_state_data_t), KM_SLEEP);
541 	rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
542 	lkup_status = ibcm_lookup_msg(IBCM_OUTGOING_REQ, local_comid, 0, 0,
543 	    hcap, &statep);
544 	rw_exit(&hcap->hca_state_rwlock);
545 
546 	/* CM should be seeing this for the first time */
547 	ASSERT(lkup_status == IBCM_LOOKUP_NEW);
548 
549 	/* Increment the hca's resource count */
550 	ibcm_inc_hca_res_cnt(hcap);
551 
552 	/* Once a resource created on hca, no need to hold the acc cnt */
553 	ibcm_dec_hca_acc_cnt(hcap);
554 
555 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
556 
557 	statep->timerid = 0;
558 	statep->local_hca_guid = hca_guid;
559 	statep->local_qpn = local_qpn;
560 	statep->stored_reply_addr.cm_qp_entry = cm_qp_entry;
561 	statep->prim_port = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
562 	statep->alt_port = IBCM_ALT_CEP_PATH(chan_args).cep_hca_port_num;
563 
564 
565 	/* Save "statep" as channel's CM private data.  */
566 	statep->channel = channel;
567 	IBCM_SET_CHAN_PRIVATE(statep->channel, statep);
568 
569 	statep->stored_msg = ibmf_msg;
570 
571 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*req_msgp))
572 
573 	/* Start filling in the REQ MAD */
574 	req_msgp = (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
575 	req_msgp->req_local_comm_id = h2b32(local_comid);
576 	req_msgp->req_svc_id = h2b64(chan_args->oc_path->pi_sid);
577 	req_msgp->req_local_ca_guid = h2b64(hca_guid);
578 	req_msgp->req_local_qkey = h2b32(local_qkey);	/* for EEC/RD */
579 
580 	/* Bytes 32-35 are req_local_qpn and req_off_resp_resources */
581 	req_msgp->req_local_qpn_plus = h2b32(local_qpn << 8 | rdma_in);
582 
583 	/* Bytes 36-39 are req_local_eec_no and req_off_initiator_depth */
584 	req_msgp->req_local_eec_no_plus = h2b32(local_eecn << 8 | rdma_out);
585 
586 	if (flags & IBT_OCHAN_REMOTE_CM_TM)
587 		remote_cm_resp_time = chan_args->oc_remote_cm_time;
588 	else
589 		remote_cm_resp_time = ibcm_remote_response_time;
590 
591 	/*
592 	 * Bytes 40-43 - remote_eecn, remote_cm_resp_time, tran_type,
593 	 * IBT_CM_FLOW_CONTROL is always set by default.
594 	 */
595 	req_msgp->req_remote_eecn_plus = h2b32(
596 	    remote_eecn << 8 | (ibt_usec2ib(remote_cm_resp_time) & 0x1f) << 3 |
597 	    IBT_RC_SRV << 1 | IBT_CM_FLOW_CONTROL);
598 
599 	if (flags & IBT_OCHAN_LOCAL_CM_TM)
600 		local_cm_proc_time = chan_args->oc_local_cm_time;
601 	else
602 		local_cm_proc_time = ibcm_local_processing_time;
603 
604 	local_cm_resp_time = ibt_usec2ib(local_cm_proc_time +
605 	    2 * ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt) +
606 	    ibcm_sw_delay);
607 
608 	/* save retry count */
609 	statep->cep_retry_cnt = chan_args->oc_path_retry_cnt;
610 
611 	if (flags & IBT_OCHAN_STARTING_PSN)
612 		starting_psn = chan_args->oc_starting_psn;
613 
614 	if (local_cm_resp_time > 0x1f)
615 		local_cm_resp_time = 0x1f;
616 
617 	/* Bytes 44-47 are req_starting_psn, local_cm_resp_time and retry_cnt */
618 	req_msgp->req_starting_psn_plus = h2b32(starting_psn << 8 |
619 	    local_cm_resp_time << 3 | statep->cep_retry_cnt);
620 
621 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
622 	    "Prim Pkt lt (IB time) 0x%x", channel,
623 	    chan_args->oc_path->pi_prim_pkt_lt);
624 
625 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
626 	    "local_cm_proc_time(usec) %d ", channel, local_cm_proc_time);
627 
628 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
629 	    "local_cm_resp_time(ib_time) %d", channel, local_cm_resp_time);
630 
631 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
632 	    "remote_cm_resp_time (usec) %d", channel, remote_cm_resp_time);
633 
634 	statep->starting_psn = starting_psn;
635 
636 	/* Pkey - bytes 48-49 */
637 	req_msgp->req_part_key = h2b16(prim_pkey);
638 
639 	if (flags & IBT_OCHAN_CM_RETRY)
640 		cm_retries = chan_args->oc_cm_retry_cnt;
641 	else
642 		cm_retries = ibcm_max_retries;
643 
644 	statep->max_cm_retries = statep->remaining_retry_cnt = cm_retries;
645 	req_msgp->req_max_cm_retries_plus = statep->max_cm_retries << 4;
646 
647 	/*
648 	 * Check whether SRQ is associated with this Channel, if yes, then
649 	 * set the SRQ Exists bit in the REQ.
650 	 */
651 	if (qp_query_attr.qp_srq != NULL) {
652 		req_msgp->req_max_cm_retries_plus |= (1 << 3);
653 	}
654 
655 	req_msgp->req_mtu_plus = chan_args->oc_path->pi_path_mtu << 4 |
656 	    chan_args->oc_path_rnr_retry_cnt;
657 
658 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p CM retry cnt %d"
659 	    " staring PSN %x", channel, cm_retries, starting_psn);
660 
661 
662 #ifdef	NO_EEC_SUPPORT_YET
663 	if (flags & IBT_OCHAN_RDC_EXISTS)
664 		req_msgp->req_mtu_plus |= 8;
665 #endif
666 
667 	/* Initialize the "primary" port stuff next - bytes 52-95 */
668 	req_msgp->req_primary_l_port_lid = h2b16(primary_slid);
669 	req_msgp->req_primary_r_port_lid =
670 	    h2b16(IBCM_PRIM_ADDS_VECT(chan_args).av_dlid);
671 	req_msgp->req_primary_l_port_gid.gid_prefix =
672 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_sgid.gid_prefix);
673 	req_msgp->req_primary_l_port_gid.gid_guid =
674 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_sgid.gid_guid);
675 	req_msgp->req_primary_r_port_gid.gid_prefix =
676 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_prefix);
677 	req_msgp->req_primary_r_port_gid.gid_guid =
678 	    h2b64(IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid);
679 	primary_grh = IBCM_PRIM_ADDS_VECT(chan_args).av_send_grh;
680 
681 	statep->remote_hca_guid = /* not correct, but helpful for debugging */
682 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid;
683 
684 	/* Bytes 88-91 - primary_flowlbl, and primary_srate */
685 	req_msgp->req_primary_flow_label_plus =
686 	    h2b32(((primary_grh == B_TRUE) ?
687 	    (IBCM_PRIM_ADDS_VECT(chan_args).av_flow << 12) : 0) |
688 	    IBCM_PRIM_ADDS_VECT(chan_args).av_srate);
689 	req_msgp->req_primary_traffic_class = (primary_grh == B_TRUE) ?
690 	    IBCM_PRIM_ADDS_VECT(chan_args).av_tclass : 0;
691 	req_msgp->req_primary_hop_limit = (primary_grh == B_TRUE) ?
692 	    IBCM_PRIM_ADDS_VECT(chan_args).av_hop : 0xff;
693 	req_msgp->req_primary_sl_plus =
694 	    IBCM_PRIM_ADDS_VECT(chan_args).av_srvl << 4 |
695 	    ((primary_grh == B_TRUE) ? 0 : 8);
696 
697 	req_msgp->req_primary_localtime_plus =
698 	    ibt_usec2ib((2 * ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt)) +
699 	    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
700 
701 	IBTF_DPRINTF_L2(cmlog, "ibt_open_rc_channel: chan %p statep %p",
702 	    channel, statep);
703 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
704 	    "active hca_ack_delay (usec) %d", channel,
705 	    req_msgp->req_primary_localtime_plus);
706 
707 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
708 	    "Sent primary cep timeout (IB Time) %d", channel,
709 	    hcap->hca_ack_delay);
710 
711 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p prim_dlid %x ",
712 	    channel, IBCM_PRIM_ADDS_VECT(chan_args).av_dlid);
713 
714 	IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
715 	    "prim GID %llX:%llX", channel,
716 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_prefix,
717 	    IBCM_PRIM_ADDS_VECT(chan_args).av_dgid.gid_guid);
718 
719 	/* Initialize the "alternate" port stuff - optional */
720 	if (chan_args->oc_path->pi_alt_cep_path.cep_hca_port_num != 0) {
721 		ib_gid_t	tmp_gid;
722 
723 		req_msgp->req_alt_l_port_lid = h2b16(alternate_slid);
724 		req_msgp->req_alt_r_port_lid =
725 		    h2b16(IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
726 		/*
727 		 * doing all this as req_alt_r/l_port_gid is at offset
728 		 * 100, 116 which is not divisible by 8
729 		 */
730 
731 		tmp_gid.gid_prefix =
732 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix);
733 		tmp_gid.gid_guid =
734 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
735 		bcopy(&tmp_gid, &req_msgp->req_alt_r_port_gid[0],
736 		    sizeof (ib_gid_t));
737 		tmp_gid.gid_prefix =
738 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_sgid.gid_prefix);
739 		tmp_gid.gid_guid =
740 		    h2b64(IBCM_ALT_ADDS_VECT(chan_args).av_sgid.gid_guid);
741 
742 		bcopy(&tmp_gid, &req_msgp->req_alt_l_port_gid[0],
743 		    sizeof (ib_gid_t));
744 		alternate_grh = IBCM_ALT_ADDS_VECT(chan_args).av_send_grh;
745 
746 		/* Bytes 132-135 - alternate_flow_label, and alternate srate */
747 		req_msgp->req_alt_flow_label_plus = h2b32(
748 		    (((alternate_grh == B_TRUE) ?
749 		    (IBCM_ALT_ADDS_VECT(chan_args).av_flow << 12) : 0) |
750 		    IBCM_ALT_ADDS_VECT(chan_args).av_srate));
751 		req_msgp->req_alt_traffic_class = (alternate_grh == B_TRUE) ?
752 		    IBCM_ALT_ADDS_VECT(chan_args).av_tclass : 0;
753 		req_msgp->req_alt_hop_limit = (alternate_grh == B_TRUE) ?
754 		    IBCM_ALT_ADDS_VECT(chan_args).av_hop : 0xff;
755 		req_msgp->req_alt_sl_plus =
756 		    IBCM_ALT_ADDS_VECT(chan_args).av_srvl << 4 |
757 		    ((alternate_grh == B_TRUE) ? 0 : 8);
758 		req_msgp->req_alt_localtime_plus = ibt_usec2ib((2 *
759 		    ibt_ib2usec(chan_args->oc_path->pi_alt_pkt_lt)) +
760 		    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
761 
762 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
763 		    "alt_dlid %x ", channel,
764 		    IBCM_ALT_ADDS_VECT(chan_args).av_dlid);
765 
766 		IBTF_DPRINTF_L5(cmlog, "ibt_open_rc_channel: chan 0x%p "
767 		    "alt GID %llX:%llX", channel,
768 		    IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_prefix,
769 		    IBCM_ALT_ADDS_VECT(chan_args).av_dgid.gid_guid);
770 	}
771 
772 	len = min(chan_args->oc_priv_data_len, IBT_REQ_PRIV_DATA_SZ);
773 	if ((len > 0) && chan_args->oc_priv_data)
774 		bcopy(chan_args->oc_priv_data, req_msgp->req_private_data, len);
775 
776 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*req_msgp))
777 
778 	/* return_data is filled up in the state machine code */
779 	if (ret_args != NULL) {
780 		statep->open_return_data = ret_args;
781 	}
782 
783 	/* initialize some statep fields here */
784 	statep->mode = IBCM_ACTIVE_MODE;
785 	statep->hcap = hcap;
786 
787 	statep->cm_handler = chan_args->oc_cm_handler;
788 	statep->state_cm_private = chan_args->oc_cm_clnt_private;
789 
790 	statep->pkt_life_time =
791 	    ibt_ib2usec(chan_args->oc_path->pi_prim_pkt_lt);
792 
793 	statep->timer_value = ibt_ib2usec(ibt_usec2ib(
794 	    2 * ibt_ib2usec(cm_pkt_lt) + remote_cm_resp_time));
795 
796 	/* Initialize statep->stored_reply_addr */
797 	statep->stored_reply_addr.ibmf_hdl = ibmf_hdl;
798 
799 	/* Initialize stored reply addr fields */
800 	statep->stored_reply_addr.grh_hdr = cm_reply_addr.grh_hdr;
801 	statep->stored_reply_addr.rcvd_addr = cm_reply_addr.rcvd_addr;
802 	statep->stored_reply_addr.grh_exists = cm_reply_addr.grh_exists;
803 	statep->stored_reply_addr.port_num = cm_reply_addr.port_num;
804 
805 	/*
806 	 * The IPD on local/active side is calculated by path functions,
807 	 * hence available in the args of ibt_open_rc_channel
808 	 */
809 	statep->local_srate = IBCM_PRIM_ADDS_VECT(chan_args).av_srate;
810 	statep->local_alt_srate = IBCM_ALT_ADDS_VECT(chan_args).av_srate;
811 
812 	/* Store the source path bits for primary and alt paths */
813 	statep->prim_src_path_bits = IBCM_PRIM_ADDS_VECT(chan_args).av_src_path;
814 	statep->alt_src_path_bits = IBCM_ALT_ADDS_VECT(chan_args).av_src_path;
815 
816 	statep->open_flow = 1;
817 	statep->open_done = B_FALSE;
818 	statep->state = statep->timer_stored_state = IBCM_STATE_REQ_SENT;
819 	IBCM_REF_CNT_INCR(statep);	/* Decremented before return */
820 	IBCM_REF_CNT_INCR(statep);	/* Decremented after REQ is posted */
821 	statep->send_mad_flags |= IBCM_REQ_POST_BUSY;
822 
823 	IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
824 	    h2b16(IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID);
825 
826 	IBCM_OUT_HDRP(statep->stored_msg)->TransactionID =
827 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_REQ, statep->local_comid,
828 	    0));
829 
830 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
831 
832 	ibcm_open_enqueue(statep);
833 
834 	mutex_enter(&statep->state_mutex);
835 
836 	if (mode == IBT_BLOCKING) {
837 
838 		/* wait for REQ/REP/RTU */
839 		while (statep->open_done != B_TRUE) {
840 			cv_wait(&statep->block_client_cv, &statep->state_mutex);
841 		}
842 
843 		/*
844 		 * In the case that open_channel() fails because of a
845 		 * REJ or timeout, change retval to IBT_CM_FAILURE
846 		 */
847 		if (statep->open_return_data->rc_status != IBT_CM_ACCEPT)
848 			status = IBT_CM_FAILURE;
849 
850 		IBTF_DPRINTF_L3(cmlog, "ibt_open_rc_channel: chan 0x%p "
851 		    "ret status %d cm status %d", channel, status,
852 		    statep->open_return_data->rc_status);
853 	}
854 
855 	/* decrement the ref-count before leaving here */
856 	IBCM_REF_CNT_DECR(statep);
857 
858 	mutex_exit(&statep->state_mutex);
859 
860 	IBTF_DPRINTF_L4(cmlog, "ibt_open_rc_channel: chan 0x%p done", channel);
861 	return (status);
862 }
863 
864 /*
865  * ibcm_init_reply_addr:
866  *
867  * The brief description of functionality below.
868  *
869  * For IBT_OCHAN_PORT_REDIRECTED (ie., port redirected case):
870  *	Build CM path from chan_args->oc_cm_cep_path
871  *	Set CM pkt lt (ie.,life time) to chan_args->oc_cm_pkt_lt
872  *
873  * For IBT_OCHAN_REDIRECTED (ie., port and CM redirected case):
874  *	If Redirect LID is specified,
875  *		If Redirect GID is not specified or specified to be on the same
876  *		    subnet, then
877  *			Build CM path from chan_args->oc_cm_redirect_info
878  *			Set CM pkt lt to subnet timeout
879  *		Else (ie., GID specified, but on a different subnet)
880  *			Do a path lookup to build CM Path and set CM pkt lt
881  *
882  */
883 static ibt_status_t
884 ibcm_init_reply_addr(ibcm_hca_info_t *hcap, ibcm_mad_addr_t *reply_addr,
885     ibt_chan_open_args_t *chan_args, ibt_chan_open_flags_t flags,
886     ib_time_t *cm_pkt_lt, ib_lid_t prim_slid)
887 {
888 	ibt_adds_vect_t	*cm_adds;
889 	ibt_path_info_t	path;
890 	boolean_t	cm_grh;
891 	ibt_status_t	status;
892 
893 	IBTF_DPRINTF_L5(cmlog, "ibcm_init_reply_addr:");
894 
895 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*reply_addr))
896 
897 	/*
898 	 * sending side CM lid/gid/port num are not based on any redirect
899 	 * params. These values are set to primary RC path lid/gid/port num.
900 	 * In the future, these values can be set based on framework policy
901 	 * decisions ensuring reachability.
902 	 */
903 	reply_addr->grh_hdr.ig_sender_gid =
904 	    IBCM_PRIM_ADDS_VECT(chan_args).av_sgid;
905 	reply_addr->rcvd_addr.ia_local_lid = prim_slid;
906 	reply_addr->port_num = IBCM_PRIM_CEP_PATH(chan_args).cep_hca_port_num;
907 
908 	if (flags & IBT_OCHAN_PORT_REDIRECTED) {
909 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
910 		    "IBT_OCHAN_PORT_REDIRECTED specified");
911 
912 		status = ibt_index2pkey_byguid(hcap->hca_guid,
913 		    chan_args->oc_cm_cep_path->cep_hca_port_num,
914 		    chan_args->oc_cm_cep_path->cep_pkey_ix,
915 		    &reply_addr->rcvd_addr.ia_p_key);
916 
917 		if (status != IBT_SUCCESS) {
918 			IBTF_DPRINTF_L2(cmlog, "ibcm_init_rely_addr: Invalid "
919 			    "CM PKeyIx %x port_num %x",
920 			    chan_args->oc_cm_cep_path->cep_pkey_ix,
921 			    chan_args->oc_cm_cep_path->cep_hca_port_num);
922 			return (status);
923 		}
924 
925 		cm_adds = &(chan_args->oc_cm_cep_path->cep_adds_vect);
926 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: dlid = %x",
927 		    cm_adds->av_dlid);
928 
929 		reply_addr->rcvd_addr.ia_q_key = IB_GSI_QKEY;
930 		reply_addr->rcvd_addr.ia_remote_qno = 1;
931 		*cm_pkt_lt = chan_args->oc_cm_pkt_lt;
932 
933 	} else if (flags & IBT_OCHAN_REDIRECTED) {
934 		ibt_redirect_info_t	*redirect_info;
935 		ibt_hca_portinfo_t	*port_infop;
936 		uint_t			psize, nports;
937 
938 		IBTF_DPRINTF_L4(cmlog, "ibcm_init_rely_addr: "
939 		    "IBT_OCHAN_REDIRECTED specified");
940 
941 		redirect_info = chan_args->oc_cm_redirect_info;
942 
943 		if ((redirect_info->rdi_gid.gid_prefix == 0) ||
944 		    (redirect_info->rdi_gid.gid_guid == 0)) {
945 			IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
946 			    "ERROR: Re-direct GID value NOT Provided.");
947 			return (IBT_INVALID_PARAM);
948 		}
949 
950 		/* As per spec definition 1.1, it's always IB_GSI_QKEY */
951 		reply_addr->rcvd_addr.ia_q_key = redirect_info->rdi_qkey;
952 		reply_addr->rcvd_addr.ia_remote_qno = redirect_info->rdi_qpn;
953 		reply_addr->rcvd_addr.ia_p_key = redirect_info->rdi_pkey;
954 
955 		/*
956 		 * if LID is non-zero in classportinfo then use classportinfo
957 		 * fields to form CM MAD destination address.
958 		 */
959 		if (redirect_info->rdi_dlid != 0) {
960 			status = ibtl_cm_query_hca_ports_byguid(hcap->hca_guid,
961 			    reply_addr->port_num, &port_infop, &nports, &psize);
962 			if ((status != IBT_SUCCESS) || (nports == 0)) {
963 				IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
964 				    "Query Ports Failed: %d", status);
965 				return (status);
966 			} else if (port_infop->p_subnet_timeout >
967 			    IBCM_MAX_IB_PKT_LT) {
968 				IBTF_DPRINTF_L2(cmlog, "ibcm_init_reply_addr: "
969 				    "large subnet timeout %x port_no %x",
970 				    port_infop->p_subnet_timeout,
971 				    reply_addr->port_num);
972 				ibt_free_portinfo(port_infop, psize);
973 				return (IBT_PATH_PKT_LT_TOO_HIGH);
974 			} else {
975 				IBTF_DPRINTF_L3(cmlog, "ibcm_init_reply_addr: "
976 				    "subnet timeout %x port_no %x",
977 				    port_infop->p_subnet_timeout,
978 				    reply_addr->port_num);
979 
980 				*cm_pkt_lt =
981 				    ibt_ib2usec(min(ibcm_max_ib_mad_pkt_lt,
982 				    port_infop->p_subnet_timeout));
983 
984 				ibt_free_portinfo(port_infop, psize);
985 			}
986 
987 			reply_addr->rcvd_addr.ia_remote_lid =
988 			    redirect_info->rdi_dlid;
989 			reply_addr->rcvd_addr.ia_service_level =
990 			    redirect_info->rdi_sl;
991 			reply_addr->grh_exists = B_TRUE;
992 			reply_addr->grh_hdr.ig_recver_gid =
993 			    redirect_info->rdi_gid;
994 			reply_addr->grh_hdr.ig_tclass =
995 			    redirect_info->rdi_tclass;
996 			reply_addr->grh_hdr.ig_flow_label =
997 			    redirect_info->rdi_flow;
998 
999 			/* Classportinfo doesn't have hoplimit field */
1000 			reply_addr->grh_hdr.ig_hop_limit = 0xff;
1001 			return (IBT_SUCCESS);
1002 
1003 		} else {
1004 			ibt_path_attr_t	path_attr;
1005 			ib_gid_t	path_dgid[1];
1006 
1007 			/*
1008 			 * If GID is specified, and LID is zero in classportinfo
1009 			 * do a path lookup using specified GID, Pkey,
1010 			 * in classportinfo
1011 			 */
1012 
1013 			bzero(&path_attr, sizeof (path_attr));
1014 
1015 			path_attr.pa_dgids = &path_dgid[0];
1016 			path_attr.pa_dgids[0] = redirect_info->rdi_gid;
1017 
1018 			/*
1019 			 * use reply_addr below, as sender_gid in reply_addr
1020 			 * may have been set above based on some policy decision
1021 			 * for originating end point for CM MADs above
1022 			 */
1023 			path_attr.pa_sgid = reply_addr->grh_hdr.ig_sender_gid;
1024 			path_attr.pa_num_dgids = 1;
1025 			path_attr.pa_pkey = redirect_info->rdi_pkey;
1026 
1027 			if ((status = ibt_get_paths(ibcm_ibt_handle,
1028 			    IBT_PATH_PKEY, &path_attr, 1, &path, NULL)) !=
1029 			    IBT_SUCCESS)
1030 				return (status);
1031 
1032 			/* Initialize cm_adds */
1033 			cm_adds = &path.pi_prim_cep_path.cep_adds_vect;
1034 			*cm_pkt_lt = path.pi_prim_pkt_lt;
1035 		}
1036 
1037 	} else	{ /* cm_pkey initialized in ibt_open_rc_channel */
1038 		reply_addr->rcvd_addr.ia_q_key = IB_GSI_QKEY;
1039 		reply_addr->rcvd_addr.ia_remote_qno = 1;
1040 		*cm_pkt_lt = chan_args->oc_path->pi_prim_pkt_lt;
1041 		cm_adds = &(IBCM_PRIM_ADDS_VECT(chan_args));
1042 	}
1043 
1044 
1045 	cm_grh = cm_adds->av_send_grh;
1046 	reply_addr->grh_exists = cm_grh;
1047 
1048 	reply_addr->rcvd_addr.ia_remote_lid =
1049 	    cm_adds->av_dlid;
1050 	reply_addr->grh_hdr.ig_recver_gid =
1051 	    cm_adds->av_dgid;
1052 	reply_addr->grh_hdr.ig_flow_label =
1053 	    cm_adds->av_flow & IB_GRH_FLOW_LABEL_MASK;
1054 	reply_addr->grh_hdr.ig_tclass =
1055 	    (cm_grh == B_TRUE) ? cm_adds->av_tclass : 0;
1056 	reply_addr->grh_hdr.ig_hop_limit =
1057 	    (cm_grh == B_TRUE) ? cm_adds->av_hop : 0xff;
1058 	reply_addr->rcvd_addr.ia_service_level =
1059 	    cm_adds->av_srvl;
1060 
1061 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*reply_addr))
1062 
1063 	return (IBT_SUCCESS);
1064 }
1065 
1066 
1067 /*
1068  * ibt_prime_close_rc_channel()
1069  *	It allocates resources required for close channel operation, so
1070  *	ibt_close_rc_channel can be called from interrupt routine.
1071  *
1072  * INPUTS:
1073  *	channel			The address of an ibt_channel_t struct that
1074  *				specifies the channel to open.
1075  *
1076  * RETURN VALUES:
1077  *	IBT_SUCCESS	on success(or respective failure on error)
1078  *
1079  * Clients are typically expected to call this function in established state
1080  */
1081 ibt_status_t
1082 ibt_prime_close_rc_channel(ibt_channel_hdl_t channel)
1083 {
1084 	ibcm_state_data_t	*statep;
1085 	ibt_status_t		status = IBT_SUCCESS;
1086 
1087 	IBTF_DPRINTF_L3(cmlog, "ibt_prime_close_rc_channel(%p)", channel);
1088 
1089 	/* validate channel, first */
1090 	if (IBCM_INVALID_CHANNEL(channel)) {
1091 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
1092 		    "invalid channel", channel);
1093 		return (IBT_CHAN_HDL_INVALID);
1094 	}
1095 
1096 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
1097 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
1098 		    "Invalid Channel type: Applicable only to RC Channel",
1099 		    channel);
1100 		return (IBT_CHAN_SRV_TYPE_INVALID);
1101 	}
1102 
1103 	/* get the statep */
1104 	IBCM_GET_CHAN_PRIVATE(channel, statep);
1105 
1106 	/*
1107 	 * This can happen, if the statep is already gone by a DREQ from
1108 	 * the remote side
1109 	 */
1110 
1111 	if (statep == NULL) {
1112 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
1113 		    "statep NULL", channel);
1114 		return (IBT_SUCCESS);
1115 	}
1116 
1117 	mutex_enter(&statep->state_mutex);
1118 	IBCM_RELEASE_CHAN_PRIVATE(channel);
1119 	if (statep->state != IBCM_STATE_ESTABLISHED) {
1120 		mutex_exit(&statep->state_mutex);
1121 		return (IBT_CHAN_STATE_INVALID);
1122 	}
1123 	IBCM_REF_CNT_INCR(statep);
1124 	IBTF_DPRINTF_L4(cmlog, "ibt_prime_close_rc_channel: chan 0x%p statep %p"
1125 	    " state %x", channel, statep, statep->state);
1126 	mutex_exit(&statep->state_mutex);
1127 
1128 	/* clients could pre-allocate dreq mad, even before connection est */
1129 	if (statep->dreq_msg == NULL)
1130 		status = ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl,
1131 		    &statep->dreq_msg, MAD_METHOD_SEND);
1132 
1133 	mutex_enter(&statep->state_mutex);
1134 	IBCM_REF_CNT_DECR(statep);
1135 	mutex_exit(&statep->state_mutex);
1136 
1137 	if (status != IBT_SUCCESS) {
1138 		IBTF_DPRINTF_L2(cmlog, "ibt_prime_close_rc_channel: chan 0x%p "
1139 		    "ibcm_alloc_out_msg failed ", channel);
1140 		return (status);
1141 	}
1142 
1143 	/* If this message isn't seen then ibt_prime_close_rc_channel failed */
1144 	IBTF_DPRINTF_L5(cmlog, "ibt_prime_close_rc_channel: chan 0x%p done",
1145 	    channel);
1146 
1147 	return (IBT_SUCCESS);
1148 }
1149 
1150 /*
1151  * ibt_close_rc_channel()
1152  *	It closes an established channel.
1153  *
1154  * RETURN VALUES:
1155  *	IBT_SUCCESS	on success(or respective failure on error)
1156  */
1157 ibt_status_t
1158 ibt_close_rc_channel(ibt_channel_hdl_t channel, ibt_execution_mode_t mode,
1159     void *priv_data, ibt_priv_data_len_t priv_data_len, uint8_t *ret_status,
1160     void *ret_priv_data, ibt_priv_data_len_t *ret_priv_data_len_p)
1161 {
1162 	ibcm_hca_info_t		*hcap;
1163 	ibcm_state_data_t	*statep;
1164 	ibt_status_t		status;
1165 
1166 	IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel(%p, %x, %p, %d, %p)",
1167 	    channel, mode, priv_data, priv_data_len,
1168 	    (ret_priv_data_len_p == NULL) ? 0 : *ret_priv_data_len_p);
1169 
1170 	/* validate channel, first */
1171 	if (IBCM_INVALID_CHANNEL(channel)) {
1172 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
1173 		    "invalid channel", channel);
1174 		return (IBT_CHAN_HDL_INVALID);
1175 	}
1176 
1177 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
1178 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
1179 		    "Invalid Channel type: Applicable only to RC Channel",
1180 		    channel);
1181 		return (IBT_CHAN_SRV_TYPE_INVALID);
1182 	}
1183 
1184 	if (mode == IBT_BLOCKING) {
1185 		/* valid only for BLOCKING MODE */
1186 		if ((ret_priv_data_len_p != NULL) &&
1187 		    (*ret_priv_data_len_p > IBT_DREP_PRIV_DATA_SZ)) {
1188 			IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p"
1189 			    " private data len %d is too large", channel,
1190 			    *ret_priv_data_len_p);
1191 			return (IBT_INVALID_PARAM);
1192 		}
1193 	} else if ((mode != IBT_NONBLOCKING) && (mode != IBT_NOCALLBACKS)) {
1194 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
1195 		    "invalid mode %x specified", channel, mode);
1196 		return (IBT_INVALID_PARAM);
1197 	}
1198 
1199 	/* get the statep */
1200 	IBCM_GET_CHAN_PRIVATE(channel, statep);
1201 
1202 	if (statep == NULL) {
1203 
1204 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
1205 		    "statep NULL", channel);
1206 		if (ibtl_cm_is_chan_closing(channel) ||
1207 		    ibtl_cm_is_chan_closed(channel)) {
1208 			if (ret_status)
1209 				*ret_status = IBT_CM_CLOSED_ALREADY;
1210 
1211 			/* No private data to return to the client */
1212 			if (ret_priv_data_len_p != NULL)
1213 				*ret_priv_data_len_p = 0;
1214 
1215 			return (IBT_SUCCESS);
1216 		}
1217 		return (IBT_CHAN_STATE_INVALID);
1218 	}
1219 
1220 	mutex_enter(&statep->state_mutex);
1221 	IBCM_RELEASE_CHAN_PRIVATE(channel);
1222 	IBCM_REF_CNT_INCR(statep);
1223 	mutex_exit(&statep->state_mutex);
1224 
1225 	IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel: chan 0x%p statep %p",
1226 	    channel, statep);
1227 
1228 	mutex_enter(&statep->state_mutex);
1229 	hcap = statep->hcap;
1230 
1231 	/* HCA must have been in active state. If not, it's a client bug */
1232 	if (!IBCM_ACCESS_HCA_OK(hcap)) {
1233 		IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: chan 0x%p "
1234 		    "hcap 0x%p not active", channel, hcap);
1235 		IBCM_REF_CNT_DECR(statep);
1236 		mutex_exit(&statep->state_mutex);
1237 		return (IBT_CHAN_HDL_INVALID);
1238 	}
1239 
1240 	if (statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) {
1241 		while (statep->cep_in_rts == IBCM_BLOCK)
1242 			cv_wait(&statep->block_mad_cv, &statep->state_mutex);
1243 	}
1244 
1245 	/* Do TRANSIENT_DREQ check after TRANSIENT_ESTABLISHED check */
1246 	while (statep->state == IBCM_STATE_TRANSIENT_DREQ_SENT)
1247 		cv_wait(&statep->block_mad_cv, &statep->state_mutex);
1248 
1249 	IBTF_DPRINTF_L4(cmlog, "ibt_close_rc_channel: chan 0x%p "
1250 	    "connection state is %x", channel, statep->state);
1251 
1252 	statep->close_ret_status = ret_status;
1253 
1254 	/* If state is in pre-established states, abort the connection est */
1255 	if (statep->state != IBCM_STATE_ESTABLISHED) {
1256 		statep->cm_retries++;	/* ensure connection trace is dumped */
1257 
1258 		/* No DREP private data possible */
1259 		if (ret_priv_data_len_p != NULL)
1260 			*ret_priv_data_len_p = 0;
1261 
1262 		/*
1263 		 * If waiting for a response mad, then cancel the timer,
1264 		 * and delete the connection
1265 		 */
1266 		if (statep->state == IBCM_STATE_REQ_SENT ||
1267 		    statep->state == IBCM_STATE_REP_SENT ||
1268 		    statep->state == IBCM_STATE_REP_WAIT ||
1269 		    statep->state == IBCM_STATE_MRA_REP_RCVD) {
1270 			timeout_id_t		timer_val = statep->timerid;
1271 			ibcm_conn_state_t	old_state;
1272 
1273 			IBTF_DPRINTF_L4(cmlog, "ibt_close_rc_channel: "
1274 			    "chan 0x%p connection aborted in state %x", channel,
1275 			    statep->state);
1276 
1277 			old_state = statep->state;
1278 			statep->state = IBCM_STATE_DELETE;
1279 
1280 			if (mode == IBT_NONBLOCKING) {
1281 				if (taskq_dispatch(ibcm_taskq,
1282 				    ibcm_process_abort_via_taskq, statep,
1283 				    TQ_NOSLEEP) == 0) {
1284 
1285 					IBCM_REF_CNT_DECR(statep);
1286 					statep->state = old_state;
1287 					mutex_exit(&statep->state_mutex);
1288 					return (IBT_INSUFF_KERNEL_RESOURCE);
1289 				}	/* if taskq_dispatch succeeds */
1290 				/* Cancel the timer */
1291 				statep->timerid = 0;
1292 				mutex_exit(&statep->state_mutex);
1293 			} else {
1294 				/* Cancel the timer */
1295 				statep->timerid = 0;
1296 				mutex_exit(&statep->state_mutex);
1297 				(void) taskq_dispatch(ibcm_taskq,
1298 				    ibcm_process_abort_via_taskq, statep,
1299 				    TQ_SLEEP);
1300 			}
1301 
1302 			/* cancel the currently running timer */
1303 			if (timer_val != 0)
1304 				(void) untimeout(timer_val);
1305 
1306 			/* wait until cm handler returns for BLOCKING cases */
1307 			if ((mode == IBT_BLOCKING) ||
1308 			    (mode == IBT_NOCALLBACKS)) {
1309 				mutex_enter(&statep->state_mutex);
1310 				while (statep->close_done != B_TRUE)
1311 					cv_wait(&statep->block_client_cv,
1312 					    &statep->state_mutex);
1313 				mutex_exit(&statep->state_mutex);
1314 			}
1315 
1316 			if (ret_status)
1317 				*ret_status = IBT_CM_CLOSED_ABORT;
1318 
1319 			/*
1320 			 * It would ideal to post a REJ MAD, but that would
1321 			 * be non-conformance to spec. Hence, delete the state
1322 			 * data. Assuming that happens quickly, any retransmits
1323 			 * from the remote are replied by CM with reject
1324 			 * reason " no valid com id". That would stop remote
1325 			 * sending any more MADs.
1326 			 */
1327 			ibcm_delete_state_data(statep);
1328 			return (IBT_SUCCESS);
1329 
1330 		/* if CM busy in cm handler, wait until cm handler returns */
1331 		} else if (statep->state == IBCM_STATE_REQ_RCVD ||
1332 		    statep->state == IBCM_STATE_REP_RCVD ||
1333 		    statep->state == IBCM_STATE_MRA_SENT ||
1334 		    statep->state == IBCM_STATE_MRA_REP_SENT) {
1335 
1336 			/* take control of statep */
1337 			statep->abort_flag |= IBCM_ABORT_CLIENT;
1338 
1339 			IBTF_DPRINTF_L4(cmlog, "ibt_close_rc_channel: "
1340 			    "chan 0x%p connection aborted in state = %x",
1341 			    channel, statep->state);
1342 
1343 			/*
1344 			 * wait until state machine modifies qp state to error,
1345 			 * including disassociating statep and QP
1346 			 */
1347 			if ((mode == IBT_BLOCKING) || (mode == IBT_NOCALLBACKS))
1348 				while (statep->close_done != B_TRUE)
1349 					cv_wait(&statep->block_client_cv,
1350 					    &statep->state_mutex);
1351 
1352 			/* a sanity setting */
1353 			if (mode == IBT_NOCALLBACKS)
1354 				statep->cm_handler = NULL;
1355 			IBCM_REF_CNT_DECR(statep);
1356 			mutex_exit(&statep->state_mutex);
1357 
1358 			/*
1359 			 * In rare situations, connection attempt could be
1360 			 * terminated for some other reason, before abort is
1361 			 * processed, but CM still returns ret_status as abort
1362 			 */
1363 			if (ret_status)
1364 				*ret_status = IBT_CM_CLOSED_ABORT;
1365 
1366 			/*
1367 			 * REJ MAD is posted by the CM state machine for this
1368 			 * case, hence state structure is deleted in the
1369 			 * state machine processing.
1370 			 */
1371 			return (IBT_SUCCESS);
1372 
1373 		} else if ((statep->state == IBCM_STATE_TIMEWAIT) ||
1374 		    (statep->state == IBCM_STATE_DELETE)) {
1375 
1376 			/* State already in timewait, so no return priv data */
1377 			IBCM_REF_CNT_DECR(statep);
1378 			mutex_exit(&statep->state_mutex);
1379 
1380 			/* The teardown has already been done */
1381 			if (ret_status)
1382 				*ret_status = IBT_CM_CLOSED_ALREADY;
1383 
1384 			return (IBT_SUCCESS);
1385 
1386 		} else if ((statep->state == IBCM_STATE_DREQ_RCVD) ||
1387 		    (statep->state == IBCM_STATE_DREQ_SENT) ||
1388 		    (statep->state == IBCM_STATE_DREP_RCVD) ||
1389 		    ((statep->state == IBCM_STATE_TIMED_OUT) &&
1390 		    (statep->timedout_state == IBCM_STATE_DREQ_SENT))) {
1391 
1392 			/*
1393 			 * Either the remote or local client has already
1394 			 * initiated the teardown.  IBCM_STATE_DREP_RCVD is
1395 			 * possible, if CM initiated teardown without client's
1396 			 * knowledge, for stale handling, etc.,
1397 			 */
1398 			if (mode == IBT_NOCALLBACKS) {
1399 				if (statep->close_nocb_state == IBCM_UNBLOCK) {
1400 					statep->close_nocb_state = IBCM_FAIL;
1401 					/* enable free qp after return */
1402 					ibtl_cm_chan_is_closing(
1403 					    statep->channel);
1404 				} else while (statep->close_nocb_state ==
1405 				    IBCM_BLOCK)
1406 					cv_wait(&statep->block_client_cv,
1407 					    &statep->state_mutex);
1408 				statep->cm_handler = NULL; /* sanity setting */
1409 				if (ret_status)
1410 					*ret_status = IBT_CM_CLOSED_ALREADY;
1411 			} else if (mode == IBT_BLOCKING) {
1412 				/* wait until state is moved to timewait */
1413 				while (statep->close_done != B_TRUE)
1414 					cv_wait(&statep->block_client_cv,
1415 					    &statep->state_mutex);
1416 			}
1417 
1418 			IBCM_REF_CNT_DECR(statep);
1419 			mutex_exit(&statep->state_mutex);
1420 
1421 			/* ret_status is set in state machine code */
1422 			return (IBT_SUCCESS);
1423 
1424 		} else if (statep->state == IBCM_STATE_TIMED_OUT) {
1425 
1426 			if ((mode == IBT_BLOCKING) ||
1427 			    (mode == IBT_NOCALLBACKS)) {
1428 
1429 				/*
1430 				 * wait until cm handler invocation and
1431 				 * disassociation between statep and channel
1432 				 * is complete
1433 				 */
1434 				while (statep->close_done != B_TRUE)
1435 					cv_wait(&statep->block_client_cv,
1436 					    &statep->state_mutex);
1437 			}
1438 
1439 			if (ret_status)
1440 				*ret_status = IBT_CM_CLOSED_ABORT;
1441 			IBCM_REF_CNT_DECR(statep);
1442 			mutex_exit(&statep->state_mutex);
1443 
1444 			return (IBT_SUCCESS);
1445 		} else {
1446 			IBCM_REF_CNT_DECR(statep);
1447 			mutex_exit(&statep->state_mutex);
1448 
1449 			return (IBT_CM_FAILURE);
1450 		}
1451 	}
1452 
1453 	ASSERT(statep->close_nocb_state != IBCM_BLOCK);
1454 
1455 	if (mode == IBT_NOCALLBACKS) {
1456 		statep->close_nocb_state = IBCM_FAIL;
1457 		statep->cm_handler = NULL;
1458 		ibtl_cm_chan_is_closing(statep->channel);
1459 		IBTF_DPRINTF_L4(cmlog, "ibt_close_rc_channel: "
1460 		    "NOCALLBACKS on in statep = %p", statep);
1461 	}
1462 	mutex_exit(&statep->state_mutex);
1463 
1464 	mutex_enter(&statep->state_mutex);
1465 	if (statep->state != IBCM_STATE_ESTABLISHED) {
1466 		goto lost_race;
1467 	}
1468 
1469 	/*
1470 	 * Cancel/wait for any pending ibt_set_alt_path, and
1471 	 * release state mutex
1472 	 */
1473 	ibcm_sync_lapr_idle(statep);
1474 
1475 	ibcm_close_enter();
1476 
1477 	mutex_enter(&statep->state_mutex);
1478 	if (statep->state != IBCM_STATE_ESTABLISHED) {
1479 		ibcm_close_exit();
1480 		goto lost_race;
1481 	}
1482 
1483 	statep->state = IBCM_STATE_TRANSIENT_DREQ_SENT;
1484 	statep->timerid = 0;
1485 	statep->close_done = B_FALSE;
1486 	statep->close_flow = 1;
1487 	mutex_exit(&statep->state_mutex);
1488 
1489 	if (statep->dreq_msg == NULL) {
1490 		if ((status = ibcm_alloc_out_msg(
1491 		    statep->stored_reply_addr.ibmf_hdl, &statep->dreq_msg,
1492 		    MAD_METHOD_SEND)) != IBT_SUCCESS) {
1493 
1494 			IBTF_DPRINTF_L2(cmlog, "ibt_close_rc_channel: "
1495 			    "chan 0x%p ibcm_alloc_out_msg failed ", channel);
1496 			mutex_enter(&statep->state_mutex);
1497 			ibcm_close_exit();
1498 			statep->state = IBCM_STATE_ESTABLISHED;
1499 			IBCM_REF_CNT_DECR(statep);
1500 			cv_broadcast(&statep->block_mad_cv);
1501 			statep->close_flow = 0;
1502 			mutex_exit(&statep->state_mutex);
1503 			return (status);
1504 		}
1505 	} else
1506 		IBTF_DPRINTF_L3(cmlog, "ibt_close_rc_channel: "
1507 		    "DREQ MAD already allocated in statep %p", statep);
1508 
1509 	if ((ret_priv_data == NULL) || (ret_priv_data_len_p == NULL)) {
1510 		statep->close_priv_data = NULL;
1511 		statep->close_priv_data_len = NULL;
1512 	} else {
1513 		statep->close_priv_data = ret_priv_data;
1514 		statep->close_priv_data_len = ret_priv_data_len_p;
1515 	}
1516 
1517 	priv_data_len = min(priv_data_len, IBT_DREQ_PRIV_DATA_SZ);
1518 	if ((priv_data != NULL) && (priv_data_len > 0))
1519 		bcopy(priv_data, ((ibcm_dreq_msg_t *)
1520 		    IBCM_OUT_MSGP(statep->dreq_msg))->dreq_private_data,
1521 		    priv_data_len);
1522 
1523 	ibcm_post_dreq_mad(statep);
1524 
1525 	mutex_enter(&statep->state_mutex);
1526 
1527 lost_race:
1528 	if (mode == IBT_BLOCKING) {
1529 
1530 		/* wait for DREP */
1531 		while (statep->close_done != B_TRUE)
1532 			cv_wait(&statep->block_client_cv,
1533 			    &statep->state_mutex);
1534 
1535 		IBTF_DPRINTF_L4(cmlog, "ibt_close_rc_channel: chan 0x%p "
1536 		    "done blocking", channel);
1537 	}
1538 
1539 	IBCM_REF_CNT_DECR(statep);
1540 	mutex_exit(&statep->state_mutex);
1541 
1542 	/* If this message isn't seen then ibt_close_rc_channel failed */
1543 	IBTF_DPRINTF_L5(cmlog, "ibt_close_rc_channel: chan 0x%p done",
1544 	    channel);
1545 
1546 	return (IBT_SUCCESS);
1547 }
1548 
1549 ibt_status_t
1550 ibt_recycle_rc(ibt_channel_hdl_t rc_chan, ibt_cep_flags_t control,
1551     uint8_t hca_port_num, ibt_recycle_handler_t func, void *arg)
1552 {
1553 	ibcm_state_data_t		*statep;
1554 	ibcm_taskq_recycle_arg_t	*ibcm_tq_recycle_arg;
1555 	ibt_qp_query_attr_t		qp_attr;
1556 	ibt_status_t			retval;
1557 
1558 	IBTF_DPRINTF_L3(cmlog, "ibt_recycle_rc (%p, 0x%X, %d, %p, %p)", rc_chan,
1559 	    control, hca_port_num, func, arg);
1560 
1561 	if (IBCM_INVALID_CHANNEL(rc_chan)) {
1562 		IBTF_DPRINTF_L2(cmlog, "ibt_recycle_rc: invalid channel");
1563 		return (IBT_CHAN_HDL_INVALID);
1564 	}
1565 
1566 	/* check qp state */
1567 	retval = ibt_query_qp(rc_chan, &qp_attr);
1568 
1569 	if (retval != IBT_SUCCESS)
1570 		return (retval);
1571 
1572 	if (qp_attr.qp_info.qp_trans != IBT_RC_SRV)
1573 		return (IBT_CHAN_SRV_TYPE_INVALID);
1574 
1575 	if (qp_attr.qp_info.qp_state != IBT_STATE_ERROR)
1576 		return (IBT_CHAN_STATE_INVALID);
1577 
1578 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
1579 
1580 	ibcm_tq_recycle_arg = kmem_alloc(sizeof (ibcm_taskq_recycle_arg_t),
1581 	    KM_SLEEP);
1582 
1583 	ibcm_tq_recycle_arg->rc_chan		= rc_chan;
1584 	ibcm_tq_recycle_arg->control		= control;
1585 	ibcm_tq_recycle_arg->hca_port_num	= hca_port_num;
1586 	ibcm_tq_recycle_arg->func		= func;
1587 	ibcm_tq_recycle_arg->arg		= arg;
1588 
1589 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibcm_tq_recycle_arg))
1590 
1591 	IBCM_GET_CHAN_PRIVATE(rc_chan, statep);
1592 
1593 	/*
1594 	 * If non-blocking ie., func specified and channel has not yet completed
1595 	 * the timewait, then schedule the work for later
1596 	 */
1597 	if ((func != NULL) && (statep != NULL)) {
1598 		IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
1599 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
1600 		statep->recycle_arg = ibcm_tq_recycle_arg;
1601 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
1602 		return (IBT_SUCCESS);
1603 	}
1604 
1605 	/*
1606 	 * if blocking ie., func specified, and channel has not yet completed
1607 	 * the timewait, then block until the channel completes the timewait
1608 	 */
1609 	if (statep != NULL)
1610 		IBCM_RELEASE_CHAN_PRIVATE(rc_chan);
1611 	IBCM_WAIT_CHAN_PRIVATE(rc_chan);
1612 
1613 	if (func) {	/* NON BLOCKING case. Taskq for QP state change */
1614 		(void) taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
1615 		    ibcm_tq_recycle_arg, TQ_SLEEP);
1616 		return (IBT_SUCCESS);
1617 	} else	/* BLOCKING case */
1618 		return (ibcm_process_rc_recycle_ret(ibcm_tq_recycle_arg));
1619 }
1620 
1621 void
1622 ibcm_process_rc_recycle(void *recycle_arg)
1623 {
1624 	(void) ibcm_process_rc_recycle_ret(recycle_arg);
1625 }
1626 
1627 static ibt_status_t
1628 ibcm_process_rc_recycle_ret(void *recycle_arg)
1629 {
1630 	ibt_qp_info_t			qp_info;
1631 	ibt_status_t			ibt_status = IBT_SUCCESS;
1632 	ibt_cep_modify_flags_t		cep_flags;
1633 	ibt_qp_query_attr_t		qp_attr;
1634 	ibcm_taskq_recycle_arg_t	*ibcm_tq_recycle_arg =
1635 	    (ibcm_taskq_recycle_arg_t *)recycle_arg;
1636 
1637 	/* QP must have been in error state */
1638 	ibt_status = ibt_query_qp(ibcm_tq_recycle_arg->rc_chan, &qp_attr);
1639 	if (ibt_status != IBT_SUCCESS)
1640 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
1641 		    "chanp %p ibt_query_qp() = %d",
1642 		    ibcm_tq_recycle_arg->rc_chan, ibt_status);
1643 	else {
1644 		/* perform the QP state change from ERROR to RESET */
1645 		bzero(&qp_info, sizeof (qp_info));
1646 
1647 		qp_info.qp_trans = IBT_RC_SRV;
1648 		qp_info.qp_state = IBT_STATE_RESET;
1649 
1650 		/* Call modify_qp to move to RESET state */
1651 		ibt_status = ibt_modify_qp(ibcm_tq_recycle_arg->rc_chan,
1652 		    IBT_CEP_SET_STATE, &qp_info, NULL);
1653 
1654 		if (ibt_status != IBT_SUCCESS)
1655 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
1656 			    "chanp %p ibt_modify_qp() = %d for ERROR to RESET",
1657 			    ibcm_tq_recycle_arg->rc_chan, ibt_status);
1658 	}
1659 
1660 	if (ibt_status == IBT_SUCCESS) {
1661 
1662 		qp_info.qp_state = IBT_STATE_INIT;
1663 
1664 		/* set flags for all mandatory args from RESET to INIT */
1665 		cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
1666 		cep_flags |= IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W;
1667 		cep_flags |= IBT_CEP_SET_ATOMIC;
1668 
1669 		qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
1670 		    ibcm_tq_recycle_arg->hca_port_num;
1671 		qp_info.qp_flags |=
1672 		    ibcm_tq_recycle_arg->control & IBT_CEP_RDMA_RD;
1673 		qp_info.qp_flags |=
1674 		    ibcm_tq_recycle_arg->control & IBT_CEP_RDMA_WR;
1675 		qp_info.qp_flags |=
1676 		    ibcm_tq_recycle_arg->control & IBT_CEP_ATOMIC;
1677 
1678 		/* Always use the existing pkey */
1679 		qp_info.qp_transport.rc.rc_path.cep_pkey_ix =
1680 		    qp_attr. qp_info.qp_transport.rc.rc_path.cep_pkey_ix;
1681 
1682 		/* Call modify_qp to move to INIT state */
1683 		ibt_status = ibt_modify_qp(ibcm_tq_recycle_arg->rc_chan,
1684 		    cep_flags, &qp_info, NULL);
1685 
1686 		if (ibt_status != IBT_SUCCESS)
1687 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rc_recycle_ret: "
1688 			    "chanp %p ibt_modify_qp() = %d for RESET to INIT",
1689 			    ibcm_tq_recycle_arg->rc_chan, ibt_status);
1690 	}
1691 
1692 	/* Change the QP CM state to indicate QP being re-used */
1693 	if (ibt_status == IBT_SUCCESS)
1694 		ibtl_cm_chan_is_reused(ibcm_tq_recycle_arg->rc_chan);
1695 
1696 	/* Call func, if defined */
1697 	if (ibcm_tq_recycle_arg->func)
1698 		(*(ibcm_tq_recycle_arg->func))(ibt_status,
1699 		    ibcm_tq_recycle_arg->arg);
1700 
1701 	kmem_free(ibcm_tq_recycle_arg, sizeof (ibcm_taskq_recycle_arg_t));
1702 
1703 	return (ibt_status);
1704 }
1705 
1706 static void
1707 ibcm_process_abort_via_taskq(void *args)
1708 {
1709 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
1710 
1711 	ibcm_process_abort(statep);
1712 	mutex_enter(&statep->state_mutex);
1713 	IBCM_REF_CNT_DECR(statep);
1714 	mutex_exit(&statep->state_mutex);
1715 }
1716 
1717 /*
1718  * Local UD CM Handler's private data, used during ibt_request_ud_dest() in
1719  * Non-Blocking mode operations.
1720  */
1721 typedef struct ibcm_local_handler_s {
1722 	ibt_cm_ud_handler_t	actual_cm_handler;
1723 	void			*actual_cm_private;
1724 	ibt_ud_dest_t		*dest_hdl;
1725 } ibcm_local_handler_t;
1726 
1727 _NOTE(READ_ONLY_DATA(ibcm_local_handler_s))
1728 
1729 /*
1730  * Local UD CM Handler, used when ibt_alloc_ud_dest() is issued in
1731  * NON-Blocking mode.
1732  *
1733  * Out here, we update the UD Destination handle with
1734  * the obtained DQPN and QKey (from SIDR REP) and invokes actual client
1735  * handler that was specified by the client.
1736  */
1737 static ibt_cm_status_t
1738 ibcm_local_cm_handler(void *priv, ibt_cm_ud_event_t *event,
1739     ibt_cm_ud_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
1740 {
1741 	ibcm_local_handler_t	*handler_priv = (ibcm_local_handler_t *)priv;
1742 
1743 	IBTF_DPRINTF_L4(cmlog, "ibcm_local_cm_handler: event %d",
1744 	    event->cm_type);
1745 
1746 	ASSERT(handler_priv != NULL);
1747 
1748 	switch (event->cm_type) {
1749 	case IBT_CM_UD_EVENT_SIDR_REP:
1750 		/* Update QPN & QKey from event into destination handle. */
1751 		if (handler_priv->dest_hdl != NULL) {
1752 			handler_priv->dest_hdl->ud_dst_qpn =
1753 			    event->cm_event.sidr_rep.srep_remote_qpn;
1754 			handler_priv->dest_hdl->ud_qkey =
1755 			    event->cm_event.sidr_rep.srep_remote_qkey;
1756 		}
1757 
1758 		/* Invoke the client handler - inform only, so ignore retval */
1759 		(void) handler_priv->actual_cm_handler(
1760 		    handler_priv->actual_cm_private, event, ret_args, priv_data,
1761 		    len);
1762 
1763 		/* Free memory allocated for local handler's private data. */
1764 		if (handler_priv != NULL)
1765 			kmem_free(handler_priv, sizeof (*handler_priv));
1766 
1767 		break;
1768 	default:
1769 		IBTF_DPRINTF_L2(cmlog, "ibcm_local_cm_handler: ERROR");
1770 		break;
1771 	}
1772 
1773 	return (IBT_CM_ACCEPT);
1774 }
1775 
1776 
1777 /* Validate the input UD destination attributes.  */
1778 static ibt_status_t
1779 ibcm_validate_dqpn_data(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
1780     ibt_ud_returns_t *ret_args)
1781 {
1782 	/* cm handler must always be specified */
1783 	if (mode == IBT_NONBLOCKING && attr->ud_cm_handler == NULL) {
1784 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
1785 		    "CM handler is not specified ");
1786 		return (IBT_INVALID_PARAM);
1787 	}
1788 
1789 	if (mode == IBT_NONBLOCKING) {
1790 		if (ret_args != NULL) {
1791 			IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
1792 			    "ret_args should be NULL when called in "
1793 			    "non-blocking mode");
1794 			return (IBT_INVALID_PARAM);
1795 		}
1796 	} else if (mode == IBT_BLOCKING) {
1797 		if (ret_args == NULL) {
1798 			IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
1799 			    "ret_args should be Non-NULL when called in "
1800 			    "blocking mode");
1801 			return (IBT_INVALID_PARAM);
1802 		}
1803 	} else {
1804 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
1805 		    "invalid mode %x specified ", mode);
1806 		return (IBT_INVALID_PARAM);
1807 	}
1808 
1809 	if (attr->ud_sid == 0) {
1810 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
1811 		    "ServiceID must be specified. ");
1812 		return (IBT_INVALID_PARAM);
1813 	}
1814 
1815 	if (attr->ud_addr == NULL) {
1816 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: "
1817 		    "Address Info NULL");
1818 		return (IBT_INVALID_PARAM);
1819 	}
1820 
1821 	/* Validate SGID */
1822 	if ((attr->ud_addr->av_sgid.gid_prefix == 0) ||
1823 	    (attr->ud_addr->av_sgid.gid_guid == 0)) {
1824 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: Invalid SGID");
1825 		return (IBT_INVALID_PARAM);
1826 	}
1827 	IBTF_DPRINTF_L3(cmlog, "ibcm_validate_dqpn_data: SGID<%llX:%llX>",
1828 	    attr->ud_addr->av_sgid.gid_prefix,
1829 	    attr->ud_addr->av_sgid.gid_guid);
1830 
1831 	/* Validate DGID */
1832 	if ((attr->ud_addr->av_dgid.gid_prefix == 0) ||
1833 	    (attr->ud_addr->av_dgid.gid_guid == 0)) {
1834 		IBTF_DPRINTF_L2(cmlog, "ibcm_validate_dqpn_data: Invalid DGID");
1835 		return (IBT_INVALID_PARAM);
1836 	}
1837 	IBTF_DPRINTF_L3(cmlog, "ibcm_validate_dqpn_data: DGID<%llX:%llX>",
1838 	    attr->ud_addr->av_dgid.gid_prefix,
1839 	    attr->ud_addr->av_dgid.gid_guid);
1840 
1841 	return (IBT_SUCCESS);
1842 }
1843 
1844 
1845 /* Perform SIDR to retrieve DQPN and QKey.  */
1846 static ibt_status_t
1847 ibcm_ud_get_dqpn(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
1848     ibt_ud_returns_t *ret_args)
1849 {
1850 	ibt_status_t		retval;
1851 	ib_pkey_t		ud_pkey;
1852 	ibmf_handle_t		ibmf_hdl;
1853 	ibmf_msg_t		*ibmf_msg;
1854 	ibcm_hca_info_t		*hcap;
1855 	ibcm_sidr_req_msg_t	*sidr_req_msgp;
1856 	ibcm_ud_state_data_t	*ud_statep;
1857 	ibtl_cm_hca_port_t	port;
1858 	ibcm_sidr_srch_t	sidr_entry;
1859 	ibcm_qp_list_t		*cm_qp_entry;
1860 
1861 	/* Retrieve HCA GUID value from the available SGID info. */
1862 	retval = ibtl_cm_get_hca_port(attr->ud_addr->av_sgid, 0, &port);
1863 	if ((retval != IBT_SUCCESS) || (port.hp_port == 0)) {
1864 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1865 		    "ibtl_cm_get_hca_port failed: %d", retval);
1866 		return (retval);
1867 	}
1868 
1869 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: "
1870 	    "HCA GUID:%llX, port_num:%d", port.hp_hca_guid, port.hp_port);
1871 
1872 	/* Lookup the HCA info for this GUID */
1873 	if ((hcap = ibcm_find_hca_entry(port.hp_hca_guid)) == NULL) {
1874 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: hcap is NULL");
1875 		return (IBT_HCA_INVALID);
1876 	}
1877 
1878 	/* Return failure if the HCA device or Port is not operational */
1879 
1880 	if ((retval = ibt_get_port_state_byguid(port.hp_hca_guid, port.hp_port,
1881 	    NULL, NULL)) != IBT_SUCCESS) {
1882 		/* Device Port is not in good state, don't use it. */
1883 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: Invalid "
1884 		    "port specified or port not active");
1885 		ibcm_dec_hca_acc_cnt(hcap);
1886 		return (retval);
1887 	}
1888 
1889 	retval = ibt_index2pkey_byguid(port.hp_hca_guid, port.hp_port,
1890 	    attr->ud_pkey_ix, &ud_pkey);
1891 	if (retval != IBT_SUCCESS) {
1892 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1893 		    "Failed to convert index2pkey: %d", retval);
1894 		ibcm_dec_hca_acc_cnt(hcap);
1895 		return (retval);
1896 	}
1897 
1898 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(sidr_entry))
1899 
1900 	/* Allocate a new request id */
1901 	if (ibcm_alloc_reqid(hcap, &sidr_entry.srch_req_id) == IBCM_FAILURE) {
1902 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1903 		    "no req id available");
1904 		ibcm_dec_hca_acc_cnt(hcap);
1905 		return (IBT_INSUFF_KERNEL_RESOURCE);
1906 	}
1907 
1908 	if ((hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl == NULL) &&
1909 	    ((retval = ibcm_hca_reinit_port(hcap, port.hp_port - 1))
1910 	    != IBT_SUCCESS)) {
1911 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: "
1912 		    "ibmf reg or callback setup failed during re-initialize");
1913 		return (retval);
1914 	}
1915 
1916 	ibmf_hdl = hcap->hca_port_info[port.hp_port - 1].port_ibmf_hdl;
1917 
1918 	/* find the ibmf QP to post the SIDR REQ */
1919 	if ((cm_qp_entry = ibcm_find_qp(hcap, port.hp_port, ud_pkey)) ==
1920 	    NULL) {
1921 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF QP allocation"
1922 		    " failed");
1923 		ibcm_dec_hca_acc_cnt(hcap);
1924 		return (IBT_INSUFF_RESOURCE);
1925 	}
1926 
1927 	if ((retval = ibcm_alloc_out_msg(ibmf_hdl, &ibmf_msg, MAD_METHOD_SEND))
1928 	    != IBT_SUCCESS) {
1929 		IBTF_DPRINTF_L2(cmlog, "ibcm_ud_get_dqpn: IBMF MSG allocation"
1930 		    " failed");
1931 		ibcm_release_qp(cm_qp_entry);
1932 		ibcm_dec_hca_acc_cnt(hcap);
1933 		return (retval);
1934 	}
1935 
1936 	sidr_entry.srch_lid = port.hp_base_lid;
1937 	sidr_entry.srch_gid = attr->ud_addr->av_sgid;
1938 	sidr_entry.srch_grh_exists = attr->ud_addr->av_send_grh;
1939 	sidr_entry.srch_mode = IBCM_ACTIVE_MODE;
1940 
1941 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(sidr_entry))
1942 
1943 	/* do various allocations needed here */
1944 	rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
1945 
1946 	(void) ibcm_find_sidr_entry(&sidr_entry, hcap, &ud_statep,
1947 	    IBCM_FLAG_ADD);
1948 	rw_exit(&hcap->hca_sidr_list_lock);
1949 
1950 	/* Increment hca's resource count */
1951 	ibcm_inc_hca_res_cnt(hcap);
1952 
1953 	/* After a resource created on hca, no need to hold the acc cnt */
1954 	ibcm_dec_hca_acc_cnt(hcap);
1955 
1956 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
1957 
1958 	/* Initialize some ud_statep fields */
1959 	ud_statep->ud_stored_msg = ibmf_msg;
1960 	ud_statep->ud_svc_id = attr->ud_sid;
1961 	ud_statep->ud_pkt_life_time =
1962 	    ibt_ib2usec(attr->ud_pkt_lt);
1963 	ud_statep->ud_stored_reply_addr.cm_qp_entry = cm_qp_entry;
1964 
1965 	/* set remaining retry cnt */
1966 	ud_statep->ud_remaining_retry_cnt = ud_statep->ud_max_cm_retries;
1967 
1968 	/*
1969 	 * Get UD handler and corresponding args which is pass it back
1970 	 * as first argument for the handler.
1971 	 */
1972 	ud_statep->ud_state_cm_private = attr->ud_cm_private;
1973 
1974 	if (mode == IBT_BLOCKING)
1975 		ud_statep->ud_return_data = ret_args;
1976 	else
1977 		ud_statep->ud_cm_handler = attr->ud_cm_handler;
1978 
1979 	/* Initialize the fields of ud_statep->ud_stored_reply_addr */
1980 	ud_statep->ud_stored_reply_addr.grh_exists = attr->ud_addr->av_send_grh;
1981 	ud_statep->ud_stored_reply_addr.ibmf_hdl = ibmf_hdl;
1982 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_hop_limit =
1983 	    attr->ud_addr->av_hop;
1984 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_sender_gid =
1985 	    attr->ud_addr->av_sgid;
1986 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_recver_gid =
1987 	    attr->ud_addr->av_dgid;
1988 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_tclass =
1989 	    attr->ud_addr->av_tclass;
1990 	ud_statep->ud_stored_reply_addr.grh_hdr.ig_flow_label =
1991 	    attr->ud_addr->av_flow & IB_GRH_FLOW_LABEL_MASK;
1992 
1993 	/* needs to be derived based on the base LID and path bits */
1994 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_local_lid =
1995 	    port.hp_base_lid;
1996 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_lid =
1997 	    attr->ud_addr->av_dlid;
1998 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_p_key = ud_pkey;
1999 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_q_key = IB_GSI_QKEY;
2000 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_service_level =
2001 	    attr->ud_addr->av_srvl;
2002 
2003 	/*
2004 	 * This may be enchanced later, to use a remote qno based on past
2005 	 * redirect rej mad responses. This would be the place to specify
2006 	 * appropriate remote qno
2007 	 */
2008 	ud_statep->ud_stored_reply_addr.rcvd_addr.ia_remote_qno = 1;
2009 
2010 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
2011 
2012 	/* Initialize the SIDR REQ message fields */
2013 	sidr_req_msgp =
2014 	    (ibcm_sidr_req_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
2015 
2016 	sidr_req_msgp->sidr_req_request_id = h2b32(ud_statep->ud_req_id);
2017 	sidr_req_msgp->sidr_req_service_id = h2b64(attr->ud_sid);
2018 	sidr_req_msgp->sidr_req_pkey = h2b16(ud_pkey);
2019 	IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
2020 	    h2b16(IBCM_INCOMING_SIDR_REQ + IBCM_ATTR_BASE_ID);
2021 
2022 	if ((attr->ud_priv_data != NULL) && (attr->ud_priv_data_len > 0)) {
2023 		bcopy(attr->ud_priv_data, sidr_req_msgp->sidr_req_private_data,
2024 		    min(attr->ud_priv_data_len, IBT_SIDR_REQ_PRIV_DATA_SZ));
2025 	}
2026 
2027 	/* Send out the SIDR REQ message */
2028 	ud_statep->ud_state = IBCM_STATE_SIDR_REQ_SENT;
2029 	ud_statep->ud_timer_stored_state = IBCM_STATE_SIDR_REQ_SENT;
2030 	IBCM_UD_REF_CNT_INCR(ud_statep); /* for non-blocking SIDR REQ post */
2031 	ud_statep->ud_timer_value = ibt_ib2usec(ibcm_max_sidr_rep_proctime) +
2032 	    (ud_statep->ud_pkt_life_time * 2);
2033 
2034 	IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID =
2035 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_SIDR_REQ,
2036 	    ud_statep->ud_req_id, 0));
2037 
2038 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: timer_value in HZ = %x",
2039 	    ud_statep->ud_timer_value);
2040 
2041 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
2042 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_req_msgp))
2043 
2044 	ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
2045 	    ibcm_post_sidr_req_complete, ud_statep);
2046 
2047 	mutex_enter(&ud_statep->ud_state_mutex);
2048 
2049 	/* Wait for SIDR_REP */
2050 	if (mode == IBT_BLOCKING) {
2051 		IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: blocking");
2052 
2053 		while (ud_statep->ud_blocking_done != B_TRUE) {
2054 			cv_wait(&ud_statep->ud_block_client_cv,
2055 			    &ud_statep->ud_state_mutex);
2056 		}
2057 
2058 		IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: finished blocking");
2059 
2060 		if (ret_args->ud_status == IBT_CM_SREP_QPN_VALID) {
2061 			IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: DQPN = %x, "
2062 			    "status = %x, QKey = %x", ret_args->ud_dqpn,
2063 			    ret_args->ud_status, ret_args->ud_qkey);
2064 
2065 		} else {
2066 			IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: Status<%x>",
2067 			    ret_args->ud_status);
2068 			retval = IBT_CM_FAILURE;
2069 		}
2070 	}
2071 
2072 	IBCM_UD_REF_CNT_DECR(ud_statep);
2073 	mutex_exit(&ud_statep->ud_state_mutex);
2074 
2075 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_get_dqpn: done");
2076 
2077 	return (retval);
2078 }
2079 
2080 
2081 /*
2082  * Function:
2083  *	ibt_request_ud_dest
2084  * Input:
2085  *	ud_dest		A previously allocated UD destination handle.
2086  *	mode		This function can execute in blocking or non blocking
2087  *			modes.
2088  *	attr		UD destination attributes to be modified.
2089  * Output:
2090  *	ud_ret_args	If the function is called in blocking mode, ud_ret_args
2091  *			should be a pointer to an ibt_ud_returns_t struct.
2092  * Returns:
2093  *	IBT_SUCCESS
2094  * Description:
2095  *	Modify a previously allocated UD destination handle based on the
2096  *	results of doing the SIDR protocol.
2097  */
2098 ibt_status_t
2099 ibt_request_ud_dest(ibt_ud_dest_hdl_t ud_dest, ibt_execution_mode_t mode,
2100     ibt_ud_dest_attr_t *attr, ibt_ud_returns_t *ud_ret_args)
2101 {
2102 	ibt_status_t		retval;
2103 	ibt_ud_dest_t		*ud_destp;
2104 	ibcm_local_handler_t	*local_handler_priv = NULL;
2105 
2106 	IBTF_DPRINTF_L3(cmlog, "ibt_request_ud_dest(%p, %x, %p, %p)",
2107 	    ud_dest, mode, attr, ud_ret_args);
2108 
2109 	retval = ibcm_validate_dqpn_data(attr, mode, ud_ret_args);
2110 	if (retval != IBT_SUCCESS) {
2111 		return (retval);
2112 	}
2113 
2114 	ud_destp = ud_dest;
2115 
2116 	/* Allocate an Address handle. */
2117 	retval = ibt_modify_ah(ud_destp->ud_dest_hca, ud_destp->ud_ah,
2118 	    attr->ud_addr);
2119 	if (retval != IBT_SUCCESS) {
2120 		IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
2121 		    "Address Handle Modification failed: %d", retval);
2122 		return (retval);
2123 	}
2124 
2125 	if (mode == IBT_NONBLOCKING) {
2126 		/*
2127 		 * In NON-BLOCKING mode, and we need to update the destination
2128 		 * handle with the DQPN and QKey that are obtained from
2129 		 * SIDR REP, hook-up our own handler, so that we can catch
2130 		 * the event, and we ourselves call the actual client's
2131 		 * ud_cm_handler, in our handler.
2132 		 */
2133 
2134 		/* Allocate memory for local handler's private data. */
2135 		local_handler_priv =
2136 		    kmem_alloc(sizeof (*local_handler_priv), KM_SLEEP);
2137 
2138 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*local_handler_priv))
2139 
2140 		local_handler_priv->actual_cm_handler = attr->ud_cm_handler;
2141 		local_handler_priv->actual_cm_private = attr->ud_cm_private;
2142 		local_handler_priv->dest_hdl = ud_destp;
2143 
2144 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*local_handler_priv))
2145 
2146 		attr->ud_cm_handler = ibcm_local_cm_handler;
2147 		attr->ud_cm_private = local_handler_priv;
2148 	}
2149 
2150 	/* In order to get DQPN and Destination QKey, perform SIDR */
2151 	retval = ibcm_ud_get_dqpn(attr, mode, ud_ret_args);
2152 	if (retval != IBT_SUCCESS) {
2153 		IBTF_DPRINTF_L2(cmlog, "ibt_request_ud_dest: "
2154 		    "Failed to get DQPN: %d", retval);
2155 
2156 		/* Free memory allocated for local handler's private data. */
2157 		if (local_handler_priv != NULL)
2158 			kmem_free(local_handler_priv,
2159 			    sizeof (*local_handler_priv));
2160 		return (retval);
2161 	}
2162 
2163 	/*
2164 	 * Fill in the dqpn and dqkey as obtained from ud_ret_args,
2165 	 * values will be valid only on BLOCKING mode.
2166 	 */
2167 	if (mode == IBT_BLOCKING) {
2168 		ud_destp->ud_dst_qpn = ud_ret_args->ud_dqpn;
2169 		ud_destp->ud_qkey = ud_ret_args->ud_qkey;
2170 	}
2171 
2172 	return (retval);
2173 }
2174 
2175 /*
2176  * Function:
2177  *	ibt_ud_get_dqpn
2178  * Input:
2179  *	attr		A pointer to an ibt_ud_dest_attr_t struct that are
2180  *			required for SIDR REQ message. Not specified attributes
2181  *			should be set to "NULL" or "0".
2182  *			ud_sid, ud_addr and ud_pkt_lt must be specified.
2183  *	mode		This function can execute in blocking or non blocking
2184  *			modes.
2185  * Output:
2186  *	returns		If the function is called in blocking mode, returns
2187  *			should be a pointer to an ibt_ud_returns_t struct.
2188  * Return:
2189  *	IBT_SUCCESS	on success or respective failure on error.
2190  * Description:
2191  *	Finds the destination QPN at the specified destination that the
2192  *	specified service can be reached on. The IBTF CM initiates the
2193  *	service ID resolution protocol (SIDR) to determine a destination QPN.
2194  *
2195  * NOTE: SIDR_REQ is initiated from active side.
2196  */
2197 ibt_status_t
2198 ibt_ud_get_dqpn(ibt_ud_dest_attr_t *attr, ibt_execution_mode_t mode,
2199     ibt_ud_returns_t *returns)
2200 {
2201 	ibt_status_t		retval;
2202 
2203 	IBTF_DPRINTF_L3(cmlog, "ibt_ud_get_dqpn(%p, %x, %p)",
2204 	    attr, mode, returns);
2205 
2206 	retval = ibcm_validate_dqpn_data(attr, mode, returns);
2207 	if (retval != IBT_SUCCESS) {
2208 		return (retval);
2209 	}
2210 
2211 	return (ibcm_ud_get_dqpn(attr, mode, returns));
2212 }
2213 
2214 
2215 /*
2216  * ibt_cm_delay:
2217  *	A client CM handler function can call this function
2218  *	to extend its response time to a CM event.
2219  * INPUTS:
2220  *	flags		Indicates what CM message processing is being delayed
2221  *			by the CM handler, valid values are:
2222  *				IBT_CM_DELAY_REQ
2223  *				IBT_CM_DELAY_REP
2224  *				IBT_CM_DELAY_LAP
2225  *	cm_session_id	The session ID that was passed to client srv_handler
2226  *			by the CM
2227  *	service_time	The extended service time
2228  *	priv_data	Vendor specific data to be sent in the CM generated
2229  *			MRA message. Should be NULL if not specified.
2230  *	len		The number of bytes of data specified by priv_data.
2231  *
2232  * RETURN VALUES:
2233  *	IBT_SUCCESS	on success (or respective failure on error)
2234  */
2235 ibt_status_t
2236 ibt_cm_delay(ibt_cmdelay_flags_t flags, void *cm_session_id,
2237     clock_t service_time, void *priv_data, ibt_priv_data_len_t len)
2238 {
2239 	uint8_t			msg_typ = 0;
2240 	ibcm_mra_msg_t		*mra_msgp;
2241 	ibcm_state_data_t	*statep;
2242 	ibt_status_t		status;
2243 
2244 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_delay(0x%x, %p, 0x%x)",
2245 	    flags, cm_session_id, service_time);
2246 
2247 	/*
2248 	 * Make sure channel is associated with a statep
2249 	 */
2250 	statep = (ibcm_state_data_t *)cm_session_id;
2251 
2252 	if (statep == NULL) {
2253 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: statep NULL");
2254 		return (IBT_INVALID_PARAM);
2255 	}
2256 
2257 	IBTF_DPRINTF_L4(cmlog, "ibt_cm_delay: statep %p", statep);
2258 
2259 	/* Allocate an ibmf msg for mra, if not allocated yet */
2260 	if (statep->mra_msg == NULL) {
2261 		if ((status = ibcm_alloc_out_msg(
2262 		    statep->stored_reply_addr.ibmf_hdl, &statep->mra_msg,
2263 		    MAD_METHOD_SEND)) != IBT_SUCCESS) {
2264 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: chan 0x%p"
2265 			    "IBMF MSG allocation failed", statep->channel);
2266 			return (status);
2267 		}
2268 	}
2269 
2270 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mra_msgp))
2271 
2272 	mra_msgp = (ibcm_mra_msg_t *)IBCM_OUT_MSGP(statep->mra_msg);
2273 	mra_msgp->mra_local_comm_id = h2b32(statep->local_comid);
2274 	mra_msgp->mra_remote_comm_id = h2b32(statep->remote_comid);
2275 
2276 	/* fill in rest of MRA's fields - Message MRAed and Service Timeout */
2277 	if (flags == IBT_CM_DELAY_REQ) {
2278 		msg_typ = IBT_CM_MRA_TYPE_REQ;
2279 	} else if (flags == IBT_CM_DELAY_REP) {
2280 		msg_typ = IBT_CM_MRA_TYPE_REP;
2281 	} else if (flags == IBT_CM_DELAY_LAP) {
2282 		msg_typ = IBT_CM_MRA_TYPE_LAP;
2283 	}
2284 
2285 	mra_msgp->mra_message_type_plus = msg_typ << 6;
2286 	mra_msgp->mra_service_timeout_plus = ibt_usec2ib(service_time) << 3;
2287 
2288 	len = min(len, IBT_MRA_PRIV_DATA_SZ);
2289 	if (priv_data && (len > 0))
2290 		bcopy(priv_data, mra_msgp->mra_private_data, len);
2291 
2292 	IBCM_OUT_HDRP(statep->mra_msg)->AttributeID =
2293 	    h2b16(IBCM_INCOMING_MRA + IBCM_ATTR_BASE_ID);
2294 
2295 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mra_msgp))
2296 
2297 	mutex_enter(&statep->state_mutex);
2298 
2299 	if ((statep->mode == IBCM_ACTIVE_MODE) &&
2300 	    (statep->state == IBCM_STATE_REP_RCVD)) {
2301 		statep->state = IBCM_STATE_MRA_REP_SENT;
2302 	} else if (statep->mode == IBCM_PASSIVE_MODE) {
2303 		if (statep->state == IBCM_STATE_REQ_RCVD) {
2304 			statep->state = IBCM_STATE_MRA_SENT;
2305 		} else if (statep->ap_state == IBCM_AP_STATE_LAP_RCVD) {
2306 			statep->ap_state = IBCM_AP_STATE_MRA_LAP_RCVD;
2307 		} else {
2308 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
2309 			    "/ap_state/mode %x, %x, %x", statep->state,
2310 			    statep->ap_state, statep->mode);
2311 			mutex_exit(&statep->state_mutex);
2312 			return (IBT_CHAN_STATE_INVALID);
2313 		}
2314 	} else {
2315 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_delay: invalid state "
2316 		    "/ap_state/mode %x, %x, %x", statep->state,
2317 		    statep->ap_state, statep->mode);
2318 		mutex_exit(&statep->state_mutex);
2319 
2320 		return (IBT_CHAN_STATE_INVALID);
2321 	}
2322 	/* service time is usecs, stale_clock is nsecs */
2323 	statep->stale_clock = gethrtime() +
2324 	    (hrtime_t)ibt_ib2usec(ibt_usec2ib(service_time)) * (1000 *
2325 	    statep->max_cm_retries);
2326 
2327 	statep->send_mad_flags |= IBCM_MRA_POST_BUSY;
2328 	IBCM_REF_CNT_INCR(statep);	/* for ibcm_post_mra_complete */
2329 	mutex_exit(&statep->state_mutex);
2330 
2331 	IBCM_OUT_HDRP(statep->mra_msg)->TransactionID =
2332 		IBCM_OUT_HDRP(statep->stored_msg)->TransactionID;
2333 
2334 	/* post the MRA mad in blocking mode, as no timers involved */
2335 	ibcm_post_rc_mad(statep, statep->mra_msg, ibcm_post_mra_complete,
2336 	    statep);
2337 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_MRA);
2338 	/* If this message isn't seen then ibt_cm_delay failed */
2339 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_delay: done !!");
2340 
2341 	return (IBT_SUCCESS);
2342 }
2343 
2344 
2345 /*
2346  * ibt_register_service()
2347  *	Register a service with the IBCM
2348  *
2349  * INPUTS:
2350  *	ibt_hdl		The IBT client handle returned to the client
2351  *			on an ibt_attach() call.
2352  *
2353  *	srv		The address of a ibt_srv_desc_t that describes
2354  *			the service, containing the following:
2355  *
2356  *		sd_ud_handler	The Service CM UD event Handler.
2357  *		sd_handler	The Service CM RC/UC/RD event Handler.
2358  *		sd_flags	Service flags (peer-to-peer, or not).
2359  *
2360  *	sid		This tells CM if the service is local (sid is 0) or
2361  *			wellknown (sid is the starting service id of the range).
2362  *
2363  *	num_sids	The number of contiguous service-ids to reserve.
2364  *
2365  *	srv_hdl		The address of a service identification handle, used
2366  *			to deregister a service, and to bind GIDs to.
2367  *
2368  *	ret_sid		The address to store the Service ID return value.
2369  *			If num_sids > 1, ret_sid is the first Service ID
2370  *			in the range.
2371  *
2372  * ibt_register_service() returns:
2373  *	IBT_SUCCESS		- added a service successfully.
2374  *	IBT_INVALID_PARAM	- invalid input parameter.
2375  *	IBT_CM_FAILURE		- failed to add the service.
2376  *	IBT_CM_SERVICE_EXISTS	- service already exists.
2377  *	IBT_INSUFF_KERNEL_RESOURCE - ran out of local service ids (should
2378  *				     never happen).
2379  */
2380 ibt_status_t
2381 ibt_register_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_desc_t *srv,
2382     ib_svc_id_t sid, int num_sids, ibt_srv_hdl_t *srv_hdl, ib_svc_id_t *ret_sid)
2383 {
2384 	ibcm_svc_info_t		*svcinfop;
2385 
2386 	IBTF_DPRINTF_L2(cmlog, "ibt_register_service(%p, %p, %llx, %d)",
2387 	    ibt_hdl, srv, (longlong_t)sid, num_sids);
2388 
2389 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*svcinfop))
2390 
2391 	*srv_hdl = NULL;
2392 
2393 	if (num_sids <= 0) {
2394 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
2395 		    "Invalid number of service-ids specified (%d)", num_sids);
2396 		return (IBT_INVALID_PARAM);
2397 	}
2398 
2399 	if (sid == 0) {
2400 		if (ret_sid == NULL)
2401 			return (IBT_INVALID_PARAM);
2402 		sid = ibcm_alloc_local_sids(num_sids);
2403 		if (sid == 0)
2404 			return (IBT_INSUFF_KERNEL_RESOURCE);
2405 
2406 	/* Make sure that the ServiceId specified is not of LOCAL AGN type. */
2407 	} else if ((sid & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL) {
2408 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
2409 		    "Invalid non-LOCAL SID specified: 0x%llX",
2410 		    (longlong_t)sid);
2411 		return (IBT_INVALID_PARAM);
2412 	}
2413 
2414 	svcinfop = ibcm_create_svc_entry(sid, num_sids);
2415 
2416 	if (svcinfop == NULL) {
2417 		IBTF_DPRINTF_L2(cmlog, "ibt_register_service: "
2418 		    "Service-ID 0x%llx already registered", (longlong_t)sid);
2419 		return (IBT_CM_SERVICE_EXISTS);
2420 	}
2421 
2422 	/*
2423 	 * 'sid' and 'num_sids' are filled in ibcm_create_svc_entry()
2424 	 */
2425 	svcinfop->svc_flags = srv->sd_flags;
2426 	svcinfop->svc_rc_handler = srv->sd_handler;
2427 	svcinfop->svc_ud_handler = srv->sd_ud_handler;
2428 
2429 	if (ret_sid != NULL)
2430 		*ret_sid = sid;
2431 
2432 	*srv_hdl = svcinfop;
2433 
2434 	ibtl_cm_change_service_cnt(ibt_hdl, num_sids);
2435 
2436 	/* If this message isn't seen, then ibt_register_service failed. */
2437 	IBTF_DPRINTF_L2(cmlog, "ibt_register_service: done (%p, %llX)",
2438 	    svcinfop, sid);
2439 
2440 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*svcinfop))
2441 
2442 	return (IBT_SUCCESS);
2443 }
2444 
2445 
2446 static ibt_status_t
2447 ibcm_write_service_record(ibmf_saa_handle_t saa_handle,
2448     sa_service_record_t *srv_recp, ibmf_saa_access_type_t saa_type)
2449 {
2450 	int	rval;
2451 	int	retry;
2452 
2453 	ibcm_sa_access_enter();
2454 	for (retry = 0; retry < ibcm_max_sa_retries; retry++) {
2455 		rval = ibmf_saa_update_service_record(
2456 		    saa_handle, srv_recp, saa_type, 0);
2457 		if (rval != IBMF_TRANS_TIMEOUT) {
2458 			break;
2459 		}
2460 		IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
2461 		    "ibmf_saa_update_service_record timed out"
2462 		    " SID = %llX, rval = %d, saa_type = %d",
2463 		    (longlong_t)srv_recp->ServiceID, rval, saa_type);
2464 		delay(ibcm_sa_timeout_delay);
2465 	}
2466 	ibcm_sa_access_exit();
2467 
2468 	if (rval != IBMF_SUCCESS) {
2469 		IBTF_DPRINTF_L2(cmlog, "ibcm_write_service_record: "
2470 		    "ibmf_saa_update_service_record() : Failed - %d", rval);
2471 		return (ibcm_ibmf_analyze_error(rval));
2472 	} else
2473 		return (IBT_SUCCESS);
2474 }
2475 
2476 
2477 static void
2478 ibcm_rem_stale_srec(ibmf_saa_handle_t saa_handle, sa_service_record_t *srec)
2479 {
2480 	ibt_status_t		retval;
2481 	uint_t			num_found;
2482 	size_t			length;
2483 	sa_service_record_t	*srv_resp;
2484 	void			*results_p;
2485 	uint_t			i;
2486 	uint64_t		component_mask;
2487 	ibmf_saa_access_args_t	access_args;
2488 
2489 	component_mask =
2490 	    SA_SR_COMPMASK_PKEY | SA_SR_COMPMASK_NAME | SA_SR_COMPMASK_GID;
2491 
2492 	/* Call in SA Access retrieve routine to get Service Records. */
2493 	access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
2494 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
2495 	access_args.sq_component_mask = component_mask;
2496 	access_args.sq_template = srec;
2497 	access_args.sq_template_length = sizeof (sa_service_record_t);
2498 	access_args.sq_callback = NULL;
2499 	access_args.sq_callback_arg = NULL;
2500 
2501 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
2502 	    &results_p);
2503 	if (retval != IBT_SUCCESS) {
2504 		IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
2505 		    "SA Access Failure");
2506 		return;
2507 	}
2508 
2509 	num_found = length / sizeof (sa_service_record_t);
2510 
2511 	if (num_found)
2512 		IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
2513 		    "Found %d matching Service Records.", num_found);
2514 
2515 	/* Validate the returned number of records. */
2516 	if ((results_p != NULL) && (num_found > 0)) {
2517 
2518 		/* Remove all the records. */
2519 		for (i = 0; i < num_found; i++) {
2520 
2521 			srv_resp = (sa_service_record_t *)
2522 			    ((uchar_t *)results_p +
2523 			    i * sizeof (sa_service_record_t));
2524 
2525 			/*
2526 			 * Found some matching records, but check out whether
2527 			 * this Record is really stale or just happens to match
2528 			 * the current session records. If yes, don't remove it.
2529 			 */
2530 			mutex_enter(&ibcm_svc_info_lock);
2531 			if (ibcm_find_svc_entry(srv_resp->ServiceID) != NULL) {
2532 				/* This record is NOT STALE. */
2533 				mutex_exit(&ibcm_svc_info_lock);
2534 				IBTF_DPRINTF_L3(cmlog, "ibcm_rem_stale_srec: "
2535 				    "This is not Stale, it's an active record");
2536 				continue;
2537 			}
2538 			mutex_exit(&ibcm_svc_info_lock);
2539 
2540 			IBTF_DPRINTF_L2(cmlog, "ibcm_rem_stale_srec: "
2541 			    "Removing Stale Rec: %s, %llX",
2542 			    srv_resp->ServiceName, srv_resp->ServiceID);
2543 
2544 			IBCM_DUMP_SERVICE_REC(srv_resp);
2545 
2546 			/*
2547 			 * Remove the Service Record Entry from SA.
2548 			 *
2549 			 * Get ServiceID info from Response Buf, other
2550 			 * attributes are already filled-in.
2551 			 */
2552 
2553 			 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srec->ServiceID))
2554 
2555 			srec->ServiceID = srv_resp->ServiceID;
2556 
2557 			 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srec->ServiceID))
2558 
2559 			(void) ibcm_write_service_record(saa_handle, srec,
2560 			    IBMF_SAA_DELETE);
2561 		}
2562 
2563 		/* Deallocate the memory for results_p. */
2564 		kmem_free(results_p, length);
2565 	}
2566 }
2567 
2568 
2569 
2570 /*
2571  * ibt_bind_service()
2572  *	Register a service with the IBCM
2573  *
2574  * INPUTS:
2575  *	srv_hdl		The service id handle returned to the client
2576  *			on an ibt_service_register() call.
2577  *
2578  *	gid		The GID to which to bind the service.
2579  *
2580  *	srv_bind	The address of a ibt_srv_bind_t that describes
2581  *			the service record.  This should be NULL if there
2582  *			is to be no service record.  This contains:
2583  *
2584  *		sb_lease	Lease period
2585  *		sb_pkey		Partition
2586  *		sb_name		pointer to ASCII string Service Name,
2587  *				NULL terminated.
2588  *		sb_key[]	Key to secure the service record.
2589  *		sb_data		Service Data structure (64-byte)
2590  *
2591  *	cm_private	First argument of Service handler.
2592  *
2593  *	sb_hdl_p	The address of a service bind handle, used
2594  *			to undo the service binding.
2595  *
2596  * ibt_bind_service() returns:
2597  *	IBT_SUCCESS		- added a service successfully.
2598  *	IBT_INVALID_PARAM	- invalid input parameter.
2599  *	IBT_CM_FAILURE		- failed to add the service.
2600  *	IBT_CM_SERVICE_EXISTS	- service already exists.
2601  */
2602 ibt_status_t
2603 ibt_bind_service(ibt_srv_hdl_t srv_hdl, ib_gid_t gid, ibt_srv_bind_t *srv_bind,
2604     void *cm_private, ibt_sbind_hdl_t *sb_hdl_p)
2605 {
2606 	ibt_status_t		status;
2607 	ibtl_cm_hca_port_t	port;
2608 	ibcm_svc_bind_t		*sbindp, *sbp;
2609 	ibcm_hca_info_t		*hcap;
2610 	ib_svc_id_t		sid, start_sid, end_sid;
2611 	ibmf_saa_handle_t	saa_handle;
2612 	sa_service_record_t	srv_rec;
2613 	uint16_t		pkey_ix;
2614 
2615 	if (sb_hdl_p != NULL)
2616 		*sb_hdl_p = NULL;	/* return value for error cases */
2617 
2618 	IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: srv_hdl %p, gid (%llX:%llX)",
2619 	    srv_hdl, (longlong_t)gid.gid_prefix, (longlong_t)gid.gid_guid);
2620 
2621 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sbindp))
2622 
2623 	/* Call ibtl_cm_get_hca_port to get the port number and the HCA GUID. */
2624 	if ((status = ibtl_cm_get_hca_port(gid, 0, &port)) != IBT_SUCCESS) {
2625 		IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2626 		    "ibtl_cm_get_hca_port failed: %d", status);
2627 		return (status);
2628 	}
2629 	IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: Port:%d HCA GUID:%llX",
2630 	    port.hp_port, port.hp_hca_guid);
2631 
2632 	hcap = ibcm_find_hca_entry(port.hp_hca_guid);
2633 	if (hcap == NULL) {
2634 		IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: NO HCA found");
2635 		return (IBT_HCA_BUSY_DETACHING);
2636 	}
2637 	IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: hcap = %p", hcap);
2638 
2639 	if (srv_bind != NULL) {
2640 		saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
2641 		if (saa_handle == NULL) {
2642 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2643 			    "saa_handle is NULL");
2644 			ibcm_dec_hca_acc_cnt(hcap);
2645 			return (IBT_HCA_PORT_NOT_ACTIVE);
2646 		}
2647 		if (srv_bind->sb_pkey == 0) {
2648 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2649 			    "P_Key must not be 0");
2650 			ibcm_dec_hca_acc_cnt(hcap);
2651 			return (IBT_INVALID_PARAM);
2652 		}
2653 		if (strlen(srv_bind->sb_name) >= IB_SVC_NAME_LEN) {
2654 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2655 			    "Service Name is too long");
2656 			ibcm_dec_hca_acc_cnt(hcap);
2657 			return (IBT_INVALID_PARAM);
2658 		} else
2659 			IBTF_DPRINTF_L3(cmlog, "ibt_bind_service: "
2660 			    "Service Name='%s'", srv_bind->sb_name);
2661 		status = ibt_pkey2index_byguid(port.hp_hca_guid,
2662 		    port.hp_port, srv_bind->sb_pkey, &pkey_ix);
2663 		if (status != IBT_SUCCESS) {
2664 			IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2665 			    "P_Key 0x%x not found in P_Key_Table",
2666 			    srv_bind->sb_pkey);
2667 			ibcm_dec_hca_acc_cnt(hcap);
2668 			return (status);
2669 		}
2670 	}
2671 
2672 	/* assume success - allocate before locking */
2673 	sbindp = kmem_zalloc(sizeof (*sbindp), KM_SLEEP);
2674 	sbindp->sbind_cm_private = cm_private;
2675 	sbindp->sbind_gid = gid;
2676 	sbindp->sbind_hcaguid = port.hp_hca_guid;
2677 	sbindp->sbind_port = port.hp_port;
2678 
2679 	mutex_enter(&ibcm_svc_info_lock);
2680 
2681 	sbp = srv_hdl->svc_bind_list;
2682 	while (sbp != NULL) {
2683 		if (sbp->sbind_gid.gid_guid == gid.gid_guid &&
2684 		    sbp->sbind_gid.gid_prefix == gid.gid_prefix) {
2685 			if (srv_bind == NULL ||
2686 			    srv_bind->sb_pkey == sbp->sbind_pkey) {
2687 				IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: "
2688 				    "failed: GID %llX:%llX and PKEY %x is "
2689 				    "already bound", gid.gid_guid,
2690 				    gid.gid_prefix, sbp->sbind_pkey);
2691 				mutex_exit(&ibcm_svc_info_lock);
2692 				ibcm_dec_hca_acc_cnt(hcap);
2693 				kmem_free(sbindp, sizeof (*sbindp));
2694 				return (IBT_CM_SERVICE_EXISTS);
2695 			}
2696 		}
2697 		sbp = sbp->sbind_link;
2698 	}
2699 	/* no entry found */
2700 
2701 	sbindp->sbind_link = srv_hdl->svc_bind_list;
2702 	srv_hdl->svc_bind_list = sbindp;
2703 
2704 	mutex_exit(&ibcm_svc_info_lock);
2705 
2706 	if (srv_bind != NULL) {
2707 		bzero(&srv_rec, sizeof (srv_rec));
2708 
2709 		srv_rec.ServiceLease =
2710 		    sbindp->sbind_lease = srv_bind->sb_lease;
2711 		srv_rec.ServiceP_Key =
2712 		    sbindp->sbind_pkey = srv_bind->sb_pkey;
2713 		srv_rec.ServiceKey_hi =
2714 		    sbindp->sbind_key[0] = srv_bind->sb_key[0];
2715 		srv_rec.ServiceKey_lo =
2716 		    sbindp->sbind_key[1] = srv_bind->sb_key[1];
2717 		(void) strcpy(sbindp->sbind_name, srv_bind->sb_name);
2718 		(void) strcpy((char *)srv_rec.ServiceName, srv_bind->sb_name);
2719 		srv_rec.ServiceGID = gid;
2720 
2721 		/*
2722 		 * Find out whether we have any stale Local Service records
2723 		 * matching the current attributes.  If yes, we shall try to
2724 		 * remove them from SA using the current request's ServiceKey.
2725 		 *
2726 		 * We will perform this operation only for Local Services, as
2727 		 * it is handled by SA automatically for WellKnown Services.
2728 		 *
2729 		 * Ofcourse, clients can specify NOT to do this clean-up by
2730 		 * setting IBT_SBIND_NO_CLEANUP flag (srv_bind->sb_flag).
2731 		 */
2732 		if ((srv_hdl->svc_id & IB_SID_AGN_LOCAL) &&
2733 		    (!(srv_bind->sb_flag & IBT_SBIND_NO_CLEANUP))) {
2734 			ibcm_rem_stale_srec(saa_handle, &srv_rec);
2735 		}
2736 
2737 		/* Handle endianess for service data. */
2738 		ibcm_swizzle_from_srv(&srv_bind->sb_data, sbindp->sbind_data);
2739 
2740 		bcopy(sbindp->sbind_data, srv_rec.ServiceData, IB_SVC_DATA_LEN);
2741 
2742 		/* insert srv record into the SA */
2743 		start_sid = srv_hdl->svc_id;
2744 		end_sid = start_sid + srv_hdl->svc_num_sids - 1;
2745 		for (sid = start_sid; sid <= end_sid; sid++) {
2746 
2747 			srv_rec.ServiceID = sid;
2748 
2749 			IBCM_DUMP_SERVICE_REC(&srv_rec);
2750 
2751 			IBTF_DPRINTF_L4(cmlog, "ibt_bind_service: "
2752 			    "ibmf_saa_write_service_record, SvcId = %llX",
2753 			    (longlong_t)sid);
2754 
2755 			status = ibcm_write_service_record(saa_handle, &srv_rec,
2756 			    IBMF_SAA_UPDATE);
2757 			if (status != IBT_SUCCESS) {
2758 				IBTF_DPRINTF_L2(cmlog, "ibt_bind_service:"
2759 				    " ibcm_write_service_record fails %d, "
2760 				    "sid %llX", status, (longlong_t)sid);
2761 
2762 				if (sid != start_sid) {
2763 					/*
2764 					 * Bind failed while bind SID other than
2765 					 * first in the sid_range.  So we need
2766 					 * to unbind those, which are passed.
2767 					 *
2768 					 * Need to increment svc count to
2769 					 * compensate for ibt_unbind_service().
2770 					 */
2771 					ibcm_inc_hca_svc_cnt(hcap);
2772 					ibcm_dec_hca_acc_cnt(hcap);
2773 
2774 					(void) ibt_unbind_service(srv_hdl,
2775 					    sbindp);
2776 				} else {
2777 					ibcm_svc_bind_t		**sbpp;
2778 
2779 					/*
2780 					 * Bind failed for the first SID or the
2781 					 * only SID in question, then no need
2782 					 * to unbind, just free memory and
2783 					 * return error.
2784 					 */
2785 					mutex_enter(&ibcm_svc_info_lock);
2786 
2787 					sbpp = &srv_hdl->svc_bind_list;
2788 					sbp = *sbpp;
2789 					while (sbp != NULL) {
2790 						if (sbp == sbindp) {
2791 							*sbpp = sbp->sbind_link;
2792 							break;
2793 						}
2794 						sbpp = &sbp->sbind_link;
2795 						sbp = *sbpp;
2796 					}
2797 					mutex_exit(&ibcm_svc_info_lock);
2798 					ibcm_dec_hca_acc_cnt(hcap);
2799 
2800 					kmem_free(sbindp, sizeof (*sbindp));
2801 				}
2802 				return (status);
2803 			}
2804 		}
2805 	}
2806 	ibcm_inc_hca_svc_cnt(hcap);
2807 	ibcm_dec_hca_acc_cnt(hcap);
2808 
2809 	/* If this message isn't seen then ibt_bind_service failed */
2810 	IBTF_DPRINTF_L2(cmlog, "ibt_bind_service: DONE (%p, %llX:%llX)",
2811 	    srv_hdl, gid.gid_prefix, gid.gid_guid);
2812 
2813 	if (sb_hdl_p != NULL)
2814 		*sb_hdl_p = sbindp;
2815 
2816 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sbindp))
2817 
2818 	return (IBT_SUCCESS);
2819 }
2820 
2821 ibt_status_t
2822 ibt_unbind_service(ibt_srv_hdl_t srv_hdl, ibt_sbind_hdl_t sbindp)
2823 {
2824 	ib_svc_id_t	sid, end_sid;
2825 	ibt_status_t	rval;
2826 	ibcm_hca_info_t	*hcap;
2827 	ibcm_svc_bind_t	*sbp, **sbpp;
2828 
2829 	IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service(%p, %p)",
2830 	    srv_hdl, sbindp);
2831 
2832 	hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
2833 
2834 	/* If there is a service on hca, respective hcap cannot go away */
2835 	ASSERT(hcap != NULL);
2836 
2837 	mutex_enter(&ibcm_svc_info_lock);
2838 
2839 	sbpp = &srv_hdl->svc_bind_list;
2840 	sbp = *sbpp;
2841 	while (sbp != NULL) {
2842 		if (sbp == sbindp) {
2843 			*sbpp = sbp->sbind_link;
2844 			break;
2845 		}
2846 		sbpp = &sbp->sbind_link;
2847 		sbp = *sbpp;
2848 	}
2849 	sid = srv_hdl->svc_id;
2850 	end_sid = srv_hdl->svc_id + srv_hdl->svc_num_sids - 1;
2851 	if (sbp != NULL)
2852 		while (sbp->sbind_rewrite_state == IBCM_REWRITE_BUSY)
2853 			cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
2854 	mutex_exit(&ibcm_svc_info_lock);
2855 
2856 	if (sbp == NULL) {
2857 		IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
2858 		    "service binding not found: srv_hdl %p, srv_bind %p",
2859 		    srv_hdl, sbindp);
2860 		ibcm_dec_hca_acc_cnt(hcap);
2861 		return (IBT_INVALID_PARAM);
2862 	}
2863 
2864 	if (sbindp->sbind_pkey != 0) {	/* Are there service records? */
2865 		ibtl_cm_hca_port_t	port;
2866 		sa_service_record_t	srv_rec;
2867 		ibmf_saa_handle_t	saa_handle;
2868 		ibt_status_t		status;
2869 
2870 		/* get the default SGID of the port */
2871 		if ((status = ibtl_cm_get_hca_port(sbindp->sbind_gid, 0, &port))
2872 		    != IBT_SUCCESS) {
2873 			IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
2874 			    "ibtl_cm_get_hca_port failed: %d", status);
2875 			/* we're done, but there may be stale service records */
2876 			goto done;
2877 		}
2878 
2879 		saa_handle = ibcm_get_saa_handle(hcap, port.hp_port);
2880 		if (saa_handle == NULL) {
2881 			IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
2882 			    "saa_handle is NULL");
2883 			/* we're done, but there may be stale service records */
2884 			goto done;
2885 		}
2886 
2887 		/* Fill in fields of srv_rec */
2888 		bzero(&srv_rec, sizeof (srv_rec));
2889 
2890 		srv_rec.ServiceP_Key = sbindp->sbind_pkey;
2891 		srv_rec.ServiceKey_hi = sbindp->sbind_key[0];
2892 		srv_rec.ServiceKey_lo = sbindp->sbind_key[1];
2893 		srv_rec.ServiceGID = sbindp->sbind_gid;
2894 		(void) strcpy((char *)srv_rec.ServiceName, sbindp->sbind_name);
2895 
2896 		while (sid <= end_sid) {
2897 
2898 			srv_rec.ServiceID = sid;
2899 			IBCM_DUMP_SERVICE_REC(&srv_rec);
2900 
2901 			rval = ibcm_write_service_record(saa_handle, &srv_rec,
2902 			    IBMF_SAA_DELETE);
2903 
2904 			IBTF_DPRINTF_L4(cmlog, "ibt_unbind_service: "
2905 			    "ibcm_write_service_record rval = %d, SID %llx",
2906 			    rval, sid);
2907 			if (rval != IBT_SUCCESS) {
2908 				/* this is not considered a reason to fail */
2909 				IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: "
2910 				    "ibcm_write_service_record fails %d, "
2911 				    "sid %llx", rval, sid);
2912 			}
2913 			sid++;
2914 		}
2915 	}
2916 done:
2917 	ibcm_dec_hca_svc_cnt(hcap);
2918 	ibcm_dec_hca_acc_cnt(hcap);
2919 	kmem_free(sbindp, sizeof (*sbindp));
2920 
2921 	/* If this message isn't seen then ibt_unbind_service failed */
2922 	IBTF_DPRINTF_L2(cmlog, "ibt_unbind_service: done !!");
2923 
2924 	return (IBT_SUCCESS);
2925 }
2926 
2927 /*
2928  * Simply pull off each binding from the list and unbind it.
2929  * If any of the unbind calls fail, we fail.
2930  */
2931 ibt_status_t
2932 ibt_unbind_all_services(ibt_srv_hdl_t srv_hdl)
2933 {
2934 	ibt_status_t	status;
2935 	ibcm_svc_bind_t	*sbp;
2936 
2937 	mutex_enter(&ibcm_svc_info_lock);
2938 	sbp = NULL;
2939 
2940 	/* this compare keeps the loop from being infinite */
2941 	while (sbp != srv_hdl->svc_bind_list) {
2942 		sbp = srv_hdl->svc_bind_list;
2943 		mutex_exit(&ibcm_svc_info_lock);
2944 		status = ibt_unbind_service(srv_hdl, sbp);
2945 		if (status != IBT_SUCCESS)
2946 			return (status);
2947 		mutex_enter(&ibcm_svc_info_lock);
2948 		if (srv_hdl->svc_bind_list == NULL)
2949 			break;
2950 	}
2951 	mutex_exit(&ibcm_svc_info_lock);
2952 	return (IBT_SUCCESS);
2953 }
2954 
2955 /*
2956  * ibt_deregister_service()
2957  *	Deregister a service with the IBCM
2958  *
2959  * INPUTS:
2960  *	ibt_hdl		The IBT client handle returned to the client
2961  *			on an ibt_attach() call.
2962  *
2963  *	srv_hdl		The address of a service identification handle, used
2964  *			to de-register a service.
2965  * RETURN VALUES:
2966  *	IBT_SUCCESS	on success (or respective failure on error)
2967  */
2968 ibt_status_t
2969 ibt_deregister_service(ibt_clnt_hdl_t ibt_hdl, ibt_srv_hdl_t srv_hdl)
2970 {
2971 	ibcm_svc_info_t		*svcp;
2972 	ibcm_svc_lookup_t	svc;
2973 
2974 	IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(%p, %p)",
2975 	    ibt_hdl, srv_hdl);
2976 
2977 	mutex_enter(&ibcm_svc_info_lock);
2978 
2979 	if (srv_hdl->svc_bind_list != NULL) {
2980 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service:"
2981 		    " srv_hdl %p still has bindings", srv_hdl);
2982 		mutex_exit(&ibcm_svc_info_lock);
2983 		return (IBT_CM_SERVICE_BUSY);
2984 	}
2985 	svc.sid = srv_hdl->svc_id;
2986 	svc.num_sids = 1;
2987 	IBTF_DPRINTF_L3(cmlog, "ibt_deregister_service: SID 0x%llX, numsids %d",
2988 	    srv_hdl->svc_id, srv_hdl->svc_num_sids);
2989 
2990 #ifdef __lock_lint
2991 	ibcm_svc_compare(NULL, NULL);
2992 #endif
2993 	svcp = avl_find(&ibcm_svc_avl_tree, &svc, NULL);
2994 	if (svcp != srv_hdl) {
2995 		mutex_exit(&ibcm_svc_info_lock);
2996 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service(): "
2997 		    "srv_hdl %p not found", srv_hdl);
2998 		return (IBT_INVALID_PARAM);
2999 	}
3000 	avl_remove(&ibcm_svc_avl_tree, svcp);
3001 
3002 	/* wait for active REQ/SREQ handling to be done */
3003 	svcp->svc_to_delete = 1;
3004 	while (svcp->svc_ref_cnt != 0)
3005 		cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
3006 
3007 	mutex_exit(&ibcm_svc_info_lock);
3008 
3009 	if ((srv_hdl->svc_id & IB_SID_AGN_MASK) == IB_SID_AGN_LOCAL)
3010 		ibcm_free_local_sids(srv_hdl->svc_id, srv_hdl->svc_num_sids);
3011 
3012 	ibtl_cm_change_service_cnt(ibt_hdl, -srv_hdl->svc_num_sids);
3013 	kmem_free(srv_hdl, sizeof (*srv_hdl));
3014 
3015 	/* If this message isn't seen then ibt_deregister_service failed */
3016 	IBTF_DPRINTF_L2(cmlog, "ibt_deregister_service: done !!");
3017 
3018 	return (IBT_SUCCESS);
3019 }
3020 
3021 ibcm_status_t
3022 ibcm_ar_init(void)
3023 {
3024 	ib_svc_id_t	sid = IBCM_DAPL_ATS_SID;
3025 	ibcm_svc_info_t *tmp_svcp;
3026 
3027 	IBTF_DPRINTF_L3(cmlog, "ibcm_ar_init()");
3028 
3029 	/* remove this special SID from the pool of available SIDs */
3030 	if ((tmp_svcp = ibcm_create_svc_entry(sid, 1)) == NULL) {
3031 		IBTF_DPRINTF_L2(cmlog, "ibcm_ar_init: "
3032 		    "DAPL ATS SID 0x%llx already registered", (longlong_t)sid);
3033 		return (IBCM_FAILURE);
3034 	}
3035 	mutex_enter(&ibcm_svc_info_lock);
3036 	ibcm_ar_svcinfop = tmp_svcp;
3037 	ibcm_ar_list = NULL;	/* no address records registered yet */
3038 	mutex_exit(&ibcm_svc_info_lock);
3039 	return (IBCM_SUCCESS);
3040 }
3041 
3042 ibcm_status_t
3043 ibcm_ar_fini(void)
3044 {
3045 	ibcm_ar_t	*ar_list;
3046 	ibcm_svc_info_t	*tmp_svcp;
3047 
3048 	mutex_enter(&ibcm_svc_info_lock);
3049 	ar_list = ibcm_ar_list;
3050 
3051 	if (ar_list == NULL &&
3052 	    avl_numnodes(&ibcm_svc_avl_tree) == 1 &&
3053 	    avl_first(&ibcm_svc_avl_tree) == ibcm_ar_svcinfop) {
3054 		avl_remove(&ibcm_svc_avl_tree, ibcm_ar_svcinfop);
3055 		tmp_svcp = ibcm_ar_svcinfop;
3056 		mutex_exit(&ibcm_svc_info_lock);
3057 		kmem_free(tmp_svcp, sizeof (*ibcm_ar_svcinfop));
3058 		return (IBCM_SUCCESS);
3059 	}
3060 	mutex_exit(&ibcm_svc_info_lock);
3061 	return (IBCM_FAILURE);
3062 }
3063 
3064 
3065 /*
3066  * Return to the caller:
3067  *	IBT_SUCCESS		Found a perfect match.
3068  *				*arpp is set to the record.
3069  *	IBT_INCONSISTENT_AR	Found a record that's inconsistent.
3070  *	IBT_AR_NOT_REGISTERED	Found no record with same GID/pkey and
3071  *				found no record with same data.
3072  */
3073 static ibt_status_t
3074 ibcm_search_ar(ibt_ar_t *arp, ibcm_ar_t **arpp)
3075 {
3076 	ibcm_ar_t	*tmp;
3077 	int		i;
3078 
3079 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
3080 	tmp = ibcm_ar_list;
3081 	while (tmp != NULL) {
3082 		if (tmp->ar.ar_gid.gid_prefix == arp->ar_gid.gid_prefix &&
3083 		    tmp->ar.ar_gid.gid_guid == arp->ar_gid.gid_guid &&
3084 		    tmp->ar.ar_pkey == arp->ar_pkey) {
3085 			for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++)
3086 				if (tmp->ar.ar_data[i] != arp->ar_data[i])
3087 					return (IBT_INCONSISTENT_AR);
3088 			*arpp = tmp;
3089 			return (IBT_SUCCESS);
3090 		} else {
3091 			/* if all the data bytes match, we have inconsistency */
3092 			for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++)
3093 				if (tmp->ar.ar_data[i] != arp->ar_data[i])
3094 					break;
3095 			if (i == IBCM_DAPL_ATS_NBYTES)
3096 				return (IBT_INCONSISTENT_AR);
3097 			/* try next address record */
3098 		}
3099 		tmp = tmp->ar_link;
3100 	}
3101 	return (IBT_AR_NOT_REGISTERED);
3102 }
3103 
3104 ibt_status_t
3105 ibt_register_ar(ibt_clnt_hdl_t ibt_hdl, ibt_ar_t *arp)
3106 {
3107 	ibcm_ar_t		*found;
3108 	ibcm_ar_t		*tmp;
3109 	ibt_status_t		status;
3110 	ibt_status_t		s1, s2;
3111 	char			*s;
3112 	ibcm_ar_ref_t		*hdlp;
3113 	ibcm_ar_t		*new;
3114 	ibcm_ar_t		**linkp;
3115 	ibtl_cm_hca_port_t	cm_port;
3116 	uint16_t		pkey_ix;
3117 	ibcm_hca_info_t		*hcap;
3118 	ibmf_saa_handle_t	saa_handle;
3119 	sa_service_record_t	*srv_recp;
3120 	uint64_t		gid_ored;
3121 
3122 	IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: PKey 0x%X GID %llX:%llX",
3123 	    arp->ar_pkey, (longlong_t)arp->ar_gid.gid_prefix,
3124 	    (longlong_t)arp->ar_gid.gid_guid);
3125 
3126 	/*
3127 	 * If P_Key is 0, but GID is not, this query is invalid.
3128 	 * If GID is 0, but P_Key is not, this query is invalid.
3129 	 */
3130 	gid_ored = arp->ar_gid.gid_guid | arp->ar_gid.gid_prefix;
3131 	if ((arp->ar_pkey == 0 && gid_ored != 0ULL) ||
3132 	    (arp->ar_pkey != 0 && gid_ored == 0ULL)) {
3133 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
3134 		    "GID/P_Key is not valid");
3135 		return (IBT_INVALID_PARAM);
3136 	}
3137 
3138 	/* assume success, so these might be needed */
3139 	hdlp = kmem_alloc(sizeof (*hdlp), KM_SLEEP);
3140 	new = kmem_zalloc(sizeof (*new), KM_SLEEP);
3141 
3142 	mutex_enter(&ibcm_svc_info_lock);
3143 	/* search for existing GID/pkey (there can be at most 1) */
3144 	status = ibcm_search_ar(arp, &found);
3145 	if (status == IBT_INCONSISTENT_AR) {
3146 		mutex_exit(&ibcm_svc_info_lock);
3147 		kmem_free(new, sizeof (*new));
3148 		kmem_free(hdlp, sizeof (*hdlp));
3149 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
3150 		    "address record is inconsistent with a known one");
3151 		return (IBT_INCONSISTENT_AR);
3152 	} else if (status == IBT_SUCCESS) {
3153 		if (found->ar_flags == IBCM_AR_INITING) {
3154 			found->ar_waiters++;
3155 			cv_wait(&found->ar_cv, &ibcm_svc_info_lock);
3156 			found->ar_waiters--;
3157 		}
3158 		if (found->ar_flags == IBCM_AR_FAILED) {
3159 			if (found->ar_waiters == 0) {
3160 				cv_destroy(&found->ar_cv);
3161 				kmem_free(found, sizeof (*found));
3162 			}
3163 			mutex_exit(&ibcm_svc_info_lock);
3164 			kmem_free(new, sizeof (*new));
3165 			kmem_free(hdlp, sizeof (*hdlp));
3166 			return (ibt_get_module_failure(IBT_FAILURE_IBCM, 0));
3167 		}
3168 		hdlp->ar_ibt_hdl = ibt_hdl;
3169 		hdlp->ar_ref_link = found->ar_ibt_hdl_list;
3170 		found->ar_ibt_hdl_list = hdlp;
3171 		mutex_exit(&ibcm_svc_info_lock);
3172 		kmem_free(new, sizeof (*new));
3173 		ibtl_cm_change_service_cnt(ibt_hdl, 1);
3174 		return (IBT_SUCCESS);
3175 	} else {
3176 		ASSERT(status == IBT_AR_NOT_REGISTERED);
3177 	}
3178 	hdlp->ar_ref_link = NULL;
3179 	hdlp->ar_ibt_hdl = ibt_hdl;
3180 	new->ar_ibt_hdl_list = hdlp;
3181 	new->ar = *arp;
3182 	new->ar_flags = IBCM_AR_INITING;
3183 	new->ar_waiters = 0;
3184 	cv_init(&new->ar_cv, NULL, CV_DEFAULT, NULL);
3185 	new->ar_link = ibcm_ar_list;
3186 	ibcm_ar_list = new;
3187 
3188 	/* verify GID/pkey is valid for a local port, etc. */
3189 	hcap = NULL;
3190 	if ((s1 = ibtl_cm_get_hca_port(arp->ar_gid, 0, &cm_port))
3191 		!= IBT_SUCCESS ||
3192 	    (s2 = ibt_pkey2index_byguid(cm_port.hp_hca_guid, cm_port.hp_port,
3193 		arp->ar_pkey, &pkey_ix)) != IBT_SUCCESS ||
3194 	    (hcap = ibcm_find_hca_entry(cm_port.hp_hca_guid)) == NULL) {
3195 		cv_destroy(&new->ar_cv);
3196 		ibcm_ar_list = new->ar_link;
3197 		mutex_exit(&ibcm_svc_info_lock);
3198 		kmem_free(new, sizeof (*new));
3199 		kmem_free(hdlp, sizeof (*hdlp));
3200 		status = IBT_INVALID_PARAM;
3201 		if (s1 == IBT_HCA_PORT_NOT_ACTIVE) {
3202 			s = "PORT DOWN";
3203 			status = IBT_HCA_PORT_NOT_ACTIVE;
3204 		} else if (s1 != IBT_SUCCESS)
3205 			s = "GID not found";
3206 		else if (s2 != IBT_SUCCESS)
3207 			s = "PKEY not found";
3208 		else
3209 			s = "CM could not find its HCA entry";
3210 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: %s, status = %d",
3211 		    s, status);
3212 		return (status);
3213 	}
3214 	mutex_exit(&ibcm_svc_info_lock);
3215 	saa_handle = ibcm_get_saa_handle(hcap, cm_port.hp_port);
3216 
3217 	/* create service record */
3218 	srv_recp = kmem_zalloc(sizeof (*srv_recp), KM_SLEEP);
3219 	srv_recp->ServiceLease = 0xFFFFFFFF;	/* infinite */
3220 	srv_recp->ServiceP_Key = arp->ar_pkey;
3221 	srv_recp->ServiceKey_hi = 0xDA410000ULL;	/* DAPL */
3222 	srv_recp->ServiceKey_lo = 0xA7500000ULL;	/* ATS */
3223 	(void) strcpy((char *)srv_recp->ServiceName, IBCM_DAPL_ATS_NAME);
3224 	srv_recp->ServiceGID = arp->ar_gid;
3225 	bcopy(arp->ar_data, srv_recp->ServiceData, IBCM_DAPL_ATS_NBYTES);
3226 	srv_recp->ServiceID = IBCM_DAPL_ATS_SID;
3227 
3228 	/* insert service record into the SA */
3229 
3230 	IBCM_DUMP_SERVICE_REC(srv_recp);
3231 
3232 	if (saa_handle != NULL)
3233 		status = ibcm_write_service_record(saa_handle, srv_recp,
3234 		    IBMF_SAA_UPDATE);
3235 	else
3236 		status = IBT_HCA_PORT_NOT_ACTIVE;
3237 
3238 	if (status != IBT_SUCCESS) {
3239 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: sa access fails %d, "
3240 		    "sid %llX", status, (longlong_t)srv_recp->ServiceID);
3241 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: FAILED for gid "
3242 		    "%llX:%llX pkey 0x%X", (longlong_t)arp->ar_gid.gid_prefix,
3243 		    (longlong_t)arp->ar_gid.gid_guid, arp->ar_pkey);
3244 
3245 		kmem_free(srv_recp, sizeof (*srv_recp));
3246 		kmem_free(hdlp, sizeof (*hdlp));
3247 
3248 		mutex_enter(&ibcm_svc_info_lock);
3249 		linkp = &ibcm_ar_list;
3250 		tmp = *linkp;
3251 		while (tmp != NULL) {
3252 			if (tmp == new) {
3253 				*linkp = new->ar_link;
3254 				break;
3255 			}
3256 			linkp = &tmp->ar_link;
3257 			tmp = *linkp;
3258 		}
3259 		if (new->ar_waiters > 0) {
3260 			new->ar_flags = IBCM_AR_FAILED;
3261 			cv_broadcast(&new->ar_cv);
3262 			mutex_exit(&ibcm_svc_info_lock);
3263 		} else {
3264 			cv_destroy(&new->ar_cv);
3265 			mutex_exit(&ibcm_svc_info_lock);
3266 			kmem_free(new, sizeof (*new));
3267 		}
3268 		ibcm_dec_hca_acc_cnt(hcap);
3269 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: "
3270 		    "IBMF_SAA failed to write address record");
3271 	} else {					/* SUCCESS */
3272 		uint8_t		*b;
3273 
3274 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar: SUCCESS for gid "
3275 		    "%llx:%llx pkey %x", (longlong_t)arp->ar_gid.gid_prefix,
3276 		    (longlong_t)arp->ar_gid.gid_guid, arp->ar_pkey);
3277 		b = arp->ar_data;
3278 
3279 		IBTF_DPRINTF_L2(cmlog, "ibt_register_ar:"
3280 		    " data %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
3281 		    b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9],
3282 		    b[10], b[11], b[12], b[13], b[14], b[15]);
3283 		mutex_enter(&ibcm_svc_info_lock);
3284 		new->ar_srv_recp = srv_recp;
3285 		new->ar_saa_handle = saa_handle;
3286 		new->ar_port = cm_port.hp_port;
3287 		new->ar_hcap = hcap;
3288 		new->ar_flags = IBCM_AR_SUCCESS;
3289 		if (new->ar_waiters > 0)
3290 			cv_broadcast(&new->ar_cv);
3291 		mutex_exit(&ibcm_svc_info_lock);
3292 		ibtl_cm_change_service_cnt(ibt_hdl, 1);
3293 		/* do not call ibcm_dec_hca_acc_cnt(hcap) until deregister */
3294 	}
3295 	return (status);
3296 }
3297 
3298 ibt_status_t
3299 ibt_deregister_ar(ibt_clnt_hdl_t ibt_hdl, ibt_ar_t *arp)
3300 {
3301 	ibcm_ar_t		*found;
3302 	ibcm_ar_t		*tmp;
3303 	ibcm_ar_t		**linkp;
3304 	ibcm_ar_ref_t		*hdlp;
3305 	ibcm_ar_ref_t		**hdlpp;
3306 	ibt_status_t		status;
3307 	ibmf_saa_handle_t	saa_handle;
3308 	sa_service_record_t	*srv_recp;
3309 	uint64_t		gid_ored;
3310 
3311 	IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: pkey %x", arp->ar_pkey);
3312 	IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: gid %llx:%llx",
3313 	    (longlong_t)arp->ar_gid.gid_prefix,
3314 	    (longlong_t)arp->ar_gid.gid_guid);
3315 
3316 	/*
3317 	 * If P_Key is 0, but GID is not, this query is invalid.
3318 	 * If GID is 0, but P_Key is not, this query is invalid.
3319 	 */
3320 	gid_ored = arp->ar_gid.gid_guid | arp->ar_gid.gid_prefix;
3321 	if ((arp->ar_pkey == 0 && gid_ored != 0ULL) ||
3322 	    (arp->ar_pkey != 0 && gid_ored == 0ULL)) {
3323 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
3324 		    "GID/P_Key is not valid");
3325 		return (IBT_INVALID_PARAM);
3326 	}
3327 
3328 	mutex_enter(&ibcm_svc_info_lock);
3329 	/* search for existing GID/pkey (there can be at most 1) */
3330 	status = ibcm_search_ar(arp, &found);
3331 	if (status == IBT_INCONSISTENT_AR || status == IBT_AR_NOT_REGISTERED) {
3332 		mutex_exit(&ibcm_svc_info_lock);
3333 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
3334 		    "address record not found");
3335 		return (IBT_AR_NOT_REGISTERED);
3336 	}
3337 	ASSERT(status == IBT_SUCCESS);
3338 
3339 	hdlpp = &found->ar_ibt_hdl_list;
3340 	hdlp = *hdlpp;
3341 	while (hdlp != NULL) {
3342 		if (hdlp->ar_ibt_hdl == ibt_hdl)
3343 			break;
3344 		hdlpp = &hdlp->ar_ref_link;
3345 		hdlp = *hdlpp;
3346 	}
3347 	if (hdlp == NULL) {	/* could not find ibt_hdl on list */
3348 		mutex_exit(&ibcm_svc_info_lock);
3349 		IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
3350 		    "address record found, but not for this client");
3351 		return (IBT_AR_NOT_REGISTERED);
3352 	}
3353 	*hdlpp = hdlp->ar_ref_link;	/* remove ref for this client */
3354 	if (found->ar_ibt_hdl_list == NULL && found->ar_waiters == 0) {
3355 		/* last entry was removed */
3356 		found->ar_flags = IBCM_AR_INITING; /* hold off register_ar */
3357 		saa_handle = found->ar_saa_handle;
3358 		srv_recp = found->ar_srv_recp;
3359 
3360 		/* wait if this service record is being rewritten */
3361 		while (found->ar_rewrite_state == IBCM_REWRITE_BUSY)
3362 			cv_wait(&ibcm_svc_info_cv, &ibcm_svc_info_lock);
3363 		mutex_exit(&ibcm_svc_info_lock);
3364 
3365 		/* remove service record */
3366 		status = ibcm_write_service_record(saa_handle, srv_recp,
3367 		    IBMF_SAA_DELETE);
3368 		if (status != IBT_SUCCESS)
3369 			IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
3370 			    "IBMF_SAA failed to delete address record");
3371 		mutex_enter(&ibcm_svc_info_lock);
3372 		if (found->ar_waiters == 0) {	/* still no waiters */
3373 			linkp = &ibcm_ar_list;
3374 			tmp = *linkp;
3375 			while (tmp != found) {
3376 				linkp = &tmp->ar_link;
3377 				tmp = *linkp;
3378 			}
3379 			*linkp = tmp->ar_link;
3380 			ibcm_dec_hca_acc_cnt(found->ar_hcap);
3381 			kmem_free(srv_recp, sizeof (*srv_recp));
3382 			cv_destroy(&found->ar_cv);
3383 			kmem_free(found, sizeof (*found));
3384 		} else {
3385 			/* add service record back in for the waiters */
3386 			mutex_exit(&ibcm_svc_info_lock);
3387 			status = ibcm_write_service_record(saa_handle, srv_recp,
3388 			    IBMF_SAA_UPDATE);
3389 			mutex_enter(&ibcm_svc_info_lock);
3390 			if (status == IBT_SUCCESS)
3391 				found->ar_flags = IBCM_AR_SUCCESS;
3392 			else {
3393 				found->ar_flags = IBCM_AR_FAILED;
3394 				IBTF_DPRINTF_L2(cmlog, "ibt_deregister_ar: "
3395 				    "IBMF_SAA failed to write address record");
3396 			}
3397 			cv_broadcast(&found->ar_cv);
3398 		}
3399 	}
3400 	mutex_exit(&ibcm_svc_info_lock);
3401 	kmem_free(hdlp, sizeof (*hdlp));
3402 	ibtl_cm_change_service_cnt(ibt_hdl, -1);
3403 	return (status);
3404 }
3405 
3406 ibt_status_t
3407 ibt_query_ar(ib_gid_t *sgid, ibt_ar_t *queryp, ibt_ar_t *resultp)
3408 {
3409 	sa_service_record_t	svcrec_req;
3410 	sa_service_record_t	*svcrec_resp;
3411 	void			*results_p;
3412 	uint64_t		component_mask = 0;
3413 	uint64_t		gid_ored;
3414 	size_t			length;
3415 	int			num_rec;
3416 	int			i;
3417 	ibmf_saa_access_args_t	access_args;
3418 	ibt_status_t		retval;
3419 	ibtl_cm_hca_port_t	cm_port;
3420 	ibcm_hca_info_t		*hcap;
3421 	ibmf_saa_handle_t	saa_handle;
3422 
3423 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar(%p, %p)", queryp, resultp);
3424 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: sgid %llx:%llx",
3425 	    (longlong_t)sgid->gid_prefix, (longlong_t)sgid->gid_guid);
3426 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: query_pkey %x", queryp->ar_pkey);
3427 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: query_gid %llx:%llx",
3428 	    (longlong_t)queryp->ar_gid.gid_prefix,
3429 	    (longlong_t)queryp->ar_gid.gid_guid);
3430 
3431 	/*
3432 	 * If P_Key is 0, but GID is not, this query is invalid.
3433 	 * If GID is 0, but P_Key is not, this query is invalid.
3434 	 */
3435 	gid_ored = queryp->ar_gid.gid_guid | queryp->ar_gid.gid_prefix;
3436 	if ((queryp->ar_pkey == 0 && gid_ored != 0ULL) ||
3437 	    (queryp->ar_pkey != 0 && gid_ored == 0ULL)) {
3438 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: GID/P_Key is not valid");
3439 		return (IBT_INVALID_PARAM);
3440 	}
3441 
3442 	hcap = NULL;
3443 	if (ibtl_cm_get_hca_port(*sgid, 0, &cm_port) != IBT_SUCCESS ||
3444 	    (hcap = ibcm_find_hca_entry(cm_port.hp_hca_guid)) == NULL ||
3445 	    (saa_handle = ibcm_get_saa_handle(hcap, cm_port.hp_port)) == NULL) {
3446 		if (hcap != NULL)
3447 			ibcm_dec_hca_acc_cnt(hcap);
3448 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: sgid is not valid");
3449 		return (IBT_INVALID_PARAM);
3450 	}
3451 
3452 	bzero(&svcrec_req, sizeof (svcrec_req));
3453 
3454 	/* Is GID/P_Key Specified. */
3455 	if (queryp->ar_pkey != 0) {	/* GID is non-zero from check above */
3456 		svcrec_req.ServiceP_Key = queryp->ar_pkey;
3457 		component_mask |= SA_SR_COMPMASK_PKEY;
3458 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: P_Key %X",
3459 		    queryp->ar_pkey);
3460 		svcrec_req.ServiceGID = queryp->ar_gid;
3461 		component_mask |= SA_SR_COMPMASK_GID;
3462 		IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: GID %llX:%llX",
3463 		    (longlong_t)queryp->ar_gid.gid_prefix,
3464 		    (longlong_t)queryp->ar_gid.gid_guid);
3465 	}
3466 
3467 	/* Is ServiceData Specified. */
3468 	for (i = 0; i < IBCM_DAPL_ATS_NBYTES; i++) {
3469 		if (queryp->ar_data[i] != 0) {
3470 			bcopy(queryp->ar_data, svcrec_req.ServiceData,
3471 			    IBCM_DAPL_ATS_NBYTES);
3472 			component_mask |= 0xFFFF << 7;	/* all 16 Data8 */
3473 							/* components */
3474 			break;
3475 		}
3476 	}
3477 
3478 	/* Service Name */
3479 	(void) strcpy((char *)svcrec_req.ServiceName, IBCM_DAPL_ATS_NAME);
3480 	component_mask |= SA_SR_COMPMASK_NAME;
3481 
3482 	svcrec_req.ServiceID = IBCM_DAPL_ATS_SID;
3483 	component_mask |= SA_SR_COMPMASK_ID;
3484 
3485 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
3486 	    "Perform SA Access: Mask: 0x%X", component_mask);
3487 
3488 	/*
3489 	 * Call in SA Access retrieve routine to get Service Records.
3490 	 *
3491 	 * SA Access framework allocated memory for the "results_p".
3492 	 * Make sure to deallocate once we are done with the results_p.
3493 	 * The size of the buffer allocated will be as returned in
3494 	 * "length" field.
3495 	 */
3496 	access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
3497 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
3498 	access_args.sq_component_mask = component_mask;
3499 	access_args.sq_template = &svcrec_req;
3500 	access_args.sq_template_length = sizeof (sa_service_record_t);
3501 	access_args.sq_callback = NULL;
3502 	access_args.sq_callback_arg = NULL;
3503 
3504 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
3505 	    &results_p);
3506 
3507 	ibcm_dec_hca_acc_cnt(hcap);
3508 	if (retval != IBT_SUCCESS) {
3509 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: SA Access Failed");
3510 		return (retval);
3511 	}
3512 
3513 	num_rec = length / sizeof (sa_service_record_t);
3514 
3515 	IBTF_DPRINTF_L3(cmlog, "ibt_query_ar: "
3516 	    "Found %d Service Records.", num_rec);
3517 
3518 	/* Validate the returned number of records. */
3519 	if ((results_p != NULL) && (num_rec > 0)) {
3520 		uint8_t		*b;
3521 
3522 		/* Just return info from the first service record. */
3523 		svcrec_resp = (sa_service_record_t *)results_p;
3524 
3525 		/* The Service GID and Service ID */
3526 		resultp->ar_gid = svcrec_resp->ServiceGID;
3527 		resultp->ar_pkey = svcrec_resp->ServiceP_Key;
3528 		bcopy(svcrec_resp->ServiceData,
3529 		    resultp->ar_data, IBCM_DAPL_ATS_NBYTES);
3530 
3531 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: "
3532 		    "Found: pkey %x dgid %llX:%llX", resultp->ar_pkey,
3533 		    (longlong_t)resultp->ar_gid.gid_prefix,
3534 		    (longlong_t)resultp->ar_gid.gid_guid);
3535 		b = resultp->ar_data;
3536 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar:"
3537 		    " data %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
3538 		    b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9],
3539 		    b[10], b[11], b[12], b[13], b[14], b[15]);
3540 
3541 		/* Deallocate the memory for results_p. */
3542 		kmem_free(results_p, length);
3543 		if (num_rec > 1)
3544 			retval = IBT_MULTIPLE_AR;
3545 		else
3546 			retval = IBT_SUCCESS;
3547 	} else {
3548 		IBTF_DPRINTF_L2(cmlog, "ibt_query_ar: "
3549 		    "ibmf_sa_access found 0 matching records");
3550 		retval = IBT_AR_NOT_REGISTERED;
3551 	}
3552 	return (retval);
3553 }
3554 
3555 /* mark all ATS service records associated with the port */
3556 static void
3557 ibcm_mark_ar(ib_guid_t hca_guid, uint8_t port)
3558 {
3559 	ibcm_ar_t	*tmp;
3560 
3561 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
3562 	for (tmp = ibcm_ar_list; tmp != NULL; tmp = tmp->ar_link) {
3563 		if (tmp->ar_hcap->hca_guid == hca_guid &&
3564 		    tmp->ar_port == port) {
3565 			/* even if it's busy, we mark it for rewrite */
3566 			tmp->ar_rewrite_state = IBCM_REWRITE_NEEDED;
3567 		}
3568 	}
3569 }
3570 
3571 /* rewrite all ATS service records */
3572 static int
3573 ibcm_rewrite_ar(void)
3574 {
3575 	ibcm_ar_t		*tmp;
3576 	ibmf_saa_handle_t	saa_handle;
3577 	sa_service_record_t	*srv_recp;
3578 	ibt_status_t		rval;
3579 	int			did_something = 0;
3580 
3581 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
3582 check_for_work:
3583 	for (tmp = ibcm_ar_list; tmp != NULL; tmp = tmp->ar_link) {
3584 		if (tmp->ar_rewrite_state == IBCM_REWRITE_NEEDED) {
3585 			tmp->ar_rewrite_state = IBCM_REWRITE_BUSY;
3586 			saa_handle = tmp->ar_saa_handle;
3587 			srv_recp = tmp->ar_srv_recp;
3588 			mutex_exit(&ibcm_svc_info_lock);
3589 			IBTF_DPRINTF_L3(cmlog, "ibcm_rewrite_ar: "
3590 			    "rewriting ar @ %p", tmp);
3591 			did_something = 1;
3592 			rval = ibcm_write_service_record(saa_handle, srv_recp,
3593 			    IBMF_SAA_UPDATE);
3594 			if (rval != IBT_SUCCESS)
3595 				IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_ar: "
3596 				    "ibcm_write_service_record failed: "
3597 				    "status = %d", rval);
3598 			mutex_enter(&ibcm_svc_info_lock);
3599 			/* if it got marked again, then we want to rewrite */
3600 			if (tmp->ar_rewrite_state == IBCM_REWRITE_BUSY)
3601 				tmp->ar_rewrite_state = IBCM_REWRITE_IDLE;
3602 			/* in case there was a waiter... */
3603 			cv_broadcast(&ibcm_svc_info_cv);
3604 			goto check_for_work;
3605 		}
3606 	}
3607 	return (did_something);
3608 }
3609 
3610 static void
3611 ibcm_rewrite_svc_record(ibcm_svc_info_t *srv_hdl, ibcm_svc_bind_t *sbindp)
3612 {
3613 	ibcm_hca_info_t		*hcap;
3614 	ib_svc_id_t		sid, start_sid, end_sid;
3615 	ibmf_saa_handle_t	saa_handle;
3616 	sa_service_record_t	srv_rec;
3617 	ibt_status_t		rval;
3618 
3619 	hcap = ibcm_find_hca_entry(sbindp->sbind_hcaguid);
3620 	if (hcap == NULL) {
3621 		IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record: "
3622 		    "NO HCA found for HCA GUID %llX", sbindp->sbind_hcaguid);
3623 		return;
3624 	}
3625 
3626 	saa_handle = ibcm_get_saa_handle(hcap, sbindp->sbind_port);
3627 	if (saa_handle == NULL) {
3628 		IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record: "
3629 		    "saa_handle is NULL");
3630 		ibcm_dec_hca_acc_cnt(hcap);
3631 		return;
3632 	}
3633 
3634 	IBTF_DPRINTF_L3(cmlog, "ibcm_rewrite_svc_record: "
3635 	    "rewriting svc '%s', port_guid = %llX", sbindp->sbind_name,
3636 	    sbindp->sbind_gid.gid_guid);
3637 
3638 	bzero(&srv_rec, sizeof (srv_rec));
3639 
3640 	srv_rec.ServiceLease = sbindp->sbind_lease;
3641 	srv_rec.ServiceP_Key = sbindp->sbind_pkey;
3642 	srv_rec.ServiceKey_hi = sbindp->sbind_key[0];
3643 	srv_rec.ServiceKey_lo = sbindp->sbind_key[1];
3644 	(void) strcpy((char *)srv_rec.ServiceName, sbindp->sbind_name);
3645 	srv_rec.ServiceGID = sbindp->sbind_gid;
3646 
3647 	bcopy(sbindp->sbind_data, srv_rec.ServiceData, IB_SVC_DATA_LEN);
3648 
3649 	/* insert srv record into the SA */
3650 	start_sid = srv_hdl->svc_id;
3651 	end_sid = start_sid + srv_hdl->svc_num_sids - 1;
3652 	for (sid = start_sid; sid <= end_sid; sid++) {
3653 		srv_rec.ServiceID = sid;
3654 
3655 		rval = ibcm_write_service_record(saa_handle, &srv_rec,
3656 		    IBMF_SAA_UPDATE);
3657 
3658 		IBTF_DPRINTF_L4(cmlog, "ibcm_rewrite_svc_record: "
3659 		    "ibcm_write_service_record, SvcId = %llX, "
3660 		    "rval = %d", (longlong_t)sid, rval);
3661 		if (rval != IBT_SUCCESS) {
3662 			IBTF_DPRINTF_L2(cmlog, "ibcm_rewrite_svc_record:"
3663 			    " ibcm_write_service_record fails %d sid %llX",
3664 			    rval, (longlong_t)sid);
3665 		}
3666 	}
3667 	ibcm_dec_hca_acc_cnt(hcap);
3668 }
3669 
3670 /*
3671  * Task to mark all service records as needing to be rewritten to the SM/SA.
3672  * This task does not return until all of them have been rewritten.
3673  */
3674 void
3675 ibcm_service_record_rewrite_task(void *arg)
3676 {
3677 	ibcm_port_up_t	*pup = (ibcm_port_up_t *)arg;
3678 	ib_guid_t	hca_guid = pup->pup_hca_guid;
3679 	uint8_t		port = pup->pup_port;
3680 	ibcm_svc_info_t	*svcp;
3681 	ibcm_svc_bind_t	*sbp;
3682 	avl_tree_t	*avl_tree = &ibcm_svc_avl_tree;
3683 	static int	task_is_running = 0;
3684 
3685 	IBTF_DPRINTF_L2(cmlog, "ibcm_service_record_rewrite_task STARTED "
3686 	    "for hca_guid %llX, port %d", hca_guid, port);
3687 
3688 	mutex_enter(&ibcm_svc_info_lock);
3689 	ibcm_mark_ar(hca_guid, port);
3690 	for (svcp = avl_first(avl_tree); svcp != NULL;
3691 	    svcp = avl_walk(avl_tree, svcp, AVL_AFTER)) {
3692 		sbp = svcp->svc_bind_list;
3693 		while (sbp != NULL) {
3694 			if (sbp->sbind_pkey != 0 &&
3695 			    sbp->sbind_port == port &&
3696 			    sbp->sbind_hcaguid == hca_guid) {
3697 				/* even if it's busy, we mark it for rewrite */
3698 				sbp->sbind_rewrite_state = IBCM_REWRITE_NEEDED;
3699 			}
3700 			sbp = sbp->sbind_link;
3701 		}
3702 	}
3703 	if (task_is_running) {
3704 		/* let the other task thread finish the work */
3705 		mutex_exit(&ibcm_svc_info_lock);
3706 		return;
3707 	}
3708 	task_is_running = 1;
3709 
3710 	(void) ibcm_rewrite_ar();
3711 
3712 check_for_work:
3713 	for (svcp = avl_first(avl_tree); svcp != NULL;
3714 	    svcp = avl_walk(avl_tree, svcp, AVL_AFTER)) {
3715 		sbp = svcp->svc_bind_list;
3716 		while (sbp != NULL) {
3717 			if (sbp->sbind_rewrite_state == IBCM_REWRITE_NEEDED) {
3718 				sbp->sbind_rewrite_state = IBCM_REWRITE_BUSY;
3719 				mutex_exit(&ibcm_svc_info_lock);
3720 				ibcm_rewrite_svc_record(svcp, sbp);
3721 				mutex_enter(&ibcm_svc_info_lock);
3722 				/* if it got marked again, we want to rewrite */
3723 				if (sbp->sbind_rewrite_state ==
3724 				    IBCM_REWRITE_BUSY)
3725 					sbp->sbind_rewrite_state =
3726 					    IBCM_REWRITE_IDLE;
3727 				/* in case there was a waiter... */
3728 				cv_broadcast(&ibcm_svc_info_cv);
3729 				goto check_for_work;
3730 			}
3731 			sbp = sbp->sbind_link;
3732 		}
3733 	}
3734 	/*
3735 	 * If there were no service records to write, and we failed to
3736 	 * have to rewrite any more ATS service records, then we're done.
3737 	 */
3738 	if (ibcm_rewrite_ar() != 0)
3739 		goto check_for_work;
3740 	task_is_running = 0;
3741 	mutex_exit(&ibcm_svc_info_lock);
3742 
3743 	IBTF_DPRINTF_L2(cmlog, "ibcm_service_record_rewrite_task DONE");
3744 	kmem_free(pup, sizeof (ibcm_port_up_t));
3745 }
3746 
3747 
3748 /*
3749  * Function:
3750  * 	ibt_cm_proceed
3751  *
3752  * Verifies the arguments and dispatches the cm state machine processing
3753  * via taskq
3754  */
3755 
3756 ibt_status_t
3757 ibt_cm_proceed(ibt_cm_event_type_t event, void *session_id,
3758     ibt_cm_status_t status, ibt_cm_proceed_reply_t *cm_event_data,
3759     void *priv_data, ibt_priv_data_len_t priv_data_len)
3760 {
3761 	ibcm_state_data_t *statep = (ibcm_state_data_t *)session_id;
3762 	ibcm_proceed_targs_t	*proceed_targs;
3763 	ibcm_proceed_error_t	proceed_error;
3764 
3765 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_proceed chan 0x%p event %x status %x "
3766 	    "session_id %p", statep->channel, event, status, session_id);
3767 
3768 	IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed chan 0x%p cm_event_data %p, "
3769 	    "priv_data %p priv_data_len %x", statep->channel, cm_event_data,
3770 	    priv_data, priv_data_len);
3771 
3772 	/* validate session_id and status */
3773 	if ((statep == NULL) || (status == IBT_CM_DEFER)) {
3774 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : Invalid Args");
3775 		return (IBT_INVALID_PARAM);
3776 	}
3777 
3778 	/* If priv data len specified, then priv_data cannot be NULL */
3779 	if ((priv_data_len > 0) && (priv_data == NULL))
3780 		return (IBT_INVALID_PARAM);
3781 
3782 	proceed_error = IBCM_PROCEED_INVALID_NONE;
3783 
3784 	mutex_enter(&statep->state_mutex);
3785 	if (event == IBT_CM_EVENT_REQ_RCV) {
3786 
3787 		if ((statep->state != IBCM_STATE_REQ_RCVD) &&
3788 		    (statep->state != IBCM_STATE_MRA_SENT))
3789 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
3790 		else if (priv_data_len > IBT_REP_PRIV_DATA_SZ)
3791 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
3792 
3793 	} else if (event == IBT_CM_EVENT_REP_RCV) {
3794 		if ((statep->state != IBCM_STATE_REP_RCVD) &&
3795 		    (statep->state != IBCM_STATE_MRA_REP_SENT))
3796 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
3797 		else if (priv_data_len > IBT_RTU_PRIV_DATA_SZ)
3798 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
3799 	} else if (event == IBT_CM_EVENT_LAP_RCV) {
3800 		if ((statep->ap_state != IBCM_AP_STATE_LAP_RCVD) &&
3801 		    (statep->ap_state != IBCM_AP_STATE_MRA_LAP_SENT))
3802 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
3803 		else if (priv_data_len > IBT_APR_PRIV_DATA_SZ)
3804 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
3805 	} else if (event == IBT_CM_EVENT_CONN_CLOSED) {
3806 		if (statep->state != IBCM_STATE_DREQ_RCVD)
3807 			proceed_error = IBCM_PROCEED_INVALID_EVENT_STATE;
3808 		else if (priv_data_len > IBT_DREP_PRIV_DATA_SZ)
3809 			proceed_error = IBCM_PROCEED_INVALID_PRIV_SZ;
3810 	} else {
3811 			proceed_error = IBCM_PROCEED_INVALID_EVENT;
3812 	}
3813 
3814 	/* if there is an error, print an error message and return */
3815 	if (proceed_error != IBCM_PROCEED_INVALID_NONE) {
3816 		mutex_exit(&statep->state_mutex);
3817 		if (proceed_error == IBCM_PROCEED_INVALID_EVENT_STATE) {
3818 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
3819 			    "Invalid Event/State combination specified",
3820 			    statep->channel);
3821 			return (IBT_INVALID_PARAM);
3822 		} else if (proceed_error == IBCM_PROCEED_INVALID_PRIV_SZ) {
3823 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
3824 			    "Invalid Event/priv len combination specified",
3825 			    statep->channel);
3826 			return (IBT_INVALID_PARAM);
3827 		} else if (proceed_error == IBCM_PROCEED_INVALID_EVENT) {
3828 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
3829 			    "Invalid Event specified", statep->channel);
3830 			return (IBT_INVALID_PARAM);
3831 		} else {
3832 			ASSERT(proceed_error == IBCM_PROCEED_INVALID_LAP);
3833 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p"
3834 			    "IBT_CM_EVENT_LAP_RCV not supported",
3835 			    statep->channel);
3836 			/* UNTIL HCA DRIVER ENABLES AP SUPPORT, FAIL THE CALL */
3837 			return (IBT_APM_NOT_SUPPORTED);
3838 		}
3839 	}
3840 
3841 
3842 	/* wait until client's CM handler returns DEFER status back to CM */
3843 
3844 	while (statep->clnt_proceed == IBCM_BLOCK) {
3845 		IBTF_DPRINTF_L5(cmlog, "ibt_cm_proceed : chan 0x%p blocked for "
3846 		    "return of client's cm handler", statep->channel);
3847 		cv_wait(&statep->block_client_cv, &statep->state_mutex);
3848 	}
3849 
3850 	if (statep->clnt_proceed == IBCM_FAIL) {
3851 		mutex_exit(&statep->state_mutex);
3852 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_proceed : chan 0x%p Failed as "
3853 		    "client returned non-DEFER status from cm handler",
3854 		    statep->channel);
3855 		return (IBT_CHAN_STATE_INVALID);
3856 	}
3857 
3858 	ASSERT(statep->clnt_proceed == IBCM_UNBLOCK);
3859 	statep->clnt_proceed = IBCM_FAIL;
3860 	mutex_exit(&statep->state_mutex);
3861 
3862 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
3863 
3864 	/* the state machine processing is done in a separate thread */
3865 
3866 	/* proceed_targs is freed in ibcm_proceed_via_taskq */
3867 	proceed_targs = kmem_alloc(sizeof (ibcm_proceed_targs_t),
3868 	    KM_SLEEP);
3869 
3870 	proceed_targs->event  = event;
3871 	proceed_targs->status = status;
3872 	proceed_targs->priv_data_len = priv_data_len;
3873 
3874 	bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
3875 
3876 	proceed_targs->tst.rc.statep = statep;
3877 	bcopy(cm_event_data, &proceed_targs->tst.rc.rc_cm_event_data,
3878 	    sizeof (ibt_cm_proceed_reply_t));
3879 
3880 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
3881 
3882 	(void) taskq_dispatch(ibcm_taskq, ibcm_proceed_via_taskq,
3883 	    proceed_targs, TQ_SLEEP);
3884 
3885 	return (IBT_SUCCESS);
3886 }
3887 
3888 /*
3889  * Function:
3890  * 	ibcm_proceed_via_taskq
3891  *
3892  * Called from taskq, dispatched by ibt_cm_proceed
3893  * Completes the cm state processing for ibt_cm_proceed
3894  */
3895 void
3896 ibcm_proceed_via_taskq(void *targs)
3897 {
3898 	ibcm_proceed_targs_t	*proceed_targs = (ibcm_proceed_targs_t *)targs;
3899 	ibcm_state_data_t *statep = proceed_targs->tst.rc.statep;
3900 	ibt_cm_reason_t reject_reason;
3901 	uint8_t arej_len;
3902 	ibcm_status_t response;
3903 	ibcm_clnt_reply_info_t clnt_info;
3904 
3905 	clnt_info.reply_event = &proceed_targs->tst.rc.rc_cm_event_data;
3906 	clnt_info.priv_data = proceed_targs->priv_data;
3907 	clnt_info.priv_data_len = proceed_targs->priv_data_len;
3908 
3909 	IBTF_DPRINTF_L4(cmlog, "ibcm_proceed_via_taskq chan 0x%p targs %x",
3910 	    statep->channel, targs);
3911 
3912 	if (proceed_targs->event == IBT_CM_EVENT_REQ_RCV) {
3913 		response =
3914 		    ibcm_process_cep_req_cm_hdlr(statep, proceed_targs->status,
3915 		    &clnt_info, &reject_reason, &arej_len,
3916 		    (ibcm_req_msg_t *)statep->defer_cm_msg);
3917 
3918 		ibcm_handle_cep_req_response(statep, response, reject_reason,
3919 		    arej_len);
3920 
3921 	} else if (proceed_targs->event == IBT_CM_EVENT_REP_RCV) {
3922 		response =
3923 		    ibcm_process_cep_rep_cm_hdlr(statep, proceed_targs->status,
3924 		    &clnt_info, &reject_reason, &arej_len,
3925 		    (ibcm_rep_msg_t *)statep->defer_cm_msg);
3926 
3927 		ibcm_handle_cep_rep_response(statep, response, reject_reason,
3928 		    arej_len, (ibcm_rep_msg_t *)statep->defer_cm_msg);
3929 
3930 	} else if (proceed_targs->event == IBT_CM_EVENT_LAP_RCV) {
3931 		ibcm_process_cep_lap_cm_hdlr(statep, proceed_targs->status,
3932 		    &clnt_info, (ibcm_lap_msg_t *)statep->defer_cm_msg,
3933 		    (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg));
3934 
3935 		ibcm_post_apr_mad(statep);
3936 
3937 	} else {
3938 		ASSERT(proceed_targs->event == IBT_CM_EVENT_CONN_CLOSED);
3939 		ibcm_handle_cep_dreq_response(statep, proceed_targs->priv_data,
3940 		    proceed_targs->priv_data_len);
3941 	}
3942 
3943 	kmem_free(targs, sizeof (ibcm_proceed_targs_t));
3944 }
3945 
3946 /*
3947  * Function:
3948  * 	ibt_cm_ud_proceed
3949  *
3950  * Verifies the arguments and dispatches the cm state machine processing
3951  * via taskq
3952  */
3953 ibt_status_t
3954 ibt_cm_ud_proceed(void *session_id, ibt_channel_hdl_t ud_channel,
3955     ibt_cm_status_t status, ibt_redirect_info_t *redirect_infop,
3956     void *priv_data, ibt_priv_data_len_t priv_data_len)
3957 {
3958 	ibcm_ud_state_data_t *ud_statep = (ibcm_ud_state_data_t *)session_id;
3959 	ibcm_proceed_targs_t	*proceed_targs;
3960 	ibt_qp_query_attr_t	qp_attr;
3961 	ibt_status_t		retval;
3962 
3963 	IBTF_DPRINTF_L3(cmlog, "ibt_cm_ud_proceed session_id %p "
3964 	    "ud_channel %p ", session_id, ud_channel);
3965 
3966 	IBTF_DPRINTF_L4(cmlog, "ibt_cm_ud_proceed status %x priv_data %p "
3967 	    "priv_data_len %x",  status, priv_data, priv_data_len);
3968 
3969 	/* validate session_id and status */
3970 	if ((ud_statep == NULL) || (status == IBT_CM_DEFER)) {
3971 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Invalid Args");
3972 		return (IBT_INVALID_PARAM);
3973 	}
3974 
3975 	/* If priv data len specified, then priv_data cannot be NULL */
3976 	if ((priv_data_len > 0) && (priv_data == NULL))
3977 		return (IBT_INVALID_PARAM);
3978 
3979 	if (priv_data_len > IBT_SIDR_REP_PRIV_DATA_SZ)
3980 		return (IBT_INVALID_PARAM);
3981 
3982 	/* retrieve qpn and qkey from ud channel */
3983 
3984 	/* validate event and statep's state */
3985 
3986 	if (status == IBT_CM_ACCEPT) {
3987 		retval = ibt_query_qp(ud_channel, &qp_attr);
3988 		if ((retval != IBT_SUCCESS) ||
3989 		    (qp_attr.qp_info.qp_trans != IBT_UD_SRV)) {
3990 			IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed: "
3991 			    "Failed to retrieve QPN from the channel: %d",
3992 			    retval);
3993 			return (IBT_INVALID_PARAM);
3994 		}
3995 	}
3996 
3997 
3998 	mutex_enter(&ud_statep->ud_state_mutex);
3999 
4000 	if (ud_statep->ud_state != IBCM_STATE_SIDR_REQ_RCVD) {
4001 		mutex_exit(&ud_statep->ud_state_mutex);
4002 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Invalid State "
4003 		    "specified");
4004 		return (IBT_INVALID_PARAM);
4005 	}
4006 
4007 	/* wait until client's CM handler returns DEFER status back to CM */
4008 
4009 	while (ud_statep->ud_clnt_proceed == IBCM_BLOCK) {
4010 		IBTF_DPRINTF_L5(cmlog, "ibt_cm_ud_proceed : Blocked for return"
4011 		    " of client's ud cm handler");
4012 		cv_wait(&ud_statep->ud_block_client_cv,
4013 		    &ud_statep->ud_state_mutex);
4014 	}
4015 
4016 	if (ud_statep->ud_clnt_proceed == IBCM_FAIL) {
4017 		mutex_exit(&ud_statep->ud_state_mutex);
4018 		IBTF_DPRINTF_L2(cmlog, "ibt_cm_ud_proceed : Failed as client "
4019 		    "returned non-DEFER status from cm handler");
4020 		return (IBT_INVALID_PARAM);
4021 	}
4022 
4023 	ASSERT(ud_statep->ud_clnt_proceed == IBCM_UNBLOCK);
4024 	ud_statep->ud_clnt_proceed = IBCM_FAIL;
4025 	mutex_exit(&ud_statep->ud_state_mutex);
4026 
4027 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*proceed_targs))
4028 
4029 	/* the state machine processing is done in a separate thread */
4030 
4031 	/* proceed_targs is freed in ibcm_proceed_via_taskq */
4032 	proceed_targs = kmem_alloc(sizeof (ibcm_proceed_targs_t),
4033 	    KM_SLEEP);
4034 
4035 	proceed_targs->status = status;
4036 	proceed_targs->priv_data_len = priv_data_len;
4037 
4038 	bcopy(priv_data, proceed_targs->priv_data, priv_data_len);
4039 
4040 	if (status == IBT_CM_ACCEPT) {
4041 		proceed_targs->tst.ud.ud_qkey =
4042 		    qp_attr.qp_info.qp_transport.ud.ud_qkey;
4043 		proceed_targs->tst.ud.ud_qpn = qp_attr.qp_qpn;
4044 	}
4045 
4046 	proceed_targs->tst.ud.ud_statep = ud_statep;
4047 
4048 	/* copy redirect info based on status */
4049 	if (status == IBT_CM_REDIRECT)
4050 		bcopy(redirect_infop, &proceed_targs->tst.ud.ud_redirect_info,
4051 		    sizeof (ibt_redirect_info_t));
4052 
4053 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*proceed_targs))
4054 
4055 	(void) taskq_dispatch(ibcm_taskq, ibcm_ud_proceed_via_taskq,
4056 	    proceed_targs, TQ_SLEEP);
4057 
4058 	return (IBT_SUCCESS);
4059 }
4060 
4061 /*
4062  * Function:
4063  * 	ibcm_ud_proceed_via_taskq
4064  *
4065  * Called from taskq, dispatched by ibt_cm_ud_proceed
4066  * Completes the cm state processing for ibt_cm_ud_proceed
4067  */
4068 void
4069 ibcm_ud_proceed_via_taskq(void *targs)
4070 {
4071 	ibcm_proceed_targs_t	*proceed_targs = (ibcm_proceed_targs_t *)targs;
4072 	ibcm_ud_state_data_t	*ud_statep = proceed_targs->tst.ud.ud_statep;
4073 	ibcm_ud_clnt_reply_info_t ud_clnt_info;
4074 	ibt_sidr_status_t	sidr_status;
4075 
4076 	IBTF_DPRINTF_L4(cmlog, "ibcm_ud_proceed_via_taskq(%p)", targs);
4077 
4078 	ud_clnt_info.ud_qpn  = proceed_targs->tst.ud.ud_qpn;
4079 	ud_clnt_info.ud_qkey  = proceed_targs->tst.ud.ud_qkey;
4080 	ud_clnt_info.priv_data = proceed_targs->priv_data;
4081 	ud_clnt_info.priv_data_len = proceed_targs->priv_data_len;
4082 	ud_clnt_info.redirect_infop = &proceed_targs->tst.ud.ud_redirect_info;
4083 
4084 	/* validate event and statep's state */
4085 	ibcm_process_sidr_req_cm_hdlr(ud_statep, proceed_targs->status,
4086 	    &ud_clnt_info, &sidr_status,
4087 	    (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg));
4088 
4089 	ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
4090 
4091 	/* decr the statep ref cnt incremented in ibcm_process_sidr_req_msg */
4092 	mutex_enter(&ud_statep->ud_state_mutex);
4093 	IBCM_UD_REF_CNT_DECR(ud_statep);
4094 	mutex_exit(&ud_statep->ud_state_mutex);
4095 
4096 	kmem_free(targs, sizeof (ibcm_proceed_targs_t));
4097 }
4098 
4099 /*
4100  * Function:
4101  *	ibt_set_alt_path
4102  * Input:
4103  *	channel		Channel handle returned from ibt_alloc_rc_channel(9F).
4104  *
4105  *	mode		Execute in blocking or non blocking mode.
4106  *
4107  *	alt_path	A pointer to an ibt_alt_path_info_t as returned from an
4108  *			ibt_get_alt_path(9F) call that specifies the new
4109  *			alternate path.
4110  *
4111  *	priv_data       A pointer to a buffer specified by caller for the
4112  *			private data in the outgoing CM Load Alternate Path
4113  *			(LAP) message sent to the remote host. This can be NULL
4114  *			if no private data is available to communicate to the
4115  *			remote node.
4116  *
4117  *	priv_data_len   Length of valid data in priv_data, this should be less
4118  *			than or equal to IBT_LAP_PRIV_DATA_SZ.
4119  *
4120  * Output:
4121  *	ret_args	If called in blocking mode, points to a return argument
4122  *			structure of type ibt_ap_returns_t.
4123  *
4124  * Returns:
4125  *	IBT_SUCCESS on Success else appropriate error.
4126  * Description:
4127  *	Load the specified alternate path. Causes the CM to send an LAP message
4128  *	to the remote node.
4129  *	Can only be called on a previously opened RC channel.
4130  */
4131 ibt_status_t
4132 ibt_set_alt_path(ibt_channel_hdl_t channel, ibt_execution_mode_t mode,
4133     ibt_alt_path_info_t *alt_path, void *priv_data,
4134     ibt_priv_data_len_t priv_data_len, ibt_ap_returns_t *ret_args)
4135 {
4136 	ibmf_handle_t		ibmf_hdl;
4137 	ibt_status_t		status = IBT_SUCCESS;
4138 	ibcm_lap_msg_t		*lap_msgp;
4139 	ibcm_hca_info_t		*hcap;
4140 	ibcm_state_data_t	*statep;
4141 	uint8_t			port_no;
4142 	ib_lid_t		alternate_slid;
4143 	ibt_priv_data_len_t	len;
4144 	ib_lid_t		base_lid;
4145 	boolean_t		alt_grh;
4146 
4147 	IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path(%p, %x, %p, %p, %x, %p)",
4148 	    channel, mode, alt_path, priv_data, priv_data_len, ret_args);
4149 
4150 	/* validate channel */
4151 	if (IBCM_INVALID_CHANNEL(channel)) {
4152 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: invalid channel");
4153 		return (IBT_CHAN_HDL_INVALID);
4154 	}
4155 
4156 	if (ibtl_cm_get_chan_type(channel) != IBT_RC_SRV) {
4157 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4158 		    "Invalid Channel type: Applicable only to RC Channel");
4159 		return (IBT_CHAN_SRV_TYPE_INVALID);
4160 	}
4161 
4162 	if (mode == IBT_NONBLOCKING) {
4163 		if (ret_args != NULL) {
4164 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4165 			    "ret_args should be NULL when called in "
4166 			    "non-blocking mode");
4167 			return (IBT_INVALID_PARAM);
4168 		}
4169 	} else if (mode == IBT_BLOCKING) {
4170 		if (ret_args == NULL) {
4171 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4172 			    "ret_args should be Non-NULL when called in "
4173 			    "blocking mode");
4174 			return (IBT_INVALID_PARAM);
4175 		}
4176 		if (ret_args->ap_priv_data_len > IBT_APR_PRIV_DATA_SZ) {
4177 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4178 			    "expected private data length is too large");
4179 			return (IBT_INVALID_PARAM);
4180 		}
4181 		if ((ret_args->ap_priv_data_len > 0) &&
4182 		    (ret_args->ap_priv_data == NULL)) {
4183 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4184 			    "apr_priv_data_len > 0, but apr_priv_data NULL");
4185 			return (IBT_INVALID_PARAM);
4186 		}
4187 	} else { /* any other mode is not valid for ibt_set_alt_path */
4188 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4189 		    "invalid mode %x specified", mode);
4190 		return (IBT_INVALID_PARAM);
4191 	}
4192 
4193 	if ((port_no = alt_path->ap_alt_cep_path.cep_hca_port_num) == 0)
4194 		return (IBT_INVALID_PARAM);
4195 
4196 	/* get the statep */
4197 	IBCM_GET_CHAN_PRIVATE(channel, statep);
4198 	if (statep == NULL) {
4199 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: statep NULL");
4200 		return (IBT_CM_FAILURE);
4201 	}
4202 
4203 	mutex_enter(&statep->state_mutex);
4204 	IBCM_RELEASE_CHAN_PRIVATE(channel);
4205 	IBCM_REF_CNT_INCR(statep);
4206 	mutex_exit(&statep->state_mutex);
4207 
4208 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: statep %p", statep);
4209 
4210 	hcap = statep->hcap;
4211 
4212 	/* HCA must have been in active state. If not, it's a client bug */
4213 	if (!IBCM_ACCESS_HCA_OK(hcap))
4214 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: hca in error state");
4215 
4216 	ASSERT(statep->cm_handler != NULL);
4217 
4218 	/* Check Alternate port */
4219 	status = ibt_get_port_state_byguid(hcap->hca_guid, port_no, NULL,
4220 	    &base_lid);
4221 	if (status != IBT_SUCCESS) {
4222 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4223 		    "ibt_get_port_state_byguid status %d ", status);
4224 		mutex_enter(&statep->state_mutex);
4225 		IBCM_REF_CNT_DECR(statep);
4226 		mutex_exit(&statep->state_mutex);
4227 		return (status);
4228 	}
4229 
4230 	if ((hcap->hca_port_info[port_no - 1].port_ibmf_hdl == NULL) &&
4231 	    ((status = ibcm_hca_reinit_port(hcap, port_no - 1))
4232 	    != IBT_SUCCESS)) {
4233 		IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4234 		    "ibmf reg or callback setup failed during re-initialize");
4235 		mutex_enter(&statep->state_mutex);
4236 		IBCM_REF_CNT_DECR(statep);
4237 		mutex_exit(&statep->state_mutex);
4238 		return (status);
4239 	}
4240 
4241 	ibmf_hdl = statep->stored_reply_addr.ibmf_hdl;
4242 
4243 	alternate_slid = base_lid +
4244 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_src_path;
4245 
4246 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: alternate SLID = %x",
4247 	    h2b16(alternate_slid));
4248 
4249 	ibcm_lapr_enter();	/* limit how many run simultaneously */
4250 
4251 	/* Allocate MAD for LAP */
4252 	if (statep->lapr_msg == NULL)
4253 		if ((status = ibcm_alloc_out_msg(ibmf_hdl, &statep->lapr_msg,
4254 		    MAD_METHOD_SEND)) != IBT_SUCCESS) {
4255 			ibcm_lapr_exit();
4256 			IBTF_DPRINTF_L2(cmlog, "ibt_set_alt_path: "
4257 			    "chan 0x%p ibcm_alloc_out_msg failed", channel);
4258 			mutex_enter(&statep->state_mutex);
4259 			IBCM_REF_CNT_DECR(statep);
4260 			mutex_exit(&statep->state_mutex);
4261 			return (status);
4262 		}
4263 
4264 	mutex_enter(&statep->state_mutex);
4265 
4266 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: connection state is"
4267 	    " %x", statep->state);
4268 
4269 	/* Check state */
4270 	if ((statep->state != IBCM_STATE_ESTABLISHED) ||
4271 	    (statep->ap_state != IBCM_AP_STATE_IDLE)) {
4272 		IBCM_REF_CNT_DECR(statep);
4273 		mutex_exit(&statep->state_mutex);
4274 		(void) ibcm_free_out_msg(ibmf_hdl, &statep->lapr_msg);
4275 		ibcm_lapr_exit();
4276 		return (IBT_CHAN_STATE_INVALID);
4277 	} else {
4278 		/* Set to LAP Sent state */
4279 		statep->ap_state = IBCM_AP_STATE_LAP_SENT;
4280 		statep->ap_done = B_FALSE;
4281 		statep->remaining_retry_cnt = statep->max_cm_retries;
4282 		statep->timer_stored_state = statep->state;
4283 		statep->timer_stored_ap_state = statep->ap_state;
4284 		IBCM_REF_CNT_INCR(statep); /* for ibcm_post_lap_complete */
4285 	}
4286 
4287 	mutex_exit(&statep->state_mutex);
4288 
4289 	/* No more failure returns below */
4290 
4291 	/* Allocate MAD for LAP */
4292 	IBTF_DPRINTF_L5(cmlog, "ibt_set_alt_path:"
4293 	    " statep's mad addr = 0x%p", IBCM_OUT_HDRP(statep->lapr_msg));
4294 
4295 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lap_msgp))
4296 
4297 	lap_msgp = (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
4298 
4299 	lap_msgp->lap_alt_l_port_lid = h2b16(alternate_slid);
4300 	lap_msgp->lap_alt_r_port_lid =
4301 	    h2b16(alt_path->ap_alt_cep_path.cep_adds_vect.av_dlid);
4302 
4303 	/* Fill in remote port gid */
4304 	lap_msgp->lap_alt_r_port_gid.gid_prefix =
4305 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_prefix);
4306 	lap_msgp->lap_alt_r_port_gid.gid_guid =
4307 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_dgid.gid_guid);
4308 
4309 	/* Fill in local port gid */
4310 	lap_msgp->lap_alt_l_port_gid.gid_prefix =
4311 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_prefix);
4312 	lap_msgp->lap_alt_l_port_gid.gid_guid =
4313 	    h2b64(alt_path->ap_alt_cep_path.cep_adds_vect.av_sgid.gid_guid);
4314 
4315 	alt_grh = alt_path->ap_alt_cep_path.cep_adds_vect.av_send_grh;
4316 
4317 	/* alternate_flow_label, and alternate srate, alternate traffic class */
4318 	lap_msgp->lap_alt_srate_plus =
4319 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_srate & 0x3f;
4320 	lap_msgp->lap_alt_flow_label_plus = h2b32(((alt_grh == B_TRUE) ?
4321 	    (alt_path->ap_alt_cep_path.cep_adds_vect.av_flow << 12) : 0) |
4322 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_tclass);
4323 
4324 	/* Alternate hop limit, service level */
4325 	lap_msgp->lap_alt_hop_limit = (alt_grh == B_TRUE) ?
4326 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_hop : 0xff;
4327 	lap_msgp->lap_alt_sl_plus =
4328 	    alt_path->ap_alt_cep_path.cep_adds_vect.av_srvl << 4 |
4329 	    ((alt_grh == B_FALSE) ? 0x8 : 0);
4330 
4331 	lap_msgp->lap_alt_local_acktime_plus = ibt_usec2ib(
4332 	    (2 * statep->rc_alt_pkt_lt) +
4333 	    ibt_ib2usec(hcap->hca_ack_delay)) << 3;
4334 
4335 	lap_msgp->lap_local_comm_id = h2b32(statep->local_comid);
4336 	lap_msgp->lap_remote_comm_id = h2b32(statep->remote_comid);
4337 
4338 	lap_msgp->lap_remote_qpn_eecn_plus =
4339 	    h2b32((statep->remote_qpn << 8) |
4340 	    ibt_usec2ib(ibcm_remote_response_time) << 3);
4341 
4342 	len = min(priv_data_len, IBT_LAP_PRIV_DATA_SZ);
4343 	if ((len > 0) && priv_data) {
4344 		bcopy(priv_data, lap_msgp->lap_private_data, len);
4345 	}
4346 
4347 	/* only rc_alt_pkt_lt and ap_return_data fields are initialized */
4348 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
4349 
4350 	statep->rc_alt_pkt_lt = ibt_ib2usec(alt_path->ap_alt_pkt_lt);
4351 
4352 	/* return_data is filled up in the state machine code */
4353 	statep->ap_return_data = ret_args;
4354 
4355 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
4356 
4357 	IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
4358 	    h2b16(IBCM_INCOMING_LAP + IBCM_ATTR_BASE_ID);
4359 
4360 	IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID =
4361 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_LAP, statep->local_comid,
4362 	    0));
4363 	IBTF_DPRINTF_L3(cmlog, "ibt_set_alt_path: statep %p, tid %llx",
4364 	    statep, IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID);
4365 
4366 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*lap_msgp))
4367 
4368 	/* Send LAP */
4369 	ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_lap_complete,
4370 	    statep);
4371 
4372 	mutex_enter(&statep->state_mutex);
4373 
4374 	if (mode == IBT_BLOCKING) {
4375 		IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: blocking");
4376 
4377 		/* wait for APR */
4378 		while (statep->ap_done != B_TRUE) {
4379 			cv_wait(&statep->block_client_cv,
4380 			    &statep->state_mutex);
4381 		}
4382 
4383 		IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done blocking");
4384 
4385 		/*
4386 		 * In the case that ibt_set_alt_path fails,
4387 		 * change retval to IBT_CM_FAILURE
4388 		 */
4389 		if (statep->ap_return_data->ap_status != IBT_CM_AP_LOADED)
4390 			status = IBT_CM_FAILURE;
4391 
4392 	}
4393 
4394 	/* decrement the ref-count before leaving here */
4395 	IBCM_REF_CNT_DECR(statep);
4396 
4397 	mutex_exit(&statep->state_mutex);
4398 
4399 	ibcm_lapr_exit();
4400 
4401 	/* If this message isn't seen then ibt_set_alt_path failed */
4402 	IBTF_DPRINTF_L4(cmlog, "ibt_set_alt_path: done");
4403 
4404 	return (status);
4405 }
4406 
4407 
4408 #ifdef DEBUG
4409 
4410 /*
4411  * ibcm_query_classport_info:
4412  *	Query classportinfo
4413  *
4414  * INPUTS:
4415  *	channel		- Channel that is associated with a statep
4416  *
4417  * RETURN VALUE: NONE
4418  * This function is currently used to generate a valid get method classport
4419  * info, and test CM functionality. There is no ibtl client interface to
4420  * generate a classportinfo. It is possible that CM may use classportinfo
4421  * from other nodes in the future, and most of the code below could be re-used.
4422  */
4423 void
4424 ibcm_query_classport_info(ibt_channel_hdl_t channel)
4425 {
4426 	ibcm_state_data_t	*statep;
4427 	ibmf_msg_t		*msgp;
4428 
4429 	IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info(%p)", channel);
4430 
4431 	/* validate channel, first */
4432 	if (IBCM_INVALID_CHANNEL(channel)) {
4433 		IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info: "
4434 		    "invalid channel (%p)", channel);
4435 		return;
4436 	}
4437 
4438 	/* get the statep */
4439 	IBCM_GET_CHAN_PRIVATE(channel, statep);
4440 
4441 	/*
4442 	 * This can happen, if the statep is already gone by a DREQ from
4443 	 * the remote side
4444 	 */
4445 	if (statep == NULL) {
4446 		IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info: "
4447 		    "statep NULL");
4448 		return;
4449 	}
4450 
4451 	mutex_enter(&statep->state_mutex);
4452 	IBCM_RELEASE_CHAN_PRIVATE(channel);
4453 	IBCM_REF_CNT_INCR(statep);
4454 	mutex_exit(&statep->state_mutex);
4455 
4456 	/* Debug/test code, so don't care about return status */
4457 	(void) ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl, &msgp,
4458 	    MAD_METHOD_GET);
4459 
4460 	IBCM_OUT_HDRP(msgp)->TransactionID = h2b64(ibcm_generate_tranid(
4461 	    MAD_ATTR_ID_CLASSPORTINFO, statep->local_comid, 0));
4462 	IBCM_OUT_HDRP(msgp)->AttributeID = h2b16(MAD_ATTR_ID_CLASSPORTINFO);
4463 
4464 	(void) ibcm_post_mad(msgp, &statep->stored_reply_addr, NULL, NULL);
4465 
4466 	IBTF_DPRINTF_L2(cmlog, "ibcm_query_classport_info(%p) "
4467 	    "Get method MAD posted ", channel);
4468 
4469 	(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl, &msgp);
4470 
4471 	mutex_enter(&statep->state_mutex);
4472 	IBCM_REF_CNT_DECR(statep);
4473 	mutex_exit(&statep->state_mutex);
4474 }
4475 
4476 static void
4477 ibcm_print_reply_addr(ibt_channel_hdl_t channel, ibcm_mad_addr_t *cm_reply_addr)
4478 {
4479 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: chan 0x%p, SLID %x, "
4480 	    "DLID %x", channel, cm_reply_addr->rcvd_addr.ia_local_lid,
4481 	    cm_reply_addr->rcvd_addr.ia_remote_lid);
4482 
4483 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: QKEY %x, PKEY %x, "
4484 	    "RQPN %x SL %x", cm_reply_addr->rcvd_addr.ia_q_key,
4485 	    cm_reply_addr->rcvd_addr.ia_p_key,
4486 	    cm_reply_addr->rcvd_addr.ia_remote_qno,
4487 	    cm_reply_addr->rcvd_addr.ia_service_level);
4488 
4489 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM SGID %llX:%llX ",
4490 	    cm_reply_addr->grh_hdr.ig_sender_gid.gid_prefix,
4491 	    cm_reply_addr->grh_hdr.ig_sender_gid.gid_guid);
4492 
4493 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM DGID %llX:%llX",
4494 	    cm_reply_addr->grh_hdr.ig_recver_gid.gid_prefix,
4495 	    cm_reply_addr->grh_hdr.ig_recver_gid.gid_guid);
4496 
4497 	IBTF_DPRINTF_L4(cmlog, "ibcm_print_reply_addr: CM FL %x TC %x HL %x",
4498 	    cm_reply_addr->grh_hdr.ig_flow_label,
4499 	    cm_reply_addr->grh_hdr.ig_tclass,
4500 	    cm_reply_addr->grh_hdr.ig_hop_limit);
4501 }
4502 
4503 #endif
4504 
4505 typedef struct ibcm_join_mcg_tqarg_s {
4506 	ib_gid_t		rgid;
4507 	ibt_mcg_attr_t		mcg_attr;
4508 	ibt_mcg_info_t		*mcg_infop;
4509 	ibt_mcg_handler_t	func;
4510 	void			*arg;
4511 } ibcm_join_mcg_tqarg_t;
4512 
4513 _NOTE(READ_ONLY_DATA(ibcm_join_mcg_tqarg_s))
4514 
4515 /*
4516  * Function:
4517  *	ibt_join_mcg
4518  * Input:
4519  *	rgid		The request GID that defines the HCA port from which a
4520  *			contact to SA Access is performed to add the specified
4521  *			endport GID ((mcg_attr->mc_pgid) to a multicast group.
4522  *			If mcg_attr->mc_pgid is null, then this (rgid) will be
4523  *			treated as endport GID that is to be added to the
4524  *			multicast group.
4525  *
4526  *	mcg_attr	A pointer to an ibt_mcg_attr_t structure that defines
4527  *			the attributes of the desired multicast group to be
4528  *			created or joined.
4529  *
4530  *	func		NULL or a pointer to a function to call when
4531  *			ibt_join_mcg() completes. If 'func' is not NULL then
4532  *			ibt_join_mcg() will return as soon as possible after
4533  *			initiating the multicast group join/create process.
4534  *			'func' is then called when the process completes.
4535  *
4536  *	arg		Argument to the 'func'.
4537  *
4538  * Output:
4539  *	mcg_info_p	A pointer to the ibt_mcg_info_t structure, allocated
4540  *			by the caller, where the attributes of the created or
4541  *			joined multicast group are copied.
4542  * Returns:
4543  *	IBT_SUCCESS
4544  *	IBT_INVALID_PARAM
4545  *	IBT_MCG_RECORDS_NOT_FOUND
4546  *	IBT_INSUFF_RESOURCE
4547  * Description:
4548  *	Join a multicast group.  The first full member "join" causes the MCG
4549  *	to be created.
4550  */
4551 ibt_status_t
4552 ibt_join_mcg(ib_gid_t rgid, ibt_mcg_attr_t *mcg_attr,
4553     ibt_mcg_info_t *mcg_info_p, ibt_mcg_handler_t func, void  *arg)
4554 {
4555 	ibcm_join_mcg_tqarg_t	*mcg_tq;
4556 	int			flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
4557 
4558 	IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg(%llX:%llX, %p)", rgid.gid_prefix,
4559 	    rgid.gid_guid, mcg_attr);
4560 
4561 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
4562 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Request GID is required");
4563 		return (IBT_INVALID_PARAM);
4564 	}
4565 
4566 	if ((mcg_attr->mc_pkey == IB_PKEY_INVALID_LIMITED) ||
4567 	    (mcg_attr->mc_pkey == IB_PKEY_INVALID_FULL)) {
4568 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Invalid P_Key specified");
4569 		return (IBT_INVALID_PARAM);
4570 	}
4571 
4572 	if (mcg_attr->mc_join_state == 0) {
4573 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: JoinState not specified");
4574 		return (IBT_INVALID_PARAM);
4575 	}
4576 
4577 	if (mcg_info_p == NULL) {
4578 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: mcg_info_p is NULL");
4579 		return (IBT_INVALID_PARAM);
4580 	}
4581 
4582 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mcg_tq))
4583 
4584 	mcg_tq = kmem_alloc(sizeof (ibcm_join_mcg_tqarg_t), flag);
4585 	if (mcg_tq == NULL) {
4586 		IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: "
4587 		    "Unable to allocate memory for local usage.");
4588 		return (IBT_INSUFF_KERNEL_RESOURCE);
4589 	}
4590 
4591 	mcg_tq->rgid = rgid;
4592 	bcopy(mcg_attr, &mcg_tq->mcg_attr, sizeof (ibt_mcg_attr_t));
4593 	mcg_tq->mcg_infop = mcg_info_p;
4594 	mcg_tq->func = func;
4595 	mcg_tq->arg = arg;
4596 
4597 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mcg_tq))
4598 
4599 	if (func != NULL) {	/* Non-Blocking */
4600 		IBTF_DPRINTF_L3(cmlog, "ibt_join_mcg: Non-Blocking Call");
4601 		if (taskq_dispatch(ibcm_taskq, ibcm_process_async_join_mcg,
4602 		    mcg_tq, TQ_NOSLEEP) == 0) {
4603 			IBTF_DPRINTF_L2(cmlog, "ibt_join_mcg: Failed to "
4604 			    "Dispatch the TaskQ");
4605 			kmem_free(mcg_tq, sizeof (ibcm_join_mcg_tqarg_t));
4606 			return (IBT_INSUFF_KERNEL_RESOURCE);
4607 		} else
4608 			return (IBT_SUCCESS);
4609 	} else {		/* Blocking */
4610 		return (ibcm_process_join_mcg(mcg_tq));
4611 	}
4612 }
4613 
4614 static void
4615 ibcm_process_async_join_mcg(void *tq_arg)
4616 {
4617 	(void) ibcm_process_join_mcg(tq_arg);
4618 }
4619 
4620 static ibt_status_t
4621 ibcm_process_join_mcg(void *taskq_arg)
4622 {
4623 	sa_mcmember_record_t	mcg_req;
4624 	sa_mcmember_record_t	*mcg_resp;
4625 	ibmf_saa_access_args_t	access_args;
4626 	ibmf_saa_handle_t	saa_handle;
4627 	uint64_t		component_mask = 0;
4628 	ibt_status_t		retval;
4629 	ibtl_cm_hca_port_t	hca_port;
4630 	uint_t			num_records;
4631 	size_t			length;
4632 	ibcm_hca_info_t		*hcap;
4633 	ibcm_join_mcg_tqarg_t	*mcg_arg = (ibcm_join_mcg_tqarg_t *)taskq_arg;
4634 	ibt_mcg_info_t		*mcg_info_p = mcg_arg->mcg_infop;
4635 
4636 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg(%p)", mcg_arg);
4637 
4638 	retval = ibtl_cm_get_hca_port(mcg_arg->rgid, 0, &hca_port);
4639 	if (retval != IBT_SUCCESS) {
4640 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: Failed to get "
4641 		    "port info from specified RGID: status = %d", retval);
4642 		goto ibcm_join_mcg_exit1;
4643 	}
4644 
4645 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
4646 
4647 	if ((mcg_arg->mcg_attr.mc_pgid.gid_prefix == 0) ||
4648 	    (mcg_arg->mcg_attr.mc_pgid.gid_guid == 0)) {
4649 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
4650 		    "Request GID is Port GID");
4651 		mcg_req.PortGID = mcg_arg->rgid;
4652 	} else {
4653 		mcg_req.PortGID = mcg_arg->mcg_attr.mc_pgid;
4654 	}
4655 	component_mask |= SA_MC_COMPMASK_PORTGID;
4656 
4657 	mcg_req.Q_Key = mcg_arg->mcg_attr.mc_qkey;
4658 	mcg_req.P_Key = mcg_arg->mcg_attr.mc_pkey;
4659 	mcg_req.JoinState = mcg_arg->mcg_attr.mc_join_state;
4660 	mcg_req.TClass = mcg_arg->mcg_attr.mc_tclass;
4661 	mcg_req.FlowLabel = mcg_arg->mcg_attr.mc_flow;
4662 	mcg_req.SL = mcg_arg->mcg_attr.mc_sl;
4663 
4664 	component_mask |= SA_MC_COMPMASK_QKEY | SA_MC_COMPMASK_PKEY |
4665 	    SA_MC_COMPMASK_JOINSTATE | SA_MC_COMPMASK_TCLASS |
4666 	    SA_MC_COMPMASK_FLOWLABEL | SA_MC_COMPMASK_SL;
4667 
4668 	/* If client has specified MGID, use it else SA will assign one. */
4669 	if ((mcg_arg->mcg_attr.mc_mgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
4670 		mcg_req.MGID = mcg_arg->mcg_attr.mc_mgid;
4671 		component_mask |= SA_MC_COMPMASK_MGID;
4672 	}
4673 
4674 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: PGID=%llX:%llX, "
4675 	    "MGID=%llX:%llX", mcg_req.PortGID.gid_prefix,
4676 	    mcg_req.PortGID.gid_guid, mcg_req.MGID.gid_prefix,
4677 	    mcg_req.MGID.gid_guid);
4678 
4679 	/* Is MTU specified. */
4680 	if (mcg_arg->mcg_attr.mc_mtu_req.r_mtu) {
4681 		mcg_req.MTU = mcg_arg->mcg_attr.mc_mtu_req.r_mtu;
4682 		mcg_req.MTUSelector = mcg_arg->mcg_attr.mc_mtu_req.r_selector;
4683 
4684 		component_mask |= SA_MC_COMPMASK_MTUSELECTOR |
4685 		    SA_MC_COMPMASK_MTU;
4686 	}
4687 
4688 	/* Is RATE specified. */
4689 	if (mcg_arg->mcg_attr.mc_rate_req.r_srate) {
4690 		mcg_req.Rate = mcg_arg->mcg_attr.mc_rate_req.r_srate;
4691 		mcg_req.RateSelector =
4692 		    mcg_arg->mcg_attr.mc_rate_req.r_selector;
4693 
4694 		component_mask |= SA_MC_COMPMASK_RATESELECTOR |
4695 		    SA_MC_COMPMASK_RATE;
4696 	}
4697 
4698 	/* Is Packet Life Time specified. */
4699 	if (mcg_arg->mcg_attr.mc_pkt_lt_req.p_pkt_lt) {
4700 		mcg_req.Rate = mcg_arg->mcg_attr.mc_pkt_lt_req.p_pkt_lt;
4701 		mcg_req.RateSelector =
4702 		    mcg_arg->mcg_attr.mc_pkt_lt_req.p_selector;
4703 
4704 		component_mask |= SA_MC_COMPMASK_PKTLTSELECTOR |
4705 		    SA_MC_COMPMASK_PKTLT;
4706 	}
4707 
4708 	if (mcg_arg->mcg_attr.mc_hop) {
4709 		mcg_req.HopLimit = mcg_arg->mcg_attr.mc_hop;
4710 		component_mask |= SA_MC_COMPMASK_HOPLIMIT;
4711 	}
4712 
4713 	if (mcg_arg->mcg_attr.mc_scope) {
4714 		mcg_req.Scope = mcg_arg->mcg_attr.mc_scope;
4715 		component_mask |= SA_MC_COMPMASK_SCOPE;
4716 	}
4717 
4718 	if (mcg_arg->mcg_attr.mc_mlid) {
4719 		mcg_req.MLID = mcg_arg->mcg_attr.mc_mlid;
4720 		component_mask |= SA_MC_COMPMASK_MLID;
4721 	}
4722 
4723 	/* Get SA Access Handle. */
4724 	hcap = ibcm_find_hca_entry(hca_port.hp_hca_guid);
4725 	if (hcap == NULL) {
4726 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: NO HCA found");
4727 
4728 		retval = IBT_HCA_BUSY_DETACHING;
4729 		goto ibcm_join_mcg_exit1;
4730 	}
4731 
4732 	saa_handle = ibcm_get_saa_handle(hcap, hca_port.hp_port);
4733 	if (saa_handle == NULL) {
4734 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: SA Handle NULL");
4735 
4736 		retval = IBT_HCA_PORT_NOT_ACTIVE;
4737 		goto ibcm_join_mcg_exit;
4738 	}
4739 
4740 	if ((mcg_arg->mcg_attr.mc_pgid.gid_prefix != 0) &&
4741 	    (mcg_arg->mcg_attr.mc_pgid.gid_guid != 0)) {
4742 		retval = ibtl_cm_get_hca_port(mcg_arg->mcg_attr.mc_pgid, 0,
4743 		    &hca_port);
4744 		if (retval != IBT_SUCCESS) {
4745 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: Failed "
4746 			    "to get PortInfo of specified PGID: status = %d",
4747 			    retval);
4748 			goto ibcm_join_mcg_exit1;
4749 		}
4750 	}
4751 
4752 	/* Contact SA Access */
4753 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
4754 	access_args.sq_access_type = IBMF_SAA_UPDATE;
4755 	access_args.sq_component_mask = component_mask;
4756 	access_args.sq_template = &mcg_req;
4757 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
4758 	access_args.sq_callback = NULL;
4759 	access_args.sq_callback_arg = NULL;
4760 
4761 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
4762 	    (void **)&mcg_resp);
4763 	if (retval != IBT_SUCCESS) {
4764 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_join_mcg: "
4765 		    "SA Access Failed");
4766 		goto ibcm_join_mcg_exit;
4767 	}
4768 
4769 	num_records = length/sizeof (sa_mcmember_record_t);
4770 
4771 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_join_mcg: "
4772 	    "Found %d MCMember Records", num_records);
4773 
4774 	/* Validate the returned number of records. */
4775 	if ((mcg_resp != NULL) && (num_records > 0)) {
4776 		/* Update the return values. */
4777 		mcg_info_p->mc_adds_vect.av_dgid = mcg_resp->MGID;
4778 		mcg_info_p->mc_adds_vect.av_sgid = mcg_resp->PortGID;
4779 		mcg_info_p->mc_adds_vect.av_srate = mcg_resp->Rate;
4780 		mcg_info_p->mc_adds_vect.av_srvl = mcg_resp->SL;
4781 		mcg_info_p->mc_adds_vect.av_flow = mcg_resp->FlowLabel;
4782 		mcg_info_p->mc_adds_vect.av_tclass = mcg_resp->TClass;
4783 		mcg_info_p->mc_adds_vect.av_hop = mcg_resp->HopLimit;
4784 		mcg_info_p->mc_adds_vect.av_send_grh = B_TRUE;
4785 		mcg_info_p->mc_adds_vect.av_dlid = mcg_resp->MLID;
4786 		mcg_info_p->mc_mtu = mcg_resp->MTU;
4787 		mcg_info_p->mc_qkey = mcg_resp->Q_Key;
4788 
4789 		retval = ibt_pkey2index_byguid(hca_port.hp_hca_guid,
4790 		    hca_port.hp_port, mcg_resp->P_Key, &mcg_info_p->mc_pkey_ix);
4791 		if (retval != IBT_SUCCESS) {
4792 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
4793 			    "Pkey2Index Conversion failed<%d>", retval);
4794 			mcg_info_p->mc_pkey_ix = 0;
4795 		}
4796 
4797 		mcg_info_p->mc_scope = mcg_resp->Scope;
4798 		mcg_info_p->mc_pkt_lt = mcg_resp->PacketLifeTime;
4799 
4800 		mcg_info_p->mc_adds_vect.av_port_num = hca_port.hp_port;
4801 		mcg_info_p->mc_adds_vect.av_sgid_ix = hca_port.hp_sgid_ix;
4802 		mcg_info_p->mc_adds_vect.av_src_path = 0;
4803 
4804 		/* Deallocate the memory allocated by SA for mcg_resp. */
4805 		kmem_free(mcg_resp, length);
4806 		retval = IBT_SUCCESS;
4807 	} else {
4808 		retval = IBT_MCG_RECORDS_NOT_FOUND;
4809 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_join_mcg: "
4810 		    "MCG RECORDS NOT FOUND");
4811 	}
4812 
4813 ibcm_join_mcg_exit:
4814 	ibcm_dec_hca_acc_cnt(hcap);
4815 
4816 ibcm_join_mcg_exit1:
4817 	if (mcg_arg->func)
4818 		(*(mcg_arg->func))(mcg_arg->arg, retval, mcg_info_p);
4819 
4820 	kmem_free(mcg_arg, sizeof (ibcm_join_mcg_tqarg_t));
4821 
4822 	return (retval);
4823 }
4824 
4825 
4826 /*
4827  * Function:
4828  *	ibt_leave_mcg
4829  * Input:
4830  *	rgid		The request GID that defines the HCA port upon which
4831  *			to send the request to the Subnet Administrator, to
4832  *			remove the specified port (port_gid) from the multicast
4833  *			group.  If 'port_gid' is the Reserved GID (i.e.
4834  *			port_gid.gid_prefix = 0 and port_gid.gid_guid = 0),
4835  *			then the end-port associated with 'rgid' is removed
4836  *			from the multicast group.
4837  *
4838  *	mc_gid		A multicast group GID as returned from ibt_join_mcg()
4839  *			call.  This is optional, if not specified (i.e.
4840  *			mc_gid.gid_prefix has 0xFF in its upper 8 bits to
4841  *			identify this as being a multicast GID), then the
4842  *			port is removed from all the multicast groups of
4843  *			which it is a member.
4844  *
4845  *	port_gid	This is optional, if not the Reserved GID (gid_prefix
4846  *			and gid_guid not equal to 0), then this specifies the
4847  *			endport GID of the multicast group member being deleted
4848  *			from the group. If it is the Reserved GID (gid_prefix
4849  *			and gid_guid equal to 0) then the member endport GID is
4850  *			determined from 'rgid'.
4851  *
4852  *	mc_join_state	The Join State attribute used when the group was joined
4853  *			using ibt_join_mcg(). This Join State component must
4854  *			contains at least one bit set to 1 in the same position
4855  *			as that used during ibt_join_mcg(). i.e. the logical
4856  *			AND of the two JoinState components is not all zeros.
4857  *			This Join State component must not have some bits set
4858  *			which are not set using ibt_join_mcg().
4859  * Output:
4860  *	None.
4861  * Returns:
4862  *	IBT_SUCCESS
4863  *	IBT_INVALID_PARAM
4864  *	IBT_MC_GROUP_INVALID
4865  *	IBT_INSUFF_RESOURCE
4866  * Description:
4867  *	The port associated with the port GID shall be removed from the
4868  *	multicast group specified by MGID (mc_gid) or from all the multicast
4869  *	groups of which it is a member if the MGID (mc_gid) is not specified.
4870  *
4871  *	The last full member to leave causes the destruction of the Multicast
4872  *	Group.
4873  */
4874 ibt_status_t
4875 ibt_leave_mcg(ib_gid_t rgid, ib_gid_t mc_gid, ib_gid_t port_gid,
4876     uint8_t mc_join_state)
4877 {
4878 	sa_mcmember_record_t	mcg_req;
4879 	ibmf_saa_access_args_t	access_args;
4880 	ibmf_saa_handle_t	saa_handle;
4881 	uint64_t		component_mask = 0;
4882 	int			sa_retval;
4883 	ibt_status_t		retval;
4884 	ibtl_cm_hca_port_t	hca_port;
4885 	size_t			length;
4886 	void			*results_p;
4887 	ibcm_hca_info_t		*hcap;
4888 
4889 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg(%llX:%llX, %llX:%llX)",
4890 	    rgid.gid_prefix, rgid.gid_guid, mc_gid.gid_prefix, mc_gid.gid_guid);
4891 
4892 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg(%llX:%llX, 0x%X)",
4893 	    port_gid.gid_prefix, port_gid.gid_guid, mc_join_state);
4894 
4895 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
4896 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: RequestGID is required");
4897 		return (IBT_INVALID_PARAM);
4898 	}
4899 
4900 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
4901 
4902 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: MGID: %llX%llX",
4903 	    mc_gid.gid_prefix, mc_gid.gid_guid);
4904 
4905 	/* Validate MGID */
4906 	if ((mc_gid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
4907 		mcg_req.MGID = mc_gid;
4908 		component_mask |= SA_MC_COMPMASK_MGID;
4909 	} else if ((mc_gid.gid_prefix != 0) || (mc_gid.gid_guid != 0)) {
4910 		IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Invalid MGID specified");
4911 		return (IBT_MC_MGID_INVALID);
4912 	}
4913 
4914 	if ((port_gid.gid_prefix == 0) || (port_gid.gid_guid == 0)) {
4915 		mcg_req.PortGID = rgid;
4916 	} else {
4917 		IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Performing PROXY Leave");
4918 		mcg_req.PortGID = port_gid;
4919 	}
4920 	component_mask |= SA_MC_COMPMASK_PORTGID;
4921 
4922 	IBTF_DPRINTF_L3(cmlog, "ibt_leave_mcg: Port GID <%llX:%llX>",
4923 	    mcg_req.PortGID.gid_prefix, mcg_req.PortGID.gid_guid);
4924 
4925 	/* Join State */
4926 	mcg_req.JoinState = mc_join_state;
4927 	component_mask |= SA_MC_COMPMASK_JOINSTATE;
4928 
4929 	retval = ibtl_cm_get_hca_port(rgid, 0, &hca_port);
4930 	if (retval != IBT_SUCCESS) {
4931 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: Failed to get port info "
4932 		    "from specified RGID : status = %d", retval);
4933 		return (retval);
4934 	}
4935 
4936 	/* Get SA Access Handle. */
4937 	hcap = ibcm_find_hca_entry(hca_port.hp_hca_guid);
4938 	if (hcap == NULL) {
4939 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: "
4940 		    "NO HCA found");
4941 		return (IBT_HCA_BUSY_DETACHING);
4942 	}
4943 
4944 	saa_handle = ibcm_get_saa_handle(hcap, hca_port.hp_port);
4945 	if (saa_handle == NULL) {
4946 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: saa_handle is NULL");
4947 		ibcm_dec_hca_acc_cnt(hcap);
4948 		return (IBT_HCA_PORT_NOT_ACTIVE);
4949 	}
4950 
4951 	/* Contact SA Access */
4952 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
4953 	access_args.sq_access_type = IBMF_SAA_DELETE;
4954 	access_args.sq_component_mask = component_mask;
4955 	access_args.sq_template = &mcg_req;
4956 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
4957 	access_args.sq_callback = NULL;
4958 	access_args.sq_callback_arg = NULL;
4959 
4960 	ibcm_sa_access_enter();
4961 
4962 	sa_retval = ibmf_sa_access(saa_handle, &access_args, 0, &length,
4963 	    &results_p);
4964 	if (sa_retval != IBMF_SUCCESS) {
4965 		IBTF_DPRINTF_L2(cmlog, "ibt_leave_mcg: SA access Failed: %d",
4966 		    sa_retval);
4967 		(void) ibcm_ibmf_analyze_error(sa_retval);
4968 		retval = IBT_MC_GROUP_INVALID;
4969 	}
4970 
4971 	ibcm_sa_access_exit();
4972 
4973 	ibcm_dec_hca_acc_cnt(hcap);
4974 
4975 	return (retval);
4976 }
4977 
4978 
4979 /*
4980  * Function:
4981  *	ibt_query_mcg
4982  * Input:
4983  *	rgid		The request GID that defines the HCA port upon which
4984  *			to send the request to the Subnet Administrator, to
4985  *			retrieve Multicast Records matching attributes as
4986  *			specified through 'mcg_attr' argument.
4987  *
4988  *	mcg_attr	NULL or a pointer to an ibt_mcg_attr_t structure that
4989  *			specifies MCG attributes that are to be matched.
4990  *			Attributes that are not required can be wild carded
4991  *			by specifying as '0'.
4992  *
4993  *	mcgs_max_num	The maximum number of matching multicast groups to
4994  *			return.  If zero, then all available matching multicast
4995  *			groups are returned.
4996  * Output:
4997  *	mcgs_info_p	The address of an ibt_mcg_info_t pointer, where
4998  *			multicast group information is returned. The actual
4999  *			number of entries filled in the array is returned in
5000  *			entries_p.
5001  *
5002  *	entries_p	The number of ibt_mcg_attr_t entries returned.
5003  * Returns:
5004  *	IBT_SUCCESS
5005  *	IBT_INVALID_PARAM
5006  *	IBT_MCG_RECORDS_NOT_FOUND
5007  * Description:
5008  *	Request information on multicast groups that match the parameters
5009  *	specified in mcg_attr. Information on each multicast group is returned
5010  *	to the caller in the form of an array of ibt_mcg_info_t.
5011  *	ibt_query_mcg() allocates the memory for this array and returns a
5012  *	pointer to the array (mcgs_p) and the number of entries in the array
5013  *	(entries_p). This memory should be freed by the client using
5014  *	ibt_free_mcg_info().
5015  */
5016 ibt_status_t
5017 ibt_query_mcg(ib_gid_t rgid, ibt_mcg_attr_t *mcg_attr, uint_t mcgs_max_num,
5018     ibt_mcg_info_t **mcgs_info_p, uint_t *entries_p)
5019 {
5020 	sa_mcmember_record_t	mcg_req;
5021 	sa_mcmember_record_t	*mcg_resp;
5022 	ibt_mcg_info_t		*mcg_infop;
5023 	ibmf_saa_access_args_t	access_args;
5024 	ibmf_saa_handle_t	saa_handle;
5025 	uint64_t		component_mask = 0;
5026 	ibt_status_t		retval;
5027 	ibtl_cm_hca_port_t	hport;
5028 	uint_t			num_records;
5029 	size_t			length;
5030 	void			*results_p;
5031 	ib_gid_t		port_gid;
5032 	ibcm_hca_info_t		*hcap;
5033 
5034 	IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg(%p, %d)", mcg_attr, mcgs_max_num);
5035 
5036 	if ((entries_p == NULL) || (mcgs_info_p == NULL)) {
5037 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: "
5038 		    "entries_p or mcgs_info_p is NULL");
5039 		return (IBT_INVALID_PARAM);
5040 	}
5041 
5042 	if ((rgid.gid_prefix == 0) || (rgid.gid_guid == 0)) {
5043 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: RequestGID is required");
5044 		return (IBT_INVALID_PARAM);
5045 	}
5046 	IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: Request GID <%llX:%llX>",
5047 	    rgid.gid_prefix, rgid.gid_guid);
5048 
5049 	bzero(&mcg_req, sizeof (sa_mcmember_record_t));
5050 	port_gid.gid_prefix = port_gid.gid_guid = 0;
5051 
5052 	if (mcg_attr != NULL) {
5053 		port_gid = mcg_attr->mc_pgid;
5054 
5055 		if ((port_gid.gid_prefix != 0) && (port_gid.gid_guid != 0)) {
5056 			mcg_req.PortGID = mcg_attr->mc_pgid;
5057 			component_mask |= SA_MC_COMPMASK_PORTGID;
5058 
5059 			IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: PGID %llX:%llX",
5060 			    port_gid.gid_prefix, port_gid.gid_guid);
5061 		}
5062 
5063 		/* Is Q_Key specified. */
5064 		if (mcg_attr->mc_qkey != 0) {
5065 			mcg_req.Q_Key = mcg_attr->mc_qkey;
5066 			component_mask |= SA_MC_COMPMASK_QKEY;
5067 		}
5068 
5069 		/* Is P_Key specified. */
5070 		if (mcg_attr->mc_pkey != 0) {
5071 			mcg_req.P_Key = mcg_attr->mc_pkey;
5072 			component_mask |= SA_MC_COMPMASK_PKEY;
5073 		}
5074 
5075 		/* Is MGID specified. */
5076 		if ((mcg_attr->mc_mgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
5077 			mcg_req.MGID = mcg_attr->mc_mgid;
5078 			component_mask |= SA_MC_COMPMASK_MGID;
5079 		}
5080 
5081 		/* Is MTU specified. */
5082 		if (mcg_attr->mc_mtu_req.r_mtu) {
5083 			mcg_req.MTU = mcg_attr->mc_mtu_req.r_mtu;
5084 			mcg_req.MTUSelector = mcg_attr->mc_mtu_req.r_selector;
5085 
5086 			component_mask |= SA_MC_COMPMASK_MTUSELECTOR |
5087 			    SA_MC_COMPMASK_MTU;
5088 		}
5089 
5090 		if (mcg_attr->mc_tclass) {
5091 			mcg_req.TClass = mcg_attr->mc_tclass;
5092 			component_mask |= SA_MC_COMPMASK_TCLASS;
5093 		}
5094 
5095 		/* Is RATE specified. */
5096 		if (mcg_attr->mc_rate_req.r_srate) {
5097 			mcg_req.Rate = mcg_attr->mc_rate_req.r_srate;
5098 			mcg_req.RateSelector = mcg_attr->mc_rate_req.r_selector;
5099 
5100 			component_mask |= SA_MC_COMPMASK_RATESELECTOR |
5101 			    SA_MC_COMPMASK_RATE;
5102 		}
5103 
5104 		/* Is Packet Life Time specified. */
5105 		if (mcg_attr->mc_pkt_lt_req.p_pkt_lt) {
5106 			mcg_req.Rate = mcg_attr->mc_pkt_lt_req.p_pkt_lt;
5107 			mcg_req.RateSelector =
5108 			    mcg_attr->mc_pkt_lt_req.p_selector;
5109 
5110 			component_mask |= SA_MC_COMPMASK_PKTLTSELECTOR |
5111 			    SA_MC_COMPMASK_PKTLT;
5112 		}
5113 
5114 		if (mcg_attr->mc_hop) {
5115 			mcg_req.HopLimit = mcg_attr->mc_hop;
5116 			component_mask |= SA_MC_COMPMASK_HOPLIMIT;
5117 		}
5118 
5119 		if (mcg_attr->mc_flow) {
5120 			mcg_req.FlowLabel = mcg_attr->mc_flow;
5121 			component_mask |= SA_MC_COMPMASK_FLOWLABEL;
5122 		}
5123 
5124 		if (mcg_attr->mc_sl) {
5125 			mcg_req.SL = mcg_attr->mc_sl;
5126 			component_mask |= SA_MC_COMPMASK_SL;
5127 		}
5128 
5129 		if (mcg_attr->mc_scope) {
5130 			mcg_req.Scope = mcg_attr->mc_scope;
5131 			component_mask |= SA_MC_COMPMASK_SCOPE;
5132 		}
5133 
5134 		if (mcg_attr->mc_join_state) {
5135 			mcg_req.JoinState = mcg_attr->mc_join_state;
5136 			component_mask |= SA_MC_COMPMASK_JOINSTATE;
5137 		}
5138 
5139 		if (mcg_attr->mc_mlid) {
5140 			mcg_req.MLID = mcg_attr->mc_mlid;
5141 			component_mask |= SA_MC_COMPMASK_MLID;
5142 		}
5143 	}
5144 
5145 	retval = ibtl_cm_get_hca_port(rgid, 0, &hport);
5146 	if (retval != IBT_SUCCESS) {
5147 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: Failed to get port info "
5148 		    "from specified RGID : status = %d", retval);
5149 		return (retval);
5150 	}
5151 
5152 	/* Get SA Access Handle. */
5153 	hcap = ibcm_find_hca_entry(hport.hp_hca_guid);
5154 	if (hcap == NULL) {
5155 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: NO HCA found");
5156 		return (IBT_HCA_BUSY_DETACHING);
5157 	}
5158 
5159 	saa_handle = ibcm_get_saa_handle(hcap, hport.hp_port);
5160 	if (saa_handle == NULL) {
5161 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: saa_handle is NULL");
5162 		ibcm_dec_hca_acc_cnt(hcap);
5163 		return (IBT_HCA_PORT_NOT_ACTIVE);
5164 	}
5165 
5166 	/* Contact SA Access */
5167 	access_args.sq_attr_id = SA_MCMEMBERRECORD_ATTRID;
5168 	access_args.sq_access_type = IBMF_SAA_RETRIEVE;
5169 	access_args.sq_component_mask = component_mask;
5170 	access_args.sq_template = &mcg_req;
5171 	access_args.sq_template_length = sizeof (sa_mcmember_record_t);
5172 	access_args.sq_callback = NULL;
5173 	access_args.sq_callback_arg = NULL;
5174 
5175 	retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
5176 	    &results_p);
5177 	if (retval != IBT_SUCCESS) {
5178 		IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: SA access Failed");
5179 		ibcm_dec_hca_acc_cnt(hcap);
5180 		return (retval);
5181 	}
5182 
5183 	num_records = length/sizeof (sa_mcmember_record_t);
5184 
5185 	IBTF_DPRINTF_L4(cmlog, "ibt_query_mcg: Found %d MCMember Records",
5186 	    num_records);
5187 
5188 	/* Validate the returned number of records. */
5189 	if ((results_p != NULL) && (num_records > 0)) {
5190 		uint_t	i;
5191 
5192 		/*
5193 		 * If mcgs_max_num is zero, then return all records else
5194 		 * return only requested number of records
5195 		 */
5196 		if ((mcgs_max_num != 0) && (num_records > mcgs_max_num)) {
5197 			/* we are interested in only mcgs_max_num records */
5198 			num_records = mcgs_max_num;
5199 		}
5200 
5201 		/*
5202 		 * The SGID returned in "mcg_info_p" buffer should be PortGID,
5203 		 * (mcg_attr->mc_pgid), if 'mcg_attr->mc_pgid' was specified,
5204 		 * else RequestGID (rgid) should be returned.
5205 		 */
5206 		if ((port_gid.gid_prefix != 0) && (port_gid.gid_guid != 0)) {
5207 
5208 			/* Get sgid_ix and port number of 'port_gid' */
5209 			retval = ibtl_cm_get_hca_port(port_gid, 0, &hport);
5210 			if (retval != IBT_SUCCESS) {
5211 				IBTF_DPRINTF_L2(cmlog, "ibt_query_mcg: "
5212 				    "Failed to Get Portinfo for PortGID :"
5213 				    "status = %d", retval);
5214 				return (retval);
5215 			}
5216 		} else {
5217 			/*
5218 			 * The sgid_ix and port number related to RequestGID
5219 			 * are already obtained at the beginning.
5220 			 */
5221 			port_gid = rgid;
5222 		}
5223 
5224 		/*
5225 		 * Allocate memory for return buffer, to be freed in
5226 		 * ibt_free_mcg_info().
5227 		 */
5228 		mcg_infop = kmem_alloc((num_records * sizeof (ibt_mcg_info_t)),
5229 		    KM_SLEEP);
5230 
5231 		*mcgs_info_p = mcg_infop;
5232 		*entries_p = num_records;
5233 
5234 		/* Update the return values. */
5235 		for (i = 0; i < num_records; i++) {
5236 
5237 			mcg_resp = (sa_mcmember_record_t *)((uchar_t *)
5238 			    results_p + i * sizeof (sa_mcmember_record_t));
5239 
5240 			mcg_infop[i].mc_adds_vect.av_dgid = mcg_resp->MGID;
5241 			mcg_infop[i].mc_adds_vect.av_sgid = port_gid;
5242 			mcg_infop[i].mc_adds_vect.av_srate = mcg_resp->Rate;
5243 			mcg_infop[i].mc_adds_vect.av_srvl = mcg_resp->SL;
5244 			mcg_infop[i].mc_adds_vect.av_flow = mcg_resp->FlowLabel;
5245 			mcg_infop[i].mc_adds_vect.av_tclass = mcg_resp->TClass;
5246 			mcg_infop[i].mc_adds_vect.av_hop = mcg_resp->HopLimit;
5247 			mcg_infop[i].mc_adds_vect.av_port_num = hport.hp_port;
5248 			mcg_infop[i].mc_adds_vect.av_send_grh = B_TRUE;
5249 			mcg_infop[i].mc_adds_vect.av_dlid = mcg_resp->MLID;
5250 			mcg_infop[i].mc_adds_vect.av_sgid_ix = hport.hp_sgid_ix;
5251 			mcg_infop[i].mc_adds_vect.av_src_path = 0;
5252 			mcg_infop[i].mc_mtu = mcg_resp->MTU;
5253 			mcg_infop[i].mc_qkey = mcg_resp->Q_Key;
5254 			mcg_infop[i].mc_scope = mcg_resp->Scope;
5255 			mcg_infop[i].mc_pkt_lt = mcg_resp->PacketLifeTime;
5256 
5257 			if (ibt_pkey2index_byguid(hport.hp_hca_guid,
5258 			    hport.hp_port, mcg_resp->P_Key,
5259 			    &mcg_infop[i].mc_pkey_ix) != IBT_SUCCESS) {
5260 				IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: "
5261 				    "Pkey2Index Conversion failed");
5262 				mcg_infop[i].mc_pkey_ix = 0;
5263 			}
5264 		}
5265 
5266 		/*
5267 		 * Deallocate the memory allocated by SA for results_p.
5268 		 */
5269 		kmem_free(results_p, length);
5270 		retval = IBT_SUCCESS;
5271 
5272 		IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: returning %d MCGRecords",
5273 		    num_records);
5274 
5275 	} else {
5276 		retval = IBT_MCG_RECORDS_NOT_FOUND;
5277 		*entries_p = 0;
5278 
5279 		IBTF_DPRINTF_L3(cmlog, "ibt_query_mcg: MCG RECORDS NOT FOUND");
5280 	}
5281 
5282 	ibcm_dec_hca_acc_cnt(hcap);
5283 
5284 	return (retval);
5285 }
5286 
5287 
5288 /*
5289  * ibt_free_mcg_info()
5290  *	Free the memory allocated by successful ibt_query_mcg()
5291  *
5292  *	mcgs_info	Pointer returned by ibt_query_mcg().
5293  *
5294  *	entries		The number of ibt_mcg_info_t entries to free.
5295  */
5296 void
5297 ibt_free_mcg_info(ibt_mcg_info_t *mcgs_info, uint_t entries)
5298 {
5299 	IBTF_DPRINTF_L3(cmlog, "ibt_free_mcg_info: "
5300 	    "Free <%d> entries from 0x%p", entries, mcgs_info);
5301 
5302 	if ((mcgs_info != NULL) && (entries > 0))
5303 		kmem_free(mcgs_info, entries * sizeof (ibt_mcg_info_t));
5304 	else
5305 		IBTF_DPRINTF_L2(cmlog, "ibt_free_mcg_info: "
5306 		    "ERROR: NULL buf pointer or length specified.");
5307 }
5308 
5309 
5310 /*
5311  * Function:
5312  *	ibt_gid_to_node_info()
5313  * Input:
5314  *	gid		Identifies the IB Node and port for which to obtain
5315  *			Node information.
5316  * Output:
5317  *	node_info_p	A pointer to an ibt_node_info_t structure (allocated
5318  *			by the caller) in which to return the node information.
5319  * Returns:
5320  *	IBT_SUCCESS
5321  *	IBT_INVALID_PARAM
5322  *	IBT_NODE_RECORDS_NOT_FOUND
5323  *	IBT_NO_HCAS_AVAILABLE
5324  * Description:
5325  *	Retrieve Node Information for the specified GID.
5326  */
5327 ibt_status_t
5328 ibt_gid_to_node_info(ib_gid_t gid, ibt_node_info_t *node_info_p)
5329 {
5330 	sa_node_record_t	nr_req, *nr_resp;
5331 	ibmf_saa_handle_t	saa_handle;
5332 	ibt_status_t		retval;
5333 	ibcm_hca_info_t		*hcap;
5334 	ibtl_cm_hca_port_t	hport;
5335 	int			i, j;
5336 	uint_t			num_rec;
5337 	ib_guid_t		*guid_array = NULL;
5338 	sa_path_record_t	*path;
5339 	size_t			len;
5340 	uint8_t			npaths;
5341 	uint32_t		num_hcas = 0;
5342 	ib_lid_t		node_lid;
5343 	boolean_t		local_node = B_FALSE;
5344 	void			*res_p;
5345 	uint8_t			num_ports = 0;
5346 
5347 
5348 	IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info(%llX:%llX, %p)",
5349 	    gid.gid_prefix, gid.gid_guid, node_info_p);
5350 
5351 	if ((gid.gid_prefix == 0) || (gid.gid_guid == 0)) {
5352 		IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: GID is required");
5353 		return (IBT_INVALID_PARAM);
5354 	}
5355 
5356 	if (node_info_p == NULL) {
5357 		IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
5358 		    "Return Buf (node_info_p) is NULL.");
5359 		return (IBT_INVALID_PARAM);
5360 	}
5361 
5362 	/*
5363 	 * If 'gid' is on local node, then get node lid (i.e. base lid of the
5364 	 * associated port) info via ibtl_cm_get_hca_port() call.
5365 	 */
5366 	bzero(&hport, sizeof (ibtl_cm_hca_port_t));
5367 	if (ibtl_cm_get_hca_port(gid, 0, &hport) == IBT_SUCCESS) {
5368 
5369 		hcap = ibcm_find_hca_entry(hport.hp_hca_guid);
5370 		if (hcap == NULL) {
5371 			IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
5372 			    "HCA(%llX) info not found", hport.hp_hca_guid);
5373 			return (IBT_NO_HCAS_AVAILABLE);
5374 		}
5375 		num_ports = 1;
5376 		num_hcas = 1;
5377 		node_lid = hport.hp_base_lid;
5378 		local_node = B_TRUE;
5379 		IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info: Local Node: "
5380 		    "LID = 0x%X", node_lid);
5381 	} else {
5382 		/* Get the number of HCAs and their GUIDs */
5383 		num_hcas = ibt_get_hca_list(&guid_array);
5384 		IBTF_DPRINTF_L4(cmlog, "ibt_gid_to_node_info: ibt_get_hca_list "
5385 		    "returned %d hcas", num_hcas);
5386 
5387 		if (num_hcas == 0) {
5388 			IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
5389 			    "NO HCA's Found on this system");
5390 			return (IBT_NO_HCAS_AVAILABLE);
5391 		}
5392 	}
5393 
5394 	for (i = 0; i < num_hcas; i++) {
5395 		if (local_node == B_FALSE) {
5396 			hcap = ibcm_find_hca_entry(guid_array[i]);
5397 			if (hcap == NULL) {
5398 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
5399 				    "HCA(%llX) info not found", guid_array[i]);
5400 				retval = IBT_NO_HCAS_AVAILABLE;
5401 				continue;
5402 			}
5403 			num_ports = hcap->hca_num_ports;
5404 		}
5405 
5406 		for (j = 0; j < num_ports; j++) {
5407 			uint8_t		port = 0;
5408 
5409 			if (local_node == B_TRUE)
5410 				port = hport.hp_port;
5411 			else
5412 				port = j + 1;
5413 
5414 			/* Get SA Access Handle. */
5415 			saa_handle = ibcm_get_saa_handle(hcap, port);
5416 			if (saa_handle == NULL) {
5417 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
5418 				    "Port %d of HCA (%llX) is NOT ACTIVE",
5419 				    port, hport.hp_hca_guid);
5420 				retval = IBT_NODE_RECORDS_NOT_FOUND;
5421 				continue;
5422 			}
5423 
5424 			if (local_node == B_FALSE) {
5425 				ib_gid_t	sgid;
5426 				int		sa_ret;
5427 
5428 				/*
5429 				 * Check whether 'gid' and this port has same
5430 				 * subnet prefix. If not, then there is no use
5431 				 * in searching from this port.
5432 				 */
5433 				sgid = hcap->hca_port_info[j].port_sgid0;
5434 				if (gid.gid_prefix != sgid.gid_prefix) {
5435 					IBTF_DPRINTF_L3(cmlog,
5436 					    "ibt_gid_to_node_info:Sn_Prefix of "
5437 					    "GID(%llX) and Port's(%llX) differ",
5438 					    gid.gid_prefix, sgid.gid_prefix);
5439 					retval = IBT_NODE_RECORDS_NOT_FOUND;
5440 					continue;
5441 				}
5442 
5443 				/*
5444 				 * First Get Path Records for the specified DGID
5445 				 * from this port (SGID). From Path Records,
5446 				 * note down DLID, then use this DLID as Input
5447 				 * attribute to get NodeRecords from SA Access.
5448 				 */
5449 				npaths = 1;
5450 				path = NULL;
5451 
5452 				sa_ret = ibmf_saa_gid_to_pathrecords(saa_handle,
5453 				    sgid, gid, 0, 0, B_TRUE, &npaths, 0, &len,
5454 				    &path);
5455 				if (sa_ret != IBMF_SUCCESS) {
5456 					IBTF_DPRINTF_L2(cmlog,
5457 					    "ibt_gid_to_node_info: "
5458 					    "ibmf_saa_gid_to_pathrecords() "
5459 					    "returned error: %d ", sa_ret);
5460 					retval =
5461 					    ibcm_ibmf_analyze_error(sa_ret);
5462 					continue;
5463 				} else if ((npaths == 0) || (path == NULL)) {
5464 					IBTF_DPRINTF_L3(cmlog,
5465 					    "ibt_gid_to_node_info: failed (%d) "
5466 					    "to get path records for the DGID "
5467 					    "0x%llX from SGID 0x%llX", sa_ret,
5468 					    gid.gid_guid, sgid.gid_guid);
5469 					retval = IBT_NODE_RECORDS_NOT_FOUND;
5470 					continue;
5471 				}
5472 				node_lid = path->DLID;	/* LID */
5473 
5474 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
5475 				    "Remote Node: LID = 0x%X", node_lid);
5476 
5477 				/* Free SA_Access memory for path record. */
5478 				kmem_free(path, len);
5479 			}
5480 
5481 			/* Retrieve Node Records from SA Access. */
5482 			bzero(&nr_req, sizeof (sa_node_record_t));
5483 
5484 			nr_req.LID = node_lid;	/* LID */
5485 
5486 			retval = ibcm_get_node_rec(saa_handle, &nr_req,
5487 			    SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
5488 			if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
5489 				IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
5490 				    "failed (%d) to get Node records", retval);
5491 				continue;
5492 			} else if (retval != IBT_SUCCESS) {
5493 				IBTF_DPRINTF_L2(cmlog, "ibt_gid_to_node_info: "
5494 				    "failed (%d) to get Node records", retval);
5495 				ibcm_dec_hca_acc_cnt(hcap);
5496 				goto gid_to_ni_exit;
5497 			}
5498 
5499 			num_rec = len/sizeof (sa_node_record_t);
5500 			nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
5501 
5502 			/* Validate the returned number of records. */
5503 			if ((nr_resp != NULL) && (num_rec > 0)) {
5504 
5505 				IBCM_DUMP_NODE_REC(nr_resp);
5506 
5507 				_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
5508 				    *node_info_p))
5509 
5510 				node_info_p->n_sys_img_guid =
5511 				    nr_resp->NodeInfo.SystemImageGUID;
5512 				node_info_p->n_node_guid =
5513 				    nr_resp->NodeInfo.NodeGUID;
5514 				node_info_p->n_port_guid =
5515 				    nr_resp->NodeInfo.PortGUID;
5516 				node_info_p->n_dev_id =
5517 				    nr_resp->NodeInfo.DeviceID;
5518 				node_info_p->n_revision =
5519 				    nr_resp->NodeInfo.Revision;
5520 				node_info_p->n_vendor_id =
5521 				    nr_resp->NodeInfo.VendorID;
5522 				node_info_p->n_num_ports =
5523 				    nr_resp->NodeInfo.NumPorts;
5524 				node_info_p->n_port_num =
5525 				    nr_resp->NodeInfo.LocalPortNum;
5526 				node_info_p->n_node_type =
5527 				    nr_resp->NodeInfo.NodeType;
5528 				(void) strncpy(node_info_p->n_description,
5529 				    (char *)&nr_resp->NodeDescription, 64);
5530 
5531 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
5532 				    *node_info_p))
5533 
5534 				/*
5535 				 * Deallocate the memory allocated by SA for
5536 				 * 'nr_resp'.
5537 				 */
5538 				ibcm_dec_hca_acc_cnt(hcap);
5539 				kmem_free(nr_resp, len);
5540 				retval = IBT_SUCCESS;
5541 
5542 				goto gid_to_ni_exit;
5543 			} else {
5544 				retval = IBT_NODE_RECORDS_NOT_FOUND;
5545 				IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: "
5546 				    "Node Records NOT found - PortGUID %016llX",
5547 				    gid.gid_guid);
5548 			}
5549 		}
5550 		ibcm_dec_hca_acc_cnt(hcap);
5551 
5552 		if (local_node == B_TRUE)
5553 			break;
5554 	}
5555 
5556 gid_to_ni_exit:
5557 	if (guid_array)
5558 		ibt_free_hca_list(guid_array, num_hcas);
5559 
5560 	IBTF_DPRINTF_L3(cmlog, "ibt_gid_to_node_info: done. Status %d", retval);
5561 
5562 	return (retval);
5563 }
5564 
5565 
5566 static ibt_status_t
5567 ibcm_get_node_rec(ibmf_saa_handle_t saa_handle, sa_node_record_t *nr_req,
5568     uint64_t component_mask, void *result_p, size_t *len)
5569 {
5570 	ibmf_saa_access_args_t  args;
5571 	size_t			length;
5572 	ibt_status_t		retval;
5573 
5574 	args.sq_attr_id = SA_NODERECORD_ATTRID;
5575 	args.sq_template = nr_req;
5576 	args.sq_access_type = IBMF_SAA_RETRIEVE;
5577 	args.sq_template_length = sizeof (sa_node_record_t);
5578 	args.sq_component_mask = component_mask;
5579 	args.sq_callback = NULL;
5580 	args.sq_callback_arg = NULL;
5581 
5582 	retval = ibcm_contact_sa_access(saa_handle, &args, &length, result_p);
5583 	if (retval != IBT_SUCCESS) {
5584 		IBTF_DPRINTF_L2(cmlog, "ibcm_get_node_rec: SA Call Failed");
5585 		return (retval);
5586 	}
5587 
5588 	*len = length;
5589 
5590 	/* Validate the returned number of records. */
5591 	if ((result_p != NULL) && (length > 0)) {
5592 		IBTF_DPRINTF_L3(cmlog, "ibcm_get_node_rec: Node Records FOUND");
5593 
5594 		/* Got it, done!. */
5595 		return (IBT_SUCCESS);
5596 	} else {
5597 		IBTF_DPRINTF_L2(cmlog, "ibcm_get_node_rec: Node Rec NOT found");
5598 		return (IBT_NODE_RECORDS_NOT_FOUND);
5599 	}
5600 }
5601 
5602 
5603 /*
5604  * Function:
5605  *	ibt_get_companion_port_gids()
5606  * Description:
5607  *	Get list of GID's available on a companion port(s) of the specified
5608  *	GID or list of GIDs available on a specified Node GUID/SystemImage GUID.
5609  */
5610 ibt_status_t
5611 ibt_get_companion_port_gids(ib_gid_t gid, ib_guid_t hca_guid,
5612     ib_guid_t sysimg_guid, ib_gid_t **gids_p, uint_t *num_gids_p)
5613 {
5614 	sa_node_record_t	nr_req, *nr_resp;
5615 	void			*res_p;
5616 	ibmf_saa_handle_t	saa_handle;
5617 	int			sa_ret;
5618 	ibt_status_t		retval = IBT_SUCCESS;
5619 	ibcm_hca_info_t		*hcap;
5620 	ibtl_cm_hca_port_t	hport;
5621 	int			i, j;
5622 	uint_t			num_rec;
5623 	ib_guid_t		*guid_array = NULL;
5624 	sa_path_record_t	*path;
5625 	size_t			len;
5626 	uint8_t			npaths;
5627 	uint32_t		num_hcas = 0;
5628 	boolean_t		local_node = B_FALSE;
5629 	boolean_t		local_hca = B_FALSE;
5630 	ib_guid_t		h_guid = hca_guid;
5631 	ib_gid_t		*gidp = NULL, *t_gidp = NULL;
5632 	int			multi_hca_loop = 0;
5633 
5634 	IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids(%llX:%llX, %llX, "
5635 	    "%llX)", gid.gid_prefix, gid.gid_guid, hca_guid, sysimg_guid);
5636 
5637 	if (((gid.gid_prefix == 0) || (gid.gid_guid == 0)) && (hca_guid == 0) &&
5638 	    (sysimg_guid == 0)) {
5639 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
5640 		    "Null Input attribute specified.");
5641 		return (IBT_INVALID_PARAM);
5642 	}
5643 
5644 	if ((num_gids_p == NULL) || (gids_p == NULL)) {
5645 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
5646 		    "num_gids_p or gids_p is NULL");
5647 		return (IBT_INVALID_PARAM);
5648 	}
5649 
5650 	*num_gids_p = 0;
5651 
5652 	/* Get the number of HCAs and their GUIDs */
5653 	if ((num_hcas = ibt_get_hca_list(&guid_array)) == 0) {
5654 		IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
5655 		    "NO HCA's Found on this system");
5656 		return (IBT_NO_HCAS_AVAILABLE);
5657 	}
5658 
5659 	IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids: "
5660 	    "ibt_get_hca_list() returned %d hcas", num_hcas);
5661 
5662 	/*
5663 	 * If 'gid' is on local node, then get node lid (i.e. base lid of the
5664 	 * associated port) info via ibtl_cm_get_hca_port() call.
5665 	 */
5666 	bzero(&hport, sizeof (ibtl_cm_hca_port_t));
5667 	if ((gid.gid_prefix != 0) && (gid.gid_guid != 0) &&
5668 	    (ibtl_cm_get_hca_port(gid, 0, &hport) == IBT_SUCCESS)) {
5669 
5670 		if ((hca_guid != 0) && (hca_guid != hport.hp_hca_guid)) {
5671 			IBTF_DPRINTF_L2(cmlog, "ibt_get_companion_port_gids: "
5672 			    "Invalid GID<->HCAGUID combination specified.");
5673 			retval = IBT_INVALID_PARAM;
5674 			goto get_comp_pgid_exit;
5675 		}
5676 		h_guid = hport.hp_hca_guid;
5677 		local_node = B_TRUE;
5678 
5679 		IBTF_DPRINTF_L4(cmlog, "ibt_get_companion_port_gids: "
5680 		    "Local Node: HCA (0x%llX)", h_guid);
5681 	} else if (h_guid) {	/* Is specified HCA GUID - local? */
5682 		for (i = 0; i < num_hcas; i++) {
5683 			if (h_guid == guid_array[i]) {
5684 				local_hca = B_TRUE;
5685 				break;
5686 			}
5687 		}
5688 	} else if (sysimg_guid) { /* Is specified SystemImage GUID - local? */
5689 		for (i = 0; i < num_hcas; i++) {
5690 			ibt_status_t	ret;
5691 			ibt_hca_attr_t	hca_attr;
5692 
5693 			ret = ibt_query_hca_byguid(guid_array[i], &hca_attr);
5694 			if (ret != IBT_SUCCESS) {
5695 				IBTF_DPRINTF_L2(cmlog,
5696 				    "ibt_get_companion_port_gids: HCA(%llX) "
5697 				    "info not found", guid_array[i]);
5698 				retval = IBT_NO_HCAS_AVAILABLE;
5699 				continue;
5700 			}
5701 			if (hca_attr.hca_si_guid == sysimg_guid) {
5702 				if ((hca_guid != 0) &&
5703 				    (hca_guid != hca_attr.hca_node_guid)) {
5704 					IBTF_DPRINTF_L2(cmlog,
5705 					    "ibt_get_companion_port_gids: "
5706 					    "Invalid SysImg<->HCA GUID "
5707 					    "combination specified.");
5708 					retval = IBT_INVALID_PARAM;
5709 					goto get_comp_pgid_exit;
5710 				}
5711 				local_hca = B_TRUE;
5712 				h_guid = hca_attr.hca_node_guid;
5713 				break;
5714 			}
5715 		}
5716 	}
5717 
5718 	if ((local_node == B_TRUE) || (local_hca == B_TRUE)) {
5719 		retval = ibtl_cm_get_local_comp_gids(h_guid, gid, gids_p,
5720 		    num_gids_p);
5721 		goto get_comp_pgid_exit;
5722 	}
5723 
5724 get_comp_for_multihca:
5725 	/* We will be here, if request is for remote node */
5726 	for (i = 0; i < num_hcas; i++) {
5727 		int		multism;
5728 		uint8_t		count = 0;
5729 		int		multi_sm_loop = 0;
5730 		uint_t		k = 0, l;
5731 
5732 		hcap = ibcm_find_hca_entry(guid_array[i]);
5733 		if (hcap == NULL) {
5734 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
5735 			    "HCA(%llX) info not found", guid_array[i]);
5736 			retval = IBT_NO_HCAS_AVAILABLE;
5737 			continue;
5738 		}
5739 
5740 		/* 1 - MultiSM, 0 - Single SM */
5741 		multism = ibtl_cm_is_multi_sm(guid_array[i]);
5742 
5743 		for (j = 0; j < hcap->hca_num_ports; j++) {
5744 			ib_gid_t	sgid;
5745 			uint64_t	c_mask = 0;
5746 			ib_guid_t	pg;
5747 			uint_t		port = j;
5748 
5749 get_comp_for_multism:
5750 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
5751 			    "Port %d, HCA %llX, MultiSM= %d, Loop=%d",
5752 			    port + 1, h_guid, multism, multi_sm_loop);
5753 
5754 			/* Get SA Access Handle. */
5755 			saa_handle = ibcm_get_saa_handle(hcap, port + 1);
5756 			if (saa_handle == NULL) {
5757 				IBTF_DPRINTF_L2(cmlog,
5758 				    "ibt_get_companion_port_gids: "
5759 				    "Port (%d)  - NOT ACTIVE", port + 1);
5760 				retval = IBT_GIDS_NOT_FOUND;
5761 				continue;
5762 			}
5763 
5764 			/*
5765 			 * Check whether 'gid' and this port has same subnet
5766 			 * prefix. If not, then there is no use in searching
5767 			 * from this port.
5768 			 */
5769 			sgid = hcap->hca_port_info[port].port_sgid0;
5770 			if ((h_guid == 0) && (gid.gid_prefix != 0) &&
5771 			    (multi_sm_loop == 0) &&
5772 			    (gid.gid_prefix != sgid.gid_prefix)) {
5773 				IBTF_DPRINTF_L2(cmlog,
5774 				    "ibt_get_companion_port_gids: SnPrefix of "
5775 				    "GID(%llX) and Port SN_Pfx(%llX) differ",
5776 				    gid.gid_prefix, sgid.gid_prefix);
5777 				retval = IBT_GIDS_NOT_FOUND;
5778 				continue;
5779 			}
5780 
5781 			/*
5782 			 * If HCA GUID or System Image GUID is specified, then
5783 			 * we can achieve our goal sooner!.
5784 			 */
5785 			if ((h_guid == 0) && (sysimg_guid == 0)) {
5786 				/* So only GID info is provided. */
5787 
5788 				/*
5789 				 * First Get Path Records for the specified DGID
5790 				 * from this port (SGID). From Path Records,
5791 				 * note down DLID, then use this DLID as Input
5792 				 * attribute to get NodeRecords.
5793 				 */
5794 				npaths = 1;
5795 				path = NULL;
5796 
5797 				sa_ret = ibmf_saa_gid_to_pathrecords(saa_handle,
5798 				    sgid, gid, 0, 0, B_TRUE, &npaths, 0, &len,
5799 				    &path);
5800 				if (sa_ret != IBMF_SUCCESS) {
5801 					IBTF_DPRINTF_L2(cmlog,
5802 					    "ibt_get_companion_port_gids: "
5803 					    "ibmf_saa_gid_to_pathrecords() "
5804 					    "returned error: %d ", sa_ret);
5805 					retval =
5806 					    ibcm_ibmf_analyze_error(sa_ret);
5807 					ibcm_dec_hca_acc_cnt(hcap);
5808 					goto get_comp_pgid_exit;
5809 				} else if ((npaths == 0) || (path == NULL)) {
5810 					IBTF_DPRINTF_L2(cmlog,
5811 					    "ibt_get_companion_port_gids: "
5812 					    "failed (%d) to get path records "
5813 					    "for the DGID (0x%llX) from SGID "
5814 					    "(0x%llX)", sa_ret, gid.gid_guid,
5815 					    sgid.gid_guid);
5816 					retval = IBT_GIDS_NOT_FOUND;
5817 					continue;
5818 				}
5819 
5820 				bzero(&nr_req, sizeof (sa_node_record_t));
5821 				nr_req.LID = path->DLID;	/* LID */
5822 
5823 				IBTF_DPRINTF_L3(cmlog,
5824 				    "ibt_get_companion_port_gids: "
5825 				    "Remote Node: LID = 0x%X", nr_req.LID);
5826 
5827 				/* Free SA_Access memory for path record. */
5828 				kmem_free(path, len);
5829 
5830 				IBTF_DPRINTF_L3(cmlog,
5831 				    "ibt_get_companion_port_gids: SAA Call: "
5832 				    "based on LID ");
5833 
5834 				retval = ibcm_get_node_rec(saa_handle, &nr_req,
5835 				    SA_NODEINFO_COMPMASK_NODELID, &res_p, &len);
5836 				if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
5837 					IBTF_DPRINTF_L2(cmlog,
5838 					    "ibt_get_companion_port_gids: "
5839 					    "failed (%d) to get Node records",
5840 					    retval);
5841 					continue;
5842 				} else if (retval != IBT_SUCCESS) {
5843 					IBTF_DPRINTF_L2(cmlog,
5844 					    "ibt_get_companion_port_gids: "
5845 					    "failed (%d) to get Node records",
5846 					    retval);
5847 					ibcm_dec_hca_acc_cnt(hcap);
5848 					goto get_comp_pgid_exit;
5849 				}
5850 
5851 				nr_resp = (sa_node_record_t *)(uchar_t *)res_p;
5852 				/* Note down HCA GUID info. */
5853 				h_guid = nr_resp->NodeInfo.NodeGUID;
5854 
5855 				IBTF_DPRINTF_L3(cmlog,
5856 				    "ibt_get_companion_port_gids: "
5857 				    "Remote HCA GUID: 0x%llX", h_guid);
5858 
5859 				IBCM_DUMP_NODE_REC(nr_resp);
5860 
5861 				kmem_free(res_p, len);
5862 			}
5863 
5864 			bzero(&nr_req, sizeof (sa_node_record_t));
5865 			if (h_guid != 0) {
5866 				nr_req.NodeInfo.NodeGUID = h_guid;
5867 				c_mask = SA_NODEINFO_COMPMASK_NODEGUID;
5868 			}
5869 
5870 			if (sysimg_guid != 0) {
5871 				nr_req.NodeInfo.SystemImageGUID = sysimg_guid;
5872 				c_mask |= SA_NODEINFO_COMPMASK_SYSIMAGEGUID;
5873 			}
5874 
5875 			IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: "
5876 			    "SAA Call: CMASK= 0x%llX", c_mask);
5877 
5878 			retval = ibcm_get_node_rec(saa_handle, &nr_req, c_mask,
5879 			    &res_p, &len);
5880 			if (retval == IBT_NODE_RECORDS_NOT_FOUND) {
5881 				IBTF_DPRINTF_L3(cmlog,
5882 				    "ibt_get_companion_port_gids: "
5883 				    "failed (%d) to get Node records", retval);
5884 				continue;
5885 			} else if (retval != IBT_SUCCESS) {
5886 				IBTF_DPRINTF_L2(cmlog,
5887 				    "ibt_get_companion_port_gids: Error: (%d) "
5888 				    "while getting Node records", retval);
5889 				ibcm_dec_hca_acc_cnt(hcap);
5890 				goto get_comp_pgid_exit;
5891 			}
5892 
5893 			num_rec = len/sizeof (sa_node_record_t);
5894 
5895 			/* We will be here, only if we found some NodeRec */
5896 			if (gid.gid_prefix && gid.gid_guid) {
5897 				nr_resp = (sa_node_record_t *)res_p;
5898 				for (l = 0; l < num_rec; l++, nr_resp++) {
5899 					pg = nr_resp->NodeInfo.PortGUID;
5900 					if (gid.gid_guid != pg)
5901 						count++;
5902 				}
5903 			} else {
5904 				count = num_rec;
5905 			}
5906 
5907 			if (count != 0) {
5908 				if (multi_sm_loop == 1) {
5909 					count += k;
5910 					t_gidp = kmem_zalloc(count *
5911 					    sizeof (ib_gid_t), KM_SLEEP);
5912 
5913 					if ((k != 0) && (gidp != NULL)) {
5914 						bcopy(gidp, t_gidp,
5915 						    k * sizeof (ib_gid_t));
5916 						kmem_free(gidp,
5917 						    k * sizeof (ib_gid_t));
5918 					}
5919 					gidp = t_gidp;
5920 				} else {
5921 					gidp = kmem_zalloc(count *
5922 					    sizeof (ib_gid_t), KM_SLEEP);
5923 				}
5924 				*num_gids_p = count;
5925 				*gids_p = gidp;
5926 
5927 				nr_resp = (sa_node_record_t *)res_p;
5928 				for (l = 0; l < num_rec; l++, nr_resp++) {
5929 					IBCM_DUMP_NODE_REC(nr_resp);
5930 
5931 					pg = nr_resp->NodeInfo.PortGUID;
5932 					IBTF_DPRINTF_L4(cmlog,
5933 					    "ibt_get_companion_port_gids: "
5934 					    "PortGID %llX", pg);
5935 
5936 					if (pg != gid.gid_guid) {
5937 						gidp[k].gid_prefix =
5938 						    sgid.gid_prefix;
5939 						gidp[k].gid_guid = pg;
5940 
5941 						IBTF_DPRINTF_L3(cmlog,
5942 						    "ibt_get_companion_pgids: "
5943 						    "GID[%d] = %llX:%llX", k,
5944 						    gidp[k].gid_prefix,
5945 						    gidp[k].gid_guid);
5946 
5947 						k++;
5948 						if (k == count)
5949 							break;
5950 					}
5951 				}
5952 				retval = IBT_SUCCESS;	/* done!. */
5953 				kmem_free(res_p, len);
5954 				ibcm_dec_hca_acc_cnt(hcap);
5955 				goto get_comp_pgid_exit;
5956 			} else {
5957 				IBTF_DPRINTF_L2(cmlog,
5958 				    "ibt_get_companion_port_gids: "
5959 				    "Companion PortGIDs not available");
5960 				retval = IBT_GIDS_NOT_FOUND;
5961 			}
5962 			/* Deallocate the memory for 'res_p'. */
5963 			kmem_free(res_p, len);
5964 
5965 			/*
5966 			 * If we are on MultiSM setup, then we need to lookout
5967 			 * from that subnet port too.
5968 			 */
5969 			if (multism) {
5970 				/* break if already searched both the subnet */
5971 				if (multi_sm_loop == 1)
5972 					break;
5973 
5974 				port = (j == 0) ? 1 : 0;
5975 				multi_sm_loop = 1;
5976 				goto get_comp_for_multism;
5977 			} else {
5978 				break;
5979 			}
5980 		}
5981 		ibcm_dec_hca_acc_cnt(hcap);
5982 
5983 		/*
5984 		 * We may be on dual HCA with dual SM configured system.  And
5985 		 * the input attr GID was visible from second HCA. So in order
5986 		 * to get the companion portgid we need to re-look from the
5987 		 * first HCA ports.
5988 		 */
5989 		if ((num_hcas > 1) && (i > 0) && (h_guid != 0) &&
5990 		    (multi_hca_loop != 1)) {
5991 			multi_hca_loop = 1;
5992 			goto get_comp_for_multihca;
5993 		}
5994 	}
5995 	if (*num_gids_p == 0)
5996 		retval = IBT_GIDS_NOT_FOUND;
5997 
5998 get_comp_pgid_exit:
5999 	if (guid_array)
6000 		ibt_free_hca_list(guid_array, num_hcas);
6001 
6002 	if ((retval != IBT_SUCCESS) && (*num_gids_p != 0)) {
6003 		retval = IBT_SUCCESS;
6004 	}
6005 
6006 	IBTF_DPRINTF_L3(cmlog, "ibt_get_companion_port_gids: done. Status %d, "
6007 	    "Found %d GIDs", retval, *num_gids_p);
6008 
6009 	return (retval);
6010 }
6011 
6012 
6013 /* Routines for warlock */
6014 
6015 /* ARGSUSED */
6016 static void
6017 ibcm_dummy_mcg_handler(void *arg, ibt_status_t retval, ibt_mcg_info_t *minfo)
6018 {
6019 	ibcm_join_mcg_tqarg_t	dummy_mcg;
6020 
6021 	dummy_mcg.func = ibcm_dummy_mcg_handler;
6022 
6023 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_mcg_handler: "
6024 	    "dummy_mcg.func %p", dummy_mcg.func);
6025 }
6026 
6027 
6028 /* ARGSUSED */
6029 static void
6030 ibcm_dummy_recycle_rc_handler(ibt_status_t retval, void *arg)
6031 {
6032 	ibcm_taskq_recycle_arg_t	dummy_rc_recycle;
6033 
6034 	dummy_rc_recycle.func = ibcm_dummy_recycle_rc_handler;
6035 
6036 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_recycle_rc_handler: "
6037 	    "dummy_rc_recycle.func %p", dummy_rc_recycle.func);
6038 }
6039 
6040 
6041 /* ARGSUSED */
6042 static ibt_cm_status_t
6043 ibcm_dummy_ud_handler(void *priv, ibt_cm_ud_event_t *event,
6044     ibt_cm_ud_return_args_t *ret_args,
6045     void *priv_data, ibt_priv_data_len_t len)
6046 {
6047 	/*
6048 	 * Let warlock see that ibcm_local_handler_s::actual_cm_handler
6049 	 * points to this routine.
6050 	 */
6051 	ibcm_local_handler_t	p;
6052 	ibcm_ud_state_data_t	dummy_ud;
6053 
6054 	p.actual_cm_handler = ibcm_dummy_ud_handler;
6055 	dummy_ud.ud_cm_handler = ibcm_dummy_ud_handler;
6056 
6057 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_ud_handler: p.actual_cm_handler %p"
6058 	    "dummy_ud.ud_cm_handler %p", p.actual_cm_handler,
6059 	    dummy_ud.ud_cm_handler);
6060 	/*
6061 	 * Call all routines that the client's callback routine could call.
6062 	 */
6063 
6064 	return (IBT_CM_ACCEPT);
6065 }
6066 
6067 /* ARGSUSED */
6068 static ibt_cm_status_t
6069 ibcm_dummy_rc_handler(void *priv, ibt_cm_event_t *event,
6070     ibt_cm_return_args_t *ret_args, void *priv_data, ibt_priv_data_len_t len)
6071 {
6072 	ibcm_state_data_t	dummy_rc;
6073 
6074 	dummy_rc.cm_handler = ibcm_dummy_rc_handler;
6075 
6076 	IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_rc_handler: "
6077 	    "dummy_ud.ud_cm_handler %p", dummy_rc.cm_handler);
6078 	/*
6079 	 * Call all routines that the client's callback routine could call.
6080 	 */
6081 
6082 	return (IBT_CM_ACCEPT);
6083 }
6084