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