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