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