xref: /illumos-gate/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_utils.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * ibcm_utils.c
31  *
32  * contains internal lookup functions of IB CM module
33  * along with some other miscellaneous stuff
34  *
35  * TBD:
36  * 1. Code needed to ensure that if any clients are using a service then
37  * don't de-register it.
38  */
39 
40 #include <sys/ib/mgt/ibcm/ibcm_impl.h>
41 #include <sys/ddi.h>
42 
43 
44 /* statics */
45 static vmem_t		*ibcm_local_sid_arena;
46 static ib_svc_id_t	ibcm_local_sid_seed;
47 static ib_com_id_t	ibcm_local_cid_seed;
48 _NOTE(READ_ONLY_DATA({ibcm_local_sid_arena ibcm_local_sid_seed
49     ibcm_local_cid_seed}))
50 static void		ibcm_delete_state_from_avl(ibcm_state_data_t *statep);
51 static void		ibcm_init_conn_trace(ibcm_state_data_t *statep);
52 static void		ibcm_fini_conn_trace(ibcm_state_data_t *statep);
53 static void		ibcm_dump_conn_trbuf(void *statep, char *line_prefix,
54 			    char *buf, int buf_size);
55 
56 /*
57  * ibcm_lookup_msg:
58  *
59  * Retrieves an existing state structure or creates a new one if none found.
60  * This function is used during
61  *	Passive connection side for INCOMING REQ/REJ/RTU/MRA/DREQ/DREP/LAP msgs
62  *	Active connection side for INCOMING REP/REJ/MRA/DREQ/DREP/APR msgs
63  *	Active side CM for outgoing REQ message.
64  *
65  * NOTE: Only return IBCM_LOOKUP_FAIL if lookup failed to find a match.
66  *
67  * Arguments are:-
68  *	event_type	- type of message
69  *			incoming REQ, REP, REJ, MRA, RTU
70  *	remote_qpn	- Remote QP number
71  *	comid		- local/remote comid
72  *	remote_hca_guid	- Remote HCA GUID
73  *	hcap		- HCA entry ptr
74  *	rstatep		- return statep pointer
75  *
76  * Return Values:
77  *	IBCM_LOOKUP_NEW		- new statep allocated
78  *	IBCM_LOOKUP_EXISTS	- found an existing entry
79  *	IBCM_LOOKUP_FAIL	- No lookup entry found
80  *	IBCM_MEMORY_FAILURE	- Memory allocs failed
81  */
82 ibcm_status_t
83 ibcm_lookup_msg(ibcm_event_type_t event_type, ib_com_id_t comid,
84     ib_qpn_t remote_qpn, ib_guid_t remote_hca_guid, ibcm_hca_info_t *hcap,
85     ibcm_state_data_t **rstatep)
86 {
87 	avl_index_t		where;
88 	ibcm_state_data_t	*sp;
89 
90 	IBTF_DPRINTF_L4(cmlog, "ibcm_lookup_msg: event = 0x%x, comid = 0x%lx",
91 	    event_type, comid);
92 	IBTF_DPRINTF_L4(cmlog, "ibcm_lookup_msg: rem_qpn = 0x%lX, "
93 	    "rem_hca_guid = 0x%llX", remote_qpn, remote_hca_guid);
94 
95 	ASSERT(rw_lock_held(&hcap->hca_state_rwlock));
96 
97 	/*
98 	 * Lookup in "hca_passive_tree" for IBCM_INCOMING_REQ and
99 	 * IBCM_INCOMING_REP_STALE;
100 	 *
101 	 * Lookup in "hca_passive_comid_tree" for IBCM_INCOMING_REQ_STALE
102 	 *
103 	 * All other lookups in "hca_active_tree".
104 	 *
105 	 * NOTE: "hca_active_tree" lookups are based on the local comid.
106 	 * "hca_passive_state_tree" lookups are based on remote QPN
107 	 * and remote hca GUID.
108 	 *
109 	 * Call avl_find to lookup in the respective tree and save result in
110 	 * "sp". If "sp" is null it implies that no match was found. If so,
111 	 * allocate a new ibcm_state_data_t and insert it into the AVL tree(s).
112 	 */
113 	if ((event_type == IBCM_INCOMING_REQ) ||
114 	    (event_type == IBCM_INCOMING_REP_STALE)) {
115 		ibcm_passive_node_info_t	info;
116 
117 		info.info_qpn = remote_qpn;
118 		info.info_hca_guid = remote_hca_guid;
119 
120 		/* Lookup based on Remote QPN and Remote GUID in Passive Tree */
121 		sp = avl_find(&hcap->hca_passive_tree, &info, &where);
122 	} else if ((event_type == IBCM_INCOMING_REQ_STALE) ||
123 	    (event_type == IBCM_INCOMING_REJ_RCOMID)) {
124 		ibcm_passive_comid_node_info_t	info;
125 
126 		info.info_comid = comid;
127 		info.info_hca_guid = remote_hca_guid;
128 
129 		/* Lookup based on Remote COMID in Passive Tree */
130 		sp = avl_find(&hcap->hca_passive_comid_tree, &info, &where);
131 	} else {	/* any other event including IBCM_OUTGOING_REQ */
132 		/* Lookup based on Local comid in Active Tree */
133 		sp = avl_find(&hcap->hca_active_tree, &comid, &where);
134 	}
135 
136 	/* matching entry found !! */
137 	if (sp != NULL) {
138 		IBTF_DPRINTF_L4(cmlog, "ibcm_lookup_msg: match found "
139 		    "statep = %p", sp);
140 		if (event_type == IBCM_INCOMING_REQ)
141 			kmem_free(*rstatep, sizeof (ibcm_state_data_t));
142 		*rstatep = sp;		/* return the matched statep */
143 
144 		mutex_enter(&(sp->state_mutex));
145 		IBCM_REF_CNT_INCR(sp); /* increment the ref count */
146 		mutex_exit(&(sp->state_mutex));
147 
148 		return (IBCM_LOOKUP_EXISTS);
149 	}
150 
151 	/*
152 	 * If we came here then it implies that CM didn't
153 	 * find a matching entry. We will create a new entry in avl tree,
154 	 * if event_type is INCOMING/OUTGOING REQ, REQ_STALE/REP_STALE.
155 	 * statep is created for INCOMING/OUTGOING REQ.
156 	 * For all other event_types we return lookup failure
157 	 */
158 	if (!((event_type == IBCM_INCOMING_REQ) ||
159 	    (event_type == IBCM_INCOMING_REQ_STALE) ||
160 	    (event_type == IBCM_INCOMING_REP_STALE) ||
161 	    (event_type == IBCM_OUTGOING_REQ))) {
162 		IBTF_DPRINTF_L2(cmlog, "ibcm_lookup_msg: failed for "
163 		    "event type %x", event_type);
164 
165 		return (IBCM_LOOKUP_FAIL);
166 	}
167 
168 	if ((event_type == IBCM_INCOMING_REQ) ||
169 	    (event_type == IBCM_OUTGOING_REQ)) {
170 
171 		/* fill in the new ibcm_state_data */
172 		sp = *rstatep;
173 
174 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sp))
175 
176 		/* initialize statep */
177 		mutex_init(&sp->state_mutex, NULL, MUTEX_DEFAULT, NULL);
178 		cv_init(&sp->block_client_cv, NULL, CV_DRIVER, NULL);
179 		cv_init(&sp->block_mad_cv, NULL, CV_DRIVER, NULL);
180 
181 		sp->hcap = hcap;
182 		IBCM_REF_CNT_INCR(sp);
183 		sp->local_comid = comid;
184 
185 		if (ibcm_enable_trace != 0)
186 			ibcm_init_conn_trace(sp);
187 
188 		if (event_type == IBCM_INCOMING_REQ) {	/* Passive side */
189 			sp->state = IBCM_STATE_REQ_RCVD;
190 			sp->clnt_proceed = IBCM_BLOCK;
191 			sp->close_nocb_state = IBCM_UNBLOCK;
192 			sp->remote_hca_guid = remote_hca_guid;
193 			sp->remote_qpn = remote_qpn;
194 
195 		} else if (event_type == IBCM_OUTGOING_REQ) { /* Active side */
196 			sp->close_nocb_state = IBCM_UNBLOCK;
197 			sp->state = IBCM_STATE_IDLE;
198 		}
199 
200 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sp))
201 
202 	} else {
203 		sp = *rstatep;	/* for incoming REQ/REP STALE only */
204 	}
205 
206 	if ((event_type == IBCM_INCOMING_REQ) ||
207 	    (event_type == IBCM_INCOMING_REP_STALE)) {
208 
209 		/* First, insert a new "sp" into "hca_passive_tree" @ "where" */
210 		avl_insert(&(hcap->hca_passive_tree), (void *)sp, where);
211 
212 		if (event_type == IBCM_INCOMING_REQ) {	/* Only INCOMING_REQ */
213 			/*
214 			 * We have to do an avl_find() to figure out
215 			 * "where" to insert the statep into the active tree.
216 			 *
217 			 * CM doesn't care for avl_find's retval.
218 			 */
219 			(void) avl_find(&hcap->hca_active_tree,
220 			    &sp->local_comid, &where);
221 
222 			/* Next, insert the "sp" into "hca_active_tree" */
223 			avl_insert(&hcap->hca_active_tree, (void *)sp, where);
224 		}
225 	} else if (event_type == IBCM_INCOMING_REQ_STALE) {
226 		avl_insert(&(hcap->hca_passive_comid_tree), (void *)sp, where);
227 	} else {	/* IBCM_OUTGOING_REQ */
228 		/* Insert the new sp only into "hca_active_tree", @ "where" */
229 		avl_insert(&(hcap->hca_active_tree), (void *)sp, where);
230 	}
231 
232 	return (IBCM_LOOKUP_NEW);	/* return new lookup */
233 }
234 
235 
236 /*
237  * ibcm_active_node_compare:
238  * 	- AVL active tree node compare
239  *
240  * Arguments:
241  *	p1	: pointer to local comid
242  *	p2	: pointer to passed ibcm_state_data_t
243  *
244  * Return values:
245  *	0	: match found
246  *	-1	: no match but insert to left side of the tree
247  *	+1	: no match but insert to right side of the tree
248  */
249 int
250 ibcm_active_node_compare(const void *p1, const void *p2)
251 {
252 	ib_com_id_t		*local_comid = (ib_com_id_t *)p1;
253 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)p2;
254 
255 	IBTF_DPRINTF_L5(cmlog, "ibcm_active_node_compare: "
256 	    "comid: 0x%x, statep: 0x%p", *local_comid, statep);
257 
258 	if (*local_comid > statep->local_comid) {
259 		return (+1);
260 	} else if (*local_comid < statep->local_comid) {
261 		return (-1);
262 	} else {
263 		return (0);
264 	}
265 }
266 
267 
268 /*
269  * ibcm_passive_node_compare:
270  * 	- AVL passive tree node compare (passive side)
271  *
272  * Arguments:
273  *	p1	: pointer to ibcm_passive_node_info (remote qpn and remote guid)
274  *	p2	: pointer to passed ibcm_state_data_t
275  *
276  * Return values:
277  *	0	: match found
278  *	-1	: no match but insert to left side of the tree
279  *	+1	: no match but insert to right side of the tree
280  */
281 int
282 ibcm_passive_node_compare(const void *p1, const void *p2)
283 {
284 	ibcm_state_data_t		*statep = (ibcm_state_data_t *)p2;
285 	ibcm_passive_node_info_t	*infop = (ibcm_passive_node_info_t *)p1;
286 
287 	IBTF_DPRINTF_L5(cmlog, "ibcm_passive_node_compare: "
288 	    "statep: 0x%p, p1: 0x%p", statep, p1);
289 
290 	/*
291 	 * PASSIVE SIDE: (REQ, REP, MRA, REJ)
292 	 *	always search by active COMID
293 	 */
294 	if (infop->info_qpn > statep->remote_qpn) {
295 		return (+1);
296 	} else if (infop->info_qpn < statep->remote_qpn) {
297 		return (-1);
298 	} else {
299 		if (infop->info_hca_guid < statep->remote_hca_guid) {
300 			return (-1);
301 		} else if (infop->info_hca_guid > statep->remote_hca_guid) {
302 			return (+1);
303 		} else {
304 			return (0);
305 		}
306 	}
307 }
308 
309 /*
310  * ibcm_passive_comid_node_compare:
311  * 	- AVL passive comid tree node compare (passive side)
312  *
313  * Arguments:
314  *	p1	: pointer to ibcm_passive_comid_node_info
315  *		  (remote comid and remote guid)
316  *	p2	: pointer to passed ibcm_state_data_t
317  *
318  * Return values:
319  *	0	: match found
320  *	-1	: no match but insert to left side of the tree
321  *	+1	: no match but insert to right side of the tree
322  */
323 int
324 ibcm_passive_comid_node_compare(const void *p1, const void *p2)
325 {
326 	ibcm_state_data_t		*statep = (ibcm_state_data_t *)p2;
327 	ibcm_passive_comid_node_info_t	*infop =
328 	    (ibcm_passive_comid_node_info_t *)p1;
329 
330 	IBTF_DPRINTF_L5(cmlog, "ibcm_passive_comid_node_compare: "
331 	    "statep: 0x%p, p1: 0x%p", statep, p1);
332 
333 	if (infop->info_comid > statep->remote_comid) {
334 		return (+1);
335 	} else if (infop->info_comid < statep->remote_comid) {
336 		return (-1);
337 	} else {
338 		if (infop->info_hca_guid < statep->remote_hca_guid) {
339 			return (-1);
340 		} else if (infop->info_hca_guid > statep->remote_hca_guid) {
341 			return (+1);
342 		} else {
343 			return (0);
344 		}
345 	}
346 }
347 
348 
349 void
350 ibcm_delete_state_from_avl(ibcm_state_data_t *statep)
351 {
352 	avl_index_t			a_where = 0;
353 	avl_index_t			p_where = 0;
354 	avl_index_t			pcomid_where = 0;
355 	ibcm_hca_info_t			*hcap;
356 	ibcm_state_data_t		*active_nodep, *passive_nodep,
357 					*passive_comid_nodep;
358 	ibcm_passive_node_info_t	info;
359 	ibcm_passive_comid_node_info_t	info_comid;
360 
361 	IBTF_DPRINTF_L4(cmlog, "ibcm_delete_state_from_avl: statep 0x%p",
362 	    statep);
363 
364 	if (statep == NULL) {
365 		IBTF_DPRINTF_L2(cmlog, "ibcm_delete_state_from_avl: statep"
366 		    " NULL");
367 		return;
368 	}
369 
370 	hcap = statep->hcap;
371 
372 	/*
373 	 * Once the avl tree lock is acquired, no other thread can increment
374 	 * ref cnt, until tree lock is exit'ed. Since the statep is removed
375 	 * from the avl's after acquiring lock below, no other thread can
376 	 * increment the ref cnt after acquiring the lock below
377 	 */
378 
379 	rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
380 
381 	/* Lookup based on Local comid in the active tree */
382 	active_nodep = avl_find(&hcap->hca_active_tree, &(statep->local_comid),
383 	    &a_where);
384 
385 	/* Lookup based on Remote QPN and Remote GUID in the passive tree */
386 	info.info_qpn = statep->remote_qpn;
387 	info.info_hca_guid = statep->remote_hca_guid;
388 	passive_nodep =  avl_find(&hcap->hca_passive_tree, &info, &p_where);
389 
390 	/* Lookup based on Remote Comid and Remote GUID in the passive tree */
391 	info_comid.info_comid = statep->remote_comid;
392 	info_comid.info_hca_guid = statep->remote_hca_guid;
393 	passive_comid_nodep =  avl_find(&hcap->hca_passive_comid_tree,
394 	    &info_comid, &pcomid_where);
395 
396 	/* remove it from the tree, destroy record and the nodep */
397 	if (active_nodep == statep) {
398 		avl_remove(&hcap->hca_active_tree, active_nodep);
399 	}
400 
401 	if (passive_nodep == statep) {
402 		avl_remove(&hcap->hca_passive_tree, passive_nodep);
403 	}
404 
405 	if (passive_comid_nodep == statep) {
406 		avl_remove(&hcap->hca_passive_comid_tree, passive_comid_nodep);
407 	}
408 
409 	rw_exit(&hcap->hca_state_rwlock);
410 }
411 
412 /*
413  * ibcm_dealloc_state_data:
414  *	Deallocates all buffers and the memory of state structure
415  * This routine can be called on statep that has ref_cnt of 0, and that is
416  * already deleted from the avl tree's
417  *
418  * Arguments are:-
419  *	statep	- statep to be deleted
420  *
421  * Return Values:	NONE
422  */
423 void
424 ibcm_dealloc_state_data(ibcm_state_data_t *statep)
425 {
426 	timeout_id_t timer_val;
427 	IBTF_DPRINTF_L4(cmlog, "ibcm_dealloc_state_data: statep 0x%p", statep);
428 
429 	if (statep == NULL) {
430 		IBTF_DPRINTF_L2(cmlog, "ibcm_dealloc_state_data: statep NULL");
431 		return;
432 	}
433 
434 	/* ref_cnt is 0 */
435 	/* If timer is running - expire it */
436 	mutex_enter(&statep->state_mutex);
437 	timer_val = statep->timerid;
438 	if (timer_val != 0) {
439 		statep->timerid = 0;
440 		mutex_exit(&statep->state_mutex);
441 		(void) untimeout(timer_val);
442 	} else
443 		mutex_exit(&statep->state_mutex);
444 
445 	/* release the ref cnt on the associated ibmf qp */
446 	if (statep->stored_reply_addr.cm_qp_entry != NULL)
447 		ibcm_release_qp(statep->stored_reply_addr.cm_qp_entry);
448 
449 	if (statep->stored_msg != NULL)
450 		(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
451 		    &statep->stored_msg);
452 
453 	if (statep->dreq_msg != NULL)
454 		(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
455 		    &statep->dreq_msg);
456 
457 	if (statep->drep_msg != NULL)
458 		(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
459 		    &statep->drep_msg);
460 
461 	if (statep->mra_msg != NULL)
462 		(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
463 		    &statep->mra_msg);
464 
465 	if (statep->lapr_msg != NULL)
466 		(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
467 		    &statep->lapr_msg);
468 
469 	if (statep->defer_cm_msg != NULL)
470 		kmem_free(statep->defer_cm_msg, IBCM_MSG_SIZE);
471 
472 	IBTF_DPRINTF_L4(cmlog, "ibcm_dealloc_state_data: done for sp = 0x%p",
473 	    statep);
474 
475 	/* Ensure the thread doing ref cnt decr releases the mutex */
476 	mutex_enter(&statep->state_mutex);
477 	mutex_exit(&statep->state_mutex);
478 
479 	/*
480 	 * now call the mutex_destroy() and cv_destroy()
481 	 */
482 	mutex_destroy(&statep->state_mutex);
483 
484 	cv_destroy(&statep->block_client_cv);
485 	cv_destroy(&statep->block_mad_cv);
486 
487 	/* free the comid */
488 	ibcm_free_comid(statep->hcap, statep->local_comid);
489 
490 	/* Decrement the resource on hcap */
491 	ibcm_dec_hca_res_cnt(statep->hcap);
492 
493 	/* dump the trace data into ibtf_debug_buf */
494 	if (ibcm_enable_trace & 4)
495 		ibcm_dump_conn_trace(statep);
496 
497 	ibcm_fini_conn_trace(statep);
498 
499 	/* free the statep */
500 	kmem_free(statep, sizeof (ibcm_state_data_t));
501 }
502 
503 /*
504  * ibcm_delete_state_data:
505  *	Deletes the state from avl trees, and tries to deallocate state
506  *
507  * Arguments are:-
508  *	statep	- statep to be deleted
509  *
510  * Return Values:	NONE
511  */
512 void
513 ibcm_delete_state_data(ibcm_state_data_t *statep)
514 {
515 	IBTF_DPRINTF_L4(cmlog, "ibcm_delete_state_data:");
516 
517 	ibcm_delete_state_from_avl(statep);
518 
519 	/* Must acquire the state mutex to set delete_state_data */
520 	mutex_enter(&statep->state_mutex);
521 	if (statep->ref_cnt > 0) {
522 		statep->delete_state_data = B_TRUE;
523 		IBTF_DPRINTF_L4(cmlog, "ibcm_delete_state_data: statep 0x%p "
524 		    "ref_cnt = %x", statep, statep->ref_cnt);
525 		mutex_exit(&statep->state_mutex);
526 		return;
527 	}
528 	mutex_exit(&statep->state_mutex);
529 
530 	ibcm_dealloc_state_data(statep);
531 }
532 
533 /*
534  * ibcm_find_sidr_entry:
535  *	Routines for CM SIDR state structure list manipulation.
536  *	Finds an entry based on lid, gid and grh exists fields
537  *
538  * INPUTS:
539  *	lid:		LID of incoming SIDR REQ
540  *	gid:		GID of incoming SIDR REQ
541  *	grh_exists:	TRUE if GRH exists in the incoming SIDR REQ
542  *	req_id:		Request ID
543  *	hcap:		CM State table to search for SIDR state structure
544  *	statep:		Returns a valid state structure, if one exists based
545  *			on lid, gid and grh_exists fields
546  *	flag:		IBCM_FLAG_LOOKUP - just lookup
547  *			IBCM_FLAG_LOOKUP_AND_ADD - if lookup fails, add it.
548  * Return Values:
549  *	IBCM_LOOKUP_EXISTS	- found an existing entry
550  *	IBCM_LOOKUP_FAIL	- failed to find an entry
551  *	IBCM_LOOKUP_NEW		- created a new entry
552  */
553 ibcm_status_t
554 ibcm_find_sidr_entry(ibcm_sidr_srch_t *srch_param, ibcm_hca_info_t *hcap,
555     ibcm_ud_state_data_t **ud_statep, ibcm_lookup_flag_t flag)
556 {
557 	ibcm_status_t		status;
558 	ibcm_ud_state_data_t	*usp;
559 
560 	IBTF_DPRINTF_L5(cmlog, "ibcm_find_sidr_entry: srch_params are:"
561 	    "lid=%x, (%llX, %llX), grh: %x, id: %x",
562 	    srch_param->srch_lid, srch_param->srch_gid.gid_prefix,
563 	    srch_param->srch_gid.gid_guid, srch_param->srch_grh_exists,
564 	    srch_param->srch_req_id);
565 
566 	if (flag == IBCM_FLAG_ADD) {
567 		*ud_statep = ibcm_add_sidr_entry(srch_param, hcap);
568 		return (IBCM_LOOKUP_NEW);
569 	}
570 
571 	usp = hcap->hca_sidr_list;	/* Point to the list */
572 
573 	/* traverse the list for a matching entry */
574 	while (usp != NULL) {
575 		IBTF_DPRINTF_L5(cmlog, "ibcm_find_sidr_entry: "
576 		    "lid=%x, (%llX, %llX), grh: %x, id: %x",
577 		    usp->ud_sidr_req_lid, usp->ud_sidr_req_gid.gid_prefix,
578 		    usp->ud_sidr_req_gid.gid_guid, usp->ud_grh_exists,
579 		    usp->ud_req_id);
580 
581 		if ((usp->ud_sidr_req_lid == srch_param->srch_lid) &&
582 		    ((srch_param->srch_gid.gid_prefix == 0) ||
583 		    (srch_param->srch_gid.gid_prefix ==
584 			usp->ud_sidr_req_gid.gid_prefix)) &&
585 		    ((srch_param->srch_gid.gid_guid == 0) ||
586 		    (srch_param->srch_gid.gid_guid ==
587 			usp->ud_sidr_req_gid.gid_guid)) &&
588 		    (srch_param->srch_req_id == usp->ud_req_id) &&
589 		    (usp->ud_grh_exists == srch_param->srch_grh_exists) &&
590 		    (usp->ud_mode == srch_param->srch_mode)) { /* found match */
591 			*ud_statep = usp;
592 			IBTF_DPRINTF_L5(cmlog, "ibcm_find_sidr_entry: "
593 			    "found usp = %p", usp);
594 			mutex_enter(&usp->ud_state_mutex);
595 			IBCM_UD_REF_CNT_INCR(usp);
596 			mutex_exit(&usp->ud_state_mutex);
597 
598 			return (IBCM_LOOKUP_EXISTS);
599 		}
600 		usp = usp->ud_nextp;
601 	}
602 
603 	/*
604 	 * If code came here --> it couldn't find a match.
605 	 *	OR
606 	 * the "hcap->hca_sidr_list" was NULL
607 	 */
608 	if (flag == IBCM_FLAG_LOOKUP) {
609 		IBTF_DPRINTF_L3(cmlog, "ibcm_find_sidr_entry: no match found "
610 		    "lid=%x, (%llX, %llX), grh: %x, id: %x",
611 		    srch_param->srch_lid, srch_param->srch_gid.gid_prefix,
612 		    srch_param->srch_gid.gid_guid, srch_param->srch_grh_exists,
613 		    srch_param->srch_req_id);
614 		status = IBCM_LOOKUP_FAIL;
615 	} else {
616 		*ud_statep = ibcm_add_sidr_entry(srch_param, hcap);
617 		status = IBCM_LOOKUP_NEW;
618 	}
619 
620 	return (status);
621 }
622 
623 
624 /*
625  * ibcm_add_sidr_entry:
626  *	Adds a SIDR entry. Called *ONLY* from ibcm_find_sidr_entry()
627  *
628  * INPUTS:
629  *	lid:		LID of incoming SIDR REQ
630  *	gid:		GID of incoming SIDR REQ
631  *	grh_exists:	TRUE if GRH exists in the incoming SIDR REQ
632  *	req_id:		Request ID
633  *	hcap:		CM State table to search for SIDR state structure
634  * Return Values: NONE
635  */
636 ibcm_ud_state_data_t *
637 ibcm_add_sidr_entry(ibcm_sidr_srch_t *srch_param, ibcm_hca_info_t *hcap)
638 {
639 	ibcm_ud_state_data_t	*ud_statep;
640 
641 	IBTF_DPRINTF_L5(cmlog, "ibcm_add_sidr_entry: lid=%x, guid=%llX, "
642 	    "grh = %x req_id = %lx", srch_param->srch_lid,
643 	    srch_param->srch_gid.gid_guid, srch_param->srch_grh_exists,
644 	    srch_param->srch_req_id);
645 
646 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
647 
648 	/* didn't find the entry - so create new */
649 	ud_statep = kmem_zalloc(sizeof (ibcm_ud_state_data_t), KM_SLEEP);
650 
651 	mutex_init(&ud_statep->ud_state_mutex, NULL, MUTEX_DEFAULT, NULL);
652 	cv_init(&ud_statep->ud_block_client_cv, NULL, CV_DRIVER, NULL);
653 
654 	/* Initialize some ud_statep fields */
655 	mutex_enter(&ud_statep->ud_state_mutex);
656 	ud_statep->ud_hcap		= hcap;
657 	ud_statep->ud_req_id		= srch_param->srch_req_id;
658 	ud_statep->ud_ref_cnt		= 1;
659 	ud_statep->ud_grh_exists	= srch_param->srch_grh_exists;
660 	ud_statep->ud_sidr_req_lid	= srch_param->srch_lid;
661 	ud_statep->ud_sidr_req_gid	= srch_param->srch_gid;
662 	ud_statep->ud_mode		= srch_param->srch_mode;
663 	ud_statep->ud_max_cm_retries	= ibcm_max_retries;
664 	mutex_exit(&ud_statep->ud_state_mutex);
665 
666 	/* Update the list */
667 	ud_statep->ud_nextp = hcap->hca_sidr_list;
668 	hcap->hca_sidr_list = ud_statep;
669 
670 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
671 
672 	return (ud_statep);
673 }
674 
675 
676 /*
677  * ibcm_delete_ud_state_data:
678  *	Deletes a given state structure
679  *
680  * Arguments are:-
681  *	statep	- statep to be deleted
682  *
683  * Return Values:	NONE
684  */
685 void
686 ibcm_delete_ud_state_data(ibcm_ud_state_data_t *ud_statep)
687 {
688 	ibcm_ud_state_data_t	*prevp, *headp;
689 	ibcm_hca_info_t		*hcap;
690 
691 	IBTF_DPRINTF_L4(cmlog, "ibcm_delete_ud_state_data: ud_statep 0x%p",
692 	    ud_statep);
693 
694 	if (ud_statep == NULL || ud_statep->ud_hcap == NULL) {
695 		IBTF_DPRINTF_L2(cmlog, "ibcm_delete_ud_state_data: "
696 		    "ud_statep or hcap is NULL");
697 		return;
698 	}
699 
700 	hcap = ud_statep->ud_hcap;
701 
702 	rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
703 
704 	/* Next, remove this from the HCA SIDR list */
705 	if (hcap->hca_sidr_list != NULL) {
706 		prevp = NULL;
707 		headp = hcap->hca_sidr_list;
708 
709 		while (headp != NULL) {
710 			/* delete the matching entry */
711 			if (headp == ud_statep) {
712 				if (prevp) {
713 					prevp->ud_nextp = headp->ud_nextp;
714 				} else {
715 					prevp = headp->ud_nextp;
716 					hcap->hca_sidr_list = prevp;
717 				}
718 				break;
719 			}
720 			prevp = headp;
721 			headp = headp->ud_nextp;
722 		}
723 	}
724 
725 	rw_exit(&hcap->hca_sidr_list_lock);
726 
727 	/*
728 	 * While ref_cnt >  0
729 	 * - implies someone else is accessing the statep (possibly in
730 	 * a timeout function handler etc.)
731 	 * - don't delete statep unless they are done otherwise potentially
732 	 * one could access released memory and panic.
733 	 */
734 	mutex_enter(&ud_statep->ud_state_mutex);
735 	if (ud_statep->ud_ref_cnt > 0) {
736 		ud_statep->ud_delete_state_data = B_TRUE;
737 		IBTF_DPRINTF_L4(cmlog, "ibcm_delete_ud_state_data: "
738 		    "ud_statep 0x%p ud_ref_cnt = %x", ud_statep,
739 		    ud_statep->ud_ref_cnt);
740 		mutex_exit(&ud_statep->ud_state_mutex);
741 		return;
742 	}
743 	mutex_exit(&ud_statep->ud_state_mutex);
744 
745 	ibcm_dealloc_ud_state_data(ud_statep);
746 }
747 
748 /*
749  * ibcm_ud_dealloc_state_data:
750  *	Deallocates a given ud state structure
751  *
752  * Arguments are:-
753  *	ud statep	- ud statep to be deleted
754  *
755  * Return Values:	NONE
756  */
757 void
758 ibcm_dealloc_ud_state_data(ibcm_ud_state_data_t *ud_statep)
759 {
760 	timeout_id_t		timer_val;
761 
762 	IBTF_DPRINTF_L4(cmlog, "ibcm_dealloc_ud_state_data: ud_statep 0x%p",
763 	    ud_statep);
764 
765 	/* If timer is running - expire it */
766 	mutex_enter(&ud_statep->ud_state_mutex);
767 	if (ud_statep->ud_timerid) {
768 		timer_val = ud_statep->ud_timerid;
769 		ud_statep->ud_timerid = 0;
770 		mutex_exit(&ud_statep->ud_state_mutex);
771 		(void) untimeout(timer_val);
772 		IBTF_DPRINTF_L2(cmlog, "ibcm_dealloc_ud_state_data: "
773 		    "Unexpected timer id 0x%p ud_statep 0x%p", timer_val,
774 		    ud_statep);
775 	} else
776 		mutex_exit(&ud_statep->ud_state_mutex);
777 
778 	if (ud_statep->ud_stored_msg != NULL) {
779 		(void) ibcm_free_out_msg(
780 		    ud_statep->ud_stored_reply_addr.ibmf_hdl,
781 		    &ud_statep->ud_stored_msg);
782 	}
783 
784 	/* release the ref cnt on the associated ibmf qp */
785 	ASSERT(ud_statep->ud_stored_reply_addr.cm_qp_entry != NULL);
786 	ibcm_release_qp(ud_statep->ud_stored_reply_addr.cm_qp_entry);
787 
788 	/* Ensure the thread doing ref cnt decr releases the mutex */
789 	mutex_enter(&ud_statep->ud_state_mutex);
790 	mutex_exit(&ud_statep->ud_state_mutex);
791 
792 	/* now do the mutex_destroy() and cv_destroy() */
793 	mutex_destroy(&ud_statep->ud_state_mutex);
794 
795 	cv_destroy(&ud_statep->ud_block_client_cv);
796 
797 	/* free the req id on SIDR REQ sender side */
798 	if (ud_statep->ud_mode == IBCM_ACTIVE_MODE)
799 		ibcm_free_reqid(ud_statep->ud_hcap, ud_statep->ud_req_id);
800 
801 	/* Decrement the resource on hcap */
802 	ibcm_dec_hca_res_cnt(ud_statep->ud_hcap);
803 
804 	/* free the statep */
805 	kmem_free(ud_statep, sizeof (ibcm_ud_state_data_t));
806 }
807 
808 
809 /*
810  * ibcm_init_ids:
811  *	Create the vmem arenas for the various global ids
812  *
813  * Arguments are:-
814  *	NONE
815  *
816  * Return Values:	ibcm_status_t
817  */
818 
819 ibcm_status_t
820 ibcm_init_ids(void)
821 {
822 	timespec_t tv;
823 
824 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_local_sid_arena))
825 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_local_sid_seed))
826 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_local_cid_seed))
827 
828 	ibcm_local_sid_arena = vmem_create("ibcm_local_sid",
829 	    (void *)IBCM_INITIAL_SID, IBCM_MAX_LOCAL_SIDS, 1, NULL, NULL, NULL,
830 	    0, VM_SLEEP | VMC_IDENTIFIER);
831 
832 	if (!ibcm_local_sid_arena)
833 		return (IBCM_FAILURE);
834 
835 	/* create a random starting value for local service ids */
836 	gethrestime(&tv);
837 	ibcm_local_sid_seed = ((uint64_t)tv.tv_sec << 20) & 0x007FFFFFFFF00000;
838 	ASSERT((ibcm_local_sid_seed & IB_SID_AGN_MASK) == 0);
839 	ibcm_local_sid_seed |= IB_SID_AGN_LOCAL;
840 	ibcm_local_cid_seed = (ib_com_id_t)tv.tv_sec;
841 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_local_sid_arena))
842 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_local_sid_seed))
843 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_local_cid_seed))
844 
845 	return (IBCM_SUCCESS);
846 }
847 
848 
849 /*
850  * ibcm_init_hca_ids:
851  *	Create the vmem arenas for the various hca level ids
852  *
853  * Arguments are:-
854  *	hcap		pointer to ibcm_hca_info_t
855  *
856  * Return Values:	ibcm_status_t
857  */
858 ibcm_status_t
859 ibcm_init_hca_ids(ibcm_hca_info_t *hcap)
860 {
861 	hcap->hca_comid_arena = vmem_create("ibcm_com_ids",
862 	    (void *)IBCM_INITIAL_COMID, IBCM_MAX_COMIDS,
863 	    1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
864 
865 	if (!hcap->hca_comid_arena)
866 		return (IBCM_FAILURE);
867 
868 	hcap->hca_reqid_arena = vmem_create("ibcm_req_ids",
869 	    (void *)IBCM_INITIAL_REQID, IBCM_MAX_REQIDS,
870 	    1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
871 
872 	if (!hcap->hca_reqid_arena) {
873 		vmem_destroy(hcap->hca_comid_arena);
874 		return (IBCM_FAILURE);
875 	}
876 
877 	return (IBCM_SUCCESS);
878 }
879 
880 /*
881  * ibcm_free_ids:
882  *	Destroy the vmem arenas for the various ids
883  *
884  * Arguments are:-
885  *	NONE
886  *
887  * Return Values:	NONE
888  */
889 void
890 ibcm_fini_ids(void)
891 {
892 	/* All arenas shall be valid */
893 	vmem_destroy(ibcm_local_sid_arena);
894 }
895 
896 /*
897  * ibcm_free_hca_ids:
898  *	Destroy the vmem arenas for the various ids
899  *
900  * Arguments are:-
901  *	hcap		pointer to ibcm_hca_info_t
902  *
903  * Return Values:	NONE
904  */
905 void
906 ibcm_fini_hca_ids(ibcm_hca_info_t *hcap)
907 {
908 	/* All arenas shall be valid */
909 	vmem_destroy(hcap->hca_comid_arena);
910 	vmem_destroy(hcap->hca_reqid_arena);
911 }
912 
913 /* Communication id management routines ie., allocate, free up comids */
914 
915 /*
916  * ibcm_alloc_comid:
917  *	Allocate a new communication id
918  *
919  * Arguments are:-
920  *	hcap	:	pointer to ibcm_hca_info_t
921  *	comid:		pointer to the newly allocated communication id
922  *
923  * Return Values:	ibt_status_t
924  */
925 ibcm_status_t
926 ibcm_alloc_comid(ibcm_hca_info_t *hcap, ib_com_id_t *comidp)
927 {
928 	ib_com_id_t comid;
929 
930 	/* Use next fit, so least recently used com id is allocated */
931 	comid = (ib_com_id_t)(uintptr_t)vmem_alloc(hcap->hca_comid_arena, 1,
932 	    VM_SLEEP | VM_NEXTFIT);
933 
934 	IBTF_DPRINTF_L4(cmlog, "ibcm_alloc_comid: hcap 0x%p comid 0x%lX", hcap,
935 	    comid);
936 
937 	/*
938 	 * As comid is 32 bits, and maximum connections possible are 2^24
939 	 * per hca, comid allocation would never fail
940 	 */
941 	*comidp = comid + ibcm_local_cid_seed;
942 	if (comid == 0) {
943 		IBTF_DPRINTF_L2(cmlog, "ibcm_alloc_comid: hcap 0x%p"
944 		    "no more comids available", hcap);
945 		return (IBCM_FAILURE);
946 	}
947 
948 	return (IBCM_SUCCESS);
949 }
950 
951 /*
952  * ibcm_free_comid:
953  *	Releases the given Communication Id
954  *
955  * Arguments are:
956  *	hcap	:	pointer to ibcm_hca_info_t
957  *	comid	:	Communication id to be free'd
958  *
959  * Return Values:	NONE
960  */
961 void
962 ibcm_free_comid(ibcm_hca_info_t *hcap, ib_com_id_t comid)
963 {
964 	IBTF_DPRINTF_L4(cmlog, "ibcm_free_comid: hcap 0x%p"
965 	    "comid %x", hcap, comid);
966 	comid -= ibcm_local_cid_seed;
967 	vmem_free(hcap->hca_comid_arena, (void *)(uintptr_t)comid, 1);
968 }
969 
970 /* Allocate and Free local service ids */
971 
972 /*
973  * ibcm_alloc_local_sids:
974  *	Create and destroy the vmem arenas for the service ids
975  *
976  * Arguments are:-
977  *	Number of contiguous SIDs needed
978  *
979  * Return Values:	starting SID
980  */
981 ib_svc_id_t
982 ibcm_alloc_local_sids(int num_sids)
983 {
984 	ib_svc_id_t sid;
985 
986 	sid = (ib_svc_id_t)(uintptr_t)vmem_alloc(ibcm_local_sid_arena,
987 	    num_sids, VM_SLEEP | VM_NEXTFIT);
988 
989 	IBTF_DPRINTF_L4(cmlog, "ibcm_alloc_local_sids: ServiceID 0x%llX "
990 	    "num_sids %d", sid, num_sids);
991 	if (sid == 0) {
992 		IBTF_DPRINTF_L2(cmlog, "ibcm_alloc_local_sids: "
993 		    "no more local sids available");
994 	} else {
995 		ASSERT((ibcm_local_sid_seed & IB_SID_AGN_MASK) ==
996 		    IB_SID_AGN_LOCAL);
997 		sid += ibcm_local_sid_seed;
998 		IBTF_DPRINTF_L4(cmlog, "ibcm_alloc_local_sids: Success: "
999 		    "allocated 0x%llX:%d", sid, num_sids);
1000 	}
1001 	return (sid);
1002 }
1003 
1004 /*
1005  * ibcm_free_local_sids:
1006  *	Releases the given Local service id
1007  *
1008  * Arguments are:
1009  *	num_sids:	Number of local service id's to be free'd
1010  *	service_id:	Starting local service id that needs to be free'd
1011  *
1012  * Return Values:	NONE
1013  */
1014 void
1015 ibcm_free_local_sids(ib_svc_id_t service_id, int num_sids)
1016 {
1017 	service_id -= ibcm_local_sid_seed;
1018 	IBTF_DPRINTF_L4(cmlog, "ibcm_free_local_sids: "
1019 	    "service_id 0x%llX num_sids %d", service_id, num_sids);
1020 	vmem_free(ibcm_local_sid_arena,
1021 	    (void *)(uintptr_t)service_id, num_sids);
1022 }
1023 
1024 /* Allocate and free request id routines for SIDR */
1025 
1026 /*
1027  * ibcm_alloc_reqid:
1028  *	Allocate a new SIDR REQ request id
1029  *
1030  * Arguments are:-
1031  *	hcap	:	pointer to ibcm_hca_info_t
1032  *	*reqid	:	pointer to the new request id returned
1033  *
1034  * Return Values:	ibcm_status_t
1035  */
1036 ibcm_status_t
1037 ibcm_alloc_reqid(ibcm_hca_info_t *hcap, uint32_t *reqid)
1038 {
1039 	/* Use next fit, so least recently used com id is allocated */
1040 	*reqid = (uint32_t)(uintptr_t)vmem_alloc(hcap->hca_reqid_arena, 1,
1041 	    VM_SLEEP | VM_NEXTFIT);
1042 
1043 	IBTF_DPRINTF_L4(cmlog, "ibcm_alloc_reqid: hcap 0x%p reqid %x", hcap,
1044 	    *reqid);
1045 	if (!(*reqid)) {
1046 		IBTF_DPRINTF_L2(cmlog, "ibcm_alloc_reqid: "
1047 		    "no more req ids available");
1048 		return (IBCM_FAILURE);
1049 	}
1050 	return (IBCM_SUCCESS);
1051 }
1052 
1053 /*
1054  * ibcm_free_reqid:
1055  *	Releases the given SIDR REQ request id
1056  *
1057  * Arguments are:
1058  *	hcap	:	pointer to ibcm_hca_info_t
1059  *	reqid	:	Request id to be free'd
1060  *
1061  * Return Values:	NONE
1062  */
1063 void
1064 ibcm_free_reqid(ibcm_hca_info_t *hcap, uint32_t reqid)
1065 {
1066 	IBTF_DPRINTF_L4(cmlog, "ibcm_free_reqid: hcap 0x%p reqid %x", hcap,
1067 	    reqid);
1068 	vmem_free(hcap->hca_reqid_arena, (void *)(uintptr_t)reqid, 1);
1069 }
1070 
1071 /*
1072  * ibcm_generate_tranid:
1073  *	Generate a new transaction id based on args
1074  *
1075  * Arguments are:-
1076  *	event_type	CM Message REQ/DREQ/LAP
1077  *	id		32 bit identifier
1078  *	cm_tran_priv	CM private data to be filled in top 28 MSB bits of
1079  *			tran id
1080  *
1081  *
1082  * Return Value:	uint64_t
1083  */
1084 uint64_t
1085 ibcm_generate_tranid(uint8_t event, uint32_t id, uint32_t cm_tran_priv)
1086 {
1087 	/*
1088 	 * copy comid to bits 31-0 of tran id,
1089 	 * attr id to bits 35-32 of tran id,
1090 	 * cm_priv to bits 63-36 of tran id
1091 	 */
1092 	if (cm_tran_priv == 0)
1093 		/*
1094 		 * The below ensures that no duplicate transaction id is
1095 		 * generated atleast for next 6 months. Calculations:
1096 		 * (2^28)/(1000 * 60 * 24 * 30) = 6 approx
1097 		 */
1098 		cm_tran_priv = gethrtime() >> 20;	/* ~time in ms */
1099 
1100 	return ((((uint64_t)cm_tran_priv << 36) | (uint64_t)event << 32) | id);
1101 }
1102 
1103 #ifdef DEBUG
1104 
1105 /*
1106  * ibcm_decode_tranid:
1107  *	Decodes a given transaction id, assuming certain format.
1108  *
1109  * Arguments are:-
1110  *	tran_id		Transaction id to be decoded
1111  *	cm_tran_priv	CM private data retrieved from transaction id
1112  *
1113  * Return Value:	None
1114  */
1115 void
1116 ibcm_decode_tranid(uint64_t tran_id, uint32_t *cm_tran_priv)
1117 {
1118 	ib_com_id_t		id;
1119 	ibcm_event_type_t	event;
1120 
1121 	id = tran_id & 0xFFFFFFFF;
1122 	event = (tran_id >> 32) & 0xF;
1123 
1124 	IBTF_DPRINTF_L5(cmlog, "ibcm_decode_tranid: id = 0x%lx, event = %x",
1125 	    id, event);
1126 
1127 	if (cm_tran_priv) {
1128 		*cm_tran_priv = tran_id >> 36;
1129 		IBTF_DPRINTF_L5(cmlog, "ibcm_decode_tranid: "
1130 		    "cm_tran_priv = %x", *cm_tran_priv);
1131 	}
1132 }
1133 
1134 #endif
1135 
1136 /*
1137  * Service ID entry create and lookup functions
1138  */
1139 
1140 /*
1141  * ibcm_svc_compare:
1142  * 	- AVL svc tree node compare
1143  *
1144  * Arguments:
1145  *	p1	: pointer to local comid
1146  *	p2	: pointer to passed ibcm_state_data_t
1147  *
1148  * Return values:
1149  *	0	: match found
1150  *	-1	: no match but insert to left side of the tree
1151  *	+1	: no match but insert to right side of the tree
1152  */
1153 int
1154 ibcm_svc_compare(const void *p1, const void *p2)
1155 {
1156 	ibcm_svc_lookup_t	*sidp = (ibcm_svc_lookup_t *)p1;
1157 	ibcm_svc_info_t		*svcp = (ibcm_svc_info_t *)p2;
1158 	ib_svc_id_t		start_sid = sidp->sid;
1159 	ib_svc_id_t		end_sid = start_sid + sidp->num_sids - 1;
1160 
1161 	IBTF_DPRINTF_L5(cmlog, "ibcm_svc_compare: "
1162 	    "sid: 0x%llx, numsids: %d, node_sid: 0x%llx node_num_sids: %d",
1163 	    sidp->sid, sidp->num_sids, svcp->svc_id, svcp->svc_num_sids);
1164 
1165 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
1166 
1167 	if (svcp->svc_id > end_sid)
1168 		return (-1);
1169 	if (svcp->svc_id + svcp->svc_num_sids - 1 < start_sid)
1170 		return (+1);
1171 	return (0);	/* means there is some overlap of SIDs */
1172 }
1173 
1174 
1175 /*
1176  * ibcm_create_svc_entry:
1177  *	Make sure no conflicting entry exists, then allocate it.
1178  *	Fill in the critical "look up" details that are provided
1179  *	in the arguments before dropping the lock.
1180  *
1181  * Return values:
1182  *	Pointer to ibcm_svc_info_t, if created, otherwise NULL.
1183  */
1184 ibcm_svc_info_t *
1185 ibcm_create_svc_entry(ib_svc_id_t sid, int num_sids)
1186 {
1187 	ibcm_svc_info_t	*svcp;
1188 	ibcm_svc_info_t	*svcinfop;
1189 	ibcm_svc_lookup_t svc;
1190 	avl_index_t where = 0;
1191 
1192 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*svcinfop))
1193 
1194 	/* assume success, and avoid kmem while holding the writer lock */
1195 	svcinfop = kmem_zalloc(sizeof (*svcinfop), KM_SLEEP);
1196 	svcinfop->svc_id = sid;
1197 	svcinfop->svc_num_sids = num_sids;
1198 
1199 	svc.sid = sid;
1200 	svc.num_sids = num_sids;
1201 
1202 	mutex_enter(&ibcm_svc_info_lock);
1203 #ifdef __lock_lint
1204 	ibcm_svc_compare(NULL, NULL);
1205 #endif
1206 	svcp = avl_find(&ibcm_svc_avl_tree, &svc, &where);
1207 	if (svcp != NULL) {	/* overlab exists */
1208 		mutex_exit(&ibcm_svc_info_lock);
1209 		kmem_free(svcinfop, sizeof (*svcinfop));
1210 		return (NULL);
1211 	}
1212 	avl_insert(&ibcm_svc_avl_tree, (void *)svcinfop, where);
1213 	mutex_exit(&ibcm_svc_info_lock);
1214 
1215 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*svcinfop))
1216 
1217 	return (svcinfop);
1218 }
1219 
1220 /*
1221  * ibcm_find_svc_entry:
1222  *	Finds a ibcm_svc_info_t entry into the CM's global table.
1223  *	The search done here assumes the list is sorted by SID.
1224  *
1225  * Arguments are:
1226  *	sid		- Service ID to look up
1227  *
1228  * Return values:
1229  *	Pointer to ibcm_svc_info_t, if found, otherwise NULL.
1230  */
1231 ibcm_svc_info_t *
1232 ibcm_find_svc_entry(ib_svc_id_t sid)
1233 {
1234 	ibcm_svc_info_t	*svcp;
1235 	ibcm_svc_lookup_t svc;
1236 
1237 	IBTF_DPRINTF_L3(cmlog, "ibcm_find_svc_entry: finding SID 0x%llX", sid);
1238 
1239 	ASSERT(MUTEX_HELD(&ibcm_svc_info_lock));
1240 
1241 	svc.sid = sid;
1242 	svc.num_sids = 1;
1243 #ifdef __lock_lint
1244 	ibcm_svc_compare(NULL, NULL);
1245 #endif
1246 	svcp = avl_find(&ibcm_svc_avl_tree, &svc, NULL);
1247 	if (svcp != NULL) {
1248 		IBTF_DPRINTF_L3(cmlog, "ibcm_find_svc_entry: "
1249 		    "found SID = 0x%llX", sid);
1250 		return (svcp);	/* found it */
1251 	}
1252 	IBTF_DPRINTF_L3(cmlog, "ibcm_find_svc_entry: SID %llX not found", sid);
1253 	return (NULL);
1254 }
1255 
1256 /*
1257  * ibcm_alloc_ibmf_msg:
1258  * Allocate an ibmf message structure and the additional memory required for
1259  * sending an outgoing CM mad.  The ibmf message structure contains two
1260  * ibmf_msg_bufs_t fields, one for the incoming MAD and one for the outgoing
1261  * MAD.  The CM must allocate the memory for the outgoing MAD.  The msg_buf
1262  * field has three buffers: the mad header, the class header, and the class
1263  * data.  To simplify the code and reduce the number of kmem_zalloc() calls,
1264  * ibcm_alloc_ibmf_msg will allocate one buffer and set the pointers to the
1265  * right offsets.  No class header is needed so only the mad header and class
1266  * data fields are used.
1267  */
1268 ibt_status_t
1269 ibcm_alloc_out_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t **ibmf_msgpp,
1270     uint8_t method)
1271 {
1272 	ib_mad_hdr_t	*output_mad_hdr;
1273 	int		sa_retval;
1274 
1275 	if ((sa_retval =
1276 	    ibmf_alloc_msg(ibmf_handle, IBMF_ALLOC_SLEEP, ibmf_msgpp)) !=
1277 	    IBMF_SUCCESS) {
1278 		IBTF_DPRINTF_L1(cmlog, "ibcm_alloc_out_msg: "
1279 		    "ibmf_alloc_msg failed with IBMF_ALLOC_SLEEP");
1280 		return (ibcm_ibmf_analyze_error(sa_retval));
1281 	}
1282 
1283 	(*ibmf_msgpp)->im_msgbufs_send.im_bufs_mad_hdr = kmem_zalloc(
1284 	    IBCM_MAD_SIZE, KM_SLEEP);
1285 
1286 	(*ibmf_msgpp)->im_msgbufs_send.im_bufs_cl_data_len = IBCM_MSG_SIZE;
1287 	(*ibmf_msgpp)->im_msgbufs_send.im_bufs_cl_data =
1288 	    (uchar_t *)((*ibmf_msgpp)->im_msgbufs_send.im_bufs_mad_hdr) +
1289 	    IBCM_MAD_HDR_SIZE;
1290 
1291 	/* initialize generic CM MAD header fields */
1292 	output_mad_hdr = IBCM_OUT_HDRP((*ibmf_msgpp));
1293 	output_mad_hdr->BaseVersion = IBCM_MAD_BASE_VERSION;
1294 	output_mad_hdr->MgmtClass = MAD_MGMT_CLASS_COMM_MGT;
1295 	output_mad_hdr->ClassVersion = IBCM_MAD_CLASS_VERSION;
1296 	output_mad_hdr->R_Method = method;
1297 
1298 	return (IBT_SUCCESS);
1299 }
1300 
1301 /*
1302  * ibcm_free_ibmf_msg:
1303  * Frees the buffer and ibmf message associated with an outgoing CM message.
1304  * This function should only be used to free messages created by
1305  * ibcm_alloc_out_msg.  Will return IBCM_FAILURE if the ibmf_free_msg() call
1306  * fails and IBCM_SUCCESS otherwise.
1307  */
1308 ibcm_status_t
1309 ibcm_free_out_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t **ibmf_msgpp)
1310 {
1311 	int ibmf_status;
1312 
1313 	kmem_free((*ibmf_msgpp)->im_msgbufs_send.im_bufs_mad_hdr,
1314 	    IBCM_MAD_SIZE);
1315 
1316 	if ((ibmf_status = ibmf_free_msg(ibmf_handle, ibmf_msgpp)) !=
1317 	    IBMF_SUCCESS) {
1318 		IBTF_DPRINTF_L2(cmlog, "ibcm_free_out_msg: "
1319 		    "ibmf_free_msg failed %d", ibmf_status);
1320 		return (IBCM_FAILURE);
1321 	} else
1322 		return (IBCM_SUCCESS);
1323 }
1324 
1325 ibcm_qp_list_t *
1326 ibcm_find_qp(ibcm_hca_info_t *hcap, int port_no, ib_pkey_t pkey)
1327 {
1328 	ibcm_qp_list_t		*entry;
1329 	ibmf_qp_handle_t	ibmf_qp;
1330 	int			ibmf_status;
1331 
1332 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*entry))
1333 
1334 	mutex_enter(&ibcm_qp_list_lock);
1335 
1336 	/*
1337 	 * CM currently does not track port up and down status. If tracking of
1338 	 * " port status" is added in the future, then CM could be optimized to
1339 	 * re-use other ports on hcap, if the port associated with the above
1340 	 * port_no is down. But, the issue of "reachability" needs to be
1341 	 * handled, before selecting an alternative port different from above.
1342 	 */
1343 	entry = hcap->hca_port_info[port_no-1].port_qplist;
1344 	while (entry != NULL) {
1345 		if (entry->qp_pkey == pkey) {
1346 			++entry->qp_ref_cnt;
1347 			mutex_exit(&ibcm_qp_list_lock);
1348 			return (entry);
1349 		}
1350 		entry = entry->qp_next;
1351 	}
1352 
1353 	/*
1354 	 * entry not found, attempt to alloc a qp
1355 	 * This may be optimized in the future, to allocate ibmf qp's
1356 	 * once the "CM mgmt pkeys" are precisely known.
1357 	 */
1358 	ibmf_status = ibmf_alloc_qp(
1359 	    hcap->hca_port_info[port_no-1].port_ibmf_hdl, pkey, IB_GSI_QKEY,
1360 	    IBMF_ALT_QP_MAD_NO_RMPP, &ibmf_qp);
1361 
1362 	if (ibmf_status != IBMF_SUCCESS) {
1363 		mutex_exit(&ibcm_qp_list_lock);
1364 		IBTF_DPRINTF_L2(cmlog, "ibcm_find_qp: failed to alloc IBMF QP"
1365 		    "for Pkey = %x port_no = %x status = %d hcaguid = %llXp",
1366 		    pkey, port_no, ibmf_status, hcap->hca_guid);
1367 		/*
1368 		 * This may be optimized in the future, so as CM would attempt
1369 		 * to re-use other QP's whose ref cnt is 0 in the respective
1370 		 * port_qplist, by doing an ibmf_modify_qp with pkey above.
1371 		 */
1372 		return (NULL);
1373 	}
1374 
1375 	entry = kmem_alloc(sizeof (ibcm_qp_list_t), KM_SLEEP);
1376 	entry->qp_next = hcap->hca_port_info[port_no-1].port_qplist;
1377 	hcap->hca_port_info[port_no-1].port_qplist = entry;
1378 	entry->qp_cm = ibmf_qp;
1379 	entry->qp_ref_cnt = 1;
1380 	entry->qp_pkey = pkey;
1381 	entry->qp_port = &(hcap->hca_port_info[port_no-1]);
1382 
1383 	mutex_exit(&ibcm_qp_list_lock);
1384 
1385 	/* set-up the handler */
1386 	ibmf_status = ibmf_setup_async_cb(
1387 	    hcap->hca_port_info[port_no-1].port_ibmf_hdl, ibmf_qp,
1388 	    ibcm_recv_cb, entry, 0);
1389 
1390 	ASSERT(ibmf_status == IBMF_SUCCESS);
1391 
1392 #ifdef	DEBUG
1393 	ibcm_query_qp(hcap->hca_port_info[port_no-1].port_ibmf_hdl, ibmf_qp);
1394 #endif
1395 
1396 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*entry))
1397 
1398 	return (entry);
1399 }
1400 
1401 void
1402 ibcm_release_qp(ibcm_qp_list_t *cm_qp_entry)
1403 {
1404 	mutex_enter(&ibcm_qp_list_lock);
1405 	--cm_qp_entry->qp_ref_cnt;
1406 	ASSERT(cm_qp_entry->qp_ref_cnt >= 0);
1407 	mutex_exit(&ibcm_qp_list_lock);
1408 }
1409 
1410 
1411 /* called holding the ibcm_qp_list_lock mutex */
1412 ibcm_status_t
1413 ibcm_free_qp(ibcm_qp_list_t *cm_qp_entry)
1414 {
1415 	int	ibmf_status;
1416 
1417 	IBTF_DPRINTF_L5(cmlog, "ibcm_free_qp: qp_hdl %p ref_cnt %d pkey %x",
1418 	    cm_qp_entry->qp_cm, cm_qp_entry->qp_ref_cnt, cm_qp_entry->qp_pkey);
1419 
1420 	/* check, there are no users of this ibmf qp */
1421 	if (cm_qp_entry->qp_ref_cnt != 0)
1422 		return (IBCM_FAILURE);
1423 
1424 	/* Tear down the receive callback */
1425 	ibmf_status = ibmf_tear_down_async_cb(
1426 	    cm_qp_entry->qp_port->port_ibmf_hdl, cm_qp_entry->qp_cm, 0);
1427 	if (ibmf_status != IBMF_SUCCESS) {
1428 		IBTF_DPRINTF_L2(cmlog, "ibcm_free_qp: "
1429 		    "ibmf_tear_down_async_cb failed %d port_num %d",
1430 		    ibmf_status, cm_qp_entry->qp_port->port_num);
1431 		return (IBCM_FAILURE);
1432 	}
1433 
1434 	ibmf_status = ibmf_free_qp(cm_qp_entry->qp_port->port_ibmf_hdl,
1435 	    &cm_qp_entry->qp_cm, 0);
1436 	if (ibmf_status != IBMF_SUCCESS) {
1437 		IBTF_DPRINTF_L2(cmlog, "ibcm_free_qp: ibmf_free_qp failed for"
1438 		    " ibmf_status %d qp hdl %p port_no %x", ibmf_status,
1439 		    cm_qp_entry->qp_cm, cm_qp_entry->qp_port->port_num);
1440 		return (IBCM_FAILURE);
1441 	}
1442 
1443 	return (IBCM_SUCCESS);
1444 }
1445 
1446 ibcm_status_t
1447 ibcm_free_allqps(ibcm_hca_info_t *hcap, int port_no)
1448 {
1449 	ibcm_qp_list_t		*entry, *freed;
1450 	ibcm_status_t		ibcm_status = IBCM_SUCCESS;
1451 
1452 	IBTF_DPRINTF_L5(cmlog, "ibcm_free_allqps: hcap %p port_no %d", hcap,
1453 	    port_no);
1454 
1455 	mutex_enter(&ibcm_qp_list_lock);
1456 	entry = hcap->hca_port_info[port_no-1].port_qplist;
1457 	while ((entry != NULL) &&
1458 	    ((ibcm_status = ibcm_free_qp(entry)) == IBCM_SUCCESS)) {
1459 		freed = entry;
1460 		entry = entry->qp_next;
1461 		kmem_free(freed, sizeof (ibcm_qp_list_t));
1462 	}
1463 
1464 	if (ibcm_status != IBCM_SUCCESS)	/* sanity the linked list */
1465 		hcap->hca_port_info[port_no-1].port_qplist = entry;
1466 	else	/* all ibmf qp's of port must have been free'd successfully */
1467 		hcap->hca_port_info[port_no-1].port_qplist = NULL;
1468 
1469 	mutex_exit(&ibcm_qp_list_lock);
1470 	return (ibcm_status);
1471 }
1472 
1473 /*
1474  * ibt_bind_service() and ibt_get_paths() needs the following helper function
1475  * to handle endianess in case of Service Data.
1476  */
1477 void
1478 ibcm_swizzle_from_srv(ibt_srv_data_t *sb_data, uint8_t *service_bytes)
1479 {
1480 	uint8_t		*p8 = service_bytes;
1481 	uint16_t	*p16;
1482 	uint32_t	*p32;
1483 	uint64_t	*p64;
1484 	int		i;
1485 
1486 	for (i = 0; i < 16; i++)
1487 		*p8++ = sb_data->s_data8[i];
1488 
1489 	p16 = (uint16_t *)p8;
1490 	for (i = 0; i < 8; i++)
1491 		*p16++ = h2b16(sb_data->s_data16[i]);
1492 
1493 	p32 = (uint32_t *)p16;
1494 	for (i = 0; i < 4; i++)
1495 		*p32++ = h2b32(sb_data->s_data32[i]);
1496 
1497 	p64 = (uint64_t *)p32;
1498 	for (i = 0; i < 2; i++)
1499 		*p64++ = h2b64(sb_data->s_data64[i]);
1500 }
1501 
1502 void
1503 ibcm_swizzle_to_srv(uint8_t *service_bytes, ibt_srv_data_t *sb_data)
1504 {
1505 	uint8_t		*p8 = service_bytes;
1506 	uint16_t	*p16;
1507 	uint32_t	*p32;
1508 	uint64_t	*p64;
1509 	int		i;
1510 
1511 	for (i = 0; i < 16; i++)
1512 		sb_data->s_data8[i] = *p8++;
1513 
1514 	p16 = (uint16_t *)p8;
1515 	for (i = 0; i < 8; i++)
1516 		sb_data->s_data16[i] = h2b16(*p16++);
1517 
1518 	p32 = (uint32_t *)p16;
1519 	for (i = 0; i < 4; i++)
1520 		sb_data->s_data32[i] = h2b32(*p32++);
1521 	p64 = (uint64_t *)p32;
1522 
1523 	for (i = 0; i < 2; i++)
1524 		sb_data->s_data64[i] = h2b64(*p64++);
1525 }
1526 
1527 /* Trace related functions */
1528 
1529 void
1530 ibcm_init_conn_trace(ibcm_state_data_t *sp)
1531 {
1532 	IBTF_DPRINTF_L5(cmlog, "ibcm_init_conn_trace: statep %p", sp);
1533 
1534 	/* Initialize trace related fields */
1535 
1536 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sp->conn_trace))
1537 	sp->conn_trace = kmem_zalloc(sizeof (ibcm_conn_trace_t), KM_SLEEP);
1538 	if ((ibcm_enable_trace & 1) == 0)
1539 		sp->conn_trace->conn_base_tm = gethrtime();
1540 	sp->conn_trace->conn_allocated_trcnt = ibcm_conn_max_trcnt;
1541 	sp->conn_trace->conn_trace_events =
1542 	    kmem_zalloc(sp->conn_trace->conn_allocated_trcnt, KM_SLEEP);
1543 	sp->conn_trace->conn_trace_event_times =
1544 	    kmem_zalloc(sp->conn_trace->conn_allocated_trcnt *
1545 	    sizeof (tm_diff_type), KM_SLEEP);
1546 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sp->conn_trace))
1547 }
1548 
1549 void
1550 ibcm_fini_conn_trace(ibcm_state_data_t *statep)
1551 {
1552 	IBTF_DPRINTF_L5(cmlog, "ibcm_fini_conn_trace: statep %p tracep %p",
1553 	    statep, statep->conn_trace);
1554 
1555 	/* free the trace data */
1556 	if (statep->conn_trace) {
1557 		if (statep->conn_trace->conn_trace_events)
1558 			kmem_free(statep->conn_trace->conn_trace_events,
1559 			    statep->conn_trace->conn_allocated_trcnt);
1560 		if (statep->conn_trace->conn_trace_event_times)
1561 			kmem_free(statep->conn_trace->conn_trace_event_times,
1562 			    statep->conn_trace->conn_allocated_trcnt *
1563 			    sizeof (tm_diff_type));
1564 
1565 		kmem_free(statep->conn_trace, sizeof (ibcm_conn_trace_t));
1566 	}
1567 }
1568 
1569 void
1570 ibcm_insert_trace(void *statep, ibcm_state_rc_trace_qualifier_t event_qualifier)
1571 {
1572 	ibcm_conn_trace_t	*conn_trace;
1573 	uint8_t			conn_trace_ind;
1574 	clock_t			time_diff;
1575 
1576 	if (!(((ibcm_state_data_t *)statep)->conn_trace))
1577 		return;
1578 
1579 	conn_trace = ((ibcm_state_data_t *)statep)->conn_trace;
1580 
1581 	if (!conn_trace->conn_trace_events)
1582 		return;
1583 
1584 	IBTF_DPRINTF_L5(cmlog, "ibcm_insert_trace: statep %p event %d",
1585 	    statep, event_qualifier);
1586 
1587 	mutex_enter(&ibcm_trace_mutex);
1588 
1589 	/* No more trace memory available, hence return */
1590 	if (conn_trace->conn_trace_ind == conn_trace->conn_allocated_trcnt) {
1591 		mutex_exit(&ibcm_trace_mutex);
1592 		return;
1593 	} else
1594 		++conn_trace->conn_trace_ind;
1595 
1596 	conn_trace_ind = conn_trace->conn_trace_ind - 1;
1597 
1598 	conn_trace->conn_trace_events[conn_trace_ind] = event_qualifier;
1599 
1600 	if ((ibcm_enable_trace & 1) == 0) {
1601 		time_diff = gethrtime() - conn_trace->conn_base_tm;
1602 		time_diff = time_diff >> 10;
1603 		if (time_diff >= TM_DIFF_MAX)
1604 			time_diff = 0;
1605 		conn_trace->conn_trace_event_times[conn_trace_ind] = time_diff;
1606 	}
1607 
1608 	mutex_exit(&ibcm_trace_mutex);
1609 
1610 	IBTF_DPRINTF_L5(cmlog, "ibcm_insert_trace: statep %p inserted event %d",
1611 	    statep, event_qualifier);
1612 }
1613 
1614 void
1615 ibcm_dump_conn_trace(void *statep)
1616 {
1617 	IBTF_DPRINTF_L5(cmlog, "ibcm_dump_conn_trace: statep %p",
1618 	    statep);
1619 
1620 	mutex_enter(&ibcm_trace_print_mutex);
1621 	ibcm_debug_buf[0] = '\0';
1622 	ibcm_dump_conn_trbuf(statep, "ibcm: ", ibcm_debug_buf,
1623 	    IBCM_DEBUG_BUF_SIZE);
1624 	if (ibcm_debug_buf[0] != '\0')
1625 		IBTF_DPRINTF_L2(cmlog, "\n%s", ibcm_debug_buf);
1626 
1627 #ifdef	DEBUG
1628 
1629 	if (ibcm_test_mode > 1)
1630 		cmn_err(CE_CONT, "IBCM DEBUG TRACE:\n%s", ibcm_debug_buf);
1631 #endif
1632 
1633 	mutex_exit(&ibcm_trace_print_mutex);
1634 }
1635 
1636 void
1637 ibcm_dump_conn_trbuf(void *statep, char *line_prefix, char *buf, int buf_size)
1638 {
1639 	ibcm_conn_trace_t	*conn_trace;
1640 	int			tr_ind;
1641 	ibcm_state_data_t	*sp;
1642 	int	cur_size = 0;	/* size of item copied */
1643 	int	rem_size;	/* remaining size in trace buffer */
1644 	int	next_data = 0;	/* location where next item copied */
1645 
1646 	if ((buf == NULL) || (buf_size <= 0))
1647 		return;
1648 
1649 	sp = (ibcm_state_data_t *)statep;
1650 
1651 	if (!sp->conn_trace)
1652 		return;
1653 
1654 	conn_trace = sp->conn_trace;
1655 
1656 	if (!conn_trace->conn_trace_events)
1657 		return;
1658 
1659 	rem_size = buf_size;
1660 
1661 	/* Print connection level global data */
1662 
1663 	/* Print statep, local comid, local qpn */
1664 	cur_size = snprintf(&buf[next_data], rem_size, "%s%s0x%p\n%s%s0x%p\n"
1665 	    "%s%s0x%x/%llx/%d\n%s%s0x%x\n%s%s0x%x/%llx\n%s%s0x%x\n%s%s%lu\n",
1666 	    line_prefix, event_str[IBCM_DISPLAY_SID], (void *)sp,
1667 	    line_prefix, event_str[IBCM_DISPLAY_CHAN], (void *)sp->channel,
1668 	    line_prefix, event_str[IBCM_DISPLAY_LCID], sp->local_comid,
1669 	    (longlong_t)sp->local_hca_guid, sp->prim_port,
1670 	    line_prefix, event_str[IBCM_DISPLAY_LQPN], sp->local_qpn,
1671 	    line_prefix, event_str[IBCM_DISPLAY_RCID], sp->remote_comid,
1672 	    (longlong_t)sp->remote_hca_guid,
1673 	    line_prefix, event_str[IBCM_DISPLAY_RQPN], sp->remote_qpn,
1674 	    line_prefix, event_str[IBCM_DISPLAY_TM], conn_trace->conn_base_tm);
1675 
1676 	rem_size = rem_size - cur_size;
1677 	if (rem_size <= 0) {
1678 		buf[buf_size-1] = '\n';
1679 		return;
1680 	}
1681 
1682 	next_data = next_data + cur_size;
1683 
1684 	for (tr_ind = 0; tr_ind < conn_trace->conn_trace_ind; tr_ind++) {
1685 		cur_size = snprintf(&buf[next_data], rem_size,
1686 		    "%s%sTM_DIFF %u\n", line_prefix,
1687 		    event_str[conn_trace->conn_trace_events[tr_ind]],
1688 		    conn_trace->conn_trace_event_times[tr_ind]);
1689 		rem_size = rem_size - cur_size;
1690 		if (rem_size <= 0) {
1691 			buf[buf_size-1] = '\n';
1692 			return;
1693 		}
1694 		next_data = next_data + cur_size;
1695 	}
1696 
1697 	buf[next_data] = '\0';
1698 	IBTF_DPRINTF_L5(cmlog, "ibcm_dump_conn_trbuf: statep %p "
1699 	    "debug buf size %d bytes", statep, next_data);
1700 }
1701 
1702 
1703 #ifdef	DEBUG
1704 
1705 void
1706 ibcm_query_qp(ibmf_handle_t ibmf_hdl, ibmf_qp_handle_t ibmf_qp)
1707 {
1708 	uint8_t		qp_port_num;
1709 	ib_qpn_t	qp_num;
1710 	ib_pkey_t	qp_pkey;
1711 	ib_qkey_t	qp_qkey;
1712 	int		ibmf_status;
1713 
1714 	if (ibmf_qp == IBMF_QP_HANDLE_DEFAULT) {
1715 		IBTF_DPRINTF_L4(cmlog, "ibcm_query_qp: QP1");
1716 		return;
1717 	}
1718 
1719 	ibmf_status =
1720 	    ibmf_query_qp(ibmf_hdl, ibmf_qp, &qp_num, &qp_pkey, &qp_qkey,
1721 	    &qp_port_num, 0);
1722 
1723 	ASSERT(ibmf_status == IBMF_SUCCESS);
1724 
1725 	IBTF_DPRINTF_L5(cmlog, "ibcm_query_qp: qpn %lx qkey %x pkey %x port %d",
1726 	    qp_num, qp_qkey, qp_pkey, qp_port_num);
1727 }
1728 
1729 /*
1730  * ibcm_dump_raw_message:
1731  *	dumps 256 bytes of data of a raw message (REP/REQ/DREQ ...)
1732  *	(can be called from the kernel debugger w/ the message pointer)
1733  *
1734  * Arguments:
1735  *	msgp	- the messages that needs to be dumped
1736  *
1737  * Return values: NONE
1738  */
1739 void
1740 ibcm_dump_raw_message(uchar_t *c)
1741 {
1742 	int	i;
1743 
1744 	for (i = 0; i < IBCM_MAD_SIZE; i += 16) {
1745 		/* print in batches of 16 chars at a time */
1746 		IBTF_DPRINTF_L4(cmlog,
1747 		    "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
1748 		    c[i], c[i + 1], c[i + 2], c[i + 3], c[i + 4], c[i + 5],
1749 		    c[i + 6], c[i + 7], c[i + 8], c[i + 9], c[i + 10],
1750 		    c[i + 11], c[i + 12], c[i + 13], c[i + 14], c[i + 15]);
1751 	}
1752 }
1753 
1754 
1755 /*
1756  * ibcm_dump_srv_rec:
1757  *	Dumps Service Records.
1758  *
1759  * Arguments:
1760  *	srv_rec	- the pointer to sa_service_record_t struct.
1761  *
1762  * Return values: NONE
1763  */
1764 void
1765 ibcm_dump_srvrec(sa_service_record_t *srv_rec)
1766 {
1767 	uint8_t		i;
1768 
1769 	IBTF_DPRINTF_L4(cmlog, "ibcm_dump_srvrec: Service Records");
1770 	IBTF_DPRINTF_L4(cmlog, "SID       : 0x%016llX", srv_rec->ServiceID);
1771 	IBTF_DPRINTF_L4(cmlog, "Svc GID   : 0x%016llX:0x%016llX",
1772 	    srv_rec->ServiceGID.gid_prefix, srv_rec->ServiceGID.gid_guid);
1773 	IBTF_DPRINTF_L4(cmlog, "Svc PKey  : 0x%X", srv_rec->ServiceP_Key);
1774 
1775 	IBTF_DPRINTF_L4(cmlog, "Svc Lease : 0x%lX", srv_rec->ServiceLease);
1776 	IBTF_DPRINTF_L4(cmlog, "Svc Key-hi: 0x%016llX", srv_rec->ServiceKey_hi);
1777 	IBTF_DPRINTF_L4(cmlog, "Svc Key-lo: 0x%016llX", srv_rec->ServiceKey_lo);
1778 	IBTF_DPRINTF_L4(cmlog, "Svc Name  : %s", srv_rec->ServiceName);
1779 	IBTF_DPRINTF_L4(cmlog, "Svc Data  : ");
1780 	for (i = 0; i < IB_SVC_DATA_LEN; i += 8) {
1781 		IBTF_DPRINTF_L4(cmlog,
1782 		    "\t 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X",
1783 		    srv_rec->ServiceData[i], srv_rec->ServiceData[i+1],
1784 		    srv_rec->ServiceData[i+2], srv_rec->ServiceData[i+3],
1785 		    srv_rec->ServiceData[i+4], srv_rec->ServiceData[i+5],
1786 		    srv_rec->ServiceData[i+6], srv_rec->ServiceData[i+7]);
1787 	}
1788 }
1789 
1790 
1791 /*
1792  * ibcm_dump_pathrec:
1793  *	Dumps Path Records.
1794  *
1795  * Arguments:
1796  *	path_rec - the pointer to sa_path_record_t struct.
1797  *
1798  * Return values: NONE
1799  */
1800 void
1801 ibcm_dump_pathrec(sa_path_record_t *path_rec)
1802 {
1803 	IBTF_DPRINTF_L5(cmlog, "Path Record:");
1804 	IBTF_DPRINTF_L5(cmlog, "SGID: (sn_prefix)  %016llX",
1805 	    path_rec->SGID.gid_prefix);
1806 	IBTF_DPRINTF_L5(cmlog, "SGID: (GUID)       %016llX",
1807 	    path_rec->SGID.gid_guid);
1808 	IBTF_DPRINTF_L5(cmlog, "DGID: (sn_prefix)  %016llX",
1809 	    path_rec->DGID.gid_prefix);
1810 	IBTF_DPRINTF_L5(cmlog, "DGID: (GUID)       %016llX",
1811 	    path_rec->DGID.gid_guid);
1812 	IBTF_DPRINTF_L5(cmlog, "SLID:              %04X", path_rec->SLID);
1813 	IBTF_DPRINTF_L5(cmlog, "DLID:              %04X", path_rec->DLID);
1814 	IBTF_DPRINTF_L5(cmlog, "Raw Traffic:       %01X", path_rec->RawTraffic);
1815 	IBTF_DPRINTF_L5(cmlog, "Flow Label:        %05X", path_rec->FlowLabel);
1816 	IBTF_DPRINTF_L5(cmlog, "Hop Limit:         %02X", path_rec->HopLimit);
1817 	IBTF_DPRINTF_L5(cmlog, "TClass:            %02X", path_rec->TClass);
1818 	IBTF_DPRINTF_L5(cmlog, "Reversible:	   %01X", path_rec->Reversible);
1819 	IBTF_DPRINTF_L5(cmlog, "Numb Paths:        %02d", path_rec->NumbPath);
1820 	IBTF_DPRINTF_L5(cmlog, "P_Key:             %04X", path_rec->P_Key);
1821 	IBTF_DPRINTF_L5(cmlog, "SL:                %02X", path_rec->SL);
1822 	IBTF_DPRINTF_L5(cmlog, "Path MTU Selector: %01X",
1823 	    path_rec->MtuSelector);
1824 	IBTF_DPRINTF_L5(cmlog, "Path MTU:          %02X", path_rec->Mtu);
1825 	IBTF_DPRINTF_L5(cmlog, "Path Rate Selector:%01X",
1826 	    path_rec->RateSelector);
1827 	IBTF_DPRINTF_L5(cmlog, "Path Rate:         %02X", path_rec->Rate);
1828 	IBTF_DPRINTF_L5(cmlog, "Packet LT Selector:%01X",
1829 	    path_rec->PacketLifeTimeSelector);
1830 	IBTF_DPRINTF_L5(cmlog, "Packet Life Time:  %d (dec)",
1831 	    path_rec->PacketLifeTime);
1832 	IBTF_DPRINTF_L5(cmlog, "Preference Bit:    %02X", path_rec->Preference);
1833 }
1834 
1835 
1836 /*
1837  * ibcm_dump_node_rec:
1838  *	Dumps Node Records.
1839  *
1840  * Arguments:
1841  *	nrec - the pointer to sa_node_record_t struct.
1842  *
1843  * Return values: NONE
1844  */
1845 void
1846 ibcm_dump_noderec(sa_node_record_t *nrec)
1847 {
1848 	IBTF_DPRINTF_L5(cmlog, "ibcm_dump_noderec: Node Info Record");
1849 	IBTF_DPRINTF_L5(cmlog, "LID       : %04X", nrec->LID);
1850 	IBTF_DPRINTF_L5(cmlog, "Base Ver  : %02X", nrec->NodeInfo.BaseVersion);
1851 	IBTF_DPRINTF_L5(cmlog, "Class Ver : %02X", nrec->NodeInfo.ClassVersion);
1852 	IBTF_DPRINTF_L5(cmlog, "Node Type : %02d", nrec->NodeInfo.NodeType);
1853 	IBTF_DPRINTF_L5(cmlog, "Num Ports : %02X", nrec->NodeInfo.NumPorts);
1854 	IBTF_DPRINTF_L5(cmlog, "SysImgGUID: %016llX",
1855 	    nrec->NodeInfo.SystemImageGUID);
1856 	IBTF_DPRINTF_L5(cmlog, "NODE GUID : %016llX", nrec->NodeInfo.NodeGUID);
1857 	IBTF_DPRINTF_L5(cmlog, "Port GUID : %016llX", nrec->NodeInfo.PortGUID);
1858 	IBTF_DPRINTF_L5(cmlog, "PartionCap: %04X", nrec->NodeInfo.PartitionCap);
1859 	IBTF_DPRINTF_L5(cmlog, "Device ID : %04X", nrec->NodeInfo.DeviceID);
1860 	IBTF_DPRINTF_L5(cmlog, "Revision  : %06X", nrec->NodeInfo.Revision);
1861 	IBTF_DPRINTF_L5(cmlog, "LocalPort#: %02X", nrec->NodeInfo.LocalPortNum);
1862 	IBTF_DPRINTF_L5(cmlog, "Vendor ID : %06X", nrec->NodeInfo.VendorID);
1863 	IBTF_DPRINTF_L5(cmlog, "Description: %s",
1864 	    (char *)&nrec->NodeDescription);
1865 }
1866 #endif
1867 
1868 
1869 /*
1870  * ibcm_ibmf_analyze_error:
1871  *	Checks IBMF status and determines appropriate ibt status.
1872  *
1873  * Arguments:
1874  *	ibmf_status - IBMF Status
1875  *
1876  * Return values:
1877  *	ibt_status_t
1878  */
1879 ibt_status_t
1880 ibcm_ibmf_analyze_error(int ibmf_status)
1881 {
1882 	if (ibt_check_failure(ibmf_status, NULL) != IBT_FAILURE_STANDARD) {
1883 		/*
1884 		 * IBMF specific failure, return special error code
1885 		 * to the client so that it can retrieve any associated ENA.
1886 		 */
1887 		return (ibmf_status);
1888 	} else {
1889 		/*
1890 		 * IBMF failed for some other reason, invalid arguments etc.
1891 		 * Analyze, log ENA with IBTF and obtain a special ibt_status_t
1892 		 * that indicates IBMF failure.
1893 		 */
1894 		if ((ibmf_status == IBMF_BAD_CLASS) ||
1895 		    (ibmf_status == IBMF_BAD_HANDLE) ||
1896 		    (ibmf_status == IBMF_BAD_QP_HANDLE) ||
1897 		    (ibmf_status == IBMF_BAD_NODE) ||
1898 		    (ibmf_status == IBMF_BAD_PORT) ||
1899 		    (ibmf_status == IBMF_BAD_VERSION) ||
1900 		    (ibmf_status == IBMF_BAD_FLAGS) ||
1901 		    (ibmf_status == IBMF_BAD_SIZE) ||
1902 		    (ibmf_status == IBMF_INVALID_GID) ||
1903 		    (ibmf_status == IBMF_INVALID_ARG) ||
1904 		    (ibmf_status == IBMF_INVALID_FIELD) ||
1905 		    (ibmf_status == IBMF_UNSUPP_METHOD) ||
1906 		    (ibmf_status == IBMF_UNSUPP_METHOD_ATTR)) {
1907 
1908 			/*
1909 			 * These errors, we should not see...
1910 			 * something really bad happened!.
1911 			 */
1912 			IBTF_DPRINTF_L2(cmlog, "ibcm_ibmf_analyze_error: "
1913 			    "Unexpected ERROR from IBMF - %d", ibmf_status);
1914 		}
1915 		return (ibt_get_module_failure(IBT_FAILURE_IBMF, 0));
1916 	}
1917 }
1918