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