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