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