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