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