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