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