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