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