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