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