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