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