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