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