xref: /illumos-gate/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_sm.c (revision 5974a6fc6becd7cf6c95fb5bd2cbe9967cf3c93b)
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 2007 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/callb.h>
30 
31 /*
32  * ibcm_sm.c
33  *	These routines implement the CM state machine (both ACTIVE and PASSIVE)
34  *
35  * Points to Note :
36  *
37  * o  CM uses one ibcm_hca_info_t entry per HCA  to store all the
38  *    connection state data belonging to that HCA in the AVL trees, etc.,
39  *
40  * o  There is one state structure per RC, referenced from three AVL trees
41  *    ie. the HCA active AVL tree, and the HCA passive AVL tree and HCA
42  *    passive comid tree
43  *
44  * o  SIDR state structures are stored in a linked list
45  *
46  * o  The term statep generally refers to RC, until explicitly mentioned
47  *    in the notes below
48  *
49  * o  Any thread that may access statep increments the ref_cnt. This ensures
50  *    that statep is not deleted when it is still being accessed and modified
51  *    by other threads
52  *
53  * o  Any thread that may want to search the AVL tree(s) holds the hca state
54  *    table reader lock. If it shall insert/delete a new state structure, then
55  *    the lock held is writer lock.
56  *
57  * o  Incrementing and Decrementing the ref_cnt can happen only after acquiring
58  *    statep mutex
59  *
60  * o  Deleting a statep can happen only by acquiring the hca state writer lock
61  *    and statep mutex and if ref_cnt is zero.
62  *
63  * o  Statep mutexes are used to decrease the hca state table lock holding
64  *    times. thus increasing more number of threads that can access hca
65  *    global data structures
66  *
67  * o  Statep mutexes cannot be hold for long time. They are primarily used to
68  *    check the state of statep, change it and exit the lock. Other threads
69  *    checking this statep find statep's new state, and may exit without
70  *    further processing (as the statep->state has changed).
71  *
72  * o  Statep mutex must be held while setting and unsetting the timer id
73  *    values and during untimeout
74  *
75  * Re-stating, the overall purpose of these various locks are:
76  *   - Minimize the time state table locks are held
77  *   - Writer locks are held only while inserting/deleting into trees,
78  *	so multiple readers can traverse data structures in parallel
79  *   - Minimize the time statep mutex held, so other threads entering the same
80  *	statep mutex are not held for long
81  *
82  * The CM state machine logic ensures that the statep is valid and exists
83  * when timeout callback (ibcm_timeout_cb) is called. This is ensured by
84  * cancelling timeouts on state changes, where appropriate
85  *
86  *
87  * The timeout processing is handled in the context in which the
88  * timeout callback is invoked.
89  *
90  * The CM STATE MACHINE logic flow:
91  *
92  * On an incoming MAD:-
93  *
94  * IBMF -> ibcm_process_incoming_mad
95  *	Verify and branch to one of the below connection state routines.
96  *	The callback arg from ibmf has the pointer to ibcm_hca_info_t
97  *
98  * 1. INCOMING REQ MAD
99  *
100  *	Acquire hca state table WRITER lock
101  *	Do lookup in passive AVL tree by remote qpn and remote hca guid
102  *
103  *	If (new lookup)
104  *
105  *	  create new statep, initialize key fields
106  *	  obtain new local com id, insert into hca state AVL tree
107  *	  release hca state table WRITER lock
108  *
109  *	  Initialize remaining fields
110  *	  If invalid service id,
111  *		send a REJ reply,
112  *		decr ref_cnt holding state mutex
113  *	  If existing peer conn, check guids, and break the tie
114  *	  Call the cep state transition function
115  *	  Send an RTU/REJ reply
116  *	  Check and handle for any incoming REJ's during REQ RCVD state
117  *
118  *    else if (existing lookup)
119  *
120  *	  increment refcnt holding state mutex
121  *	  release hca state table WRITER lock
122  *
123  *	  re-acquire the statep mutex
124  *	  if (statep->state is REP SENT/REJ SENT/ MRA SENT)
125  *		resend the mad
126  *	  else if established
127  *		handle the stale detection
128  *	  else
129  *		drop the mad (no processing required)
130  *	  decr statep->ref_cnt, release state mutex
131  *
132  *
133  * 2. INCOMING REP MAD
134  *
135  *    Acquire hca state READER lock
136  *    Do lookup in hca state tree by local com id
137  *    Release hca state table READER lock
138  *
139  *    if lookup does not exist
140  *	 return
141  *
142  *    if look up exists
143  *	 incr statep->ref_cnt holding state mutex
144  *
145  *    acquire the statep lock
146  *    if (state == ESTABLISHED or REJ SENt or MRA REP SENT)
147  *	  resend the MAD
148  *	  release state mutex, cancel req sent timer
149  *	  decrement ref_cnt holding the statep lock
150  *	  return
151  *
152  *    if (state == REQ_SENT or REP_WAIT)
153  *	  first, change state to REP_RCVD
154  *	  release statep lock
155  *	  cancel timers
156  *	  lookup in the passive tree by remote qpn and remote hca guid
157  *	  if entry already exists
158  *		 handle the stale detection
159  *	  else
160  *		add to the passive tree
161  *
162  *	  Initialize fields of statep
163  *	  Call the qp state transition function
164  *	  Post RTU/REJ reply
165  *	  Acquire the state mutex
166  *	  decrement the ref cnt
167  *	  release the statep lock
168  *
169  * 3. INCOMING MRA
170  *
171  *	Acquire hca state table READER lock
172  *	Do lookup in active hca state tree by local com id
173  *	Release hca state table READER lock
174  *
175  *	If lookup does not exist
176  *		return
177  *
178  *	if look up exists
179  *		 incr statep->ref_cnt holding state mutex
180  *
181  *	acquire state mutex
182  *	if (state is REQ_SENT or REP_SENT)
183  *	  change state to REP WAIT or MRA REP RCVD
184  *	  release state mutex
185  *	  cancel the current timer
186  *
187  *	  reacquire state mutex
188  *	  if (state is REP_WAIT or MRA_REP_RCVD)
189  *		set new timer, using service timeout for the first timeout
190  *    decr ref cnt, release state mutex
191  *
192  * 4. INCOMING RTU
193  *
194  *	Acquire hca state table READER lock
195  *	Do lookup in active hca state tree by local com id
196  *	Release hca state table READER lock
197  *
198  *	If lookup does not exist
199  *		return
200  *
201  *	 if look up exists
202  *		 incr statep->ref_cnt holding state mutex
203  *
204  *	acquire statep mutex
205  *	if (state == REP_SENT or MRA REP RCVD))
206  *	  change state to ESTABLISHED
207  *	  release statep mutex
208  *	  cancel timer
209  *
210  *	  Change QP state
211  *
212  *	  acquire the statep mutex
213  *	decrement the ref count
214  *	release statep mutex
215  *
216  * 5. INCOMING REJ
217  *
218  *	Acquire hca state table READER lock
219  *	Do lookup in active hca state tree by local com id
220  *	Release hca state table READER lock
221  *
222  *	If lookup does not exist
223  *		return
224  *
225  *	if look up exists
226  *		 incr statep->ref_cnt holding state mutex
227  *
228  *	if (state == REQ RCVD or REP RCVD MRA_SENT or MRA_REP_SNET)
229  *	  set statep->delete = true
230  *	  decrement the ref_cnt
231  *	  release statep mutex;
232  *
233  *    else if (state == REQ_SENT or REP SENT or MRA REP Rcvd)
234  *	 state = IBCM_STATE_DELETE
235  *	 Cancel running timers
236  *	 decrement the ref_cnt
237  *	 release state mutex
238  *	 Call the client QP handler
239  *	 delete the state data
240  *
241  * 6. INCOMING DREQ
242  *
243  *	Acquire hca state table READER lock
244  *	Do lookup in active hca state tree by local com id
245  *	Release hca state table READER lock
246  *
247  *	If lookup does not exist
248  *		return
249  *
250  *	if look up exists
251  *		 incr statep->ref_cnt holding state mutex
252  *
253  *	acquire state mutex
254  *	if (state is ESTABLISHED/DREQ SENT/TIMEWAIT)
255  *	  if state is ESTABLISHED/DREQ SENT,
256  *		change state to DREQ RECVD
257  *		start timers
258  *
259  *    send DREP reply
260  *    decr ref_cnt
261  *    release state mutex
262  *
263  * 7.  Incoming DREP
264  *
265  *	Acquire hca state table READER lock
266  *	Do lookup in active hca state tree by local com id
267  *	Release hca state table READER lock
268  *
269  *	If lookup does not exist
270  *		return
271  *
272  *	if look up exists
273  *		 incr statep->ref_cnt holding state mutex
274  *
275  *	acquire state mutex
276  *	if state is DREQ_SENT
277  *	  change state to DREP_RCVD
278  *	  cancel timer
279  *	  change state to TIMEWAIT
280  *	  set timewait timer
281  *    decr ref_cnt
282  *    release state mutex
283  *
284  * 8. Timeout handler
285  *
286  *  (for states REQ SENT/REP SENT/REJ SENT/DREQ SENT/DREP SENT/TIMEWAIT)
287  *
288  *	 acquire the statep mutex
289  *
290  *	 if (set state != stored_state)
291  *	    The thread that changed the state is responsible for any cleanup
292  *	    decrement ref cnt
293  *	    release statep mutex
294  *	    return
295  *	 else if (statep's state == REJ SENT)
296  *		change state to DELETE
297  *		decrement ref cnt
298  *		release statep mutex
299  *		delete statep
300  *		return
301  *	 else if (state == TIME WAIT)
302  *		do the time wait state processing
303  *		decrement ref cnt
304  *		change state to DELETE
305  *		release statep mutex
306  *		delete statep, and also QP
307  *	 else if (remaining retry cnt > 0)
308  *		resend the mad
309  *		decrement ref cnt
310  *		release statep mutex
311  *	 else if (state == rep sent or req sent or mra rep rcvd or rep wait)
312  *		(retry counter expired)
313  *		change state to REJ SENT (No one shall delete in REJ SENT)
314  *		decrement the ref_cnt
315  *		release the statep mutex
316  *		Post REJ MAD
317  *		cv_signal anyone blocking
318  *		Invoke client handler
319  *	 else if state == DREQ_SENT
320  *		change state to TIME WAIT
321  *		decrement the ref cnt
322  *		set a timer for time wait time
323  *		release the statep mutex
324  *
325  *
326  * SIDR processing
327  *
328  * 9. INCOMING SIDR_REQ MAD
329  *
330  *    Figure out LID/GID
331  *    Do lookup in SIDR LIST based on LID, GID, grh_exists and req_id
332  *    increment ud_statep->ud_ref_cnt
333  *
334  *    If (new lookup)
335  *
336  *	  validate service id, and the create new statep,
337  *	  initialize key fields
338  *	  do a lookup based on service id
339  *	  if service_id_lookup returns exists
340  *		set sidr_status to QPN_VALID
341  *	  else
342  *		set sidr_status to SID_INVALID
343  *	  post SIDR_REP mad
344  *	  decr ud_statep->ud_ref_cnt, release ud_state_mutex
345  *
346  *    else if (existing lookup)
347  *
348  *	  if (ud_statep->ud_state is SIDR_REP_SENT)
349  *		resend the mad
350  *
351  *	  decr ud_statep->ud_ref_cnt, release ud_state_mutex
352  *
353  *
354  * 10. INCOMING SIDR_REP MAD
355  *
356  *    Figure out LID/GID
357  *    Do lookup in SIDR LIST based on LID, GID, grh_exists and req_id
358  *    increment ud_statep->ud_ref_cnt
359  *
360  *    if look up doesn't exists
361  *	  return
362  *
363  *    if (state == SIDR_REQ_SENT)
364  *	  first, change state to SIDR_REP_RCVD
365  *	  release statep lock
366  *	  cancel timers
367  *	  cv_signal anyone blocking
368  *	  release the statep lock
369  *	  extract return args
370  *	  destroy the statep
371  *
372  * 11. Timeout handler
373  *
374  *  (for states SIDR_REQ_SENT/SIDR_REP_SENT)
375  *
376  *	 acquire the statep mutex
377  *
378  *	 if (statep's state == SIDR_REP_SENT SENT)
379  *		change state to DELETE
380  *		decrement ref cnt
381  *		release statep mutex
382  *		delete statep
383  *		return
384  *	 else if (remaining retry cnt > 0 and state is SIDR_REQ_SENT)
385  *		resend the mad
386  *		decrement ref cnt
387  *		release statep mutex
388  *	 else if (state == SIDR_REQ_SENT)
389  *		(retry counter expired)
390  *		change state to DELETE
391  *		decrement the ref_cnt
392  *		the statep mutex
393  *		cv_signal anyone blocking
394  *		Invoke client handler
395  *		delete statep
396  */
397 
398 /* Function prototypes */
399 static void		ibcm_set_primary_adds_vect(ibcm_state_data_t *,
400 			    ibt_adds_vect_t *, ibcm_req_msg_t *);
401 static void		ibcm_set_alt_adds_vect(ibcm_state_data_t *,
402 			    ibt_adds_vect_t *, ibcm_req_msg_t *);
403 static ibt_status_t	ibcm_set_primary_cep_path(ibcm_state_data_t *,
404 			    ibt_cep_path_t *, ibcm_req_msg_t *);
405 static ibt_status_t	ibcm_set_alt_cep_path(ibcm_state_data_t *,
406 			    ibt_cep_path_t *, ibcm_req_msg_t *);
407 static ibt_status_t	ibcm_invoke_qp_modify(ibcm_state_data_t *,
408 			    ibcm_req_msg_t *, ibcm_rep_msg_t *);
409 static ibt_status_t	ibcm_invoke_rtu_qp_modify(ibcm_state_data_t *,
410 			    ib_time_t, ibcm_rep_msg_t *);
411 static ibcm_status_t	ibcm_sidr_req_ud_handler(ibcm_ud_state_data_t *,
412 			    ibcm_sidr_req_msg_t *, ibcm_mad_addr_t *,
413 			    ibt_sidr_status_t *);
414 static void		ibcm_sidr_rep_ud_handler(ibcm_ud_state_data_t *,
415 			    ibcm_sidr_rep_msg_t *);
416 static void		ibcm_handler_conn_fail(ibcm_state_data_t *,
417 			    uint8_t cf_code, uint8_t cf_msg,
418 			    ibt_cm_reason_t rej_reason, uint8_t *,
419 			    ibt_priv_data_len_t);
420 static void		ibcm_build_n_post_rej_mad(uint8_t *input_madp,
421 			    ib_com_id_t, ibcm_mad_addr_t *, int, uint16_t);
422 static void		ibcm_post_drep_mad(ibcm_state_data_t *);
423 
424 static ibcm_status_t	ibcm_verify_req_gids_and_svcid(
425 			    ibcm_state_data_t *statep,
426 			    ibcm_req_msg_t *cm_req_msgp);
427 
428 static void		ibcm_timeout_client_cb(ibcm_state_data_t *statep);
429 static void		ibcm_ud_timeout_client_cb(
430 			    ibcm_ud_state_data_t *ud_statep);
431 
432 static void		ibcm_process_dreq_timeout(ibcm_state_data_t *statep);
433 
434 static void		ibcm_fill_adds_from_lap(ibt_adds_vect_t *adds,
435 			    ibcm_lap_msg_t *lap_msg, ibcm_mode_t mode);
436 
437 static void		ibcm_post_stored_apr_mad(ibcm_state_data_t *statep,
438 			    uint8_t *input_madp);
439 
440 static ibcm_status_t	ibcm_set_qp_from_apr(ibcm_state_data_t *statep,
441 			    ibcm_lap_msg_t *lap_msg);
442 
443 static boolean_t	ibcm_compare_prim_alt_paths(ibt_adds_vect_t *prim,
444 			    ibt_adds_vect_t *alt);
445 
446 static void		ibcm_process_get_classport_info(ibcm_hca_info_t *hcap,
447 			    uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr);
448 
449 static void		ibcm_decode_classport_info(ibcm_hca_info_t *hcap,
450 			    uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr);
451 
452 static void		ibcm_post_rej_ver_mismatch(uint8_t *input_madp,
453 			    ibcm_mad_addr_t *cm_mad_addr);
454 
455 static void		ibcm_init_clp_to_mad(ibcm_classportinfo_msg_t *clp,
456 			    ibt_redirect_info_t *rinfo);
457 
458 static void		ibcm_init_clp_from_mad(ibcm_classportinfo_msg_t *clp,
459 			    ibt_redirect_info_t *rinfo);
460 
461 static void		ibcm_copy_addl_rej(ibcm_state_data_t *statep,
462 			    ibcm_rej_msg_t *rej_msgp,
463 			    ibt_cm_conn_failed_t *failed);
464 
465 static void		ibcm_return_open_data(ibcm_state_data_t *statep,
466 			    ibcm_rep_msg_t *rep_msgp,
467 			    ibt_cm_reason_t reject_reason);
468 
469 /* limit the number of taskq threads to handle received MADs. */
470 int ibcm_recv_tasks = 0;
471 int ibcm_max_recv_tasks = 24;
472 int ibcm_recv_timeouts = 0;
473 
474 /*
475  * Tunable MAX MRA Service Timeout value in MicroSECONDS.
476  *	0 - Tunable parameter not used.
477  *
478  *	Ex:   60000000 - Max MRA Service Delay is 60 Seconds.
479  */
480 clock_t ibcm_mra_service_timeout_max = 0;
481 
482 #ifdef	DEBUG
483 
484 static void			print_modify_qp(char *prefix,
485 				    ibt_qp_hdl_t ibt_qp,
486 				    ibt_cep_modify_flags_t flags,
487 				    ibt_qp_info_t *qp_attr);
488 #endif
489 
490 /*	Warlock annotations */
491 
492 _NOTE(READ_ONLY_DATA(ibt_arej_info_u))
493 
494 /*
495  * ibcm_process_incoming_mad:
496  *	The CM callback that is invoked by IBMF, when a valid CM MAD arrives
497  *	on any of the registered ibmf handles by CM.
498  *
499  *	It is assumed that the incoming MAD (except for incoming REQ) belongs
500  *	to a connection on the HCA, on which the MAD is received.
501  *	The IBMF callback arg specifies ibcm_hca_info_t
502  *
503  * NOTE: IBMF always invokes ibcm_recv_cb() in a taskq. CM does some memory
504  * allocations and invoke ibcm_sm_funcs_tbl[i]() in the same taskq.
505  *
506  * INPUTS:
507  *	ibmf_handle	- IBMF Handle
508  *	args		- from IBMF. Is a ptr to ibcm_hca_info_t
509  *	status		- Callback status. Is mostly IBMF_SUCCESS
510  *	madbuf		- IBMF allocated MAD buffer (CM should free it)
511  *	madaddr		- IBMF MAD's address
512  *	grhvalid	- If GRH is valid or not
513  *
514  * RETURN VALUES: NONE
515  */
516 void
517 ibcm_process_incoming_mad(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
518     void *args)
519 {
520 	uint8_t			method;		/* Method type in MAD hdr */
521 	ib_mad_hdr_t		*in_mad_hdr;	/* Incoming MAD's header */
522 	ibcm_hca_info_t		*hcap;		/* pointer to HCA entry */
523 	ibcm_port_info_t	*portp;
524 	ibcm_mad_addr_t		*cm_mad_addr;	/* MAD address information */
525 	ibcm_event_type_t	attr_id;	/* Attribute ID in MAD hdr */
526 	ibcm_mad_addr_t		loc_mad_addr;	/* MAD address information */
527 	ibcm_qp_list_t		*cm_qp_entry;
528 	int			ibmf_status;
529 
530 
531 	/* Noticed that IBMF always calls with IBMF_SUCCESS, but still check */
532 	if (msgp->im_msg_status != IBMF_SUCCESS) {
533 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
534 		    "bad status %x", msgp->im_msg_status);
535 		/* IBMF allocates Input MAD, so free it here */
536 		if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
537 		    IBMF_SUCCESS)
538 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
539 			    "ibmf_free_msg failed %d", ibmf_status);
540 		return;
541 	}
542 
543 	/* Get the HCA entry pointer */
544 	cm_qp_entry = (ibcm_qp_list_t *)args;
545 
546 	IBTF_DPRINTF_L5(cmlog, "ibcm_process_incoming_mad: ibmf_hdl %p "
547 	    "msg %p args %p", ibmf_handle, msgp, args);
548 
549 #ifdef	DEBUG
550 	if (ibcm_test_mode > 1)
551 		ibcm_query_qp(ibmf_handle, cm_qp_entry->qp_cm);
552 #endif
553 
554 	portp = cm_qp_entry->qp_port;
555 	hcap = portp->port_hcap;
556 
557 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: CM MAD on "
558 	    "port %d", portp->port_num);
559 
560 	/* Increment hca ref cnt, if HCA is in attached state, else fail */
561 	if (ibcm_inc_hca_acc_cnt(hcap) != IBCM_SUCCESS) {
562 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
563 		    "hca not in attach state");
564 		/* IBMF allocates Input MAD, and ibcm free's it */
565 		if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
566 		    IBMF_SUCCESS)
567 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
568 			    "ibmf_free_msg failed %d", ibmf_status);
569 		return;
570 	}
571 
572 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cm_mad_addr))
573 
574 	/* allocate memory for internal MAD address buffer */
575 	cm_mad_addr = &loc_mad_addr;
576 	bzero(cm_mad_addr, sizeof (ibcm_mad_addr_t));
577 
578 	cm_mad_addr->port_num = portp->port_num;
579 
580 	/* initialize cm_mad_addr field(s) */
581 	in_mad_hdr = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
582 
583 	if (in_mad_hdr->MgmtClass != MAD_MGMT_CLASS_COMM_MGT) {
584 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
585 		    "bad mgmt class %x", in_mad_hdr->MgmtClass);
586 		if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
587 		    IBMF_SUCCESS)
588 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
589 			    "ibmf_free_msg failed %d", ibmf_status);
590 		ibcm_dec_hca_acc_cnt(hcap);
591 		return;
592 	}
593 
594 	cm_mad_addr->rcvd_addr = msgp->im_local_addr;
595 	if (msgp->im_msg_flags & IBMF_MSG_FLAGS_GLOBAL_ADDRESS) {
596 		cm_mad_addr->grh_hdr = msgp->im_global_addr;
597 		cm_mad_addr->grh_exists = B_TRUE;
598 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_incoming_mad: "
599 		    "CM recv GID GUID %llX sender GID GUID %llX",
600 		    msgp->im_global_addr.ig_recver_gid.gid_guid,
601 		    msgp->im_global_addr.ig_sender_gid.gid_guid);
602 	}
603 
604 	/* Save IBMF handle and ibmf qp related information */
605 	cm_mad_addr->ibmf_hdl = ibmf_handle;
606 	cm_mad_addr->cm_qp_entry = cm_qp_entry;
607 
608 	/* IBMF does not initialize ia_p_key for non-QP1's */
609 	if (cm_qp_entry->qp_cm != IBMF_QP_HANDLE_DEFAULT)
610 		cm_mad_addr->rcvd_addr.ia_p_key = cm_qp_entry->qp_pkey;
611 
612 	if (cm_mad_addr->rcvd_addr.ia_p_key & 0x8000)
613 		IBTF_DPRINTF_L5(cmlog, "ibcm_process_incoming_mad: PKEY %x",
614 		    cm_mad_addr->rcvd_addr.ia_p_key);
615 	else
616 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: CM MAD "
617 		    "arrived from limited PKEY %x",
618 		    cm_mad_addr->rcvd_addr.ia_p_key);
619 
620 	/* Retrieve the method and Attr-Id from generic mad header */
621 	method = in_mad_hdr->R_Method;
622 	attr_id = b2h16(in_mad_hdr->AttributeID);
623 
624 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: "
625 	    "Method %x Attribute %x", method, attr_id);
626 
627 	if (in_mad_hdr->ClassVersion != IBCM_MAD_CLASS_VERSION) {
628 
629 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
630 		    "unsupported ibcm class version %x",
631 		    in_mad_hdr->ClassVersion);
632 
633 		if (attr_id == (IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID))
634 			ibcm_post_rej_ver_mismatch(
635 			    (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
636 
637 		if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
638 		    IBMF_SUCCESS)
639 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
640 			    "ibmf_free_msg failed %d", ibmf_status);
641 		ibcm_dec_hca_acc_cnt(hcap);
642 		return;
643 	}
644 
645 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: "
646 	    "Transaction Id 0x%llX", b2h64(in_mad_hdr->TransactionID));
647 
648 #ifdef	DEBUG
649 	ibcm_decode_tranid(b2h64(in_mad_hdr->TransactionID), NULL);
650 #endif
651 
652 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cm_mad_addr))
653 
654 	/*
655 	 * The following are valid combination of Method type
656 	 * and attribute id in the received MAD :-
657 	 *	o ClassPortInfo with Get method
658 	 *	o CM messages with Send method
659 	 */
660 	if ((attr_id == MAD_ATTR_ID_CLASSPORTINFO) &&
661 	    ((method == MAD_METHOD_GET) ||
662 	    (method == MAD_METHOD_GET_RESPONSE))) {
663 		if (method == MAD_METHOD_GET)
664 			ibcm_process_get_classport_info(hcap,
665 			    (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
666 		else if (method == MAD_METHOD_GET_RESPONSE)
667 			ibcm_decode_classport_info(hcap,
668 			    (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
669 	} else if ((attr_id >= IBCM_ATTR_BASE_ID) &&
670 	    (attr_id < (IBCM_ATTR_BASE_ID + IBCM_MAX_EVENTS)) &&
671 	    (method == MAD_METHOD_SEND)) {
672 
673 		attr_id -= IBCM_ATTR_BASE_ID;	/* figure out CM message id */
674 
675 		ASSERT(msgp->im_msgbufs_recv.im_bufs_mad_hdr != NULL);
676 
677 		/* Call the CM process connection state function */
678 		ibcm_sm_funcs_tbl[attr_id](hcap,
679 		    (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
680 	} else {
681 		/*
682 		 * Any other combination of method and attribute are invalid,
683 		 * hence drop the MAD
684 		 */
685 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
686 		    "unknown Method %x or Attribute %x", method, attr_id);
687 	}
688 
689 	/* decrement the hcap access reference count */
690 	ibcm_dec_hca_acc_cnt(hcap);
691 
692 	/* ASSERT(NO_LOCKS_HELD); */
693 
694 	/* free up ibmf msgp  */
695 	if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) != IBMF_SUCCESS)
696 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
697 		    "ibmf_free_msg failed %d", ibmf_status);
698 }
699 
700 /*
701  * Structure to carry the arguments from ibcm_recv_cb() to
702  * ibcm_recv_incoming_mad() via taskq_dispatch
703  */
704 typedef struct ibcm_taskq_args_s {
705 	ibmf_handle_t	tq_ibmf_handle;
706 	ibmf_msg_t	*tq_ibmf_msgp;
707 	void		*tq_args;
708 } ibcm_taskq_args_t;
709 
710 #define	IBCM_RECV_MAX	128
711 ibcm_taskq_args_t ibcm_recv_array[IBCM_RECV_MAX + 1];
712 int ibcm_get, ibcm_put;
713 int ibcm_recv_total;
714 int ibcm_recv_queued;
715 
716 _NOTE(READ_ONLY_DATA(ibcm_taskq_args_t))
717 
718 static int
719 ibcm_recv_dequeue(ibmf_handle_t *ibmf_handlep, ibmf_msg_t **msgpp, void **argsp)
720 {
721 	ibcm_taskq_args_t *tq;
722 
723 	if (ibcm_put == ibcm_get)
724 		return (0);
725 
726 	if (++ibcm_get >= IBCM_RECV_MAX)
727 		ibcm_get = 0;
728 	tq = ibcm_recv_array + ibcm_get;
729 	*ibmf_handlep = tq->tq_ibmf_handle;
730 	*msgpp = tq->tq_ibmf_msgp;
731 	*argsp = tq->tq_args;
732 	return (1);
733 }
734 
735 static int
736 ibcm_recv_enqueue(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
737 {
738 	int next;
739 	ibcm_taskq_args_t *tq;
740 
741 	ASSERT(MUTEX_HELD(&ibcm_recv_mutex));
742 	next = ibcm_put + 1;
743 	if (next >= IBCM_RECV_MAX)
744 		next = 0;
745 	if (next != ibcm_get) {
746 		ibcm_recv_queued++;
747 		ibcm_put = next;
748 		tq = ibcm_recv_array + next;
749 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tq))
750 		tq->tq_ibmf_handle = ibmf_handle;
751 		tq->tq_ibmf_msgp = msgp;
752 		tq->tq_args = args;
753 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*tq))
754 		return (1);
755 	} else {
756 		return (0);
757 	}
758 }
759 
760 void
761 ibcm_drop_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp)
762 {
763 	int ibmf_status;
764 
765 	IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: discarding MAD");
766 
767 	if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) != IBMF_SUCCESS)
768 		IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: "
769 		    "ibmf_free_msg failed %d", ibmf_status);
770 }
771 
772 /*
773  * Processing done in taskq thread.
774  *
775  * Calls ibcm_process_incoming_mad with all function arguments extracted
776  * from args.  Afterwards, check for queued requests.
777  */
778 static void
779 ibcm_recv_task(void *args)
780 {
781 	ibcm_taskq_args_t *taskq_args;
782 	ibmf_handle_t ibmf_handle;
783 	ibmf_msg_t *msgp;
784 
785 	taskq_args = (ibcm_taskq_args_t *)args;
786 
787 	IBTF_DPRINTF_L4(cmlog, "ibcm_recv_task: Processing incoming MAD"
788 	    " via taskq");
789 
790 	ibcm_process_incoming_mad(taskq_args->tq_ibmf_handle,
791 	    taskq_args->tq_ibmf_msgp, taskq_args->tq_args);
792 
793 	kmem_free(taskq_args, sizeof (ibcm_taskq_args_t));
794 
795 	/* process queued entries before giving up this thread */
796 	mutex_enter(&ibcm_recv_mutex);
797 	while (ibcm_recv_dequeue(&ibmf_handle, &msgp, &args)) {
798 		mutex_exit(&ibcm_recv_mutex);
799 		ibcm_process_incoming_mad(ibmf_handle, msgp, args);
800 		mutex_enter(&ibcm_recv_mutex);
801 	}
802 	--ibcm_recv_tasks;
803 	mutex_exit(&ibcm_recv_mutex);
804 }
805 
806 static void
807 ibcm_recv_timeout_cb(void *args)
808 {
809 	ibcm_taskq_args_t *tq = (ibcm_taskq_args_t *)args;
810 	int rv = 1;
811 
812 	mutex_enter(&ibcm_recv_mutex);
813 	ibcm_recv_timeouts--;
814 	if (ibcm_recv_tasks == 0) {
815 		ibcm_recv_tasks++;
816 		mutex_exit(&ibcm_recv_mutex);
817 		if (taskq_dispatch(ibcm_taskq, ibcm_recv_task, tq,
818 		    TQ_NOQUEUE | TQ_NOSLEEP) == 0) {
819 			mutex_enter(&ibcm_recv_mutex);
820 			if (--ibcm_recv_tasks == 0) {
821 				(void) timeout(ibcm_recv_timeout_cb, tq, 1);
822 				ibcm_recv_timeouts++;
823 			} else {
824 				rv = ibcm_recv_enqueue(tq->tq_ibmf_handle,
825 				    tq->tq_ibmf_msgp, tq->tq_args);
826 				kmem_free(tq, sizeof (*tq));
827 			}
828 			mutex_exit(&ibcm_recv_mutex);
829 		}
830 	} else {
831 		/*
832 		 * one or more taskq threads are running now
833 		 * so just try to enqueue this one.
834 		 */
835 		rv = ibcm_recv_enqueue(tq->tq_ibmf_handle,
836 		    tq->tq_ibmf_msgp, tq->tq_args);
837 		kmem_free(tq, sizeof (*tq));
838 		mutex_exit(&ibcm_recv_mutex);
839 	}
840 	if (rv == 0)
841 		ibcm_drop_msg(tq->tq_ibmf_handle, tq->tq_ibmf_msgp);
842 }
843 
844 /*
845  * Dispatch to taskq if we're not using many, else just queue it
846  * and have the taskq thread pick it up.  Return 0 if we're dropping it.
847  */
848 static int
849 ibcm_recv_add_one(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
850 {
851 	int rv;
852 	ibcm_taskq_args_t *tq;
853 
854 	mutex_enter(&ibcm_recv_mutex);
855 	ibcm_recv_total++;
856 	if (ibcm_recv_tasks >= ibcm_max_recv_tasks) { /* just queue this one */
857 		rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
858 		mutex_exit(&ibcm_recv_mutex);
859 		return (rv);
860 	} else {
861 		ibcm_recv_tasks++; /* dispatch this one to a taskq thread */
862 		mutex_exit(&ibcm_recv_mutex);
863 		tq = kmem_alloc(sizeof (*tq), KM_NOSLEEP);
864 		if (tq == NULL) {
865 			mutex_enter(&ibcm_recv_mutex);
866 			if (--ibcm_recv_tasks > 0)
867 				rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
868 			else	/* don't enqueue if no threads are running */
869 				rv = 0;
870 			mutex_exit(&ibcm_recv_mutex);
871 			return (rv);
872 		}
873 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tq))
874 		tq->tq_ibmf_handle = ibmf_handle;
875 		tq->tq_ibmf_msgp = msgp;
876 		tq->tq_args = args;
877 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*tq))
878 		if (taskq_dispatch(ibcm_taskq, ibcm_recv_task, tq,
879 		    TQ_NOQUEUE | TQ_NOSLEEP) == 0) {	/* dispatch failed */
880 			mutex_enter(&ibcm_recv_mutex);
881 			if (--ibcm_recv_tasks == 0) {
882 				/* try the dispatch again, after a tick */
883 				(void) timeout(ibcm_recv_timeout_cb, tq, 1);
884 				ibcm_recv_timeouts++;
885 				rv = 1;	/* indicate success */
886 			} else {
887 				rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
888 				kmem_free(tq, sizeof (*tq));
889 			}
890 			mutex_exit(&ibcm_recv_mutex);
891 			return (rv);
892 		} else {
893 			return (1);
894 		}
895 	}
896 }
897 
898 /*
899  * ibcm_recv_cb:
900  *	The CM callback that is invoked by IBMF, when a valid CM MAD arrives
901  *	on any of the registered ibmf handles by CM.
902  *
903  * INPUTS:
904  *	ibmf_handle	- IBMF Handle
905  *	msgp		- IBMF msg containing the MAD (allocated by IBMF)
906  *	args		- Ptr to ibcm_hca_info_t
907  *
908  * RETURN VALUES: NONE
909  */
910 void
911 ibcm_recv_cb(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
912 {
913 	if (ibcm_recv_add_one(ibmf_handle, msgp, args) == 0)
914 		ibcm_drop_msg(ibmf_handle, msgp);
915 }
916 
917 /*
918  * ibcm_process_req_msg:
919  *	PASSIVE SIDE CM
920  *	Called from ibcm_process_incoming_mad on reception of a REQ message
921  *
922  * Description:
923  * 	If it a new REQ (not duplicate)
924  *		creates a new state structure in passive connection mode
925  *		populate state structure fields
926  *		inserts state structure in hca active and passive trees
927  *		validates service id
928  *		validates primary and alternate lid/gid in REQ,
929  *		calls QP state transition function
930  *		generates REP/REJ response
931  *		stores the response MAD in state structure for future re-sends
932  *		initializes timers as required
933  *	If a duplicate REQ, action depends upon current state in the state
934  *	structure
935  *
936  * INPUTS:
937  *	hcap		- HCA entry ptr
938  *	input_madp	- CM MAD that is input to this function
939  *	cm_mad_addr	- Address information for the MAD
940  *
941  * RETURN VALUE:
942  *	NONE
943  */
944 void
945 ibcm_process_req_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
946     ibcm_mad_addr_t *cm_mad_addr)
947 {
948 	ibt_priv_data_len_t	arej_info_len = 0;
949 	ib_qpn_t		remote_qpn;
950 	ib_guid_t		remote_hca_guid;
951 	ib_com_id_t		remote_comid;
952 	ib_com_id_t		local_comid;
953 	ibcm_status_t		state_lookup_status;
954 	ibcm_status_t		comid_lookup_status;
955 	ibcm_status_t		response;
956 	ibcm_req_msg_t		*req_msgp =
957 	    (ibcm_req_msg_t *)&input_madp[IBCM_MAD_HDR_SIZE];
958 	ibt_cm_reason_t		reject_reason = IBT_CM_SUCCESS;
959 	ibcm_state_data_t	*statep;
960 	ibcm_state_data_t	*stale_statep = NULL;
961 	ibcm_status_t		svc_gid_check;
962 	uint32_t		psn24_timeout5_retry3;
963 	ibt_tran_srv_t		trans;
964 
965 	IBTF_DPRINTF_L5(cmlog, "ibcm_process_req_msg(%p, %p, %p)",
966 	    hcap, input_madp, cm_mad_addr);
967 
968 	/*
969 	 * Lookup for an existing state structure or create a new state struct
970 	 * If there is no entry, the lookup function also allocates a new
971 	 * state structure and inserts in the table, initializes remote qpn
972 	 * and hca guid from REQ
973 	 */
974 	remote_hca_guid = b2h64(req_msgp->req_local_ca_guid);
975 	remote_qpn = b2h32(req_msgp->req_local_qpn_plus) >> 8;
976 	remote_comid = b2h32(req_msgp->req_local_comm_id);
977 
978 	IBCM_DUMP_RAW_MSG((uchar_t *)input_madp);
979 
980 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_comid = %x"
981 	    " remote_qpn = %x", remote_comid, remote_qpn);
982 
983 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_hcaguid = %llX",
984 	    remote_hca_guid);
985 
986 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
987 
988 new_req:
989 	/* allocate the local_comid before proceeding */
990 	if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
991 		ibcm_build_n_post_rej_mad(input_madp,
992 		    b2h32(req_msgp->req_local_comm_id), cm_mad_addr,
993 		    IBT_CM_FAILURE_REQ, IBT_CM_NO_RESC);
994 		return;
995 	}
996 
997 	/* allocate ibcm_state_data_t before grabbing the WRITER lock */
998 	statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
999 
1000 	rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
1001 
1002 	/* NOTE that only a writer lock is held here */
1003 
1004 	state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REQ,
1005 	    local_comid, remote_qpn, remote_hca_guid, hcap, &statep);
1006 
1007 	if (state_lookup_status == IBCM_LOOKUP_NEW) {
1008 		/* seeing the REQ request for the first time */
1009 
1010 		mutex_enter(&statep->state_mutex);
1011 		/* Release the state table lock */
1012 		rw_exit(&hcap->hca_state_rwlock);
1013 
1014 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: New statep 0x%p"
1015 		    " created", statep);
1016 
1017 		psn24_timeout5_retry3 = b2h32(req_msgp->req_starting_psn_plus);
1018 
1019 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1020 
1021 		/* if ibmf msg allocation fails, delete the statep */
1022 		if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1023 		    &statep->stored_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1024 
1025 			IBCM_REF_CNT_DECR(statep);
1026 			statep->state = IBCM_STATE_DELETE;
1027 			mutex_exit(&statep->state_mutex);
1028 			/* HCA res cnt decremented via ibcm_delete_state_data */
1029 			ibcm_inc_hca_res_cnt(hcap);
1030 			ibcm_delete_state_data(statep);
1031 			return;
1032 		}
1033 
1034 		/* Allocate dreq_msg buf to be used during teardown. */
1035 		if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1036 		    &statep->dreq_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1037 
1038 			IBCM_REF_CNT_DECR(statep);
1039 			statep->state = IBCM_STATE_DELETE;
1040 			mutex_exit(&statep->state_mutex);
1041 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1042 			    "statep 0x%p: Failed to allocate dreq_msg", statep);
1043 
1044 			/* HCA res cnt decremented via ibcm_delete_state_data */
1045 			ibcm_inc_hca_res_cnt(hcap);
1046 			ibcm_delete_state_data(statep);
1047 			return;
1048 		}
1049 
1050 		/* initialize some "statep" fields */
1051 		statep->mode		= IBCM_PASSIVE_MODE;
1052 		statep->hcap		= hcap;
1053 		statep->remote_comid	= remote_comid;
1054 		statep->svcid		= b2h64(req_msgp->req_svc_id);
1055 
1056 		/*
1057 		 * get the remote_ack_delay, etc.
1058 		 */
1059 		statep->remote_ack_delay =
1060 		    ibt_ib2usec(req_msgp->req_primary_localtime_plus >> 3);
1061 		statep->cep_retry_cnt = psn24_timeout5_retry3 & 0x7;
1062 
1063 		/*
1064 		 * get the req_max_cm_retries
1065 		 */
1066 		statep->max_cm_retries = req_msgp->req_max_cm_retries_plus >> 4;
1067 		statep->remaining_retry_cnt = statep->max_cm_retries;
1068 
1069 		/* Approximate pkt life time for now */
1070 		statep->pkt_life_time = statep->remote_ack_delay/2;
1071 
1072 		/* Passive side timer is set to LocalCMRespTime in REQ */
1073 		statep->timer_value =
1074 		    ibt_ib2usec(psn24_timeout5_retry3 >> 3 & 0x1f);
1075 
1076 		statep->starting_psn = psn24_timeout5_retry3 >> 8;
1077 
1078 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: statep 0x%p "
1079 		    "active cep timeout(usec) = %u",
1080 		    statep, statep->remote_ack_delay);
1081 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1082 		    "passive timer(usec) = %u", statep->timer_value);
1083 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1084 		    "approx pkt lt(usec)= %u ", statep->pkt_life_time);
1085 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1086 		    "max cm retries %u", statep->max_cm_retries);
1087 
1088 		/* The reply ie., REP/REJ transaction id copied from REQ */
1089 		IBCM_OUT_HDRP(statep->stored_msg)->TransactionID =
1090 		    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
1091 
1092 		/*
1093 		 * Initialize the stale clock. Any other REQ
1094 		 * messages on this statep are considered as duplicate
1095 		 * if they arrive within stale clock
1096 		 * ibcm_adj_btime is used to offset for retry REQ's
1097 		 * arriving  just after expected retry clock
1098 		 */
1099 		statep->stale_clock = gethrtime() +
1100 		    (hrtime_t)(ibcm_adj_btime  * 1000000000) +
1101 		    (hrtime_t)statep->remote_ack_delay *
1102 		    (statep->max_cm_retries * (1000 / 2));
1103 
1104 		mutex_exit(&statep->state_mutex);
1105 
1106 		ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_REQ);
1107 
1108 		/* Increment the hca's resource count */
1109 		ibcm_inc_hca_res_cnt(hcap);
1110 
1111 		ibcm_build_reply_mad_addr(cm_mad_addr,
1112 		    &statep->stored_reply_addr);
1113 
1114 		if (statep->stored_reply_addr.cm_qp_entry == NULL) {
1115 
1116 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1117 			    "statep 0x%p cm_qp_entry alloc failed", statep);
1118 
1119 			/*
1120 			 * Not much choice. CM MADs cannot go on QP1, not even
1121 			 * REJ. Hence delete state data and go away silently.
1122 			 * The remote will timeout after repeated attempts
1123 			 */
1124 			mutex_enter(&statep->state_mutex);
1125 			IBCM_REF_CNT_DECR(statep);
1126 			statep->state = IBCM_STATE_DELETE;
1127 			mutex_exit(&statep->state_mutex);
1128 
1129 			ibcm_delete_state_data(statep);
1130 			return;
1131 		}
1132 
1133 		stale_statep = statep;
1134 		rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
1135 		comid_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REQ_STALE,
1136 		    remote_comid, 0, remote_hca_guid, hcap, &stale_statep);
1137 		rw_exit(&hcap->hca_state_rwlock);
1138 
1139 		if (comid_lookup_status == IBCM_LOOKUP_EXISTS) {
1140 
1141 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1142 			    "dup comid %x stale_statep 0x%p statep 0x%p",
1143 			    remote_comid, stale_statep, statep);
1144 
1145 			ibcm_insert_trace(stale_statep,
1146 			    IBCM_TRACE_STALE_DETECT);
1147 
1148 			/* Send a REJ with duplicate com id */
1149 			ibcm_post_rej_mad(statep, IBT_CM_DUP_COM_ID,
1150 			    IBT_CM_FAILURE_REQ, NULL, 0);
1151 
1152 			/*
1153 			 * Don't free the ibmf msg, if stale_statep is not in
1154 			 * ESTABLISHED state, because probability is very less.
1155 			 * ibmf msg shall be deleted along with statep
1156 			 */
1157 
1158 			/*
1159 			 * if stale_statep is in established state, process
1160 			 * stale connection handling on stale_statep
1161 			 */
1162 			mutex_enter(&stale_statep->state_mutex);
1163 			if (stale_statep->state == IBCM_STATE_ESTABLISHED) {
1164 
1165 				stale_statep->state =
1166 				    IBCM_STATE_TRANSIENT_DREQ_SENT;
1167 				stale_statep->stale = B_TRUE;
1168 
1169 				/* Cancel pending ibt_set_alt_path */
1170 				ibcm_sync_lapr_idle(stale_statep);
1171 				/* The above call releases the state mutex */
1172 
1173 				if (stale_statep->dreq_msg == NULL)
1174 					(void) ibcm_alloc_out_msg(stale_statep->
1175 					    stored_reply_addr.ibmf_hdl,
1176 					    &stale_statep->dreq_msg,
1177 					    MAD_METHOD_SEND);
1178 
1179 				/*
1180 				 * Spec says, post DREQ MAD on the stale
1181 				 * channel. This moves channel into timewait
1182 				 */
1183 				if (stale_statep->dreq_msg != NULL) {
1184 					ibcm_post_dreq_mad(stale_statep);
1185 					mutex_enter(&stale_statep->state_mutex);
1186 				} else {
1187 					mutex_enter(&stale_statep->state_mutex);
1188 					/* Set it back to original state. */
1189 					stale_statep->state =
1190 					    IBCM_STATE_ESTABLISHED;
1191 					cv_broadcast(
1192 					    &stale_statep->block_mad_cv);
1193 				}
1194 			}
1195 
1196 			IBCM_REF_CNT_DECR(stale_statep);
1197 			mutex_exit(&stale_statep->state_mutex);
1198 
1199 			mutex_enter(&statep->state_mutex);
1200 			IBCM_REF_CNT_DECR(statep);
1201 			mutex_exit(&statep->state_mutex);
1202 			return;
1203 		}
1204 
1205 		/* If unknown service type, just post a REJ */
1206 		trans = ((uint8_t *)&req_msgp->req_remote_eecn_plus)[3] >> 1 &
1207 		    0x3;
1208 		if ((trans != IBT_RC_SRV) && (trans != IBT_UC_SRV) &&
1209 		    (trans != IBT_RD_SRV)) {
1210 
1211 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1212 			    "statep 0x%p invalid transport type %x", statep,
1213 			    trans);
1214 
1215 			/* Send a REJ with invalid transport type */
1216 			ibcm_post_rej_mad(statep, IBT_CM_INVALID_SRV_TYPE,
1217 			    IBT_CM_FAILURE_REQ, NULL, 0);
1218 
1219 			mutex_enter(&statep->state_mutex);
1220 			IBCM_REF_CNT_DECR(statep);
1221 			mutex_exit(&statep->state_mutex);
1222 			return;
1223 		}
1224 
1225 		/* Validate the gids, lids and service id */
1226 		svc_gid_check = ibcm_verify_req_gids_and_svcid(statep,
1227 		    req_msgp);
1228 
1229 		if (svc_gid_check == IBCM_FAILURE) {
1230 
1231 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_req_msg: Either "
1232 			    "gid or sid invalid for statep 0x%p", statep);
1233 			mutex_enter(&statep->state_mutex);
1234 			IBCM_REF_CNT_DECR(statep);
1235 			mutex_exit(&statep->state_mutex);
1236 
1237 			/* REJ posted from ibcm_verify_req_gids_and_svcid */
1238 			return;
1239 		}
1240 
1241 		/* Call the QP state transition processing function */
1242 		response = ibcm_cep_state_req(statep, req_msgp,
1243 		    &reject_reason, &arej_info_len);
1244 
1245 		/* If defer, return holding the statep ref cnt */
1246 		if (response == IBCM_DEFER) {
1247 			IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1248 			    "statep %0xp client returned DEFER response",
1249 			    statep);
1250 			return;
1251 		}
1252 
1253 		/* statep ref cnt decremented in the func below */
1254 		ibcm_handle_cep_req_response(statep, response,
1255 		    reject_reason, arej_info_len);
1256 
1257 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1258 
1259 		return;
1260 
1261 	} else {
1262 		rw_exit(&hcap->hca_state_rwlock);
1263 		ibcm_free_comid(hcap, local_comid);
1264 	}
1265 
1266 	if (state_lookup_status == IBCM_LOOKUP_EXISTS) {
1267 		hrtime_t	cur_time;
1268 
1269 		mutex_enter(&statep->state_mutex);
1270 
1271 		/*
1272 		 * There is an existing state structure entry
1273 		 * with the same active comid
1274 		 * Resending REP MAD is necessary only for REP/REJ/MRA Sent
1275 		 * states
1276 		 * Any other state implies the active has already received
1277 		 * the REP/REJ response, and this REQ is an old MAD popping
1278 		 * out of the fabric, hence no resend is required
1279 		 */
1280 		cur_time = gethrtime();
1281 
1282 		if ((remote_comid == statep->remote_comid) &&
1283 		    (IBCM_OUT_HDRP(statep->stored_msg)->TransactionID ==
1284 		    ((ib_mad_hdr_t *)(input_madp))->TransactionID) &&
1285 		    (cur_time <= statep->stale_clock)) {
1286 
1287 			ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_REQ);
1288 
1289 			if (statep->state == IBCM_STATE_REP_SENT)
1290 				ibcm_resend_rep_mad(statep);
1291 			else if (statep->state == IBCM_STATE_REJ_SENT)
1292 				ibcm_resend_rej_mad(statep);
1293 			else if (statep->state == IBCM_STATE_MRA_SENT)
1294 				ibcm_resend_mra_mad(statep);
1295 
1296 			/* decrementing ref cnt and returning from below */
1297 
1298 		} else if ((statep->state == IBCM_STATE_REJ_SENT) &&
1299 		    remote_comid != statep->remote_comid) {
1300 			timeout_id_t		timer_val;
1301 
1302 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1303 			    "statep 0x%p being retired, REMOTE_QPN %x",
1304 			    statep, remote_qpn);
1305 			/*
1306 			 * OK, this is reuse of the QPN on the active side
1307 			 * that was not connected last time.  This REQ is
1308 			 * considered NEW.  We delete the statep here,
1309 			 * then start over from the top.
1310 			 */
1311 			statep->state = IBCM_STATE_DELETE;
1312 			timer_val = statep->timerid;
1313 			statep->timerid = 0;
1314 			mutex_exit(&statep->state_mutex);
1315 			if (timer_val)
1316 				(void) untimeout(timer_val);
1317 			IBCM_REF_CNT_DECR(statep);
1318 			ibcm_delete_state_data(statep);
1319 			goto new_req;
1320 
1321 		/*
1322 		 * The statep is stale in the following cases :-
1323 		 *  1) if incoming REQ's comid's doesn't match with what is
1324 		 *	stored in statep
1325 		 *  2) incoming REQ's local comid matches with statep's
1326 		 *	remote comid, but the REQ is for a new connection.
1327 		 *	This is verified that by comparing the current time
1328 		 *	with stale clock in statep
1329 		 */
1330 		} else {
1331 			/* This is a stale connection on passive side */
1332 
1333 			ibcm_insert_trace(statep, IBCM_TRACE_STALE_DETECT);
1334 
1335 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_msg: "
1336 			    "stale detected statep %p state %x",
1337 			    statep, statep->state);
1338 
1339 			IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1340 			    "cur_time 0x%llX stale_clock 0x%llX", cur_time,
1341 			    statep->stale_clock);
1342 
1343 			if (statep->state == IBCM_STATE_ESTABLISHED) {
1344 
1345 				statep->state = IBCM_STATE_TRANSIENT_DREQ_SENT;
1346 				statep->stale = B_TRUE;
1347 
1348 				/* Cancel pending ibt_set_alt_path */
1349 				ibcm_sync_lapr_idle(statep);
1350 				/* The above call releases the state mutex */
1351 
1352 				if (statep->dreq_msg == NULL)
1353 					(void) ibcm_alloc_out_msg(
1354 					    statep->stored_reply_addr.ibmf_hdl,
1355 					    &statep->dreq_msg, MAD_METHOD_SEND);
1356 
1357 				/*
1358 				 * Spec says, post DREQ MAD on the stale
1359 				 * channel. This moves channel into timewait
1360 				 */
1361 				if (statep->dreq_msg != NULL)
1362 					ibcm_post_dreq_mad(statep);
1363 				else {
1364 					mutex_enter(&statep->state_mutex);
1365 					statep->state = IBCM_STATE_ESTABLISHED;
1366 					cv_broadcast(&statep->block_mad_cv);
1367 					mutex_exit(&statep->state_mutex);
1368 				}
1369 			} else {
1370 				/*
1371 				 * If not in established state, the CM
1372 				 * protocol would timeout and delete the
1373 				 * statep that is stale, eventually
1374 				 */
1375 				mutex_exit(&statep->state_mutex);
1376 			}
1377 
1378 			/* Post a REJ MAD to the incoming REQ's sender */
1379 			ibcm_build_n_post_rej_mad(input_madp,
1380 			    b2h32(req_msgp->req_local_comm_id),
1381 			    cm_mad_addr, IBT_CM_FAILURE_REQ, IBT_CM_CONN_STALE);
1382 
1383 			mutex_enter(&statep->state_mutex);
1384 		}
1385 		IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
1386 		mutex_exit(&statep->state_mutex);
1387 	}
1388 }
1389 
1390 /*
1391  * ibcm_handle_cep_req_response:
1392  *	Processes the response from ibcm_cep_state_req. Called holding a
1393  *	statep ref cnt. The statep ref cnt is decremented before returning.
1394  */
1395 void
1396 ibcm_handle_cep_req_response(ibcm_state_data_t *statep, ibcm_status_t response,
1397     ibt_cm_reason_t reject_reason, uint8_t arej_info_len)
1398 {
1399 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1400 
1401 	if (response == IBCM_SEND_REP)
1402 		ibcm_post_rep_mad(statep);
1403 	else {
1404 		ASSERT(response == IBCM_SEND_REJ);
1405 		IBTF_DPRINTF_L4(cmlog, "ibcm_handle_cep_req_response: statep %p"
1406 		    " posting REJ reject_reason = %d", statep, reject_reason);
1407 
1408 		ibcm_post_rej_mad(statep,
1409 		    reject_reason, IBT_CM_FAILURE_REQ,
1410 		    NULL, arej_info_len);
1411 	}
1412 
1413 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1414 
1415 	mutex_enter(&statep->state_mutex);
1416 	IBCM_REF_CNT_DECR(statep);
1417 	mutex_exit(&statep->state_mutex);
1418 }
1419 
1420 
1421 /*
1422  * ibcm_process_rep_msg:
1423  *	ACTIVE SIDE CM
1424  *	Called from ibcm_process_incoming_mad on reception of a REP message
1425  *
1426  * INPUTS:
1427  *	hcap		- HCA entry pointer
1428  *	input_madp	- CM MAD that is input to this function
1429  *	cm_mad_addr	- Address information for the MAD
1430  *
1431  * RETURN VALUE:	NONE
1432  */
1433 void
1434 ibcm_process_rep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
1435     ibcm_mad_addr_t *cm_mad_addr)
1436 {
1437 	ibt_priv_data_len_t	arej_info_len = 0;
1438 	ib_com_id_t		local_comid;
1439 	timeout_id_t		timer_val;
1440 	ibcm_status_t		lookup_status;	/* state lookup status */
1441 	ibcm_status_t		stale_lookup_status;
1442 	ibcm_status_t		stale_comid_lookup_status;
1443 	ibcm_status_t		response;
1444 	ibcm_rep_msg_t		*rep_msgp;	/* Response REP mesg */
1445 	ibt_cm_reason_t		reject_reason;
1446 	ibcm_state_data_t	*statep = NULL;
1447 	ibcm_state_data_t	*stale_qpn = NULL;
1448 	ibcm_state_data_t	*stale_comid = NULL;
1449 	ib_guid_t		remote_ca_guid;
1450 
1451 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_rep_msg:");
1452 
1453 	/* Lookup for an existing state structure */
1454 	rep_msgp = (ibcm_rep_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
1455 
1456 	IBTF_DPRINTF_L5(cmlog, "ibcm_process_rep_msg: active comid: %x",
1457 	    rep_msgp->rep_remote_comm_id);
1458 
1459 	local_comid = b2h32(rep_msgp->rep_remote_comm_id);
1460 
1461 	/* lookup message holding a reader lock */
1462 	rw_enter(&hcap->hca_state_rwlock, RW_READER);
1463 	lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REP, local_comid, 0, 0,
1464 	    hcap, &statep);
1465 	rw_exit(&hcap->hca_state_rwlock);
1466 
1467 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: lkup status %x, "
1468 	    "statep 0x%p active comid %x", lookup_status, statep, local_comid);
1469 
1470 	if (lookup_status == IBCM_LOOKUP_FAIL) {
1471 		ibcm_build_n_post_rej_mad(input_madp,
1472 		    b2h32(rep_msgp->rep_local_comm_id), cm_mad_addr,
1473 		    IBT_CM_FAILURE_REP, IBT_CM_INVALID_CID);
1474 
1475 		return;
1476 	}
1477 
1478 	/* if transaction id is not as expected, drop the REP mad */
1479 	if (IBCM_OUT_HDRP(statep->stored_msg)->TransactionID !=
1480 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
1481 
1482 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_rep_msg: statep 0x%p, "
1483 		    "An REP MAD with tid expected 0x%llX tid found 0x%llX ",
1484 		    statep,
1485 		    b2h64(IBCM_OUT_HDRP(statep->stored_msg)->TransactionID),
1486 		    b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID));
1487 
1488 		mutex_enter(&statep->state_mutex);
1489 		IBCM_REF_CNT_DECR(statep);
1490 		mutex_exit(&statep->state_mutex);
1491 		return;
1492 	}
1493 
1494 	ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_REP);
1495 
1496 	/* grab mutex first */
1497 	mutex_enter(&statep->state_mutex);
1498 
1499 	/*
1500 	 * There is a state structure entry with active comid
1501 	 * First, handle the re-send cases
1502 	 * The resend routines below release the state mutex
1503 	 */
1504 	if (statep->state == IBCM_STATE_ESTABLISHED ||
1505 	    statep->state == IBCM_STATE_DREQ_SENT)
1506 		ibcm_resend_rtu_mad(statep);
1507 	else if (statep->state == IBCM_STATE_REJ_SENT)
1508 		ibcm_resend_rej_mad(statep);
1509 	else if (statep->state == IBCM_STATE_MRA_REP_SENT)
1510 		ibcm_resend_mra_mad(statep);
1511 	else if ((statep->state == IBCM_STATE_REQ_SENT) ||
1512 	    (statep->state == IBCM_STATE_REP_WAIT)) {
1513 
1514 		/* change state */
1515 		statep->state = IBCM_STATE_REP_RCVD;
1516 		statep->clnt_proceed = IBCM_BLOCK;
1517 
1518 		/* cancel the REQ timer */
1519 		if (statep->timerid != 0) {
1520 			timer_val = statep->timerid;
1521 			statep->timerid = 0;
1522 			mutex_exit(&statep->state_mutex);
1523 			(void) untimeout(timer_val);
1524 		} else {
1525 			mutex_exit(&statep->state_mutex);
1526 		}
1527 
1528 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1529 
1530 		/* Initialize the remote destination QPN for further MADs */
1531 		statep->stored_reply_addr.rcvd_addr.ia_remote_qno =
1532 		    cm_mad_addr->rcvd_addr.ia_remote_qno;
1533 		statep->remote_qpn = b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
1534 		statep->remote_comid = b2h32(rep_msgp->rep_local_comm_id);
1535 		bcopy(rep_msgp->rep_local_ca_guid, &remote_ca_guid,
1536 		    sizeof (ib_guid_t));
1537 		statep->remote_hca_guid = b2h64(remote_ca_guid);
1538 
1539 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1540 		    "passive cid = %x passive qpn = %x", statep,
1541 		    statep->remote_comid, statep->remote_qpn);
1542 
1543 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1544 		    "passive hcaguid = %llX", statep, statep->remote_hca_guid);
1545 
1546 		stale_qpn = statep;
1547 		stale_comid = statep;
1548 
1549 		/* Handle stale connection detection on active side */
1550 		rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
1551 
1552 		stale_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REP_STALE,
1553 		    0, statep->remote_qpn, statep->remote_hca_guid, hcap,
1554 		    &stale_qpn);
1555 
1556 		stale_comid_lookup_status = ibcm_lookup_msg(
1557 		    IBCM_INCOMING_REQ_STALE, statep->remote_comid, 0,
1558 		    statep->remote_hca_guid, hcap, &stale_comid);
1559 
1560 		rw_exit(&hcap->hca_state_rwlock);
1561 
1562 		/*
1563 		 * Check for other side reusing QPN that was attempted
1564 		 * to be used, but somehow we sent a REJ.
1565 		 */
1566 		mutex_enter(&stale_qpn->state_mutex);
1567 		if ((stale_lookup_status == IBCM_LOOKUP_EXISTS) &&
1568 		    (stale_comid_lookup_status != IBCM_LOOKUP_EXISTS) &&
1569 		    (stale_qpn->state == IBCM_STATE_REJ_SENT)) {
1570 
1571 			timeout_id_t		timer_val;
1572 
1573 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_rep_msg: "
1574 			    "statep 0x%p being retired, REMOTE_QPN %x",
1575 			    stale_qpn, statep->remote_qpn);
1576 			/*
1577 			 * OK, this is reuse of the QPN on the active side
1578 			 * that was not connected last time.  This REQ is
1579 			 * considered NEW.  We delete the statep here,
1580 			 * then start over from the top.
1581 			 */
1582 			stale_qpn->state = IBCM_STATE_DELETE;
1583 			timer_val = stale_qpn->timerid;
1584 			stale_qpn->timerid = 0;
1585 			mutex_exit(&stale_qpn->state_mutex);
1586 			if (timer_val)
1587 				(void) untimeout(timer_val);
1588 			IBCM_REF_CNT_DECR(stale_qpn);
1589 			ibcm_delete_state_data(stale_qpn);
1590 			stale_qpn = statep;
1591 			rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
1592 			stale_lookup_status = ibcm_lookup_msg(
1593 			    IBCM_INCOMING_REP_STALE, 0, statep->remote_qpn,
1594 			    statep->remote_hca_guid, hcap, &stale_qpn);
1595 			rw_exit(&hcap->hca_state_rwlock);
1596 			/* OK to continue now */
1597 		} else
1598 			mutex_exit(&stale_qpn->state_mutex);
1599 
1600 		/*
1601 		 * lookup exists implies that there is already an entry with
1602 		 * the remote qpn/comid and remote hca guid
1603 		 */
1604 		if ((stale_lookup_status == IBCM_LOOKUP_EXISTS) ||
1605 		    (stale_comid_lookup_status == IBCM_LOOKUP_EXISTS)) {
1606 
1607 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1608 			    "statep 0x%p stale detected "
1609 			    "qpn_lkup %d comid_lkup %d", statep,
1610 			    stale_lookup_status, stale_comid_lookup_status);
1611 
1612 			/* Disassociate statep and QP */
1613 			IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
1614 
1615 			if (stale_lookup_status == IBCM_LOOKUP_EXISTS)
1616 				reject_reason = IBT_CM_CONN_STALE;
1617 			else
1618 				reject_reason = IBT_CM_DUP_COM_ID;
1619 
1620 			ibcm_handler_conn_fail(statep,
1621 			    IBT_CM_FAILURE_REJ_SENT, IBT_CM_FAILURE_REP,
1622 			    reject_reason,
1623 			    IBCM_REJ_PRIV(statep->stored_msg),
1624 			    IBT_REJ_PRIV_DATA_SZ);
1625 
1626 			/* Send a REJ with stale reason for statep */
1627 			ibcm_post_rej_mad(statep, reject_reason,
1628 			    IBT_CM_FAILURE_REP, NULL, 0);
1629 
1630 			/* Now let's handle the logic for stale connections */
1631 			/* If in established state, stale_statep is stale */
1632 			if (stale_lookup_status == IBCM_LOOKUP_EXISTS) {
1633 
1634 				IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1635 				    "state_qpn 0x%p stale QPN detected "
1636 				    "state %X", stale_qpn, stale_qpn->state);
1637 
1638 				ibcm_insert_trace(stale_qpn,
1639 				    IBCM_TRACE_STALE_DETECT);
1640 
1641 				mutex_enter(&stale_qpn->state_mutex);
1642 				if (stale_qpn->state ==
1643 				    IBCM_STATE_ESTABLISHED) {
1644 					/* change state to DREQ sent */
1645 					stale_qpn->state =
1646 					    IBCM_STATE_TRANSIENT_DREQ_SENT;
1647 					stale_qpn->stale = B_TRUE;
1648 
1649 					/* wait for/cancel pending LAP/APR */
1650 					ibcm_sync_lapr_idle(stale_qpn);
1651 					/* above call releases state mutex */
1652 
1653 					if (stale_qpn->dreq_msg == NULL)
1654 						(void) ibcm_alloc_out_msg(
1655 						    stale_qpn->
1656 						    stored_reply_addr.ibmf_hdl,
1657 						    &stale_qpn->dreq_msg,
1658 						    MAD_METHOD_SEND);
1659 
1660 					if (stale_qpn->dreq_msg != NULL) {
1661 						ibcm_post_dreq_mad(stale_qpn);
1662 						mutex_enter(
1663 						    &stale_qpn->state_mutex);
1664 					} else {
1665 						mutex_enter(
1666 						    &stale_qpn->state_mutex);
1667 						stale_qpn->state =
1668 						    IBCM_STATE_ESTABLISHED;
1669 						cv_broadcast(
1670 						    &stale_qpn->block_mad_cv);
1671 					}
1672 				}
1673 				IBCM_REF_CNT_DECR(stale_qpn);
1674 				mutex_exit(&stale_qpn->state_mutex);
1675 			}
1676 
1677 			if (stale_comid_lookup_status == IBCM_LOOKUP_EXISTS) {
1678 
1679 				IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1680 				    "state_comid 0x%p stale COMID detected "
1681 				    "state %X", stale_comid,
1682 				    stale_comid->state);
1683 
1684 				mutex_enter(&stale_comid->state_mutex);
1685 				if (!((stale_lookup_status ==
1686 				    IBCM_LOOKUP_EXISTS) &&
1687 				    (stale_qpn == stale_comid)) &&
1688 				    (stale_comid->state ==
1689 				    IBCM_STATE_ESTABLISHED)) {
1690 
1691 					ibcm_insert_trace(stale_comid,
1692 					    IBCM_TRACE_STALE_DETECT);
1693 
1694 					/* change state to DREQ sent */
1695 					stale_comid->state =
1696 					    IBCM_STATE_TRANSIENT_DREQ_SENT;
1697 					stale_comid->stale = B_TRUE;
1698 
1699 					/* wait for/cancel pending LAP/APR */
1700 					ibcm_sync_lapr_idle(stale_comid);
1701 
1702 					/* above call releases state mutex */
1703 
1704 					if (stale_comid->dreq_msg == NULL)
1705 						(void) ibcm_alloc_out_msg(
1706 						    stale_comid->
1707 						    stored_reply_addr.ibmf_hdl,
1708 						    &stale_comid->dreq_msg,
1709 						    MAD_METHOD_SEND);
1710 
1711 					if (stale_comid->dreq_msg != NULL) {
1712 						ibcm_post_dreq_mad(stale_comid);
1713 						mutex_enter(
1714 						    &stale_comid->state_mutex);
1715 					} else {
1716 						mutex_enter(
1717 						    &stale_comid->state_mutex);
1718 						stale_comid->state =
1719 						    IBCM_STATE_ESTABLISHED;
1720 						cv_broadcast(
1721 						    &stale_comid->block_mad_cv);
1722 					}
1723 				}
1724 				IBCM_REF_CNT_DECR(stale_comid);
1725 				mutex_exit(&stale_comid->state_mutex);
1726 			}
1727 			ibcm_return_open_data(statep, rep_msgp, reject_reason);
1728 			return;
1729 		}
1730 
1731 		/*
1732 		 * No need to handle out of memory conditions as we called
1733 		 * ibcm_lookup_msg() with IBT_CHAN_BLOCKING flags.
1734 		 */
1735 		ASSERT(stale_lookup_status == IBCM_LOOKUP_NEW);
1736 
1737 		/* Initialize the remote ack delay */
1738 		statep->remote_ack_delay =
1739 		    ibt_ib2usec(rep_msgp->rep_target_delay_plus >> 3);
1740 
1741 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p"
1742 		    " passive hca_ack_delay= %x ", statep,
1743 		    statep->remote_ack_delay);
1744 
1745 		response = ibcm_cep_state_rep(statep, rep_msgp,
1746 		    &reject_reason, &arej_info_len);
1747 
1748 		if (response == IBCM_DEFER) {
1749 			IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: "
1750 			    "statep 0x%p client returned DEFER response",
1751 			    statep);
1752 			return;
1753 		}
1754 		ibcm_handle_cep_rep_response(statep, response,
1755 		    reject_reason, arej_info_len, rep_msgp);
1756 
1757 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1758 
1759 		return;
1760 
1761 	} else if (statep->state == IBCM_STATE_DELETE) {
1762 
1763 		mutex_exit(&statep->state_mutex);
1764 		ibcm_build_n_post_rej_mad(input_madp,
1765 		    b2h32(rep_msgp->rep_local_comm_id), cm_mad_addr,
1766 		    IBT_CM_FAILURE_REP, IBT_CM_INVALID_CID);
1767 		mutex_enter(&statep->state_mutex);
1768 	} else {
1769 
1770 #ifdef DEBUG
1771 		if (ibcm_test_mode > 0)
1772 			if (statep->state == IBCM_STATE_REP_RCVD)
1773 				IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1774 				    "REP re-send from passive for statep 0x%p"
1775 				    " in state %d", statep, statep->state);
1776 			else
1777 				IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1778 				    "Unexpected REP for statep 0x%p in "
1779 				    "state %d", statep, statep->state);
1780 #endif
1781 	}
1782 	/* decrement ref count and return for LOOKUP_EXISTS */
1783 	IBCM_REF_CNT_DECR(statep);
1784 	mutex_exit(&statep->state_mutex);
1785 
1786 }
1787 
1788 /*
1789  * ibcm_handle_cep_req_response:
1790  *	Processes the response from ibcm_cep_state_rep. Called holding a
1791  *	statep ref cnt. The statep ref cnt is decremented before returning.
1792  */
1793 void
1794 ibcm_handle_cep_rep_response(ibcm_state_data_t *statep, ibcm_status_t response,
1795     ibt_cm_reason_t reject_reason, uint8_t arej_info_len,
1796     ibcm_rep_msg_t *rep_msgp)
1797 {
1798 	/* wait until the send completion callback is invoked for REQ post */
1799 	mutex_enter(&statep->state_mutex);
1800 	while (statep->send_mad_flags & IBCM_REQ_POST_BUSY)
1801 		cv_wait(&statep->block_mad_cv, &statep->state_mutex);
1802 	mutex_exit(&statep->state_mutex);
1803 
1804 	if (response == IBCM_SEND_RTU) {
1805 		/* if connection aborted, return */
1806 		if (ibcm_post_rtu_mad(statep) != IBCM_SUCCESS) {
1807 			mutex_enter(&statep->state_mutex);
1808 			IBCM_REF_CNT_DECR(statep);
1809 			mutex_exit(&statep->state_mutex);
1810 			return;
1811 		}
1812 
1813 		/*
1814 		 * Call client handler with cm event  IBT_CM_EVENT_CONN_EST to
1815 		 * indicate RTU posted
1816 		 */
1817 		ibcm_cep_send_rtu(statep);
1818 	} else {
1819 		IBTF_DPRINTF_L4(cmlog, "ibcm_handle_cep_rep_response: statep %p"
1820 		    " posting REJ reject_reason = %d", statep, reject_reason);
1821 
1822 		ASSERT(response == IBCM_SEND_REJ);
1823 		ibcm_post_rej_mad(statep, reject_reason, IBT_CM_FAILURE_REP,
1824 		    NULL, arej_info_len);
1825 	}
1826 
1827 	ibcm_return_open_data(statep, rep_msgp, reject_reason);
1828 }
1829 
1830 /*
1831  * ibcm_return_open_data:
1832  *	Initializes the ibt_open_rc_channel return data. The statep ref cnt is
1833  *	decremented before returning.
1834  */
1835 static void
1836 ibcm_return_open_data(ibcm_state_data_t *statep, ibcm_rep_msg_t *rep_msgp,
1837     ibt_cm_reason_t reject_reason)
1838 {
1839 	/* signal waiting CV - blocking in ibt_open_channel() */
1840 	if (statep->open_return_data != NULL) {
1841 		if (statep->open_return_data->rc_priv_data_len > 0)
1842 			bcopy(rep_msgp->rep_private_data,
1843 			    statep->open_return_data->rc_priv_data,
1844 			    statep->open_return_data->rc_priv_data_len);
1845 		statep->open_return_data->rc_rdma_ra_in =
1846 		    rep_msgp->rep_resp_resources;
1847 		statep->open_return_data->rc_rdma_ra_out =
1848 		    rep_msgp->rep_initiator_depth;
1849 		statep->open_return_data->rc_failover_status =
1850 		    rep_msgp->rep_target_delay_plus >> 1 & 3;
1851 		statep->open_return_data->rc_status = reject_reason;
1852 
1853 		mutex_enter(&statep->state_mutex);
1854 		statep->open_done = B_TRUE;
1855 		cv_broadcast(&statep->block_client_cv);
1856 	} else mutex_enter(&statep->state_mutex);
1857 
1858 	/* decrement ref count and return for LOOKUP_EXISTS */
1859 	IBCM_REF_CNT_DECR(statep);
1860 	mutex_exit(&statep->state_mutex);
1861 }
1862 
1863 
1864 /*
1865  * ibcm_process_mra_msg:
1866  *	Called from ibcm_process_incoming_mad on reception of a MRA message
1867  *
1868  *	Cancels existing timer, and sets a new timer based on timeout
1869  *	value from MRA message. The remaining retry count of statep is
1870  *	not changed, and timer value for the remaining retry timers is
1871  *	also not changed
1872  *
1873  * INPUTS:
1874  *	hcap		- HCA entry pointer
1875  *	input_madp	- CM MAD that is input to this function
1876  *	cm_mad_addr	- Address information for the MAD
1877  *
1878  * RETURN VALUE:	NONE
1879  */
1880 void
1881 ibcm_process_mra_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
1882     ibcm_mad_addr_t *cm_mad_addr)
1883 {
1884 	ibcm_status_t		state_lookup_status;
1885 	ibcm_mra_msg_t		*mra_msgp =
1886 	    (ibcm_mra_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
1887 	ibcm_state_data_t	*statep = NULL;
1888 	uint8_t			mra_msg;
1889 
1890 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_mra_msg:");
1891 
1892 	/* Lookup for an existing state structure (as a READER) */
1893 	rw_enter(&hcap->hca_state_rwlock, RW_READER);
1894 	state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_MRA,
1895 	    b2h32(mra_msgp->mra_remote_comm_id), 0, 0, hcap, &statep);
1896 	rw_exit(&hcap->hca_state_rwlock);
1897 
1898 	/* if state doesn't exist just return */
1899 	if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
1900 		ibcm_build_n_post_rej_mad(input_madp,
1901 		    b2h32(mra_msgp->mra_local_comm_id), cm_mad_addr,
1902 		    IBT_CM_FAILURE_UNKNOWN, IBT_CM_INVALID_CID);
1903 		return;
1904 	}
1905 
1906 	if (IBCM_OUT_HDRP(statep->stored_msg)->TransactionID !=
1907 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
1908 		mutex_enter(&statep->state_mutex);
1909 		IBCM_REF_CNT_DECR(statep);
1910 		mutex_exit(&statep->state_mutex);
1911 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_mra_msg: statep 0x%p "
1912 		    "MRA MAD with tid expected 0x%llX tid found 0x%llX "
1913 		    "com id 0x%x arrived", statep,
1914 		    b2h64(IBCM_OUT_HDRP(statep->stored_msg)->TransactionID),
1915 		    b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID),
1916 		    b2h32(mra_msgp->mra_local_comm_id));
1917 		return;
1918 	}
1919 
1920 	ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_MRA);
1921 
1922 	mutex_enter(&statep->state_mutex);
1923 
1924 	/*
1925 	 * Only allow for REQ/REP "mra_msg_typ" ONLY
1926 	 * (to validate MRA message received)?
1927 	 */
1928 	mra_msg = mra_msgp->mra_message_type_plus >> 6;
1929 	if ((mra_msg != IBT_CM_MRA_TYPE_REQ) &&
1930 	    (mra_msg != IBT_CM_MRA_TYPE_REP) &&
1931 	    (mra_msg != IBT_CM_MRA_TYPE_LAP)) {
1932 
1933 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_mra_msg: statep 0x%p "
1934 		    "Unexpected MRA MSG Type %x", statep, mra_msg);
1935 		IBCM_REF_CNT_DECR(statep);
1936 		mutex_exit(&statep->state_mutex);
1937 		return;
1938 	}
1939 
1940 	if ((statep->state == IBCM_STATE_REQ_SENT) ||
1941 	    (statep->state == IBCM_STATE_REP_SENT) ||
1942 	    ((statep->state == IBCM_STATE_ESTABLISHED) &&
1943 	    (statep->ap_state == IBCM_AP_STATE_LAP_SENT))) {
1944 		timeout_id_t	timer_val = statep->timerid;
1945 		clock_t		service_timeout;
1946 
1947 		if (statep->state == IBCM_STATE_REQ_SENT) {
1948 			mra_msg = IBT_CM_MRA_TYPE_REQ;
1949 			statep->state = IBCM_STATE_REP_WAIT;
1950 		} else if (statep->state == IBCM_STATE_REP_SENT) {
1951 			mra_msg = IBT_CM_MRA_TYPE_REP;
1952 			statep->state = IBCM_STATE_MRA_REP_RCVD;
1953 		} else { /* statep->state == IBCM_STATE_LAP_SENT */
1954 			mra_msg = IBT_CM_MRA_TYPE_LAP;
1955 			statep->ap_state = IBCM_AP_STATE_MRA_LAP_RCVD;
1956 		}
1957 
1958 		/* cancel the timer */
1959 		statep->timerid = 0;
1960 		mutex_exit(&statep->state_mutex);
1961 
1962 		(void) untimeout(timer_val);
1963 
1964 		service_timeout =
1965 		    ibt_ib2usec(mra_msgp->mra_service_timeout_plus >> 3);
1966 
1967 		/*
1968 		 * If tunable MAX MRA Service Timeout parameter is set, then
1969 		 * verify whether the requested timer value exceeds the MAX
1970 		 * value and reset the timer value to the MAX value.
1971 		 */
1972 		if (ibcm_mra_service_timeout_max &&
1973 		    ibcm_mra_service_timeout_max < service_timeout) {
1974 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_mra_msg: "
1975 			    "Unexpected MRA Service Timeout value (%ld), Max "
1976 			    "allowed is (%ld)", service_timeout,
1977 			    ibcm_mra_service_timeout_max);
1978 			service_timeout = ibcm_mra_service_timeout_max;
1979 		}
1980 
1981 		/*
1982 		 * Invoke client handler to pass the MRA private data
1983 		 */
1984 		if (statep->cm_handler != NULL) {
1985 			ibt_cm_event_t	event;
1986 
1987 			bzero(&event, sizeof (event));
1988 
1989 			event.cm_type = IBT_CM_EVENT_MRA_RCV;
1990 			event.cm_channel = statep->channel;
1991 			event.cm_session_id = NULL;
1992 			event.cm_priv_data = mra_msgp->mra_private_data;
1993 			event.cm_priv_data_len = IBT_MRA_PRIV_DATA_SZ;
1994 
1995 			event.cm_event.mra.mra_msg_type = mra_msg;
1996 
1997 			event.cm_event.mra.mra_service_time = service_timeout;
1998 
1999 			/* Client cannot return private data */
2000 			(void) statep->cm_handler(statep->state_cm_private,
2001 			    &event, NULL, NULL, 0);
2002 		}
2003 
2004 		/*
2005 		 * Must re-check state, as an RTU could have come
2006 		 * after the above mutex_exit and mutex_enter below
2007 		 */
2008 		mutex_enter(&statep->state_mutex);
2009 		if ((statep->state == IBCM_STATE_REP_WAIT) ||
2010 		    (statep->state == IBCM_STATE_MRA_REP_RCVD) ||
2011 		    (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
2012 
2013 			statep->remaining_retry_cnt = statep->max_cm_retries;
2014 
2015 			/*
2016 			 * The timeout interval is changed only for the first
2017 			 * retry.  The later retries use the timeout from
2018 			 * statep->timer_value
2019 			 */
2020 			statep->timer_stored_state = statep->state;
2021 			statep->timer_value = statep->pkt_life_time +
2022 			    service_timeout;
2023 			statep->timerid = IBCM_TIMEOUT(statep,
2024 			    statep->timer_value);
2025 		}
2026 
2027 	} else if (statep->state == IBCM_STATE_DELETE) {
2028 
2029 		mutex_exit(&statep->state_mutex);
2030 		ibcm_build_n_post_rej_mad(input_madp,
2031 		    b2h32(mra_msgp->mra_local_comm_id), cm_mad_addr,
2032 		    IBT_CM_FAILURE_UNKNOWN, IBT_CM_INVALID_CID);
2033 		mutex_enter(&statep->state_mutex);
2034 	} else {
2035 
2036 #ifdef DEBUG
2037 		if (ibcm_test_mode > 0)
2038 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_mra_msg: "
2039 			    "Unexpected mra for statep 0x%p in state %d",
2040 			    statep, statep->state);
2041 #endif
2042 	}
2043 
2044 	IBCM_REF_CNT_DECR(statep);
2045 	mutex_exit(&statep->state_mutex);
2046 }
2047 
2048 
2049 /*
2050  * ibcm_process_rtu_msg:
2051  *	Called from ibcm_process_incoming_mad on reception of a RTU message
2052  *
2053  *	Changes connection state to established if in REP SENT state
2054  *
2055  * INPUTS:
2056  *	hcap		- HCA entry pointer
2057  *	input_madp	- CM MAD that is input to this function
2058  *	cm_mad_addr	- Address information for the MAD
2059  *
2060  * RETURN VALUE:	NONE
2061  */
2062 void
2063 ibcm_process_rtu_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
2064     ibcm_mad_addr_t *cm_mad_addr)
2065 {
2066 	timeout_id_t		timer_val;
2067 	ibcm_status_t		status;
2068 	ibcm_rtu_msg_t		*rtu_msg =
2069 	    (ibcm_rtu_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
2070 	ibcm_state_data_t	*statep = NULL;
2071 
2072 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_rtu_msg:");
2073 
2074 	/* Lookup for an existing state structure - using a reader lock */
2075 	rw_enter(&hcap->hca_state_rwlock, RW_READER);
2076 	status = ibcm_lookup_msg(IBCM_INCOMING_RTU,
2077 	    b2h32(rtu_msg->rtu_remote_comm_id), 0, 0, hcap, &statep);
2078 	rw_exit(&hcap->hca_state_rwlock);
2079 
2080 	/* if state doesn't exist just return */
2081 	if (status != IBCM_LOOKUP_EXISTS) {
2082 		ibcm_build_n_post_rej_mad(input_madp,
2083 		    b2h32(rtu_msg->rtu_local_comm_id), cm_mad_addr,
2084 		    IBT_CM_FAILURE_UNKNOWN, IBT_CM_INVALID_CID);
2085 		return;
2086 	}
2087 
2088 	if (IBCM_OUT_HDRP(statep->stored_msg)->TransactionID !=
2089 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
2090 		mutex_enter(&statep->state_mutex);
2091 		IBCM_REF_CNT_DECR(statep);
2092 		mutex_exit(&statep->state_mutex);
2093 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_rtu_msg: statep 0x%p "
2094 		    "An RTU MAD with tid expected 0x%llX tid found 0x%llX "
2095 		    "com id 0x%x arrived", statep,
2096 		    b2h64(IBCM_OUT_HDRP(statep->stored_msg)->TransactionID),
2097 		    b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID),
2098 		    b2h32(rtu_msg->rtu_remote_comm_id));
2099 		return;
2100 	}
2101 
2102 	ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_RTU);
2103 
2104 	mutex_enter(&statep->state_mutex);
2105 
2106 	if ((statep->state == IBCM_STATE_REP_SENT) ||
2107 	    (statep->state == IBCM_STATE_MRA_REP_RCVD)) {
2108 
2109 		/* transient until ibt_modify_qp succeeds to RTS */
2110 		statep->state = IBCM_STATE_TRANSIENT_ESTABLISHED;
2111 
2112 		timer_val = statep->timerid;
2113 		statep->timerid = 0;
2114 		mutex_exit(&statep->state_mutex);
2115 
2116 		(void) untimeout(timer_val);
2117 
2118 		ibcm_cep_state_rtu(statep, rtu_msg);
2119 
2120 		mutex_enter(&statep->state_mutex);
2121 
2122 	} else if (statep->state == IBCM_STATE_REJ_SENT) {
2123 		ibcm_resend_rej_mad(statep);
2124 	} else if (statep->state == IBCM_STATE_DELETE) {
2125 
2126 		mutex_exit(&statep->state_mutex);
2127 		ibcm_build_n_post_rej_mad(input_madp,
2128 		    b2h32(rtu_msg->rtu_local_comm_id), cm_mad_addr,
2129 		    IBT_CM_FAILURE_UNKNOWN, IBT_CM_INVALID_CID);
2130 		mutex_enter(&statep->state_mutex);
2131 	} else {
2132 
2133 #ifdef DEBUG
2134 		if ((ibcm_test_mode > 0) &&
2135 		    (statep->state != IBCM_STATE_ESTABLISHED))
2136 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rtu_msg: "
2137 			    "Unexpected rtu for statep 0x%p in state %d",
2138 			    statep, statep->state);
2139 #endif
2140 	}
2141 
2142 	IBCM_REF_CNT_DECR(statep);
2143 	mutex_exit(&statep->state_mutex);
2144 }
2145 
2146 
2147 /*
2148  * ibcm_process_rej_msg:
2149  *	Called from ibcm_process_incoming_mad on reception of a REJ message.
2150  *
2151  * INPUTS:
2152  *	hcap		- HCA entry pointer
2153  *	input_madp	- CM MAD that is input to this function
2154  *	cm_mad_addr	- Address information for the MAD
2155  *
2156  * RETURN VALUE:	NONE
2157  */
2158 /* ARGSUSED */
2159 void
2160 ibcm_process_rej_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
2161     ibcm_mad_addr_t *cm_mad_addr)
2162 {
2163 	ibcm_status_t		state_lookup_status;
2164 	ibcm_rej_msg_t		*rej_msg =
2165 	    (ibcm_rej_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
2166 	ibcm_state_data_t	*statep = NULL;
2167 	ib_guid_t		remote_hca_guid;
2168 	ibcm_conn_state_t	rej_state;
2169 
2170 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_rej_msg:");
2171 
2172 	/* Lookup for an existing state structure */
2173 	rw_enter(&hcap->hca_state_rwlock, RW_READER);	/* grab READER lock */
2174 
2175 	if ((b2h32(rej_msg->rej_remote_comm_id) == 0) &&
2176 	    ((rej_msg->rej_reject_info_len_plus >> 1) >= sizeof (ib_guid_t)) &&
2177 	    (b2h16(rej_msg->rej_rejection_reason) == IBT_CM_TIMEOUT)) {
2178 		bcopy(rej_msg->rej_addl_rej_info, &remote_hca_guid,
2179 		    sizeof (ib_guid_t));
2180 		remote_hca_guid = b2h64(remote_hca_guid);
2181 
2182 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_rej_msg: "
2183 		    "hca guid in REJ's ARI =  %llX", remote_hca_guid);
2184 
2185 		state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REJ_RCOMID,
2186 		    b2h32(rej_msg->rej_local_comm_id), 0, remote_hca_guid,
2187 		    hcap, &statep);
2188 	} else
2189 		state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REJ,
2190 		    b2h32(rej_msg->rej_remote_comm_id), 0, 0, hcap, &statep);
2191 
2192 	rw_exit(&hcap->hca_state_rwlock);
2193 
2194 
2195 	/* if state doesn't exist just return */
2196 	if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
2197 
2198 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_rej_msg: no statep with "
2199 		    "local com id %x remote com id %x reason %d",
2200 		    b2h32(rej_msg->rej_remote_comm_id),
2201 		    b2h32(rej_msg->rej_local_comm_id),
2202 		    b2h16(rej_msg->rej_rejection_reason));
2203 
2204 		/* Do NOT respond with invalid comid REJ */
2205 		return;
2206 	}
2207 
2208 	IBTF_DPRINTF_L2(cmlog, "ibcm_process_rej_msg: statep 0x%p INCOMING_REJ",
2209 	    statep);
2210 	ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_REJ);
2211 	if (ibcm_enable_trace & 2)
2212 		ibcm_dump_conn_trace(statep);
2213 
2214 	mutex_enter(&statep->state_mutex);
2215 
2216 	rej_state = statep->state;
2217 
2218 	if ((statep->state == IBCM_STATE_REP_SENT) ||
2219 	    (statep->state == IBCM_STATE_REQ_SENT) ||
2220 	    (statep->state == IBCM_STATE_REP_WAIT) ||
2221 	    (statep->state == IBCM_STATE_MRA_REP_RCVD)) {
2222 		timeout_id_t	timer_val = statep->timerid;
2223 
2224 		statep->state = IBCM_STATE_DELETE;
2225 
2226 		/* cancel the REQ/REP timer */
2227 		if (timer_val != 0) {
2228 			statep->timerid = 0;
2229 			mutex_exit(&statep->state_mutex);
2230 
2231 			(void) untimeout(timer_val);
2232 		} else {
2233 			mutex_exit(&statep->state_mutex);
2234 		}
2235 
2236 		/*
2237 		 * Call the QP state transition processing function
2238 		 * NOTE: Input MAD is the REJ received, there is no output MAD
2239 		 */
2240 		ibcm_cep_state_rej(statep, rej_msg, rej_state);
2241 
2242 		/* signal waiting CV - blocking in ibt_open_channel() */
2243 		if (statep->open_return_data != NULL) {
2244 			statep->open_return_data->rc_status =
2245 			    b2h16(rej_msg->rej_rejection_reason);
2246 
2247 			if (statep->open_return_data->rc_priv_data_len > 0)
2248 				bcopy(rej_msg->rej_private_data,
2249 				    statep->open_return_data->rc_priv_data,
2250 				    min(
2251 				    statep->open_return_data->rc_priv_data_len,
2252 				    IBT_REJ_PRIV_DATA_SZ));
2253 			mutex_enter(&statep->state_mutex);
2254 			statep->open_done = B_TRUE;
2255 			cv_broadcast(&statep->block_client_cv);
2256 		} else {
2257 			mutex_enter(&statep->state_mutex);
2258 		}
2259 
2260 		IBCM_REF_CNT_DECR(statep);
2261 		mutex_exit(&statep->state_mutex);
2262 
2263 		/* Now delete the statep */
2264 		ibcm_delete_state_data(statep);
2265 
2266 	} else if ((statep->state == IBCM_STATE_ESTABLISHED) &&
2267 	    (statep->mode == IBCM_ACTIVE_MODE)) {
2268 
2269 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_rej_msg: statep 0x%p "
2270 		    "REJ in established state", statep);
2271 
2272 		statep->state = IBCM_STATE_TIMEWAIT;
2273 
2274 		/* wait for/cancel pending LAP/APR, release state mutex */
2275 		ibcm_sync_lapr_idle(statep);
2276 
2277 		/* wait until client is informed CONN EST event */
2278 		mutex_enter(&statep->state_mutex);
2279 		while (statep->cep_in_rts == IBCM_BLOCK)
2280 			cv_wait(&statep->block_mad_cv, &statep->state_mutex);
2281 		mutex_exit(&statep->state_mutex);
2282 
2283 		/*
2284 		 * Call the QP state transition processing function
2285 		 * NOTE: Input MAD is the REJ received, there is no output MAD
2286 		 */
2287 		ibcm_cep_state_rej_est(statep);
2288 
2289 		/*
2290 		 * Start the timewait state timer, as connection is in
2291 		 * established state
2292 		 */
2293 
2294 		/*
2295 		 * For passive side CM set it to remote_ack_delay
2296 		 * For active side CM add the pkt_life_time * 2
2297 		 */
2298 		mutex_enter(&statep->state_mutex);
2299 		statep->timer_value = statep->remote_ack_delay;
2300 		/* statep->mode == IBCM_ACTIVE_MODE) */
2301 		statep->timer_value += (2 * statep->pkt_life_time);
2302 
2303 		statep->remaining_retry_cnt = 0;
2304 		statep->timer_stored_state = statep->state;
2305 
2306 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
2307 
2308 		IBCM_REF_CNT_DECR(statep);
2309 		mutex_exit(&statep->state_mutex);
2310 
2311 	} else if (((statep->state == IBCM_STATE_REQ_RCVD) ||
2312 	    (statep->state == IBCM_STATE_REP_RCVD) ||
2313 	    (statep->state == IBCM_STATE_MRA_SENT) ||
2314 	    (statep->state == IBCM_STATE_MRA_REP_SENT)) &&
2315 	    (b2h16(rej_msg->rej_rejection_reason) == IBT_CM_TIMEOUT)) {
2316 
2317 		if (statep->abort_flag == IBCM_ABORT_INIT)
2318 			statep->abort_flag = IBCM_ABORT_REJ;
2319 
2320 		IBCM_REF_CNT_DECR(statep);
2321 		mutex_exit(&statep->state_mutex);
2322 	} else {
2323 
2324 #ifdef DEBUG
2325 		if ((ibcm_test_mode > 0) &&
2326 		    (statep->state != IBCM_STATE_DELETE))
2327 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_rej_msg: "
2328 			    "Unexpected rej for statep 0x%p in state %d",
2329 			    statep, statep->state);
2330 #endif
2331 		IBCM_REF_CNT_DECR(statep);
2332 		mutex_exit(&statep->state_mutex);
2333 	}
2334 }
2335 
2336 
2337 /*
2338  * ibcm_process_dreq_msg:
2339  *	Processes incoming DREQ message on active/passive side
2340  *
2341  * INPUTS:
2342  *	hcap		- HCA entry pointer
2343  *	input_madp	- CM MAD that is input to this function
2344  *	cm_mad_addr	- Address information for the MAD
2345  *
2346  * RETURN VALUE:	NONE
2347  */
2348 /*ARGSUSED*/
2349 void
2350 ibcm_process_dreq_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
2351     ibcm_mad_addr_t *cm_mad_addr)
2352 {
2353 	void			*priv_data = NULL;
2354 	ibcm_status_t		state_lookup_status;
2355 	ib_qpn_t		local_qpn;
2356 	ibcm_dreq_msg_t		*dreq_msgp =
2357 	    (ibcm_dreq_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
2358 	ibcm_state_data_t	*statep = NULL;
2359 	uint8_t			close_event_type;
2360 	ibt_cm_status_t		cb_status;
2361 
2362 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_dreq_msg:");
2363 
2364 	/* Lookup for an existing state structure */
2365 	rw_enter(&hcap->hca_state_rwlock, RW_READER);
2366 
2367 	state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_DREQ,
2368 	    b2h32(dreq_msgp->dreq_remote_comm_id), 0, 0, hcap, &statep);
2369 	rw_exit(&hcap->hca_state_rwlock);
2370 
2371 	local_qpn = b2h32(dreq_msgp->dreq_remote_qpn_eecn_plus) >> 8;
2372 
2373 	if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
2374 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_dreq_msg: no statep with"
2375 		    "com id %x", b2h32(dreq_msgp->dreq_remote_comm_id));
2376 		/* implies a bogus message */
2377 		return;
2378 	}
2379 
2380 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_dreq_msg: statep 0x%p "
2381 	    "lookup status %x dreq qpn = %x", statep, state_lookup_status,
2382 	    local_qpn);
2383 
2384 	/*
2385 	 * Local QPN check is necessary. There could be a DREQ from
2386 	 * a remote stale connection processing with the same com id, but
2387 	 * not intended for this statep
2388 	 */
2389 	mutex_enter(&statep->state_mutex);
2390 	if ((statep->local_qpn != local_qpn) ||
2391 	    (statep->remote_comid != b2h32(dreq_msgp->dreq_local_comm_id))) {
2392 
2393 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_dreq_msg:"
2394 		    "statep->local_qpn = %x qpn in dreq = %x"
2395 		    "statep->remote_comid = %x local comid in dreq = %x",
2396 		    statep->local_qpn, local_qpn, statep->remote_comid,
2397 		    b2h32(dreq_msgp->dreq_local_comm_id));
2398 
2399 		IBCM_REF_CNT_DECR(statep);
2400 		mutex_exit(&statep->state_mutex);
2401 		return;
2402 	}
2403 	/*
2404 	 * If another thread is processing a copy of this same DREQ,
2405 	 * bail out here.
2406 	 */
2407 	if (statep->state == IBCM_STATE_TRANSIENT_DREQ_SENT ||
2408 	    statep->drep_in_progress) {
2409 		IBCM_REF_CNT_DECR(statep);
2410 		mutex_exit(&statep->state_mutex);
2411 		return;
2412 	}
2413 	switch (statep->state) {
2414 	case IBCM_STATE_ESTABLISHED:
2415 	case IBCM_STATE_DREQ_SENT:
2416 	case IBCM_STATE_TIMEWAIT:
2417 		break;
2418 	default:
2419 		/* All other states ignore DREQ */
2420 		IBCM_REF_CNT_DECR(statep);
2421 		mutex_exit(&statep->state_mutex);
2422 		return;
2423 	}
2424 	statep->drep_in_progress = 1;
2425 
2426 	/*
2427 	 * If drep msg wasn't really required, it shall be deleted finally
2428 	 * when statep goes away
2429 	 */
2430 	if (statep->drep_msg == NULL) {
2431 		mutex_exit(&statep->state_mutex);
2432 		if (ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl,
2433 		    &statep->drep_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
2434 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_dreq_msg: "
2435 			    "statep 0x%p ibcm_alloc_out_msg failed", statep);
2436 			mutex_enter(&statep->state_mutex);
2437 			statep->drep_in_progress = 0;
2438 			IBCM_REF_CNT_DECR(statep);
2439 			mutex_exit(&statep->state_mutex);
2440 			return;
2441 		}
2442 		mutex_enter(&statep->state_mutex);
2443 	}
2444 
2445 	if (statep->state == IBCM_STATE_TRANSIENT_DREQ_SENT) {
2446 		IBCM_REF_CNT_DECR(statep);
2447 		statep->drep_in_progress = 0;
2448 		mutex_exit(&statep->state_mutex);
2449 		return;
2450 	}
2451 
2452 	/*
2453 	 * Need to generate drep, as time wait can be reached either by an
2454 	 * outgoing dreq or an incoming dreq
2455 	 */
2456 	if ((statep->state == IBCM_STATE_ESTABLISHED) ||
2457 	    (statep->state == IBCM_STATE_DREQ_SENT)) {
2458 		timeout_id_t	timer_val = statep->timerid;
2459 
2460 		if (statep->state == IBCM_STATE_DREQ_SENT) {
2461 			statep->state = IBCM_STATE_DREQ_RCVD;
2462 			statep->timerid = 0;
2463 			ibcm_close_done(statep, 0);
2464 			mutex_exit(&statep->state_mutex);
2465 
2466 			close_event_type = IBT_CM_CLOSED_DUP;
2467 			if (timer_val != 0) {
2468 				/* Cancel the timer set for DREP reception */
2469 				(void) untimeout(timer_val);
2470 			}
2471 		} else {	/* In ESTABLISHED State */
2472 			statep->state = IBCM_STATE_DREQ_RCVD;
2473 			statep->clnt_proceed = IBCM_BLOCK;
2474 
2475 			/* Cancel or wait for LAP/APR to complete */
2476 			ibcm_sync_lapr_idle(statep);
2477 			/* The above function releases the state mutex */
2478 
2479 			/* wait until client knows CONN EST event */
2480 			mutex_enter(&statep->state_mutex);
2481 			while (statep->cep_in_rts == IBCM_BLOCK)
2482 				cv_wait(&statep->block_mad_cv,
2483 				    &statep->state_mutex);
2484 			mutex_exit(&statep->state_mutex);
2485 
2486 			close_event_type = IBT_CM_CLOSED_DREQ_RCVD;
2487 			/* Move CEP to error state */
2488 			(void) ibcm_cep_to_error_state(statep);
2489 		}
2490 		mutex_enter(&statep->state_mutex);
2491 		statep->drep_in_progress = 0;
2492 
2493 		IBCM_OUT_HDRP(statep->drep_msg)->TransactionID =
2494 		    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
2495 
2496 		priv_data = &(((ibcm_drep_msg_t *)
2497 		    IBCM_OUT_MSGP(statep->drep_msg))->drep_private_data[0]);
2498 
2499 		if (statep->close_ret_status)
2500 			*statep->close_ret_status = close_event_type;
2501 
2502 		if (statep->close_nocb_state != IBCM_FAIL) {
2503 			ibtl_cm_chan_is_closing(statep->channel);
2504 			statep->close_nocb_state = IBCM_BLOCK;
2505 		}
2506 		mutex_exit(&statep->state_mutex);
2507 
2508 		/*
2509 		 * if close_nocb_state is IBCM_FAIL, then cm_handler is NULL
2510 		 * if close_nocb_state is IBCM_BLOCK, client cannot go away
2511 		 */
2512 		if (statep->cm_handler != NULL) {
2513 			ibt_cm_event_t		event;
2514 			ibt_cm_return_args_t	ret_args;
2515 
2516 			bzero(&event, sizeof (event));
2517 			bzero(&ret_args, sizeof (ret_args));
2518 
2519 			event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
2520 			event.cm_channel = statep->channel;
2521 			event.cm_session_id = statep;
2522 			event.cm_priv_data = dreq_msgp->dreq_private_data;
2523 			event.cm_priv_data_len = IBT_DREQ_PRIV_DATA_SZ;
2524 			event.cm_event.closed = close_event_type;
2525 
2526 			ibcm_insert_trace(statep,
2527 			    IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
2528 
2529 			cb_status = statep->cm_handler(statep->state_cm_private,
2530 			    &event, &ret_args, priv_data,
2531 			    IBT_DREP_PRIV_DATA_SZ);
2532 
2533 			ibcm_insert_trace(statep,
2534 			    IBCM_TRACE_RET_CONN_CLOSE_EVENT);
2535 
2536 			if (cb_status == IBT_CM_DEFER) {
2537 				mutex_enter(&statep->state_mutex);
2538 				statep->clnt_proceed =
2539 				    IBCM_UNBLOCK;
2540 				cv_broadcast(&statep->block_client_cv);
2541 				mutex_exit(&statep->state_mutex);
2542 
2543 				IBTF_DPRINTF_L4(cmlog, "ibcm_process_dreq_msg:"
2544 				    " statep 0x%p client returned DEFER "
2545 				    "response", statep);
2546 				return;
2547 			}
2548 		}
2549 
2550 		/* fail/resume any blocked cm api call */
2551 		mutex_enter(&statep->state_mutex);
2552 
2553 		/* Signal for cm proceed api */
2554 		statep->clnt_proceed = IBCM_FAIL;
2555 
2556 		/* Signal for close with no callbacks */
2557 		statep->close_nocb_state = IBCM_FAIL;
2558 
2559 		/* Signal any waiting close channel thread */
2560 		statep->close_done = B_TRUE;
2561 
2562 		cv_broadcast(&statep->block_client_cv);
2563 		mutex_exit(&statep->state_mutex);
2564 
2565 		ibcm_handle_cep_dreq_response(statep, NULL, 0);
2566 
2567 	} else if (statep->state == IBCM_STATE_TIMEWAIT) {
2568 		statep->drep_in_progress = 0;
2569 		if (statep->send_mad_flags & IBCM_DREP_POST_BUSY) {
2570 			IBCM_REF_CNT_DECR(statep);
2571 			mutex_exit(&statep->state_mutex);
2572 			return;
2573 		}
2574 		statep->send_mad_flags |= IBCM_DREP_POST_BUSY;
2575 
2576 		/* Release statep mutex before posting the MAD */
2577 		mutex_exit(&statep->state_mutex);
2578 
2579 		IBCM_OUT_HDRP(statep->drep_msg)->TransactionID =
2580 		    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
2581 
2582 		ibcm_post_drep_mad(statep);
2583 		/* ref cnt decremented in ibcm_post_drep_complete */
2584 	} else {
2585 #ifdef DEBUG
2586 		if ((ibcm_test_mode > 0) &&
2587 		    (statep->state != IBCM_STATE_DELETE))
2588 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_dreq_msg: "
2589 			    "Unexpected dreq for statep 0x%p in state %d",
2590 			    statep, statep->state);
2591 #endif
2592 		IBCM_REF_CNT_DECR(statep);
2593 		statep->drep_in_progress = 0;
2594 		mutex_exit(&statep->state_mutex);
2595 	}
2596 }
2597 
2598 /*
2599  * ibcm_handle_cep_dreq_response:
2600  *	Processes the response from client handler for an incoming DREQ.
2601  *	The statep ref cnt is decremented before returning.
2602  */
2603 void
2604 ibcm_handle_cep_dreq_response(ibcm_state_data_t *statep, void *priv_data,
2605     ibt_priv_data_len_t priv_data_len)
2606 {
2607 	if ((priv_data != NULL) && (priv_data_len > 0))
2608 		bcopy(priv_data,
2609 		    &(((ibcm_drep_msg_t *)
2610 		    IBCM_OUT_MSGP(statep->drep_msg))->drep_private_data[0]),
2611 		    min(priv_data_len, IBT_DREP_PRIV_DATA_SZ));
2612 
2613 	ibcm_post_drep_mad(statep);
2614 }
2615 
2616 
2617 /*
2618  * ibcm_post_dreq_mad:
2619  *	Posts a DREQ MAD
2620  * Post DREQ now for TIMEWAIT state and DREQ_RCVD
2621  *
2622  * INPUTS:
2623  *	statep		- state pointer
2624  *
2625  * RETURN VALUE:
2626  *	NONE
2627  */
2628 void
2629 ibcm_post_dreq_mad(void *vstatep)
2630 {
2631 	ibcm_state_data_t	*statep = vstatep;
2632 	ibcm_dreq_msg_t		*dreq_msgp;
2633 
2634 	ASSERT(statep->dreq_msg != NULL);
2635 
2636 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dreq_msgp))
2637 
2638 	/* Fill in the DREQ message */
2639 	dreq_msgp = (ibcm_dreq_msg_t *)IBCM_OUT_MSGP(statep->dreq_msg);
2640 	dreq_msgp->dreq_local_comm_id = h2b32(statep->local_comid);
2641 	dreq_msgp->dreq_remote_comm_id = h2b32(statep->remote_comid);
2642 	dreq_msgp->dreq_remote_qpn_eecn_plus = h2b32(statep->remote_qpn << 8);
2643 
2644 	IBCM_OUT_HDRP(statep->dreq_msg)->AttributeID =
2645 	    h2b16(IBCM_INCOMING_DREQ + IBCM_ATTR_BASE_ID);
2646 
2647 	/* wait until client knows CONN EST event */
2648 	mutex_enter(&statep->state_mutex);
2649 	while (statep->cep_in_rts == IBCM_BLOCK)
2650 		cv_wait(&statep->block_mad_cv, &statep->state_mutex);
2651 	mutex_exit(&statep->state_mutex);
2652 
2653 	/* Transition QP/EEC state to ERROR state */
2654 	(void) ibcm_cep_to_error_state(statep);
2655 
2656 	IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID =
2657 	    h2b64(ibcm_generate_tranid(IBCM_INCOMING_DREQ, statep->local_comid,
2658 	    0));
2659 
2660 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*dreq_msgp))
2661 
2662 	/* post the first DREQ via timeout callback */
2663 	mutex_enter(&statep->state_mutex);
2664 
2665 	statep->state = IBCM_STATE_DREQ_SENT;
2666 	cv_broadcast(&statep->block_mad_cv);
2667 
2668 	statep->timer_stored_state = statep->state;
2669 	/* client cannot specify more than 16 retries */
2670 	statep->timer_value = statep->remote_ack_delay;
2671 	if (statep->mode == IBCM_ACTIVE_MODE) {
2672 		statep->timer_value += (2 * statep->pkt_life_time);
2673 	}
2674 	statep->remaining_retry_cnt = statep->max_cm_retries + 1;
2675 	statep->timerid = IBCM_TIMEOUT(statep, 0);
2676 	mutex_exit(&statep->state_mutex);
2677 }
2678 
2679 /*
2680  * ibcm_post_drep_mad:
2681  *	Posts a DREP MAD
2682  * Post DREP now for TIMEWAIT state and DREQ_RCVD
2683  *
2684  * INPUTS:
2685  *	statep		- state pointer
2686  *
2687  * RETURN VALUE:
2688  *	NONE
2689  */
2690 static void
2691 ibcm_post_drep_mad(ibcm_state_data_t *statep)
2692 {
2693 	ibcm_drep_msg_t	*drep_msgp;
2694 
2695 	drep_msgp = (ibcm_drep_msg_t *)IBCM_OUT_MSGP(statep->drep_msg);
2696 
2697 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*drep_msgp))
2698 
2699 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_drep_mad:");
2700 
2701 	/* Fill up DREP fields */
2702 	drep_msgp->drep_local_comm_id = h2b32(statep->local_comid);
2703 	drep_msgp->drep_remote_comm_id = h2b32(statep->remote_comid);
2704 	IBCM_OUT_HDRP(statep->drep_msg)->AttributeID =
2705 	    h2b16(IBCM_INCOMING_DREP + IBCM_ATTR_BASE_ID);
2706 
2707 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*drep_msgp))
2708 
2709 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_DREP);
2710 
2711 	/* Post the DREP MAD now.  */
2712 	ibcm_post_rc_mad(statep, statep->drep_msg, ibcm_post_drep_complete,
2713 	    statep);
2714 }
2715 
2716 /*
2717  * ibcm_process_drep_msg:
2718  *	Processes incoming DREP message on active/passive side
2719  *
2720  * INPUTS:
2721  *	hcap		- HCA entry pointer
2722  *	input_madp	- CM MAD that is input to this function
2723  *	cm_mad_addr	- Address information for the MAD
2724  *
2725  * RETURN VALUE: NONE
2726  */
2727 /* ARGSUSED */
2728 void
2729 ibcm_process_drep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
2730     ibcm_mad_addr_t *cm_mad_addr)
2731 {
2732 	ibcm_status_t		state_lookup_status;
2733 	ibcm_drep_msg_t		*drep_msgp =
2734 	    (ibcm_drep_msg_t *)(&input_madp[IBCM_MAD_HDR_SIZE]);
2735 	ibcm_state_data_t	*statep = NULL;
2736 
2737 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_drep_msg:");
2738 
2739 	/* Lookup for an existing state structure */
2740 	rw_enter(&hcap->hca_state_rwlock, RW_READER);
2741 
2742 	state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_DREP,
2743 	    b2h32(drep_msgp->drep_remote_comm_id), 0, 0, hcap, &statep);
2744 	rw_exit(&hcap->hca_state_rwlock);
2745 
2746 	if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
2747 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_drep_msg: no statep with"
2748 		    "com id %x", b2h32(drep_msgp->drep_remote_comm_id));
2749 		return;
2750 	}
2751 
2752 	/* if transaction id is not as expected, drop the DREP mad */
2753 	if (IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID !=
2754 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
2755 		mutex_enter(&statep->state_mutex);
2756 		IBCM_REF_CNT_DECR(statep);
2757 		mutex_exit(&statep->state_mutex);
2758 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_drep_msg: statep 0x%p "
2759 		    "DREP with tid expected 0x%llX tid found 0x%llX", statep,
2760 		    b2h64(IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID),
2761 		    b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID));
2762 		return;
2763 	}
2764 
2765 	ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_DREP);
2766 
2767 	mutex_enter(&statep->state_mutex);
2768 
2769 	if (statep->state == IBCM_STATE_DREQ_SENT) {
2770 		timeout_id_t	timer_val = statep->timerid;
2771 
2772 		statep->state = IBCM_STATE_DREP_RCVD;
2773 
2774 		statep->timerid = 0;
2775 		mutex_exit(&statep->state_mutex);
2776 		(void) untimeout(timer_val);
2777 
2778 		if (statep->stale == B_TRUE)
2779 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_drep_msg: "
2780 			    "statep 0x%p Unexpected DREP received for a stale "
2781 			    "DREQ sent", statep);
2782 
2783 		mutex_enter(&statep->state_mutex);
2784 		/* allow free qp, if close channel with NOCALLBACKS didn't */
2785 		if (statep->close_nocb_state != IBCM_FAIL) {
2786 			ibtl_cm_chan_is_closing(statep->channel);
2787 			statep->close_nocb_state = IBCM_BLOCK;
2788 		}
2789 		mutex_exit(&statep->state_mutex);
2790 
2791 		/* if close_nocb_state is IBCM_FAIL, then cm_handler is NULL */
2792 		if (statep->cm_handler != NULL) {
2793 			ibt_cm_event_t		event;
2794 			ibt_cm_return_args_t	ret_args;
2795 
2796 			bzero(&event, sizeof (event));
2797 			bzero(&ret_args, sizeof (ret_args));
2798 
2799 			event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
2800 			event.cm_channel = statep->channel;
2801 			event.cm_session_id = NULL;
2802 
2803 			if (statep->stale == B_TRUE) {
2804 				event.cm_event.closed = IBT_CM_CLOSED_STALE;
2805 				event.cm_priv_data = NULL;
2806 				event.cm_priv_data_len = 0;
2807 			} else {
2808 				event.cm_event.closed = IBT_CM_CLOSED_DREP_RCVD;
2809 				event.cm_priv_data =
2810 				    drep_msgp->drep_private_data;
2811 				event.cm_priv_data_len = IBT_DREP_PRIV_DATA_SZ;
2812 			}
2813 
2814 			ibcm_insert_trace(statep,
2815 			    IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
2816 
2817 			(void) statep->cm_handler(statep->state_cm_private,
2818 			    &event, &ret_args, NULL, 0);
2819 
2820 			ibcm_insert_trace(statep,
2821 			    IBCM_TRACE_RET_CONN_CLOSE_EVENT);
2822 		}
2823 
2824 		/* copy the private to close channel, if specified */
2825 		if ((statep->close_ret_priv_data != NULL) &&
2826 		    (statep->close_ret_priv_data_len != NULL) &&
2827 		    (*statep->close_ret_priv_data_len > 0)) {
2828 			bcopy(drep_msgp->drep_private_data,
2829 			    statep->close_ret_priv_data,
2830 			    min(*statep->close_ret_priv_data_len,
2831 			    IBT_DREP_PRIV_DATA_SZ));
2832 		}
2833 
2834 		mutex_enter(&statep->state_mutex);
2835 		if (statep->close_ret_status)
2836 			*statep->close_ret_status = IBT_CM_CLOSED_DREP_RCVD;
2837 		/* signal waiting CV - blocking in ibt_close_channel() */
2838 		statep->close_done = B_TRUE;
2839 
2840 		/* signal any blocked close channels with no callbacks */
2841 		statep->close_nocb_state = IBCM_FAIL;
2842 
2843 		cv_broadcast(&statep->block_client_cv);
2844 
2845 		/* Set the timer wait state timer */
2846 		statep->state = statep->timer_stored_state =
2847 		    IBCM_STATE_TIMEWAIT;
2848 		ibcm_close_done(statep, 0);
2849 
2850 		statep->remaining_retry_cnt = 0;
2851 		/*
2852 		 * For passive side CM set it to remote_ack_delay
2853 		 * For active side CM add the pkt_life_time * 2
2854 		 */
2855 		statep->timer_value = statep->remote_ack_delay;
2856 		if (statep->mode == IBCM_ACTIVE_MODE) {
2857 			statep->timer_value += (2 * statep->pkt_life_time);
2858 		}
2859 
2860 		/* start TIMEWAIT processing */
2861 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
2862 	}
2863 
2864 	/* There is no processing required for other states */
2865 	IBCM_REF_CNT_DECR(statep);
2866 	mutex_exit(&statep->state_mutex);
2867 }
2868 
2869 /*
2870  * Following are the routines used to resend various CM MADs as a response to
2871  * incoming MADs
2872  */
2873 void
2874 ibcm_resend_rtu_mad(ibcm_state_data_t *statep)
2875 {
2876 	ASSERT(MUTEX_HELD(&statep->state_mutex));
2877 
2878 	IBTF_DPRINTF_L3(cmlog, "ibcm_resend_rtu_mad statep %p ", statep);
2879 
2880 	/* don't care, if timer is running or not. Timer may be from LAP */
2881 
2882 	if (!(statep->send_mad_flags & IBCM_RTU_POST_BUSY)) {
2883 		statep->send_mad_flags |= IBCM_RTU_POST_BUSY;
2884 		IBCM_REF_CNT_INCR(statep);	/* for non-blocking RTU post */
2885 		mutex_exit(&statep->state_mutex);
2886 
2887 		ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_RTU);
2888 
2889 		ibcm_post_rc_mad(statep, statep->stored_msg,
2890 		    ibcm_post_rtu_complete, statep);
2891 		mutex_enter(&statep->state_mutex);
2892 	}
2893 	/* ref cnt is decremented in ibcm_post_rtu_complete */
2894 }
2895 
2896 void
2897 ibcm_resend_rej_mad(ibcm_state_data_t *statep)
2898 {
2899 	timeout_id_t		timer_val = statep->timerid;
2900 
2901 	ASSERT(MUTEX_HELD(&statep->state_mutex));
2902 
2903 	IBTF_DPRINTF_L3(cmlog, "ibcm_resend_rej_mad statep %p ", statep);
2904 
2905 	/* It's a too fast of a REQ or REP */
2906 	if (timer_val == 0)
2907 		return;
2908 
2909 	statep->timerid = 0;
2910 	if (!(statep->send_mad_flags & IBCM_REJ_POST_BUSY)) {
2911 		statep->send_mad_flags |= IBCM_REJ_POST_BUSY;
2912 		IBCM_REF_CNT_INCR(statep);	/* for nonblocking REJ post */
2913 		mutex_exit(&statep->state_mutex);
2914 		(void) untimeout(timer_val);
2915 
2916 		ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REJ);
2917 		if (ibcm_enable_trace & 2)
2918 			ibcm_dump_conn_trace(statep);
2919 		else
2920 			IBTF_DPRINTF_L2(cmlog, "ibcm_resend_rej_mad statep %p "
2921 			    "OUTGOING_REJ", statep);
2922 
2923 		ibcm_post_rc_mad(statep, statep->stored_msg,
2924 		    ibcm_post_rej_complete, statep);
2925 		mutex_enter(&statep->state_mutex);
2926 	}
2927 	/* return, holding the state mutex */
2928 }
2929 
2930 void
2931 ibcm_resend_rep_mad(ibcm_state_data_t *statep)
2932 {
2933 	timeout_id_t		timer_val = statep->timerid;
2934 
2935 	ASSERT(MUTEX_HELD(&statep->state_mutex));
2936 
2937 	IBTF_DPRINTF_L3(cmlog, "ibcm_resend_rep_mad statep %p ", statep);
2938 
2939 	/* REP timer that is set by ibcm_post_rep_mad */
2940 	if (timer_val != 0) {
2941 		/* Re-start REP timeout */
2942 		statep->remaining_retry_cnt = statep->max_cm_retries;
2943 		if (!(statep->send_mad_flags & IBCM_REP_POST_BUSY)) {
2944 			statep->send_mad_flags |= IBCM_REP_POST_BUSY;
2945 			/* for nonblocking REP post */
2946 			IBCM_REF_CNT_INCR(statep);
2947 			mutex_exit(&statep->state_mutex);
2948 
2949 			ibcm_insert_trace(statep, IBCM_TRACE_OUT_REP_RETRY);
2950 
2951 			ibcm_post_rc_mad(statep, statep->stored_msg,
2952 			    ibcm_resend_post_rep_complete, statep);
2953 			mutex_enter(&statep->state_mutex);
2954 		}
2955 	}
2956 
2957 	/*
2958 	 * else, timer is not yet set by ibcm_post_rep_mad. This is too fast
2959 	 * of a REQ being re-transmitted.
2960 	 */
2961 }
2962 
2963 void
2964 ibcm_resend_mra_mad(ibcm_state_data_t *statep)
2965 {
2966 	ASSERT(MUTEX_HELD(&statep->state_mutex));
2967 
2968 	IBTF_DPRINTF_L3(cmlog, "ibcm_resend_mra_mad statep %p ", statep);
2969 
2970 	if (statep->send_mad_flags & IBCM_MRA_POST_BUSY)
2971 		return;
2972 
2973 	statep->send_mad_flags |= IBCM_MRA_POST_BUSY;
2974 
2975 	statep->mra_time = gethrtime();
2976 	IBCM_REF_CNT_INCR(statep); 	/* for non-blocking MRA post */
2977 	/* Exit the statep mutex, before sending the MAD */
2978 	mutex_exit(&statep->state_mutex);
2979 
2980 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_MRA);
2981 
2982 	/* Always resend the response MAD to the original reply destination */
2983 	ibcm_post_rc_mad(statep, statep->mra_msg, ibcm_post_mra_complete,
2984 	    statep);
2985 
2986 	mutex_enter(&statep->state_mutex);
2987 
2988 	/* return, holding the state mutex */
2989 }
2990 
2991 
2992 /*
2993  * ibcm_post_rej_mad:
2994  *	Posts a REJ MAD and starts timer
2995  *
2996  * INPUTS:
2997  *	statep		- state pointer
2998  *	which_msg	- which message is being MRAed
2999  *	reject_reason	- Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
3000  *	addl_rej_info	- Additional rej Information
3001  *	arej_info_len	- Additional rej Info length
3002  *
3003  * RETURN VALUE:
3004  *	NONE
3005  * Notes
3006  *  There is no need to hold the statep->mutex and call ibcm_post_rej_mad
3007  *  REJ can be posted either in IBCM_STATE_REQ_RCVD or IBCM_STATE_REP_RCVD
3008  *  In these states, there is no timer active, and an incoming REJ shall
3009  *  not modify the state or cancel timers
3010  *  An incoming REJ doesn't affect statep in state = IBCM_STATE_REJ_SENT/BUSY
3011  */
3012 void
3013 ibcm_post_rej_mad(ibcm_state_data_t *statep, ibt_cm_reason_t reject_reason,
3014     int which_msg, void *addl_rej_info, ibt_priv_data_len_t arej_info_len)
3015 {
3016 	ibcm_rej_msg_t	*rej_msg =
3017 	    (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3018 
3019 	/* Message printed if connection gets REJed */
3020 	IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_mad: "
3021 	    "statep = %p, reject_reason = %d", statep, reject_reason);
3022 
3023 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3024 
3025 	/* Initialize rej_msg fields */
3026 	rej_msg->rej_local_comm_id = h2b32(statep->local_comid);
3027 	rej_msg->rej_remote_comm_id = h2b32(statep->remote_comid);
3028 	rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3029 	rej_msg->rej_reject_info_len_plus = arej_info_len << 1;
3030 	rej_msg->rej_rejection_reason = h2b16((uint16_t)reject_reason);
3031 
3032 	if ((arej_info_len != 0) && (addl_rej_info != NULL))
3033 		bcopy(addl_rej_info, rej_msg->rej_addl_rej_info, arej_info_len);
3034 
3035 	IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3036 	    h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3037 
3038 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3039 
3040 	mutex_enter(&statep->state_mutex);
3041 
3042 	/* signal any waiting close channels with blocking or no callbacks  */
3043 	statep->close_done = B_TRUE;
3044 	statep->close_nocb_state = IBCM_FAIL;
3045 
3046 	cv_signal(&statep->block_client_cv);
3047 
3048 	statep->timer_stored_state = statep->state = IBCM_STATE_REJ_SENT;
3049 	statep->send_mad_flags |= IBCM_REJ_POST_BUSY;
3050 
3051 	IBCM_REF_CNT_INCR(statep); /* for non-blocking post */
3052 	mutex_exit(&statep->state_mutex);
3053 
3054 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REJ);
3055 	if (ibcm_enable_trace & 2)
3056 		ibcm_dump_conn_trace(statep);
3057 	else
3058 		IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_mad statep %p "
3059 		    "OUTGOING_REJ", statep);
3060 
3061 	ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_rej_complete,
3062 	    statep);
3063 }
3064 
3065 
3066 /*
3067  * ibcm_build_n_post_rej_mad:
3068  *	Builds and posts a REJ MAD for "reject_reason"
3069  *	Doesn't set a timer, and doesn't need statep
3070  *
3071  * INPUTS:
3072  *	input_madp	- Incoming MAD
3073  *	remote_comid	- Local comid in the message being rejected
3074  *	cm_mad_addr	- Address information for the MAD to be posted
3075  *	which_msg	- REJ message type ie., REJ for REQ/REP
3076  *
3077  * RETURN VALUE:
3078  *	NONE
3079  */
3080 static void
3081 ibcm_build_n_post_rej_mad(uint8_t *input_madp, ib_com_id_t remote_comid,
3082     ibcm_mad_addr_t *cm_mad_addr, int which_msg, uint16_t reject_reason)
3083 {
3084 	ibcm_rej_msg_t	*rej_msg;
3085 	ibmf_msg_t	*cm_rej_msg;
3086 	ibcm_mad_addr_t	rej_reply_addr;
3087 
3088 	IBTF_DPRINTF_L3(cmlog, "ibcm_build_n_post_rej_mad: "
3089 	    "remote_comid: %x reject_reason %d", remote_comid, reject_reason);
3090 
3091 	if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3092 	    MAD_METHOD_SEND) != IBT_SUCCESS) {
3093 		IBTF_DPRINTF_L2(cmlog, "ibcm_build_n_post_rej_mad: "
3094 		    "ibcm_alloc_out_msg failed");
3095 		return;
3096 	}
3097 
3098 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3099 
3100 	IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3101 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3102 
3103 	/* Initialize rej_msg fields */
3104 	rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3105 	rej_msg->rej_local_comm_id = 0;
3106 	rej_msg->rej_remote_comm_id = h2b32(remote_comid);
3107 	rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3108 	rej_msg->rej_reject_info_len_plus = 0;
3109 	rej_msg->rej_rejection_reason = h2b16(reject_reason);
3110 
3111 	IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3112 	    h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3113 
3114 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3115 
3116 	ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3117 
3118 	if (rej_reply_addr.cm_qp_entry != NULL) {
3119 		(void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3120 		ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3121 	}
3122 
3123 	(void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3124 }
3125 
3126 /* posts a REJ for an incoming REQ with unsupported class version */
3127 
3128 static void
3129 ibcm_post_rej_ver_mismatch(uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr)
3130 {
3131 	ibcm_req_msg_t	*req_msgp =
3132 	    (ibcm_req_msg_t *)&input_madp[IBCM_MAD_HDR_SIZE];
3133 	ibcm_rej_msg_t	*rej_msg;
3134 	ibmf_msg_t	*cm_rej_msg;
3135 	ibcm_mad_addr_t	rej_reply_addr;
3136 
3137 	IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_ver_mismatch: remote comid %x",
3138 	    b2h32(req_msgp->req_local_comm_id));
3139 
3140 	if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3141 	    MAD_METHOD_SEND) != IBT_SUCCESS) {
3142 		IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_ver_mismatch: "
3143 		    "ibcm_alloc_out_msg failed");
3144 		return;
3145 	}
3146 
3147 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3148 
3149 	IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3150 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3151 
3152 	/* Initialize rej_msg fields */
3153 	rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3154 	rej_msg->rej_local_comm_id = 0;
3155 	rej_msg->rej_remote_comm_id = req_msgp->req_local_comm_id;
3156 	rej_msg->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
3157 	rej_msg->rej_rejection_reason = h2b16(IBT_CM_CLASS_NO_SUPPORT);
3158 	rej_msg->rej_reject_info_len_plus = 1 << 1;
3159 	rej_msg->rej_addl_rej_info[0] = IBCM_MAD_CLASS_VERSION;
3160 
3161 	IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3162 	    h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3163 	IBCM_OUT_HDRP(cm_rej_msg)->Status = h2b16(MAD_STATUS_BAD_VERSION);
3164 
3165 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3166 
3167 	ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3168 	if (rej_reply_addr.cm_qp_entry != NULL) {
3169 		(void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3170 		ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3171 	}
3172 	(void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3173 }
3174 
3175 
3176 /*
3177  * ibcm_post_rep_mad:
3178  *	Posts a REP MAD and starts timer
3179  *
3180  * INPUTS:
3181  *	statep		- state pointer
3182  *
3183  * RETURN VALUE:
3184  *	NONE
3185  */
3186 void
3187 ibcm_post_rep_mad(ibcm_state_data_t *statep)
3188 {
3189 	ibcm_rep_msg_t	*rep_msgp =
3190 	    (ibcm_rep_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3191 	ibmf_msg_t	*mra_msg = NULL;
3192 	boolean_t	ret = B_FALSE;
3193 
3194 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_mad: statep 0x%p", statep);
3195 
3196 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp))
3197 
3198 	/*
3199 	 * All other REP fields, other that the 2 below, are filled in
3200 	 * the ibcm_cep_state_req() function.
3201 	 */
3202 	rep_msgp->rep_local_comm_id = h2b32(statep->local_comid);
3203 	rep_msgp->rep_remote_comm_id = h2b32(statep->remote_comid);
3204 	IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3205 	    h2b16(IBCM_INCOMING_REP + IBCM_ATTR_BASE_ID);
3206 
3207 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp))
3208 
3209 	/*
3210 	 * Changing state and attempt to delete the mra msg must be done
3211 	 * together holding the state_mutex
3212 	 */
3213 	mutex_enter(&statep->state_mutex);
3214 
3215 	/* Now, attempt to delete the mra_msg, if there is one allocated */
3216 	if (statep->mra_msg != NULL) {
3217 		if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3218 			mra_msg = statep->mra_msg;
3219 			statep->mra_msg = NULL;
3220 		} else statep->delete_mra_msg = B_TRUE;
3221 	}
3222 
3223 	if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3224 		statep->state = IBCM_STATE_ABORTED;
3225 		mutex_exit(&statep->state_mutex);
3226 		ibcm_process_abort(statep);
3227 
3228 		/* Now post a REJ MAD, rej reason consumer abort */
3229 		ibcm_post_rej_mad(statep, IBT_CM_CONSUMER, IBT_CM_FAILURE_REQ,
3230 		    NULL, 0);
3231 		ret = B_TRUE;
3232 	} else if (statep->abort_flag & IBCM_ABORT_REJ) {
3233 
3234 		statep->state = IBCM_STATE_DELETE;
3235 		mutex_exit(&statep->state_mutex);
3236 
3237 		ibcm_process_abort(statep);
3238 		ibcm_delete_state_data(statep);
3239 		ret = B_TRUE;
3240 	} else {
3241 
3242 		statep->state = statep->timer_stored_state =
3243 		    IBCM_STATE_REP_SENT;
3244 		statep->remaining_retry_cnt = statep->max_cm_retries;
3245 		statep->send_mad_flags |= IBCM_REP_POST_BUSY;
3246 		IBCM_REF_CNT_INCR(statep);	/* for nonblocking REP Post */
3247 		mutex_exit(&statep->state_mutex);
3248 	}
3249 
3250 	if (mra_msg != NULL)
3251 		(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
3252 		    &mra_msg);
3253 	if (ret == B_TRUE)
3254 		return;
3255 
3256 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REP);
3257 
3258 	ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_rep_complete,
3259 	    statep);
3260 }
3261 
3262 
3263 /*
3264  * ibcm_post_rtu_mad:
3265  *	From active side post RTU MAD
3266  *
3267  * INPUTS:
3268  *	statep		- state pointer
3269  *
3270  * RETURN VALUE: NONE
3271  *
3272  * NOTE: No timer set after posting RTU
3273  */
3274 ibcm_status_t
3275 ibcm_post_rtu_mad(ibcm_state_data_t *statep)
3276 {
3277 	ibcm_rtu_msg_t	*rtu_msg;
3278 	ibmf_msg_t	*mra_msg = NULL;
3279 	boolean_t	ret = B_FALSE;
3280 
3281 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_rtu_mad: statep 0x%p", statep);
3282 
3283 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rtu_msg))
3284 
3285 	rtu_msg = (ibcm_rtu_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3286 
3287 	rtu_msg->rtu_local_comm_id = h2b32(statep->local_comid);
3288 	rtu_msg->rtu_remote_comm_id = h2b32(statep->remote_comid);
3289 	IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3290 	    h2b16(IBCM_INCOMING_RTU + IBCM_ATTR_BASE_ID);
3291 
3292 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rtu_msg))
3293 
3294 	mutex_enter(&statep->state_mutex);
3295 
3296 	/* Now, attempt to delete the mra_msg, if there is one allocated */
3297 	if (statep->mra_msg != NULL) {
3298 		if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3299 			mra_msg = statep->mra_msg;
3300 			statep->mra_msg = NULL;
3301 		} else statep->delete_mra_msg = B_TRUE;
3302 	}
3303 
3304 	if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3305 		statep->state = IBCM_STATE_ABORTED;
3306 		mutex_exit(&statep->state_mutex);
3307 
3308 		ibcm_process_abort(statep);
3309 
3310 		/* Now post a REJ MAD */
3311 		ibcm_post_rej_mad(statep, IBT_CM_CONSUMER, IBT_CM_FAILURE_REP,
3312 		    NULL, 0);
3313 		ret = B_TRUE;
3314 	} else if (statep->abort_flag & IBCM_ABORT_REJ) {
3315 		statep->state = IBCM_STATE_DELETE;
3316 		mutex_exit(&statep->state_mutex);
3317 
3318 		ibcm_process_abort(statep);
3319 		ibcm_delete_state_data(statep);
3320 		ret = B_TRUE;
3321 	} else {
3322 		statep->state = IBCM_STATE_ESTABLISHED;
3323 		ibtl_cm_chan_is_open(statep->channel);
3324 		statep->send_mad_flags |= IBCM_RTU_POST_BUSY;
3325 		IBCM_REF_CNT_INCR(statep);	/* for nonblocking RTU post */
3326 		mutex_exit(&statep->state_mutex);
3327 	}
3328 
3329 	if (mra_msg != NULL)
3330 		(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
3331 		    &mra_msg);
3332 
3333 	if (ret == B_TRUE)	/* Abort case, no RTU posted */
3334 		return (IBCM_FAILURE);
3335 
3336 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_RTU);
3337 
3338 	ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_rtu_complete,
3339 	    statep);
3340 	return (IBCM_SUCCESS);
3341 }
3342 
3343 
3344 /*
3345  * ibcm_process_abort:
3346  * 	Processes abort, if client requested abort connection attempt
3347  *
3348  * INPUTS:
3349  *	statep	- pointer to ibcm_state_data_t is passed
3350  *
3351  * RETURN VALUES: None
3352  */
3353 void
3354 ibcm_process_abort(ibcm_state_data_t *statep)
3355 {
3356 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_abort: statep 0x%p", statep);
3357 
3358 	/* move CEP to error state, before calling client handler */
3359 	(void) ibcm_cep_to_error_state(statep);
3360 
3361 	/* Now disassociate the link between statep and qp */
3362 	IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
3363 
3364 	/* invoke cm handler, for non-blocking open/close rc channel calls */
3365 	if (statep->cm_handler) { /* cannot be NULL, but still .. */
3366 		ibt_cm_event_t		event;
3367 		ibt_cm_return_args_t	ret_args;
3368 
3369 		bzero(&event, sizeof (event));
3370 		bzero(&ret_args, sizeof (ret_args));
3371 
3372 		if (statep->abort_flag & IBCM_ABORT_REJ)
3373 			ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_RCV,
3374 			    IBT_CM_FAILURE_UNKNOWN, IBT_CM_TIMEOUT, NULL, 0);
3375 		else {
3376 			ibcm_path_cache_purge();
3377 
3378 			event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
3379 			event.cm_channel = statep->channel;
3380 			event.cm_event.closed = IBT_CM_CLOSED_ABORT;
3381 
3382 			ibcm_insert_trace(statep,
3383 			    IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
3384 
3385 			(void) statep->cm_handler(statep->state_cm_private,
3386 			    &event, &ret_args, NULL, 0);
3387 
3388 			ibcm_insert_trace(statep,
3389 			    IBCM_TRACE_RET_CONN_CLOSE_EVENT);
3390 
3391 			mutex_enter(&statep->state_mutex);
3392 			ibcm_open_done(statep);
3393 			mutex_exit(&statep->state_mutex);
3394 		}
3395 	}
3396 
3397 	/*
3398 	 * Unblock an ibt_open_rc_channel called in a blocking mode, though
3399 	 * it is an unlikely scenario
3400 	 */
3401 	mutex_enter(&statep->state_mutex);
3402 
3403 	statep->cm_retries++; /* cause connection trace to be printed */
3404 	statep->open_done = B_TRUE;
3405 	statep->close_done = B_TRUE;
3406 	statep->close_nocb_state = IBCM_FAIL; /* sanity sake */
3407 
3408 	if (statep->open_return_data != NULL) {
3409 		/* REJ came first, and then client aborted connection */
3410 		if (statep->abort_flag & IBCM_ABORT_REJ)
3411 			statep->open_return_data->rc_status = IBT_CM_TIMEOUT;
3412 		else statep->open_return_data->rc_status = IBT_CM_ABORT;
3413 	}
3414 
3415 	cv_broadcast(&statep->block_client_cv);
3416 	mutex_exit(&statep->state_mutex);
3417 	if (ibcm_enable_trace != 0)
3418 		ibcm_dump_conn_trace(statep);
3419 }
3420 
3421 /*
3422  * ibcm_timeout_cb:
3423  *	Called when the timer expires
3424  *
3425  * INPUTS:
3426  *	arg	- ibcm_state_data_t is passed
3427  *
3428  * RETURN VALUES: NONE
3429  */
3430 void
3431 ibcm_timeout_cb(void *arg)
3432 {
3433 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)arg;
3434 
3435 	mutex_enter(&statep->state_mutex);
3436 
3437 	/*
3438 	 * The blocking operations are handled in a separate thread.
3439 	 * All other non-blocking operations, including ibmf non-blocking
3440 	 * posts are done from timeout context
3441 	 */
3442 
3443 	if ((statep->timer_stored_state != statep->state) ||
3444 	    ((statep->timer_stored_state == IBCM_STATE_ESTABLISHED) &&
3445 	    (statep->ap_state != statep->timer_stored_ap_state))) {
3446 		mutex_exit(&statep->state_mutex);
3447 		return;
3448 	}
3449 
3450 	IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: statep 0x%p state %x "
3451 	    "ap_state %x", statep, statep->state, statep->ap_state);
3452 
3453 	/* Processing depends upon current state */
3454 
3455 	if (statep->state == IBCM_STATE_REJ_SENT) {
3456 		statep->state = IBCM_STATE_DELETE;
3457 		mutex_exit(&statep->state_mutex);
3458 
3459 		/* Deallocate the CM state structure */
3460 		ibcm_delete_state_data(statep);
3461 		return;
3462 
3463 	} else if (statep->state == IBCM_STATE_TIMEWAIT) {
3464 		statep->state = IBCM_STATE_DELETE;
3465 
3466 		/* TIME_WAIT timer expired, so cleanup */
3467 		mutex_exit(&statep->state_mutex);
3468 
3469 		if (statep->channel)
3470 			ibtl_cm_chan_is_closed(statep->channel);
3471 
3472 		if (statep->recycle_arg) {
3473 			struct ibcm_taskq_recycle_arg_s *recycle_arg;
3474 
3475 			recycle_arg = statep->recycle_arg;
3476 
3477 			_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
3478 			    statep->recycle_arg))
3479 			statep->recycle_arg = NULL;
3480 			_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
3481 
3482 			/* if possible, do not slow down calling recycle func */
3483 			if (taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
3484 			    recycle_arg, TQ_NOQUEUE | TQ_NOSLEEP) == 0) {
3485 
3486 				_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
3487 				    statep->recycle_arg))
3488 				statep->recycle_arg = recycle_arg;
3489 				_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
3490 				    statep->recycle_arg))
3491 				ibcm_add_tlist(statep);
3492 				return;
3493 			}
3494 		}
3495 
3496 		ibcm_delete_state_data(statep);
3497 		return;
3498 	} else if (statep->remaining_retry_cnt > 0) {
3499 		ibcm_conn_state_t	stored_state;
3500 		ibcm_ap_state_t		stored_ap_state;
3501 
3502 		statep->remaining_retry_cnt--;
3503 		IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: statep 0x%p "
3504 		    "attr-id= 0x%x, retries remaining = 0x%x", statep,
3505 		    b2h16(IBCM_OUT_HDRP(statep->stored_msg)->AttributeID),
3506 		    statep->remaining_retry_cnt);
3507 
3508 		/*
3509 		 * REP could be resent, either because of timeout or an
3510 		 * incoming REQ. Any other MAD below can be resent, because
3511 		 * of timeout only, hence send_mad_flag manipulation not
3512 		 * required for those cases.
3513 		 * If REP is already being retransmitted, then just set the
3514 		 * timer and return. Else post REP in non-blocking mode
3515 		 */
3516 		if (statep->timer_stored_state == IBCM_STATE_REP_SENT) {
3517 			if (statep->send_mad_flags & IBCM_REP_POST_BUSY) {
3518 				statep->timerid = IBCM_TIMEOUT(statep,
3519 				    statep->timer_value);
3520 				mutex_exit(&statep->state_mutex);
3521 				ibcm_insert_trace(statep,
3522 				    IBCM_TRACE_TIMEOUT_REP);
3523 				return;
3524 			}
3525 
3526 			/*
3527 			 * Set REP  busy flag, so any incoming REQ's will not
3528 			 * initiate new REP transmissions
3529 			 */
3530 			statep->send_mad_flags |= IBCM_REP_POST_BUSY;
3531 
3532 		/* Since REQ/RTU/REJ on active side use same MAD, synchronize */
3533 		} else if (statep->timer_stored_state == IBCM_STATE_REQ_SENT) {
3534 			ASSERT((statep->send_mad_flags & IBCM_REQ_POST_BUSY)
3535 			    == 0);
3536 			statep->send_mad_flags |= IBCM_REQ_POST_BUSY;
3537 		}
3538 
3539 		IBCM_REF_CNT_INCR(statep);	/* for non-blocking post */
3540 		stored_state = statep->timer_stored_state;
3541 		stored_ap_state = statep->timer_stored_ap_state;
3542 		mutex_exit(&statep->state_mutex);
3543 
3544 		/* Post REQ MAD in non-blocking mode */
3545 		if (stored_state == IBCM_STATE_REQ_SENT) {
3546 			ibcm_insert_trace(statep, IBCM_TRACE_OUT_REQ_RETRY);
3547 			ibcm_post_rc_mad(statep, statep->stored_msg,
3548 			    ibcm_post_req_complete, statep);
3549 		/* Post REQ MAD in non-blocking mode */
3550 		} else if (stored_state == IBCM_STATE_REP_WAIT) {
3551 			ibcm_insert_trace(statep, IBCM_TRACE_OUT_REQ_RETRY);
3552 			ibcm_post_rc_mad(statep, statep->stored_msg,
3553 			    ibcm_post_rep_wait_complete, statep);
3554 		/* Post REP MAD in non-blocking mode */
3555 		} else if (stored_state == IBCM_STATE_REP_SENT) {
3556 			ibcm_insert_trace(statep, IBCM_TRACE_OUT_REP_RETRY);
3557 			ibcm_post_rc_mad(statep, statep->stored_msg,
3558 			    ibcm_post_rep_complete, statep);
3559 		/* Post REP MAD in non-blocking mode */
3560 		} else if (stored_state == IBCM_STATE_MRA_REP_RCVD) {
3561 			ibcm_insert_trace(statep, IBCM_TRACE_OUT_REP_RETRY);
3562 			mutex_enter(&statep->state_mutex);
3563 			statep->mra_time = gethrtime();
3564 			mutex_exit(&statep->state_mutex);
3565 			ibcm_post_rc_mad(statep, statep->stored_msg,
3566 			    ibcm_post_mra_rep_complete, statep);
3567 		/* Post DREQ MAD in non-blocking mode */
3568 		} else if (stored_state == IBCM_STATE_DREQ_SENT) {
3569 			mutex_enter(&statep->state_mutex);
3570 			if (statep->remaining_retry_cnt ==
3571 			    statep->max_cm_retries)
3572 				ibcm_insert_trace(statep,
3573 				    IBCM_TRACE_OUTGOING_DREQ);
3574 			else {
3575 				ibcm_insert_trace(statep,
3576 				    IBCM_TRACE_OUT_DREQ_RETRY);
3577 				statep->cm_retries++;
3578 				ibcm_close_done(statep, 0);
3579 			}
3580 			mutex_exit(&statep->state_mutex);
3581 			ibcm_post_rc_mad(statep, statep->dreq_msg,
3582 			    ibcm_post_dreq_complete, statep);
3583 		/* post LAP MAD in non-blocking mode */
3584 		} else if (stored_ap_state == IBCM_AP_STATE_LAP_SENT) {
3585 			ibcm_insert_trace(statep, IBCM_TRACE_OUT_LAP_RETRY);
3586 			ibcm_post_rc_mad(statep, statep->lapr_msg,
3587 			    ibcm_post_lap_complete, statep);
3588 		/* post LAP MAD in non-blocking mode */
3589 		} else if (stored_ap_state == IBCM_AP_STATE_MRA_LAP_RCVD) {
3590 			ibcm_insert_trace(statep, IBCM_TRACE_OUT_LAP_RETRY);
3591 			mutex_enter(&statep->state_mutex);
3592 			statep->mra_time = gethrtime();
3593 			mutex_exit(&statep->state_mutex);
3594 			ibcm_post_rc_mad(statep, statep->lapr_msg,
3595 			    ibcm_post_mra_lap_complete, statep);
3596 		}
3597 		return;
3598 
3599 	} else if ((statep->state == IBCM_STATE_REQ_SENT) ||
3600 	    (statep->state == IBCM_STATE_REP_SENT) ||
3601 	    (statep->state == IBCM_STATE_MRA_REP_RCVD) ||
3602 	    (statep->state == IBCM_STATE_REP_WAIT)) {
3603 
3604 		/*
3605 		 * MAX retries reached, send a REJ to the remote,
3606 		 * and close the connection
3607 		 */
3608 		statep->timedout_state = statep->state;
3609 		statep->state = IBCM_STATE_TIMED_OUT;
3610 
3611 		IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: "
3612 		    "max retries done for statep 0x%p", statep);
3613 		statep->cm_retries++; /* cause conn trace to print */
3614 		mutex_exit(&statep->state_mutex);
3615 
3616 		if ((statep->timedout_state == IBCM_STATE_REP_SENT) ||
3617 		    (statep->timedout_state == IBCM_STATE_MRA_REP_RCVD))
3618 			(void) ibcm_cep_to_error_state(statep);
3619 
3620 		/* Disassociate statep from QP */
3621 		IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
3622 
3623 		/*
3624 		 * statep is in REJ SENT state, the only way to get deleted is
3625 		 * the timeout callback that is set after posting REJ
3626 		 * The thread processing is required where cm handler is
3627 		 * specified
3628 		 */
3629 
3630 		if (statep->cm_handler != NULL) {
3631 			/* Attach the statep to timeout list */
3632 			ibcm_add_tlist(statep);
3633 		} else {
3634 			ib_guid_t local_hca_guid;
3635 
3636 			mutex_enter(&statep->state_mutex);
3637 
3638 			/*
3639 			 * statep->open_return_data is set for blocking
3640 			 * No handler specified, hence signal blocked
3641 			 * ibt_open_rc_channel from here
3642 			 */
3643 			if (statep->open_return_data != NULL) {
3644 				statep->open_return_data->rc_status =
3645 				    IBT_CM_TIMEOUT;
3646 				statep->open_done = B_TRUE;
3647 				cv_broadcast(&statep->block_client_cv);
3648 			}
3649 
3650 			mutex_exit(&statep->state_mutex);
3651 
3652 			local_hca_guid = h2b64(statep->local_hca_guid);
3653 			ibcm_post_rej_mad(statep, IBT_CM_TIMEOUT,
3654 			    (statep->timedout_state == IBCM_STATE_REP_SENT ||
3655 			    statep->timedout_state == IBCM_STATE_MRA_REP_RCVD) ?
3656 			    IBT_CM_FAILURE_REP: IBT_CM_FAILURE_REQ,
3657 			    &local_hca_guid, sizeof (ib_guid_t));
3658 		}
3659 
3660 	} else if ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
3661 	    (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
3662 
3663 		IBTF_DPRINTF_L4(cmlog, "ibcm_timeout_cb: statep 0x%p "
3664 		    "LAP timed out",  statep);
3665 		statep->timedout_state = statep->state;
3666 		/*
3667 		 * This state setting ensures that the processing of DREQ is
3668 		 * sequentialized, once this ap_state is set. If statep is
3669 		 * attached to timeout list, it cannot be re-attached as long
3670 		 * as in this state
3671 		 */
3672 		statep->ap_state = IBCM_AP_STATE_TIMED_OUT;
3673 		ibcm_open_done(statep);
3674 
3675 		if (statep->cm_handler != NULL) {
3676 			/* Attach statep to timeout list - thread handling */
3677 			ibcm_add_tlist(statep);
3678 		} else if (statep->ap_return_data != NULL) {
3679 			/*
3680 			 * statep->ap_return_data is initialized for blocking in
3681 			 * ibt_set_alt_path(), signal the waiting CV
3682 			 */
3683 			statep->ap_return_data->ap_status = IBT_CM_AP_TIMEOUT;
3684 			statep->ap_done = B_TRUE;
3685 			cv_broadcast(&statep->block_client_cv);
3686 
3687 			statep->ap_state = IBCM_AP_STATE_IDLE;
3688 			/* Wake up threads waiting for LAP/APR to complete */
3689 			cv_broadcast(&statep->block_mad_cv);
3690 		}
3691 		mutex_exit(&statep->state_mutex);
3692 
3693 	} else if (statep->state == IBCM_STATE_DREQ_SENT) {
3694 
3695 		statep->timedout_state = statep->state;
3696 		statep->state = IBCM_STATE_TIMED_OUT;
3697 
3698 		/*
3699 		 * The logic below is necessary, for a race situation between
3700 		 * ibt_close_rc_channel with no callbacks option and CM's
3701 		 * internal stale connection handling on the same connection
3702 		 */
3703 		if (statep->close_nocb_state != IBCM_FAIL) {
3704 			ASSERT(statep->close_nocb_state == IBCM_UNBLOCK);
3705 			ibtl_cm_chan_is_closing(statep->channel);
3706 			statep->close_nocb_state = IBCM_BLOCK;
3707 		}
3708 
3709 		mutex_exit(&statep->state_mutex);
3710 
3711 		/*
3712 		 * If cm handler is specified, then invoke handler for
3713 		 * the DREQ timeout
3714 		 */
3715 		if (statep->cm_handler != NULL) {
3716 			ibcm_add_tlist(statep);
3717 			return;
3718 		}
3719 
3720 		ibcm_process_dreq_timeout(statep);
3721 	} else {
3722 
3723 #ifdef DEBUG
3724 		if (ibcm_test_mode > 0)
3725 			IBTF_DPRINTF_L2(cmlog, "ibcm_timeout_cb: "
3726 			    "Unexpected unhandled timeout  for statep 0x%p "
3727 			    "state %d", statep, statep->state);
3728 #endif
3729 		mutex_exit(&statep->state_mutex);
3730 	}
3731 }
3732 
3733 /*
3734  * Following are set of ibmf send callback routines that are used when posting
3735  * various CM MADs in non-blocking post mode
3736  */
3737 
3738 /*ARGSUSED*/
3739 void
3740 ibcm_post_req_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
3741 {
3742 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3743 
3744 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_req_complete statep %p ", statep);
3745 
3746 	mutex_enter(&statep->state_mutex);
3747 	ibcm_flow_dec(statep->post_time, "REQ");
3748 	ibcm_insert_trace(statep, IBCM_TRACE_REQ_POST_COMPLETE);
3749 
3750 	statep->send_mad_flags &= ~IBCM_REQ_POST_BUSY;
3751 
3752 	/* signal any waiting threads for REQ MAD to become available */
3753 	cv_signal(&statep->block_mad_cv);
3754 
3755 	if (statep->state == IBCM_STATE_REQ_SENT)
3756 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3757 
3758 	IBCM_REF_CNT_DECR(statep);
3759 	mutex_exit(&statep->state_mutex);
3760 }
3761 
3762 /*ARGSUSED*/
3763 void
3764 ibcm_post_rep_wait_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3765     void *args)
3766 {
3767 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3768 
3769 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_wait_complete statep %p", statep);
3770 
3771 	mutex_enter(&statep->state_mutex);
3772 	ibcm_flow_dec(statep->post_time, "REQ_RETRY");
3773 	ibcm_insert_trace(statep, IBCM_TRACE_REQ_POST_COMPLETE);
3774 	if (statep->state == IBCM_STATE_REP_WAIT)
3775 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3776 	IBCM_REF_CNT_DECR(statep);
3777 	mutex_exit(&statep->state_mutex);
3778 }
3779 
3780 /*ARGSUSED*/
3781 void
3782 ibcm_post_rep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
3783 {
3784 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3785 
3786 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_complete statep %p", statep);
3787 
3788 	mutex_enter(&statep->state_mutex);
3789 	ibcm_flow_dec(statep->post_time, "REP");
3790 	ibcm_insert_trace(statep, IBCM_TRACE_REP_POST_COMPLETE);
3791 	statep->send_mad_flags &= ~IBCM_REP_POST_BUSY;
3792 	if (statep->state == IBCM_STATE_REP_SENT)
3793 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3794 	IBCM_REF_CNT_DECR(statep);
3795 	mutex_exit(&statep->state_mutex);
3796 }
3797 
3798 /*ARGSUSED*/
3799 void
3800 ibcm_resend_post_rep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3801     void *args)
3802 {
3803 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3804 
3805 	IBTF_DPRINTF_L4(cmlog, "ibcm_resend_post_rep_complete(%p)", statep);
3806 
3807 	mutex_enter(&statep->state_mutex);
3808 	ibcm_flow_dec(statep->post_time, "REP_RETRY");
3809 	ibcm_insert_trace(statep, IBCM_TRACE_REP_POST_COMPLETE);
3810 	statep->send_mad_flags &= ~IBCM_REP_POST_BUSY;
3811 
3812 	/* No new timeout is set for resending a REP MAD for an incoming REQ */
3813 	IBCM_REF_CNT_DECR(statep);
3814 	mutex_exit(&statep->state_mutex);
3815 }
3816 
3817 /*ARGSUSED*/
3818 void
3819 ibcm_post_mra_rep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3820     void *args)
3821 {
3822 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3823 
3824 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_mra_rep_complete statep %p", statep);
3825 
3826 	mutex_enter(&statep->state_mutex);
3827 	ibcm_flow_dec(statep->mra_time, "MRA_REP");
3828 	ibcm_insert_trace(statep, IBCM_TRACE_REP_POST_COMPLETE);
3829 	if (statep->state == IBCM_STATE_MRA_REP_RCVD)
3830 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3831 	IBCM_REF_CNT_DECR(statep);
3832 	mutex_exit(&statep->state_mutex);
3833 }
3834 
3835 
3836 /*ARGSUSED*/
3837 void
3838 ibcm_post_mra_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3839     void *args)
3840 {
3841 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3842 
3843 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_mra_complete statep %p", statep);
3844 
3845 	mutex_enter(&statep->state_mutex);
3846 	ibcm_flow_dec(statep->mra_time, "MRA");
3847 	ibcm_insert_trace(statep, IBCM_TRACE_MRA_POST_COMPLETE);
3848 
3849 	if (statep->delete_mra_msg == B_TRUE) {
3850 		ibmf_msg_t	*mra_msg;
3851 
3852 		mra_msg = statep->mra_msg;
3853 		statep->mra_msg = NULL;
3854 		mutex_exit(&statep->state_mutex);
3855 		(void) ibcm_free_out_msg(statep->stored_reply_addr.ibmf_hdl,
3856 		    &mra_msg);
3857 		mutex_enter(&statep->state_mutex);
3858 	}
3859 	statep->send_mad_flags &= ~IBCM_MRA_POST_BUSY;
3860 	IBCM_REF_CNT_DECR(statep);
3861 	mutex_exit(&statep->state_mutex);
3862 }
3863 
3864 /*ARGSUSED*/
3865 void
3866 ibcm_post_dreq_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
3867 {
3868 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3869 
3870 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_dreq_complete statep %p", statep);
3871 
3872 	mutex_enter(&statep->state_mutex);
3873 	ibcm_flow_dec(statep->post_time, "DREQ");
3874 	ibcm_insert_trace(statep, IBCM_TRACE_DREQ_POST_COMPLETE);
3875 	if (statep->state == IBCM_STATE_DREQ_SENT)
3876 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3877 	ibcm_close_done(statep, 1);
3878 	IBCM_REF_CNT_DECR(statep);
3879 	mutex_exit(&statep->state_mutex);
3880 }
3881 
3882 /*ARGSUSED*/
3883 void
3884 ibcm_post_lap_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
3885 {
3886 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3887 
3888 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_lap_complete statep %p", statep);
3889 
3890 	mutex_enter(&statep->state_mutex);
3891 	ibcm_flow_dec(statep->post_time, "LAP");
3892 	ibcm_insert_trace(statep, IBCM_TRACE_LAP_POST_COMPLETE);
3893 	if (statep->ap_state == IBCM_AP_STATE_LAP_SENT)
3894 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3895 	IBCM_REF_CNT_DECR(statep);
3896 	mutex_exit(&statep->state_mutex);
3897 }
3898 
3899 /*ARGSUSED*/
3900 void
3901 ibcm_post_mra_lap_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3902     void *args)
3903 {
3904 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3905 
3906 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_mra_lap_complete statep %p", statep);
3907 
3908 	mutex_enter(&statep->state_mutex);
3909 	ibcm_flow_dec(statep->mra_time, "MRA_LAP");
3910 	ibcm_insert_trace(statep, IBCM_TRACE_LAP_POST_COMPLETE);
3911 	if (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)
3912 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
3913 	IBCM_REF_CNT_DECR(statep);
3914 	mutex_exit(&statep->state_mutex);
3915 }
3916 
3917 /*ARGSUSED*/
3918 void
3919 ibcm_post_rej_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3920     void *args)
3921 {
3922 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3923 
3924 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_rej_complete statep %p", statep);
3925 
3926 	mutex_enter(&statep->state_mutex);
3927 	ibcm_flow_dec(statep->post_time, "REJ");
3928 	ibcm_insert_trace(statep, IBCM_TRACE_REJ_POST_COMPLETE);
3929 	statep->send_mad_flags &= ~IBCM_REJ_POST_BUSY;
3930 	if (statep->state == IBCM_STATE_REJ_SENT) {
3931 		statep->remaining_retry_cnt = 0;
3932 
3933 		/* wait until all possible retransmits of REQ/REP happened */
3934 		statep->timerid = IBCM_TIMEOUT(statep,
3935 		    statep->timer_value * statep->max_cm_retries);
3936 	}
3937 
3938 	IBCM_REF_CNT_DECR(statep);
3939 	mutex_exit(&statep->state_mutex);
3940 }
3941 
3942 /*ARGSUSED*/
3943 void
3944 ibcm_post_rtu_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3945     void *args)
3946 {
3947 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3948 
3949 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_rtu_complete statep %p", statep);
3950 
3951 	mutex_enter(&statep->state_mutex);
3952 	ibcm_flow_dec(statep->post_time, "RTU");
3953 	ibcm_insert_trace(statep, IBCM_TRACE_RTU_POST_COMPLETE);
3954 	statep->send_mad_flags &= ~IBCM_RTU_POST_BUSY;
3955 	IBCM_REF_CNT_DECR(statep);
3956 	ibcm_open_done(statep);
3957 	mutex_exit(&statep->state_mutex);
3958 }
3959 
3960 /*ARGSUSED*/
3961 void
3962 ibcm_post_apr_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3963     void *args)
3964 {
3965 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
3966 
3967 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_apr_complete statep %p", statep);
3968 
3969 	mutex_enter(&statep->state_mutex);
3970 	ibcm_flow_dec(statep->post_time, "APR");
3971 	ibcm_insert_trace(statep, IBCM_TRACE_APR_POST_COMPLETE);
3972 	/* As long as one APR mad in transit, no retransmits are allowed */
3973 	statep->ap_state = IBCM_AP_STATE_IDLE;
3974 
3975 	/* unblock any DREQ threads and close channels */
3976 	cv_broadcast(&statep->block_mad_cv);
3977 	IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
3978 	mutex_exit(&statep->state_mutex);
3979 
3980 }
3981 
3982 /*ARGSUSED*/
3983 void
3984 ibcm_post_stored_apr_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3985     void *args)
3986 {
3987 	ibmf_msg_t	*ibmf_apr_msg = (ibmf_msg_t *)args;
3988 
3989 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_stored_apr_complete args %p", args);
3990 
3991 	ibcm_flow_dec(0, "APR_RESEND");
3992 	(void) ibcm_free_out_msg(ibmf_handle, &ibmf_apr_msg);
3993 }
3994 
3995 /*ARGSUSED*/
3996 void
3997 ibcm_post_drep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
3998     void *args)
3999 {
4000 	ibcm_state_data_t	*statep = (ibcm_state_data_t *)args;
4001 
4002 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_drep_complete statep %p", statep);
4003 
4004 	mutex_enter(&statep->state_mutex);
4005 	ibcm_flow_dec(statep->post_time, "DREP");
4006 	ibcm_insert_trace(statep, IBCM_TRACE_DREP_POST_COMPLETE);
4007 	statep->send_mad_flags &= ~IBCM_REJ_POST_BUSY;
4008 
4009 	if (statep->state == IBCM_STATE_DREQ_RCVD) {
4010 
4011 		ibcm_close_done(statep, 1);
4012 		statep->state = IBCM_STATE_TIMEWAIT;
4013 
4014 		/*
4015 		 * For passive side CM set it to remote_ack_delay
4016 		 * For active side CM add the pkt_life_time * 2
4017 		 */
4018 		statep->timer_value = statep->remote_ack_delay;
4019 		if (statep->mode == IBCM_ACTIVE_MODE)
4020 			statep->timer_value += (2 * statep->pkt_life_time);
4021 		statep->remaining_retry_cnt = 0;
4022 		statep->timer_stored_state = statep->state;
4023 		statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
4024 	}
4025 
4026 	IBCM_REF_CNT_DECR(statep);
4027 	mutex_exit(&statep->state_mutex);
4028 }
4029 
4030 /*ARGSUSED*/
4031 void
4032 ibcm_post_sidr_rep_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
4033     void *args)
4034 {
4035 	ibcm_ud_state_data_t	*ud_statep = (ibcm_ud_state_data_t *)args;
4036 
4037 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_sidr_rep_complete ud_statep %p",
4038 	    ud_statep);
4039 
4040 	ibcm_flow_dec(0, "SIDR_REP");
4041 	mutex_enter(&ud_statep->ud_state_mutex);
4042 	ud_statep->ud_send_mad_flags &= ~IBCM_SREP_POST_BUSY;
4043 	ud_statep->ud_remaining_retry_cnt = 0;
4044 	if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT)
4045 		ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4046 		    ud_statep->ud_timer_value);
4047 	IBCM_UD_REF_CNT_DECR(ud_statep);
4048 	mutex_exit(&ud_statep->ud_state_mutex);
4049 
4050 }
4051 
4052 /*ARGSUSED*/
4053 void
4054 ibcm_post_sidr_req_complete(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp,
4055     void *args)
4056 {
4057 	ibcm_ud_state_data_t	*ud_statep = (ibcm_ud_state_data_t *)args;
4058 
4059 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_sidr_req_complete ud_statep %p",
4060 	    ud_statep);
4061 
4062 	ibcm_flow_dec(0, "SIDR_REQ");
4063 	mutex_enter(&ud_statep->ud_state_mutex);
4064 	if (ud_statep->ud_state == IBCM_STATE_SIDR_REQ_SENT)
4065 		ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4066 		    ud_statep->ud_timer_value);
4067 	IBCM_UD_REF_CNT_DECR(ud_statep);
4068 	mutex_exit(&ud_statep->ud_state_mutex);
4069 
4070 }
4071 
4072 /*
4073  * ibcm_process_dreq_timeout:
4074  *	Called when the timer expires on DREP
4075  *
4076  * INPUTS:
4077  *	arg	- ibcm_state_data_t is passed
4078  *
4079  * RETURN VALUES: NONE
4080  */
4081 void
4082 ibcm_process_dreq_timeout(ibcm_state_data_t *statep)
4083 {
4084 	mutex_enter(&statep->state_mutex);
4085 
4086 	/* Max retries reached, move to the time wait state */
4087 	statep->state = statep->timer_stored_state =
4088 	    IBCM_STATE_TIMEWAIT;
4089 	ibcm_close_done(statep, 0);
4090 
4091 	/* Set the TIME_WAIT state timer value */
4092 	statep->timer_value = statep->remote_ack_delay;
4093 	if (statep->mode == IBCM_ACTIVE_MODE) {
4094 		statep->timer_value += (2 * statep->pkt_life_time);
4095 	}
4096 
4097 	statep->timerid = IBCM_TIMEOUT(statep, statep->timer_value);
4098 
4099 	if (statep->close_ret_status)
4100 		if (statep->stale == B_TRUE)
4101 			*statep->close_ret_status = IBT_CM_CLOSED_STALE;
4102 		else *statep->close_ret_status = IBT_CM_CLOSED_DREQ_TIMEOUT;
4103 
4104 	/* signal waiting CVs - blocking in ibt_close_channel() */
4105 	statep->close_done = B_TRUE;
4106 	if (statep->close_ret_priv_data_len != NULL)
4107 		*statep->close_ret_priv_data_len = 0;
4108 
4109 	/* unblock any close channel with no callbacks option */
4110 	statep->close_nocb_state = IBCM_FAIL;
4111 
4112 	cv_broadcast(&statep->block_client_cv);
4113 	mutex_exit(&statep->state_mutex);
4114 }
4115 
4116 /*
4117  * ibcm_add_tlist:
4118  *	Adds the given RC statep to timeout list
4119  *
4120  * INPUTS:
4121  *	arg	- ibcm_state_data_t is passed
4122  *
4123  * RETURN VALUES: NONE
4124  */
4125 void
4126 ibcm_add_tlist(ibcm_state_data_t *statep)
4127 {
4128 	mutex_enter(&ibcm_timeout_list_lock);
4129 
4130 	statep->timeout_next = NULL;
4131 	if (ibcm_timeout_list_hdr == NULL) {
4132 		ibcm_timeout_list_hdr = statep;
4133 	} else {
4134 		ibcm_timeout_list_tail->timeout_next = statep;
4135 	}
4136 
4137 	ibcm_timeout_list_tail = statep;
4138 
4139 	cv_signal(&ibcm_timeout_list_cv);
4140 
4141 	mutex_exit(&ibcm_timeout_list_lock);
4142 	IBTF_DPRINTF_L3(cmlog, "ibcm_add_tlist: "
4143 	    "attached state = %p to timeout list", statep);
4144 }
4145 
4146 void
4147 ibcm_run_tlist_thread(void)
4148 {
4149 	mutex_enter(&ibcm_timeout_list_lock);
4150 	cv_signal(&ibcm_timeout_list_cv);
4151 	mutex_exit(&ibcm_timeout_list_lock);
4152 }
4153 
4154 /*
4155  * ibcm_add_ud_tlist:
4156  *	Adds the given UD statep to timeout list
4157  *
4158  * INPUTS:
4159  *	arg	- ibcm_ud_state_data_t is passed
4160  *
4161  * RETURN VALUES: NONE
4162  */
4163 void
4164 ibcm_add_ud_tlist(ibcm_ud_state_data_t *ud_statep)
4165 {
4166 	mutex_enter(&ibcm_timeout_list_lock);
4167 
4168 	ud_statep->ud_timeout_next = NULL;
4169 	if (ibcm_ud_timeout_list_hdr == NULL) {
4170 		ibcm_ud_timeout_list_hdr = ud_statep;
4171 	} else {
4172 		ibcm_ud_timeout_list_tail->ud_timeout_next = ud_statep;
4173 	}
4174 
4175 	ibcm_ud_timeout_list_tail = ud_statep;
4176 
4177 	cv_signal(&ibcm_timeout_list_cv);
4178 
4179 	mutex_exit(&ibcm_timeout_list_lock);
4180 	IBTF_DPRINTF_L3(cmlog, "ibcm_add_ud_tlist: "
4181 	    "attached state = %p to ud timeout list", ud_statep);
4182 }
4183 
4184 /*
4185  * ibcm_process_tlist:
4186  *	Thread that processes all the RC and UD statep's from
4187  *	the appropriate lists
4188  *
4189  * INPUTS:
4190  *	NONE
4191  *
4192  * RETURN VALUES: NONE
4193  */
4194 void
4195 ibcm_process_tlist()
4196 {
4197 	ibcm_state_data_t 	*statep;
4198 	ibcm_ud_state_data_t 	*ud_statep;
4199 	callb_cpr_t		cprinfo;
4200 
4201 	IBTF_DPRINTF_L5(cmlog, "ibcm_process_tlist: thread started");
4202 
4203 	mutex_enter(&ibcm_timeout_list_lock);
4204 
4205 	CALLB_CPR_INIT(&cprinfo, &ibcm_timeout_list_lock, callb_generic_cpr,
4206 	    "ibcm_process_tlist");
4207 
4208 	for (;;) {
4209 		if (ibcm_timeout_list_flags & IBCM_TIMEOUT_THREAD_EXIT) {
4210 			/* The thread needs to exit */
4211 			cv_signal(&ibcm_timeout_thread_done_cv);
4212 			break;
4213 		}
4214 		mutex_exit(&ibcm_timeout_list_lock);
4215 		ibcm_check_for_opens();
4216 		ibcm_check_for_async_close();
4217 		mutex_enter(&ibcm_timeout_list_lock);
4218 
4219 		/* First, handle pending RC statep's, followed by UD's */
4220 		if (ibcm_timeout_list_hdr != NULL) {
4221 			statep = ibcm_timeout_list_hdr;
4222 			ibcm_timeout_list_hdr = statep->timeout_next;
4223 
4224 			if (ibcm_timeout_list_hdr == NULL)
4225 				ibcm_timeout_list_tail = NULL;
4226 
4227 			statep->timeout_next = NULL;
4228 
4229 			mutex_exit(&ibcm_timeout_list_lock);
4230 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_tlist: "
4231 			    "scheduling state = %p", statep);
4232 			ibcm_timeout_client_cb(statep);
4233 			mutex_enter(&ibcm_timeout_list_lock);
4234 		} else if (ibcm_ud_timeout_list_hdr != NULL) {
4235 			ud_statep = ibcm_ud_timeout_list_hdr;
4236 			ibcm_ud_timeout_list_hdr = ud_statep->ud_timeout_next;
4237 
4238 			if (ibcm_ud_timeout_list_hdr == NULL)
4239 				ibcm_ud_timeout_list_tail = NULL;
4240 
4241 			ud_statep->ud_timeout_next = NULL;
4242 
4243 			mutex_exit(&ibcm_timeout_list_lock);
4244 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_tlist: "
4245 			    "ud scheduling state = %p", ud_statep);
4246 			ibcm_ud_timeout_client_cb(ud_statep);
4247 			mutex_enter(&ibcm_timeout_list_lock);
4248 		} else {
4249 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
4250 			cv_wait(&ibcm_timeout_list_cv, &ibcm_timeout_list_lock);
4251 			CALLB_CPR_SAFE_END(&cprinfo, &ibcm_timeout_list_lock);
4252 		}
4253 	}
4254 
4255 #ifndef	__lock_lint
4256 	CALLB_CPR_EXIT(&cprinfo);	/* mutex_exit */
4257 #endif
4258 }
4259 
4260 
4261 /*
4262  * ibcm_timeout_client_cb:
4263  *	Called from timeout thread processing
4264  *	Primary purpose is to call client handler
4265  *
4266  * INPUTS:
4267  *	arg	- ibcm_state_data_t is passed
4268  *
4269  * RETURN VALUES: NONE
4270  */
4271 void
4272 ibcm_timeout_client_cb(ibcm_state_data_t *statep)
4273 {
4274 	mutex_enter(&statep->state_mutex);
4275 
4276 	if ((statep->state == IBCM_STATE_DELETE) &&
4277 	    (statep->recycle_arg != NULL)) {
4278 		struct ibcm_taskq_recycle_arg_s *recycle_arg;
4279 
4280 		recycle_arg = statep->recycle_arg;
4281 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
4282 		statep->recycle_arg = NULL;
4283 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
4284 		mutex_exit(&statep->state_mutex);
4285 		(void) ibcm_process_rc_recycle(recycle_arg);
4286 		ibcm_delete_state_data(statep);
4287 		return;
4288 	}
4289 
4290 	if ((statep->state == IBCM_STATE_DELETE) &&
4291 	    (statep->delete_state_data == B_TRUE)) {
4292 		mutex_exit(&statep->state_mutex);
4293 		ibcm_dealloc_state_data(statep);
4294 		return;
4295 	}
4296 
4297 	/* Else, it must be in TIMEOUT state, do the necessary processing */
4298 	if (statep->state == IBCM_STATE_TIMED_OUT) {
4299 		void		*data;
4300 		uint8_t		cf_msg;
4301 		ib_guid_t	local_hca_guid;
4302 
4303 		mutex_exit(&statep->state_mutex);
4304 
4305 		if (statep->timedout_state == IBCM_STATE_DREQ_SENT) {
4306 			ibt_cm_event_t		event;
4307 			ibt_cm_return_args_t	ret_args;
4308 
4309 			bzero(&event, sizeof (event));
4310 			bzero(&ret_args, sizeof (ret_args));
4311 
4312 			event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
4313 			event.cm_channel = statep->channel;
4314 			event.cm_session_id = NULL;
4315 			event.cm_priv_data = NULL;
4316 			event.cm_priv_data_len = 0;
4317 
4318 			if (statep->stale == B_TRUE)
4319 				event.cm_event.closed = IBT_CM_CLOSED_STALE;
4320 			else event.cm_event.closed = IBT_CM_CLOSED_DREQ_TIMEOUT;
4321 
4322 			/*
4323 			 * cm handler cannot be non-NULL, as that check is
4324 			 * already made in ibcm_timeout_cb
4325 			 */
4326 			ibcm_insert_trace(statep,
4327 			    IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
4328 
4329 			(void) statep->cm_handler(statep->state_cm_private,
4330 			    &event, &ret_args, NULL, 0);
4331 
4332 			ibcm_insert_trace(statep,
4333 			    IBCM_TRACE_RET_CONN_CLOSE_EVENT);
4334 
4335 			ibcm_process_dreq_timeout(statep);
4336 			return;
4337 		}
4338 
4339 		data = ((ibcm_rej_msg_t *)
4340 		    IBCM_OUT_MSGP(statep->stored_msg))->rej_private_data;
4341 
4342 		if ((statep->timedout_state == IBCM_STATE_REQ_SENT) ||
4343 		    (statep->timedout_state == IBCM_STATE_REP_WAIT)) {
4344 			cf_msg = IBT_CM_FAILURE_REQ;
4345 		} else {
4346 			ASSERT(
4347 			    (statep->timedout_state == IBCM_STATE_REP_SENT) ||
4348 			    (statep->timedout_state ==
4349 			    IBCM_STATE_MRA_REP_RCVD));
4350 			cf_msg = IBT_CM_FAILURE_REP;
4351 		}
4352 
4353 		/*
4354 		 * Invoke the CM handler w/ event IBT_CM_EVENT_TIMEOUT
4355 		 * This callback happens for only active non blocking or
4356 		 * passive client
4357 		 */
4358 		ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_TIMEOUT,
4359 		    cf_msg, IBT_CM_TIMEOUT, data, IBT_REJ_PRIV_DATA_SZ);
4360 
4361 		/* signal the blocked ibt_open_rc_channel */
4362 		mutex_enter(&statep->state_mutex);
4363 
4364 		/*
4365 		 * statep->open_return_data is set for blocking
4366 		 * signal the blocked ibt_open_rc_channel
4367 		 */
4368 		if (statep->open_return_data != NULL) {
4369 			statep->open_return_data->rc_status = IBT_CM_TIMEOUT;
4370 			statep->open_done = B_TRUE;
4371 			cv_broadcast(&statep->block_client_cv);
4372 		}
4373 
4374 		mutex_exit(&statep->state_mutex);
4375 
4376 		local_hca_guid = h2b64(statep->local_hca_guid);
4377 		ibcm_post_rej_mad(statep, IBT_CM_TIMEOUT,
4378 		    IBT_CM_FAILURE_UNKNOWN, &local_hca_guid,
4379 		    sizeof (ib_guid_t));
4380 	} else if (statep->ap_state == IBCM_AP_STATE_TIMED_OUT) {
4381 
4382 		mutex_exit(&statep->state_mutex);
4383 
4384 		ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_TIMEOUT,
4385 		    IBT_CM_FAILURE_LAP, IBT_CM_TIMEOUT, NULL, 0);
4386 
4387 		/* Now wake up threads waiting for LAP/APR to complete */
4388 		mutex_enter(&statep->state_mutex);
4389 		/*
4390 		 * statep->ap_return_data is initialized for blocking in
4391 		 * ibt_set_alt_path(), signal the waiting CV
4392 		 */
4393 		if (statep->ap_return_data != NULL) {
4394 			statep->ap_return_data->ap_status = IBT_CM_AP_TIMEOUT;
4395 			statep->ap_done = B_TRUE;
4396 			cv_broadcast(&statep->block_client_cv);
4397 		}
4398 		statep->ap_state = IBCM_AP_STATE_IDLE;
4399 		cv_broadcast(&statep->block_mad_cv);
4400 		mutex_exit(&statep->state_mutex);
4401 	} else {
4402 		IBTF_DPRINTF_L2(cmlog, "ibcm_timeout_client_cb "
4403 		    "Unexpected else path statep %p state %d ap_state %d",
4404 		    statep, statep->state, statep->ap_state);
4405 		mutex_exit(&statep->state_mutex);
4406 
4407 	}
4408 }
4409 
4410 /*
4411  * ibcm_ud_timeout_client_cb:
4412  *	Called from UD timeout thread processing
4413  *	Primary purpose is to call client handler
4414  *
4415  * INPUTS:
4416  *	arg	- ibcm_ud_state_data_t is passed
4417  *
4418  * RETURN VALUES: NONE
4419  */
4420 void
4421 ibcm_ud_timeout_client_cb(ibcm_ud_state_data_t *ud_statep)
4422 {
4423 	ibt_cm_ud_event_t	ud_event;
4424 
4425 	mutex_enter(&ud_statep->ud_state_mutex);
4426 
4427 	if ((ud_statep->ud_state == IBCM_STATE_DELETE) &&
4428 	    (ud_statep->ud_delete_state_data == B_TRUE)) {
4429 
4430 		mutex_exit(&ud_statep->ud_state_mutex);
4431 		ibcm_dealloc_ud_state_data(ud_statep);
4432 		return;
4433 	} else
4434 		mutex_exit(&ud_statep->ud_state_mutex);
4435 
4436 	/* Fill in ibt_cm_ud_event_t */
4437 	ud_event.cm_type = IBT_CM_UD_EVENT_SIDR_REP;
4438 	ud_event.cm_session_id = NULL;
4439 	ud_event.cm_event.sidr_rep.srep_status = IBT_CM_SREP_TIMEOUT;
4440 
4441 	(void) ud_statep->ud_cm_handler(ud_statep->ud_state_cm_private,
4442 	    &ud_event, NULL, NULL, 0);
4443 
4444 	/* Delete UD state data now, finally done with it */
4445 	ibcm_delete_ud_state_data(ud_statep);
4446 }
4447 
4448 
4449 /*
4450  * ibcm_process_sidr_req_msg:
4451  *	This call processes an incoming SIDR REQ
4452  *
4453  * INPUTS:
4454  *	hcap		- HCA entry pointer
4455  *	input_madp	- Incoming CM SIDR REQ MAD
4456  *	cm_mad_addr	- Address information for the MAD to be posted
4457  *
4458  * RETURN VALUE:
4459  *	NONE
4460  */
4461 void
4462 ibcm_process_sidr_req_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
4463     ibcm_mad_addr_t *cm_mad_addr)
4464 {
4465 	ib_gid_t		gid;
4466 	ib_lid_t		lid;
4467 	uint32_t		req_id;
4468 	ibcm_status_t		state_lookup_status;
4469 	ibcm_status_t		cm_status;
4470 	ibt_sidr_status_t	sidr_status;
4471 	ibcm_svc_info_t		*svc_infop;
4472 	ibcm_svc_bind_t		*svc_bindp;
4473 	ibcm_svc_bind_t		*tmp_bindp;
4474 	ibcm_sidr_req_msg_t	*sidr_reqp = (ibcm_sidr_req_msg_t *)
4475 	    (&input_madp[IBCM_MAD_HDR_SIZE]);
4476 	ibcm_ud_state_data_t	*ud_statep = NULL;
4477 	ibcm_sidr_srch_t	srch_sidr;
4478 	ib_pkey_t		pkey;
4479 	uint8_t			port_num;
4480 	ib_guid_t		hca_guid;
4481 
4482 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg:");
4483 
4484 	hca_guid = hcap->hca_guid;
4485 	port_num = cm_mad_addr->port_num;
4486 
4487 	/* Figure out LID, GID, RequestId for svc_id lookup */
4488 	lid = cm_mad_addr->rcvd_addr.ia_remote_lid;
4489 	req_id = b2h32(sidr_reqp->sidr_req_request_id);
4490 	pkey = b2h16(sidr_reqp->sidr_req_pkey);
4491 	if (cm_mad_addr->grh_exists == B_TRUE)
4492 		gid = cm_mad_addr->grh_hdr.ig_sender_gid;
4493 	else
4494 		gid.gid_prefix = gid.gid_guid = 0;
4495 
4496 	/*
4497 	 * Lookup for an existing state structure
4498 	 * - if lookup fails it creates a new ud_state struct
4499 	 * No need to hold a lock across the call to ibcm_find_sidr_entry() as
4500 	 * the list lock is held in that function to find the matching entry.
4501 	 */
4502 
4503 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srch_sidr))
4504 
4505 	srch_sidr.srch_lid = lid;
4506 	srch_sidr.srch_gid = gid;
4507 	srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4508 	srch_sidr.srch_req_id = req_id;
4509 	srch_sidr.srch_mode = IBCM_PASSIVE_MODE;
4510 
4511 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srch_sidr))
4512 
4513 	rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
4514 	state_lookup_status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4515 	    IBCM_FLAG_LOOKUP_AND_ADD);
4516 	rw_exit(&hcap->hca_sidr_list_lock);
4517 
4518 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: ud_statep 0x%p "
4519 	    "lookup status %x", ud_statep, state_lookup_status);
4520 
4521 	if (state_lookup_status == IBCM_LOOKUP_NEW) {
4522 
4523 		/* Increment hca's resource count */
4524 		ibcm_inc_hca_res_cnt(hcap);
4525 
4526 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
4527 
4528 		/*
4529 		 * Allocate CM MAD for a response
4530 		 * This MAD is deallocated on state structure delete
4531 		 * and re-used for all outgoing MADs for this connection.
4532 		 * If MAD allocation fails, delete the ud statep
4533 		 */
4534 		if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
4535 		    &ud_statep->ud_stored_msg, MAD_METHOD_SEND) !=
4536 		    IBT_SUCCESS) {
4537 			mutex_enter(&ud_statep->ud_state_mutex);
4538 			IBCM_UD_REF_CNT_DECR(ud_statep);
4539 			mutex_exit(&ud_statep->ud_state_mutex);
4540 			ibcm_dec_hca_res_cnt(hcap);
4541 			ibcm_delete_ud_state_data(ud_statep);
4542 			return;
4543 		}
4544 
4545 		/* Lookup for service */
4546 		ud_statep->ud_svc_id = b2h64(sidr_reqp->sidr_req_service_id);
4547 		ud_statep->ud_state  = IBCM_STATE_SIDR_REQ_RCVD;
4548 		ud_statep->ud_clnt_proceed = IBCM_BLOCK;
4549 		ud_statep->ud_hcap = hcap;
4550 
4551 		mutex_enter(&ibcm_svc_info_lock);
4552 
4553 		svc_infop = ibcm_find_svc_entry(ud_statep->ud_svc_id);
4554 
4555 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: "
4556 		    " ud_statep 0x%p svc_info %p", ud_statep, svc_infop);
4557 
4558 		/*
4559 		 * No need to hold the ud state mutex, as no other thread
4560 		 * modifies ud statep in IBCM_STATE_SIDR_REQ_RCVD state
4561 		 */
4562 
4563 		if (svc_infop != NULL) {
4564 			/* find the "bind" entry that enables this port */
4565 
4566 			svc_bindp = NULL;
4567 			tmp_bindp = svc_infop->svc_bind_list;
4568 			while (tmp_bindp) {
4569 				if (tmp_bindp->sbind_hcaguid == hca_guid &&
4570 				    tmp_bindp->sbind_port == port_num) {
4571 					if (gid.gid_guid ==
4572 					    tmp_bindp->sbind_gid.gid_guid &&
4573 					    gid.gid_prefix ==
4574 					    tmp_bindp->sbind_gid.gid_prefix) {
4575 						/* a really good match */
4576 						svc_bindp = tmp_bindp;
4577 						if (pkey ==
4578 						    tmp_bindp->sbind_pkey)
4579 							/* absolute best */
4580 							break;
4581 					} else if (svc_bindp == NULL) {
4582 						/* port match => a good match */
4583 						svc_bindp = tmp_bindp;
4584 					}
4585 				}
4586 				tmp_bindp = tmp_bindp->sbind_link;
4587 			}
4588 			if (svc_bindp == NULL) {
4589 				svc_infop = NULL;
4590 			}
4591 		}
4592 
4593 		IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID =
4594 		    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
4595 
4596 		ibcm_build_reply_mad_addr(cm_mad_addr,
4597 		    &ud_statep->ud_stored_reply_addr);
4598 
4599 		if (ud_statep->ud_stored_reply_addr.cm_qp_entry == NULL) {
4600 
4601 			mutex_exit(&ibcm_svc_info_lock);
4602 
4603 			/* Not much choice. CM MADs cannot go on QP1 */
4604 			mutex_enter(&ud_statep->ud_state_mutex);
4605 			IBCM_UD_REF_CNT_DECR(ud_statep);
4606 			ud_statep->ud_state = IBCM_STATE_DELETE;
4607 			mutex_exit(&ud_statep->ud_state_mutex);
4608 
4609 			ibcm_delete_ud_state_data(ud_statep);
4610 			return;
4611 		}
4612 
4613 		if (svc_infop == NULL || svc_infop->svc_ud_handler == NULL) {
4614 			/*
4615 			 * Don't have a record of Service ID in CM's
4616 			 * internal list registered at this gid/lid.
4617 			 * So, send out Service ID not supported SIDR REP msg
4618 			 */
4619 			sidr_status = IBT_CM_SREP_SID_INVALID;
4620 		} else {
4621 			ud_statep->ud_cm_handler = svc_infop->svc_ud_handler;
4622 			ud_statep->ud_state_cm_private =
4623 			    svc_bindp->sbind_cm_private;
4624 			IBCM_SVC_INCR(svc_infop);
4625 			mutex_exit(&ibcm_svc_info_lock);
4626 
4627 			/* Call Client's UD handler */
4628 			cm_status = ibcm_sidr_req_ud_handler(ud_statep,
4629 			    sidr_reqp, cm_mad_addr, &sidr_status);
4630 
4631 			mutex_enter(&ibcm_svc_info_lock);
4632 			IBCM_SVC_DECR(svc_infop);
4633 		}
4634 
4635 		mutex_exit(&ibcm_svc_info_lock);
4636 
4637 		if (cm_status == IBCM_DEFER) {
4638 			IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: "
4639 			    "ud_statep 0x%p client returned DEFER response",
4640 			    ud_statep);
4641 			return;
4642 		}
4643 
4644 		ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
4645 
4646 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
4647 
4648 		mutex_enter(&ud_statep->ud_state_mutex);
4649 		IBCM_UD_REF_CNT_DECR(ud_statep);
4650 		mutex_exit(&ud_statep->ud_state_mutex);
4651 	} else {
4652 		ASSERT(state_lookup_status == IBCM_LOOKUP_EXISTS);
4653 
4654 		mutex_enter(&ud_statep->ud_state_mutex);
4655 
4656 		if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT)
4657 			ibcm_resend_srep_mad(ud_statep);
4658 
4659 		IBCM_UD_REF_CNT_DECR(ud_statep);
4660 		mutex_exit(&ud_statep->ud_state_mutex);
4661 	}
4662 }
4663 
4664 
4665 /*
4666  * ibcm_process_sidr_rep_msg:
4667  *	This call processes an incoming SIDR REP
4668  *
4669  * INPUTS:
4670  *	hcap		- HCA entry pointer
4671  *	input_madp	- incoming CM SIDR REP MAD
4672  *	cm_mad_addr	- Address information for the MAD to be posted
4673  *
4674  * RETURN VALUE:
4675  *	NONE
4676  */
4677 void
4678 ibcm_process_sidr_rep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
4679     ibcm_mad_addr_t *cm_mad_addr)
4680 {
4681 	ib_lid_t		lid;
4682 	ib_gid_t		gid;
4683 	ibcm_status_t		status;
4684 	ib_svc_id_t		tmp_svc_id;
4685 	ibcm_sidr_rep_msg_t	*sidr_repp = (ibcm_sidr_rep_msg_t *)
4686 	    (&input_madp[IBCM_MAD_HDR_SIZE]);
4687 	ibcm_ud_state_data_t	*ud_statep = NULL;
4688 	ibcm_sidr_srch_t	srch_sidr;
4689 
4690 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg:");
4691 
4692 	lid = cm_mad_addr->rcvd_addr.ia_local_lid;
4693 	if (cm_mad_addr->grh_exists == B_TRUE)
4694 		gid = cm_mad_addr->grh_hdr.ig_recver_gid;
4695 	else
4696 		gid.gid_prefix = gid.gid_guid = 0;
4697 
4698 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_sidr_rep_msg: QPN rcvd = %x",
4699 	    h2b32(sidr_repp->sidr_rep_qpn_plus) >> 8);
4700 
4701 	/*
4702 	 * Lookup for an existing state structure.
4703 	 * No need to hold a lock as ibcm_find_sidr_entry() holds the
4704 	 * list lock to find the matching entry.
4705 	 */
4706 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep: lid=%x, (%llX, %llX), "
4707 	    "grh = %x, id = %x", lid, gid.gid_prefix, gid.gid_guid,
4708 	    cm_mad_addr->grh_exists, sidr_repp->sidr_rep_request_id);
4709 
4710 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srch_sidr))
4711 
4712 	srch_sidr.srch_lid = lid;
4713 	srch_sidr.srch_gid = gid;
4714 	srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4715 	srch_sidr.srch_req_id = b2h32(sidr_repp->sidr_rep_request_id);
4716 	srch_sidr.srch_mode = IBCM_ACTIVE_MODE;
4717 
4718 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srch_sidr))
4719 
4720 	rw_enter(&hcap->hca_sidr_list_lock, RW_READER);
4721 	status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4722 	    IBCM_FLAG_LOOKUP);
4723 	rw_exit(&hcap->hca_sidr_list_lock);
4724 
4725 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg: ud_statep 0x%p "
4726 	    "find sidr entry status = %x", ud_statep, status);
4727 
4728 	if (status != IBCM_LOOKUP_EXISTS) {
4729 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4730 		    "No matching ud_statep for SIDR REP");
4731 		return;
4732 	}
4733 
4734 	if (IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID !=
4735 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
4736 		mutex_enter(&ud_statep->ud_state_mutex);
4737 		IBCM_UD_REF_CNT_DECR(ud_statep);
4738 		mutex_exit(&ud_statep->ud_state_mutex);
4739 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4740 		    "ud_statep 0x%p. A SIDR REP MAD with tid expected 0x%llX "
4741 		    "tid found 0x%llX req_id %x arrived", ud_statep,
4742 		    b2h64(
4743 		    IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID),
4744 		    b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID),
4745 		    b2h32(sidr_repp->sidr_rep_request_id));
4746 		return;
4747 	}
4748 
4749 	mutex_enter(&ud_statep->ud_state_mutex);
4750 
4751 	/*
4752 	 * We need to check service ID received against the one sent?
4753 	 * If they don't match just return.
4754 	 */
4755 	bcopy(sidr_repp->sidr_rep_service_id, &tmp_svc_id, sizeof (tmp_svc_id));
4756 	bcopy(&tmp_svc_id, sidr_repp->sidr_rep_service_id, sizeof (tmp_svc_id));
4757 	if (ud_statep->ud_svc_id != b2h64(tmp_svc_id)) {
4758 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4759 		    "ud_statep -0x%p svcids do not match %llx %llx",
4760 		    ud_statep, ud_statep->ud_svc_id, b2h64(tmp_svc_id));
4761 
4762 		IBCM_UD_REF_CNT_DECR(ud_statep);
4763 		mutex_exit(&ud_statep->ud_state_mutex);
4764 		return;
4765 	}
4766 
4767 	if (ud_statep->ud_state == IBCM_STATE_SIDR_REQ_SENT) {
4768 		timeout_id_t	timer_val = ud_statep->ud_timerid;
4769 
4770 		ud_statep->ud_state = IBCM_STATE_SIDR_REP_RCVD;
4771 		ud_statep->ud_timerid = 0;
4772 		mutex_exit(&ud_statep->ud_state_mutex);
4773 
4774 		/* Cancel timer set after sending SIDR REQ */
4775 		(void) untimeout(timer_val);
4776 
4777 		/*
4778 		 * Call Client's UD handler
4779 		 */
4780 		ibcm_sidr_rep_ud_handler(ud_statep, sidr_repp);
4781 
4782 		mutex_enter(&ud_statep->ud_state_mutex);
4783 
4784 		ud_statep->ud_state = IBCM_STATE_DELETE;
4785 
4786 		/*
4787 		 * ud_statep->ud_return_data is initialized for blocking in
4788 		 * ibt_ud_get_dqpn(). Initialize its fields and
4789 		 * signal the blocking call in ibt_ud_get_dqpn().
4790 		 */
4791 		if (ud_statep->ud_return_data != NULL) {
4792 			/* get rep_qpn and rep_status */
4793 			ibt_priv_data_len_t len;
4794 
4795 			/* Copy the SIDR private data */
4796 			len = min(ud_statep->ud_return_data->ud_priv_data_len,
4797 			    IBT_SIDR_REP_PRIV_DATA_SZ);
4798 
4799 			if ((ud_statep->ud_return_data->ud_priv_data != NULL) &&
4800 			    (len > 0)) {
4801 				bcopy(sidr_repp->sidr_rep_private_data,
4802 				    ud_statep->ud_return_data->ud_priv_data,
4803 				    len);
4804 			}
4805 
4806 			/* get status first */
4807 			ud_statep->ud_return_data->ud_status =
4808 			    sidr_repp->sidr_rep_rep_status;
4809 
4810 			if (ud_statep->ud_return_data->ud_status ==
4811 			    IBT_CM_SREP_QPN_VALID) {
4812 				ud_statep->ud_return_data->ud_dqpn =
4813 				    h2b32(sidr_repp->sidr_rep_qpn_plus) >> 8;
4814 				ud_statep->ud_return_data->ud_qkey =
4815 				    b2h32(sidr_repp->sidr_rep_qkey);
4816 			}
4817 
4818 			ud_statep->ud_blocking_done = B_TRUE;
4819 			cv_broadcast(&ud_statep->ud_block_client_cv);
4820 		}
4821 
4822 		IBCM_UD_REF_CNT_DECR(ud_statep);
4823 		mutex_exit(&ud_statep->ud_state_mutex);
4824 
4825 		/* Delete UD state data now, finally done with it */
4826 		ibcm_delete_ud_state_data(ud_statep);
4827 	} else {
4828 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_sidr_rep_msg: "
4829 		    "ud state is = 0x%x", ud_statep->ud_state);
4830 		IBCM_UD_REF_CNT_DECR(ud_statep);
4831 		mutex_exit(&ud_statep->ud_state_mutex);
4832 	}
4833 }
4834 
4835 
4836 /*
4837  * ibcm_post_sidr_rep_mad:
4838  *	This call posts a SIDR REP MAD
4839  *
4840  * INPUTS:
4841  *	ud_statep	- pointer to ibcm_ud_state_data_t
4842  *	status		- Status information
4843  *
4844  * RETURN VALUE: NONE
4845  */
4846 void
4847 ibcm_post_sidr_rep_mad(ibcm_ud_state_data_t *ud_statep,
4848     ibt_sidr_status_t status)
4849 {
4850 	ib_svc_id_t		tmp_svc_id;
4851 	ibcm_sidr_rep_msg_t	*sidr_repp =
4852 	    (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
4853 	clock_t			timer_value;
4854 
4855 	IBTF_DPRINTF_L5(cmlog, "ibcm_post_sidr_rep_mad:");
4856 
4857 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
4858 
4859 	IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
4860 	    h2b16(IBCM_INCOMING_SIDR_REP + IBCM_ATTR_BASE_ID);
4861 
4862 	/*
4863 	 * Initialize SIDR REP message. (Other fields were
4864 	 * already filled up in ibcm_sidr_req_ud_handler()
4865 	 */
4866 	sidr_repp->sidr_rep_request_id = h2b32(ud_statep->ud_req_id);
4867 	tmp_svc_id = h2b64(ud_statep->ud_svc_id);
4868 	bcopy(&tmp_svc_id, sidr_repp->sidr_rep_service_id, sizeof (tmp_svc_id));
4869 
4870 	sidr_repp->sidr_rep_rep_status = (uint8_t)status;
4871 
4872 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_repp))
4873 
4874 	/* post the SIDR REP MAD */
4875 	ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg, NULL, NULL);
4876 
4877 	timer_value = ibt_ib2usec(ibcm_max_sidr_rep_store_time);
4878 	/*
4879 	 * Hold the statep lock, as a SIDR REQ may come in after setting state
4880 	 * but before timeout. This can result in a dangling timeout ie.,
4881 	 * the incoming SIDR REQ would be unable to cancel this timeout
4882 	 */
4883 	mutex_enter(&ud_statep->ud_state_mutex);
4884 
4885 	ud_statep->ud_remaining_retry_cnt = 1;
4886 	ud_statep->ud_timer_value = timer_value;
4887 
4888 	ud_statep->ud_timer_stored_state = ud_statep->ud_state =
4889 	    IBCM_STATE_SIDR_REP_SENT;
4890 	ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4891 	    ud_statep->ud_timer_value);
4892 
4893 	mutex_exit(&ud_statep->ud_state_mutex);
4894 }
4895 
4896 
4897 /*
4898  * ibcm_sidr_timeout_cb:
4899  *	Called when the timer expires on SIDR request
4900  *
4901  * INPUTS:
4902  *	arg	-	ibcm_ud_state_data_t with all the info
4903  *
4904  * RETURN VALUE: NONE
4905  */
4906 void
4907 ibcm_sidr_timeout_cb(void *arg)
4908 {
4909 	ibcm_ud_state_data_t	*ud_statep = (ibcm_ud_state_data_t *)arg;
4910 
4911 	mutex_enter(&ud_statep->ud_state_mutex);
4912 
4913 	IBTF_DPRINTF_L3(cmlog, "ibcm_sidr_timeout_cb: ud_statep 0x%p "
4914 	    "state = 0x%x", ud_statep, ud_statep->ud_state);
4915 
4916 	/* Processing depends upon current state */
4917 	if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT) {
4918 		ud_statep->ud_state = IBCM_STATE_DELETE;
4919 
4920 		mutex_exit(&ud_statep->ud_state_mutex);
4921 
4922 		/* Deallocate the CM state structure */
4923 		ibcm_delete_ud_state_data(ud_statep);
4924 
4925 	} else if ((ud_statep->ud_remaining_retry_cnt > 0) &&
4926 	    (ud_statep->ud_state == IBCM_STATE_SIDR_REQ_SENT)) {
4927 
4928 		ud_statep->ud_remaining_retry_cnt--;
4929 		IBCM_UD_REF_CNT_INCR(ud_statep); /* for non-blocking post */
4930 		IBTF_DPRINTF_L4(cmlog, "ibcm_sidr_timeout_cb: "
4931 		    "ud_statep = %p, retries remaining = 0x%x",
4932 		    ud_statep, ud_statep->ud_remaining_retry_cnt);
4933 		mutex_exit(&ud_statep->ud_state_mutex);
4934 
4935 		/* Post mad in non blocking mode */
4936 		ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
4937 		    ibcm_post_sidr_req_complete, ud_statep);
4938 
4939 	} else if (ud_statep->ud_state == IBCM_STATE_SIDR_REQ_SENT) {
4940 
4941 		/* This is on SIDR REQ Sender side processing */
4942 
4943 		/* set state to IBCM_STATE_DELETE */
4944 		ud_statep->ud_state = IBCM_STATE_DELETE;
4945 
4946 		/*
4947 		 * retry counter expired, clean up
4948 		 *
4949 		 * Invoke the client/server handler with a "status" of
4950 		 * IBT_CM_SREP_TIMEOUT.
4951 		 */
4952 
4953 		if (ud_statep->ud_return_data != NULL) {
4954 			ud_statep->ud_return_data->ud_status =
4955 			    IBT_CM_SREP_TIMEOUT;
4956 			ud_statep->ud_blocking_done = B_TRUE;
4957 			cv_broadcast(&ud_statep->ud_block_client_cv);
4958 		}
4959 
4960 		mutex_exit(&ud_statep->ud_state_mutex);
4961 
4962 		/* Invoke the client handler in a separate thread */
4963 		if (ud_statep->ud_cm_handler != NULL) {
4964 			/* UD state data is delete in timeout thread */
4965 			ibcm_add_ud_tlist(ud_statep);
4966 			return;
4967 		}
4968 
4969 		/* Delete UD state data now, finally done with it */
4970 		ibcm_delete_ud_state_data(ud_statep);
4971 	} else {
4972 
4973 #ifdef DEBUG
4974 		if (ibcm_test_mode > 0)
4975 			IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_timeout_cb: "
4976 			    "Nop timeout  for ud_statep 0x%p in ud_state %d",
4977 			    ud_statep, ud_statep->ud_state);
4978 #endif
4979 		mutex_exit(&ud_statep->ud_state_mutex);
4980 	}
4981 }
4982 
4983 
4984 /*
4985  * ibcm_resend_srep_mad:
4986  *	Called on a duplicate incoming SIDR REQ on server side
4987  *	Posts the stored MAD from ud state structure using ud_stored_reply_addr
4988  *	Cancels any running timer, and then re-starts the timer
4989  *	This routine must be called with state structure table lock held
4990  *
4991  * INPUTS:
4992  *	ud_statep	-	ibcm_ud_state_data_t
4993  *
4994  * RETURN VALUE: NONE
4995  */
4996 void
4997 ibcm_resend_srep_mad(ibcm_ud_state_data_t *ud_statep)
4998 {
4999 	timeout_id_t		timer_val;
5000 
5001 	ASSERT(MUTEX_HELD(&ud_statep->ud_state_mutex));
5002 
5003 	IBTF_DPRINTF_L3(cmlog, "ibcm_resend_srep_mad: ud_statep 0x%p",
5004 	    ud_statep);
5005 
5006 	if (ud_statep->ud_send_mad_flags & IBCM_SREP_POST_BUSY)
5007 		return;
5008 
5009 	ud_statep->ud_send_mad_flags |= IBCM_SREP_POST_BUSY;
5010 
5011 	/* for nonblocking SIDR REP Post */
5012 	IBCM_UD_REF_CNT_INCR(ud_statep);
5013 
5014 	/* Cancel currently running timer */
5015 	timer_val = ud_statep->ud_timerid;
5016 
5017 	if (ud_statep->ud_timerid != 0) {
5018 		ud_statep->ud_timerid = 0;
5019 		mutex_exit(&ud_statep->ud_state_mutex);
5020 		(void) untimeout(timer_val);
5021 	} else {
5022 		mutex_exit(&ud_statep->ud_state_mutex);
5023 	}
5024 
5025 	/* Always resend the response MAD to the original reply destination */
5026 	ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg,
5027 	    ibcm_post_sidr_rep_complete, ud_statep);
5028 
5029 	mutex_enter(&ud_statep->ud_state_mutex);
5030 }
5031 
5032 
5033 /*
5034  * ibcm_build_reply_mad_addr:
5035  *	Forms the reply MAD address based on "incoming mad addr" that is
5036  *	supplied as an arg.
5037  *
5038  *	Swaps the source and destination gids in ib_grh_t
5039  *
5040  * INPUTS:
5041  * inp_mad_addr:	Address information in the incoming MAD
5042  * out_mad_addr:	Derived address for the reply MAD
5043  *			The reply MAD address is derived based
5044  *			address information of incoming CM MAD
5045  * RETURN VALUE: NONE
5046  */
5047 void
5048 ibcm_build_reply_mad_addr(ibcm_mad_addr_t *inp_mad_addr,
5049     ibcm_mad_addr_t *out_mad_addr)
5050 {
5051 	IBTF_DPRINTF_L5(cmlog, "ibcm_build_reply_mad_addr:");
5052 
5053 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_mad_addr))
5054 
5055 	bcopy(inp_mad_addr, out_mad_addr, sizeof (ibcm_mad_addr_t));
5056 
5057 	/* Swap the GIDs in the GRH */
5058 	if (inp_mad_addr->grh_exists == B_TRUE) {
5059 		ib_gid_t sgid = inp_mad_addr->grh_hdr.ig_sender_gid;
5060 
5061 		/* swap the SGID and DGID */
5062 		out_mad_addr->grh_hdr.ig_sender_gid =
5063 		    inp_mad_addr->grh_hdr.ig_recver_gid;
5064 		out_mad_addr->grh_hdr.ig_recver_gid = sgid;
5065 	}
5066 
5067 	/*
5068 	 * CM posts response MAD on a new/existing internal QP on the same port
5069 	 * and pkey
5070 	 */
5071 	out_mad_addr->cm_qp_entry =
5072 	    ibcm_find_qp(inp_mad_addr->cm_qp_entry->qp_port->port_hcap,
5073 	    inp_mad_addr->port_num, inp_mad_addr->rcvd_addr.ia_p_key);
5074 
5075 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_mad_addr))
5076 }
5077 
5078 
5079 /*
5080  * ibcm_post_rc_mad
5081  *	Posts a CM MAD associated with a RC statep
5082  *
5083  * INPUTS:
5084  * statep	: RC statep associated with the post
5085  * msgp		: CM MAD to be posted
5086  * post_cb	: non-NULL callback address implies non-blocking post
5087  * args		: Args to ibmf send callback
5088  *
5089  * RETURN VALUE: based on ibmf_send_mad
5090  */
5091 void
5092 ibcm_post_rc_mad(ibcm_state_data_t *statep, ibmf_msg_t *msgp,
5093     ibmf_msg_cb_t post_cb, void *args)
5094 {
5095 	ibt_status_t	status;
5096 
5097 	mutex_enter(&statep->state_mutex);
5098 	statep->post_time = gethrtime();
5099 	mutex_exit(&statep->state_mutex);
5100 	status = ibcm_post_mad(msgp, &statep->stored_reply_addr, post_cb,
5101 	    args);
5102 	if ((status != IBT_SUCCESS) && (post_cb != NULL))
5103 		/* Call ibmf callback directly */
5104 		(*post_cb)(NULL, msgp, args);
5105 }
5106 
5107 
5108 /*
5109  * ibcm_post_ud_mad
5110  *	Posts a CM MAD associated with a UD statep
5111  *
5112  * INPUTS:
5113  * ud_statep	: UD statep associated with the post
5114  * msgp		: CM MAD to be posted
5115  * post_cb	: non-NULL callback address implies non-blocking post
5116  * args		: Args to ibmf send callback
5117  *
5118  * RETURN VALUE: based on ibmf_send_mad
5119  */
5120 void
5121 ibcm_post_ud_mad(ibcm_ud_state_data_t *ud_statep, ibmf_msg_t *msgp,
5122     ibmf_msg_cb_t ud_post_cb, void *args)
5123 {
5124 	ibt_status_t	status;
5125 	status = ibcm_post_mad(msgp, &ud_statep->ud_stored_reply_addr,
5126 	    ud_post_cb, args);
5127 	if ((status != IBT_SUCCESS) && (ud_post_cb != NULL))
5128 		/* Call ibmf callback directly */
5129 		(*ud_post_cb)(NULL, msgp, args);
5130 }
5131 
5132 /*
5133  * ibcm_post_mad:
5134  *	Posts CM MAD using IBMF in blocking mode
5135  *
5136  * INPUTS:
5137  * msgp		: CM MAD to be posted
5138  * cm_mad_addr	: Address information for the MAD to be posted
5139  * post_cb	: non-NULL callback address implies non-blocking post
5140  * args		: Args to ibmf send callback
5141  *
5142  * RETURN VALUE: based on ibmf_send_mad
5143  */
5144 ibt_status_t
5145 ibcm_post_mad(ibmf_msg_t *msgp, ibcm_mad_addr_t *cm_mad_addr,
5146     ibmf_msg_cb_t post_cb, void *args)
5147 {
5148 	int	post_status;
5149 
5150 	IBTF_DPRINTF_L5(cmlog, "ibcm_post_mad: "
5151 	    "ibmf_msg_t = %p, cm_madd_adr = %p", msgp, cm_mad_addr);
5152 
5153 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_mad: dlid = %x, d_qno= %x",
5154 	    cm_mad_addr->rcvd_addr.ia_remote_lid,
5155 	    cm_mad_addr->rcvd_addr.ia_remote_qno);
5156 	IBTF_DPRINTF_L4(cmlog, "ibcm_post_mad: p_key = %x, q_key = %x, "
5157 	    "sl = %x, grh_exists = %x",
5158 	    cm_mad_addr->rcvd_addr.ia_p_key, cm_mad_addr->rcvd_addr.ia_q_key,
5159 	    cm_mad_addr->rcvd_addr.ia_service_level, cm_mad_addr->grh_exists);
5160 
5161 	/* Copy local addressing info */
5162 	msgp->im_local_addr = cm_mad_addr->rcvd_addr;
5163 
5164 	/* Copy global/GRH addressing info */
5165 	if (cm_mad_addr->grh_exists == B_TRUE)
5166 		msgp->im_global_addr = cm_mad_addr->grh_hdr;
5167 
5168 	if (post_cb)
5169 		ibcm_flow_inc();
5170 	post_status = ibmf_msg_transport(
5171 	    cm_mad_addr->ibmf_hdl, cm_mad_addr->cm_qp_entry->qp_cm, msgp,
5172 	    NULL, post_cb, args, 0);
5173 	if (post_status != IBMF_SUCCESS) {
5174 		IBTF_DPRINTF_L2(cmlog, "ibcm_post_mad: ibmf_msg_transport "
5175 		    "failed: status %d, cb = %p", post_status, post_cb);
5176 		/* Analyze the reason for failure */
5177 		return (ibcm_ibmf_analyze_error(post_status));
5178 	}
5179 
5180 	return (IBT_SUCCESS);
5181 }
5182 
5183 
5184 /*
5185  * ibcm_process_get_classport_info:
5186  *	Get classportinfo
5187  *
5188  * INPUTS:
5189  *	hcap		- HCA entry pointer
5190  *	input_madp	- Input MAD pointer
5191  *	cm_mad_addr	- Address information for the MAD to be posted
5192  *
5193  * RETURN VALUE: NONE
5194  */
5195 static void
5196 ibcm_process_get_classport_info(ibcm_hca_info_t *hcap, uint8_t *input_madp,
5197     ibcm_mad_addr_t *cm_mad_addr)
5198 {
5199 	ibmf_msg_t		*msgp;
5200 
5201 	IBTF_DPRINTF_L5(cmlog, "ibcm_process_get_classport_info: (%p, %p, %p)",
5202 	    hcap, input_madp, cm_mad_addr);
5203 
5204 	if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &msgp,
5205 	    MAD_METHOD_GET_RESPONSE) != IBT_SUCCESS) {
5206 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_classport_info: "
5207 		    "ibcm_alloc_out_msg failed");
5208 		return;
5209 	}
5210 
5211 	/* copy the transaction id from input get mad */
5212 	IBCM_OUT_HDRP(msgp)->TransactionID =
5213 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
5214 	IBCM_OUT_HDRP(msgp)->AttributeID = h2b16(MAD_ATTR_ID_CLASSPORTINFO);
5215 
5216 	bcopy(&ibcm_clpinfo, IBCM_OUT_MSGP(msgp), sizeof (ibcm_clpinfo));
5217 
5218 	(void) ibcm_post_mad(msgp, cm_mad_addr, NULL, NULL);
5219 	(void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &msgp);
5220 
5221 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_classport_info: done");
5222 }
5223 
5224 /*
5225  * ibcm_decode_classport_info:
5226  *	Decode classportinfo
5227  *
5228  * INPUTS:
5229  *	hcap		- HCA entry pointer
5230  *	cm_mad_addr	- Address information for the MAD to be posted
5231  *	input_madp	- Input MAD pointer
5232  *
5233  * RETURN VALUE: NONE
5234  */
5235 static void
5236 ibcm_decode_classport_info(ibcm_hca_info_t *hcap, uint8_t *input_madp,
5237     ibcm_mad_addr_t *cm_mad_addr)
5238 {
5239 	ibcm_classportinfo_msg_t *portinfop = (ibcm_classportinfo_msg_t *)
5240 	    (&input_madp[IBCM_MAD_HDR_SIZE]);
5241 	IBTF_DPRINTF_L5(cmlog, "ibcm_decode_classport_info: (%p, %p, %p)",
5242 	    hcap, input_madp, cm_mad_addr);
5243 
5244 	/* Print various fields of received classportinfo in debuf buf */
5245 
5246 	IBTF_DPRINTF_L4(cmlog, "ibcm_decode_classport_info: "
5247 	    "Base version %d Class version %d", portinfop->BaseVersion,
5248 	    portinfop->ClassVersion);
5249 	IBTF_DPRINTF_L4(cmlog, "ibcm_decode_classport_info: "
5250 	    "Cap Mask %d Resp Time %d", portinfop->CapabilityMask,
5251 	    portinfop->RespTimeValue_plus);
5252 }
5253 
5254 
5255 /*
5256  * ibcm_handler_conn_fail:
5257  *	Helper function used to call client handler for Conn fail event
5258  *
5259  * INPUTS:
5260  *	statep:			The connection state pointer
5261  *	rej_type:		Message being rejected
5262  *	rej_reason:		Reason why CM is sending the REJ message
5263  *	client_data:		Private data returned by the client for REJ
5264  *	client_data_len:	Length of above client's private data.
5265  *
5266  * RETURN VALUE:	Client Handler's return status
5267  */
5268 static void
5269 ibcm_handler_conn_fail(ibcm_state_data_t *statep, uint8_t cf_code,
5270     uint8_t cf_msg, ibt_cm_reason_t cf_reason, uint8_t *client_data,
5271     ibt_priv_data_len_t client_data_len)
5272 {
5273 	ibt_cm_event_t	event;
5274 
5275 	ibcm_path_cache_purge();
5276 
5277 	/* Invoke CM handler w/ event passed as arg */
5278 	if (statep->cm_handler != NULL) {
5279 		bzero(&event, sizeof (ibt_cm_event_t));
5280 
5281 		event.cm_type = IBT_CM_EVENT_FAILURE;
5282 		event.cm_channel = statep->channel;
5283 		event.cm_session_id = NULL;
5284 		event.cm_priv_data = NULL;
5285 		event.cm_priv_data_len = 0;
5286 
5287 		event.cm_event.failed.cf_code = cf_code;
5288 		event.cm_event.failed.cf_msg =  cf_msg;
5289 		event.cm_event.failed.cf_reason =  cf_reason;
5290 
5291 		ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_FAIL_EVENT);
5292 
5293 		(void) statep->cm_handler(statep->state_cm_private, &event,
5294 		    NULL, client_data, client_data_len);
5295 
5296 		ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_FAIL_EVENT);
5297 	}
5298 	if (ibcm_enable_trace != 0)
5299 		ibcm_dump_conn_trace(statep);
5300 	mutex_enter(&statep->state_mutex);
5301 	ibcm_open_done(statep);
5302 	mutex_exit(&statep->state_mutex);
5303 }
5304 
5305 /*
5306  * QP State transition functions here
5307  *
5308  * The brief description of these functions :
5309  *	Validate QP related attributes in the messages
5310  *	Call client/server callback handlers
5311  *	Change QP state
5312  *	Set QP attributes (modify QP)
5313  *	Fill up the response MADs
5314  */
5315 
5316 /*
5317  * ibcm_set_primary_adds_vect:
5318  *	Helper function used to fill up ibt_adds_vect_t PRIMARY PATH
5319  *	(called from ibcm_cep_state_*() functions)
5320  *
5321  * INPUTS:
5322  * statep	: The connection state pointer
5323  * adds_vectp	: The ibt_adds_vect_t ptr that is being filled up
5324  * msgp		: CM REQ message that is the source of information
5325  *
5326  * RETURN VALUE:	NONE
5327  */
5328 static void
5329 ibcm_set_primary_adds_vect(ibcm_state_data_t *statep,
5330     ibt_adds_vect_t *adds_vectp, ibcm_req_msg_t *msgp)
5331 {
5332 	uint32_t flow_label20_res6_rate6;
5333 
5334 	flow_label20_res6_rate6 = b2h32(msgp->req_primary_flow_label_plus);
5335 
5336 	/* first setup the srvl, srate, dlid and dgid */
5337 	adds_vectp->av_srvl = msgp->req_primary_sl_plus >> 4;
5338 	adds_vectp->av_src_path = statep->prim_src_path_bits;
5339 
5340 	if (statep->mode == IBCM_PASSIVE_MODE) {
5341 		adds_vectp->av_dlid = b2h16(msgp->req_primary_l_port_lid);
5342 		adds_vectp->av_dgid.gid_prefix =
5343 		    b2h64(msgp->req_primary_l_port_gid.gid_prefix);
5344 		adds_vectp->av_dgid.gid_guid =
5345 		    b2h64(msgp->req_primary_l_port_gid.gid_guid);
5346 		adds_vectp->av_sgid.gid_prefix =
5347 		    b2h64(msgp->req_primary_r_port_gid.gid_prefix);
5348 		adds_vectp->av_sgid.gid_guid =
5349 		    b2h64(msgp->req_primary_r_port_gid.gid_guid);
5350 		adds_vectp->av_srate = flow_label20_res6_rate6 & 0x3f;
5351 	} else {
5352 		adds_vectp->av_dlid = b2h16(msgp->req_primary_r_port_lid);
5353 		adds_vectp->av_dgid.gid_prefix =
5354 		    b2h64(msgp->req_primary_r_port_gid.gid_prefix);
5355 		adds_vectp->av_dgid.gid_guid =
5356 		    b2h64(msgp->req_primary_r_port_gid.gid_guid);
5357 		adds_vectp->av_sgid.gid_prefix =
5358 		    b2h64(msgp->req_primary_l_port_gid.gid_prefix);
5359 		adds_vectp->av_sgid.gid_guid =
5360 		    b2h64(msgp->req_primary_l_port_gid.gid_guid);
5361 		adds_vectp->av_srate = statep->local_srate;
5362 	}
5363 
5364 	/* next copy off the GRH info if it exists  */
5365 	if ((msgp->req_primary_sl_plus & 0x8) == 0) {
5366 		adds_vectp->av_send_grh = B_TRUE;
5367 		adds_vectp->av_flow = flow_label20_res6_rate6 >> 12;
5368 		adds_vectp->av_tclass = msgp->req_primary_traffic_class;
5369 		adds_vectp->av_hop = msgp->req_primary_hop_limit;
5370 	} else {
5371 		adds_vectp->av_send_grh = B_FALSE;
5372 	}
5373 }
5374 
5375 
5376 /*
5377  * ibcm_set_alt_adds_vect:
5378  *	Helper function used to fill up ibt_adds_vect_t ALTERNATE PATH
5379  *	(called from ibcm_cep_state_*() functions)
5380  *
5381  * INPUTS:
5382  * statep	: The connection state pointer
5383  * adds_vectp	: The ibt_adds_vect_t ptr that is being filled up
5384  * msgp		: CM REQ message that is the source of information
5385  *
5386  * RETURN VALUE:	NONE
5387  */
5388 static void
5389 ibcm_set_alt_adds_vect(ibcm_state_data_t *statep,
5390     ibt_adds_vect_t *adds_vectp, ibcm_req_msg_t *msgp)
5391 {
5392 	ib_gid_t dgid;
5393 	ib_gid_t sgid;
5394 	uint32_t flow_label20_res6_rate6;
5395 
5396 	flow_label20_res6_rate6 = b2h32(msgp->req_alt_flow_label_plus);
5397 
5398 	/* first setup the srvl, srate, dlid and dgid */
5399 	adds_vectp->av_srvl = msgp->req_alt_sl_plus >> 4;
5400 	adds_vectp->av_src_path = statep->alt_src_path_bits;
5401 
5402 	if (statep->mode == IBCM_PASSIVE_MODE) {
5403 		adds_vectp->av_dlid = b2h16(msgp->req_alt_l_port_lid);
5404 		bcopy(&msgp->req_alt_l_port_gid[0], &dgid, sizeof (ib_gid_t));
5405 		bcopy(&msgp->req_alt_r_port_gid[0], &sgid, sizeof (ib_gid_t));
5406 		adds_vectp->av_srate = flow_label20_res6_rate6 & 0x3f;
5407 	} else {
5408 		adds_vectp->av_dlid = b2h16(msgp->req_alt_r_port_lid);
5409 		bcopy(&msgp->req_alt_r_port_gid[0], &dgid, sizeof (ib_gid_t));
5410 		bcopy(&msgp->req_alt_l_port_gid[0], &sgid, sizeof (ib_gid_t));
5411 		adds_vectp->av_srate = statep->local_alt_srate;
5412 	}
5413 	adds_vectp->av_dgid.gid_prefix = b2h64(dgid.gid_prefix);
5414 	adds_vectp->av_dgid.gid_guid = b2h64(dgid.gid_guid);
5415 	adds_vectp->av_sgid.gid_prefix = b2h64(sgid.gid_prefix);
5416 	adds_vectp->av_sgid.gid_guid = b2h64(sgid.gid_guid);
5417 
5418 	/* next copy off the GRH info if it exists  */
5419 	if ((msgp->req_alt_sl_plus & 0x8) == 0) {
5420 		adds_vectp->av_send_grh = B_TRUE;
5421 		adds_vectp->av_flow = flow_label20_res6_rate6 >> 12;
5422 		adds_vectp->av_tclass = msgp->req_alt_traffic_class;
5423 		adds_vectp->av_hop = msgp->req_alt_hop_limit;
5424 	} else {
5425 		adds_vectp->av_send_grh = B_FALSE;	/* no GRH */
5426 	}
5427 }
5428 
5429 
5430 /*
5431  * ibcm_set_primary_cep_path:
5432  *	Helper function used to fill up ibt_cep_path_t PRIMARY PATH
5433  *	(called from ibcm_cep_state_*() functions)
5434  *
5435  * INPUTS:
5436  * statep	: The connection state pointer
5437  * adds_vectp	: The ibt_cep_path_t ptr that is being filled up
5438  * msgp		: CM REQ message that is the source of information
5439  *
5440  * RETURN VALUE:	NONE
5441  */
5442 static ibt_status_t
5443 ibcm_set_primary_cep_path(ibcm_state_data_t *statep, ibt_cep_path_t *pathp,
5444     ibcm_req_msg_t *msgp)
5445 {
5446 	ibt_status_t		status;
5447 
5448 	/* validate the PKEY in REQ for prim port */
5449 	status = ibt_pkey2index_byguid(statep->local_hca_guid,
5450 	    statep->prim_port, b2h16(msgp->req_part_key), &pathp->cep_pkey_ix);
5451 
5452 	if (status != IBT_SUCCESS) {
5453 		IBTF_DPRINTF_L2(cmlog, "ibcm_set_primary_cep_path: "
5454 		    "statep 0x%p pkey %x prim_port %d ", statep,
5455 		    b2h16(msgp->req_part_key), statep->prim_port);
5456 		IBTF_DPRINTF_L2(cmlog, "ibcm_set_primary_cep_path: "
5457 		    "statep 0x%p Invalid PKEY on prim_port, status %d ",
5458 		    statep, status);
5459 		return (status);
5460 	}
5461 	statep->pkey = b2h16(msgp->req_part_key);
5462 	ibcm_set_primary_adds_vect(statep, &pathp->cep_adds_vect, msgp);
5463 	return (IBT_SUCCESS);
5464 }
5465 
5466 
5467 /*
5468  * ibcm_set_alt_cep_path:
5469  *	Helper function used to fill up ibt_cep_path_t ALTERNATE PATH
5470  *	(called from ibcm_cep_state_*() functions)
5471  *
5472  * INPUTS:
5473  * statep	: The connection state pointer
5474  * adds_vectp	: The ibt_cep_path_t ptr that is being filled up
5475  * msgp		: CM REQ message that is the source of information
5476  *
5477  * RETURN VALUE:	NONE
5478  */
5479 static ibt_status_t
5480 ibcm_set_alt_cep_path(ibcm_state_data_t *statep, ibt_cep_path_t *pathp,
5481     ibcm_req_msg_t *msgp)
5482 {
5483 	ibt_status_t		status;
5484 
5485 	if (b2h16(msgp->req_alt_l_port_lid) == 0) {
5486 		/* no alternate path specified */
5487 		return (IBT_SUCCESS);
5488 	}
5489 
5490 	/* validate the PKEY in REQ for alt port */
5491 	status = ibt_pkey2index_byguid(statep->local_hca_guid,
5492 	    statep->alt_port, b2h16(msgp->req_part_key), &pathp->cep_pkey_ix);
5493 
5494 	if (status != IBT_SUCCESS) {
5495 		IBTF_DPRINTF_L2(cmlog, "ibcm_set_alt_cep_path: "
5496 		    "statep 0x%p pkey %x alt_port %d ", statep,
5497 		    b2h16(msgp->req_part_key), statep->alt_port);
5498 		IBTF_DPRINTF_L2(cmlog, "ibcm_set_alt_cep_path: "
5499 		    "statep 0x%p Invalid PKEY on alt_port, status %d ",
5500 		    statep, status);
5501 		return (status);
5502 	}
5503 	pathp->cep_hca_port_num = statep->alt_port;
5504 	ibcm_set_alt_adds_vect(statep, &pathp->cep_adds_vect, msgp);
5505 	return (IBT_SUCCESS);
5506 
5507 }
5508 
5509 /*
5510  * ibcm_compare_prim_alt_paths:
5511  *	Helper function used to find if primary and alternate paths are
5512  *	identical
5513  *	(called from ibcm_cep_state_req)
5514  *
5515  * INPUTS:
5516  * req:			Pointer to ibt_cm_req_rcv_t, filled before invoking
5517  *			the function
5518  *
5519  * RETURN VALUE:	NONE
5520  */
5521 
5522 static boolean_t
5523 ibcm_compare_prim_alt_paths(ibt_adds_vect_t *prim, ibt_adds_vect_t *alt)
5524 {
5525 
5526 	if ((alt->av_dlid == prim->av_dlid) &&
5527 	    (alt->av_dgid.gid_prefix == prim->av_dgid.gid_prefix) &&
5528 	    (alt->av_dgid.gid_guid == prim->av_dgid.gid_guid) &&
5529 	    (alt->av_sgid.gid_prefix == prim->av_sgid.gid_prefix) &&
5530 	    (alt->av_sgid.gid_guid == prim->av_sgid.gid_guid) &&
5531 	    (alt->av_src_path == prim->av_src_path)) {
5532 
5533 		return (B_TRUE);
5534 	}
5535 	return (B_FALSE);
5536 }
5537 
5538 
5539 /*
5540  * ibcm_invoke_qp_modify:
5541  *	Helper function used to call ibt_modify_qp()
5542  *	called from ibcm_cep_state_req()/ibcm_cep_state_rep()
5543  *	It sets up qp_info/eec_info
5544  *
5545  *	Sets state to RTR as well.
5546  *
5547  *
5548  * INPUTS:
5549  *	statep:		The connection state pointer
5550  *	req_msgp:	The CM REQ message
5551  *
5552  * RETURN VALUE:
5553  *	IBT_SUCCESS	-	call succeeded
5554  */
5555 static ibt_status_t
5556 ibcm_invoke_qp_modify(ibcm_state_data_t *statep, ibcm_req_msg_t *req_msgp,
5557     ibcm_rep_msg_t *rep_msgp)
5558 {
5559 	ibt_status_t		status;
5560 	ibt_qp_info_t		qp_info;
5561 	ibt_cep_modify_flags_t	cep_flags;
5562 	ibt_tran_srv_t		trans;
5563 
5564 	cep_flags = IBT_CEP_SET_INIT_RTR | IBT_CEP_SET_PKEY_IX;
5565 	trans = ((uint8_t *)&req_msgp->req_remote_eecn_plus)[3] >> 1 & 0x3;
5566 
5567 	ASSERT(statep->channel != NULL);
5568 
5569 	/*
5570 	 * If alternate path is present in REQ message then
5571 	 * OR in IBT_CEP_SET_ALT_PATH, if APM supported on hca
5572 	 */
5573 	if (b2h16(req_msgp->req_alt_l_port_lid) != 0) {
5574 
5575 		if (statep->hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)
5576 			cep_flags |= IBT_CEP_SET_ALT_PATH;
5577 			/* default value of rep_failover is ACCEPT */
5578 		else {
5579 			rep_msgp->rep_target_delay_plus |=
5580 			    IBT_CM_FAILOVER_REJ_NOTSUPP << 1;
5581 			IBTF_DPRINTF_L3(cmlog, "ibcm_invoke_qp_modify"
5582 			    " Alt Path specified in REQ, but not supported");
5583 		}
5584 	}
5585 
5586 	/* If transport type is RD OR in IBC_CEP_SET_QKEY */
5587 	if (trans == IBT_RD_SRV) {
5588 		cep_flags |= IBT_CEP_SET_QKEY;
5589 	}
5590 
5591 	/* Start filling up ibt_qp_info_t.  */
5592 	bzero(&qp_info, sizeof (qp_info));
5593 	qp_info.qp_trans = trans;
5594 	qp_info.qp_state = IBT_STATE_RTR;
5595 	qp_info.qp_flags = IBT_CEP_NO_FLAGS;
5596 
5597 	switch (trans) {
5598 	case IBT_RC_SRV:
5599 
5600 		if (statep->mode == IBCM_ACTIVE_MODE) {
5601 			/* Setting PSN on RQ */
5602 
5603 			IBCM_QPINFO_RC(qp_info).rc_rq_psn =
5604 			    b2h32(req_msgp->req_starting_psn_plus) >> 8;
5605 
5606 			IBCM_QPINFO_RC(qp_info).rc_dst_qpn =
5607 			    b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
5608 
5609 			/* RDMA resources taken from negotiated REP values */
5610 			IBCM_QPINFO_RC(qp_info).rc_rdma_ra_in =
5611 			    rep_msgp->rep_initiator_depth;
5612 
5613 		} else { /* Passive side CM */
5614 			/* Setting PSN on SQ and RQ */
5615 			IBCM_QPINFO_RC(qp_info).rc_rq_psn =
5616 			    b2h32(rep_msgp->rep_starting_psn_plus) >> 8;
5617 
5618 			IBCM_QPINFO_RC(qp_info).rc_dst_qpn =
5619 			    b2h32(req_msgp->req_local_qpn_plus) >> 8;
5620 
5621 			/* RDMA resources taken from negotiated REP values */
5622 			IBCM_QPINFO_RC(qp_info).rc_rdma_ra_in =
5623 			    rep_msgp->rep_resp_resources;
5624 		}
5625 
5626 		/* XXX, Oh!, ibtl doesn't have interface for setting this */
5627 		IBCM_QPINFO_RC(qp_info).rc_min_rnr_nak =
5628 		    ibcm_default_rnr_nak_time;
5629 		IBCM_QPINFO_RC(qp_info).rc_path_mtu =
5630 		    req_msgp->req_mtu_plus >> 4;
5631 		IBCM_QPINFO_RC(qp_info).rc_retry_cnt =
5632 		    ((uint8_t *)&req_msgp->req_starting_psn_plus)[3] & 0x7;
5633 		IBCM_QPINFO_RC(qp_info).rc_rnr_retry_cnt =
5634 		    req_msgp->req_mtu_plus & 0x7;
5635 
5636 		if ((status = ibcm_set_primary_cep_path(statep,
5637 		    &IBCM_QPINFO_RC(qp_info).rc_path, req_msgp)) !=
5638 		    IBT_SUCCESS)
5639 			return (status);
5640 
5641 		if ((status = ibcm_set_alt_cep_path(statep,
5642 		    &IBCM_QPINFO_RC(qp_info).rc_alt_path, req_msgp)) !=
5643 		    IBT_SUCCESS)
5644 			return (status);
5645 
5646 		break;
5647 	case IBT_RD_SRV:
5648 		if (statep->mode == IBCM_ACTIVE_MODE) { /* look at REP msg */
5649 			IBCM_QPINFO(qp_info).rd.rd_qkey =
5650 			    b2h32(rep_msgp->rep_local_qkey);
5651 		} else {
5652 			IBCM_QPINFO(qp_info).rd.rd_qkey =
5653 			    b2h32(req_msgp->req_local_qkey);
5654 		}
5655 
5656 		break;
5657 
5658 	case IBT_UC_SRV:
5659 		if (statep->mode == IBCM_ACTIVE_MODE) { /* look at REP msg */
5660 			IBCM_QPINFO_UC(qp_info).uc_rq_psn =
5661 			    b2h32(req_msgp->req_starting_psn_plus) >> 8;
5662 			IBCM_QPINFO_UC(qp_info).uc_dst_qpn =
5663 			    b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
5664 		} else {
5665 			IBCM_QPINFO_UC(qp_info).uc_rq_psn =
5666 			    b2h32(rep_msgp->rep_starting_psn_plus) >> 8;
5667 			IBCM_QPINFO_UC(qp_info).uc_dst_qpn =
5668 			    b2h32(req_msgp->req_local_qpn_plus) >> 8;
5669 		}
5670 		IBCM_QPINFO_UC(qp_info).uc_path_mtu =
5671 		    req_msgp->req_mtu_plus >> 4;
5672 
5673 		if ((status = ibcm_set_primary_cep_path(statep,
5674 		    &IBCM_QPINFO_UC(qp_info).uc_path, req_msgp)) !=
5675 		    IBT_SUCCESS)
5676 			return (status);
5677 
5678 		if ((status = ibcm_set_alt_cep_path(statep,
5679 		    &IBCM_QPINFO_UC(qp_info).uc_alt_path, req_msgp)) !=
5680 		    IBT_SUCCESS)
5681 			return (status);
5682 
5683 		break;
5684 	default:
5685 		IBTF_DPRINTF_L2(cmlog, "ibcm_invoke_qp_modify: "
5686 		    "unknown svc_type = %x", trans);
5687 		break;
5688 	}
5689 
5690 	/* Call modify_qp */
5691 	status = ibt_modify_qp(statep->channel, cep_flags, &qp_info, NULL);
5692 	IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_qp_modify: statep 0x%p"
5693 	    " ibt_modify_qp() Init to RTR returned = %d", statep, status);
5694 
5695 	if (status == IBT_SUCCESS)
5696 		ibcm_insert_trace(statep, IBCM_TRACE_INIT_RTR);
5697 	else
5698 		ibcm_insert_trace(statep, IBCM_TRACE_INIT_RTR_FAIL);
5699 
5700 #ifdef	DEBUG
5701 
5702 	print_modify_qp("Init to RTR", statep->channel, cep_flags, &qp_info);
5703 
5704 	if (statep->channel != NULL) {
5705 		ibt_qp_query_attr_t	qp_attrs;
5706 
5707 		(void) ibt_query_qp(statep->channel, &qp_attrs);
5708 		IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_qp_modify: "
5709 		    "qp_info.qp_state = %x", qp_attrs.qp_info.qp_state);
5710 	}
5711 #endif
5712 
5713 	return (status);
5714 }
5715 
5716 
5717 /*
5718  * ibcm_verify_req_gids_and_svcid
5719  *	Validation of LIDs, GIDs and SVC ID
5720  *
5721  * INPUTS:
5722  *	statep		- state pointer
5723  *	cm_req_msgp	- REQ message pointer
5724  *
5725  * RETURN VALUE: IBCM_SUCCESS/IBCM_FAILURE
5726  *
5727  */
5728 ibcm_status_t
5729 ibcm_verify_req_gids_and_svcid(ibcm_state_data_t *statep,
5730     ibcm_req_msg_t *cm_req_msgp)
5731 {
5732 	ib_gid_t		gid;
5733 	ib_gid_t		agid;
5734 	ib_lid_t		lid;
5735 	ibt_status_t		status;
5736 	ibtl_cm_hca_port_t	port;
5737 	ibt_cm_reason_t		reject_reason = IBT_CM_SUCCESS;
5738 	ibcm_svc_info_t		*svc_infop;
5739 	ibcm_svc_bind_t		*svc_bindp;
5740 	ibcm_svc_bind_t		*tmp_bindp;
5741 	ib_pkey_t		pkey;
5742 	uint8_t			port_num;
5743 	ib_guid_t		hca_guid;
5744 	ibcm_ip_pvtdata_t	*ip_data;
5745 
5746 	/* Verify LID and GID of primary port */
5747 
5748 	gid.gid_prefix = b2h64(cm_req_msgp->req_primary_r_port_gid.gid_prefix);
5749 	gid.gid_guid = b2h64(cm_req_msgp->req_primary_r_port_gid.gid_guid);
5750 
5751 	IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p"
5752 	    " PRIM _r_gid (%llx, %llx)", statep, gid.gid_prefix,
5753 	    gid.gid_guid);
5754 
5755 	IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5756 	    "PRIM passive lid %x", statep,
5757 	    b2h16(cm_req_msgp->req_primary_r_port_lid));
5758 
5759 	/* Verify GID validity, if specified */
5760 	if ((status = ibtl_cm_get_hca_port(gid, 0, &port)) == IBT_SUCCESS) {
5761 
5762 		IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5763 		    "prim_port_num %d", statep, port.hp_port);
5764 
5765 		IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5766 		    "passive hca_guid 0x%llX", statep, port.hp_hca_guid);
5767 
5768 		port_num = port.hp_port;
5769 		hca_guid = port.hp_hca_guid;
5770 	}
5771 
5772 	if (status != IBT_SUCCESS) {
5773 		IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5774 		    "ibtl_cm_get_hca_port() primary port failed = %d", statep,
5775 		    status);
5776 		reject_reason = IBT_CM_PRIM_GID;
5777 		/* we will search for an acceptable GID to this port */
5778 		port_num = statep->stored_reply_addr.port_num;
5779 		hca_guid = statep->hcap->hca_guid;
5780 
5781 	} else if (port.hp_base_lid !=
5782 	    (b2h16(cm_req_msgp->req_primary_r_port_lid) &
5783 	    (~((1 << port.hp_lmc) - 1)))) {
5784 		IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids: statep 0x%p "
5785 		    "primary port lid invalid (%x, %x, %x)", statep,
5786 		    port.hp_base_lid,
5787 		    b2h16(cm_req_msgp->req_primary_r_port_lid), port.hp_lmc);
5788 		reject_reason = IBT_CM_PRIM_LID;
5789 	} else {
5790 
5791 		statep->local_hca_guid = port.hp_hca_guid;
5792 		statep->prim_port = port.hp_port;
5793 		statep->prim_src_path_bits =
5794 		    b2h16(cm_req_msgp->req_primary_r_port_lid) -
5795 		    port.hp_base_lid;
5796 
5797 		IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: "
5798 		    "statep 0x%p prim_port_path_bits %d ",
5799 		    statep, statep->prim_src_path_bits);
5800 
5801 		/* Verify LID and GID  of alternate port. Post REJ if invalid */
5802 
5803 		/* Need a bcopy, as alt port gid is unaligned in req message */
5804 		bcopy(&cm_req_msgp->req_alt_r_port_gid[0], &agid,
5805 		    sizeof (ib_gid_t));
5806 		agid.gid_prefix = b2h64(agid.gid_prefix);
5807 		agid.gid_guid = b2h64(agid.gid_guid);
5808 
5809 		IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: statep 0x%p"
5810 		    " Alt port_gid is (%llX:%llX)", statep, agid.gid_prefix,
5811 		    agid.gid_guid);
5812 
5813 		if ((agid.gid_prefix != 0) || (agid.gid_guid != 0)) {
5814 
5815 			/* Verify GID validity, if specified */
5816 			if ((status = ibtl_cm_get_hca_port(agid,
5817 			    statep->local_hca_guid, &port)) != IBT_SUCCESS) {
5818 				IBTF_DPRINTF_L2(cmlog,
5819 				    "ibcm_verify_req_gids: ibtl_cm_get_hca_port"
5820 				    " statep 0x%p alternate port failed = %d",
5821 				    statep, status);
5822 				reject_reason = IBT_CM_ALT_GID;
5823 
5824 			} else if (port.hp_base_lid !=
5825 			    (b2h16(cm_req_msgp->req_alt_r_port_lid) &
5826 			    (~((1 << port.hp_lmc) - 1)))) {
5827 
5828 				IBTF_DPRINTF_L2(cmlog,
5829 				    "ibcm_verify_req_gids: statep 0x%p "
5830 				    "alternate port lid invalid (%x, %x, %x)",
5831 				    statep, port.hp_base_lid,
5832 				    cm_req_msgp->req_alt_r_port_lid,
5833 				    port.hp_lmc);
5834 				reject_reason = IBT_CM_ALT_LID;
5835 			} else { /* Alt LID and GID are valid */
5836 				statep->alt_port = port.hp_port;
5837 				statep->alt_src_path_bits =
5838 				    b2h16(cm_req_msgp->req_alt_r_port_lid) -
5839 				    port.hp_base_lid;
5840 
5841 				IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: "
5842 				    "statep 0x%p alt_port_num %d "
5843 				    "alt_rc_hca_guid 0x%llX", statep,
5844 				    port.hp_port, port.hp_hca_guid);
5845 
5846 				IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: "
5847 				    "statep 0x%p alt_port_path_bits %d ",
5848 				    statep, statep->alt_src_path_bits);
5849 			}
5850 		}
5851 	}
5852 
5853 	mutex_enter(&ibcm_svc_info_lock);
5854 	svc_infop = ibcm_find_svc_entry(statep->svcid);
5855 
5856 	/*
5857 	 * Note: When we return SUCCESS, the reader lock won't get dropped
5858 	 * until after the cm_handler is called from ibcm_cep_state_req().
5859 	 */
5860 
5861 	IBTF_DPRINTF_L4(cmlog, "ibcm_verify_req_gids: "
5862 	    "ibcm_find_svc_entry found svc_infop %p", svc_infop);
5863 
5864 	/*
5865 	 * Send REJ with reject reason "invalid service id" for the
5866 	 * the following cases :-
5867 	 * Service id is valid, but not available at gid/lid of REQ
5868 	 * Service id is invalid
5869 	 */
5870 
5871 	if (svc_infop == NULL || svc_infop->svc_bind_list == NULL) {
5872 		mutex_exit(&ibcm_svc_info_lock);
5873 
5874 		IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid: "
5875 		    "statep 0x%p svc_id %llX svc_infop NULL", statep,
5876 		    statep->svcid);
5877 
5878 		/* Send a REJ with invalid SID reason */
5879 		ibcm_post_rej_mad(statep,
5880 		    IBT_CM_INVALID_SID, IBT_CM_FAILURE_REQ, NULL, 0);
5881 		return (IBCM_FAILURE);
5882 	}
5883 
5884 	if (svc_infop->svc_rc_handler == NULL) {
5885 		mutex_exit(&ibcm_svc_info_lock);
5886 
5887 		/* Send a REJ with invalid SID reason */
5888 		ibcm_post_rej_mad(statep,
5889 		    IBT_CM_INVALID_SRV_TYPE, IBT_CM_FAILURE_REQ, NULL, 0);
5890 		return (IBCM_FAILURE);
5891 	}
5892 
5893 	/*
5894 	 * Check if ServiceID is in RDMA IP CM SID range, if yes, we parse
5895 	 * the REQ's Private Data and verify for it's goodness.
5896 	 */
5897 	if (((statep->svcid & IB_SID_IPADDR_PREFIX_MASK) == 0) &&
5898 	    (statep->svcid & IB_SID_IPADDR_PREFIX)) {
5899 		ibt_ari_ip_t	ari_ip;
5900 		boolean_t	rdma_rej_mad = B_FALSE;
5901 
5902 		if (cm_req_msgp->req_private_data == NULL) {
5903 			mutex_exit(&ibcm_svc_info_lock);
5904 
5905 			IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:"
5906 			    " RDMA CM IP REQ Priv Data is NULL");
5907 
5908 			/* Send a REJ with CONSUMER REJ */
5909 			ibcm_post_rej_mad(statep, IBT_CM_CONSUMER,
5910 			    IBT_CM_FAILURE_REQ, NULL, 0);
5911 			return (IBCM_FAILURE);
5912 		}
5913 		ip_data = (ibcm_ip_pvtdata_t *)cm_req_msgp->req_private_data;
5914 
5915 		bzero(&ari_ip, sizeof (ibt_ari_ip_t));
5916 
5917 		/* RDMA IP CM Layer Rejects this */
5918 		if (ip_data->ip_MajV != IBT_CM_IP_MAJ_VER) {
5919 			IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:"
5920 			    "IP MajorVer mis-match %d", ip_data->ip_MajV);
5921 			ari_ip.ip_reason = IBT_ARI_IP_MAJOR_VERSION;
5922 			ari_ip.ip_suggested_version = IBT_CM_IP_MAJ_VER;
5923 			ari_ip.ip_suggested = B_TRUE;
5924 			rdma_rej_mad = B_TRUE;
5925 		} else if (ip_data->ip_MinV != IBT_CM_IP_MIN_VER) {
5926 			IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:"
5927 			    "IP MinorVer mis-match %d", ip_data->ip_MinV);
5928 			ari_ip.ip_reason = IBT_ARI_IP_MINOR_VERSION;
5929 			ari_ip.ip_suggested_version = IBT_CM_IP_MIN_VER;
5930 			ari_ip.ip_suggested = B_TRUE;
5931 			rdma_rej_mad = B_TRUE;
5932 		} else if ((ip_data->ip_ipv != IBT_CM_IP_IPV_V4) &&
5933 		    (ip_data->ip_ipv != IBT_CM_IP_IPV_V6)) {
5934 			IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:"
5935 			    " Invalid IPV specified %d", ip_data->ip_ipv);
5936 			ari_ip.ip_reason = IBT_ARI_IP_IPV;
5937 			ari_ip.ip_suggested_version = IBT_CM_IP_IPV_V4;
5938 			ari_ip.ip_suggested = B_TRUE;
5939 			rdma_rej_mad = B_TRUE;
5940 		} else {
5941 			/*
5942 			 * Validate whether ip_addr specified are non-NULL.
5943 			 *
5944 			 * NOTE:
5945 			 * RDMA ULP which is servicing this SID, should validate
5946 			 * the correctness of srcip/dstip and accordingly post
5947 			 * REJ related to ibt_ari_ip_reason_t of
5948 			 * IBT_ARI_IP_SRC_ADDR, IBT_ARI_IP_DST_ADDR and
5949 			 * IBT_ARI_IP_UNKNOWN_ADDR.
5950 			 */
5951 			if (ip_data->ip_ipv == IBT_CM_IP_IPV_V4) {
5952 				if (ip_data->ip_srcv4 == 0) {
5953 					IBTF_DPRINTF_L2(cmlog,
5954 					    "ibcm_verify_req_gids_and_svcid: "
5955 					    "Invalid NULL V4 SrcIp specified");
5956 					rdma_rej_mad = B_TRUE;
5957 					ari_ip.ip_reason = IBT_ARI_IP_SRC_ADDR;
5958 					ari_ip.ip_suggested = B_TRUE;
5959 					ari_ip.ip_suggested_version =
5960 					    IBT_CM_IP_IPV_V4;
5961 				} else if (ip_data->ip_dstv4 == 0) {
5962 					IBTF_DPRINTF_L2(cmlog,
5963 					    "ibcm_verify_req_gids_and_svcid: "
5964 					    "Invalid NULL V4 DstIp specified");
5965 					rdma_rej_mad = B_TRUE;
5966 					ari_ip.ip_reason = IBT_ARI_IP_DST_ADDR;
5967 					ari_ip.ip_suggested = B_TRUE;
5968 					ari_ip.ip_suggested_version =
5969 					    IBT_CM_IP_IPV_V4;
5970 				}
5971 			} else if (ip_data->ip_ipv == IBT_CM_IP_IPV_V6) {
5972 				if (IN6_IS_ADDR_UNSPECIFIED(
5973 				    &ip_data->ip_srcv6)) {
5974 					IBTF_DPRINTF_L2(cmlog,
5975 					    "ibcm_verify_req_gids_and_svcid: "
5976 					    "Invalid NULL V6 SrcIp specified");
5977 					rdma_rej_mad = B_TRUE;
5978 					ari_ip.ip_reason = IBT_ARI_IP_SRC_ADDR;
5979 					ari_ip.ip_suggested = B_TRUE;
5980 					ari_ip.ip_suggested_version =
5981 					    IBT_CM_IP_IPV_V6;
5982 				} else if (IN6_IS_ADDR_UNSPECIFIED(
5983 				    &ip_data->ip_dstv6)) {
5984 					IBTF_DPRINTF_L2(cmlog,
5985 					    "ibcm_verify_req_gids_and_svcid: "
5986 					    "Invalid NULL V6 DstIp specified");
5987 					rdma_rej_mad = B_TRUE;
5988 					ari_ip.ip_reason = IBT_ARI_IP_DST_ADDR;
5989 					ari_ip.ip_suggested = B_TRUE;
5990 					ari_ip.ip_suggested_version =
5991 					    IBT_CM_IP_IPV_V6;
5992 				}
5993 			}
5994 			/* TBD: IBT_ARI_IP_UNKNOWN_ADDR */
5995 		}
5996 		if (rdma_rej_mad == B_TRUE) {
5997 			ibt_ari_con_t	cons_rej;
5998 
5999 			mutex_exit(&ibcm_svc_info_lock);
6000 
6001 			cons_rej.rej_ari_len = 1 + sizeof (ibt_ari_ip_t);
6002 			cons_rej.rej_ari[0] = 0; /* Rejected by CM Layer */
6003 			bcopy(&ari_ip, &cons_rej.rej_ari[1],
6004 			    sizeof (ibt_ari_ip_t));
6005 			/* Send a REJ with CONSUMER REJ */
6006 			ibcm_post_rej_mad(statep, IBT_CM_CONSUMER,
6007 			    IBT_CM_FAILURE_REQ, &cons_rej,
6008 			    sizeof (ibt_ari_con_t));
6009 			return (IBCM_FAILURE);
6010 		}
6011 	}
6012 
6013 	/* find the best "bind" entry that enables this port */
6014 
6015 	pkey = b2h16(cm_req_msgp->req_part_key);
6016 	svc_bindp = NULL;
6017 	tmp_bindp = svc_infop->svc_bind_list;
6018 	while (tmp_bindp) {
6019 		if (tmp_bindp->sbind_hcaguid == hca_guid &&
6020 		    tmp_bindp->sbind_port == port_num) {
6021 			if (gid.gid_guid ==
6022 			    tmp_bindp->sbind_gid.gid_guid &&
6023 			    gid.gid_prefix ==
6024 			    tmp_bindp->sbind_gid.gid_prefix) {
6025 				/* gid match => really good match */
6026 				svc_bindp = tmp_bindp;
6027 				if (pkey == tmp_bindp->sbind_pkey)
6028 					/* absolute best match */
6029 					break;
6030 			} else if (svc_bindp == NULL) {
6031 				/* port match => a good match */
6032 				svc_bindp = tmp_bindp;
6033 			}
6034 		}
6035 		tmp_bindp = tmp_bindp->sbind_link;
6036 	}
6037 	if (svc_bindp == NULL) { /* port not enabled for this SID */
6038 		mutex_exit(&ibcm_svc_info_lock);
6039 		IBTF_DPRINTF_L2(cmlog,
6040 		    "ibcm_verify_req_gids_and_svcid: statep 0x%p "
6041 		    "no binding found", statep);
6042 		ibcm_post_rej_mad(statep,
6043 		    IBT_CM_INVALID_SID, IBT_CM_FAILURE_REQ, NULL, 0);
6044 		return (IBCM_FAILURE);
6045 	}
6046 	/* copy the GID in case we need it in REJ below */
6047 	gid.gid_prefix = b2h64(svc_bindp->sbind_gid.gid_prefix);
6048 	gid.gid_guid = b2h64(svc_bindp->sbind_gid.gid_guid);
6049 
6050 	statep->state_cm_private = svc_bindp->sbind_cm_private;
6051 	statep->state_svc_infop = svc_infop;
6052 	statep->cm_handler = svc_infop->svc_rc_handler;
6053 	if (reject_reason == IBT_CM_SUCCESS)
6054 		IBCM_SVC_INCR(svc_infop);
6055 	mutex_exit(&ibcm_svc_info_lock);
6056 
6057 	/*
6058 	 * If the service id is valid, but gid in REQ is invalid,
6059 	 * then send a REJ with invalid gid
6060 	 * For Invalid primary gid, the ARI field is filled with
6061 	 * with gid from svcinfo
6062 	 * For invalid prim/alt gid reject, CM uses one of the gids
6063 	 * registered in ARI.
6064 	 * For invalid prim/alt lid reject, CM uses the base lid in ARI
6065 	 */
6066 	if (reject_reason != IBT_CM_SUCCESS) {
6067 
6068 		switch (reject_reason) {
6069 
6070 		case IBT_CM_PRIM_GID :
6071 		case IBT_CM_ALT_GID :
6072 			ibcm_post_rej_mad(statep,
6073 			    reject_reason, IBT_CM_FAILURE_REQ,
6074 			    &gid, sizeof (ib_gid_t));
6075 			break;
6076 
6077 		case IBT_CM_PRIM_LID :
6078 		case IBT_CM_ALT_LID :
6079 
6080 			lid = h2b16(port.hp_base_lid);
6081 			ibcm_post_rej_mad(statep,
6082 			    reject_reason, IBT_CM_FAILURE_REQ,
6083 			    &lid, sizeof (ib_lid_t));
6084 			break;
6085 		}
6086 
6087 		return (IBCM_FAILURE);
6088 	}
6089 
6090 	/* Service, primary/alt gid and lid are all valid */
6091 
6092 	return (IBCM_SUCCESS);
6093 }
6094 
6095 /*
6096  * ibcm_cep_state_req:
6097  *	QP state transition function called for an incoming REQ on passive side
6098  *	LIDs and GIDs should be maintained and validated by the client handler
6099  *
6100  * INPUTS:
6101  *	statep		- state pointer
6102  *	cm_req_msgp	- REQ message pointer
6103  *	reject_reason	- Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
6104  *	arej_info_len	- Additional Rejection reason info length
6105  *
6106  * RETURN VALUE: IBCM_SEND_REP/IBCM_SEND_REJ
6107  */
6108 ibcm_status_t
6109 ibcm_cep_state_req(ibcm_state_data_t *statep, ibcm_req_msg_t *cm_req_msgp,
6110     ibt_cm_reason_t *reject_reason, uint8_t *arej_len)
6111 {
6112 	void			*priv_data = NULL;
6113 	ibt_cm_event_t		event;
6114 	ibt_cm_status_t		cb_status;
6115 	ibcm_status_t		status;
6116 	ibt_cm_return_args_t	ret_args;
6117 	ibcm_clnt_reply_info_t	clnt_info;
6118 
6119 	IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: statep 0x%p", statep);
6120 	/* client handler should be valid */
6121 	ASSERT(statep->cm_handler != NULL);
6122 
6123 	bzero(&event, sizeof (event));
6124 
6125 	/* Fill in ibt_cm_event_t */
6126 	event.cm_type = IBT_CM_EVENT_REQ_RCV;
6127 	event.cm_session_id = statep;
6128 	IBCM_EVT_REQ(event).req_service_id = b2h64(cm_req_msgp->req_svc_id);
6129 	IBCM_EVT_REQ(event).req_transport =
6130 	    ((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] >> 1 & 0x3;
6131 	IBCM_EVT_REQ(event).req_timeout = ibt_ib2usec(
6132 	    (((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] >> 3) & 0x1F);
6133 	IBCM_EVT_REQ(event).req_retry_cnt =
6134 	    ((uint8_t *)&cm_req_msgp->req_starting_psn_plus)[3] & 0x7;
6135 	IBCM_EVT_REQ(event).req_rnr_retry_cnt = cm_req_msgp->req_mtu_plus & 0x7;
6136 	IBCM_EVT_REQ(event).req_pkey = b2h16(cm_req_msgp->req_part_key);
6137 	IBCM_EVT_REQ(event).req_rdma_ra_in =
6138 	    ((uint8_t *)&cm_req_msgp->req_local_qpn_plus)[3];
6139 	IBCM_EVT_REQ(event).req_rdma_ra_out =
6140 	    ((uint8_t *)&cm_req_msgp->req_local_eec_no_plus)[3];
6141 
6142 	/* Account for CM and other software delays */
6143 	if (IBCM_EVT_REQ(event).req_timeout > ibcm_sw_delay) {
6144 		IBCM_EVT_REQ(event).req_timeout -= ibcm_sw_delay;
6145 		IBTF_DPRINTF_L5(cmlog, "ibcm_cep_state_req: statep 0x%p"
6146 		    "Avail resp time %d (usec)", statep,
6147 		    IBCM_EVT_REQ(event).req_timeout);
6148 	} else {
6149 		IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p "
6150 		    "REQ rem_resp_time < local sw delay 0x%x", statep,
6151 		    IBCM_EVT_REQ(event).req_timeout);
6152 
6153 		IBCM_EVT_REQ(event).req_timeout = 0;
6154 	}
6155 
6156 	IBCM_EVT_REQ(event).req_prim_hca_port = statep->prim_port;
6157 	IBCM_EVT_REQ(event).req_alt_hca_port = statep->alt_port;
6158 	IBCM_EVT_REQ(event).req_hca_guid = statep->local_hca_guid;
6159 	IBCM_EVT_REQ(event).req_remote_qpn = statep->remote_qpn;
6160 
6161 	if (((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] &
6162 	    IBT_CM_FLOW_CONTROL)
6163 		IBCM_EVT_REQ(event).req_flags |= IBT_CM_FLOW_CONTROL;
6164 
6165 	if ((cm_req_msgp->req_max_cm_retries_plus >> 3) & 0x1)
6166 		IBCM_EVT_REQ(event).req_flags |= IBT_CM_SRQ_EXISTS;
6167 
6168 	/* Initialize req.req_prim_addr */
6169 	ibcm_set_primary_adds_vect(statep, &IBCM_EVT_REQ(event).req_prim_addr,
6170 	    cm_req_msgp);
6171 
6172 	/* Initialize req.req_alternate_path if they exist */
6173 	if (b2h16(cm_req_msgp->req_alt_l_port_lid) != 0) {
6174 		ibcm_set_alt_adds_vect(statep,
6175 		    &IBCM_EVT_REQ(event).req_alt_addr, cm_req_msgp);
6176 
6177 		/* Verify, alt path is not same as primary */
6178 		if (ibcm_compare_prim_alt_paths(
6179 		    &event.cm_event.req.req_prim_addr,
6180 		    &event.cm_event.req.req_alt_addr) == B_TRUE) {
6181 			/* XXX New REJ code needed */
6182 			*reject_reason = IBT_CM_NO_RESC;
6183 			IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p"
6184 			    " Alt and prim paths are same", statep);
6185 			mutex_enter(&ibcm_svc_info_lock);
6186 			IBCM_SVC_DECR(statep->state_svc_infop);
6187 			mutex_exit(&ibcm_svc_info_lock);
6188 			return (IBCM_SEND_REJ);
6189 		}
6190 	}
6191 
6192 #ifdef	NO_EEC_SUPPORT_YET
6193 	IBCM_EVT_REQ(event).req_rdc_exists = cm_req_msgp->req_mtu_plus >> 3 & 1;
6194 	IBCM_EVT_REQ(event).req_remote_eecn =
6195 	    b2h32(cm_req_msgp->req_remote_eecn_plus) >> 8;
6196 	IBCM_EVT_REQ(event).req_local_eecn =
6197 	    b2h32(cm_req_msgp->req_local_eec_no_plus) >> 8;
6198 	IBCM_EVT_REQ(event).req_remote_qkey =
6199 	    b2h32(cm_req_msgp->req_local_qkey);
6200 #endif
6201 
6202 	/* cm_req_msgp->req_private_data to event.cm_event.cm_priv_data */
6203 	event.cm_priv_data = cm_req_msgp->req_private_data;
6204 
6205 	event.cm_priv_data_len = IBT_REQ_PRIV_DATA_SZ;
6206 
6207 	/*
6208 	 * Allocate priv_data of size IBT_MAX_PRIV_DATA_SZ
6209 	 */
6210 	priv_data = kmem_zalloc(IBT_MAX_PRIV_DATA_SZ, KM_SLEEP);
6211 
6212 	bzero(&ret_args, sizeof (ret_args));
6213 
6214 	/* Fill in the default values from REQ, that client can modify */
6215 	ret_args.cm_ret.rep.cm_rdma_ra_in = IBCM_EVT_REQ(event).req_rdma_ra_out;
6216 	ret_args.cm_ret.rep.cm_rdma_ra_out = IBCM_EVT_REQ(event).req_rdma_ra_in;
6217 	ret_args.cm_ret.rep.cm_rnr_retry_cnt = cm_req_msgp->req_mtu_plus & 0x7;
6218 
6219 	ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REQ_RCVD_EVENT);
6220 
6221 	/* Invoke the client handler */
6222 	cb_status = statep->cm_handler(statep->state_cm_private, &event,
6223 	    &ret_args, priv_data, IBT_REP_PRIV_DATA_SZ);
6224 
6225 	ibcm_insert_trace(statep, IBCM_TRACE_RET_REQ_RCVD_EVENT);
6226 
6227 	mutex_enter(&ibcm_svc_info_lock);
6228 	IBCM_SVC_DECR(statep->state_svc_infop);
6229 	mutex_exit(&ibcm_svc_info_lock);
6230 
6231 	IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: Client handler returned %d"
6232 	    " statep 0x%p", cb_status, statep);
6233 
6234 	if (cb_status == IBT_CM_DEFER) {
6235 
6236 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
6237 
6238 		if (statep->defer_cm_msg == NULL)
6239 			statep->defer_cm_msg =
6240 			    kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
6241 		bcopy(cm_req_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE);
6242 
6243 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
6244 
6245 		/*
6246 		 * unblock any blocked cm proceed api calls. Do not access
6247 		 * statep after cv_signal
6248 		 */
6249 		mutex_enter(&statep->state_mutex);
6250 		statep->clnt_proceed = IBCM_UNBLOCK;
6251 		cv_broadcast(&statep->block_client_cv);
6252 		mutex_exit(&statep->state_mutex);
6253 
6254 		kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6255 		return (IBCM_DEFER);
6256 	}
6257 
6258 	/* fail any blocked cm proceed api call - client bug */
6259 	mutex_enter(&statep->state_mutex);
6260 	statep->clnt_proceed = IBCM_FAIL;
6261 	cv_broadcast(&statep->block_client_cv);
6262 	mutex_exit(&statep->state_mutex);
6263 
6264 	clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
6265 	clnt_info.priv_data = priv_data;
6266 	clnt_info.priv_data_len = ret_args.cm_ret_len;
6267 
6268 	status =
6269 	    ibcm_process_cep_req_cm_hdlr(statep, cb_status,
6270 	    &clnt_info, reject_reason, arej_len, cm_req_msgp);
6271 	kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6272 	return (status);
6273 }
6274 
6275 /*
6276  * ibcm_process_cep_req_cm_hdlr:
6277  *	Processes the response from client handler for an incoming REQ.
6278  */
6279 ibcm_status_t
6280 ibcm_process_cep_req_cm_hdlr(ibcm_state_data_t *statep,
6281     ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
6282     ibt_cm_reason_t *reject_reason, uint8_t *arej_len,
6283     ibcm_req_msg_t *cm_req_msg)
6284 {
6285 	ibt_status_t		status;
6286 	ibt_qp_query_attr_t	qp_attrs;
6287 	ibcm_state_data_t	*old_statep;
6288 	ibt_channel_hdl_t	channel;
6289 	ib_guid_t		local_ca_guid;
6290 	ibcm_rej_msg_t		*rej_msgp;
6291 #ifdef	NO_EEC_SUPPORT_YET
6292 	ibt_eec_query_attr_t	eec_attrs;
6293 #endif
6294 
6295 	if (cb_status == IBT_CM_DEFAULT)
6296 		cb_status = IBT_CM_REJECT;
6297 
6298 	/* verify status */
6299 	if (cb_status == IBT_CM_ACCEPT) {
6300 		*reject_reason = IBT_CM_SUCCESS;
6301 	} else if (cb_status == IBT_CM_REJECT) {
6302 		*reject_reason = IBT_CM_CONSUMER;
6303 	} else if (cb_status == IBT_CM_REDIRECT_PORT) {
6304 		*reject_reason = IBT_CM_PORT_REDIRECT;
6305 	} else if (cb_status == IBT_CM_REDIRECT) {
6306 		*reject_reason = IBT_CM_REDIRECT_CM;
6307 	} else if (cb_status == IBT_CM_NO_CHANNEL) {
6308 		*reject_reason = IBT_CM_NO_CHAN;
6309 	} else if (cb_status == IBT_CM_NO_RESOURCE) {
6310 		*reject_reason = IBT_CM_NO_RESC;
6311 	} else {
6312 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p"
6313 		    " Client handler unexpected return %x", statep, cb_status);
6314 		*reject_reason = IBT_CM_CONSUMER;
6315 	}
6316 
6317 	/* client handler gave CM ok */
6318 	if (cb_status == IBT_CM_ACCEPT) {
6319 		ibcm_rep_msg_t	*rep_msgp = (ibcm_rep_msg_t *)
6320 		    IBCM_OUT_MSGP(statep->stored_msg);
6321 
6322 
6323 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6324 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp))
6325 
6326 		/*
6327 		 * Check first if ret_args make sense. If not, bailout
6328 		 * here rather than going along and panicing later.
6329 		 */
6330 		channel = clnt_info->reply_event->rep.cm_channel;
6331 		if (IBCM_INVALID_CHANNEL(channel)) {
6332 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6333 			    "statep 0x%p server's QP handle is NULL", statep);
6334 			*reject_reason = IBT_CM_NO_CHAN;
6335 		}
6336 
6337 		IBCM_GET_CHAN_PRIVATE(channel, old_statep);
6338 
6339 		if ((*reject_reason == IBT_CM_SUCCESS) &&
6340 		    (old_statep != NULL)) {
6341 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6342 			    "statep 0x%p Channel being re-used on passive side",
6343 			    statep);
6344 			*reject_reason = IBT_CM_NO_CHAN;
6345 		}
6346 		if (old_statep != NULL)
6347 			IBCM_RELEASE_CHAN_PRIVATE(channel);
6348 
6349 		if (*reject_reason != IBT_CM_SUCCESS) {
6350 			ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6351 			    IBT_CM_FAILURE_REQ, *reject_reason, NULL, 0);
6352 			return (IBCM_SEND_REJ);
6353 		}
6354 
6355 		statep->channel = channel;
6356 		status = ibt_query_qp(channel, &qp_attrs);
6357 
6358 		if (status != IBT_SUCCESS) {
6359 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6360 			    "statep %p ibt_query_qp failed %d", statep, status);
6361 			*reject_reason = IBT_CM_NO_RESC;
6362 			ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6363 			    IBT_CM_FAILURE_REQ, IBT_CM_CI_FAILURE, NULL, 0);
6364 			return (IBCM_SEND_REJ);
6365 		}
6366 
6367 		if (qp_attrs.qp_info.qp_trans != IBT_RC_SRV) {
6368 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6369 			    "statep %p qp is not RC channel on server", statep);
6370 			*reject_reason = IBT_CM_INVALID_SRV_TYPE;
6371 			ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6372 			    IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE,
6373 			    NULL, 0);
6374 			return (IBCM_SEND_REJ);
6375 		}
6376 
6377 		if (qp_attrs.qp_info.qp_state != IBT_STATE_INIT) {
6378 			IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6379 			    "qp state != INIT on server");
6380 			*reject_reason = IBT_CM_CHAN_INVALID_STATE;
6381 			ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6382 			    IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE,
6383 			    NULL, 0);
6384 			return (IBCM_SEND_REJ);
6385 		}
6386 
6387 		/* Init to Init, if required */
6388 		if (qp_attrs.qp_info.qp_transport.rc.rc_path.cep_hca_port_num !=
6389 		    statep->prim_port) {
6390 
6391 			ibt_qp_info_t		qp_info;
6392 			ibt_cep_modify_flags_t	cep_flags;
6393 
6394 			IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6395 			    "chan 0x%p chan port %d", channel,
6396 			    qp_attrs.qp_info.qp_transport.rc.rc_path.\
6397 			    cep_hca_port_num);
6398 
6399 			IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6400 			    "chan 0x%p d path port %d", channel,
6401 			    statep->prim_port);
6402 
6403 			bzero(&qp_info, sizeof (qp_info));
6404 			qp_info.qp_trans = IBT_RC_SRV;
6405 			qp_info.qp_state = IBT_STATE_INIT;
6406 			qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
6407 			    statep->prim_port;
6408 
6409 			cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT;
6410 
6411 			status = ibt_modify_qp(statep->channel, cep_flags,
6412 			    &qp_info, NULL);
6413 
6414 			if (status != IBT_SUCCESS) {
6415 				IBTF_DPRINTF_L2(cmlog,
6416 				    "ibcm_process_cep_req_cm_hdlr: "
6417 				    "chan 0x%p ibt_modify_qp() = %d", channel,
6418 				    status);
6419 				*reject_reason = IBT_CM_NO_RESC;
6420 
6421 				ibcm_insert_trace(statep,
6422 				    IBCM_TRACE_INIT_INIT_FAIL);
6423 
6424 				ibcm_handler_conn_fail(statep,
6425 				    IBT_CM_FAILURE_REJ_SENT, IBT_CM_FAILURE_REQ,
6426 				    IBT_CM_CI_FAILURE, NULL, 0);
6427 				return (IBCM_SEND_REJ);
6428 			} else {
6429 				ibcm_insert_trace(statep,
6430 				    IBCM_TRACE_INIT_INIT);
6431 
6432 				IBTF_DPRINTF_L5(cmlog,
6433 				    "ibcm_process_cep_req_cm_hdlr: "
6434 				    "chan 0x%p ibt_modify_qp() = %d", channel,
6435 				    status);
6436 			}
6437 		}
6438 
6439 		/* fill in the REP msg based on ret_args from client */
6440 		rep_msgp->rep_resp_resources =
6441 		    clnt_info->reply_event->rep.cm_rdma_ra_in;
6442 		rep_msgp->rep_initiator_depth =
6443 		    clnt_info->reply_event->rep.cm_rdma_ra_out;
6444 
6445 		/* IBT_CM_FLOW_CONTROL is always set by default. */
6446 		rep_msgp->rep_target_delay_plus |= IBT_CM_FLOW_CONTROL;
6447 
6448 		rep_msgp->rep_rnr_retry_cnt_plus =
6449 		    (clnt_info->reply_event->rep.cm_rnr_retry_cnt & 0x7) << 5;
6450 
6451 		/*
6452 		 * Check out whether SRQ is associated with this channel.
6453 		 * If yes, then set the appropriate bit.
6454 		 */
6455 		if (qp_attrs.qp_srq != NULL) {
6456 			rep_msgp->rep_rnr_retry_cnt_plus |= (1 << 4);
6457 		}
6458 
6459 		local_ca_guid = h2b64(statep->local_hca_guid);
6460 		bcopy(&local_ca_guid, rep_msgp->rep_local_ca_guid,
6461 		    sizeof (ib_guid_t));
6462 
6463 		/* Transition QP from Init to RTR state */
6464 		if (ibcm_invoke_qp_modify(statep, cm_req_msg, rep_msgp) !=
6465 		    IBT_SUCCESS) {
6466 
6467 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr "
6468 			    "statep 0x%p ibcm_invoke_qp_modify failed because "
6469 			    "of invalid data", statep);
6470 			*reject_reason = IBT_CM_NO_RESC;
6471 			ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6472 			    IBT_CM_FAILURE_REQ, IBT_CM_CI_FAILURE, NULL, 0);
6473 			return (IBCM_SEND_REJ);
6474 		}
6475 
6476 		/*
6477 		 * Link statep and channel, once CM determines it is
6478 		 * post REP definitely.
6479 		 */
6480 		IBCM_SET_CHAN_PRIVATE(statep->channel, statep);
6481 
6482 		/*
6483 		 * Fill up the REP fields from ret_args
6484 		 * failover status,  from ret_args
6485 		 *
6486 		 * Fill up local QPN and EECN from ret_args->channel
6487 		 */
6488 
6489 		/* fill in REP msg bytes Qkey, Starting PSN, 12-15, and 16-19 */
6490 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6491 		    "qp_info.qp_state = %x", qp_attrs.qp_info.qp_state);
6492 
6493 		rep_msgp->rep_local_qpn_plus = h2b32(qp_attrs.qp_qpn << 8);
6494 
6495 		statep->local_qpn = qp_attrs.qp_qpn;
6496 
6497 		switch (qp_attrs.qp_info.qp_trans) {
6498 		case IBT_RD_SRV:
6499 			rep_msgp->rep_local_qkey = h2b32(
6500 			    qp_attrs.qp_info.qp_transport.rd.rd_qkey);
6501 			break;
6502 		case IBT_RC_SRV:
6503 			rep_msgp->rep_starting_psn_plus =
6504 			    h2b32(IBCM_QP_RC(qp_attrs).rc_sq_psn << 8);
6505 			break;
6506 		case IBT_UC_SRV:
6507 			rep_msgp->rep_starting_psn_plus =
6508 			    h2b32(IBCM_QP_UC(qp_attrs).uc_sq_psn << 8);
6509 			break;
6510 		}
6511 
6512 #ifdef	NO_EEC_SUPPORT_YET
6513 		if (ret_args.cm_channel.ch_eec != NULL) {
6514 			status = ibt_query_eec(ret_args.cm_channel.ch_eec,
6515 			    &eec_attrs);
6516 			if (status == IBT_SUCCESS) {
6517 				rep_msgp->rep_local_eecn_plus =
6518 				    h2b32(((uint32_t)eec_attrs.eec_eecn << 8));
6519 			}
6520 		}
6521 #endif
6522 
6523 		/* figure out Target ACK delay */
6524 		rep_msgp->rep_target_delay_plus |= (status == IBT_SUCCESS) ?
6525 		    statep->hcap->hca_ack_delay << 3 : 0;
6526 
6527 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr:statep %p "
6528 		    "REP priv len %x", statep, clnt_info->priv_data_len);
6529 		/* Copy PrivateData from priv_data */
6530 		if (clnt_info->priv_data_len != 0) {
6531 			bcopy(clnt_info->priv_data, rep_msgp->rep_private_data,
6532 			    min(IBT_REP_PRIV_DATA_SZ,
6533 			    clnt_info->priv_data_len));
6534 		}
6535 
6536 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
6537 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp))
6538 
6539 		return (IBCM_SEND_REP);
6540 	}
6541 
6542 	/* REJ message */
6543 	rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6544 
6545 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p REJ "
6546 	    "priv len %x", statep, clnt_info->priv_data_len);
6547 
6548 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp))
6549 
6550 	/* if priv_data_len != 0 use priv_data to copy back to rej_priv_data */
6551 	if (clnt_info->priv_data_len != 0) {
6552 		bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6553 		    min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6554 	}
6555 
6556 	if (cb_status == IBT_CM_REDIRECT_PORT) {
6557 		ib_gid_t tgid;
6558 
6559 		tgid.gid_guid =
6560 		    h2b64(clnt_info->reply_event->rej.ari_gid.gid_guid);
6561 		tgid.gid_prefix =
6562 		    h2b64(clnt_info->reply_event->rej.ari_gid.gid_prefix);
6563 
6564 		*arej_len = sizeof (ib_gid_t);
6565 		bcopy(&tgid, &rej_msgp->rej_addl_rej_info, sizeof (ib_gid_t));
6566 
6567 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: ari_gid= "
6568 		    "%llX:%llX", tgid.gid_prefix, tgid.gid_guid);
6569 
6570 	} else if (cb_status == IBT_CM_REDIRECT) {
6571 		ibcm_classportinfo_msg_t	tclp;
6572 
6573 		ibcm_init_clp_to_mad(&tclp,
6574 		    &clnt_info->reply_event->rej.ari_redirect);
6575 		bcopy(&tclp, rej_msgp->rej_addl_rej_info, sizeof (tclp));
6576 
6577 		*arej_len = sizeof (ibcm_classportinfo_msg_t);
6578 
6579 	} else if (cb_status == IBT_CM_REJECT) {
6580 
6581 		/* Fill up the REJ fields, from ret_args */
6582 		*arej_len = min(
6583 		    clnt_info->reply_event->rej.ari_consumer.rej_ari_len,
6584 		    IBT_CM_ADDL_REJ_LEN);
6585 		bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari,
6586 		    &rej_msgp->rej_addl_rej_info, *arej_len);
6587 
6588 		/*
6589 		 * RDMA IP REQ was passed up to the ULP, the ULP decided to do
6590 		 * a "normal" consumer REJ, by the returning IBT_CM_REJECT in
6591 		 * the cm handler.
6592 		 * CM has to do some extra stuff too, it has to
6593 		 * a) return REJ code 28 (consumer) and b) put 0x1 in the first
6594 		 * byte of the ARI data, to indicate that this is a RDMA aware
6595 		 * ULP that is doing a consumer reject.  The ULP should have
6596 		 * put its consumer specific data into ibt_arej_info_t(9s) at
6597 		 * byte 1 of the rej_ari[] array.
6598 		 */
6599 		if (((statep->svcid & IB_SID_IPADDR_PREFIX_MASK) == 0) &&
6600 		    (statep->svcid & IB_SID_IPADDR_PREFIX)) {
6601 			rej_msgp->rej_addl_rej_info[0] = 1;
6602 		}
6603 	}
6604 
6605 	rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
6606 
6607 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp))
6608 
6609 	return (IBCM_SEND_REJ);
6610 }
6611 
6612 /*
6613  * ibcm_cep_state_rep:
6614  *	QP state transition function called for an incoming REP on active side
6615  *
6616  * INPUTS:
6617  *	statep		- state pointer
6618  *	cm_rep_msg	- REP message pointer
6619  *	reject_reason	- Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
6620  *
6621  * RETURN VALUE:
6622  */
6623 ibcm_status_t
6624 ibcm_cep_state_rep(ibcm_state_data_t *statep, ibcm_rep_msg_t *cm_rep_msgp,
6625     ibt_cm_reason_t *reject_reason, uint8_t *arej_len)
6626 {
6627 	void			*priv_data = NULL;
6628 	ibcm_status_t		rval = IBCM_SEND_RTU;
6629 	ibt_cm_event_t		event;
6630 	ibt_cm_status_t		cb_status = IBT_CM_ACCEPT;
6631 	ibt_cm_return_args_t	ret_args;
6632 	ibcm_clnt_reply_info_t	clnt_info;
6633 
6634 	IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rep: statep 0x%p", statep);
6635 
6636 	/* Check first if client handler is valid */
6637 	if (statep->cm_handler != NULL) {
6638 		/* initialize fields in ibt_cm_event_t */
6639 		bzero(&event, sizeof (event));
6640 		event.cm_type = IBT_CM_EVENT_REP_RCV;
6641 		event.cm_channel = statep->channel;
6642 		event.cm_session_id = statep;
6643 
6644 		IBCM_EVT_REP(event).rep_rdma_ra_in =
6645 		    cm_rep_msgp->rep_resp_resources;
6646 		IBCM_EVT_REP(event).rep_rdma_ra_out =
6647 		    cm_rep_msgp->rep_initiator_depth;
6648 		IBCM_EVT_REP(event).rep_service_time = ibt_ib2usec(
6649 		    ((uint8_t *)&(((ibcm_req_msg_t *)IBCM_OUT_MSGP(
6650 		    statep->stored_msg))->req_starting_psn_plus))[3] >> 3);
6651 
6652 		IBCM_EVT_REP(event).rep_service_time -=
6653 		    2 * statep->pkt_life_time - ibcm_sw_delay;
6654 
6655 		IBCM_EVT_REP(event).rep_failover_status =
6656 		    cm_rep_msgp->rep_target_delay_plus >> 1 & 3;
6657 
6658 		if (cm_rep_msgp->rep_target_delay_plus & 0x1)
6659 			IBCM_EVT_REP(event).rep_flags |= IBT_CM_FLOW_CONTROL;
6660 
6661 		if ((cm_rep_msgp->rep_rnr_retry_cnt_plus >> 4) & 0x1)
6662 			IBCM_EVT_REP(event).rep_flags |= IBT_CM_SRQ_EXISTS;
6663 
6664 		IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rep: statep 0x%p "
6665 		    "rep_service_time %d", statep,
6666 		    IBCM_EVT_REP(event).rep_service_time);
6667 
6668 		event.cm_priv_data = &(cm_rep_msgp->rep_private_data[0]);
6669 		event.cm_priv_data_len = IBT_REP_PRIV_DATA_SZ;
6670 
6671 		/*
6672 		 * Allocate priv_data of size IBT_MAX_PRIV_DATA_SZ
6673 		 */
6674 		priv_data = kmem_zalloc(IBT_MAX_PRIV_DATA_SZ, KM_SLEEP);
6675 		bzero(&ret_args, sizeof (ret_args));
6676 
6677 
6678 		ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REP_RCVD_EVENT);
6679 
6680 		/* invoke the CM handler */
6681 		cb_status = statep->cm_handler(statep->state_cm_private, &event,
6682 		    &ret_args, priv_data, IBT_RTU_PRIV_DATA_SZ);
6683 
6684 		ibcm_insert_trace(statep, IBCM_TRACE_RET_REP_RCVD_EVENT);
6685 
6686 		IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rep: statep 0x%p "
6687 		    "Client handler returned %x", statep, cb_status);
6688 
6689 		if (cb_status == IBT_CM_DEFER) {
6690 			if (statep->defer_cm_msg == NULL)
6691 				statep->defer_cm_msg =
6692 				    kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
6693 			bcopy(cm_rep_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE);
6694 
6695 			/* unblock any blocked cm proceed api calls */
6696 			mutex_enter(&statep->state_mutex);
6697 			statep->clnt_proceed = IBCM_UNBLOCK;
6698 			cv_broadcast(&statep->block_client_cv);
6699 			mutex_exit(&statep->state_mutex);
6700 
6701 			kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6702 			return (IBCM_DEFER);
6703 		}
6704 	}
6705 
6706 	/* fail any blocked cm proceed api calls - client bug */
6707 	mutex_enter(&statep->state_mutex);
6708 	statep->clnt_proceed = IBCM_FAIL;
6709 	cv_broadcast(&statep->block_client_cv);
6710 	mutex_exit(&statep->state_mutex);
6711 
6712 	clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
6713 	clnt_info.priv_data = priv_data;
6714 	clnt_info.priv_data_len = ret_args.cm_ret_len;
6715 
6716 	rval =
6717 	    ibcm_process_cep_rep_cm_hdlr(statep, cb_status, &clnt_info,
6718 	    reject_reason, arej_len, cm_rep_msgp);
6719 
6720 	if (priv_data != NULL)
6721 		kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6722 	return (rval);
6723 }
6724 
6725 
6726 /*
6727  * ibcm_process_cep_rep_cm_hdlr:
6728  *	Processes the response from client handler for an incoming REP.
6729  */
6730 ibcm_status_t
6731 ibcm_process_cep_rep_cm_hdlr(ibcm_state_data_t *statep,
6732     ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
6733     ibt_cm_reason_t *reject_reason, uint8_t *arej_len,
6734     ibcm_rep_msg_t *cm_rep_msgp)
6735 {
6736 	ibcm_status_t		rval = IBCM_SEND_RTU;
6737 	ibcm_rej_msg_t		*rej_msgp;
6738 
6739 	if (cb_status == IBT_CM_DEFAULT)
6740 		cb_status = IBT_CM_ACCEPT;
6741 
6742 	if (cb_status == IBT_CM_REJECT) {
6743 		*reject_reason = IBT_CM_CONSUMER;
6744 	} else if (cb_status == IBT_CM_REDIRECT_PORT) {
6745 		*reject_reason = IBT_CM_PORT_REDIRECT;
6746 	} else if (cb_status == IBT_CM_REDIRECT) {
6747 		*reject_reason = IBT_CM_REDIRECT_CM;
6748 	} else if (cb_status == IBT_CM_NO_RESOURCE) {
6749 		*reject_reason = IBT_CM_NO_RESC;
6750 	} else if (cb_status != IBT_CM_ACCEPT) {
6751 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep "
6752 		    "0x%p, Client handler returned unexpected value %d",
6753 		    statep, cb_status);
6754 		*reject_reason = IBT_CM_CONSUMER;
6755 	} else
6756 		*reject_reason = IBT_CM_SUCCESS;
6757 
6758 
6759 	/* We come here if status is ACCEPT or CM handler is NULL */
6760 	if (cb_status == IBT_CM_ACCEPT) {
6761 		ib_time_t	time;
6762 
6763 		time = ibt_usec2ib(statep->pkt_life_time * 2 +
6764 		    ibt_ib2usec(cm_rep_msgp->rep_target_delay_plus >> 3));
6765 
6766 		IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6767 		    " active cep_timeout(usec) 0x%x ", statep, time);
6768 
6769 		IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6770 		    " passive hca_ack_delay(ib_time) = 0x%x, ", statep,
6771 		    cm_rep_msgp->rep_target_delay_plus >> 3);
6772 
6773 		IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6774 		    " rnr_retry_cnt = 0x%x", statep,
6775 		    cm_rep_msgp->rep_rnr_retry_cnt_plus >> 5);
6776 
6777 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6778 		statep->starting_psn =
6779 		    b2h32(cm_rep_msgp->rep_starting_psn_plus) >> 8;
6780 
6781 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6782 
6783 		/* Call IBTL CM's qp modify function from Init to RTR */
6784 		if (ibcm_invoke_qp_modify(statep,
6785 		    (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg),
6786 		    cm_rep_msgp) != IBT_SUCCESS) {
6787 
6788 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6789 			    "statep %p, ibcm_invoke_qp_modify to RTR failed",
6790 			    statep);
6791 			*reject_reason = IBT_CM_NO_RESC;
6792 		/*
6793 		 * Call modify qp function from RTR to RTS
6794 		 * RDMA initiator depth on active is same as negotiated
6795 		 * passive REP's responder resources
6796 		 */
6797 		} else if (ibcm_invoke_rtu_qp_modify(statep, time, cm_rep_msgp)
6798 		    != IBT_SUCCESS) {
6799 
6800 			IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6801 			    "statep %p ibcm_invoke_rtu_qp_modify to RTS failed",
6802 			    statep);
6803 			(void) ibcm_cep_to_error_state(statep);
6804 			*reject_reason = IBT_CM_NO_RESC;
6805 		}
6806 
6807 		if (*reject_reason == IBT_CM_NO_RESC) {
6808 
6809 			/* Disassociate statep and QP */
6810 			IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6811 
6812 			ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6813 			    IBT_CM_FAILURE_REP, IBT_CM_CI_FAILURE, NULL, 0);
6814 			return (IBCM_SEND_REJ);	/* send REJ */
6815 		}
6816 
6817 		if (clnt_info->priv_data_len != 0) {
6818 			ibcm_rtu_msg_t *rtu_msgp;
6819 			rtu_msgp = (ibcm_rtu_msg_t *)
6820 			    IBCM_OUT_MSGP(statep->stored_msg);
6821 			bcopy(clnt_info->priv_data, rtu_msgp->rtu_private_data,
6822 			    min(IBT_RTU_PRIV_DATA_SZ,
6823 			    clnt_info->priv_data_len));
6824 		}
6825 
6826 		*reject_reason = IBT_CM_SUCCESS;
6827 		return (rval);
6828 	}
6829 
6830 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp))
6831 
6832 	/* Fill up the REJ fields, from ret_args */
6833 	rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6834 	rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REP << 6;
6835 
6836 	/* if priv_len != 0 use priv_data to copy back to rej_priv_data */
6837 	if (clnt_info->priv_data_len != 0)
6838 		bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6839 		    min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6840 
6841 	if (clnt_info->reply_event != NULL)
6842 		*arej_len =
6843 		    min(clnt_info->reply_event->rej.ari_consumer.rej_ari_len,
6844 		    IBT_CM_ADDL_REJ_LEN);
6845 
6846 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej))
6847 
6848 	if (*arej_len != 0)	/* asserts that clnt_info->reply_event != 0 */
6849 		bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari,
6850 		    &rej_msgp->rej_addl_rej_info, *arej_len);
6851 
6852 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej))
6853 
6854 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp))
6855 
6856 	rval = IBCM_SEND_REJ;
6857 
6858 	/* Disassociate statep and QP */
6859 	IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6860 
6861 	/* callback client, to enable client to do resource cleanup */
6862 	ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6863 	    IBT_CM_FAILURE_REP, *reject_reason, NULL, 0);
6864 
6865 	return (rval);
6866 }
6867 
6868 /*
6869  * ibcm_invoke_rtu_qp_modify:
6870  *	Helper function to modify QP for RTU only called from
6871  *	ibcm_cep_state_rtu() and ibcm_cep_send_rtu()
6872  *
6873  * INPUTS:
6874  *	statep		- connection state pointer
6875  *
6876  * RETURN VALUE:
6877  */
6878 static ibt_status_t
6879 ibcm_invoke_rtu_qp_modify(ibcm_state_data_t *statep, ib_time_t timeout,
6880     ibcm_rep_msg_t *rep_msg)
6881 {
6882 	ibt_status_t		status;
6883 	ibt_qp_info_t		qp_info;
6884 	ibt_cep_modify_flags_t	cep_flags = IBT_CEP_SET_RTR_RTS;
6885 
6886 	/* Start filling up ibt_qp_info_t.  */
6887 	bzero(&qp_info, sizeof (qp_info));
6888 	qp_info.qp_trans = ibtl_cm_get_chan_type(statep->channel);
6889 	qp_info.qp_current_state = IBT_STATE_RTR;
6890 
6891 	switch (qp_info.qp_trans) {
6892 	case IBT_RC_SRV:
6893 		IBCM_QPINFO_RC_PATH(qp_info).cep_timeout = timeout;
6894 		IBCM_QPINFO_RC(qp_info).rc_retry_cnt = statep->cep_retry_cnt;
6895 		IBCM_QPINFO_RC(qp_info).rc_rnr_retry_cnt =
6896 		    rep_msg->rep_rnr_retry_cnt_plus >> 5;
6897 		IBCM_QPINFO_RC(qp_info).rc_sq_psn = statep->starting_psn;
6898 
6899 		if (statep->mode == IBCM_ACTIVE_MODE) {
6900 			IBCM_QPINFO_RC(qp_info).rc_rdma_ra_out =
6901 			    rep_msg->rep_resp_resources;
6902 		} else {
6903 			IBCM_QPINFO_RC(qp_info).rc_rdma_ra_out =
6904 			    rep_msg->rep_initiator_depth;
6905 		}
6906 		if (statep->alt_port &&
6907 		    (((rep_msg->rep_target_delay_plus >> 1) & 0x3) ==
6908 		    IBT_CM_FAILOVER_ACCEPT)) {
6909 			/* failover was accepted */
6910 			cep_flags |= IBT_CEP_SET_MIG;
6911 			IBCM_QPINFO_RC(qp_info).rc_mig_state =
6912 			    IBT_STATE_REARMED;
6913 		}
6914 
6915 		break;
6916 	/* XXX RD? */
6917 	case IBT_UC_SRV:
6918 		IBCM_QPINFO_UC_PATH(qp_info).cep_timeout = timeout;
6919 		break;
6920 	default:
6921 		IBTF_DPRINTF_L2(cmlog, "ibcm_invoke_rtu_qp_modify: "
6922 		    "unknow svc_type = %x", qp_info.qp_trans);
6923 		break;
6924 	}
6925 
6926 	/* Call modify_qp */
6927 	status = ibt_modify_qp(statep->channel, cep_flags, &qp_info, NULL);
6928 	IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_rtu_qp_modify: statep 0x%p "
6929 	    "modify qp status = %d", statep, status);
6930 
6931 	if (status == IBT_SUCCESS)
6932 		ibcm_insert_trace(statep, IBCM_TRACE_RTR_RTS);
6933 	else
6934 		ibcm_insert_trace(statep, IBCM_TRACE_RTR_RTS_FAIL);
6935 
6936 #ifdef	DEBUG
6937 	print_modify_qp("RTR to RTS", statep->channel, cep_flags, &qp_info);
6938 
6939 	if (statep->channel != NULL) {
6940 		ibt_qp_query_attr_t	qp_attrs;
6941 
6942 		(void) ibt_query_qp(statep->channel, &qp_attrs);
6943 		IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_rtu_qp_modify: "
6944 		    "qp_info.qp_state = %x", qp_attrs.qp_info.qp_state);
6945 	}
6946 #endif
6947 	return (status);
6948 }
6949 
6950 
6951 /*
6952  * ibcm_cep_state_rtu:
6953  *	QP state transition function called for an incoming RTU
6954  *	on passive side.
6955  *
6956  * INPUTS:
6957  *	statep		- connection state pointer
6958  *	cm_rtu_msg	- RTU message pointer
6959  *
6960  */
6961 void
6962 ibcm_cep_state_rtu(ibcm_state_data_t *statep, ibcm_rtu_msg_t *cm_rtu_msgp)
6963 {
6964 	ibt_status_t	status;
6965 	ibt_cm_event_t	event;
6966 	ibcm_rep_msg_t	*rep_msgp = (ibcm_rep_msg_t *)
6967 	    IBCM_OUT_MSGP(statep->stored_msg);
6968 
6969 	IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rtu: statep 0x%p", statep);
6970 
6971 	ASSERT(statep->channel != NULL);
6972 
6973 	/* RDMA initiator depth taken from negotiated REP values */
6974 	status = ibcm_invoke_rtu_qp_modify(statep,
6975 	    ibt_usec2ib(statep->remote_ack_delay), rep_msgp);
6976 
6977 	if (status != IBT_SUCCESS) {
6978 
6979 		(void) ibcm_cep_to_error_state(statep);
6980 		/*
6981 		 * Disassociate statep and QP, as there is a
6982 		 * QP associated with this statep.
6983 		 */
6984 		IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6985 
6986 		ibcm_post_rej_mad(statep, IBT_CM_NO_RESC,
6987 		    IBT_CM_FAILURE_UNKNOWN, NULL, 0);
6988 		/*
6989 		 * Invoke CM handler, so client/server can do
6990 		 * resource cleanup. No private data can be returned here
6991 		 */
6992 		ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6993 		    IBT_CM_FAILURE_UNKNOWN, IBT_CM_NO_RESC, NULL, 0);
6994 
6995 		/* unblock any pending DREQ threads */
6996 		mutex_enter(&statep->state_mutex);
6997 		statep->cep_in_rts = IBCM_FAIL;
6998 		cv_broadcast(&statep->block_mad_cv);
6999 		mutex_exit(&statep->state_mutex);
7000 		return;
7001 	}
7002 
7003 	mutex_enter(&statep->state_mutex);
7004 	statep->state = IBCM_STATE_ESTABLISHED;
7005 	ibtl_cm_chan_is_open(statep->channel);
7006 	mutex_exit(&statep->state_mutex);
7007 
7008 	/* invoke the CM handler */
7009 	ASSERT(statep->cm_handler != NULL);
7010 
7011 	bzero(&event, sizeof (event));
7012 	event.cm_channel = statep->channel;
7013 	event.cm_session_id = NULL;
7014 
7015 	event.cm_type = IBT_CM_EVENT_CONN_EST;
7016 	if (cm_rtu_msgp != NULL) {
7017 		event.cm_priv_data = &(cm_rtu_msgp->rtu_private_data[0]);
7018 		event.cm_priv_data_len = IBT_RTU_PRIV_DATA_SZ;
7019 	}
7020 
7021 	ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_EST_EVENT);
7022 
7023 	(void) statep->cm_handler(statep->state_cm_private, &event, NULL,
7024 	    NULL, 0);
7025 
7026 	ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_EST_EVENT);
7027 	if (ibcm_enable_trace & 4)
7028 		ibcm_dump_conn_trace(statep);
7029 	else
7030 		IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_rtu CONN_EST Channel %p",
7031 		    statep->channel);
7032 
7033 	/* unblock any pending DREQ threads */
7034 	mutex_enter(&statep->state_mutex);
7035 	statep->cep_in_rts = IBCM_UNBLOCK;
7036 	cv_broadcast(&statep->block_mad_cv);
7037 	mutex_exit(&statep->state_mutex);
7038 }
7039 
7040 
7041 /*
7042  * ibcm_cep_send_rtu:
7043  *	QP state transition function called for an outgoing RTU
7044  *	on active side.
7045  *
7046  * INPUTS:
7047  *	statep		- connection state pointer
7048  *
7049  * RETURN VALUE:
7050  */
7051 void
7052 ibcm_cep_send_rtu(ibcm_state_data_t *statep)
7053 {
7054 	/* invoke the CM handler */
7055 	if (statep->cm_handler) {
7056 		ibt_cm_event_t	event;
7057 
7058 		bzero(&event, sizeof (event));
7059 		event.cm_type  = IBT_CM_EVENT_CONN_EST;
7060 		event.cm_channel = statep->channel;
7061 		event.cm_session_id = NULL;
7062 		event.cm_priv_data = NULL;
7063 		event.cm_priv_data_len = 0;
7064 
7065 		ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_EST_EVENT);
7066 
7067 		(void) statep->cm_handler(statep->state_cm_private, &event,
7068 		    NULL, NULL, 0);
7069 
7070 		ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_EST_EVENT);
7071 
7072 	} else {
7073 		IBTF_DPRINTF_L2(cmlog, "ibcm_cep_send_rtu: cm_handler NULL");
7074 	}
7075 	if (ibcm_enable_trace & 4)
7076 		ibcm_dump_conn_trace(statep);
7077 	else
7078 		IBTF_DPRINTF_L2(cmlog, "ibcm_cep_send_rtu CONN_EST Channel %p",
7079 		    statep->channel);
7080 
7081 	/* unblock any pending DREQ threads */
7082 	mutex_enter(&statep->state_mutex);
7083 	statep->cep_in_rts = IBCM_UNBLOCK;
7084 	cv_broadcast(&statep->block_mad_cv);
7085 	mutex_exit(&statep->state_mutex);
7086 }
7087 
7088 
7089 /*
7090  * ibcm_cep_to_error_state:
7091  *	CEP state transition function. Changes state to IBT_STATE_ERROR
7092  *
7093  * INPUTS:
7094  *	statep		- connection state pointer
7095  *
7096  * RETURN VALUE:
7097  *	IBT_SUCCESS	- if able to change state otherwise failure
7098  */
7099 ibt_status_t
7100 ibcm_cep_to_error_state(ibcm_state_data_t *statep)
7101 {
7102 	ibt_status_t		status = IBT_SUCCESS;
7103 
7104 	if (statep->channel != NULL) {
7105 		ibt_qp_info_t	qp_info;
7106 
7107 		bzero(&qp_info, sizeof (qp_info));
7108 		/* For now, set it to RC type */
7109 		qp_info.qp_trans = IBT_RC_SRV;
7110 		qp_info.qp_state = IBT_STATE_ERROR;
7111 
7112 		/* Call modify_qp to move to ERROR state */
7113 		status = ibt_modify_qp(statep->channel, IBT_CEP_SET_STATE,
7114 		    &qp_info, NULL);
7115 
7116 		IBTF_DPRINTF_L4(cmlog, "ibcm_cep_to_error_state: "
7117 		    "statep %p ibt_modify_qp() = %d", statep, status);
7118 
7119 		if (status == IBT_SUCCESS)
7120 			ibcm_insert_trace(statep, IBCM_TRACE_ERROR);
7121 		else
7122 			ibcm_insert_trace(statep, IBCM_TRACE_ERROR_FAIL);
7123 
7124 	}
7125 
7126 #ifdef	NO_EEC_SUPPORT_YET
7127 	if (statep->channel.ch_eec != NULL) {
7128 		ibt_eec_info_t	eec_info;
7129 
7130 		bzero(&eec_info, sizeof (ibt_eec_info_t));
7131 		eec_info.eec_state = what;
7132 
7133 		/* Call modify_eec */
7134 		status = ibtl_cm_modify_eec(statep->channel.ch_eec, &eec_info,
7135 		    IBT_CEP_SET_NOTHING);
7136 		IBTF_DPRINTF_L4(cmlog, "ibcm_cep_to_error_state: "
7137 		    "ibtl_cm_modify_eec() returned = %x", status);
7138 	}
7139 #endif
7140 
7141 	return (status);
7142 }
7143 
7144 
7145 /*
7146  * ibcm_cep_state_rej:
7147  *	QP state transition function called for an incoming REJ
7148  *	on active/passive side
7149  *
7150  * INPUTS:
7151  *	statep		- connection state pointer
7152  *	rej_msgp	- REJ message pointer
7153  *	rej_state	- State where REJ processing began
7154  *
7155  * RETURN VALUE:
7156  */
7157 void
7158 ibcm_cep_state_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp,
7159     ibcm_conn_state_t rej_state)
7160 {
7161 	ibt_cm_event_t	event;
7162 	ibt_status_t	status;
7163 
7164 	IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej: statep 0x%p", statep);
7165 
7166 	ibcm_path_cache_purge();
7167 
7168 	if ((rej_state == IBCM_STATE_REP_SENT) ||
7169 	    (rej_state == IBCM_STATE_MRA_REP_RCVD)) {
7170 		status = ibcm_cep_to_error_state(statep);
7171 		IBTF_DPRINTF_L5(cmlog, "ibcm_cep_state_rej: statep 0x%p "
7172 		    "ibcm_cep_to_error_state returned %d", statep,
7173 		    status);
7174 	}
7175 
7176 	/* Disassociate state structure and CM */
7177 	IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
7178 
7179 	/* invoke the CM handler */
7180 	bzero(&event, sizeof (event));
7181 	if (statep->cm_handler) {
7182 		event.cm_type = IBT_CM_EVENT_FAILURE;
7183 		event.cm_channel = statep->channel;
7184 		event.cm_session_id = NULL;
7185 
7186 		/*
7187 		 * copy rej_msgp->rej_private_data to
7188 		 * event.cm_event.cm_priv_data
7189 		 */
7190 		event.cm_priv_data = &(rej_msgp->rej_private_data[0]);
7191 		event.cm_priv_data_len = IBT_REJ_PRIV_DATA_SZ;
7192 
7193 		event.cm_event.failed.cf_code = IBT_CM_FAILURE_REJ_RCV;
7194 		event.cm_event.failed.cf_msg = rej_msgp->rej_msg_type_plus >> 6;
7195 		event.cm_event.failed.cf_reason =
7196 		    b2h16(rej_msgp->rej_rejection_reason);
7197 
7198 		IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rej: rej_reason = %d",
7199 		    event.cm_event.failed.cf_reason);
7200 
7201 		ibcm_copy_addl_rej(statep, rej_msgp, &event.cm_event.failed);
7202 
7203 		(void) statep->cm_handler(statep->state_cm_private, &event,
7204 		    NULL, NULL, 0);
7205 	}
7206 
7207 	if (statep->open_return_data != NULL)
7208 		bcopy(&event.cm_event.failed.cf_additional,
7209 		    &statep->open_return_data->rc_arej_info,
7210 		    sizeof (ibt_arej_info_t));
7211 	if (ibcm_enable_trace != 0)
7212 		ibcm_dump_conn_trace(statep);
7213 	mutex_enter(&statep->state_mutex);
7214 	ibcm_open_done(statep);
7215 	mutex_exit(&statep->state_mutex);
7216 }
7217 
7218 /* Used to initialize client args with addl rej information from REJ MAD */
7219 static void
7220 ibcm_copy_addl_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp,
7221     ibt_cm_conn_failed_t *failed)
7222 {
7223 	uint16_t 	rej_reason = b2h16(rej_msgp->rej_rejection_reason);
7224 	int		ari_len = rej_msgp->rej_reject_info_len_plus >> 1;
7225 	ibcm_classportinfo_msg_t tclp;
7226 	ibt_arej_info_t	*cf_addl = &failed->cf_additional;
7227 
7228 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cf_addl))
7229 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid))
7230 
7231 	failed->cf_arej_info_valid = B_FALSE;
7232 
7233 	IBTF_DPRINTF_L3(cmlog, "ibcm_copy_addl_rej: rej_reason = %d "
7234 	    "ari_len = %d", rej_reason, ari_len);
7235 
7236 	if ((statep->mode == IBCM_PASSIVE_MODE) &&
7237 	    (rej_reason != IBT_CM_CONSUMER))
7238 		return;
7239 
7240 	switch (rej_reason) {
7241 	case IBT_CM_PRIM_GID:
7242 	case IBT_CM_ALT_GID:
7243 	case IBT_CM_PORT_REDIRECT:
7244 		if (ari_len < sizeof (ib_gid_t))
7245 			break;
7246 		failed->cf_arej_info_valid = B_TRUE;
7247 		bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_gid,
7248 		    sizeof (ib_gid_t));
7249 		cf_addl->ari_gid.gid_guid = b2h64(cf_addl->ari_gid.gid_guid);
7250 		cf_addl->ari_gid.gid_prefix =
7251 		    b2h64(cf_addl->ari_gid.gid_prefix);
7252 
7253 		IBTF_DPRINTF_L4(cmlog, "ibcm_copy_addl_rej: ari_gid= %llX:%llX",
7254 		    cf_addl->ari_gid.gid_prefix, cf_addl->ari_gid.gid_guid);
7255 
7256 		break;
7257 	case IBT_CM_PRIM_LID:
7258 	case IBT_CM_ALT_LID:
7259 		if (ari_len < sizeof (ib_lid_t))
7260 			break;
7261 		failed->cf_arej_info_valid = B_TRUE;
7262 		bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_lid,
7263 		    sizeof (ib_lid_t));
7264 		cf_addl->ari_lid = b2h16(cf_addl->ari_lid);
7265 		IBTF_DPRINTF_L4(cmlog, "ibcm_copy_addl_rej: ari_lid= 0x%lX",
7266 		    cf_addl->ari_lid);
7267 
7268 		break;
7269 	case IBT_CM_INVALID_PRIM_SL:
7270 	case IBT_CM_INVALID_ALT_SL:
7271 		if (ari_len < 1)
7272 			break;
7273 		failed->cf_arej_info_valid = B_TRUE;
7274 		/* take the first 4 bits */
7275 		cf_addl->ari_sl = rej_msgp->rej_addl_rej_info[0] >> 4;
7276 		break;
7277 	case IBT_CM_INVALID_PRIM_TC:
7278 	case IBT_CM_INVALID_ALT_TC:
7279 		if (ari_len < 1)
7280 			break;
7281 		failed->cf_arej_info_valid = B_TRUE;
7282 		/* take the first byte */
7283 		cf_addl->ari_tclass = rej_msgp->rej_addl_rej_info[0];
7284 		break;
7285 	case IBT_CM_INVALID_PRIM_HOP:
7286 	case IBT_CM_INVALID_ALT_HOP:
7287 		if (ari_len < 1)
7288 			break;
7289 		failed->cf_arej_info_valid = B_TRUE;
7290 		/* take the first byte */
7291 		cf_addl->ari_hop = rej_msgp->rej_addl_rej_info[0];
7292 		break;
7293 	case IBT_CM_INVALID_PRIM_RATE:
7294 	case IBT_CM_INVALID_ALT_RATE:
7295 		if (ari_len < 1)
7296 			break;
7297 		failed->cf_arej_info_valid = B_TRUE;
7298 		/* take the first 6 bits */
7299 		cf_addl->ari_rate = rej_msgp->rej_addl_rej_info[0] >> 2;
7300 		break;
7301 	case IBT_CM_REDIRECT_CM:
7302 		if (ari_len < sizeof (ibcm_classportinfo_msg_t))
7303 			break;
7304 		failed->cf_arej_info_valid = B_TRUE;
7305 		bcopy(rej_msgp->rej_addl_rej_info, &tclp, sizeof (tclp));
7306 		ibcm_init_clp_from_mad(&tclp, &cf_addl->ari_redirect);
7307 		break;
7308 	case IBT_CM_INVALID_MTU:
7309 		if (ari_len < 1)
7310 			break;
7311 		failed->cf_arej_info_valid = B_TRUE;
7312 		/* take the first 4 bits */
7313 		cf_addl->ari_mtu = rej_msgp->rej_addl_rej_info[0] >> 4;
7314 		break;
7315 	case IBT_CM_CONSUMER:
7316 		if (ari_len == 0)
7317 			break;
7318 		failed->cf_arej_info_valid = B_TRUE;
7319 		if (ari_len > IBT_CM_ADDL_REJ_LEN)
7320 			ari_len = IBT_CM_ADDL_REJ_LEN;
7321 		bcopy(&rej_msgp->rej_addl_rej_info,
7322 		    cf_addl->ari_consumer.rej_ari, ari_len);
7323 		cf_addl->ari_consumer.rej_ari_len = ari_len;
7324 		break;
7325 	case IBT_CM_INVALID_PRIM_FLOW:
7326 	case IBT_CM_INVALID_ALT_FLOW:
7327 		if (ari_len < 3)	/* 3 bytes needed for 20 bits */
7328 			break;
7329 		failed->cf_arej_info_valid = B_TRUE;
7330 		/* take the first 20 bits */
7331 		cf_addl->ari_flow =
7332 		    b2h32(*(uint32_t *)&rej_msgp->rej_addl_rej_info) >> 12;
7333 		break;
7334 	default:
7335 		break;
7336 	}
7337 
7338 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid))
7339 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cf_addl))
7340 }
7341 
7342 
7343 /* Used to copy classportinfo to MAD from client initialized args */
7344 static void
7345 ibcm_init_clp_to_mad(ibcm_classportinfo_msg_t *clp, ibt_redirect_info_t *rinfo)
7346 {
7347 
7348 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*clp))
7349 
7350 	bcopy(&ibcm_clpinfo, clp, sizeof (ibcm_clpinfo));
7351 
7352 	clp->RedirectGID_hi = h2b64(rinfo->rdi_gid.gid_prefix);
7353 	clp->RedirectGID_lo = h2b64(rinfo->rdi_gid.gid_guid);
7354 	clp->RedirectTC_plus =
7355 	    h2b32((rinfo->rdi_tclass << 24) | (rinfo->rdi_sl << 20) |
7356 	    (rinfo->rdi_flow & 0xfffff));
7357 	clp->RedirectLID = h2b16(rinfo->rdi_dlid);
7358 	clp->RedirectQP_plus = h2b32(rinfo->rdi_qpn & 0xffffff);
7359 	clp->RedirectQ_Key = h2b32(rinfo->rdi_qkey);
7360 	clp->RedirectP_Key = h2b16(rinfo->rdi_pkey);
7361 
7362 	IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_to_mad: RedirectGID= %llX:%llX,"
7363 	    " RedirectLID= 0x%lX", clp->RedirectGID_hi, clp->RedirectGID_lo,
7364 	    clp->RedirectLID);
7365 
7366 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*clp))
7367 }
7368 
7369 
7370 /* Used to initialize classportinfo to be returned to clients, from MAD */
7371 static void
7372 ibcm_init_clp_from_mad(ibcm_classportinfo_msg_t *clp,
7373     ibt_redirect_info_t *rinfo)
7374 {
7375 	uint32_t temp32;
7376 
7377 	rinfo->rdi_gid.gid_prefix = b2h64(clp->RedirectGID_hi);
7378 	rinfo->rdi_gid.gid_guid = b2h64(clp->RedirectGID_lo);
7379 	temp32 = b2h32(clp->RedirectTC_plus);
7380 	rinfo->rdi_tclass = temp32 >> 24;
7381 	rinfo->rdi_sl = (temp32 >> 20) & 0xf;
7382 	rinfo->rdi_flow = temp32 & 0xffff;
7383 	rinfo->rdi_dlid = b2h16(clp->RedirectLID);
7384 	rinfo->rdi_qpn = b2h32(clp->RedirectQP_plus & 0xffffff);
7385 	rinfo->rdi_qkey = b2h32(clp->RedirectQ_Key);
7386 	rinfo->rdi_pkey = b2h16(clp->RedirectP_Key);
7387 
7388 	IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_from_mad: RedirectGID= %llX:%llX,"
7389 	    " RedirectLID= 0x%lX", rinfo->rdi_gid.gid_prefix,
7390 	    rinfo->rdi_gid.gid_guid, rinfo->rdi_dlid);
7391 }
7392 
7393 
7394 /*
7395  * ibcm_cep_state_rej_est:
7396  *	QP state transition function called for an incoming REJ
7397  *	on active side in established state
7398  *
7399  * INPUTS:
7400  *	statep		- connection state pointer
7401  *
7402  * RETURN VALUE:
7403  */
7404 void
7405 ibcm_cep_state_rej_est(ibcm_state_data_t *statep)
7406 {
7407 	ibt_cm_event_t	event;
7408 	ibt_status_t	status;
7409 
7410 	IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rej_est:");
7411 
7412 	status = ibcm_cep_to_error_state(statep);
7413 	IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej_est: statep 0x%p "
7414 	    "ibcm_cep_to_error_state returned %d", statep, status);
7415 
7416 	/* Disassociate state structure and CM */
7417 	IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
7418 
7419 	ibtl_cm_chan_is_closing(statep->channel);
7420 
7421 	/* invoke the CM handler */
7422 	if (statep->cm_handler) {
7423 		bzero(&event, sizeof (event));
7424 		event.cm_type = IBT_CM_EVENT_CONN_CLOSED;
7425 		event.cm_channel = statep->channel;
7426 		event.cm_session_id = NULL;
7427 
7428 		event.cm_priv_data = NULL;
7429 		event.cm_priv_data_len = 0;
7430 
7431 		event.cm_event.closed = IBT_CM_CLOSED_REJ_RCVD;
7432 
7433 		IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej_est: "
7434 		    "rej_reason = %d", event.cm_event.failed.cf_reason);
7435 
7436 		ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_CLOSE_EVENT);
7437 
7438 		(void) statep->cm_handler(statep->state_cm_private, &event,
7439 		    NULL, NULL, 0);
7440 
7441 		ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_CLOSE_EVENT);
7442 
7443 	}
7444 }
7445 
7446 
7447 /*
7448  * ibcm_sidr_req_ud_handler:
7449  *	Invoke Client's UD handler For SIDR_REQ msg
7450  *
7451  * INPUTS:
7452  *	ud_statep	- ud_state pointer
7453  *	sidr_reqp	- SIDR_REQ message pointer
7454  *
7455  * RETURN VALUE: IBCM_SEND_REP/IBCM_SEND_REJ
7456  */
7457 static ibcm_status_t
7458 ibcm_sidr_req_ud_handler(ibcm_ud_state_data_t *ud_statep,
7459     ibcm_sidr_req_msg_t *sidr_reqp, ibcm_mad_addr_t *cm_mad_addr,
7460     ibt_sidr_status_t *sidr_status)
7461 {
7462 	void			*priv_data = NULL;
7463 	ibt_cm_ud_event_t	ud_event;
7464 	ibcm_sidr_rep_msg_t	*sidr_repp;
7465 	ibt_cm_ud_return_args_t	ud_ret_args;
7466 	ibt_cm_status_t		cb_status;
7467 	ibt_qp_query_attr_t	qp_attr;
7468 	ibt_status_t		retval;
7469 	ibcm_ud_clnt_reply_info_t	ud_clnt_info;
7470 
7471 	/* Check first if UD client handler is valid */
7472 	ASSERT(ud_statep->ud_cm_handler != NULL);
7473 
7474 	/* Fill in ibt_cm_ud_event_t */
7475 	ud_event.cm_type = IBT_CM_UD_EVENT_SIDR_REQ;
7476 	ud_event.cm_session_id = ud_statep;
7477 	ud_event.cm_event.sidr_req.sreq_service_id = ud_statep->ud_svc_id;
7478 	ud_event.cm_event.sidr_req.sreq_hca_guid = ud_statep->ud_hcap->hca_guid;
7479 	ud_event.cm_event.sidr_req.sreq_pkey = b2h16(sidr_reqp->sidr_req_pkey);
7480 	ud_event.cm_event.sidr_req.sreq_hca_port = cm_mad_addr->port_num;
7481 
7482 	ud_event.cm_priv_data =
7483 	    &(sidr_reqp->sidr_req_private_data[0]);
7484 	ud_event.cm_priv_data_len = IBT_SIDR_REQ_PRIV_DATA_SZ;
7485 
7486 	sidr_repp =
7487 	    (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
7488 
7489 	priv_data = &(sidr_repp->sidr_rep_private_data[0]);
7490 
7491 	bzero(&ud_ret_args, sizeof (ud_ret_args));
7492 
7493 	/* Invoke the client handler */
7494 	cb_status = ud_statep->ud_cm_handler(ud_statep->ud_state_cm_private,
7495 	    &ud_event, &ud_ret_args, priv_data, IBT_SIDR_REP_PRIV_DATA_SZ);
7496 
7497 	if (cb_status == IBT_CM_DEFER) {
7498 
7499 		/* unblock any blocked cm ud proceed api calls */
7500 		mutex_enter(&ud_statep->ud_state_mutex);
7501 		ud_statep->ud_clnt_proceed = IBCM_UNBLOCK;
7502 		cv_broadcast(&ud_statep->ud_block_client_cv);
7503 		mutex_exit(&ud_statep->ud_state_mutex);
7504 
7505 		return (IBCM_DEFER);
7506 	}
7507 
7508 	/* fail any blocked ud cm proceed api calls - client bug */
7509 	mutex_enter(&ud_statep->ud_state_mutex);
7510 	ud_statep->ud_clnt_proceed = IBCM_FAIL;
7511 	cv_broadcast(&ud_statep->ud_block_client_cv);
7512 	mutex_exit(&ud_statep->ud_state_mutex);
7513 
7514 	/* do the query qp as soon as possible, after return from cm handler */
7515 	if (cb_status == IBT_CM_ACCEPT) {
7516 		retval = ibt_query_qp(ud_ret_args.ud_channel, &qp_attr);
7517 		if (retval != IBT_SUCCESS) {
7518 			IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_req_ud_handler: "
7519 			    "Failed to retrieve QPN from the channel: %d",
7520 			    retval);
7521 			*sidr_status = IBT_CM_SREP_NO_CHAN;
7522 			return (IBCM_SEND_SIDR_REP);
7523 		} else if (qp_attr.qp_info.qp_trans != IBT_UD_SRV) {
7524 			IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_req_ud_handler: "
7525 			    "Server/Passive returned non-UD %d transport type "
7526 			    "QP", qp_attr.qp_info.qp_trans);
7527 			*sidr_status = IBT_CM_SREP_NO_CHAN;
7528 			return (IBCM_SEND_SIDR_REP);
7529 		}
7530 
7531 		ud_clnt_info.ud_qkey = qp_attr.qp_info.qp_transport.ud.ud_qkey;
7532 		ud_clnt_info.ud_qpn = qp_attr.qp_qpn;
7533 	}
7534 
7535 	ud_clnt_info.priv_data = priv_data;
7536 	ud_clnt_info.priv_data_len = ud_ret_args.ud_ret_len;
7537 
7538 	ud_clnt_info.redirect_infop = &ud_ret_args.ud_redirect;
7539 
7540 	ibcm_process_sidr_req_cm_hdlr(ud_statep, cb_status, &ud_clnt_info,
7541 	    sidr_status, sidr_repp);
7542 
7543 	return (IBCM_SEND_SIDR_REP);
7544 }
7545 
7546 /*ARGSUSED*/
7547 void
7548 ibcm_process_sidr_req_cm_hdlr(ibcm_ud_state_data_t *ud_statep,
7549     ibt_cm_status_t cb_status, ibcm_ud_clnt_reply_info_t *ud_clnt_info,
7550     ibt_sidr_status_t *sidr_status, ibcm_sidr_rep_msg_t *sidr_repp)
7551 {
7552 	if (cb_status == IBT_CM_DEFAULT)
7553 		cb_status = IBT_CM_REJECT;
7554 
7555 	if (cb_status == IBT_CM_ACCEPT)
7556 		*sidr_status = IBT_CM_SREP_CHAN_VALID;
7557 	else if ((cb_status == IBT_CM_REJECT) ||
7558 	    (cb_status == IBT_CM_NO_RESOURCE))
7559 		*sidr_status = IBT_CM_SREP_REJ;
7560 	else if (cb_status == IBT_CM_NO_CHANNEL)
7561 		*sidr_status = IBT_CM_SREP_NO_CHAN;
7562 	else if (cb_status == IBT_CM_REDIRECT)
7563 		*sidr_status = IBT_CM_SREP_REDIRECT;
7564 	else *sidr_status = IBT_CM_SREP_REJ;
7565 
7566 	if (*sidr_status != IBT_CM_SREP_CHAN_VALID) {
7567 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_req_cm_hdlr: "
7568 		    "ud_handler return a failure: %d", cb_status);
7569 		if (*sidr_status == IBT_CM_SREP_REDIRECT) {
7570 		/*
7571 		 * typecasting to ibcm_classportinfo_msg_t is ok, as addl info
7572 		 * begins at offset 24 in sidr rep
7573 		 */
7574 			ibcm_init_clp_to_mad(
7575 			    (ibcm_classportinfo_msg_t *)
7576 			    &sidr_repp->sidr_rep_class_port_info,
7577 			    ud_clnt_info->redirect_infop);
7578 		}
7579 		return;
7580 	}
7581 
7582 
7583 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
7584 
7585 	sidr_repp->sidr_rep_qkey =
7586 	    h2b32(ud_clnt_info->ud_qkey);
7587 	sidr_repp->sidr_rep_qpn_plus = h2b32(ud_clnt_info->ud_qpn << 8);
7588 
7589 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
7590 }
7591 
7592 /*
7593  * ibcm_sidr_rep_ud_handler:
7594  *	Invoke Client's UD handler For SIDR_REP msg
7595  *
7596  * INPUTS:
7597  *	ud_statep	- ud_state pointer
7598  *	sidr_rep_msgp	- SIDR_REQ message pointer
7599  *
7600  */
7601 static void
7602 ibcm_sidr_rep_ud_handler(ibcm_ud_state_data_t *ud_statep,
7603     ibcm_sidr_rep_msg_t *sidr_rep_msgp)
7604 {
7605 	ibt_cm_ud_event_t	ud_event;
7606 
7607 	IBTF_DPRINTF_L5(cmlog, "ibcm_sidr_rep_ud_handler: ud_statep 0x%p",
7608 	    ud_statep);
7609 
7610 	/* Check first if UD client handler is valid */
7611 	if (ud_statep->ud_cm_handler == NULL) {
7612 		IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_rep_ud_handler: "
7613 		    "cm_handler NULL");
7614 		return;
7615 	}
7616 
7617 	/* Fill in ibt_cm_ud_event_t */
7618 	ud_event.cm_type = IBT_CM_UD_EVENT_SIDR_REP;
7619 	ud_event.cm_session_id = NULL;
7620 	ud_event.cm_event.sidr_rep.srep_status =
7621 	    sidr_rep_msgp->sidr_rep_rep_status;
7622 	ud_event.cm_event.sidr_rep.srep_remote_qpn =
7623 	    b2h32(sidr_rep_msgp->sidr_rep_qpn_plus) >> 8;
7624 	ud_event.cm_event.sidr_rep.srep_remote_qkey =
7625 	    h2b32(sidr_rep_msgp->sidr_rep_qkey);
7626 
7627 	if (ud_event.cm_event.sidr_rep.srep_status == IBT_CM_SREP_REDIRECT) {
7628 		/*
7629 		 * typecasting to ibcm_classportinfo_msg_t is ok, as addl info
7630 		 * begins at offset 24 in sidr rep
7631 		 */
7632 		ibcm_init_clp_from_mad(
7633 		    (ibcm_classportinfo_msg_t *)
7634 		    sidr_rep_msgp->sidr_rep_class_port_info,
7635 		    &ud_event.cm_event.sidr_rep.srep_redirect);
7636 
7637 		if (ud_statep->ud_return_data != NULL)
7638 			bcopy(&ud_event.cm_event.sidr_rep.srep_redirect,
7639 			    &ud_statep->ud_return_data->ud_redirect,
7640 			    sizeof (ibt_redirect_info_t));
7641 	}
7642 
7643 	ud_event.cm_priv_data = &(sidr_rep_msgp->sidr_rep_private_data[0]);
7644 	ud_event.cm_priv_data_len = IBT_SIDR_REP_PRIV_DATA_SZ;
7645 
7646 	/* Invoke the client handler - inform only, so ignore retval */
7647 	(void) ud_statep->ud_cm_handler(ud_statep->ud_state_cm_private,
7648 	    &ud_event, NULL, NULL, 0);
7649 
7650 
7651 }
7652 
7653 /*
7654  * ibcm_process_lap_msg:
7655  *	This call processes an incoming LAP message
7656  *
7657  * INPUTS:
7658  *	hcap		- HCA entry pointer
7659  *	input_madp	- incoming CM LAP MAD
7660  *	cm_mad_addr	- Address information for the MAD
7661  *
7662  * RETURN VALUE: NONE
7663  */
7664 /* ARGSUSED */
7665 void
7666 ibcm_process_lap_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
7667     ibcm_mad_addr_t *cm_mad_addr)
7668 {
7669 	ibcm_status_t		state_lookup_status;
7670 	ibcm_lap_msg_t		*lap_msg = (ibcm_lap_msg_t *)
7671 	    (&input_madp[IBCM_MAD_HDR_SIZE]);
7672 	ibcm_apr_msg_t		*apr_msg;
7673 	ibcm_state_data_t	*statep = NULL;
7674 
7675 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg:");
7676 
7677 	rw_enter(&hcap->hca_state_rwlock, RW_READER);
7678 
7679 	state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_LAP,
7680 	    b2h32(lap_msg->lap_remote_comm_id), 0, 0, hcap, &statep);
7681 
7682 	rw_exit(&hcap->hca_state_rwlock);
7683 
7684 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg: lookup status %x"
7685 	    " com id %x", state_lookup_status,
7686 	    b2h32(lap_msg->lap_remote_comm_id));
7687 
7688 	if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
7689 		/* Post a REJ message ? - but spec doesn't state so */
7690 		return;
7691 	}
7692 
7693 	/* There is an existing state structure entry with active comid */
7694 
7695 	ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_LAP);
7696 
7697 	mutex_enter(&statep->state_mutex);
7698 
7699 	if ((statep->state == IBCM_STATE_ESTABLISHED) &&
7700 	    (statep->ap_state == IBCM_AP_STATE_IDLE) &&
7701 	    (statep->mode == IBCM_PASSIVE_MODE)) {
7702 		if ((statep->lapr_msg) &&
7703 		    (IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID ==
7704 		    ((ib_mad_hdr_t *)(input_madp))->TransactionID))
7705 			ibcm_post_stored_apr_mad(statep, input_madp);
7706 		else {
7707 			ibcm_status_t	clnt_response;
7708 
7709 			statep->ap_state = IBCM_AP_STATE_LAP_RCVD;
7710 			statep->clnt_proceed = IBCM_BLOCK;
7711 			mutex_exit(&statep->state_mutex);
7712 
7713 			if (statep->lapr_msg == NULL) {
7714 				if (ibcm_alloc_out_msg(
7715 				    statep->stored_reply_addr.ibmf_hdl,
7716 				    &statep->lapr_msg, MAD_METHOD_SEND) !=
7717 				    IBT_SUCCESS) {
7718 
7719 					mutex_enter(&statep->state_mutex);
7720 					statep->clnt_proceed = IBCM_FAIL;
7721 					cv_broadcast(&statep->block_client_cv);
7722 					IBCM_REF_CNT_DECR(statep);
7723 					mutex_exit(&statep->state_mutex);
7724 					return;
7725 				}
7726 			}
7727 			apr_msg = (ibcm_apr_msg_t *)
7728 			    IBCM_OUT_MSGP(statep->lapr_msg);
7729 			IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID =
7730 			    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
7731 			clnt_response =
7732 			    ibcm_cep_state_lap(statep, lap_msg, apr_msg);
7733 			IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg:"
7734 			    " statep 0x%p  apr status %d", statep,
7735 			    apr_msg->apr_ap_status);
7736 
7737 			if (clnt_response == IBCM_DEFER) {
7738 				IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg: "
7739 				    "client returned DEFER response");
7740 				return;
7741 			}
7742 
7743 			/* fail any blocked cm proceed api calls - client bug */
7744 			mutex_enter(&statep->state_mutex);
7745 			statep->clnt_proceed = IBCM_FAIL;
7746 			cv_broadcast(&statep->block_client_cv);
7747 			mutex_exit(&statep->state_mutex);
7748 
7749 			ibcm_post_apr_mad(statep);
7750 			return;
7751 		}
7752 	}	/* drop the LAP MAD in any other state */
7753 
7754 	IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
7755 	mutex_exit(&statep->state_mutex);
7756 }
7757 
7758 /*
7759  * ibcm_post_stored_apr_mad:
7760  *	Builds and posts an APR MAD from the stored APR MAD
7761  *
7762  * INPUTS:
7763  *	statep		- pointer to ibcm_state_data_t
7764  *	input_madp	- pointer to incoming lap mad
7765  *
7766  * RETURN VALUE:
7767  *	NONE
7768  *
7769  * This function is called holding the state mutex, and returns
7770  * holding the state mutex
7771  */
7772 static void
7773 ibcm_post_stored_apr_mad(ibcm_state_data_t *statep, uint8_t *input_madp)
7774 {
7775 	ibmf_msg_t	*ibmf_apr_msg;
7776 	uint8_t		apr_msg[IBCM_MSG_SIZE];
7777 
7778 	/* Need to make a copy, else an incoming new LAP may modify lapr_msg */
7779 	bcopy(IBCM_OUT_MSGP(statep->lapr_msg), apr_msg, IBCM_MSG_SIZE);
7780 
7781 	mutex_exit(&statep->state_mutex);
7782 
7783 	if (ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl,
7784 	    &ibmf_apr_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
7785 		IBTF_DPRINTF_L2(cmlog, "ibcm_post_stored_apr_mad: "
7786 		    "ibcm_alloc_out_msg failed");
7787 		mutex_enter(&statep->state_mutex);
7788 		return;
7789 	}
7790 
7791 	bcopy(apr_msg, IBCM_OUT_MSGP(ibmf_apr_msg), IBCM_MSG_SIZE);
7792 
7793 	IBCM_OUT_HDRP(ibmf_apr_msg)->AttributeID =
7794 	    h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID);
7795 
7796 	IBCM_OUT_HDRP(ibmf_apr_msg)->TransactionID =
7797 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID;
7798 
7799 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR);
7800 
7801 	ibcm_post_rc_mad(statep, ibmf_apr_msg, ibcm_post_stored_apr_complete,
7802 	    ibmf_apr_msg);
7803 
7804 	/* ibcm_free_out_msg done in ibcm_post_stored_apr_complete */
7805 
7806 	mutex_enter(&statep->state_mutex);
7807 }
7808 
7809 /*
7810  * ibcm_cep_state_lap:
7811  *	This call processes an incoming LAP message for cep state
7812  *	transition and invoking cm handler
7813  *
7814  * INPUTS:
7815  *	statep		- pointer to ibcm_state_data_t
7816  *	lap_msg		- lap msg received
7817  *	apr_msg		- apr msg to be sent
7818  *
7819  * RETURN VALUE: NONE
7820  */
7821 ibcm_status_t
7822 ibcm_cep_state_lap(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
7823     ibcm_apr_msg_t *apr_msg)
7824 {
7825 	ibt_cm_event_t		event;
7826 	ibt_cm_return_args_t	ret_args;
7827 	ibt_cm_status_t		cb_status;
7828 	ibcm_clnt_reply_info_t	clnt_info;
7829 
7830 
7831 	IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: statep 0x%p", statep);
7832 
7833 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg))
7834 
7835 	/* If APM is not supported, return error */
7836 	if (!(statep->hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) {
7837 		apr_msg->apr_ap_status = IBT_CM_AP_NOT_SUPPORTED;
7838 		return (IBCM_SEND_APR);
7839 	}
7840 
7841 	if (statep->local_qpn !=
7842 	    b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8) {
7843 		apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7844 		IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: local_qpn %x does "
7845 		    "not match remote's remote_qpn %x", statep->local_qpn,
7846 		    b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8);
7847 		return (IBCM_SEND_APR);
7848 	}
7849 
7850 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg))
7851 
7852 	/* Fill up the event */
7853 	bzero(&event, sizeof (event));
7854 	event.cm_type = IBT_CM_EVENT_LAP_RCV;
7855 	event.cm_channel = statep->channel;
7856 	event.cm_session_id = statep;
7857 	event.cm_priv_data = lap_msg->lap_private_data;
7858 	event.cm_priv_data_len =  IBT_LAP_PRIV_DATA_SZ;
7859 	event.cm_event.lap.lap_timeout = ibt_ib2usec(
7860 	    ((uint8_t *)&lap_msg->lap_remote_qpn_eecn_plus)[3] >> 3);
7861 
7862 	ibcm_fill_adds_from_lap(&event.cm_event.lap.lap_alternate_path,
7863 	    lap_msg, IBCM_PASSIVE_MODE);
7864 
7865 	cb_status = statep->cm_handler(statep->state_cm_private, &event,
7866 	    &ret_args, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ);
7867 
7868 	IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_lap: cb_status = %d", cb_status);
7869 	if (cb_status == IBT_CM_DEFER) {
7870 
7871 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
7872 
7873 		if (statep->defer_cm_msg == NULL)
7874 			statep->defer_cm_msg =
7875 			    kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
7876 		bcopy(lap_msg, statep->defer_cm_msg, IBCM_MSG_SIZE);
7877 
7878 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
7879 
7880 		/* unblock any blocked cm proceed api calls */
7881 		mutex_enter(&statep->state_mutex);
7882 		statep->clnt_proceed = IBCM_UNBLOCK;
7883 		cv_broadcast(&statep->block_client_cv);
7884 		mutex_exit(&statep->state_mutex);
7885 
7886 		return (IBCM_DEFER);
7887 	}
7888 
7889 	clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
7890 	clnt_info.priv_data = NULL;
7891 	clnt_info.priv_data_len = 0;
7892 
7893 	ibcm_process_cep_lap_cm_hdlr(statep, cb_status, &clnt_info, lap_msg,
7894 	    apr_msg);
7895 	return (IBCM_SEND_APR);
7896 }
7897 
7898 /*
7899  * ibcm_fill_adds_from_lap:
7900  *	Fills the address vector (part of event structure passed to
7901  * client) from the LAP message
7902  *
7903  * INPUTS:
7904  *	adds		- Address vector to be filled-in
7905  *	lap_msg		- LAP message used to fill the address vector
7906  *
7907  * RETURN VALUE: NONE
7908  */
7909 static void
7910 ibcm_fill_adds_from_lap(ibt_adds_vect_t *adds, ibcm_lap_msg_t *lap_msg,
7911     ibcm_mode_t mode)
7912 {
7913 	adds->av_srvl = lap_msg->lap_alt_sl_plus >> 4;
7914 	if (mode == IBCM_PASSIVE_MODE) {
7915 		adds->av_dgid.gid_prefix =
7916 		    b2h64(lap_msg->lap_alt_l_port_gid.gid_prefix);
7917 		adds->av_dgid.gid_guid =
7918 		    b2h64(lap_msg->lap_alt_l_port_gid.gid_guid);
7919 		adds->av_sgid.gid_prefix =
7920 		    b2h64(lap_msg->lap_alt_r_port_gid.gid_prefix);
7921 		adds->av_sgid.gid_guid =
7922 		    b2h64(lap_msg->lap_alt_r_port_gid.gid_guid);
7923 		adds->av_dlid = b2h16(lap_msg->lap_alt_l_port_lid);
7924 	} else {
7925 		adds->av_sgid.gid_prefix =
7926 		    b2h64(lap_msg->lap_alt_l_port_gid.gid_prefix);
7927 		adds->av_sgid.gid_guid =
7928 		    b2h64(lap_msg->lap_alt_l_port_gid.gid_guid);
7929 		adds->av_dgid.gid_prefix =
7930 		    b2h64(lap_msg->lap_alt_r_port_gid.gid_prefix);
7931 		adds->av_dgid.gid_guid =
7932 		    b2h64(lap_msg->lap_alt_r_port_gid.gid_guid);
7933 		adds->av_dlid = b2h16(lap_msg->lap_alt_r_port_lid);
7934 	}
7935 
7936 	IBTF_DPRINTF_L4(cmlog, "ibcm_fill_adds_from_lap: SGID=(%llX:%llX)",
7937 	    adds->av_sgid.gid_prefix, adds->av_sgid.gid_guid);
7938 
7939 	IBTF_DPRINTF_L4(cmlog, "ibcm_fill_adds_from_lap: DGID=(%llX:%llX)",
7940 	    adds->av_dgid.gid_prefix, adds->av_dgid.gid_guid);
7941 
7942 	adds->av_srate = lap_msg->lap_alt_srate_plus & 0x3f;
7943 
7944 	/* next copy off the GRH info if it exists  */
7945 	if ((lap_msg->lap_alt_sl_plus & 0x8) == 0) {
7946 		uint32_t flow_tclass = b2h32(lap_msg->lap_alt_flow_label_plus);
7947 
7948 		adds->av_send_grh = B_TRUE;
7949 		adds->av_flow = flow_tclass >> 12;
7950 		adds->av_tclass = flow_tclass & 0xff;
7951 		adds->av_hop = lap_msg->lap_alt_hop_limit;
7952 	} else {
7953 		adds->av_send_grh = B_FALSE;
7954 	}
7955 }
7956 
7957 /*
7958  * ibcm_process_cep_lap_cm_hdlr:
7959  * Processes the cm handler response for an incoming LAP.
7960  */
7961 
7962 void
7963 ibcm_process_cep_lap_cm_hdlr(ibcm_state_data_t *statep,
7964     ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
7965     ibcm_lap_msg_t *lap_msg, ibcm_apr_msg_t *apr_msg)
7966 {
7967 	ibtl_cm_hca_port_t	port;
7968 	ibt_qp_query_attr_t	qp_attrs;
7969 	ibt_cep_modify_flags_t	cep_flags;
7970 	ibt_status_t		status;
7971 	ibt_adds_vect_t		*adds;
7972 
7973 	if (cb_status == IBT_CM_DEFAULT)
7974 		cb_status = IBT_CM_REJECT;
7975 
7976 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg))
7977 
7978 	/* verify status */
7979 	apr_msg->apr_addl_info_len = 0;
7980 	if (cb_status == IBT_CM_ACCEPT) {
7981 		apr_msg->apr_ap_status = IBT_CM_AP_LOADED;
7982 	} else if (cb_status == IBT_CM_REJECT) {
7983 		apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7984 	} else if (cb_status == IBT_CM_REDIRECT) {
7985 		apr_msg->apr_ap_status = IBT_CM_AP_REDIRECT;
7986 		/* copy redirect info to APR */
7987 		apr_msg->apr_addl_info_len = sizeof (ibcm_classportinfo_msg_t);
7988 		ibcm_init_clp_to_mad(
7989 		    (ibcm_classportinfo_msg_t *)apr_msg->apr_addl_info,
7990 		    &clnt_info->reply_event->apr);
7991 	} else if (cb_status == IBT_CM_NO_RESOURCE) {
7992 		apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7993 	} else {
7994 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
7995 		    " Client handler unexpected return %x", statep, cb_status);
7996 		cb_status = IBT_CM_REJECT;
7997 		apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7998 	}
7999 
8000 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep 0x%p "
8001 	    " client handler returned %d, apr status %d", statep, cb_status,
8002 	    apr_msg->apr_ap_status);
8003 
8004 	/* copy private data to outgoing apr, specified via priv_data */
8005 	if ((clnt_info->priv_data != NULL) && (clnt_info->priv_data_len > 0))
8006 		bcopy(clnt_info->priv_data, apr_msg->apr_private_data,
8007 		    min(clnt_info->priv_data_len, IBT_APR_PRIV_DATA_SZ));
8008 
8009 	if (cb_status != IBT_CM_ACCEPT)
8010 		return;
8011 
8012 	if (ibt_query_qp(statep->channel, &qp_attrs) != IBT_SUCCESS ||
8013 	    (qp_attrs.qp_info.qp_state != IBT_STATE_RTS &&
8014 	    qp_attrs.qp_info.qp_state != IBT_STATE_SQD)) {
8015 		apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8016 		return;
8017 	}
8018 
8019 	/* Fill up input args for ibt_modify_qp */
8020 	cep_flags = IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_STATE;
8021 
8022 	/* do RTS=>RTS or SQD=>SQD.  The next line is needed for RTS=>RTS. */
8023 	qp_attrs.qp_info.qp_current_state = qp_attrs.qp_info.qp_state;
8024 
8025 	adds = &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect;
8026 	ibcm_fill_adds_from_lap(adds, lap_msg, IBCM_PASSIVE_MODE);
8027 
8028 	if ((status = ibtl_cm_get_hca_port(adds->av_sgid,
8029 	    statep->local_hca_guid, &port)) != IBT_SUCCESS) {
8030 
8031 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:"
8032 		    " ibtl_cm_get_hca_port failed status %d", status);
8033 		apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8034 		return;
8035 	}
8036 
8037 	IBCM_QP_RC(qp_attrs).rc_alt_path.cep_hca_port_num = port.hp_port;
8038 
8039 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep 0x%p "
8040 	    "gid = (%llx, %llx), port_num = %d", statep,
8041 	    IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_dgid.
8042 	    gid_prefix,
8043 	    IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_dgid.gid_guid,
8044 	    port.hp_port);
8045 
8046 	/* The pkey is same as the primary path */
8047 	status = ibt_pkey2index_byguid(statep->local_hca_guid,
8048 	    port.hp_port, statep->pkey,
8049 	    &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_pkey_ix);
8050 
8051 	if (status != IBT_SUCCESS) {
8052 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
8053 		    " ibt_pkey2index_byguid failed %d", statep, status);
8054 		apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8055 		return;
8056 	}
8057 
8058 	IBCM_QP_RC(qp_attrs).rc_alt_path.cep_timeout =
8059 	    lap_msg->lap_alt_local_acktime_plus >> 3;
8060 
8061 	qp_attrs.qp_info.qp_trans = IBT_RC_SRV;
8062 	if (IBCM_QP_RC(qp_attrs).rc_mig_state == IBT_STATE_MIGRATED) {
8063 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
8064 		    ": rearming APM", statep);
8065 		cep_flags |= IBT_CEP_SET_MIG;
8066 		IBCM_QP_RC(qp_attrs).rc_mig_state = IBT_STATE_REARMED;
8067 	}
8068 	status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info,
8069 	    NULL);
8070 
8071 	if (status != IBT_SUCCESS) {
8072 		ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL);
8073 	} else
8074 		ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT);
8075 
8076 #ifdef	DEBUG
8077 	(void) ibt_query_qp(statep->channel, &qp_attrs);
8078 	print_modify_qp("PASSIVE LAP QUERY", statep->channel,
8079 	    cep_flags, &qp_attrs.qp_info);
8080 #endif
8081 
8082 	if (status != IBT_SUCCESS) {
8083 		apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8084 		IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:"
8085 		    " ibt_modify_qp() returned = %d", status);
8086 		return;
8087 	}
8088 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg))
8089 }
8090 
8091 
8092 /*
8093  * ibcm_post_apr_mad:
8094  *	Posts a APR MAD and starts timer
8095  *
8096  * INPUTS:
8097  *	statep		- state pointer
8098  *
8099  * RETURN VALUE: NONE
8100  */
8101 void
8102 ibcm_post_apr_mad(ibcm_state_data_t *statep)
8103 {
8104 	ibcm_apr_msg_t	*apr_msgp;
8105 
8106 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msgp))
8107 
8108 	apr_msgp = (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
8109 
8110 	apr_msgp->apr_local_comm_id = h2b32(statep->local_comid);
8111 	apr_msgp->apr_remote_comm_id = h2b32(statep->remote_comid);
8112 	IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
8113 	    h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID);
8114 
8115 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msgp))
8116 
8117 	ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR);
8118 
8119 	ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_apr_complete,
8120 	    statep);
8121 }
8122 
8123 /*
8124  * ibcm_process_apr_msg:
8125  *	This call processes an incoming APR message
8126  *
8127  * INPUTS:
8128  *	hcap		- HCA entry pointer
8129  *	input_madp	- incoming CM SIDR REP MAD
8130  *	cm_mad_addr	- Address information for the MAD to be posted
8131  *
8132  * RETURN VALUE: NONE
8133  */
8134 /*ARGSUSED*/
8135 void
8136 ibcm_process_apr_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
8137     ibcm_mad_addr_t *cm_mad_addr)
8138 {
8139 	ibcm_status_t		state_lookup_status;
8140 	ibcm_apr_msg_t		*apr_msg = (ibcm_apr_msg_t *)
8141 	    (&input_madp[IBCM_MAD_HDR_SIZE]);
8142 	ibcm_state_data_t	*statep = NULL;
8143 
8144 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_apr_msg:");
8145 
8146 	rw_enter(&hcap->hca_state_rwlock, RW_READER);
8147 	state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_APR,
8148 	    b2h32(apr_msg->apr_remote_comm_id), 0, 0, hcap, &statep);
8149 	rw_exit(&hcap->hca_state_rwlock);
8150 
8151 	if (state_lookup_status != IBCM_LOOKUP_EXISTS) {
8152 		return;
8153 	}
8154 
8155 	/* if transaction id is not as expected, drop the APR mad */
8156 	if (IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID !=
8157 	    ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
8158 		mutex_enter(&statep->state_mutex);
8159 		IBCM_REF_CNT_DECR(statep);
8160 		mutex_exit(&statep->state_mutex);
8161 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_apr_msg: statep 0x%p"
8162 		    ": rcv'd APR MAD with comid 0x%x",
8163 		    statep, b2h32(apr_msg->apr_remote_comm_id));
8164 		IBTF_DPRINTF_L3(cmlog, "ibcm_process_apr_msg: "
8165 		    "tid expected 0x%llX tid found 0x%llX",
8166 		    b2h64(IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID),
8167 		    b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID));
8168 		return;
8169 	}
8170 
8171 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_apr_msg: statep 0x%p "
8172 	    "lookup status %x", statep, state_lookup_status);
8173 
8174 	mutex_enter(&statep->state_mutex);
8175 
8176 	if (!((statep->state == IBCM_STATE_ESTABLISHED) &&
8177 	    ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
8178 	    (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)))) {
8179 		IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
8180 		mutex_exit(&statep->state_mutex);
8181 		return;
8182 	}
8183 
8184 	statep->ap_state = IBCM_AP_STATE_APR_RCVD;
8185 
8186 	/* cancel the LAP timer */
8187 	if (statep->timerid != 0) {
8188 		timeout_id_t timer_val;
8189 		timer_val = statep->timerid;
8190 		statep->timerid = 0;
8191 		mutex_exit(&statep->state_mutex);
8192 		(void) untimeout(timer_val);
8193 	} else {
8194 		mutex_exit(&statep->state_mutex);
8195 	}
8196 
8197 	ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_APR);
8198 
8199 	ibcm_cep_state_apr(statep,
8200 	    (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg), apr_msg);
8201 
8202 	mutex_enter(&statep->state_mutex);
8203 	statep->ap_state = IBCM_AP_STATE_IDLE;
8204 
8205 	/* unblock any DREQ threads and close channels */
8206 	cv_broadcast(&statep->block_mad_cv);
8207 
8208 	statep->ap_done = B_TRUE;
8209 
8210 	/* wake up blocking ibt_set_alt_path */
8211 	cv_broadcast(&statep->block_client_cv);
8212 
8213 	IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
8214 	mutex_exit(&statep->state_mutex);
8215 }
8216 
8217 static void
8218 ibcm_set_apr_arej(int ap_status, ibcm_apr_msg_t *apr_msgp,
8219     ibt_arej_info_t *ari, boolean_t *ari_valid)
8220 {
8221 	int ari_len = apr_msgp->apr_addl_info_len;
8222 	ibcm_classportinfo_msg_t tclp;
8223 
8224 	*ari_valid = B_FALSE;
8225 
8226 	IBTF_DPRINTF_L3(cmlog, "ibcm_set_apr_arej: apr_status = %d "
8227 	    "ari_len = %d", ap_status, ari_len);
8228 
8229 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ari))
8230 
8231 	switch (ap_status) {
8232 	case IBT_CM_AP_REDIRECT:
8233 		if (ari_len < sizeof (ibcm_classportinfo_msg_t))
8234 			break;
8235 		*ari_valid = B_TRUE;
8236 		bcopy(apr_msgp->apr_addl_info, &tclp, sizeof (tclp));
8237 		ibcm_init_clp_from_mad(&tclp, &ari->ari_redirect);
8238 		break;
8239 	case IBT_CM_AP_RLID_REJECTED:
8240 		if (ari_len < sizeof (ib_lid_t))
8241 			break;
8242 		*ari_valid = B_TRUE;
8243 		bcopy(apr_msgp->apr_addl_info, &ari->ari_lid,
8244 		    sizeof (ib_lid_t));
8245 		ari->ari_lid = b2h16(ari->ari_lid);
8246 		break;
8247 	case IBT_CM_AP_RGID_REJECTED:
8248 		if (ari_len < sizeof (ib_gid_t))
8249 			break;
8250 		*ari_valid = B_TRUE;
8251 		bcopy(apr_msgp->apr_addl_info, &ari->ari_gid,
8252 		    sizeof (ib_gid_t));
8253 		ari->ari_gid.gid_guid = b2h64(ari->ari_gid.gid_guid);
8254 		ari->ari_gid.gid_prefix = b2h64(ari->ari_gid.gid_prefix);
8255 
8256 		IBTF_DPRINTF_L4(cmlog, "ibcm_set_apr_arej: ari_gid= %llX:%llX",
8257 		    ari->ari_gid.gid_prefix, ari->ari_gid.gid_guid);
8258 		break;
8259 	case IBT_CM_AP_FLOW_REJECTED:
8260 		if (ari_len < 3)	/* 3 bytes needed for 20 bits */
8261 			break;
8262 		*ari_valid = B_TRUE;
8263 		/* take the first 20 bits */
8264 		ari->ari_flow =
8265 		    b2h32(*(uint32_t *)&apr_msgp->apr_addl_info) >> 12;
8266 		break;
8267 	case IBT_CM_AP_TCLASS_REJECTED:
8268 		if (ari_len < 1)
8269 			break;
8270 		*ari_valid = B_TRUE;
8271 		/* take the first byte */
8272 		ari->ari_tclass = apr_msgp->apr_addl_info[0];
8273 		break;
8274 	case IBT_CM_AP_HOP_REJECTED:
8275 		if (ari_len < 1)
8276 			break;
8277 		*ari_valid = B_TRUE;
8278 		/* take the first byte */
8279 		ari->ari_hop = apr_msgp->apr_addl_info[0];
8280 		break;
8281 	case IBT_CM_AP_RATE_REJECTED:
8282 		if (ari_len < 1)
8283 			break;
8284 		*ari_valid = B_TRUE;
8285 		/* take the first 6 bits */
8286 		ari->ari_rate = apr_msgp->apr_addl_info[0] >> 2;
8287 		break;
8288 	case IBT_CM_AP_SL_REJECTED:
8289 		if (ari_len < 1)
8290 			break;
8291 		*ari_valid = B_TRUE;
8292 		/* take the first 4 bits */
8293 		ari->ari_sl = apr_msgp->apr_addl_info[0] >> 4;
8294 		break;
8295 	default:
8296 		break;
8297 	}
8298 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ari))
8299 }
8300 
8301 /*
8302  * ibcm_cep_state_apr:
8303  *	This call processes an incoming APR message
8304  *
8305  * INPUTS:
8306  *	statep		- pointer to ibcm_state_data_t
8307  *	lap_msg		- lap msg sent earlier
8308  *	apr_msg		- apr msg received
8309  *
8310  * RETURN VALUE: NONE
8311  */
8312 void
8313 ibcm_cep_state_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
8314     ibcm_apr_msg_t *apr_msg)
8315 {
8316 	ibt_cm_event_t		event;
8317 	ibcm_status_t		status = IBCM_SUCCESS;
8318 	uint8_t			ap_status = apr_msg->apr_ap_status;
8319 
8320 	IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_apr: statep 0x%p, ap_status %d",
8321 	    statep, ap_status);
8322 
8323 	if (ap_status == IBT_CM_AP_LOADED)
8324 		status = ibcm_set_qp_from_apr(statep, lap_msg);
8325 
8326 	if (statep->ap_return_data != NULL) {	/* blocking call */
8327 
8328 		/* copy the private data */
8329 		if ((statep->ap_return_data->ap_priv_data != NULL) &&
8330 		    (statep->ap_return_data->ap_priv_data_len > 0))
8331 			bcopy(apr_msg->apr_private_data,
8332 			    statep->ap_return_data->ap_priv_data,
8333 			    statep->ap_return_data->ap_priv_data_len);
8334 
8335 		/* initialize the ap status */
8336 		if (status == IBCM_FAILURE) {
8337 			statep->ap_return_data->ap_status = IBT_CM_AP_REJECT;
8338 			statep->ap_return_data->ap_arej_info_valid = B_FALSE;
8339 		} else {
8340 			statep->ap_return_data->ap_status = ap_status;
8341 			ibcm_set_apr_arej(ap_status, apr_msg,
8342 			    &statep->ap_return_data->ap_arej_info,
8343 			    &statep->ap_return_data->ap_arej_info_valid);
8344 		}
8345 
8346 		/* do a cv signal for a blocking ibt_set_alt_path */
8347 		mutex_enter(&statep->state_mutex);
8348 		statep->ap_done = B_TRUE;
8349 		cv_broadcast(&statep->block_client_cv);
8350 		mutex_exit(&statep->state_mutex);
8351 
8352 	} else {	/* Non blocking call */
8353 		/* Fill up the event */
8354 
8355 		bzero(&event, sizeof (event));
8356 		event.cm_type = IBT_CM_EVENT_APR_RCV;
8357 		event.cm_channel = statep->channel;
8358 		event.cm_session_id = NULL;
8359 		event.cm_priv_data = apr_msg->apr_private_data;
8360 		event.cm_priv_data_len =  IBT_APR_PRIV_DATA_SZ;
8361 		if (status == IBCM_FAILURE) {
8362 			event.cm_event.apr.apr_status = IBT_CM_AP_REJECT;
8363 			event.cm_event.apr.apr_arej_info_valid = B_FALSE;
8364 		} else {
8365 			event.cm_event.apr.apr_status = ap_status;
8366 			ibcm_set_apr_arej(ap_status, apr_msg,
8367 			    &event.cm_event.apr.apr_arej_info,
8368 			    &event.cm_event.apr.apr_arej_info_valid);
8369 		}
8370 
8371 		/* initialize the ap status */
8372 		statep->cm_handler(statep->state_cm_private, &event,
8373 		    NULL, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ);
8374 	}
8375 	mutex_enter(&statep->state_mutex);
8376 	ibcm_open_done(statep);
8377 	mutex_exit(&statep->state_mutex);
8378 }
8379 
8380 /*
8381  * ibcm_set_qp_from_apr:
8382  *	This call sets QP's alt path info based on APR message contents
8383  *
8384  * INPUTS:
8385  *	statep		- pointer to ibcm_state_data_t
8386  *	lap_msg		- lap msg sent earlier
8387  *
8388  * RETURN VALUE: ibcm_status_t
8389  */
8390 static ibcm_status_t
8391 ibcm_set_qp_from_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg)
8392 {
8393 	ibtl_cm_hca_port_t	port;
8394 	ibt_adds_vect_t		*adds;
8395 
8396 	ibt_qp_query_attr_t	qp_attrs;
8397 	ibt_cep_modify_flags_t	cep_flags;
8398 	ibt_status_t		status;
8399 
8400 	IBTF_DPRINTF_L3(cmlog, "ibcm_set_qp_from_apr: statep 0x%p", statep);
8401 
8402 	status = ibt_query_qp(statep->channel, &qp_attrs);
8403 	if (status != IBT_SUCCESS ||
8404 	    (qp_attrs.qp_info.qp_state != IBT_STATE_RTS &&
8405 	    qp_attrs.qp_info.qp_state != IBT_STATE_SQD)) {
8406 		IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: ibt_query_qp "
8407 		    "failed, status = %d, qp_state = %d", statep, status,
8408 		    qp_attrs.qp_info.qp_state);
8409 		return (IBCM_FAILURE);
8410 	}
8411 
8412 	/* Fill up input args for ibt_modify_qp */
8413 	cep_flags = IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_STATE;
8414 
8415 	/* do RTS=>RTS or SQD=>SQD.  The next line is needed for RTS=>RTS. */
8416 	qp_attrs.qp_info.qp_current_state = qp_attrs.qp_info.qp_state;
8417 
8418 	/* Fill up input args for ibt_modify_qp */
8419 	adds = &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect;
8420 
8421 	ibcm_fill_adds_from_lap(adds, lap_msg, IBCM_ACTIVE_MODE);
8422 
8423 	if ((status = ibtl_cm_get_hca_port(adds->av_sgid,
8424 	    statep->local_hca_guid, &port)) != IBT_SUCCESS) {
8425 		IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: "
8426 		    "ibtl_cm_get_hca_port failed status = %d", status);
8427 		IBTF_DPRINTF_L5(cmlog, "ibcm_set_qp_from_apr:"
8428 		    " ibtl_cm_get_hca_port sgid guid %llX",
8429 		    adds->av_sgid.gid_guid);
8430 		IBTF_DPRINTF_L5(cmlog, "ibcm_set_qp_from_apr:"
8431 		    " ibtl_cm_get_hca_port sgid prefix %llX ",
8432 		    adds->av_sgid.gid_prefix);
8433 		return (IBCM_FAILURE);
8434 	}
8435 
8436 	IBCM_QP_RC(qp_attrs).rc_alt_path.cep_hca_port_num =
8437 	    port.hp_port;
8438 
8439 	IBTF_DPRINTF_L4(cmlog, "ibcm_set_qp_from_apr: "
8440 	    "gid = %llx:%llx, port_num = %d",
8441 	    IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_sgid.
8442 	    gid_prefix,
8443 	    IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_sgid.gid_guid,
8444 	    port.hp_port);
8445 
8446 	/* The pkey is same as the primary path */
8447 	status = ibt_pkey2index_byguid(statep->local_hca_guid,
8448 	    port.hp_port, statep->pkey,
8449 	    &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_pkey_ix);
8450 
8451 	if (status != IBT_SUCCESS) {
8452 		IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: "
8453 		    "ibt_pkey2index_byguid failed %d", status);
8454 		return (IBCM_FAILURE);
8455 	}
8456 	qp_attrs.qp_info.qp_trans = IBT_RC_SRV;
8457 	IBCM_QP_RC(qp_attrs).rc_alt_path.cep_timeout =
8458 	    ibt_usec2ib(statep->remote_ack_delay +
8459 	    2 * statep->rc_alt_pkt_lt);
8460 	if (IBCM_QP_RC(qp_attrs).rc_mig_state == IBT_STATE_MIGRATED) {
8461 		/* Need to rearm */
8462 		IBTF_DPRINTF_L3(cmlog, "ibcm_set_qp_from_apr: statep 0x%p: "
8463 		    "rearming APM", statep);
8464 		cep_flags |= IBT_CEP_SET_MIG;
8465 		IBCM_QP_RC(qp_attrs).rc_mig_state = IBT_STATE_REARMED;
8466 	}
8467 
8468 	status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info,
8469 	    NULL);
8470 
8471 	if (status != IBT_SUCCESS)
8472 		ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL);
8473 	else
8474 		ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT);
8475 
8476 #ifdef	DEBUG
8477 	(void) ibt_query_qp(statep->channel, &qp_attrs);
8478 	print_modify_qp("ACTIVE LAP QUERY", statep->channel,
8479 	    cep_flags, &qp_attrs.qp_info);
8480 #endif
8481 
8482 	if (status != IBT_SUCCESS) {
8483 		IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr:"
8484 		    " ibt_modify_qp() failed, status = %d", status);
8485 		return (IBCM_FAILURE);
8486 	}
8487 
8488 	return (IBCM_SUCCESS);
8489 }
8490 
8491 /*
8492  * ibcm_sync_lapr_idle:
8493  *
8494  *	This call either cancels a LAP/APR operation or waits
8495  *	until the operation is complete
8496  *
8497  * INPUTS:
8498  *	statep	Pointer to ibcm_state_data_t
8499  *
8500  * RETURN VALUE: NONE
8501  *
8502  * This function is called holding state mutex
8503  * This function returns, releasing the state mutex
8504  */
8505 void
8506 ibcm_sync_lapr_idle(ibcm_state_data_t *statep)
8507 {
8508 	timeout_id_t	timer_val = statep->timerid;
8509 	ibt_cm_event_t	event;
8510 
8511 	IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8512 	    "statep %p state %d ap_state %d", statep, statep->state,
8513 	    statep->ap_state);
8514 
8515 	ASSERT(MUTEX_HELD(&statep->state_mutex));
8516 	_NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex))
8517 
8518 	/* Busy AP states on active/passive sides */
8519 	if ((statep->ap_state == IBCM_AP_STATE_LAP_RCVD) ||
8520 	    (statep->ap_state == IBCM_AP_STATE_APR_RCVD) ||
8521 	    (statep->ap_state == IBCM_AP_STATE_MRA_LAP_SENT) ||
8522 	    (statep->ap_state == IBCM_AP_STATE_TIMED_OUT)) {
8523 
8524 		/* wait till ap_state becomes IBCM_AP_STATE_IDLE */
8525 		while (statep->ap_state != IBCM_AP_STATE_IDLE)
8526 			cv_wait(&statep->block_mad_cv, &statep->state_mutex);
8527 
8528 		mutex_exit(&statep->state_mutex);
8529 
8530 	} else if ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
8531 	    (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
8532 
8533 		/* fail the client's ibt_set_alt_path */
8534 
8535 		/* blocking ibt_set_alt_path */
8536 		if (statep->ap_return_data != NULL) {
8537 			statep->ap_return_data->ap_status =
8538 			    IBT_CM_AP_ABORT;
8539 			statep->ap_state = IBCM_AP_STATE_IDLE;
8540 			cv_broadcast(&statep->block_client_cv);
8541 			IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8542 			    "blocked wait");
8543 		}
8544 
8545 		statep->timerid = 0;
8546 		/* Cancel the timeout */
8547 		mutex_exit(&statep->state_mutex);
8548 		if (timer_val != 0)
8549 			(void) untimeout(timer_val);
8550 
8551 		/* Non blocking ibt_set_alt_path */
8552 		if (statep->ap_return_data == NULL) {
8553 
8554 			/* Fill up the event */
8555 
8556 			bzero(&event, sizeof (event));
8557 			event.cm_type = IBT_CM_EVENT_APR_RCV;
8558 			event.cm_channel = statep->channel;
8559 			event.cm_session_id = NULL;
8560 			event.cm_priv_data = NULL;
8561 			event.cm_priv_data_len =  0;
8562 			event.cm_event.apr.apr_status = IBT_CM_AP_ABORT;
8563 
8564 			/* Call the cm handler */
8565 			statep->cm_handler(statep->state_cm_private, &event,
8566 			    NULL, NULL, 0);
8567 			IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8568 			    "non-blocked wait");
8569 		}
8570 	} else mutex_exit(&statep->state_mutex);
8571 
8572 	ASSERT(!MUTEX_HELD(&statep->state_mutex));
8573 }
8574 
8575 #ifdef DEBUG
8576 
8577 /*
8578  * Debug function used to print all the modify qp attributes.
8579  * Useful to manually verify the modify qp parameters are as
8580  * expected
8581  */
8582 static void
8583 print_modify_qp(char *prefix, ibt_qp_hdl_t ibt_qp,
8584     ibt_cep_modify_flags_t flags, ibt_qp_info_t *qp_attr)
8585 {
8586 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP %s %p", prefix, ibt_qp);
8587 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP flags 0x%x", flags);
8588 
8589 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP "
8590 	    "rc_rdma_ra_in %d rc_rdma_ra_out %d",
8591 	    qp_attr->qp_transport.rc.rc_rdma_ra_in,
8592 	    qp_attr->qp_transport.rc.rc_rdma_ra_out);
8593 
8594 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8595 	    "port %d path bits %d dlid %X",
8596 	    qp_attr->qp_transport.rc.rc_path.cep_hca_port_num,
8597 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_src_path,
8598 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dlid);
8599 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8600 	    "pkey index %d cep_timeout %d",
8601 	    qp_attr->qp_transport.rc.rc_path.cep_pkey_ix,
8602 	    qp_attr->qp_transport.rc.rc_path.cep_timeout);
8603 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8604 	    "srvl %d flow label %d tclass %d",
8605 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_srvl,
8606 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_flow,
8607 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_tclass);
8608 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8609 	    "hop %d srate %d sgid_ix %d send_grh %d",
8610 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_hop,
8611 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_srate,
8612 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid_ix,
8613 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_send_grh);
8614 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8615 	    "dgid prefix %llX dgid guid %llX",
8616 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dgid.gid_prefix,
8617 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dgid.gid_guid);
8618 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: "
8619 	    "sgid prefix %llX sgid guid %llX",
8620 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid.gid_prefix,
8621 	    qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid.gid_guid);
8622 
8623 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8624 	    "port %d path bits %d dlid %X",
8625 	    qp_attr->qp_transport.rc.rc_alt_path.cep_hca_port_num,
8626 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_src_path,
8627 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dlid);
8628 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8629 	    "pkey index %d cep_timeout %d",
8630 	    qp_attr->qp_transport.rc.rc_alt_path.cep_pkey_ix,
8631 	    qp_attr->qp_transport.rc.rc_alt_path.cep_timeout);
8632 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8633 	    "srvl %d flow label %d tclass %d",
8634 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_srvl,
8635 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_flow,
8636 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_tclass);
8637 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8638 	    "hop %d srate %d sgid_ix %d send_grh %d",
8639 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_hop,
8640 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_srate,
8641 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid_ix,
8642 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_send_grh);
8643 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8644 	    "dgid prefix %llX dgid guid %llX",
8645 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dgid.
8646 	    gid_prefix,
8647 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dgid.
8648 	    gid_guid);
8649 	IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: "
8650 	    "sgid prefix %llX sgid guid %llX",
8651 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid.
8652 	    gid_prefix,
8653 	    qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid.
8654 	    gid_guid);
8655 }
8656 #endif
8657