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