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