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