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 ip_data = (ibcm_ip_pvtdata_t *)cm_req_msgp->req_private_data; 5918 5919 bzero(&ari_ip, sizeof (ibt_ari_ip_t)); 5920 5921 /* RDMA IP CM Layer Rejects this */ 5922 if (ip_data->ip_MajV != IBT_CM_IP_MAJ_VER) { 5923 IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:" 5924 "IP MajorVer mis-match %d", ip_data->ip_MajV); 5925 ari_ip.ip_reason = IBT_ARI_IP_MAJOR_VERSION; 5926 ari_ip.ip_suggested_version = IBT_CM_IP_MAJ_VER; 5927 ari_ip.ip_suggested = B_TRUE; 5928 rdma_rej_mad = B_TRUE; 5929 } else if (ip_data->ip_MinV != IBT_CM_IP_MIN_VER) { 5930 IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:" 5931 "IP MinorVer mis-match %d", ip_data->ip_MinV); 5932 ari_ip.ip_reason = IBT_ARI_IP_MINOR_VERSION; 5933 ari_ip.ip_suggested_version = IBT_CM_IP_MIN_VER; 5934 ari_ip.ip_suggested = B_TRUE; 5935 rdma_rej_mad = B_TRUE; 5936 } else if ((ip_data->ip_ipv != IBT_CM_IP_IPV_V4) && 5937 (ip_data->ip_ipv != IBT_CM_IP_IPV_V6)) { 5938 IBTF_DPRINTF_L2(cmlog, "ibcm_verify_req_gids_and_svcid:" 5939 " Invalid IPV specified %d", ip_data->ip_ipv); 5940 ari_ip.ip_reason = IBT_ARI_IP_IPV; 5941 ari_ip.ip_suggested_version = IBT_CM_IP_IPV_V4; 5942 ari_ip.ip_suggested = B_TRUE; 5943 rdma_rej_mad = B_TRUE; 5944 } else { 5945 /* 5946 * Validate whether ip_addr specified are non-NULL. 5947 * 5948 * NOTE: 5949 * RDMA ULP which is servicing this SID, should validate 5950 * the correctness of srcip/dstip and accordingly post 5951 * REJ related to ibt_ari_ip_reason_t of 5952 * IBT_ARI_IP_SRC_ADDR, IBT_ARI_IP_DST_ADDR and 5953 * IBT_ARI_IP_UNKNOWN_ADDR. 5954 */ 5955 if (ip_data->ip_ipv == IBT_CM_IP_IPV_V4) { 5956 if (ip_data->ip_srcv4 == 0) { 5957 IBTF_DPRINTF_L2(cmlog, 5958 "ibcm_verify_req_gids_and_svcid: " 5959 "Invalid NULL V4 SrcIp specified"); 5960 rdma_rej_mad = B_TRUE; 5961 ari_ip.ip_reason = IBT_ARI_IP_SRC_ADDR; 5962 ari_ip.ip_suggested = B_TRUE; 5963 ari_ip.ip_suggested_version = 5964 IBT_CM_IP_IPV_V4; 5965 } else if (ip_data->ip_dstv4 == 0) { 5966 IBTF_DPRINTF_L2(cmlog, 5967 "ibcm_verify_req_gids_and_svcid: " 5968 "Invalid NULL V4 DstIp specified"); 5969 rdma_rej_mad = B_TRUE; 5970 ari_ip.ip_reason = IBT_ARI_IP_DST_ADDR; 5971 ari_ip.ip_suggested = B_TRUE; 5972 ari_ip.ip_suggested_version = 5973 IBT_CM_IP_IPV_V4; 5974 } 5975 } else if (ip_data->ip_ipv == IBT_CM_IP_IPV_V6) { 5976 if (IN6_IS_ADDR_UNSPECIFIED( 5977 &ip_data->ip_srcv6)) { 5978 IBTF_DPRINTF_L2(cmlog, 5979 "ibcm_verify_req_gids_and_svcid: " 5980 "Invalid NULL V6 SrcIp specified"); 5981 rdma_rej_mad = B_TRUE; 5982 ari_ip.ip_reason = IBT_ARI_IP_SRC_ADDR; 5983 ari_ip.ip_suggested = B_TRUE; 5984 ari_ip.ip_suggested_version = 5985 IBT_CM_IP_IPV_V6; 5986 } else if (IN6_IS_ADDR_UNSPECIFIED( 5987 &ip_data->ip_dstv6)) { 5988 IBTF_DPRINTF_L2(cmlog, 5989 "ibcm_verify_req_gids_and_svcid: " 5990 "Invalid NULL V6 DstIp specified"); 5991 rdma_rej_mad = B_TRUE; 5992 ari_ip.ip_reason = IBT_ARI_IP_DST_ADDR; 5993 ari_ip.ip_suggested = B_TRUE; 5994 ari_ip.ip_suggested_version = 5995 IBT_CM_IP_IPV_V6; 5996 } 5997 } 5998 /* TBD: IBT_ARI_IP_UNKNOWN_ADDR */ 5999 } 6000 if (rdma_rej_mad == B_TRUE) { 6001 ibt_ari_con_t cons_rej; 6002 6003 mutex_exit(&ibcm_svc_info_lock); 6004 6005 cons_rej.rej_ari_len = 1 + sizeof (ibt_ari_ip_t); 6006 cons_rej.rej_ari[0] = 0; /* Rejected by CM Layer */ 6007 bcopy(&ari_ip, &cons_rej.rej_ari[1], 6008 sizeof (ibt_ari_ip_t)); 6009 /* Send a REJ with CONSUMER REJ */ 6010 ibcm_post_rej_mad(statep, IBT_CM_CONSUMER, 6011 IBT_CM_FAILURE_REQ, &cons_rej, 6012 sizeof (ibt_ari_con_t)); 6013 return (IBCM_FAILURE); 6014 } 6015 } 6016 6017 /* find the best "bind" entry that enables this port */ 6018 6019 pkey = b2h16(cm_req_msgp->req_part_key); 6020 svc_bindp = NULL; 6021 tmp_bindp = svc_infop->svc_bind_list; 6022 while (tmp_bindp) { 6023 if (tmp_bindp->sbind_hcaguid == hca_guid && 6024 tmp_bindp->sbind_port == port_num) { 6025 if (gid.gid_guid == 6026 tmp_bindp->sbind_gid.gid_guid && 6027 gid.gid_prefix == 6028 tmp_bindp->sbind_gid.gid_prefix) { 6029 /* gid match => really good match */ 6030 svc_bindp = tmp_bindp; 6031 if (pkey == tmp_bindp->sbind_pkey) 6032 /* absolute best match */ 6033 break; 6034 } else if (svc_bindp == NULL) { 6035 /* port match => a good match */ 6036 svc_bindp = tmp_bindp; 6037 } 6038 } 6039 tmp_bindp = tmp_bindp->sbind_link; 6040 } 6041 if (svc_bindp == NULL) { /* port not enabled for this SID */ 6042 mutex_exit(&ibcm_svc_info_lock); 6043 IBTF_DPRINTF_L2(cmlog, 6044 "ibcm_verify_req_gids_and_svcid: statep 0x%p " 6045 "no binding found", statep); 6046 ibcm_post_rej_mad(statep, 6047 IBT_CM_INVALID_SID, IBT_CM_FAILURE_REQ, NULL, 0); 6048 return (IBCM_FAILURE); 6049 } 6050 /* copy the GID in case we need it in REJ below */ 6051 gid.gid_prefix = b2h64(svc_bindp->sbind_gid.gid_prefix); 6052 gid.gid_guid = b2h64(svc_bindp->sbind_gid.gid_guid); 6053 6054 statep->state_cm_private = svc_bindp->sbind_cm_private; 6055 statep->state_svc_infop = svc_infop; 6056 statep->cm_handler = svc_infop->svc_rc_handler; 6057 if (reject_reason == IBT_CM_SUCCESS) 6058 IBCM_SVC_INCR(svc_infop); 6059 mutex_exit(&ibcm_svc_info_lock); 6060 6061 /* 6062 * If the service id is valid, but gid in REQ is invalid, 6063 * then send a REJ with invalid gid 6064 * For Invalid primary gid, the ARI field is filled with 6065 * with gid from svcinfo 6066 * For invalid prim/alt gid reject, CM uses one of the gids 6067 * registered in ARI. 6068 * For invalid prim/alt lid reject, CM uses the base lid in ARI 6069 */ 6070 if (reject_reason != IBT_CM_SUCCESS) { 6071 6072 switch (reject_reason) { 6073 6074 case IBT_CM_PRIM_GID : 6075 case IBT_CM_ALT_GID : 6076 ibcm_post_rej_mad(statep, 6077 reject_reason, IBT_CM_FAILURE_REQ, 6078 &gid, sizeof (ib_gid_t)); 6079 break; 6080 6081 case IBT_CM_PRIM_LID : 6082 case IBT_CM_ALT_LID : 6083 6084 lid = h2b16(port.hp_base_lid); 6085 ibcm_post_rej_mad(statep, 6086 reject_reason, IBT_CM_FAILURE_REQ, 6087 &lid, sizeof (ib_lid_t)); 6088 break; 6089 } 6090 6091 return (IBCM_FAILURE); 6092 } 6093 6094 /* Service, primary/alt gid and lid are all valid */ 6095 6096 return (IBCM_SUCCESS); 6097 } 6098 6099 /* 6100 * ibcm_cep_state_req: 6101 * QP state transition function called for an incoming REQ on passive side 6102 * LIDs and GIDs should be maintained and validated by the client handler 6103 * 6104 * INPUTS: 6105 * statep - state pointer 6106 * cm_req_msgp - REQ message pointer 6107 * reject_reason - Rejection reason See Section 12.6.7.2 rev1.0a IB Spec 6108 * arej_info_len - Additional Rejection reason info length 6109 * 6110 * RETURN VALUE: IBCM_SEND_REP/IBCM_SEND_REJ 6111 */ 6112 ibcm_status_t 6113 ibcm_cep_state_req(ibcm_state_data_t *statep, ibcm_req_msg_t *cm_req_msgp, 6114 ibt_cm_reason_t *reject_reason, uint8_t *arej_len) 6115 { 6116 void *priv_data = NULL; 6117 ibt_cm_event_t event; 6118 ibt_cm_status_t cb_status; 6119 ibcm_status_t status; 6120 ibt_cm_return_args_t ret_args; 6121 ibcm_clnt_reply_info_t clnt_info; 6122 6123 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: statep 0x%p", statep); 6124 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: SID 0x%lX", 6125 b2h64(cm_req_msgp->req_svc_id)); 6126 /* client handler should be valid */ 6127 ASSERT(statep->cm_handler != NULL); 6128 6129 bzero(&event, sizeof (event)); 6130 6131 /* Fill in ibt_cm_event_t */ 6132 event.cm_type = IBT_CM_EVENT_REQ_RCV; 6133 event.cm_session_id = statep; 6134 IBCM_EVT_REQ(event).req_service_id = b2h64(cm_req_msgp->req_svc_id); 6135 IBCM_EVT_REQ(event).req_transport = 6136 ((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] >> 1 & 0x3; 6137 IBCM_EVT_REQ(event).req_timeout = ibt_ib2usec( 6138 (((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] >> 3) & 0x1F); 6139 IBCM_EVT_REQ(event).req_retry_cnt = 6140 ((uint8_t *)&cm_req_msgp->req_starting_psn_plus)[3] & 0x7; 6141 IBCM_EVT_REQ(event).req_rnr_retry_cnt = cm_req_msgp->req_mtu_plus & 0x7; 6142 IBCM_EVT_REQ(event).req_pkey = b2h16(cm_req_msgp->req_part_key); 6143 IBCM_EVT_REQ(event).req_rdma_ra_in = 6144 ((uint8_t *)&cm_req_msgp->req_local_qpn_plus)[3]; 6145 IBCM_EVT_REQ(event).req_rdma_ra_out = 6146 ((uint8_t *)&cm_req_msgp->req_local_eec_no_plus)[3]; 6147 6148 /* Check for HCA limits for RDMA Resources */ 6149 if (IBCM_EVT_REQ(event).req_rdma_ra_in > 6150 statep->hcap->hca_max_rdma_in_qp) { 6151 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p, REQ " 6152 "req_rdma_ra_in %d is greater than HCA Limit %d, resetting" 6153 "it to HCA limit", statep, 6154 IBCM_EVT_REQ(event).req_rdma_ra_in, 6155 statep->hcap->hca_max_rdma_in_qp); 6156 IBCM_EVT_REQ(event).req_rdma_ra_in = 6157 statep->hcap->hca_max_rdma_in_qp; 6158 } 6159 6160 if (IBCM_EVT_REQ(event).req_rdma_ra_out > 6161 statep->hcap->hca_max_rdma_out_qp) { 6162 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p, REQ " 6163 "req_rdma_ra_out %d is greater than HCA Limit %d, resetting" 6164 "it to HCA limit", statep, 6165 IBCM_EVT_REQ(event).req_rdma_ra_out, 6166 statep->hcap->hca_max_rdma_out_qp); 6167 IBCM_EVT_REQ(event).req_rdma_ra_out = 6168 statep->hcap->hca_max_rdma_out_qp; 6169 } 6170 6171 /* Account for CM and other software delays */ 6172 if (IBCM_EVT_REQ(event).req_timeout > ibcm_sw_delay) { 6173 IBCM_EVT_REQ(event).req_timeout -= ibcm_sw_delay; 6174 IBTF_DPRINTF_L5(cmlog, "ibcm_cep_state_req: statep 0x%p" 6175 "Avail resp time %d (usec)", statep, 6176 IBCM_EVT_REQ(event).req_timeout); 6177 } else { 6178 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p " 6179 "REQ rem_resp_time < local sw delay 0x%x", statep, 6180 IBCM_EVT_REQ(event).req_timeout); 6181 6182 IBCM_EVT_REQ(event).req_timeout = 0; 6183 } 6184 6185 IBCM_EVT_REQ(event).req_prim_hca_port = statep->prim_port; 6186 IBCM_EVT_REQ(event).req_alt_hca_port = statep->alt_port; 6187 IBCM_EVT_REQ(event).req_hca_guid = statep->local_hca_guid; 6188 IBCM_EVT_REQ(event).req_remote_qpn = statep->remote_qpn; 6189 6190 if (((uint8_t *)&cm_req_msgp->req_remote_eecn_plus)[3] & 6191 IBT_CM_FLOW_CONTROL) 6192 IBCM_EVT_REQ(event).req_flags |= IBT_CM_FLOW_CONTROL; 6193 6194 if ((cm_req_msgp->req_max_cm_retries_plus >> 3) & 0x1) 6195 IBCM_EVT_REQ(event).req_flags |= IBT_CM_SRQ_EXISTS; 6196 6197 /* Initialize req.req_prim_addr */ 6198 ibcm_set_primary_adds_vect(statep, &IBCM_EVT_REQ(event).req_prim_addr, 6199 cm_req_msgp); 6200 6201 /* Initialize req.req_alternate_path if they exist */ 6202 if (b2h16(cm_req_msgp->req_alt_l_port_lid) != 0) { 6203 ibcm_set_alt_adds_vect(statep, 6204 &IBCM_EVT_REQ(event).req_alt_addr, cm_req_msgp); 6205 6206 /* Verify, alt path is not same as primary */ 6207 if (ibcm_compare_prim_alt_paths( 6208 &event.cm_event.req.req_prim_addr, 6209 &event.cm_event.req.req_alt_addr) == B_TRUE) { 6210 /* XXX New REJ code needed */ 6211 *reject_reason = IBT_CM_NO_RESC; 6212 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_req: statep 0x%p" 6213 " Alt and prim paths are same", statep); 6214 mutex_enter(&ibcm_svc_info_lock); 6215 IBCM_SVC_DECR(statep->state_svc_infop); 6216 mutex_exit(&ibcm_svc_info_lock); 6217 return (IBCM_SEND_REJ); 6218 } 6219 } 6220 6221 #ifdef NO_EEC_SUPPORT_YET 6222 IBCM_EVT_REQ(event).req_rdc_exists = cm_req_msgp->req_mtu_plus >> 3 & 1; 6223 IBCM_EVT_REQ(event).req_remote_eecn = 6224 b2h32(cm_req_msgp->req_remote_eecn_plus) >> 8; 6225 IBCM_EVT_REQ(event).req_local_eecn = 6226 b2h32(cm_req_msgp->req_local_eec_no_plus) >> 8; 6227 IBCM_EVT_REQ(event).req_remote_qkey = 6228 b2h32(cm_req_msgp->req_local_qkey); 6229 #endif 6230 6231 /* cm_req_msgp->req_private_data to event.cm_event.cm_priv_data */ 6232 event.cm_priv_data = cm_req_msgp->req_private_data; 6233 6234 event.cm_priv_data_len = IBT_REQ_PRIV_DATA_SZ; 6235 6236 /* 6237 * Allocate priv_data of size IBT_MAX_PRIV_DATA_SZ 6238 */ 6239 priv_data = kmem_zalloc(IBT_MAX_PRIV_DATA_SZ, KM_SLEEP); 6240 6241 bzero(&ret_args, sizeof (ret_args)); 6242 6243 /* Fill in the default values from REQ, that client can modify */ 6244 ret_args.cm_ret.rep.cm_rdma_ra_in = IBCM_EVT_REQ(event).req_rdma_ra_out; 6245 ret_args.cm_ret.rep.cm_rdma_ra_out = IBCM_EVT_REQ(event).req_rdma_ra_in; 6246 ret_args.cm_ret.rep.cm_rnr_retry_cnt = cm_req_msgp->req_mtu_plus & 0x7; 6247 6248 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REQ_RCVD_EVENT); 6249 6250 /* Invoke the client handler */ 6251 statep->req_msgp = cm_req_msgp; 6252 cb_status = statep->cm_handler(statep->state_cm_private, &event, 6253 &ret_args, priv_data, IBT_REP_PRIV_DATA_SZ); 6254 statep->req_msgp = NULL; 6255 6256 ibcm_insert_trace(statep, IBCM_TRACE_RET_REQ_RCVD_EVENT); 6257 6258 mutex_enter(&ibcm_svc_info_lock); 6259 IBCM_SVC_DECR(statep->state_svc_infop); 6260 mutex_exit(&ibcm_svc_info_lock); 6261 6262 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: Client handler returned %d" 6263 " statep 0x%p", cb_status, statep); 6264 6265 if (cb_status == IBT_CM_DEFER) { 6266 6267 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg)) 6268 6269 if (statep->defer_cm_msg == NULL) 6270 statep->defer_cm_msg = 6271 kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP); 6272 bcopy(cm_req_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE); 6273 6274 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg)) 6275 6276 /* 6277 * unblock any blocked cm proceed api calls. Do not access 6278 * statep after cv_signal 6279 */ 6280 mutex_enter(&statep->state_mutex); 6281 statep->clnt_proceed = IBCM_UNBLOCK; 6282 cv_broadcast(&statep->block_client_cv); 6283 mutex_exit(&statep->state_mutex); 6284 6285 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ); 6286 return (IBCM_DEFER); 6287 } 6288 6289 /* fail any blocked cm proceed api call - client bug */ 6290 mutex_enter(&statep->state_mutex); 6291 statep->clnt_proceed = IBCM_FAIL; 6292 cv_broadcast(&statep->block_client_cv); 6293 mutex_exit(&statep->state_mutex); 6294 6295 clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret; 6296 clnt_info.priv_data = priv_data; 6297 clnt_info.priv_data_len = ret_args.cm_ret_len; 6298 6299 status = 6300 ibcm_process_cep_req_cm_hdlr(statep, cb_status, 6301 &clnt_info, reject_reason, arej_len, cm_req_msgp); 6302 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ); 6303 return (status); 6304 } 6305 6306 /* 6307 * ibcm_process_cep_req_cm_hdlr: 6308 * Processes the response from client handler for an incoming REQ. 6309 */ 6310 ibcm_status_t 6311 ibcm_process_cep_req_cm_hdlr(ibcm_state_data_t *statep, 6312 ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info, 6313 ibt_cm_reason_t *reject_reason, uint8_t *arej_len, 6314 ibcm_req_msg_t *cm_req_msg) 6315 { 6316 ibt_status_t status; 6317 ibt_qp_query_attr_t qp_attrs; 6318 ibcm_state_data_t *old_statep; 6319 ibt_channel_hdl_t channel; 6320 ib_guid_t local_ca_guid; 6321 ibcm_rej_msg_t *rej_msgp; 6322 #ifdef NO_EEC_SUPPORT_YET 6323 ibt_eec_query_attr_t eec_attrs; 6324 #endif 6325 6326 if (cb_status == IBT_CM_DEFAULT) 6327 cb_status = IBT_CM_REJECT; 6328 6329 /* verify status */ 6330 if (cb_status == IBT_CM_ACCEPT) { 6331 *reject_reason = IBT_CM_SUCCESS; 6332 } else if (cb_status == IBT_CM_REJECT) { 6333 *reject_reason = IBT_CM_CONSUMER; 6334 } else if (cb_status == IBT_CM_REDIRECT_PORT) { 6335 *reject_reason = IBT_CM_PORT_REDIRECT; 6336 } else if (cb_status == IBT_CM_REDIRECT) { 6337 *reject_reason = IBT_CM_REDIRECT_CM; 6338 } else if (cb_status == IBT_CM_NO_CHANNEL) { 6339 *reject_reason = IBT_CM_NO_CHAN; 6340 } else if (cb_status == IBT_CM_NO_RESOURCE) { 6341 *reject_reason = IBT_CM_NO_RESC; 6342 } else { 6343 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p" 6344 " Client handler unexpected return %x", statep, cb_status); 6345 *reject_reason = IBT_CM_CONSUMER; 6346 } 6347 6348 /* client handler gave CM ok */ 6349 if (cb_status == IBT_CM_ACCEPT) { 6350 ibcm_rep_msg_t *rep_msgp = (ibcm_rep_msg_t *) 6351 IBCM_OUT_MSGP(statep->stored_msg); 6352 6353 6354 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep)) 6355 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp)) 6356 6357 /* 6358 * Check first if ret_args make sense. If not, bailout 6359 * here rather than going along and panicing later. 6360 */ 6361 channel = clnt_info->reply_event->rep.cm_channel; 6362 if (IBCM_INVALID_CHANNEL(channel)) { 6363 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6364 "statep 0x%p server's QP handle is NULL", statep); 6365 *reject_reason = IBT_CM_NO_CHAN; 6366 } 6367 6368 IBCM_GET_CHAN_PRIVATE(channel, old_statep); 6369 6370 if ((*reject_reason == IBT_CM_SUCCESS) && 6371 (old_statep != NULL)) { 6372 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6373 "statep 0x%p Channel being re-used on passive side", 6374 statep); 6375 *reject_reason = IBT_CM_NO_CHAN; 6376 } 6377 if (old_statep != NULL) 6378 IBCM_RELEASE_CHAN_PRIVATE(channel); 6379 6380 if (*reject_reason != IBT_CM_SUCCESS) { 6381 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6382 IBT_CM_FAILURE_REQ, *reject_reason, NULL, 0); 6383 return (IBCM_SEND_REJ); 6384 } 6385 6386 statep->channel = channel; 6387 status = ibt_query_qp(channel, &qp_attrs); 6388 6389 if (status != IBT_SUCCESS) { 6390 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6391 "statep %p ibt_query_qp failed %d", statep, status); 6392 *reject_reason = IBT_CM_NO_RESC; 6393 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6394 IBT_CM_FAILURE_REQ, IBT_CM_CI_FAILURE, NULL, 0); 6395 return (IBCM_SEND_REJ); 6396 } 6397 6398 if (qp_attrs.qp_info.qp_trans != IBT_RC_SRV) { 6399 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6400 "statep %p qp is not RC channel on server", statep); 6401 *reject_reason = IBT_CM_INVALID_SRV_TYPE; 6402 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6403 IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE, 6404 NULL, 0); 6405 return (IBCM_SEND_REJ); 6406 } 6407 6408 if (qp_attrs.qp_info.qp_state != IBT_STATE_INIT && 6409 statep->is_this_ofuv_chan == B_FALSE) { 6410 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6411 "qp state != INIT on server"); 6412 *reject_reason = IBT_CM_CHAN_INVALID_STATE; 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 } else if (statep->is_this_ofuv_chan && 6418 qp_attrs.qp_info.qp_state != IBT_STATE_RTR && 6419 qp_attrs.qp_info.qp_state != IBT_STATE_INIT) { 6420 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6421 "qp state != INIT or RTR on server"); 6422 *reject_reason = IBT_CM_CHAN_INVALID_STATE; 6423 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6424 IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE, 6425 NULL, 0); 6426 return (IBCM_SEND_REJ); 6427 } 6428 6429 if (statep->is_this_ofuv_chan && 6430 qp_attrs.qp_info.qp_state == IBT_STATE_RTR && 6431 qp_attrs.qp_info.qp_transport.rc.rc_path.cep_hca_port_num != 6432 statep->prim_port) { 6433 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6434 "QP port invalid"); 6435 *reject_reason = IBT_CM_CHAN_INVALID_STATE; 6436 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6437 IBT_CM_FAILURE_REQ, IBT_CM_CHAN_INVALID_STATE, 6438 NULL, 0); 6439 return (IBCM_SEND_REJ); 6440 } else if (statep->is_this_ofuv_chan && 6441 qp_attrs.qp_info.qp_state == IBT_STATE_RTR) { 6442 goto skip_init_trans; 6443 } 6444 6445 /* Init to Init, if required */ 6446 if (qp_attrs.qp_info.qp_transport.rc.rc_path.cep_hca_port_num != 6447 statep->prim_port) { 6448 6449 ibt_qp_info_t qp_info; 6450 ibt_cep_modify_flags_t cep_flags; 6451 6452 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6453 "chan 0x%p chan port %d", channel, 6454 qp_attrs.qp_info.qp_transport.rc.rc_path.\ 6455 cep_hca_port_num); 6456 6457 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6458 "chan 0x%p d path port %d", channel, 6459 statep->prim_port); 6460 6461 bzero(&qp_info, sizeof (qp_info)); 6462 qp_info.qp_trans = IBT_RC_SRV; 6463 qp_info.qp_state = IBT_STATE_INIT; 6464 qp_info.qp_transport.rc.rc_path.cep_hca_port_num = 6465 statep->prim_port; 6466 6467 cep_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PORT; 6468 6469 status = ibt_modify_qp(statep->channel, cep_flags, 6470 &qp_info, NULL); 6471 6472 if (status != IBT_SUCCESS) { 6473 IBTF_DPRINTF_L2(cmlog, 6474 "ibcm_process_cep_req_cm_hdlr: " 6475 "chan 0x%p ibt_modify_qp() = %d", channel, 6476 status); 6477 *reject_reason = IBT_CM_NO_RESC; 6478 6479 ibcm_insert_trace(statep, 6480 IBCM_TRACE_INIT_INIT_FAIL); 6481 6482 ibcm_handler_conn_fail(statep, 6483 IBT_CM_FAILURE_REJ_SENT, IBT_CM_FAILURE_REQ, 6484 IBT_CM_CI_FAILURE, NULL, 0); 6485 return (IBCM_SEND_REJ); 6486 } else { 6487 ibcm_insert_trace(statep, 6488 IBCM_TRACE_INIT_INIT); 6489 6490 IBTF_DPRINTF_L5(cmlog, 6491 "ibcm_process_cep_req_cm_hdlr: " 6492 "chan 0x%p ibt_modify_qp() = %d", channel, 6493 status); 6494 } 6495 } 6496 skip_init_trans: 6497 /* Do sanity tests even if we are skipping RTR */ 6498 6499 /* fill in the REP msg based on ret_args from client */ 6500 if (clnt_info->reply_event->rep.cm_rdma_ra_out > 6501 ((uint8_t *)&cm_req_msg->req_local_qpn_plus)[3]) { 6502 IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr " 6503 "statep 0x%p ERROR: InitiatorDepth(%d) is Greater " 6504 "than ResponderResource(%d)", statep, 6505 clnt_info->reply_event->rep.cm_rdma_ra_out, 6506 ((uint8_t *)&cm_req_msg->req_local_qpn_plus)[3]); 6507 *reject_reason = IBT_CM_NOT_SUPPORTED; 6508 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6509 IBT_CM_FAILURE_REQ, IBT_CM_NOT_SUPPORTED, NULL, 0); 6510 return (IBCM_SEND_REJ); 6511 } 6512 6513 /* Check for HCA limits for RDMA Resources */ 6514 if (clnt_info->reply_event->rep.cm_rdma_ra_in > 6515 statep->hcap->hca_max_rdma_in_qp) { 6516 IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr: " 6517 "statep %p, ERROR: client specified rdma_ra_in %d " 6518 "is greater than HCA Limit %d, rejecting MAD", 6519 statep, clnt_info->reply_event->rep.cm_rdma_ra_in, 6520 statep->hcap->hca_max_rdma_in_qp); 6521 *reject_reason = IBT_CM_NOT_SUPPORTED; 6522 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6523 IBT_CM_FAILURE_REQ, IBT_CM_NOT_SUPPORTED, NULL, 0); 6524 return (IBCM_SEND_REJ); 6525 } 6526 6527 if (clnt_info->reply_event->rep.cm_rdma_ra_out > 6528 statep->hcap->hca_max_rdma_out_qp) { 6529 IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr: " 6530 "statep %p, ERROR: client specified rdma_ra_out %d " 6531 "is greater than HCA Limit %d, rejecting MAD", 6532 statep, clnt_info->reply_event->rep.cm_rdma_ra_out, 6533 statep->hcap->hca_max_rdma_out_qp); 6534 *reject_reason = IBT_CM_NOT_SUPPORTED; 6535 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6536 IBT_CM_FAILURE_REQ, IBT_CM_NOT_SUPPORTED, NULL, 0); 6537 return (IBCM_SEND_REJ); 6538 } 6539 6540 rep_msgp->rep_resp_resources = 6541 clnt_info->reply_event->rep.cm_rdma_ra_in; 6542 rep_msgp->rep_initiator_depth = 6543 clnt_info->reply_event->rep.cm_rdma_ra_out; 6544 6545 /* IBT_CM_FLOW_CONTROL is always set by default. */ 6546 rep_msgp->rep_target_delay_plus |= IBT_CM_FLOW_CONTROL; 6547 6548 rep_msgp->rep_rnr_retry_cnt_plus = 6549 (clnt_info->reply_event->rep.cm_rnr_retry_cnt & 0x7) << 5; 6550 6551 /* 6552 * Check out whether SRQ is associated with this channel. 6553 * If yes, then set the appropriate bit. 6554 */ 6555 if (qp_attrs.qp_srq != NULL) { 6556 rep_msgp->rep_rnr_retry_cnt_plus |= (1 << 4); 6557 } 6558 6559 local_ca_guid = h2b64(statep->local_hca_guid); 6560 bcopy(&local_ca_guid, rep_msgp->rep_local_ca_guid, 6561 sizeof (ib_guid_t)); 6562 6563 if (statep->is_this_ofuv_chan && 6564 qp_attrs.qp_info.qp_state == IBT_STATE_RTR) 6565 goto skip_rtr_trans; 6566 6567 /* Transition QP from Init to RTR state */ 6568 if (ibcm_invoke_qp_modify(statep, cm_req_msg, rep_msgp) != 6569 IBT_SUCCESS) { 6570 6571 IBTF_DPRINTF_L2(cmlog, "ibcm_process_req_cm_hdlr " 6572 "statep 0x%p ibcm_invoke_qp_modify failed because " 6573 "of invalid data", statep); 6574 *reject_reason = IBT_CM_NO_RESC; 6575 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6576 IBT_CM_FAILURE_REQ, IBT_CM_CI_FAILURE, NULL, 0); 6577 return (IBCM_SEND_REJ); 6578 } 6579 skip_rtr_trans: 6580 6581 /* 6582 * Link statep and channel, once CM determines it is 6583 * post REP definitely. 6584 */ 6585 IBCM_SET_CHAN_PRIVATE(statep->channel, statep); 6586 6587 /* 6588 * Fill up the REP fields from ret_args 6589 * failover status, from ret_args 6590 * 6591 * Fill up local QPN and EECN from ret_args->channel 6592 */ 6593 6594 /* fill in REP msg bytes Qkey, Starting PSN, 12-15, and 16-19 */ 6595 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: " 6596 "qp_info.qp_state = %x", qp_attrs.qp_info.qp_state); 6597 6598 rep_msgp->rep_local_qpn_plus = h2b32(qp_attrs.qp_qpn << 8); 6599 6600 statep->local_qpn = qp_attrs.qp_qpn; 6601 6602 switch (qp_attrs.qp_info.qp_trans) { 6603 case IBT_RD_SRV: 6604 rep_msgp->rep_local_qkey = h2b32( 6605 qp_attrs.qp_info.qp_transport.rd.rd_qkey); 6606 break; 6607 case IBT_RC_SRV: 6608 rep_msgp->rep_starting_psn_plus = 6609 h2b32(IBCM_QP_RC(qp_attrs).rc_rq_psn << 8); 6610 break; 6611 case IBT_UC_SRV: 6612 rep_msgp->rep_starting_psn_plus = 6613 h2b32(IBCM_QP_UC(qp_attrs).uc_sq_psn << 8); 6614 break; 6615 } 6616 6617 #ifdef NO_EEC_SUPPORT_YET 6618 if (ret_args.cm_channel.ch_eec != NULL) { 6619 status = ibt_query_eec(ret_args.cm_channel.ch_eec, 6620 &eec_attrs); 6621 if (status == IBT_SUCCESS) { 6622 rep_msgp->rep_local_eecn_plus = 6623 h2b32(((uint32_t)eec_attrs.eec_eecn << 8)); 6624 } 6625 } 6626 #endif 6627 6628 /* figure out Target ACK delay */ 6629 rep_msgp->rep_target_delay_plus |= (status == IBT_SUCCESS) ? 6630 statep->hcap->hca_ack_delay << 3 : 0; 6631 6632 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr:statep %p " 6633 "REP priv len %x", statep, clnt_info->priv_data_len); 6634 /* Copy PrivateData from priv_data */ 6635 if (clnt_info->priv_data_len != 0) { 6636 bcopy(clnt_info->priv_data, rep_msgp->rep_private_data, 6637 min(IBT_REP_PRIV_DATA_SZ, 6638 clnt_info->priv_data_len)); 6639 } 6640 6641 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep)) 6642 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp)) 6643 6644 return (IBCM_SEND_REP); 6645 } 6646 6647 /* REJ message */ 6648 rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg); 6649 6650 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p REJ " 6651 "priv len %x", statep, clnt_info->priv_data_len); 6652 6653 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp)) 6654 6655 /* if priv_data_len != 0 use priv_data to copy back to rej_priv_data */ 6656 if (clnt_info->priv_data_len != 0) { 6657 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data, 6658 min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len)); 6659 } 6660 6661 if (cb_status == IBT_CM_REDIRECT_PORT) { 6662 ib_gid_t tgid; 6663 6664 tgid.gid_guid = 6665 h2b64(clnt_info->reply_event->rej.ari_gid.gid_guid); 6666 tgid.gid_prefix = 6667 h2b64(clnt_info->reply_event->rej.ari_gid.gid_prefix); 6668 6669 *arej_len = sizeof (ib_gid_t); 6670 bcopy(&tgid, &rej_msgp->rej_addl_rej_info, sizeof (ib_gid_t)); 6671 6672 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: ari_gid= " 6673 "%llX:%llX", tgid.gid_prefix, tgid.gid_guid); 6674 6675 } else if (cb_status == IBT_CM_REDIRECT) { 6676 ibcm_classportinfo_msg_t tclp; 6677 6678 ibcm_init_clp_to_mad(&tclp, 6679 &clnt_info->reply_event->rej.ari_redirect); 6680 bcopy(&tclp, rej_msgp->rej_addl_rej_info, sizeof (tclp)); 6681 6682 *arej_len = sizeof (ibcm_classportinfo_msg_t); 6683 6684 } else if (cb_status == IBT_CM_REJECT) { 6685 6686 /* Fill up the REJ fields, from ret_args */ 6687 *arej_len = min( 6688 clnt_info->reply_event->rej.ari_consumer.rej_ari_len, 6689 IBT_CM_ADDL_REJ_LEN); 6690 bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari, 6691 &rej_msgp->rej_addl_rej_info, *arej_len); 6692 6693 /* 6694 * RDMA IP REQ was passed up to the ULP, the ULP decided to do 6695 * a "normal" consumer REJ, by the returning IBT_CM_REJECT in 6696 * the cm handler. 6697 * CM has to do some extra stuff too, it has to 6698 * a) return REJ code 28 (consumer) and b) put 0x1 in the first 6699 * byte of the ARI data, to indicate that this is a RDMA aware 6700 * ULP that is doing a consumer reject. The ULP should have 6701 * put its consumer specific data into ibt_arej_info_t(9s) at 6702 * byte 1 of the rej_ari[] array. 6703 */ 6704 if (((statep->svcid & IB_SID_IPADDR_PREFIX_MASK) == 0) && 6705 (statep->svcid & IB_SID_IPADDR_PREFIX)) { 6706 rej_msgp->rej_addl_rej_info[0] = 1; 6707 } 6708 } 6709 6710 rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6; 6711 6712 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp)) 6713 6714 return (IBCM_SEND_REJ); 6715 } 6716 6717 /* 6718 * ibcm_cep_state_rep: 6719 * QP state transition function called for an incoming REP on active side 6720 * 6721 * INPUTS: 6722 * statep - state pointer 6723 * cm_rep_msg - REP message pointer 6724 * reject_reason - Rejection reason See Section 12.6.7.2 rev1.0a IB Spec 6725 * 6726 * RETURN VALUE: 6727 */ 6728 ibcm_status_t 6729 ibcm_cep_state_rep(ibcm_state_data_t *statep, ibcm_rep_msg_t *cm_rep_msgp, 6730 ibt_cm_reason_t *reject_reason, uint8_t *arej_len) 6731 { 6732 void *priv_data = NULL; 6733 ibcm_status_t rval = IBCM_SEND_RTU; 6734 ibt_cm_event_t event; 6735 ibt_cm_status_t cb_status = IBT_CM_ACCEPT; 6736 ibt_cm_return_args_t ret_args; 6737 ibcm_clnt_reply_info_t clnt_info; 6738 uint8_t req_init_depth; 6739 6740 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rep: statep 0x%p", statep); 6741 6742 /* Check first if client handler is valid */ 6743 if (statep->cm_handler != NULL) { 6744 /* initialize fields in ibt_cm_event_t */ 6745 bzero(&event, sizeof (event)); 6746 event.cm_type = IBT_CM_EVENT_REP_RCV; 6747 event.cm_channel = statep->channel; 6748 event.cm_session_id = statep; 6749 6750 IBCM_EVT_REP(event).rep_rdma_ra_in = 6751 cm_rep_msgp->rep_initiator_depth; 6752 req_init_depth = 6753 ((uint8_t *)&(((ibcm_req_msg_t *)IBCM_OUT_MSGP( 6754 statep->stored_msg))->req_local_eec_no_plus))[3]; 6755 IBCM_EVT_REP(event).rep_rdma_ra_out = 6756 min(cm_rep_msgp->rep_resp_resources, req_init_depth); 6757 6758 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rep: statep 0x%p, " 6759 "InitDepth %d, RespResr %d", statep, 6760 cm_rep_msgp->rep_initiator_depth, 6761 IBCM_EVT_REP(event).rep_rdma_ra_out); 6762 6763 IBCM_EVT_REP(event).rep_service_time = ibt_ib2usec( 6764 ((uint8_t *)&(((ibcm_req_msg_t *)IBCM_OUT_MSGP( 6765 statep->stored_msg))->req_starting_psn_plus))[3] >> 3); 6766 6767 IBCM_EVT_REP(event).rep_service_time -= 6768 2 * statep->pkt_life_time - ibcm_sw_delay; 6769 6770 IBCM_EVT_REP(event).rep_failover_status = 6771 cm_rep_msgp->rep_target_delay_plus >> 1 & 3; 6772 6773 if (cm_rep_msgp->rep_target_delay_plus & 0x1) 6774 IBCM_EVT_REP(event).rep_flags |= IBT_CM_FLOW_CONTROL; 6775 6776 if ((cm_rep_msgp->rep_rnr_retry_cnt_plus >> 4) & 0x1) 6777 IBCM_EVT_REP(event).rep_flags |= IBT_CM_SRQ_EXISTS; 6778 6779 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rep: statep 0x%p " 6780 "rep_service_time %d", statep, 6781 IBCM_EVT_REP(event).rep_service_time); 6782 6783 event.cm_priv_data = &(cm_rep_msgp->rep_private_data[0]); 6784 event.cm_priv_data_len = IBT_REP_PRIV_DATA_SZ; 6785 6786 /* 6787 * Allocate priv_data of size IBT_MAX_PRIV_DATA_SZ 6788 */ 6789 priv_data = kmem_zalloc(IBT_MAX_PRIV_DATA_SZ, KM_SLEEP); 6790 bzero(&ret_args, sizeof (ret_args)); 6791 6792 6793 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REP_RCVD_EVENT); 6794 6795 /* invoke the CM handler */ 6796 cb_status = statep->cm_handler(statep->state_cm_private, &event, 6797 &ret_args, priv_data, IBT_RTU_PRIV_DATA_SZ); 6798 6799 ibcm_insert_trace(statep, IBCM_TRACE_RET_REP_RCVD_EVENT); 6800 6801 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rep: statep 0x%p " 6802 "Client handler returned %x", statep, cb_status); 6803 6804 if (cb_status == IBT_CM_DEFER) { 6805 if (statep->defer_cm_msg == NULL) 6806 statep->defer_cm_msg = 6807 kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP); 6808 bcopy(cm_rep_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE); 6809 6810 /* unblock any blocked cm proceed api calls */ 6811 mutex_enter(&statep->state_mutex); 6812 statep->clnt_proceed = IBCM_UNBLOCK; 6813 cv_broadcast(&statep->block_client_cv); 6814 mutex_exit(&statep->state_mutex); 6815 6816 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ); 6817 return (IBCM_DEFER); 6818 } 6819 } 6820 6821 /* fail any blocked cm proceed api calls - client bug */ 6822 mutex_enter(&statep->state_mutex); 6823 statep->clnt_proceed = IBCM_FAIL; 6824 cv_broadcast(&statep->block_client_cv); 6825 mutex_exit(&statep->state_mutex); 6826 6827 clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret; 6828 clnt_info.priv_data = priv_data; 6829 clnt_info.priv_data_len = ret_args.cm_ret_len; 6830 6831 rval = 6832 ibcm_process_cep_rep_cm_hdlr(statep, cb_status, &clnt_info, 6833 reject_reason, arej_len, cm_rep_msgp); 6834 6835 if (priv_data != NULL) 6836 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ); 6837 return (rval); 6838 } 6839 6840 6841 /* 6842 * ibcm_process_cep_rep_cm_hdlr: 6843 * Processes the response from client handler for an incoming REP. 6844 */ 6845 ibcm_status_t 6846 ibcm_process_cep_rep_cm_hdlr(ibcm_state_data_t *statep, 6847 ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info, 6848 ibt_cm_reason_t *reject_reason, uint8_t *arej_len, 6849 ibcm_rep_msg_t *cm_rep_msgp) 6850 { 6851 ibcm_status_t rval = IBCM_SEND_RTU; 6852 ibcm_rej_msg_t *rej_msgp; 6853 6854 if (cb_status == IBT_CM_DEFAULT) 6855 cb_status = IBT_CM_ACCEPT; 6856 6857 if (cb_status == IBT_CM_REJECT) { 6858 *reject_reason = IBT_CM_CONSUMER; 6859 } else if (cb_status == IBT_CM_REDIRECT_PORT) { 6860 *reject_reason = IBT_CM_PORT_REDIRECT; 6861 } else if (cb_status == IBT_CM_REDIRECT) { 6862 *reject_reason = IBT_CM_REDIRECT_CM; 6863 } else if (cb_status == IBT_CM_NO_RESOURCE) { 6864 *reject_reason = IBT_CM_NO_RESC; 6865 } else if (cb_status != IBT_CM_ACCEPT) { 6866 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep " 6867 "0x%p, Client handler returned unexpected value %d", 6868 statep, cb_status); 6869 *reject_reason = IBT_CM_CONSUMER; 6870 } else 6871 *reject_reason = IBT_CM_SUCCESS; 6872 6873 6874 /* We come here if status is ACCEPT or CM handler is NULL */ 6875 if (cb_status == IBT_CM_ACCEPT) { 6876 ib_time_t time; 6877 6878 time = ibt_usec2ib(statep->pkt_life_time * 2 + 6879 ibt_ib2usec(cm_rep_msgp->rep_target_delay_plus >> 3)); 6880 6881 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p" 6882 " active cep_timeout(usec) 0x%x ", statep, time); 6883 6884 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p" 6885 " passive hca_ack_delay(ib_time) = 0x%x, ", statep, 6886 cm_rep_msgp->rep_target_delay_plus >> 3); 6887 6888 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p" 6889 " rnr_retry_cnt = 0x%x", statep, 6890 cm_rep_msgp->rep_rnr_retry_cnt_plus >> 5); 6891 6892 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep)) 6893 statep->starting_psn = 6894 b2h32(cm_rep_msgp->rep_starting_psn_plus) >> 8; 6895 6896 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep)) 6897 6898 /* Call IBTL CM's qp modify function from Init to RTR */ 6899 if (ibcm_invoke_qp_modify(statep, 6900 (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg), 6901 cm_rep_msgp) != IBT_SUCCESS) { 6902 6903 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: " 6904 "statep %p, ibcm_invoke_qp_modify to RTR failed", 6905 statep); 6906 *reject_reason = IBT_CM_NO_RESC; 6907 /* 6908 * Call modify qp function from RTR to RTS 6909 * RDMA initiator depth on active is same as negotiated 6910 * passive REP's responder resources 6911 */ 6912 } else if (ibcm_invoke_rtu_qp_modify(statep, time, cm_rep_msgp) 6913 != IBT_SUCCESS) { 6914 6915 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: " 6916 "statep %p ibcm_invoke_rtu_qp_modify to RTS failed", 6917 statep); 6918 (void) ibcm_cep_to_error_state(statep); 6919 *reject_reason = IBT_CM_NO_RESC; 6920 } 6921 6922 if (*reject_reason == IBT_CM_NO_RESC) { 6923 6924 /* Disassociate statep and QP */ 6925 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL); 6926 6927 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6928 IBT_CM_FAILURE_REP, IBT_CM_CI_FAILURE, NULL, 0); 6929 return (IBCM_SEND_REJ); /* send REJ */ 6930 } 6931 6932 if (clnt_info->priv_data_len != 0) { 6933 ibcm_rtu_msg_t *rtu_msgp; 6934 rtu_msgp = (ibcm_rtu_msg_t *) 6935 IBCM_OUT_MSGP(statep->stored_msg); 6936 bcopy(clnt_info->priv_data, rtu_msgp->rtu_private_data, 6937 min(IBT_RTU_PRIV_DATA_SZ, 6938 clnt_info->priv_data_len)); 6939 } 6940 6941 *reject_reason = IBT_CM_SUCCESS; 6942 return (rval); 6943 } 6944 6945 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp)) 6946 6947 /* Fill up the REJ fields, from ret_args */ 6948 rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg); 6949 rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REP << 6; 6950 6951 /* if priv_len != 0 use priv_data to copy back to rej_priv_data */ 6952 if (clnt_info->priv_data_len != 0) 6953 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data, 6954 min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len)); 6955 6956 if (clnt_info->reply_event != NULL) 6957 *arej_len = 6958 min(clnt_info->reply_event->rej.ari_consumer.rej_ari_len, 6959 IBT_CM_ADDL_REJ_LEN); 6960 6961 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej)) 6962 6963 if (*arej_len != 0) /* asserts that clnt_info->reply_event != 0 */ 6964 bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari, 6965 &rej_msgp->rej_addl_rej_info, *arej_len); 6966 6967 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej)) 6968 6969 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp)) 6970 6971 rval = IBCM_SEND_REJ; 6972 6973 /* Disassociate statep and QP */ 6974 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL); 6975 6976 /* callback client, to enable client to do resource cleanup */ 6977 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 6978 IBT_CM_FAILURE_REP, *reject_reason, NULL, 0); 6979 6980 return (rval); 6981 } 6982 6983 /* 6984 * ibcm_invoke_rtu_qp_modify: 6985 * Helper function to modify QP for RTU only called from 6986 * ibcm_cep_state_rtu() and ibcm_cep_send_rtu() 6987 * 6988 * INPUTS: 6989 * statep - connection state pointer 6990 * 6991 * RETURN VALUE: 6992 */ 6993 static ibt_status_t 6994 ibcm_invoke_rtu_qp_modify(ibcm_state_data_t *statep, ib_time_t timeout, 6995 ibcm_rep_msg_t *rep_msg) 6996 { 6997 ibt_status_t status; 6998 ibt_qp_info_t qp_info; 6999 ibt_cep_modify_flags_t cep_flags = IBT_CEP_SET_RTR_RTS; 7000 7001 /* Start filling up ibt_qp_info_t. */ 7002 bzero(&qp_info, sizeof (qp_info)); 7003 qp_info.qp_trans = ibtl_cm_get_chan_type(statep->channel); 7004 qp_info.qp_current_state = IBT_STATE_RTR; 7005 7006 switch (qp_info.qp_trans) { 7007 case IBT_RC_SRV: 7008 IBCM_QPINFO_RC_PATH(qp_info).cep_timeout = timeout; 7009 IBCM_QPINFO_RC(qp_info).rc_retry_cnt = statep->cep_retry_cnt; 7010 IBCM_QPINFO_RC(qp_info).rc_rnr_retry_cnt = 7011 statep->local_qp_rnr_cnt; 7012 IBCM_QPINFO_RC(qp_info).rc_sq_psn = statep->starting_psn; 7013 7014 if (statep->mode == IBCM_ACTIVE_MODE) { 7015 IBCM_QPINFO_RC(qp_info).rc_rdma_ra_out = 7016 rep_msg->rep_resp_resources; 7017 } else { 7018 IBCM_QPINFO_RC(qp_info).rc_rdma_ra_out = 7019 rep_msg->rep_initiator_depth; 7020 } 7021 if (statep->alt_port && 7022 (((rep_msg->rep_target_delay_plus >> 1) & 0x3) == 7023 IBT_CM_FAILOVER_ACCEPT)) { 7024 /* failover was accepted */ 7025 cep_flags |= IBT_CEP_SET_MIG; 7026 IBCM_QPINFO_RC(qp_info).rc_mig_state = 7027 IBT_STATE_REARMED; 7028 } 7029 7030 break; 7031 /* XXX RD? */ 7032 case IBT_UC_SRV: 7033 IBCM_QPINFO_UC_PATH(qp_info).cep_timeout = timeout; 7034 break; 7035 default: 7036 IBTF_DPRINTF_L2(cmlog, "ibcm_invoke_rtu_qp_modify: " 7037 "unknow svc_type = %x", qp_info.qp_trans); 7038 break; 7039 } 7040 7041 /* Call modify_qp */ 7042 status = ibt_modify_qp(statep->channel, cep_flags, &qp_info, NULL); 7043 IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_rtu_qp_modify: statep 0x%p " 7044 "modify qp status = %d", statep, status); 7045 7046 if (status == IBT_SUCCESS) 7047 ibcm_insert_trace(statep, IBCM_TRACE_RTR_RTS); 7048 else 7049 ibcm_insert_trace(statep, IBCM_TRACE_RTR_RTS_FAIL); 7050 7051 #ifdef DEBUG 7052 print_modify_qp("RTR to RTS", statep->channel, cep_flags, &qp_info); 7053 7054 if (statep->channel != NULL) { 7055 ibt_qp_query_attr_t qp_attrs; 7056 7057 (void) ibt_query_qp(statep->channel, &qp_attrs); 7058 IBTF_DPRINTF_L4(cmlog, "ibcm_invoke_rtu_qp_modify: " 7059 "qp_info.qp_state = %x", qp_attrs.qp_info.qp_state); 7060 } 7061 #endif 7062 return (status); 7063 } 7064 7065 7066 /* 7067 * ibcm_cep_state_rtu: 7068 * QP state transition function called for an incoming RTU 7069 * on passive side. 7070 * 7071 * INPUTS: 7072 * statep - connection state pointer 7073 * cm_rtu_msg - RTU message pointer 7074 * 7075 */ 7076 void 7077 ibcm_cep_state_rtu(ibcm_state_data_t *statep, ibcm_rtu_msg_t *cm_rtu_msgp) 7078 { 7079 ibt_status_t status; 7080 ibt_cm_event_t event; 7081 ibcm_rep_msg_t *rep_msgp = (ibcm_rep_msg_t *) 7082 IBCM_OUT_MSGP(statep->stored_msg); 7083 7084 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rtu: statep 0x%p", statep); 7085 7086 ASSERT(statep->channel != NULL); 7087 7088 /* RDMA initiator depth taken from negotiated REP values */ 7089 status = ibcm_invoke_rtu_qp_modify(statep, 7090 ibt_usec2ib(statep->remote_ack_delay), rep_msgp); 7091 7092 if (status != IBT_SUCCESS) { 7093 7094 (void) ibcm_cep_to_error_state(statep); 7095 /* 7096 * Disassociate statep and QP, as there is a 7097 * QP associated with this statep. 7098 */ 7099 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL); 7100 7101 ibcm_post_rej_mad(statep, IBT_CM_NO_RESC, 7102 IBT_CM_FAILURE_UNKNOWN, NULL, 0); 7103 /* 7104 * Invoke CM handler, so client/server can do 7105 * resource cleanup. No private data can be returned here 7106 */ 7107 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT, 7108 IBT_CM_FAILURE_UNKNOWN, IBT_CM_NO_RESC, NULL, 0); 7109 7110 /* unblock any pending DREQ threads */ 7111 mutex_enter(&statep->state_mutex); 7112 statep->cep_in_rts = IBCM_FAIL; 7113 cv_broadcast(&statep->block_mad_cv); 7114 mutex_exit(&statep->state_mutex); 7115 return; 7116 } 7117 7118 mutex_enter(&statep->state_mutex); 7119 statep->state = IBCM_STATE_ESTABLISHED; 7120 ibtl_cm_chan_is_open(statep->channel); 7121 mutex_exit(&statep->state_mutex); 7122 7123 /* invoke the CM handler */ 7124 ASSERT(statep->cm_handler != NULL); 7125 7126 bzero(&event, sizeof (event)); 7127 event.cm_channel = statep->channel; 7128 event.cm_session_id = NULL; 7129 7130 event.cm_type = IBT_CM_EVENT_CONN_EST; 7131 if (cm_rtu_msgp != NULL) { 7132 event.cm_priv_data = &(cm_rtu_msgp->rtu_private_data[0]); 7133 event.cm_priv_data_len = IBT_RTU_PRIV_DATA_SZ; 7134 } 7135 7136 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_EST_EVENT); 7137 7138 (void) statep->cm_handler(statep->state_cm_private, &event, NULL, 7139 NULL, 0); 7140 7141 ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_EST_EVENT); 7142 if (ibcm_enable_trace & 4) 7143 ibcm_dump_conn_trace(statep); 7144 else 7145 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_state_rtu CONN_EST Channel %p", 7146 statep->channel); 7147 7148 /* unblock any pending DREQ threads */ 7149 mutex_enter(&statep->state_mutex); 7150 statep->cep_in_rts = IBCM_UNBLOCK; 7151 cv_broadcast(&statep->block_mad_cv); 7152 mutex_exit(&statep->state_mutex); 7153 } 7154 7155 7156 /* 7157 * ibcm_cep_send_rtu: 7158 * QP state transition function called for an outgoing RTU 7159 * on active side. 7160 * 7161 * INPUTS: 7162 * statep - connection state pointer 7163 * 7164 * RETURN VALUE: 7165 */ 7166 void 7167 ibcm_cep_send_rtu(ibcm_state_data_t *statep) 7168 { 7169 /* invoke the CM handler */ 7170 if (statep->cm_handler) { 7171 ibt_cm_event_t event; 7172 7173 bzero(&event, sizeof (event)); 7174 event.cm_type = IBT_CM_EVENT_CONN_EST; 7175 event.cm_channel = statep->channel; 7176 event.cm_session_id = NULL; 7177 event.cm_priv_data = NULL; 7178 event.cm_priv_data_len = 0; 7179 7180 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_EST_EVENT); 7181 7182 (void) statep->cm_handler(statep->state_cm_private, &event, 7183 NULL, NULL, 0); 7184 7185 ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_EST_EVENT); 7186 7187 } else { 7188 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_send_rtu: cm_handler NULL"); 7189 } 7190 if (ibcm_enable_trace & 4) 7191 ibcm_dump_conn_trace(statep); 7192 else 7193 IBTF_DPRINTF_L2(cmlog, "ibcm_cep_send_rtu CONN_EST Channel %p", 7194 statep->channel); 7195 7196 /* unblock any pending DREQ threads */ 7197 mutex_enter(&statep->state_mutex); 7198 statep->cep_in_rts = IBCM_UNBLOCK; 7199 cv_broadcast(&statep->block_mad_cv); 7200 mutex_exit(&statep->state_mutex); 7201 } 7202 7203 7204 /* 7205 * ibcm_cep_to_error_state: 7206 * CEP state transition function. Changes state to IBT_STATE_ERROR 7207 * 7208 * INPUTS: 7209 * statep - connection state pointer 7210 * 7211 * RETURN VALUE: 7212 * IBT_SUCCESS - if able to change state otherwise failure 7213 */ 7214 ibt_status_t 7215 ibcm_cep_to_error_state(ibcm_state_data_t *statep) 7216 { 7217 ibt_status_t status = IBT_SUCCESS; 7218 7219 if (statep->channel != NULL) { 7220 ibt_qp_info_t qp_info; 7221 7222 bzero(&qp_info, sizeof (qp_info)); 7223 /* For now, set it to RC type */ 7224 qp_info.qp_trans = IBT_RC_SRV; 7225 qp_info.qp_state = IBT_STATE_ERROR; 7226 7227 /* Call modify_qp to move to ERROR state */ 7228 status = ibt_modify_qp(statep->channel, IBT_CEP_SET_STATE, 7229 &qp_info, NULL); 7230 7231 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_to_error_state: " 7232 "statep %p ibt_modify_qp() = %d", statep, status); 7233 7234 if (status == IBT_SUCCESS) 7235 ibcm_insert_trace(statep, IBCM_TRACE_ERROR); 7236 else 7237 ibcm_insert_trace(statep, IBCM_TRACE_ERROR_FAIL); 7238 7239 } 7240 7241 #ifdef NO_EEC_SUPPORT_YET 7242 if (statep->channel.ch_eec != NULL) { 7243 ibt_eec_info_t eec_info; 7244 7245 bzero(&eec_info, sizeof (ibt_eec_info_t)); 7246 eec_info.eec_state = what; 7247 7248 /* Call modify_eec */ 7249 status = ibtl_cm_modify_eec(statep->channel.ch_eec, &eec_info, 7250 IBT_CEP_SET_NOTHING); 7251 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_to_error_state: " 7252 "ibtl_cm_modify_eec() returned = %x", status); 7253 } 7254 #endif 7255 7256 return (status); 7257 } 7258 7259 7260 /* 7261 * ibcm_cep_state_rej: 7262 * QP state transition function called for an incoming REJ 7263 * on active/passive side 7264 * 7265 * INPUTS: 7266 * statep - connection state pointer 7267 * rej_msgp - REJ message pointer 7268 * rej_state - State where REJ processing began 7269 * 7270 * RETURN VALUE: 7271 */ 7272 void 7273 ibcm_cep_state_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp, 7274 ibcm_conn_state_t rej_state) 7275 { 7276 ibt_cm_event_t event; 7277 ibt_status_t status; 7278 7279 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej: statep 0x%p", statep); 7280 7281 ibcm_path_cache_purge(); 7282 7283 if ((rej_state == IBCM_STATE_REP_SENT) || 7284 (rej_state == IBCM_STATE_MRA_REP_RCVD)) { 7285 status = ibcm_cep_to_error_state(statep); 7286 IBTF_DPRINTF_L5(cmlog, "ibcm_cep_state_rej: statep 0x%p " 7287 "ibcm_cep_to_error_state returned %d", statep, 7288 status); 7289 } 7290 7291 if (statep->channel) 7292 ibtl_cm_chan_open_is_aborted(statep->channel); 7293 7294 /* Disassociate state structure and CM */ 7295 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL); 7296 7297 /* invoke the CM handler */ 7298 bzero(&event, sizeof (event)); 7299 if (statep->cm_handler) { 7300 event.cm_type = IBT_CM_EVENT_FAILURE; 7301 event.cm_channel = statep->channel; 7302 event.cm_session_id = NULL; 7303 7304 /* 7305 * copy rej_msgp->rej_private_data to 7306 * event.cm_event.cm_priv_data 7307 */ 7308 event.cm_priv_data = &(rej_msgp->rej_private_data[0]); 7309 event.cm_priv_data_len = IBT_REJ_PRIV_DATA_SZ; 7310 7311 event.cm_event.failed.cf_code = IBT_CM_FAILURE_REJ_RCV; 7312 event.cm_event.failed.cf_msg = rej_msgp->rej_msg_type_plus >> 6; 7313 event.cm_event.failed.cf_reason = 7314 b2h16(rej_msgp->rej_rejection_reason); 7315 7316 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rej: rej_reason = %d", 7317 event.cm_event.failed.cf_reason); 7318 7319 ibcm_copy_addl_rej(statep, rej_msgp, &event.cm_event.failed); 7320 7321 (void) statep->cm_handler(statep->state_cm_private, &event, 7322 NULL, NULL, 0); 7323 } 7324 7325 if (statep->open_return_data != NULL) 7326 bcopy(&event.cm_event.failed.cf_additional, 7327 &statep->open_return_data->rc_arej_info, 7328 sizeof (ibt_arej_info_t)); 7329 if (ibcm_enable_trace != 0) 7330 ibcm_dump_conn_trace(statep); 7331 mutex_enter(&statep->state_mutex); 7332 ibcm_open_done(statep); 7333 mutex_exit(&statep->state_mutex); 7334 } 7335 7336 /* Used to initialize client args with addl rej information from REJ MAD */ 7337 static void 7338 ibcm_copy_addl_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp, 7339 ibt_cm_conn_failed_t *failed) 7340 { 7341 uint16_t rej_reason = b2h16(rej_msgp->rej_rejection_reason); 7342 uint8_t ari_len = rej_msgp->rej_reject_info_len_plus >> 1; 7343 ibcm_classportinfo_msg_t tclp; 7344 ibt_arej_info_t *cf_addl = &failed->cf_additional; 7345 7346 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cf_addl)) 7347 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid)) 7348 7349 failed->cf_arej_info_valid = B_FALSE; 7350 7351 IBTF_DPRINTF_L3(cmlog, "ibcm_copy_addl_rej: rej_reason = %d " 7352 "ari_len = %d", rej_reason, ari_len); 7353 7354 if ((statep->mode == IBCM_PASSIVE_MODE) && 7355 (rej_reason != IBT_CM_CONSUMER)) 7356 return; 7357 7358 switch (rej_reason) { 7359 case IBT_CM_PRIM_GID: 7360 case IBT_CM_ALT_GID: 7361 case IBT_CM_PORT_REDIRECT: 7362 if (ari_len < sizeof (ib_gid_t)) 7363 break; 7364 failed->cf_arej_info_valid = B_TRUE; 7365 bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_gid, 7366 sizeof (ib_gid_t)); 7367 cf_addl->ari_gid.gid_guid = b2h64(cf_addl->ari_gid.gid_guid); 7368 cf_addl->ari_gid.gid_prefix = 7369 b2h64(cf_addl->ari_gid.gid_prefix); 7370 7371 IBTF_DPRINTF_L4(cmlog, "ibcm_copy_addl_rej: ari_gid= %llX:%llX", 7372 cf_addl->ari_gid.gid_prefix, cf_addl->ari_gid.gid_guid); 7373 7374 break; 7375 case IBT_CM_PRIM_LID: 7376 case IBT_CM_ALT_LID: 7377 if (ari_len < sizeof (ib_lid_t)) 7378 break; 7379 failed->cf_arej_info_valid = B_TRUE; 7380 bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_lid, 7381 sizeof (ib_lid_t)); 7382 cf_addl->ari_lid = b2h16(cf_addl->ari_lid); 7383 IBTF_DPRINTF_L4(cmlog, "ibcm_copy_addl_rej: ari_lid= 0x%lX", 7384 cf_addl->ari_lid); 7385 7386 break; 7387 case IBT_CM_INVALID_PRIM_SL: 7388 case IBT_CM_INVALID_ALT_SL: 7389 if (ari_len < 1) 7390 break; 7391 failed->cf_arej_info_valid = B_TRUE; 7392 /* take the first 4 bits */ 7393 cf_addl->ari_sl = rej_msgp->rej_addl_rej_info[0] >> 4; 7394 break; 7395 case IBT_CM_INVALID_PRIM_TC: 7396 case IBT_CM_INVALID_ALT_TC: 7397 if (ari_len < 1) 7398 break; 7399 failed->cf_arej_info_valid = B_TRUE; 7400 /* take the first byte */ 7401 cf_addl->ari_tclass = rej_msgp->rej_addl_rej_info[0]; 7402 break; 7403 case IBT_CM_INVALID_PRIM_HOP: 7404 case IBT_CM_INVALID_ALT_HOP: 7405 if (ari_len < 1) 7406 break; 7407 failed->cf_arej_info_valid = B_TRUE; 7408 /* take the first byte */ 7409 cf_addl->ari_hop = rej_msgp->rej_addl_rej_info[0]; 7410 break; 7411 case IBT_CM_INVALID_PRIM_RATE: 7412 case IBT_CM_INVALID_ALT_RATE: 7413 if (ari_len < 1) 7414 break; 7415 failed->cf_arej_info_valid = B_TRUE; 7416 /* take the first 6 bits */ 7417 cf_addl->ari_rate = rej_msgp->rej_addl_rej_info[0] >> 2; 7418 break; 7419 case IBT_CM_REDIRECT_CM: 7420 if (ari_len < sizeof (ibcm_classportinfo_msg_t)) 7421 break; 7422 failed->cf_arej_info_valid = B_TRUE; 7423 bcopy(rej_msgp->rej_addl_rej_info, &tclp, sizeof (tclp)); 7424 ibcm_init_clp_from_mad(&tclp, &cf_addl->ari_redirect); 7425 break; 7426 case IBT_CM_INVALID_MTU: 7427 if (ari_len < 1) 7428 break; 7429 failed->cf_arej_info_valid = B_TRUE; 7430 /* take the first 4 bits */ 7431 cf_addl->ari_mtu = rej_msgp->rej_addl_rej_info[0] >> 4; 7432 break; 7433 case IBT_CM_CONSUMER: 7434 if (ari_len == 0) 7435 break; 7436 failed->cf_arej_info_valid = B_TRUE; 7437 if (ari_len > IBT_CM_ADDL_REJ_LEN) 7438 ari_len = IBT_CM_ADDL_REJ_LEN; 7439 bcopy(&rej_msgp->rej_addl_rej_info, 7440 cf_addl->ari_consumer.rej_ari, ari_len); 7441 cf_addl->ari_consumer.rej_ari_len = ari_len; 7442 break; 7443 case IBT_CM_INVALID_PRIM_FLOW: 7444 case IBT_CM_INVALID_ALT_FLOW: 7445 if (ari_len < 3) /* 3 bytes needed for 20 bits */ 7446 break; 7447 failed->cf_arej_info_valid = B_TRUE; 7448 /* take the first 20 bits */ 7449 cf_addl->ari_flow = 7450 b2h32(*(uint32_t *)&rej_msgp->rej_addl_rej_info) >> 12; 7451 break; 7452 default: 7453 break; 7454 } 7455 7456 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid)) 7457 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cf_addl)) 7458 } 7459 7460 7461 /* Used to copy classportinfo to MAD from client initialized args */ 7462 static void 7463 ibcm_init_clp_to_mad(ibcm_classportinfo_msg_t *clp, ibt_redirect_info_t *rinfo) 7464 { 7465 7466 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*clp)) 7467 7468 bcopy(&ibcm_clpinfo, clp, sizeof (ibcm_clpinfo)); 7469 7470 clp->RedirectGID_hi = h2b64(rinfo->rdi_gid.gid_prefix); 7471 clp->RedirectGID_lo = h2b64(rinfo->rdi_gid.gid_guid); 7472 clp->RedirectTC_plus = 7473 h2b32((rinfo->rdi_tclass << 24) | (rinfo->rdi_sl << 20) | 7474 (rinfo->rdi_flow & 0xfffff)); 7475 clp->RedirectLID = h2b16(rinfo->rdi_dlid); 7476 clp->RedirectQP_plus = h2b32(rinfo->rdi_qpn & 0xffffff); 7477 clp->RedirectQ_Key = h2b32(rinfo->rdi_qkey); 7478 clp->RedirectP_Key = h2b16(rinfo->rdi_pkey); 7479 7480 IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_to_mad: RedirectGID= %llX:%llX," 7481 " RedirectLID= 0x%lX", clp->RedirectGID_hi, clp->RedirectGID_lo, 7482 clp->RedirectLID); 7483 7484 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*clp)) 7485 } 7486 7487 7488 /* Used to initialize classportinfo to be returned to clients, from MAD */ 7489 static void 7490 ibcm_init_clp_from_mad(ibcm_classportinfo_msg_t *clp, 7491 ibt_redirect_info_t *rinfo) 7492 { 7493 uint32_t temp32; 7494 7495 rinfo->rdi_gid.gid_prefix = b2h64(clp->RedirectGID_hi); 7496 rinfo->rdi_gid.gid_guid = b2h64(clp->RedirectGID_lo); 7497 temp32 = b2h32(clp->RedirectTC_plus); 7498 rinfo->rdi_tclass = temp32 >> 24; 7499 rinfo->rdi_sl = (temp32 >> 20) & 0xf; 7500 rinfo->rdi_flow = temp32 & 0xffff; 7501 rinfo->rdi_dlid = b2h16(clp->RedirectLID); 7502 rinfo->rdi_qpn = b2h32(clp->RedirectQP_plus & 0xffffff); 7503 rinfo->rdi_qkey = b2h32(clp->RedirectQ_Key); 7504 rinfo->rdi_pkey = b2h16(clp->RedirectP_Key); 7505 7506 IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_from_mad: RedirectGID= %llX:%llX," 7507 " RedirectLID= 0x%lX", rinfo->rdi_gid.gid_prefix, 7508 rinfo->rdi_gid.gid_guid, rinfo->rdi_dlid); 7509 } 7510 7511 7512 /* 7513 * ibcm_cep_state_rej_est: 7514 * QP state transition function called for an incoming REJ 7515 * on active side in established state 7516 * 7517 * INPUTS: 7518 * statep - connection state pointer 7519 * 7520 * RETURN VALUE: 7521 */ 7522 void 7523 ibcm_cep_state_rej_est(ibcm_state_data_t *statep) 7524 { 7525 ibt_cm_event_t event; 7526 ibt_status_t status; 7527 7528 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_rej_est:"); 7529 7530 status = ibcm_cep_to_error_state(statep); 7531 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej_est: statep 0x%p " 7532 "ibcm_cep_to_error_state returned %d", statep, status); 7533 7534 /* Disassociate state structure and CM */ 7535 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL); 7536 7537 ibtl_cm_chan_is_closing(statep->channel); 7538 7539 /* invoke the CM handler */ 7540 if (statep->cm_handler) { 7541 bzero(&event, sizeof (event)); 7542 event.cm_type = IBT_CM_EVENT_CONN_CLOSED; 7543 event.cm_channel = statep->channel; 7544 event.cm_session_id = NULL; 7545 7546 event.cm_priv_data = NULL; 7547 event.cm_priv_data_len = 0; 7548 7549 event.cm_event.closed = IBT_CM_CLOSED_REJ_RCVD; 7550 7551 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_rej_est: " 7552 "rej_reason = %d", event.cm_event.failed.cf_reason); 7553 7554 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_CONN_CLOSE_EVENT); 7555 7556 (void) statep->cm_handler(statep->state_cm_private, &event, 7557 NULL, NULL, 0); 7558 7559 ibcm_insert_trace(statep, IBCM_TRACE_RET_CONN_CLOSE_EVENT); 7560 7561 } 7562 } 7563 7564 7565 /* 7566 * ibcm_sidr_req_ud_handler: 7567 * Invoke Client's UD handler For SIDR_REQ msg 7568 * 7569 * INPUTS: 7570 * ud_statep - ud_state pointer 7571 * sidr_reqp - SIDR_REQ message pointer 7572 * 7573 * RETURN VALUE: IBCM_SEND_REP/IBCM_SEND_REJ 7574 */ 7575 static ibcm_status_t 7576 ibcm_sidr_req_ud_handler(ibcm_ud_state_data_t *ud_statep, 7577 ibcm_sidr_req_msg_t *sidr_reqp, ibcm_mad_addr_t *cm_mad_addr, 7578 ibt_sidr_status_t *sidr_status) 7579 { 7580 void *priv_data = NULL; 7581 ibt_cm_ud_event_t ud_event; 7582 ibcm_sidr_rep_msg_t *sidr_repp; 7583 ibt_cm_ud_return_args_t ud_ret_args; 7584 ibt_cm_status_t cb_status; 7585 ibt_qp_query_attr_t qp_attr; 7586 ibt_status_t retval; 7587 ibcm_ud_clnt_reply_info_t ud_clnt_info; 7588 7589 /* Check first if UD client handler is valid */ 7590 ASSERT(ud_statep->ud_cm_handler != NULL); 7591 7592 /* Fill in ibt_cm_ud_event_t */ 7593 ud_event.cm_type = IBT_CM_UD_EVENT_SIDR_REQ; 7594 ud_event.cm_session_id = ud_statep; 7595 ud_event.cm_event.sidr_req.sreq_service_id = ud_statep->ud_svc_id; 7596 ud_event.cm_event.sidr_req.sreq_hca_guid = ud_statep->ud_hcap->hca_guid; 7597 ud_event.cm_event.sidr_req.sreq_pkey = b2h16(sidr_reqp->sidr_req_pkey); 7598 ud_event.cm_event.sidr_req.sreq_hca_port = cm_mad_addr->port_num; 7599 7600 ud_event.cm_priv_data = 7601 &(sidr_reqp->sidr_req_private_data[0]); 7602 ud_event.cm_priv_data_len = IBT_SIDR_REQ_PRIV_DATA_SZ; 7603 7604 sidr_repp = 7605 (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg); 7606 7607 priv_data = &(sidr_repp->sidr_rep_private_data[0]); 7608 7609 bzero(&ud_ret_args, sizeof (ud_ret_args)); 7610 7611 /* Invoke the client handler */ 7612 cb_status = ud_statep->ud_cm_handler(ud_statep->ud_state_cm_private, 7613 &ud_event, &ud_ret_args, priv_data, IBT_SIDR_REP_PRIV_DATA_SZ); 7614 7615 if (cb_status == IBT_CM_DEFER) { 7616 7617 /* unblock any blocked cm ud proceed api calls */ 7618 mutex_enter(&ud_statep->ud_state_mutex); 7619 ud_statep->ud_clnt_proceed = IBCM_UNBLOCK; 7620 cv_broadcast(&ud_statep->ud_block_client_cv); 7621 mutex_exit(&ud_statep->ud_state_mutex); 7622 7623 return (IBCM_DEFER); 7624 } 7625 7626 /* fail any blocked ud cm proceed api calls - client bug */ 7627 mutex_enter(&ud_statep->ud_state_mutex); 7628 ud_statep->ud_clnt_proceed = IBCM_FAIL; 7629 cv_broadcast(&ud_statep->ud_block_client_cv); 7630 mutex_exit(&ud_statep->ud_state_mutex); 7631 7632 /* do the query qp as soon as possible, after return from cm handler */ 7633 if (cb_status == IBT_CM_ACCEPT) { 7634 retval = ibt_query_qp(ud_ret_args.ud_channel, &qp_attr); 7635 if (retval != IBT_SUCCESS) { 7636 IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_req_ud_handler: " 7637 "Failed to retrieve QPN from the channel: %d", 7638 retval); 7639 *sidr_status = IBT_CM_SREP_NO_CHAN; 7640 return (IBCM_SEND_SIDR_REP); 7641 } else if (qp_attr.qp_info.qp_trans != IBT_UD_SRV) { 7642 IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_req_ud_handler: " 7643 "Server/Passive returned non-UD %d transport type " 7644 "QP", qp_attr.qp_info.qp_trans); 7645 *sidr_status = IBT_CM_SREP_NO_CHAN; 7646 return (IBCM_SEND_SIDR_REP); 7647 } 7648 7649 ud_clnt_info.ud_qkey = qp_attr.qp_info.qp_transport.ud.ud_qkey; 7650 ud_clnt_info.ud_qpn = qp_attr.qp_qpn; 7651 } 7652 7653 ud_clnt_info.priv_data = priv_data; 7654 ud_clnt_info.priv_data_len = ud_ret_args.ud_ret_len; 7655 7656 ud_clnt_info.redirect_infop = &ud_ret_args.ud_redirect; 7657 7658 ibcm_process_sidr_req_cm_hdlr(ud_statep, cb_status, &ud_clnt_info, 7659 sidr_status, sidr_repp); 7660 7661 return (IBCM_SEND_SIDR_REP); 7662 } 7663 7664 /*ARGSUSED*/ 7665 void 7666 ibcm_process_sidr_req_cm_hdlr(ibcm_ud_state_data_t *ud_statep, 7667 ibt_cm_status_t cb_status, ibcm_ud_clnt_reply_info_t *ud_clnt_info, 7668 ibt_sidr_status_t *sidr_status, ibcm_sidr_rep_msg_t *sidr_repp) 7669 { 7670 void *sidr_rep_privp; 7671 7672 IBTF_DPRINTF_L5(cmlog, "ibcm_process_sidr_req_cm_hdlr(%p, %x, " 7673 "%p, %p, %p)", ud_statep, cb_status, ud_clnt_info, 7674 sidr_status, sidr_repp); 7675 7676 if (cb_status == IBT_CM_DEFAULT) 7677 cb_status = IBT_CM_REJECT; 7678 7679 if (cb_status == IBT_CM_ACCEPT) 7680 *sidr_status = IBT_CM_SREP_CHAN_VALID; 7681 else if ((cb_status == IBT_CM_REJECT) || 7682 (cb_status == IBT_CM_NO_RESOURCE)) 7683 *sidr_status = IBT_CM_SREP_REJ; 7684 else if (cb_status == IBT_CM_NO_CHANNEL) 7685 *sidr_status = IBT_CM_SREP_NO_CHAN; 7686 else if (cb_status == IBT_CM_REDIRECT) 7687 *sidr_status = IBT_CM_SREP_REDIRECT; 7688 else *sidr_status = IBT_CM_SREP_REJ; 7689 7690 /* 7691 * For Accept and reject copy the private data, if ud_clnt_info 7692 * priv_data does not point to SIDR Response private data. This 7693 * copy is needed for ibt_cm_ud_proceed(). 7694 */ 7695 sidr_rep_privp = (void *)(&(sidr_repp->sidr_rep_private_data[0])); 7696 if ((cb_status == IBT_CM_ACCEPT || cb_status == IBT_CM_REJECT) && 7697 (ud_clnt_info->priv_data != sidr_rep_privp) && 7698 ud_clnt_info->priv_data_len) { 7699 bcopy(ud_clnt_info->priv_data, sidr_rep_privp, 7700 min(ud_clnt_info->priv_data_len, 7701 IBT_SIDR_REP_PRIV_DATA_SZ)); 7702 } 7703 7704 if (*sidr_status != IBT_CM_SREP_CHAN_VALID) { 7705 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_req_cm_hdlr: " 7706 "ud_handler return a failure: %d", cb_status); 7707 if (*sidr_status == IBT_CM_SREP_REDIRECT) { 7708 /* 7709 * typecasting to ibcm_classportinfo_msg_t is ok, as addl info 7710 * begins at offset 24 in sidr rep 7711 */ 7712 ibcm_init_clp_to_mad( 7713 (ibcm_classportinfo_msg_t *) 7714 &sidr_repp->sidr_rep_class_port_info, 7715 ud_clnt_info->redirect_infop); 7716 } 7717 return; 7718 } 7719 7720 7721 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp)) 7722 7723 sidr_repp->sidr_rep_qkey = 7724 h2b32(ud_clnt_info->ud_qkey); 7725 sidr_repp->sidr_rep_qpn_plus = h2b32(ud_clnt_info->ud_qpn << 8); 7726 7727 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp)) 7728 } 7729 7730 /* 7731 * ibcm_sidr_rep_ud_handler: 7732 * Invoke Client's UD handler For SIDR_REP msg 7733 * 7734 * INPUTS: 7735 * ud_statep - ud_state pointer 7736 * sidr_rep_msgp - SIDR_REQ message pointer 7737 * 7738 */ 7739 static void 7740 ibcm_sidr_rep_ud_handler(ibcm_ud_state_data_t *ud_statep, 7741 ibcm_sidr_rep_msg_t *sidr_rep_msgp) 7742 { 7743 ibt_cm_ud_event_t ud_event; 7744 7745 IBTF_DPRINTF_L5(cmlog, "ibcm_sidr_rep_ud_handler: ud_statep 0x%p", 7746 ud_statep); 7747 7748 /* Check first if UD client handler is valid */ 7749 if (ud_statep->ud_cm_handler == NULL) { 7750 IBTF_DPRINTF_L2(cmlog, "ibcm_sidr_rep_ud_handler: " 7751 "cm_handler NULL"); 7752 return; 7753 } 7754 7755 /* Fill in ibt_cm_ud_event_t */ 7756 ud_event.cm_type = IBT_CM_UD_EVENT_SIDR_REP; 7757 ud_event.cm_session_id = NULL; 7758 ud_event.cm_event.sidr_rep.srep_status = 7759 sidr_rep_msgp->sidr_rep_rep_status; 7760 ud_event.cm_event.sidr_rep.srep_remote_qpn = 7761 b2h32(sidr_rep_msgp->sidr_rep_qpn_plus) >> 8; 7762 ud_event.cm_event.sidr_rep.srep_remote_qkey = 7763 h2b32(sidr_rep_msgp->sidr_rep_qkey); 7764 7765 if (ud_event.cm_event.sidr_rep.srep_status == IBT_CM_SREP_REDIRECT) { 7766 /* 7767 * typecasting to ibcm_classportinfo_msg_t is ok, as addl info 7768 * begins at offset 24 in sidr rep 7769 */ 7770 ibcm_init_clp_from_mad( 7771 (ibcm_classportinfo_msg_t *) 7772 sidr_rep_msgp->sidr_rep_class_port_info, 7773 &ud_event.cm_event.sidr_rep.srep_redirect); 7774 7775 if (ud_statep->ud_return_data != NULL) 7776 bcopy(&ud_event.cm_event.sidr_rep.srep_redirect, 7777 &ud_statep->ud_return_data->ud_redirect, 7778 sizeof (ibt_redirect_info_t)); 7779 } 7780 7781 ud_event.cm_priv_data = &(sidr_rep_msgp->sidr_rep_private_data[0]); 7782 ud_event.cm_priv_data_len = IBT_SIDR_REP_PRIV_DATA_SZ; 7783 7784 /* Invoke the client handler - inform only, so ignore retval */ 7785 (void) ud_statep->ud_cm_handler(ud_statep->ud_state_cm_private, 7786 &ud_event, NULL, NULL, 0); 7787 7788 7789 } 7790 7791 /* 7792 * ibcm_process_lap_msg: 7793 * This call processes an incoming LAP message 7794 * 7795 * INPUTS: 7796 * hcap - HCA entry pointer 7797 * input_madp - incoming CM LAP MAD 7798 * cm_mad_addr - Address information for the MAD 7799 * 7800 * RETURN VALUE: NONE 7801 */ 7802 /* ARGSUSED */ 7803 void 7804 ibcm_process_lap_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp, 7805 ibcm_mad_addr_t *cm_mad_addr) 7806 { 7807 ibcm_status_t state_lookup_status; 7808 ibcm_lap_msg_t *lap_msg = (ibcm_lap_msg_t *) 7809 (&input_madp[IBCM_MAD_HDR_SIZE]); 7810 ibcm_apr_msg_t *apr_msg; 7811 ibcm_state_data_t *statep = NULL; 7812 7813 IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg:"); 7814 7815 rw_enter(&hcap->hca_state_rwlock, RW_READER); 7816 7817 state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_LAP, 7818 b2h32(lap_msg->lap_remote_comm_id), 0, 0, hcap, &statep); 7819 7820 rw_exit(&hcap->hca_state_rwlock); 7821 7822 IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg: lookup status %x" 7823 " com id %x", state_lookup_status, 7824 b2h32(lap_msg->lap_remote_comm_id)); 7825 7826 if (state_lookup_status != IBCM_LOOKUP_EXISTS) { 7827 /* Post a REJ message ? - but spec doesn't state so */ 7828 return; 7829 } 7830 7831 /* There is an existing state structure entry with active comid */ 7832 7833 ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_LAP); 7834 7835 mutex_enter(&statep->state_mutex); 7836 7837 if ((statep->state == IBCM_STATE_ESTABLISHED) && 7838 (statep->ap_state == IBCM_AP_STATE_IDLE) && 7839 (statep->mode == IBCM_PASSIVE_MODE)) { 7840 if ((statep->lapr_msg) && 7841 (IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID == 7842 ((ib_mad_hdr_t *)(input_madp))->TransactionID)) 7843 ibcm_post_stored_apr_mad(statep, input_madp); 7844 else { 7845 ibcm_status_t clnt_response; 7846 7847 statep->ap_state = IBCM_AP_STATE_LAP_RCVD; 7848 statep->clnt_proceed = IBCM_BLOCK; 7849 mutex_exit(&statep->state_mutex); 7850 7851 if (statep->lapr_msg == NULL) { 7852 if (ibcm_alloc_out_msg( 7853 statep->stored_reply_addr.ibmf_hdl, 7854 &statep->lapr_msg, MAD_METHOD_SEND) != 7855 IBT_SUCCESS) { 7856 7857 mutex_enter(&statep->state_mutex); 7858 statep->clnt_proceed = IBCM_FAIL; 7859 cv_broadcast(&statep->block_client_cv); 7860 IBCM_REF_CNT_DECR(statep); 7861 mutex_exit(&statep->state_mutex); 7862 return; 7863 } 7864 } 7865 apr_msg = (ibcm_apr_msg_t *) 7866 IBCM_OUT_MSGP(statep->lapr_msg); 7867 IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID = 7868 ((ib_mad_hdr_t *)(input_madp))->TransactionID; 7869 clnt_response = 7870 ibcm_cep_state_lap(statep, lap_msg, apr_msg); 7871 IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg:" 7872 " statep 0x%p apr status %d", statep, 7873 apr_msg->apr_ap_status); 7874 7875 if (clnt_response == IBCM_DEFER) { 7876 IBTF_DPRINTF_L4(cmlog, "ibcm_process_lap_msg: " 7877 "client returned DEFER response"); 7878 return; 7879 } 7880 7881 /* fail any blocked cm proceed api calls - client bug */ 7882 mutex_enter(&statep->state_mutex); 7883 statep->clnt_proceed = IBCM_FAIL; 7884 cv_broadcast(&statep->block_client_cv); 7885 mutex_exit(&statep->state_mutex); 7886 7887 ibcm_post_apr_mad(statep); 7888 return; 7889 } 7890 } /* drop the LAP MAD in any other state */ 7891 7892 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */ 7893 mutex_exit(&statep->state_mutex); 7894 } 7895 7896 /* 7897 * ibcm_post_stored_apr_mad: 7898 * Builds and posts an APR MAD from the stored APR MAD 7899 * 7900 * INPUTS: 7901 * statep - pointer to ibcm_state_data_t 7902 * input_madp - pointer to incoming lap mad 7903 * 7904 * RETURN VALUE: 7905 * NONE 7906 * 7907 * This function is called holding the state mutex, and returns 7908 * holding the state mutex 7909 */ 7910 static void 7911 ibcm_post_stored_apr_mad(ibcm_state_data_t *statep, uint8_t *input_madp) 7912 { 7913 ibmf_msg_t *ibmf_apr_msg; 7914 uint8_t apr_msg[IBCM_MSG_SIZE]; 7915 7916 /* Need to make a copy, else an incoming new LAP may modify lapr_msg */ 7917 bcopy(IBCM_OUT_MSGP(statep->lapr_msg), apr_msg, IBCM_MSG_SIZE); 7918 7919 mutex_exit(&statep->state_mutex); 7920 7921 if (ibcm_alloc_out_msg(statep->stored_reply_addr.ibmf_hdl, 7922 &ibmf_apr_msg, MAD_METHOD_SEND) != IBT_SUCCESS) { 7923 IBTF_DPRINTF_L2(cmlog, "ibcm_post_stored_apr_mad: " 7924 "ibcm_alloc_out_msg failed"); 7925 mutex_enter(&statep->state_mutex); 7926 return; 7927 } 7928 7929 bcopy(apr_msg, IBCM_OUT_MSGP(ibmf_apr_msg), IBCM_MSG_SIZE); 7930 7931 IBCM_OUT_HDRP(ibmf_apr_msg)->AttributeID = 7932 h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID); 7933 7934 IBCM_OUT_HDRP(ibmf_apr_msg)->TransactionID = 7935 ((ib_mad_hdr_t *)(input_madp))->TransactionID; 7936 7937 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR); 7938 7939 ibcm_post_rc_mad(statep, ibmf_apr_msg, ibcm_post_stored_apr_complete, 7940 ibmf_apr_msg); 7941 7942 /* ibcm_free_out_msg done in ibcm_post_stored_apr_complete */ 7943 7944 mutex_enter(&statep->state_mutex); 7945 } 7946 7947 /* 7948 * ibcm_cep_state_lap: 7949 * This call processes an incoming LAP message for cep state 7950 * transition and invoking cm handler 7951 * 7952 * INPUTS: 7953 * statep - pointer to ibcm_state_data_t 7954 * lap_msg - lap msg received 7955 * apr_msg - apr msg to be sent 7956 * 7957 * RETURN VALUE: NONE 7958 */ 7959 ibcm_status_t 7960 ibcm_cep_state_lap(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg, 7961 ibcm_apr_msg_t *apr_msg) 7962 { 7963 ibt_cm_event_t event; 7964 ibt_cm_return_args_t ret_args; 7965 ibt_cm_status_t cb_status; 7966 ibcm_clnt_reply_info_t clnt_info; 7967 7968 7969 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: statep 0x%p", statep); 7970 7971 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg)) 7972 7973 /* If APM is not supported, return error */ 7974 if (!(statep->hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) { 7975 apr_msg->apr_ap_status = IBT_CM_AP_NOT_SUPPORTED; 7976 return (IBCM_SEND_APR); 7977 } 7978 7979 if (statep->local_qpn != 7980 b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8) { 7981 apr_msg->apr_ap_status = IBT_CM_AP_REJECT; 7982 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: local_qpn %x does " 7983 "not match remote's remote_qpn %x", statep->local_qpn, 7984 b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8); 7985 return (IBCM_SEND_APR); 7986 } 7987 7988 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg)) 7989 7990 /* Fill up the event */ 7991 bzero(&event, sizeof (event)); 7992 event.cm_type = IBT_CM_EVENT_LAP_RCV; 7993 event.cm_channel = statep->channel; 7994 event.cm_session_id = statep; 7995 event.cm_priv_data = lap_msg->lap_private_data; 7996 event.cm_priv_data_len = IBT_LAP_PRIV_DATA_SZ; 7997 event.cm_event.lap.lap_timeout = ibt_ib2usec( 7998 ((uint8_t *)&lap_msg->lap_remote_qpn_eecn_plus)[3] >> 3); 7999 8000 ibcm_fill_adds_from_lap(&event.cm_event.lap.lap_alternate_path, 8001 lap_msg, IBCM_PASSIVE_MODE); 8002 8003 cb_status = statep->cm_handler(statep->state_cm_private, &event, 8004 &ret_args, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ); 8005 8006 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_lap: cb_status = %d", cb_status); 8007 if (cb_status == IBT_CM_DEFER) { 8008 8009 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg)) 8010 8011 if (statep->defer_cm_msg == NULL) 8012 statep->defer_cm_msg = 8013 kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP); 8014 bcopy(lap_msg, statep->defer_cm_msg, IBCM_MSG_SIZE); 8015 8016 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg)) 8017 8018 /* unblock any blocked cm proceed api calls */ 8019 mutex_enter(&statep->state_mutex); 8020 statep->clnt_proceed = IBCM_UNBLOCK; 8021 cv_broadcast(&statep->block_client_cv); 8022 mutex_exit(&statep->state_mutex); 8023 8024 return (IBCM_DEFER); 8025 } 8026 8027 clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret; 8028 clnt_info.priv_data = NULL; 8029 clnt_info.priv_data_len = 0; 8030 8031 ibcm_process_cep_lap_cm_hdlr(statep, cb_status, &clnt_info, lap_msg, 8032 apr_msg); 8033 return (IBCM_SEND_APR); 8034 } 8035 8036 /* 8037 * ibcm_fill_adds_from_lap: 8038 * Fills the address vector (part of event structure passed to 8039 * client) from the LAP message 8040 * 8041 * INPUTS: 8042 * adds - Address vector to be filled-in 8043 * lap_msg - LAP message used to fill the address vector 8044 * 8045 * RETURN VALUE: NONE 8046 */ 8047 static void 8048 ibcm_fill_adds_from_lap(ibt_adds_vect_t *adds, ibcm_lap_msg_t *lap_msg, 8049 ibcm_mode_t mode) 8050 { 8051 adds->av_srvl = lap_msg->lap_alt_sl_plus >> 4; 8052 if (mode == IBCM_PASSIVE_MODE) { 8053 adds->av_dgid.gid_prefix = 8054 b2h64(lap_msg->lap_alt_l_port_gid.gid_prefix); 8055 adds->av_dgid.gid_guid = 8056 b2h64(lap_msg->lap_alt_l_port_gid.gid_guid); 8057 adds->av_sgid.gid_prefix = 8058 b2h64(lap_msg->lap_alt_r_port_gid.gid_prefix); 8059 adds->av_sgid.gid_guid = 8060 b2h64(lap_msg->lap_alt_r_port_gid.gid_guid); 8061 adds->av_dlid = b2h16(lap_msg->lap_alt_l_port_lid); 8062 } else { 8063 adds->av_sgid.gid_prefix = 8064 b2h64(lap_msg->lap_alt_l_port_gid.gid_prefix); 8065 adds->av_sgid.gid_guid = 8066 b2h64(lap_msg->lap_alt_l_port_gid.gid_guid); 8067 adds->av_dgid.gid_prefix = 8068 b2h64(lap_msg->lap_alt_r_port_gid.gid_prefix); 8069 adds->av_dgid.gid_guid = 8070 b2h64(lap_msg->lap_alt_r_port_gid.gid_guid); 8071 adds->av_dlid = b2h16(lap_msg->lap_alt_r_port_lid); 8072 } 8073 8074 IBTF_DPRINTF_L4(cmlog, "ibcm_fill_adds_from_lap: SGID=(%llX:%llX)", 8075 adds->av_sgid.gid_prefix, adds->av_sgid.gid_guid); 8076 8077 IBTF_DPRINTF_L4(cmlog, "ibcm_fill_adds_from_lap: DGID=(%llX:%llX)", 8078 adds->av_dgid.gid_prefix, adds->av_dgid.gid_guid); 8079 8080 adds->av_srate = lap_msg->lap_alt_srate_plus & 0x3f; 8081 8082 /* next copy off the GRH info if it exists */ 8083 if ((lap_msg->lap_alt_sl_plus & 0x8) == 0) { 8084 uint32_t flow_tclass = b2h32(lap_msg->lap_alt_flow_label_plus); 8085 8086 adds->av_send_grh = B_TRUE; 8087 adds->av_flow = flow_tclass >> 12; 8088 adds->av_tclass = flow_tclass & 0xff; 8089 adds->av_hop = lap_msg->lap_alt_hop_limit; 8090 } else { 8091 adds->av_send_grh = B_FALSE; 8092 } 8093 } 8094 8095 /* 8096 * ibcm_process_cep_lap_cm_hdlr: 8097 * Processes the cm handler response for an incoming LAP. 8098 */ 8099 8100 void 8101 ibcm_process_cep_lap_cm_hdlr(ibcm_state_data_t *statep, 8102 ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info, 8103 ibcm_lap_msg_t *lap_msg, ibcm_apr_msg_t *apr_msg) 8104 { 8105 ibtl_cm_hca_port_t port; 8106 ibt_qp_query_attr_t qp_attrs; 8107 ibt_cep_modify_flags_t cep_flags; 8108 ibt_status_t status; 8109 ibt_adds_vect_t *adds; 8110 8111 if (cb_status == IBT_CM_DEFAULT) 8112 cb_status = IBT_CM_REJECT; 8113 8114 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg)) 8115 8116 /* verify status */ 8117 apr_msg->apr_addl_info_len = 0; 8118 if (cb_status == IBT_CM_ACCEPT) { 8119 apr_msg->apr_ap_status = IBT_CM_AP_LOADED; 8120 } else if (cb_status == IBT_CM_REJECT) { 8121 apr_msg->apr_ap_status = IBT_CM_AP_REJECT; 8122 } else if (cb_status == IBT_CM_REDIRECT) { 8123 apr_msg->apr_ap_status = IBT_CM_AP_REDIRECT; 8124 /* copy redirect info to APR */ 8125 apr_msg->apr_addl_info_len = sizeof (ibcm_classportinfo_msg_t); 8126 ibcm_init_clp_to_mad( 8127 (ibcm_classportinfo_msg_t *)apr_msg->apr_addl_info, 8128 &clnt_info->reply_event->apr); 8129 } else if (cb_status == IBT_CM_NO_RESOURCE) { 8130 apr_msg->apr_ap_status = IBT_CM_AP_REJECT; 8131 } else { 8132 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p" 8133 " Client handler unexpected return %x", statep, cb_status); 8134 cb_status = IBT_CM_REJECT; 8135 apr_msg->apr_ap_status = IBT_CM_AP_REJECT; 8136 } 8137 8138 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep 0x%p " 8139 " client handler returned %d, apr status %d", statep, cb_status, 8140 apr_msg->apr_ap_status); 8141 8142 /* copy private data to outgoing apr, specified via priv_data */ 8143 if ((clnt_info->priv_data != NULL) && (clnt_info->priv_data_len > 0)) 8144 bcopy(clnt_info->priv_data, apr_msg->apr_private_data, 8145 min(clnt_info->priv_data_len, IBT_APR_PRIV_DATA_SZ)); 8146 8147 if (cb_status != IBT_CM_ACCEPT) 8148 return; 8149 8150 if (ibt_query_qp(statep->channel, &qp_attrs) != IBT_SUCCESS || 8151 (qp_attrs.qp_info.qp_state != IBT_STATE_RTS && 8152 qp_attrs.qp_info.qp_state != IBT_STATE_SQD)) { 8153 apr_msg->apr_ap_status = IBT_CM_AP_REJECT; 8154 return; 8155 } 8156 8157 /* Fill up input args for ibt_modify_qp */ 8158 cep_flags = IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_STATE; 8159 8160 /* do RTS=>RTS or SQD=>SQD. The next line is needed for RTS=>RTS. */ 8161 qp_attrs.qp_info.qp_current_state = qp_attrs.qp_info.qp_state; 8162 8163 adds = &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect; 8164 ibcm_fill_adds_from_lap(adds, lap_msg, IBCM_PASSIVE_MODE); 8165 8166 if ((status = ibtl_cm_get_hca_port(adds->av_sgid, 8167 statep->local_hca_guid, &port)) != IBT_SUCCESS) { 8168 8169 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:" 8170 " ibtl_cm_get_hca_port failed status %d", status); 8171 apr_msg->apr_ap_status = IBT_CM_AP_REJECT; 8172 return; 8173 } 8174 8175 IBCM_QP_RC(qp_attrs).rc_alt_path.cep_hca_port_num = port.hp_port; 8176 8177 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep 0x%p " 8178 "gid = (%llx, %llx), port_num = %d", statep, 8179 IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_dgid. 8180 gid_prefix, 8181 IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_dgid.gid_guid, 8182 port.hp_port); 8183 8184 /* The pkey is same as the primary path */ 8185 status = ibt_pkey2index_byguid(statep->local_hca_guid, 8186 port.hp_port, statep->pkey, 8187 &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_pkey_ix); 8188 8189 if (status != IBT_SUCCESS) { 8190 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p" 8191 " ibt_pkey2index_byguid failed %d", statep, status); 8192 apr_msg->apr_ap_status = IBT_CM_AP_REJECT; 8193 return; 8194 } 8195 8196 IBCM_QP_RC(qp_attrs).rc_alt_path.cep_timeout = 8197 lap_msg->lap_alt_local_acktime_plus >> 3; 8198 8199 qp_attrs.qp_info.qp_trans = IBT_RC_SRV; 8200 if (IBCM_QP_RC(qp_attrs).rc_mig_state == IBT_STATE_MIGRATED) { 8201 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p" 8202 ": rearming APM", statep); 8203 cep_flags |= IBT_CEP_SET_MIG; 8204 IBCM_QP_RC(qp_attrs).rc_mig_state = IBT_STATE_REARMED; 8205 } 8206 status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info, 8207 NULL); 8208 8209 if (status != IBT_SUCCESS) { 8210 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL); 8211 } else 8212 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT); 8213 8214 #ifdef DEBUG 8215 (void) ibt_query_qp(statep->channel, &qp_attrs); 8216 print_modify_qp("PASSIVE LAP QUERY", statep->channel, 8217 cep_flags, &qp_attrs.qp_info); 8218 #endif 8219 8220 if (status != IBT_SUCCESS) { 8221 apr_msg->apr_ap_status = IBT_CM_AP_REJECT; 8222 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:" 8223 " ibt_modify_qp() returned = %d", status); 8224 return; 8225 } 8226 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg)) 8227 } 8228 8229 8230 /* 8231 * ibcm_post_apr_mad: 8232 * Posts a APR MAD and starts timer 8233 * 8234 * INPUTS: 8235 * statep - state pointer 8236 * 8237 * RETURN VALUE: NONE 8238 */ 8239 void 8240 ibcm_post_apr_mad(ibcm_state_data_t *statep) 8241 { 8242 ibcm_apr_msg_t *apr_msgp; 8243 8244 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msgp)) 8245 8246 apr_msgp = (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg); 8247 8248 apr_msgp->apr_local_comm_id = h2b32(statep->local_comid); 8249 apr_msgp->apr_remote_comm_id = h2b32(statep->remote_comid); 8250 IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID = 8251 h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID); 8252 8253 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msgp)) 8254 8255 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR); 8256 8257 ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_apr_complete, 8258 statep); 8259 } 8260 8261 /* 8262 * ibcm_process_apr_msg: 8263 * This call processes an incoming APR message 8264 * 8265 * INPUTS: 8266 * hcap - HCA entry pointer 8267 * input_madp - incoming CM SIDR REP MAD 8268 * cm_mad_addr - Address information for the MAD to be posted 8269 * 8270 * RETURN VALUE: NONE 8271 */ 8272 /*ARGSUSED*/ 8273 void 8274 ibcm_process_apr_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp, 8275 ibcm_mad_addr_t *cm_mad_addr) 8276 { 8277 ibcm_status_t state_lookup_status; 8278 ibcm_apr_msg_t *apr_msg = (ibcm_apr_msg_t *) 8279 (&input_madp[IBCM_MAD_HDR_SIZE]); 8280 ibcm_state_data_t *statep = NULL; 8281 8282 IBTF_DPRINTF_L4(cmlog, "ibcm_process_apr_msg:"); 8283 8284 rw_enter(&hcap->hca_state_rwlock, RW_READER); 8285 state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_APR, 8286 b2h32(apr_msg->apr_remote_comm_id), 0, 0, hcap, &statep); 8287 rw_exit(&hcap->hca_state_rwlock); 8288 8289 if (state_lookup_status != IBCM_LOOKUP_EXISTS) { 8290 return; 8291 } 8292 8293 /* if transaction id is not as expected, drop the APR mad */ 8294 if (IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID != 8295 ((ib_mad_hdr_t *)(input_madp))->TransactionID) { 8296 mutex_enter(&statep->state_mutex); 8297 IBCM_REF_CNT_DECR(statep); 8298 mutex_exit(&statep->state_mutex); 8299 IBTF_DPRINTF_L3(cmlog, "ibcm_process_apr_msg: statep 0x%p" 8300 ": rcv'd APR MAD with comid 0x%x", 8301 statep, b2h32(apr_msg->apr_remote_comm_id)); 8302 IBTF_DPRINTF_L3(cmlog, "ibcm_process_apr_msg: " 8303 "tid expected 0x%llX tid found 0x%llX", 8304 b2h64(IBCM_OUT_HDRP(statep->lapr_msg)->TransactionID), 8305 b2h64(((ib_mad_hdr_t *)(input_madp))->TransactionID)); 8306 return; 8307 } 8308 8309 IBTF_DPRINTF_L4(cmlog, "ibcm_process_apr_msg: statep 0x%p " 8310 "lookup status %x", statep, state_lookup_status); 8311 8312 mutex_enter(&statep->state_mutex); 8313 8314 if (!((statep->state == IBCM_STATE_ESTABLISHED) && 8315 ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) || 8316 (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)))) { 8317 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */ 8318 mutex_exit(&statep->state_mutex); 8319 return; 8320 } 8321 8322 statep->ap_state = IBCM_AP_STATE_APR_RCVD; 8323 8324 /* cancel the LAP timer */ 8325 if (statep->timerid != 0) { 8326 timeout_id_t timer_val; 8327 timer_val = statep->timerid; 8328 statep->timerid = 0; 8329 mutex_exit(&statep->state_mutex); 8330 (void) untimeout(timer_val); 8331 } else { 8332 mutex_exit(&statep->state_mutex); 8333 } 8334 8335 ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_APR); 8336 8337 ibcm_cep_state_apr(statep, 8338 (ibcm_lap_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg), apr_msg); 8339 8340 mutex_enter(&statep->state_mutex); 8341 statep->ap_state = IBCM_AP_STATE_IDLE; 8342 8343 /* unblock any DREQ threads and close channels */ 8344 cv_broadcast(&statep->block_mad_cv); 8345 8346 statep->ap_done = B_TRUE; 8347 8348 /* wake up blocking ibt_set_alt_path */ 8349 cv_broadcast(&statep->block_client_cv); 8350 8351 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */ 8352 mutex_exit(&statep->state_mutex); 8353 } 8354 8355 static void 8356 ibcm_set_apr_arej(int ap_status, ibcm_apr_msg_t *apr_msgp, 8357 ibt_arej_info_t *ari, boolean_t *ari_valid) 8358 { 8359 uint8_t ari_len = apr_msgp->apr_addl_info_len; 8360 ibcm_classportinfo_msg_t tclp; 8361 8362 *ari_valid = B_FALSE; 8363 8364 IBTF_DPRINTF_L3(cmlog, "ibcm_set_apr_arej: apr_status = %d " 8365 "ari_len = %d", ap_status, ari_len); 8366 8367 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ari)) 8368 8369 switch (ap_status) { 8370 case IBT_CM_AP_REDIRECT: 8371 if (ari_len < sizeof (ibcm_classportinfo_msg_t)) 8372 break; 8373 *ari_valid = B_TRUE; 8374 bcopy(apr_msgp->apr_addl_info, &tclp, sizeof (tclp)); 8375 ibcm_init_clp_from_mad(&tclp, &ari->ari_redirect); 8376 break; 8377 case IBT_CM_AP_RLID_REJECTED: 8378 if (ari_len < sizeof (ib_lid_t)) 8379 break; 8380 *ari_valid = B_TRUE; 8381 bcopy(apr_msgp->apr_addl_info, &ari->ari_lid, 8382 sizeof (ib_lid_t)); 8383 ari->ari_lid = b2h16(ari->ari_lid); 8384 break; 8385 case IBT_CM_AP_RGID_REJECTED: 8386 if (ari_len < sizeof (ib_gid_t)) 8387 break; 8388 *ari_valid = B_TRUE; 8389 bcopy(apr_msgp->apr_addl_info, &ari->ari_gid, 8390 sizeof (ib_gid_t)); 8391 ari->ari_gid.gid_guid = b2h64(ari->ari_gid.gid_guid); 8392 ari->ari_gid.gid_prefix = b2h64(ari->ari_gid.gid_prefix); 8393 8394 IBTF_DPRINTF_L4(cmlog, "ibcm_set_apr_arej: ari_gid= %llX:%llX", 8395 ari->ari_gid.gid_prefix, ari->ari_gid.gid_guid); 8396 break; 8397 case IBT_CM_AP_FLOW_REJECTED: 8398 if (ari_len < 3) /* 3 bytes needed for 20 bits */ 8399 break; 8400 *ari_valid = B_TRUE; 8401 /* take the first 20 bits */ 8402 ari->ari_flow = 8403 b2h32(*(uint32_t *)&apr_msgp->apr_addl_info) >> 12; 8404 break; 8405 case IBT_CM_AP_TCLASS_REJECTED: 8406 if (ari_len < 1) 8407 break; 8408 *ari_valid = B_TRUE; 8409 /* take the first byte */ 8410 ari->ari_tclass = apr_msgp->apr_addl_info[0]; 8411 break; 8412 case IBT_CM_AP_HOP_REJECTED: 8413 if (ari_len < 1) 8414 break; 8415 *ari_valid = B_TRUE; 8416 /* take the first byte */ 8417 ari->ari_hop = apr_msgp->apr_addl_info[0]; 8418 break; 8419 case IBT_CM_AP_RATE_REJECTED: 8420 if (ari_len < 1) 8421 break; 8422 *ari_valid = B_TRUE; 8423 /* take the first 6 bits */ 8424 ari->ari_rate = apr_msgp->apr_addl_info[0] >> 2; 8425 break; 8426 case IBT_CM_AP_SL_REJECTED: 8427 if (ari_len < 1) 8428 break; 8429 *ari_valid = B_TRUE; 8430 /* take the first 4 bits */ 8431 ari->ari_sl = apr_msgp->apr_addl_info[0] >> 4; 8432 break; 8433 default: 8434 break; 8435 } 8436 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ari)) 8437 } 8438 8439 /* 8440 * ibcm_cep_state_apr: 8441 * This call processes an incoming APR message 8442 * 8443 * INPUTS: 8444 * statep - pointer to ibcm_state_data_t 8445 * lap_msg - lap msg sent earlier 8446 * apr_msg - apr msg received 8447 * 8448 * RETURN VALUE: NONE 8449 */ 8450 void 8451 ibcm_cep_state_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg, 8452 ibcm_apr_msg_t *apr_msg) 8453 { 8454 ibt_cm_event_t event; 8455 ibcm_status_t status = IBCM_SUCCESS; 8456 uint8_t ap_status = apr_msg->apr_ap_status; 8457 8458 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_apr: statep 0x%p, ap_status %d", 8459 statep, ap_status); 8460 8461 if (ap_status == IBT_CM_AP_LOADED) 8462 status = ibcm_set_qp_from_apr(statep, lap_msg); 8463 8464 if (statep->ap_return_data != NULL) { /* blocking call */ 8465 8466 /* copy the private data */ 8467 if ((statep->ap_return_data->ap_priv_data != NULL) && 8468 (statep->ap_return_data->ap_priv_data_len > 0)) 8469 bcopy(apr_msg->apr_private_data, 8470 statep->ap_return_data->ap_priv_data, 8471 statep->ap_return_data->ap_priv_data_len); 8472 8473 /* initialize the ap status */ 8474 if (status == IBCM_FAILURE) { 8475 statep->ap_return_data->ap_status = IBT_CM_AP_REJECT; 8476 statep->ap_return_data->ap_arej_info_valid = B_FALSE; 8477 } else { 8478 statep->ap_return_data->ap_status = ap_status; 8479 ibcm_set_apr_arej(ap_status, apr_msg, 8480 &statep->ap_return_data->ap_arej_info, 8481 &statep->ap_return_data->ap_arej_info_valid); 8482 } 8483 8484 /* do a cv signal for a blocking ibt_set_alt_path */ 8485 mutex_enter(&statep->state_mutex); 8486 statep->ap_done = B_TRUE; 8487 cv_broadcast(&statep->block_client_cv); 8488 mutex_exit(&statep->state_mutex); 8489 8490 } else { /* Non blocking call */ 8491 /* Fill up the event */ 8492 8493 bzero(&event, sizeof (event)); 8494 event.cm_type = IBT_CM_EVENT_APR_RCV; 8495 event.cm_channel = statep->channel; 8496 event.cm_session_id = NULL; 8497 event.cm_priv_data = apr_msg->apr_private_data; 8498 event.cm_priv_data_len = IBT_APR_PRIV_DATA_SZ; 8499 if (status == IBCM_FAILURE) { 8500 event.cm_event.apr.apr_status = IBT_CM_AP_REJECT; 8501 event.cm_event.apr.apr_arej_info_valid = B_FALSE; 8502 } else { 8503 event.cm_event.apr.apr_status = ap_status; 8504 ibcm_set_apr_arej(ap_status, apr_msg, 8505 &event.cm_event.apr.apr_arej_info, 8506 &event.cm_event.apr.apr_arej_info_valid); 8507 } 8508 8509 /* initialize the ap status */ 8510 statep->cm_handler(statep->state_cm_private, &event, 8511 NULL, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ); 8512 } 8513 mutex_enter(&statep->state_mutex); 8514 ibcm_open_done(statep); 8515 mutex_exit(&statep->state_mutex); 8516 } 8517 8518 /* 8519 * ibcm_set_qp_from_apr: 8520 * This call sets QP's alt path info based on APR message contents 8521 * 8522 * INPUTS: 8523 * statep - pointer to ibcm_state_data_t 8524 * lap_msg - lap msg sent earlier 8525 * 8526 * RETURN VALUE: ibcm_status_t 8527 */ 8528 static ibcm_status_t 8529 ibcm_set_qp_from_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg) 8530 { 8531 ibtl_cm_hca_port_t port; 8532 ibt_adds_vect_t *adds; 8533 8534 ibt_qp_query_attr_t qp_attrs; 8535 ibt_cep_modify_flags_t cep_flags; 8536 ibt_status_t status; 8537 8538 IBTF_DPRINTF_L3(cmlog, "ibcm_set_qp_from_apr: statep 0x%p", statep); 8539 8540 status = ibt_query_qp(statep->channel, &qp_attrs); 8541 if (status != IBT_SUCCESS || 8542 (qp_attrs.qp_info.qp_state != IBT_STATE_RTS && 8543 qp_attrs.qp_info.qp_state != IBT_STATE_SQD)) { 8544 IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: ibt_query_qp " 8545 "failed, status = %d, qp_state = %d", statep, status, 8546 qp_attrs.qp_info.qp_state); 8547 return (IBCM_FAILURE); 8548 } 8549 8550 /* Fill up input args for ibt_modify_qp */ 8551 cep_flags = IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_STATE; 8552 8553 /* do RTS=>RTS or SQD=>SQD. The next line is needed for RTS=>RTS. */ 8554 qp_attrs.qp_info.qp_current_state = qp_attrs.qp_info.qp_state; 8555 8556 /* Fill up input args for ibt_modify_qp */ 8557 adds = &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect; 8558 8559 ibcm_fill_adds_from_lap(adds, lap_msg, IBCM_ACTIVE_MODE); 8560 8561 if ((status = ibtl_cm_get_hca_port(adds->av_sgid, 8562 statep->local_hca_guid, &port)) != IBT_SUCCESS) { 8563 IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: " 8564 "ibtl_cm_get_hca_port failed status = %d", status); 8565 IBTF_DPRINTF_L5(cmlog, "ibcm_set_qp_from_apr:" 8566 " ibtl_cm_get_hca_port sgid guid %llX", 8567 adds->av_sgid.gid_guid); 8568 IBTF_DPRINTF_L5(cmlog, "ibcm_set_qp_from_apr:" 8569 " ibtl_cm_get_hca_port sgid prefix %llX ", 8570 adds->av_sgid.gid_prefix); 8571 return (IBCM_FAILURE); 8572 } 8573 8574 IBCM_QP_RC(qp_attrs).rc_alt_path.cep_hca_port_num = 8575 port.hp_port; 8576 8577 IBTF_DPRINTF_L4(cmlog, "ibcm_set_qp_from_apr: " 8578 "gid = %llx:%llx, port_num = %d", 8579 IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_sgid. 8580 gid_prefix, 8581 IBCM_QP_RC(qp_attrs).rc_alt_path.cep_adds_vect.av_sgid.gid_guid, 8582 port.hp_port); 8583 8584 /* The pkey is same as the primary path */ 8585 status = ibt_pkey2index_byguid(statep->local_hca_guid, 8586 port.hp_port, statep->pkey, 8587 &IBCM_QP_RC(qp_attrs).rc_alt_path.cep_pkey_ix); 8588 8589 if (status != IBT_SUCCESS) { 8590 IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr: " 8591 "ibt_pkey2index_byguid failed %d", status); 8592 return (IBCM_FAILURE); 8593 } 8594 qp_attrs.qp_info.qp_trans = IBT_RC_SRV; 8595 IBCM_QP_RC(qp_attrs).rc_alt_path.cep_timeout = 8596 ibt_usec2ib(statep->remote_ack_delay + 8597 2 * statep->rc_alt_pkt_lt); 8598 if (IBCM_QP_RC(qp_attrs).rc_mig_state == IBT_STATE_MIGRATED) { 8599 /* Need to rearm */ 8600 IBTF_DPRINTF_L3(cmlog, "ibcm_set_qp_from_apr: statep 0x%p: " 8601 "rearming APM", statep); 8602 cep_flags |= IBT_CEP_SET_MIG; 8603 IBCM_QP_RC(qp_attrs).rc_mig_state = IBT_STATE_REARMED; 8604 } 8605 8606 status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info, 8607 NULL); 8608 8609 if (status != IBT_SUCCESS) 8610 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL); 8611 else 8612 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT); 8613 8614 #ifdef DEBUG 8615 (void) ibt_query_qp(statep->channel, &qp_attrs); 8616 print_modify_qp("ACTIVE LAP QUERY", statep->channel, 8617 cep_flags, &qp_attrs.qp_info); 8618 #endif 8619 8620 if (status != IBT_SUCCESS) { 8621 IBTF_DPRINTF_L2(cmlog, "ibcm_set_qp_from_apr:" 8622 " ibt_modify_qp() failed, status = %d", status); 8623 return (IBCM_FAILURE); 8624 } 8625 8626 return (IBCM_SUCCESS); 8627 } 8628 8629 /* 8630 * ibcm_sync_lapr_idle: 8631 * 8632 * This call either cancels a LAP/APR operation or waits 8633 * until the operation is complete 8634 * 8635 * INPUTS: 8636 * statep Pointer to ibcm_state_data_t 8637 * 8638 * RETURN VALUE: NONE 8639 * 8640 * This function is called holding state mutex 8641 * This function returns, releasing the state mutex 8642 */ 8643 void 8644 ibcm_sync_lapr_idle(ibcm_state_data_t *statep) 8645 { 8646 timeout_id_t timer_val = statep->timerid; 8647 ibt_cm_event_t event; 8648 8649 IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:" 8650 "statep %p state %d ap_state %d", statep, statep->state, 8651 statep->ap_state); 8652 8653 ASSERT(MUTEX_HELD(&statep->state_mutex)); 8654 _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex)) 8655 8656 /* Busy AP states on active/passive sides */ 8657 if ((statep->ap_state == IBCM_AP_STATE_LAP_RCVD) || 8658 (statep->ap_state == IBCM_AP_STATE_APR_RCVD) || 8659 (statep->ap_state == IBCM_AP_STATE_MRA_LAP_SENT) || 8660 (statep->ap_state == IBCM_AP_STATE_TIMED_OUT)) { 8661 8662 /* wait till ap_state becomes IBCM_AP_STATE_IDLE */ 8663 while (statep->ap_state != IBCM_AP_STATE_IDLE) 8664 cv_wait(&statep->block_mad_cv, &statep->state_mutex); 8665 8666 mutex_exit(&statep->state_mutex); 8667 8668 } else if ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) || 8669 (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) { 8670 8671 /* fail the client's ibt_set_alt_path */ 8672 8673 /* blocking ibt_set_alt_path */ 8674 if (statep->ap_return_data != NULL) { 8675 statep->ap_return_data->ap_status = 8676 IBT_CM_AP_ABORT; 8677 statep->ap_state = IBCM_AP_STATE_IDLE; 8678 cv_broadcast(&statep->block_client_cv); 8679 IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:" 8680 "blocked wait"); 8681 } 8682 8683 statep->timerid = 0; 8684 /* Cancel the timeout */ 8685 mutex_exit(&statep->state_mutex); 8686 if (timer_val != 0) 8687 (void) untimeout(timer_val); 8688 8689 /* Non blocking ibt_set_alt_path */ 8690 if (statep->ap_return_data == NULL) { 8691 8692 /* Fill up the event */ 8693 8694 bzero(&event, sizeof (event)); 8695 event.cm_type = IBT_CM_EVENT_APR_RCV; 8696 event.cm_channel = statep->channel; 8697 event.cm_session_id = NULL; 8698 event.cm_priv_data = NULL; 8699 event.cm_priv_data_len = 0; 8700 event.cm_event.apr.apr_status = IBT_CM_AP_ABORT; 8701 8702 /* Call the cm handler */ 8703 statep->cm_handler(statep->state_cm_private, &event, 8704 NULL, NULL, 0); 8705 IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:" 8706 "non-blocked wait"); 8707 } 8708 } else mutex_exit(&statep->state_mutex); 8709 8710 ASSERT(!MUTEX_HELD(&statep->state_mutex)); 8711 } 8712 8713 #ifdef DEBUG 8714 8715 /* 8716 * Debug function used to print all the modify qp attributes. 8717 * Useful to manually verify the modify qp parameters are as 8718 * expected 8719 */ 8720 static void 8721 print_modify_qp(char *prefix, ibt_qp_hdl_t ibt_qp, 8722 ibt_cep_modify_flags_t flags, ibt_qp_info_t *qp_attr) 8723 { 8724 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP %s %p", prefix, ibt_qp); 8725 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP flags 0x%x", flags); 8726 8727 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP " 8728 "rc_rdma_ra_in %d rc_rdma_ra_out %d", 8729 qp_attr->qp_transport.rc.rc_rdma_ra_in, 8730 qp_attr->qp_transport.rc.rc_rdma_ra_out); 8731 8732 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: " 8733 "port %d path bits %d dlid %X", 8734 qp_attr->qp_transport.rc.rc_path.cep_hca_port_num, 8735 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_src_path, 8736 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dlid); 8737 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: " 8738 "pkey index %d cep_timeout %d", 8739 qp_attr->qp_transport.rc.rc_path.cep_pkey_ix, 8740 qp_attr->qp_transport.rc.rc_path.cep_timeout); 8741 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: " 8742 "srvl %d flow label %d tclass %d", 8743 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_srvl, 8744 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_flow, 8745 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_tclass); 8746 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: " 8747 "hop %d srate %d sgid_ix %d send_grh %d", 8748 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_hop, 8749 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_srate, 8750 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid_ix, 8751 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_send_grh); 8752 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: " 8753 "dgid prefix %llX dgid guid %llX", 8754 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dgid.gid_prefix, 8755 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_dgid.gid_guid); 8756 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP primary: " 8757 "sgid prefix %llX sgid guid %llX", 8758 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid.gid_prefix, 8759 qp_attr->qp_transport.rc.rc_path.cep_adds_vect.av_sgid.gid_guid); 8760 8761 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: " 8762 "port %d path bits %d dlid %X", 8763 qp_attr->qp_transport.rc.rc_alt_path.cep_hca_port_num, 8764 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_src_path, 8765 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dlid); 8766 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: " 8767 "pkey index %d cep_timeout %d", 8768 qp_attr->qp_transport.rc.rc_alt_path.cep_pkey_ix, 8769 qp_attr->qp_transport.rc.rc_alt_path.cep_timeout); 8770 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: " 8771 "srvl %d flow label %d tclass %d", 8772 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_srvl, 8773 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_flow, 8774 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_tclass); 8775 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: " 8776 "hop %d srate %d sgid_ix %d send_grh %d", 8777 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_hop, 8778 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_srate, 8779 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid_ix, 8780 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_send_grh); 8781 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: " 8782 "dgid prefix %llX dgid guid %llX", 8783 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dgid. 8784 gid_prefix, 8785 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_dgid. 8786 gid_guid); 8787 IBTF_DPRINTF_L4(cmlog, "PRINT_MODIFY_QP alternate: " 8788 "sgid prefix %llX sgid guid %llX", 8789 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid. 8790 gid_prefix, 8791 qp_attr->qp_transport.rc.rc_alt_path.cep_adds_vect.av_sgid. 8792 gid_guid); 8793 } 8794 #endif 8795