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