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