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