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