1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * ibcm_impl.c 28 * 29 * contains internal functions of IB CM module. 30 * 31 * TBD: 32 * 1. HCA CATASTROPHIC/RECOVERED not handled yet 33 */ 34 35 #include <sys/ib/mgt/ibcm/ibcm_impl.h> 36 #include <sys/disp.h> 37 38 39 /* function prototypes */ 40 static ibcm_status_t ibcm_init(void); 41 static ibcm_status_t ibcm_fini(void); 42 43 /* Routines to initialize and destroy CM global locks and CVs */ 44 static void ibcm_init_locks(void); 45 static void ibcm_fini_locks(void); 46 47 /* Routines that initialize/teardown CM's global hca structures */ 48 static void ibcm_init_hcas(); 49 static ibcm_status_t ibcm_fini_hcas(); 50 51 static void ibcm_init_classportinfo(); 52 static void ibcm_stop_timeout_thread(); 53 54 /* Routines that handle HCA attach/detach asyncs */ 55 static void ibcm_hca_attach(ib_guid_t); 56 static ibcm_status_t ibcm_hca_detach(ibcm_hca_info_t *); 57 58 /* Routines that initialize the HCA's port related fields */ 59 static ibt_status_t ibcm_hca_init_port(ibcm_hca_info_t *hcap, 60 uint8_t port_index); 61 static ibcm_status_t ibcm_hca_fini_port(ibcm_hca_info_t *hcap, 62 uint8_t port_index); 63 64 static void ibcm_rc_flow_control_init(void); 65 static void ibcm_rc_flow_control_fini(void); 66 67 /* 68 * Routines that check if hca's avl trees and sidr lists are free of any 69 * active client resources ie., RC or UD state structures in certain states 70 */ 71 static ibcm_status_t ibcm_check_avl_clean(ibcm_hca_info_t *hcap); 72 static ibcm_status_t ibcm_check_sidr_clean(ibcm_hca_info_t *hcap); 73 74 /* Add a new hca structure to CM's global hca list */ 75 static ibcm_hca_info_t *ibcm_add_hca_entry(ib_guid_t hcaguid, uint_t nports); 76 77 static void ibcm_comm_est_handler(ibt_async_event_t *); 78 void ibcm_async_handler(void *, ibt_hca_hdl_t, 79 ibt_async_code_t, ibt_async_event_t *); 80 81 /* Global variables */ 82 char cmlog[] = "ibcm"; /* for debug log messages */ 83 ibt_clnt_hdl_t ibcm_ibt_handle; /* IBT handle */ 84 kmutex_t ibcm_svc_info_lock; /* list lock */ 85 kcondvar_t ibcm_svc_info_cv; /* cv for deregister */ 86 kmutex_t ibcm_recv_mutex; 87 avl_tree_t ibcm_svc_avl_tree; 88 taskq_t *ibcm_taskq = NULL; 89 int taskq_dispatch_fail_cnt; 90 91 kmutex_t ibcm_mcglist_lock; /* MCG list lock */ 92 kmutex_t ibcm_trace_mutex; /* Trace mutex */ 93 kmutex_t ibcm_trace_print_mutex; /* Trace print mutex */ 94 int ibcm_conn_max_trcnt = IBCM_MAX_CONN_TRCNT; 95 96 int ibcm_enable_trace = 2; /* Trace level 4 by default */ 97 int ibcm_dtrace = 0; /* conditionally enable more dtrace */ 98 99 _NOTE(MUTEX_PROTECTS_DATA(ibcm_svc_info_lock, ibcm_svc_info_s::{svc_bind_list 100 svc_ref_cnt svc_to_delete})) 101 102 _NOTE(MUTEX_PROTECTS_DATA(ibcm_svc_info_lock, ibcm_svc_bind_s::{sbind_link})) 103 104 _NOTE(MUTEX_PROTECTS_DATA(ibcm_trace_mutex, ibcm_conn_trace_s)) 105 106 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_conn_trace_s)) 107 108 _NOTE(MUTEX_PROTECTS_DATA(ibcm_trace_print_mutex, ibcm_debug_buf)) 109 110 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_debug_buf)) 111 112 /* 113 * Initial state is INIT. All hca dr's return success immediately in this 114 * state, without adding or deleting any hca's to CM. 115 */ 116 ibcm_finit_state_t ibcm_finit_state = IBCM_FINIT_INIT; 117 118 /* mutex and cv to manage hca's reference and resource count(s) */ 119 kmutex_t ibcm_global_hca_lock; 120 kcondvar_t ibcm_global_hca_cv; 121 122 /* mutex and cv to sa session open */ 123 kmutex_t ibcm_sa_open_lock; 124 kcondvar_t ibcm_sa_open_cv; 125 int ibcm_sa_timeout_delay = 1; /* in ticks */ 126 _NOTE(MUTEX_PROTECTS_DATA(ibcm_sa_open_lock, 127 ibcm_port_info_s::{port_ibmf_saa_hdl port_saa_open_in_progress})) 128 129 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_saa_hdl})) 130 131 /* serialize sm notice callbacks */ 132 kmutex_t ibcm_sm_notice_serialize_lock; 133 134 _NOTE(LOCK_ORDER(ibcm_sm_notice_serialize_lock ibcm_global_hca_lock)) 135 136 _NOTE(MUTEX_PROTECTS_DATA(ibcm_global_hca_lock, ibcm_hca_info_s::{hca_state 137 hca_svc_cnt hca_acc_cnt hca_res_cnt hca_next})) 138 139 _NOTE(MUTEX_PROTECTS_DATA(ibcm_global_hca_lock, 140 ibcm_port_info_s::{port_ibmf_hdl})) 141 142 _NOTE(MUTEX_PROTECTS_DATA(ibcm_sm_notice_serialize_lock, 143 ibcm_port_info_s::{port_event_status})) 144 145 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_hca_info_s::{hca_state})) 146 _NOTE(DATA_READABLE_WITHOUT_LOCK( 147 ibcm_hca_info_s::{hca_port_info.port_ibmf_hdl})) 148 149 /* mutex for CM's qp list management */ 150 kmutex_t ibcm_qp_list_lock; 151 152 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_port_info_s::{port_qplist})) 153 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_qp_list_s)) 154 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_qp_list_s)) 155 156 kcondvar_t ibcm_timeout_list_cv; 157 kcondvar_t ibcm_timeout_thread_done_cv; 158 kt_did_t ibcm_timeout_thread_did; 159 ibcm_state_data_t *ibcm_timeout_list_hdr, *ibcm_timeout_list_tail; 160 ibcm_ud_state_data_t *ibcm_ud_timeout_list_hdr, *ibcm_ud_timeout_list_tail; 161 kmutex_t ibcm_timeout_list_lock; 162 uint8_t ibcm_timeout_list_flags = 0; 163 pri_t ibcm_timeout_thread_pri = MINCLSYSPRI; 164 165 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, 166 ibcm_state_data_s::timeout_next)) 167 168 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, 169 ibcm_ud_state_data_s::ud_timeout_next)) 170 171 /* 172 * Flow control logic for open_rc_channel uses the following. 173 */ 174 175 struct ibcm_open_s { 176 kmutex_t mutex; 177 kcondvar_t cv; 178 uint8_t task_running; 179 uint_t queued; 180 uint_t exit_deferred; 181 uint_t in_progress; 182 uint_t in_progress_max; 183 uint_t sends; 184 uint_t sends_max; 185 uint_t sends_lowat; 186 uint_t sends_hiwat; 187 ibcm_state_data_t *tail; 188 ibcm_state_data_t head; 189 } ibcm_open; 190 191 /* 192 * Flow control logic for SA access and close_rc_channel calls follows. 193 */ 194 195 int ibcm_close_simul_max = 12; 196 int ibcm_lapr_simul_max = 12; 197 int ibcm_saa_simul_max = 8; 198 199 typedef struct ibcm_flow1_s { 200 struct ibcm_flow1_s *link; 201 kcondvar_t cv; 202 uint8_t waiters; /* 1 to IBCM_FLOW_SIMUL_MAX */ 203 } ibcm_flow1_t; 204 205 typedef struct ibcm_flow_s { 206 ibcm_flow1_t *list; 207 uint_t simul; /* #requests currently outstanding */ 208 uint_t simul_max; 209 uint_t waiters_per_chunk; 210 uint_t lowat; 211 uint_t lowat_default; 212 /* statistics */ 213 uint_t total; 214 } ibcm_flow_t; 215 216 ibcm_flow_t ibcm_saa_flow; 217 ibcm_flow_t ibcm_close_flow; 218 ibcm_flow_t ibcm_lapr_flow; 219 220 /* NONBLOCKING close requests are queued */ 221 struct ibcm_close_s { 222 kmutex_t mutex; 223 ibcm_state_data_t *tail; 224 ibcm_state_data_t head; 225 } ibcm_close; 226 227 static ibt_clnt_modinfo_t ibcm_ibt_modinfo = { /* Client's modinfop */ 228 IBTI_V_CURR, 229 IBT_CM, 230 ibcm_async_handler, 231 NULL, 232 "IBCM" 233 }; 234 235 /* IBCM's list of HCAs registered with it */ 236 static ibcm_hca_info_t *ibcm_hca_listp = NULL; /* CM's HCA list */ 237 238 /* Array of CM state call table functions */ 239 ibcm_state_handler_t ibcm_sm_funcs_tbl[] = { 240 ibcm_process_req_msg, 241 ibcm_process_mra_msg, 242 ibcm_process_rej_msg, 243 ibcm_process_rep_msg, 244 ibcm_process_rtu_msg, 245 ibcm_process_dreq_msg, 246 ibcm_process_drep_msg, 247 ibcm_process_sidr_req_msg, 248 ibcm_process_sidr_rep_msg, 249 ibcm_process_lap_msg, 250 ibcm_process_apr_msg 251 }; 252 253 /* the following globals are CM tunables */ 254 ibt_rnr_nak_time_t ibcm_default_rnr_nak_time = IBT_RNR_NAK_655ms; 255 256 uint8_t ibcm_max_retries = IBCM_MAX_RETRIES; 257 clock_t ibcm_local_processing_time = IBCM_LOCAL_RESPONSE_TIME; 258 clock_t ibcm_remote_response_time = IBCM_REMOTE_RESPONSE_TIME; 259 ib_time_t ibcm_max_sidr_rep_proctime = IBCM_MAX_SIDR_PROCESS_TIME; 260 ib_time_t ibcm_max_sidr_pktlife_time = IBCM_MAX_SIDR_PKT_LIFE_TIME; 261 262 ib_time_t ibcm_max_sidr_rep_store_time = 18; 263 uint32_t ibcm_wait_for_acc_cnt_timeout = 2000000; /* 2 sec */ 264 265 ib_time_t ibcm_max_ib_pkt_lt = IBCM_MAX_IB_PKT_LT; 266 ib_time_t ibcm_max_ib_mad_pkt_lt = IBCM_MAX_IB_MAD_PKT_LT; 267 268 /* 269 * This delay accounts for time involved in various activities as follows : 270 * 271 * IBMF delays for posting the MADs in non-blocking mode 272 * IBMF delays for receiving the MADs and delivering to CM 273 * CM delays in processing the MADs before invoking client handlers, 274 * Any other delays associated with HCA driver in processing the MADs and 275 * other subsystems that CM may invoke (ex : SA, HCA driver) 276 */ 277 uint32_t ibcm_sw_delay = 1000; /* 1000us / 1ms */ 278 uint32_t ibcm_max_sa_retries = IBCM_MAX_SA_RETRIES + 1; 279 280 /* approx boot time */ 281 uint32_t ibcm_adj_btime = 4; /* 4 seconds */ 282 283 /* 284 * The information in ibcm_clpinfo is kept in wireformat and is setup at 285 * init time, and used read-only after that 286 */ 287 ibcm_classportinfo_msg_t ibcm_clpinfo; 288 289 char *event_str[] = { 290 "NEVER SEE THIS ", 291 "SESSION_ID ", 292 "CHAN_HDL ", 293 "LOCAL_COMID/HCA/PORT ", 294 "LOCAL_QPN ", 295 "REMOTE_COMID/HCA ", 296 "REMOTE_QPN ", 297 "BASE_TIME ", 298 "INCOMING_REQ ", 299 "INCOMING_REP ", 300 "INCOMING_RTU ", 301 "INCOMING_COMEST ", 302 "INCOMING_MRA ", 303 "INCOMING_REJ ", 304 "INCOMING_LAP ", 305 "INCOMING_APR ", 306 "INCOMING_DREQ ", 307 "INCOMING_DREP ", 308 "OUTGOING_REQ ", 309 "OUTGOING_REP ", 310 "OUTGOING_RTU ", 311 "OUTGOING_LAP ", 312 "OUTGOING_APR ", 313 "OUTGOING_MRA ", 314 "OUTGOING_REJ ", 315 "OUTGOING_DREQ ", 316 "OUTGOING_DREP ", 317 "REQ_POST_COMPLETE ", 318 "REP_POST_COMPLETE ", 319 "RTU_POST_COMPLETE ", 320 "MRA_POST_COMPLETE ", 321 "REJ_POST_COMPLETE ", 322 "LAP_POST_COMPLETE ", 323 "APR_POST_COMPLETE ", 324 "DREQ_POST_COMPLETE ", 325 "DREP_POST_COMPLETE ", 326 "TIMEOUT_REP ", 327 "CALLED_REQ_RCVD_EVENT ", 328 "RET_REQ_RCVD_EVENT ", 329 "CALLED_REP_RCVD_EVENT ", 330 "RET_REP_RCVD_EVENT ", 331 "CALLED_CONN_EST_EVENT ", 332 "RET_CONN_EST_EVENT ", 333 "CALLED_CONN_FAIL_EVENT ", 334 "RET_CONN_FAIL_EVENT ", 335 "CALLED_CONN_CLOSE_EVENT ", 336 "RET_CONN_CLOSE_EVENT ", 337 "INIT_INIT ", 338 "INIT_INIT_FAIL ", 339 "INIT_RTR ", 340 "INIT_RTR_FAIL ", 341 "RTR_RTS ", 342 "RTR_RTS_FAIL ", 343 "RTS_RTS ", 344 "RTS_RTS_FAIL ", 345 "TO_ERROR ", 346 "ERROR_FAIL ", 347 "SET_ALT ", 348 "SET_ALT_FAIL ", 349 "STALE_DETECT ", 350 "OUTGOING_REQ_RETRY ", 351 "OUTGOING_REP_RETRY ", 352 "OUTGOING_LAP_RETRY ", 353 "OUTGOING_MRA_RETRY ", 354 "OUTGOING_DREQ_RETRY ", 355 "NEVER SEE THIS " 356 }; 357 358 char ibcm_debug_buf[IBCM_DEBUG_BUF_SIZE]; 359 360 _NOTE(SCHEME_PROTECTS_DATA("used in a localized function consistently", 361 ibcm_debug_buf)) 362 _NOTE(READ_ONLY_DATA(ibcm_taskq)) 363 364 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_timeout_list_flags)) 365 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_timeout_list_hdr)) 366 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_ud_timeout_list_hdr)) 367 368 #ifdef DEBUG 369 int ibcm_test_mode = 0; /* set to 1, if running tests */ 370 #endif 371 372 373 /* Module Driver Info */ 374 static struct modlmisc ibcm_modlmisc = { 375 &mod_miscops, 376 "IB Communication Manager" 377 }; 378 379 /* Module Linkage */ 380 static struct modlinkage ibcm_modlinkage = { 381 MODREV_1, 382 { &ibcm_modlmisc, NULL } 383 }; 384 385 386 int 387 _init(void) 388 { 389 int rval; 390 ibcm_status_t status; 391 392 status = ibcm_init(); 393 if (status != IBCM_SUCCESS) { 394 IBTF_DPRINTF_L2(cmlog, "_init: ibcm failed %d", status); 395 return (EINVAL); 396 } 397 398 rval = mod_install(&ibcm_modlinkage); 399 if (rval != 0) { 400 IBTF_DPRINTF_L2(cmlog, "_init: ibcm mod_install failed %d", 401 rval); 402 (void) ibcm_fini(); 403 } 404 405 IBTF_DPRINTF_L5(cmlog, "_init: ibcm successful"); 406 return (rval); 407 408 } 409 410 411 int 412 _info(struct modinfo *modinfop) 413 { 414 return (mod_info(&ibcm_modlinkage, modinfop)); 415 } 416 417 418 int 419 _fini(void) 420 { 421 int status; 422 423 if (ibcm_fini() != IBCM_SUCCESS) 424 return (EBUSY); 425 426 if ((status = mod_remove(&ibcm_modlinkage)) != 0) { 427 IBTF_DPRINTF_L2(cmlog, "_fini: ibcm mod_remove failed %d", 428 status); 429 return (status); 430 } 431 432 IBTF_DPRINTF_L5(cmlog, "_fini: ibcm successful"); 433 434 return (status); 435 } 436 437 /* Initializes all global mutex and CV in cm module */ 438 static void 439 ibcm_init_locks() 440 { 441 442 /* Verify CM MAD sizes */ 443 #ifdef DEBUG 444 445 if (ibcm_test_mode > 1) { 446 447 IBTF_DPRINTF_L1(cmlog, "REQ MAD SIZE %d", 448 sizeof (ibcm_req_msg_t)); 449 IBTF_DPRINTF_L1(cmlog, "REP MAD SIZE %d", 450 sizeof (ibcm_rep_msg_t)); 451 IBTF_DPRINTF_L1(cmlog, "RTU MAD SIZE %d", 452 sizeof (ibcm_rtu_msg_t)); 453 IBTF_DPRINTF_L1(cmlog, "MRA MAD SIZE %d", 454 sizeof (ibcm_mra_msg_t)); 455 IBTF_DPRINTF_L1(cmlog, "REJ MAD SIZE %d", 456 sizeof (ibcm_rej_msg_t)); 457 IBTF_DPRINTF_L1(cmlog, "LAP MAD SIZE %d", 458 sizeof (ibcm_lap_msg_t)); 459 IBTF_DPRINTF_L1(cmlog, "APR MAD SIZE %d", 460 sizeof (ibcm_apr_msg_t)); 461 IBTF_DPRINTF_L1(cmlog, "DREQ MAD SIZE %d", 462 sizeof (ibcm_dreq_msg_t)); 463 IBTF_DPRINTF_L1(cmlog, "DREP MAD SIZE %d", 464 sizeof (ibcm_drep_msg_t)); 465 IBTF_DPRINTF_L1(cmlog, "SIDR REQ MAD SIZE %d", 466 sizeof (ibcm_sidr_req_msg_t)); 467 IBTF_DPRINTF_L1(cmlog, "SIDR REP MAD SIZE %d", 468 sizeof (ibcm_sidr_rep_msg_t)); 469 } 470 471 #endif 472 473 /* Create all global locks within cm module */ 474 mutex_init(&ibcm_svc_info_lock, NULL, MUTEX_DEFAULT, NULL); 475 mutex_init(&ibcm_mcglist_lock, NULL, MUTEX_DEFAULT, NULL); 476 mutex_init(&ibcm_timeout_list_lock, NULL, MUTEX_DEFAULT, NULL); 477 mutex_init(&ibcm_global_hca_lock, NULL, MUTEX_DEFAULT, NULL); 478 mutex_init(&ibcm_sa_open_lock, NULL, MUTEX_DEFAULT, NULL); 479 mutex_init(&ibcm_recv_mutex, NULL, MUTEX_DEFAULT, NULL); 480 mutex_init(&ibcm_sm_notice_serialize_lock, NULL, MUTEX_DEFAULT, NULL); 481 mutex_init(&ibcm_qp_list_lock, NULL, MUTEX_DEFAULT, NULL); 482 mutex_init(&ibcm_trace_mutex, NULL, MUTEX_DEFAULT, NULL); 483 mutex_init(&ibcm_trace_print_mutex, NULL, MUTEX_DEFAULT, NULL); 484 cv_init(&ibcm_svc_info_cv, NULL, CV_DRIVER, NULL); 485 cv_init(&ibcm_timeout_list_cv, NULL, CV_DRIVER, NULL); 486 cv_init(&ibcm_timeout_thread_done_cv, NULL, CV_DRIVER, NULL); 487 cv_init(&ibcm_global_hca_cv, NULL, CV_DRIVER, NULL); 488 cv_init(&ibcm_sa_open_cv, NULL, CV_DRIVER, NULL); 489 avl_create(&ibcm_svc_avl_tree, ibcm_svc_compare, 490 sizeof (ibcm_svc_info_t), 491 offsetof(struct ibcm_svc_info_s, svc_link)); 492 493 IBTF_DPRINTF_L5(cmlog, "ibcm_init_locks: done"); 494 } 495 496 /* Destroys all global mutex and CV in cm module */ 497 static void 498 ibcm_fini_locks() 499 { 500 /* Destroy all global locks within cm module */ 501 mutex_destroy(&ibcm_svc_info_lock); 502 mutex_destroy(&ibcm_mcglist_lock); 503 mutex_destroy(&ibcm_timeout_list_lock); 504 mutex_destroy(&ibcm_global_hca_lock); 505 mutex_destroy(&ibcm_sa_open_lock); 506 mutex_destroy(&ibcm_recv_mutex); 507 mutex_destroy(&ibcm_sm_notice_serialize_lock); 508 mutex_destroy(&ibcm_qp_list_lock); 509 mutex_destroy(&ibcm_trace_mutex); 510 mutex_destroy(&ibcm_trace_print_mutex); 511 cv_destroy(&ibcm_svc_info_cv); 512 cv_destroy(&ibcm_timeout_list_cv); 513 cv_destroy(&ibcm_timeout_thread_done_cv); 514 cv_destroy(&ibcm_global_hca_cv); 515 cv_destroy(&ibcm_sa_open_cv); 516 avl_destroy(&ibcm_svc_avl_tree); 517 518 IBTF_DPRINTF_L5(cmlog, "ibcm_fini_locks: done"); 519 } 520 521 522 /* Initialize CM's classport info */ 523 static void 524 ibcm_init_classportinfo() 525 { 526 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_clpinfo)); 527 528 ibcm_clpinfo.BaseVersion = IBCM_MAD_BASE_VERSION; 529 ibcm_clpinfo.ClassVersion = IBCM_MAD_CLASS_VERSION; 530 531 /* For now, CM supports same capabilities at all ports */ 532 ibcm_clpinfo.CapabilityMask = 533 h2b16(IBCM_CPINFO_CAP_RC | IBCM_CPINFO_CAP_SIDR); 534 535 /* Bits 0-7 are all 0 for Communication Mgmt Class */ 536 537 /* For now, CM has the same respvalue at all ports */ 538 ibcm_clpinfo.RespTimeValue_plus = 539 h2b32(ibt_usec2ib(ibcm_local_processing_time) & 0x1f); 540 541 /* For now, redirect fields are set to 0 */ 542 /* Trap fields are not applicable to CM, hence set to 0 */ 543 544 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_clpinfo)); 545 IBTF_DPRINTF_L5(cmlog, "ibcm_init_classportinfo: done"); 546 } 547 548 /* 549 * ibcm_init(): 550 * - call ibt_attach() 551 * - create AVL trees 552 * - Attach HCA handlers that are already present before 553 * CM got loaded. 554 * 555 * Arguments: NONE 556 * 557 * Return values: 558 * IBCM_SUCCESS - success 559 */ 560 static ibcm_status_t 561 ibcm_init(void) 562 { 563 ibt_status_t status; 564 kthread_t *t; 565 566 IBTF_DPRINTF_L3(cmlog, "ibcm_init:"); 567 568 ibcm_init_classportinfo(); 569 570 if (ibcm_init_ids() != IBCM_SUCCESS) { 571 IBTF_DPRINTF_L1(cmlog, "ibcm_init: " 572 "fatal error: vmem_create() failed"); 573 return (IBCM_FAILURE); 574 } 575 ibcm_init_locks(); 576 577 if (ibcm_ar_init() != IBCM_SUCCESS) { 578 IBTF_DPRINTF_L1(cmlog, "ibcm_init: " 579 "fatal error: ibcm_ar_init() failed"); 580 ibcm_fini_ids(); 581 ibcm_fini_locks(); 582 return (IBCM_FAILURE); 583 } 584 ibcm_rc_flow_control_init(); 585 586 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_taskq)) 587 ibcm_taskq = system_taskq; 588 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_taskq)) 589 590 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_flags)) 591 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_thread_did)) 592 593 /* Start the timeout list processing thread */ 594 ibcm_timeout_list_flags = 0; 595 t = thread_create(NULL, 0, ibcm_process_tlist, 0, 0, &p0, TS_RUN, 596 ibcm_timeout_thread_pri); 597 ibcm_timeout_thread_did = t->t_did; 598 599 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_flags)) 600 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_thread_did)) 601 602 /* 603 * NOTE : if ibt_attach is done after ibcm_init_hcas, then some 604 * HCA DR events may be lost. CM could call re-init hca list 605 * again, but it is more complicated. Some HCA's DR's lost may 606 * be HCA detach, which makes hca list re-syncing and locking more 607 * complex 608 */ 609 status = ibt_attach(&ibcm_ibt_modinfo, NULL, NULL, &ibcm_ibt_handle); 610 if (status != IBT_SUCCESS) { 611 IBTF_DPRINTF_L2(cmlog, "ibcm_init(): ibt_attach failed %d", 612 status); 613 (void) ibcm_ar_fini(); 614 ibcm_stop_timeout_thread(); 615 ibcm_fini_ids(); 616 ibcm_fini_locks(); 617 ibcm_rc_flow_control_fini(); 618 return (IBCM_FAILURE); 619 } 620 621 /* Block all HCA attach/detach asyncs */ 622 mutex_enter(&ibcm_global_hca_lock); 623 624 ibcm_init_hcas(); 625 ibcm_finit_state = IBCM_FINIT_IDLE; 626 627 ibcm_path_cache_init(); 628 /* 629 * This callback will be used by IBTL to get the Node record for a 630 * given LID via the speccified HCA and port. 631 */ 632 ibtl_cm_set_node_info_cb(ibcm_ibtl_node_info); 633 634 /* Unblock any waiting HCA DR asyncs in CM */ 635 mutex_exit(&ibcm_global_hca_lock); 636 637 IBTF_DPRINTF_L4(cmlog, "ibcm_init: done"); 638 return (IBCM_SUCCESS); 639 } 640 641 /* Allocates and initializes the "per hca" global data in CM */ 642 static void 643 ibcm_init_hcas() 644 { 645 uint_t num_hcas = 0; 646 ib_guid_t *guid_array; 647 int i; 648 649 IBTF_DPRINTF_L5(cmlog, "ibcm_init_hcas:"); 650 651 /* Get the number of HCAs */ 652 num_hcas = ibt_get_hca_list(&guid_array); 653 IBTF_DPRINTF_L4(cmlog, "ibcm_init_hcas: ibt_get_hca_list() " 654 "returned %d hcas", num_hcas); 655 656 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 657 658 for (i = 0; i < num_hcas; i++) 659 ibcm_hca_attach(guid_array[i]); 660 661 if (num_hcas) 662 ibt_free_hca_list(guid_array, num_hcas); 663 664 IBTF_DPRINTF_L5(cmlog, "ibcm_init_hcas: done"); 665 } 666 667 668 /* 669 * ibcm_fini(): 670 * - Deregister w/ ibt 671 * - Cleanup IBCM HCA listp 672 * - Destroy mutexes 673 * 674 * Arguments: NONE 675 * 676 * Return values: 677 * IBCM_SUCCESS - success 678 */ 679 static ibcm_status_t 680 ibcm_fini(void) 681 { 682 ibt_status_t status; 683 684 IBTF_DPRINTF_L3(cmlog, "ibcm_fini:"); 685 686 /* 687 * CM assumes that the all general clients got rid of all the 688 * established connections and service registrations, completed all 689 * pending SIDR operations before a call to ibcm_fini() 690 */ 691 692 if (ibcm_ar_fini() != IBCM_SUCCESS) { 693 IBTF_DPRINTF_L2(cmlog, "ibcm_fini: ibcm_ar_fini failed"); 694 return (IBCM_FAILURE); 695 } 696 697 /* cleanup the svcinfo list */ 698 mutex_enter(&ibcm_svc_info_lock); 699 if (avl_first(&ibcm_svc_avl_tree) != NULL) { 700 IBTF_DPRINTF_L2(cmlog, "ibcm_fini: " 701 "ibcm_svc_avl_tree is not empty"); 702 mutex_exit(&ibcm_svc_info_lock); 703 return (IBCM_FAILURE); 704 } 705 mutex_exit(&ibcm_svc_info_lock); 706 707 /* disables any new hca attach/detaches */ 708 mutex_enter(&ibcm_global_hca_lock); 709 710 ibcm_finit_state = IBCM_FINIT_BUSY; 711 712 if (ibcm_fini_hcas() != IBCM_SUCCESS) { 713 IBTF_DPRINTF_L2(cmlog, "ibcm_fini: " 714 "some hca's still have client resources"); 715 716 /* First, re-initialize the hcas */ 717 ibcm_init_hcas(); 718 /* and then enable the HCA asyncs */ 719 ibcm_finit_state = IBCM_FINIT_IDLE; 720 mutex_exit(&ibcm_global_hca_lock); 721 if (ibcm_ar_init() != IBCM_SUCCESS) { 722 IBTF_DPRINTF_L1(cmlog, "ibcm_fini:ibcm_ar_init failed"); 723 } 724 return (IBCM_FAILURE); 725 } 726 727 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_hdr)) 728 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_ud_timeout_list_hdr)) 729 730 ASSERT(ibcm_timeout_list_hdr == NULL); 731 ASSERT(ibcm_ud_timeout_list_hdr == NULL); 732 733 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_hdr)) 734 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_ud_timeout_list_hdr)) 735 736 /* Release any pending asyncs on ibcm_global_hca_lock */ 737 ibcm_finit_state = IBCM_FINIT_SUCCESS; 738 mutex_exit(&ibcm_global_hca_lock); 739 740 ibcm_stop_timeout_thread(); 741 742 ibtl_cm_set_node_info_cb(NULL); 743 /* 744 * Detach from IBTL. Waits until all pending asyncs are complete. 745 * Above cv_broadcast wakes up any waiting hca attach/detach asyncs 746 */ 747 status = ibt_detach(ibcm_ibt_handle); 748 749 /* if detach fails, CM didn't free up some resources, so assert */ 750 if (status != IBT_SUCCESS) 751 IBTF_DPRINTF_L1(cmlog, "ibcm_fini: ibt_detach failed %d", 752 status); 753 754 ibcm_rc_flow_control_fini(); 755 756 ibcm_path_cache_fini(); 757 758 ibcm_fini_ids(); 759 ibcm_fini_locks(); 760 IBTF_DPRINTF_L3(cmlog, "ibcm_fini: done"); 761 return (IBCM_SUCCESS); 762 } 763 764 /* This routine exit's the ibcm timeout thread */ 765 static void 766 ibcm_stop_timeout_thread() 767 { 768 mutex_enter(&ibcm_timeout_list_lock); 769 770 /* Stop the timeout list processing thread */ 771 ibcm_timeout_list_flags = 772 ibcm_timeout_list_flags | IBCM_TIMEOUT_THREAD_EXIT; 773 774 /* Wake up, if the timeout thread is on a cv_wait */ 775 cv_signal(&ibcm_timeout_list_cv); 776 777 mutex_exit(&ibcm_timeout_list_lock); 778 thread_join(ibcm_timeout_thread_did); 779 780 IBTF_DPRINTF_L5(cmlog, "ibcm_stop_timeout_thread: done"); 781 } 782 783 784 /* Attempts to release all the hca's associated with CM */ 785 static ibcm_status_t 786 ibcm_fini_hcas() 787 { 788 ibcm_hca_info_t *hcap, *next; 789 790 IBTF_DPRINTF_L4(cmlog, "ibcm_fini_hcas:"); 791 792 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 793 794 hcap = ibcm_hca_listp; 795 while (hcap != NULL) { 796 next = hcap->hca_next; 797 if (ibcm_hca_detach(hcap) != IBCM_SUCCESS) { 798 ibcm_hca_listp = hcap; 799 return (IBCM_FAILURE); 800 } 801 hcap = next; 802 } 803 804 IBTF_DPRINTF_L4(cmlog, "ibcm_fini_hcas: SUCCEEDED"); 805 return (IBCM_SUCCESS); 806 } 807 808 809 /* 810 * ibcm_hca_attach(): 811 * Called as an asynchronous event to notify CM of an attach of HCA. 812 * Here ibcm_hca_info_t is initialized and all fields are 813 * filled in along with SA Access handles and IBMA handles. 814 * Also called from ibcm_init to initialize ibcm_hca_info_t's for each 815 * hca's 816 * 817 * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE) 818 * hca_guid - HCA's guid 819 * 820 * Return values: NONE 821 */ 822 static void 823 ibcm_hca_attach(ib_guid_t hcaguid) 824 { 825 int i; 826 ibt_status_t status; 827 uint8_t nports = 0; 828 ibcm_hca_info_t *hcap; 829 ibt_hca_attr_t hca_attrs; 830 831 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: guid = 0x%llX", hcaguid); 832 833 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 834 835 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hcap)) 836 837 status = ibt_query_hca_byguid(hcaguid, &hca_attrs); 838 if (status != IBT_SUCCESS) { 839 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: " 840 "ibt_query_hca_byguid failed = %d", status); 841 return; 842 } 843 nports = hca_attrs.hca_nports; 844 845 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_attach: num ports = %x", nports); 846 847 if ((hcap = ibcm_add_hca_entry(hcaguid, nports)) == NULL) 848 return; 849 850 hcap->hca_guid = hcaguid; /* Set GUID */ 851 hcap->hca_num_ports = nports; /* Set number of ports */ 852 853 if (ibcm_init_hca_ids(hcap) != IBCM_SUCCESS) { 854 ibcm_delete_hca_entry(hcap); 855 return; 856 } 857 858 /* Store the static hca attribute data */ 859 hcap->hca_caps = hca_attrs.hca_flags; 860 hcap->hca_vendor_id = hca_attrs.hca_vendor_id; 861 hcap->hca_device_id = hca_attrs.hca_device_id; 862 hcap->hca_ack_delay = hca_attrs.hca_local_ack_delay; 863 hcap->hca_max_rdma_in_qp = hca_attrs.hca_max_rdma_in_qp; 864 hcap->hca_max_rdma_out_qp = hca_attrs.hca_max_rdma_out_qp; 865 866 /* loop thru nports and initialize IBMF handles */ 867 for (i = 0; i < hcap->hca_num_ports; i++) { 868 status = ibt_get_port_state_byguid(hcaguid, i + 1, NULL, NULL); 869 if (status != IBT_SUCCESS) { 870 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: " 871 "port_num %d state DOWN", i + 1); 872 } 873 874 hcap->hca_port_info[i].port_hcap = hcap; 875 hcap->hca_port_info[i].port_num = i+1; 876 877 if (ibcm_hca_init_port(hcap, i) != IBT_SUCCESS) 878 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: " 879 "ibcm_hca_init_port failed %d port_num %d", 880 status, i+1); 881 } 882 883 /* create the "active" CM AVL tree */ 884 avl_create(&hcap->hca_active_tree, ibcm_active_node_compare, 885 sizeof (ibcm_state_data_t), 886 offsetof(struct ibcm_state_data_s, avl_active_link)); 887 888 /* create the "passive" CM AVL tree */ 889 avl_create(&hcap->hca_passive_tree, ibcm_passive_node_compare, 890 sizeof (ibcm_state_data_t), 891 offsetof(struct ibcm_state_data_s, avl_passive_link)); 892 893 /* create the "passive comid" CM AVL tree */ 894 avl_create(&hcap->hca_passive_comid_tree, 895 ibcm_passive_comid_node_compare, 896 sizeof (ibcm_state_data_t), 897 offsetof(struct ibcm_state_data_s, avl_passive_comid_link)); 898 899 /* 900 * Mark the state of the HCA to "attach" only at the end 901 * Now CM starts accepting incoming MADs and client API calls 902 */ 903 hcap->hca_state = IBCM_HCA_ACTIVE; 904 905 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*hcap)) 906 907 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: ATTACH Done"); 908 } 909 910 /* 911 * ibcm_hca_detach(): 912 * Called as an asynchronous event to notify CM of a detach of HCA. 913 * Here ibcm_hca_info_t is freed up and all fields that 914 * were initialized earlier are cleaned up 915 * 916 * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE) 917 * hca_guid - HCA's guid 918 * 919 * Return values: 920 * IBCM_SUCCESS - able to detach HCA 921 * IBCM_FAILURE - failed to detach HCA 922 */ 923 static ibcm_status_t 924 ibcm_hca_detach(ibcm_hca_info_t *hcap) 925 { 926 int port_index, i; 927 ibcm_status_t status = IBCM_SUCCESS; 928 clock_t absolute_time; 929 930 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach: hcap = 0x%p guid = 0x%llX", 931 hcap, hcap->hca_guid); 932 933 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 934 935 /* 936 * Declare hca is going away to all CM clients. Wait until the 937 * access count becomes zero. 938 */ 939 hcap->hca_state = IBCM_HCA_NOT_ACTIVE; 940 941 /* wait on response CV */ 942 absolute_time = ddi_get_lbolt() + 943 drv_usectohz(ibcm_wait_for_acc_cnt_timeout); 944 945 while (hcap->hca_acc_cnt > 0) 946 if (cv_timedwait(&ibcm_global_hca_cv, &ibcm_global_hca_lock, 947 absolute_time) == -1) 948 break; 949 950 if (hcap->hca_acc_cnt != 0) { 951 /* We got a timeout */ 952 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: Aborting due" 953 " to timeout on hca_acc_cnt %u, \n Some CM Clients are " 954 "still active, looks like we need to wait some more time " 955 "(ibcm_wait_for_acc_cnt_timeout).", hcap->hca_acc_cnt); 956 hcap->hca_state = IBCM_HCA_ACTIVE; 957 return (IBCM_FAILURE); 958 } 959 960 /* 961 * First make sure, there are no active users of ibma handles, 962 * and then de-register handles. 963 */ 964 965 /* make sure that there are no "Service"s registered w/ this HCA. */ 966 if (hcap->hca_svc_cnt != 0) { 967 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: " 968 "Active services still there %d", hcap->hca_svc_cnt); 969 hcap->hca_state = IBCM_HCA_ACTIVE; 970 return (IBCM_FAILURE); 971 } 972 973 if (ibcm_check_sidr_clean(hcap) != IBCM_SUCCESS) { 974 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach:" 975 "There are active SIDR operations"); 976 hcap->hca_state = IBCM_HCA_ACTIVE; 977 return (IBCM_FAILURE); 978 } 979 980 if (ibcm_check_avl_clean(hcap) != IBCM_SUCCESS) { 981 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: " 982 "There are active RC connections"); 983 hcap->hca_state = IBCM_HCA_ACTIVE; 984 return (IBCM_FAILURE); 985 } 986 987 /* 988 * Now, wait until all rc and sidr stateps go away 989 * All these stateps must be short lived ones, waiting to be cleaned 990 * up after some timeout value, based on the current state. 991 */ 992 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach:hca_guid = 0x%llX res_cnt = %d", 993 hcap->hca_guid, hcap->hca_res_cnt); 994 995 while (hcap->hca_res_cnt > 0) 996 cv_wait(&ibcm_global_hca_cv, &ibcm_global_hca_lock); 997 998 /* Re-assert the while loop step above */ 999 ASSERT(hcap->hca_sidr_list == NULL); 1000 avl_destroy(&hcap->hca_active_tree); 1001 avl_destroy(&hcap->hca_passive_tree); 1002 avl_destroy(&hcap->hca_passive_comid_tree); 1003 1004 /* 1005 * Unregister all ports from IBMA 1006 * If there is a failure, re-initialize any free'd ibma handles. This 1007 * is required to receive the incoming mads 1008 */ 1009 status = IBCM_SUCCESS; 1010 for (port_index = 0; port_index < hcap->hca_num_ports; port_index++) { 1011 if ((status = ibcm_hca_fini_port(hcap, port_index)) != 1012 IBCM_SUCCESS) { 1013 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: " 1014 "Failed to free IBMA Handle for port_num %d", 1015 port_index + 1); 1016 break; 1017 } 1018 } 1019 1020 /* If detach fails, re-initialize ibma handles for incoming mads */ 1021 if (status != IBCM_SUCCESS) { 1022 for (i = 0; i < port_index; i++) { 1023 if (ibcm_hca_init_port(hcap, i) != IBT_SUCCESS) 1024 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: " 1025 "Failed to re-allocate IBMA Handles for" 1026 " port_num %d", port_index + 1); 1027 } 1028 hcap->hca_state = IBCM_HCA_ACTIVE; 1029 return (IBCM_FAILURE); 1030 } 1031 1032 ibcm_fini_hca_ids(hcap); 1033 ibcm_delete_hca_entry(hcap); 1034 1035 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach: DETACH succeeded"); 1036 return (IBCM_SUCCESS); 1037 } 1038 1039 /* Checks, if there are any active sidr state entries in the specified hca */ 1040 static ibcm_status_t 1041 ibcm_check_sidr_clean(ibcm_hca_info_t *hcap) 1042 { 1043 ibcm_ud_state_data_t *usp; 1044 uint32_t transient_cnt = 0; 1045 1046 IBTF_DPRINTF_L5(cmlog, "ibcm_check_sidr_clean:"); 1047 1048 rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER); 1049 usp = hcap->hca_sidr_list; /* Point to the list */ 1050 while (usp != NULL) { 1051 mutex_enter(&usp->ud_state_mutex); 1052 if ((usp->ud_state != IBCM_STATE_SIDR_REP_SENT) && 1053 (usp->ud_state != IBCM_STATE_TIMED_OUT) && 1054 (usp->ud_state != IBCM_STATE_DELETE)) { 1055 1056 IBTF_DPRINTF_L3(cmlog, "ibcm_check_sidr_clean:" 1057 "usp = %p not in transient state = %d", usp, 1058 usp->ud_state); 1059 1060 mutex_exit(&usp->ud_state_mutex); 1061 rw_exit(&hcap->hca_sidr_list_lock); 1062 return (IBCM_FAILURE); 1063 } else { 1064 mutex_exit(&usp->ud_state_mutex); 1065 ++transient_cnt; 1066 } 1067 1068 usp = usp->ud_nextp; 1069 } 1070 rw_exit(&hcap->hca_sidr_list_lock); 1071 1072 IBTF_DPRINTF_L4(cmlog, "ibcm_check_sidr_clean: transient_cnt %d", 1073 transient_cnt); 1074 1075 return (IBCM_SUCCESS); 1076 } 1077 1078 /* Checks, if there are any active rc state entries, in the specified hca */ 1079 static ibcm_status_t 1080 ibcm_check_avl_clean(ibcm_hca_info_t *hcap) 1081 1082 { 1083 ibcm_state_data_t *sp; 1084 avl_tree_t *avl_tree; 1085 uint32_t transient_cnt = 0; 1086 1087 IBTF_DPRINTF_L5(cmlog, "ibcm_check_avl_clean:"); 1088 /* 1089 * Both the trees ie., active and passive must reference to all 1090 * statep's, so let's use one 1091 */ 1092 avl_tree = &hcap->hca_active_tree; 1093 1094 rw_enter(&hcap->hca_state_rwlock, RW_WRITER); 1095 1096 for (sp = avl_first(avl_tree); sp != NULL; 1097 sp = avl_walk(avl_tree, sp, AVL_AFTER)) { 1098 mutex_enter(&sp->state_mutex); 1099 if ((sp->state != IBCM_STATE_TIMEWAIT) && 1100 (sp->state != IBCM_STATE_REJ_SENT) && 1101 (sp->state != IBCM_STATE_DELETE)) { 1102 IBTF_DPRINTF_L3(cmlog, "ibcm_check_avl_clean: " 1103 "sp = %p not in transient state = %d", sp, 1104 sp->state); 1105 mutex_exit(&sp->state_mutex); 1106 rw_exit(&hcap->hca_state_rwlock); 1107 return (IBCM_FAILURE); 1108 } else { 1109 mutex_exit(&sp->state_mutex); 1110 ++transient_cnt; 1111 } 1112 } 1113 1114 rw_exit(&hcap->hca_state_rwlock); 1115 1116 IBTF_DPRINTF_L4(cmlog, "ibcm_check_avl_clean: transient_cnt %d", 1117 transient_cnt); 1118 1119 return (IBCM_SUCCESS); 1120 } 1121 1122 /* Adds a new entry into CM's global hca list, if hca_guid is not there yet */ 1123 static ibcm_hca_info_t * 1124 ibcm_add_hca_entry(ib_guid_t hcaguid, uint_t nports) 1125 { 1126 ibcm_hca_info_t *hcap; 1127 1128 IBTF_DPRINTF_L5(cmlog, "ibcm_add_hca_entry: guid = 0x%llX", 1129 hcaguid); 1130 1131 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 1132 1133 /* 1134 * Check if this hca_guid already in the list 1135 * If yes, then ignore this and return NULL 1136 */ 1137 1138 hcap = ibcm_hca_listp; 1139 1140 /* search for this HCA */ 1141 while (hcap != NULL) { 1142 if (hcap->hca_guid == hcaguid) { 1143 /* already exists */ 1144 IBTF_DPRINTF_L2(cmlog, "ibcm_add_hca_entry: " 1145 "hcap %p guid 0x%llX, entry already exists !!", 1146 hcap, hcap->hca_guid); 1147 return (NULL); 1148 } 1149 hcap = hcap->hca_next; 1150 } 1151 1152 /* Allocate storage for the new HCA entry found */ 1153 hcap = kmem_zalloc(sizeof (ibcm_hca_info_t) + 1154 (nports - 1) * sizeof (ibcm_port_info_t), KM_SLEEP); 1155 1156 /* initialize RW lock */ 1157 rw_init(&hcap->hca_state_rwlock, NULL, RW_DRIVER, NULL); 1158 /* initialize SIDR list lock */ 1159 rw_init(&hcap->hca_sidr_list_lock, NULL, RW_DRIVER, NULL); 1160 /* Insert "hcap" into the global HCA list maintained by CM */ 1161 hcap->hca_next = ibcm_hca_listp; 1162 ibcm_hca_listp = hcap; 1163 1164 IBTF_DPRINTF_L5(cmlog, "ibcm_add_hca_entry: done hcap = 0x%p", hcap); 1165 1166 return (hcap); 1167 1168 } 1169 1170 /* deletes the given ibcm_hca_info_t from CM's global hca list */ 1171 void 1172 ibcm_delete_hca_entry(ibcm_hca_info_t *hcap) 1173 { 1174 ibcm_hca_info_t *headp, *prevp = NULL; 1175 1176 /* ibcm_hca_global_lock is held */ 1177 IBTF_DPRINTF_L5(cmlog, "ibcm_delete_hca_entry: guid = 0x%llX " 1178 "hcap = 0x%p", hcap->hca_guid, hcap); 1179 1180 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 1181 1182 headp = ibcm_hca_listp; 1183 while (headp != NULL) { 1184 if (headp == hcap) { 1185 IBTF_DPRINTF_L3(cmlog, "ibcm_delete_hca_entry: " 1186 "deleting hcap %p hcaguid %llX", hcap, 1187 hcap->hca_guid); 1188 if (prevp) { 1189 prevp->hca_next = headp->hca_next; 1190 } else { 1191 prevp = headp->hca_next; 1192 ibcm_hca_listp = prevp; 1193 } 1194 rw_destroy(&hcap->hca_state_rwlock); 1195 rw_destroy(&hcap->hca_sidr_list_lock); 1196 kmem_free(hcap, sizeof (ibcm_hca_info_t) + 1197 (hcap->hca_num_ports - 1) * 1198 sizeof (ibcm_port_info_t)); 1199 return; 1200 } 1201 1202 prevp = headp; 1203 headp = headp->hca_next; 1204 } 1205 } 1206 1207 /* 1208 * ibcm_find_hca_entry: 1209 * Given a HCA's GUID find out ibcm_hca_info_t entry for that HCA 1210 * This entry can be then used to access AVL tree/SIDR list etc. 1211 * If entry exists and in HCA ATTACH state, then hca's ref cnt is 1212 * incremented and entry returned. Else NULL returned. 1213 * 1214 * All functions that use ibcm_find_hca_entry and get a non-NULL 1215 * return values must call ibcm_dec_hca_acc_cnt to decrement the 1216 * respective hca ref cnt. There shouldn't be any usage of 1217 * ibcm_hca_info_t * returned from ibcm_find_hca_entry, 1218 * after decrementing the hca_acc_cnt 1219 * 1220 * INPUTS: 1221 * hca_guid - HCA's guid 1222 * 1223 * RETURN VALUE: 1224 * hcap - if a match is found, else NULL 1225 */ 1226 ibcm_hca_info_t * 1227 ibcm_find_hca_entry(ib_guid_t hca_guid) 1228 { 1229 ibcm_hca_info_t *hcap; 1230 1231 IBTF_DPRINTF_L5(cmlog, "ibcm_find_hca_entry: guid = 0x%llX", hca_guid); 1232 1233 mutex_enter(&ibcm_global_hca_lock); 1234 1235 hcap = ibcm_hca_listp; 1236 /* search for this HCA */ 1237 while (hcap != NULL) { 1238 if (hcap->hca_guid == hca_guid) 1239 break; 1240 hcap = hcap->hca_next; 1241 } 1242 1243 /* if no hcap for the hca_guid, return NULL */ 1244 if (hcap == NULL) { 1245 mutex_exit(&ibcm_global_hca_lock); 1246 return (NULL); 1247 } 1248 1249 /* return hcap, only if it valid to use */ 1250 if (hcap->hca_state == IBCM_HCA_ACTIVE) { 1251 ++(hcap->hca_acc_cnt); 1252 1253 IBTF_DPRINTF_L5(cmlog, "ibcm_find_hca_entry: " 1254 "found hcap = 0x%p hca_acc_cnt %u", hcap, 1255 hcap->hca_acc_cnt); 1256 1257 mutex_exit(&ibcm_global_hca_lock); 1258 return (hcap); 1259 } else { 1260 mutex_exit(&ibcm_global_hca_lock); 1261 1262 IBTF_DPRINTF_L2(cmlog, "ibcm_find_hca_entry: " 1263 "found hcap = 0x%p not in active state", hcap); 1264 return (NULL); 1265 } 1266 } 1267 1268 /* 1269 * Searches for ibcm_hca_info_t entry based on hca_guid, but doesn't increment 1270 * the hca's reference count. This function is used, where the calling context 1271 * is attempting to delete hcap itself and hence acc_cnt cannot be incremented 1272 * OR assumes that valid hcap must be available in ibcm's global hca list. 1273 */ 1274 ibcm_hca_info_t * 1275 ibcm_find_hcap_entry(ib_guid_t hca_guid) 1276 { 1277 ibcm_hca_info_t *hcap; 1278 1279 IBTF_DPRINTF_L5(cmlog, "ibcm_find_hcap_entry: guid = 0x%llX", hca_guid); 1280 1281 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 1282 1283 hcap = ibcm_hca_listp; 1284 /* search for this HCA */ 1285 while (hcap != NULL) { 1286 if (hcap->hca_guid == hca_guid) 1287 break; 1288 hcap = hcap->hca_next; 1289 } 1290 1291 if (hcap == NULL) 1292 IBTF_DPRINTF_L2(cmlog, "ibcm_find_hcap_entry: No hcap found for" 1293 " hca_guid 0x%llX", hca_guid); 1294 else 1295 IBTF_DPRINTF_L5(cmlog, "ibcm_find_hcap_entry: hcap found for" 1296 " hca_guid 0x%llX", hca_guid); 1297 1298 return (hcap); 1299 } 1300 1301 /* increment the hca's temporary reference count */ 1302 ibcm_status_t 1303 ibcm_inc_hca_acc_cnt(ibcm_hca_info_t *hcap) 1304 { 1305 mutex_enter(&ibcm_global_hca_lock); 1306 if (hcap->hca_state == IBCM_HCA_ACTIVE) { 1307 ++(hcap->hca_acc_cnt); 1308 IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_acc_cnt: " 1309 "hcap = 0x%p acc_cnt = %d ", hcap, hcap->hca_acc_cnt); 1310 mutex_exit(&ibcm_global_hca_lock); 1311 return (IBCM_SUCCESS); 1312 } else { 1313 IBTF_DPRINTF_L2(cmlog, "ibcm_inc_hca_acc_cnt: " 1314 "hcap INACTIVE 0x%p acc_cnt = %d ", hcap, 1315 hcap->hca_acc_cnt); 1316 mutex_exit(&ibcm_global_hca_lock); 1317 return (IBCM_FAILURE); 1318 } 1319 } 1320 1321 /* decrement the hca's ref count, and wake up any waiting threads */ 1322 void 1323 ibcm_dec_hca_acc_cnt(ibcm_hca_info_t *hcap) 1324 { 1325 mutex_enter(&ibcm_global_hca_lock); 1326 ASSERT(hcap->hca_acc_cnt > 0); 1327 --(hcap->hca_acc_cnt); 1328 IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_acc_cnt: hcap = 0x%p " 1329 "acc_cnt = %d", hcap, hcap->hca_acc_cnt); 1330 if ((hcap->hca_state == IBCM_HCA_NOT_ACTIVE) && 1331 (hcap->hca_acc_cnt == 0)) { 1332 IBTF_DPRINTF_L3(cmlog, "ibcm_dec_hca_acc_cnt: " 1333 "cv_broadcast for hcap = 0x%p", hcap); 1334 cv_broadcast(&ibcm_global_hca_cv); 1335 } 1336 mutex_exit(&ibcm_global_hca_lock); 1337 } 1338 1339 /* increment the hca's resource count */ 1340 void 1341 ibcm_inc_hca_res_cnt(ibcm_hca_info_t *hcap) 1342 1343 { 1344 mutex_enter(&ibcm_global_hca_lock); 1345 ++(hcap->hca_res_cnt); 1346 IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_res_cnt: hcap = 0x%p " 1347 "ref_cnt = %d", hcap, hcap->hca_res_cnt); 1348 mutex_exit(&ibcm_global_hca_lock); 1349 } 1350 1351 /* decrement the hca's resource count, and wake up any waiting threads */ 1352 void 1353 ibcm_dec_hca_res_cnt(ibcm_hca_info_t *hcap) 1354 { 1355 mutex_enter(&ibcm_global_hca_lock); 1356 ASSERT(hcap->hca_res_cnt > 0); 1357 --(hcap->hca_res_cnt); 1358 IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_res_cnt: hcap = 0x%p " 1359 "ref_cnt = %d", hcap, hcap->hca_res_cnt); 1360 if ((hcap->hca_state == IBCM_HCA_NOT_ACTIVE) && 1361 (hcap->hca_res_cnt == 0)) { 1362 IBTF_DPRINTF_L3(cmlog, "ibcm_dec_hca_res_cnt: " 1363 "cv_broadcast for hcap = 0x%p", hcap); 1364 cv_broadcast(&ibcm_global_hca_cv); 1365 } 1366 mutex_exit(&ibcm_global_hca_lock); 1367 } 1368 1369 /* increment the hca's service count */ 1370 void 1371 ibcm_inc_hca_svc_cnt(ibcm_hca_info_t *hcap) 1372 1373 { 1374 mutex_enter(&ibcm_global_hca_lock); 1375 ++(hcap->hca_svc_cnt); 1376 IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_svc_cnt: hcap = 0x%p " 1377 "svc_cnt = %d", hcap, hcap->hca_svc_cnt); 1378 mutex_exit(&ibcm_global_hca_lock); 1379 } 1380 1381 /* decrement the hca's service count */ 1382 void 1383 ibcm_dec_hca_svc_cnt(ibcm_hca_info_t *hcap) 1384 { 1385 mutex_enter(&ibcm_global_hca_lock); 1386 ASSERT(hcap->hca_svc_cnt > 0); 1387 --(hcap->hca_svc_cnt); 1388 IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_svc_cnt: hcap = 0x%p " 1389 "svc_cnt = %d", hcap, hcap->hca_svc_cnt); 1390 mutex_exit(&ibcm_global_hca_lock); 1391 } 1392 1393 /* 1394 * The following code manages three classes of requests that CM makes to 1395 * the fabric. Those three classes are SA_ACCESS, REQ/REP/RTU, and DREQ/DREP. 1396 * The main issue is that the fabric can become very busy, and the CM 1397 * protocols rely on responses being made based on a predefined timeout 1398 * value. By managing how many simultaneous sessions are allowed, there 1399 * is observed extremely high reliability of CM protocol succeeding when 1400 * it should. 1401 * 1402 * SA_ACCESS and DREQ/DREP are managed at the thread level, whereby the 1403 * thread blocks until there are less than some number of threads doing 1404 * similar requests. 1405 * 1406 * REQ/REP/RTU requests beyond a given limit are added to a list, 1407 * allowing the thread to return immediately to its caller in the 1408 * case where the "mode" is IBT_NONBLOCKING. This is the mode used 1409 * by uDAPL and seems to be an important feature/behavior. 1410 */ 1411 1412 static int 1413 ibcm_ok_to_start(struct ibcm_open_s *openp) 1414 { 1415 return (openp->sends < openp->sends_hiwat && 1416 openp->in_progress < openp->in_progress_max); 1417 } 1418 1419 void 1420 ibcm_open_done(ibcm_state_data_t *statep) 1421 { 1422 int run; 1423 ibcm_state_data_t **linkp, *tmp; 1424 1425 ASSERT(MUTEX_HELD(&statep->state_mutex)); 1426 if (statep->open_flow == 1) { 1427 statep->open_flow = 0; 1428 mutex_enter(&ibcm_open.mutex); 1429 if (statep->open_link == NULL) { 1430 ibcm_open.in_progress--; 1431 run = ibcm_ok_to_start(&ibcm_open); 1432 } else { 1433 ibcm_open.queued--; 1434 linkp = &ibcm_open.head.open_link; 1435 while (*linkp != statep) 1436 linkp = &((*linkp)->open_link); 1437 *linkp = statep->open_link; 1438 statep->open_link = NULL; 1439 /* 1440 * If we remove what tail pointed to, we need 1441 * to reassign tail (it is never NULL). 1442 * tail points to head for the empty list. 1443 */ 1444 if (ibcm_open.tail == statep) { 1445 tmp = &ibcm_open.head; 1446 while (tmp->open_link != &ibcm_open.head) 1447 tmp = tmp->open_link; 1448 ibcm_open.tail = tmp; 1449 } 1450 run = 0; 1451 } 1452 mutex_exit(&ibcm_open.mutex); 1453 if (run) 1454 ibcm_run_tlist_thread(); 1455 } 1456 } 1457 1458 /* dtrace */ 1459 void 1460 ibcm_open_wait(hrtime_t delta) 1461 { 1462 if (delta > 1000000) 1463 IBTF_DPRINTF_L2(cmlog, "ibcm_open_wait: flow more %lld", delta); 1464 } 1465 1466 void 1467 ibcm_open_start(ibcm_state_data_t *statep) 1468 { 1469 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REQ); 1470 1471 mutex_enter(&statep->state_mutex); 1472 ibcm_open_wait(gethrtime() - statep->post_time); 1473 mutex_exit(&statep->state_mutex); 1474 1475 ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_req_complete, 1476 statep); 1477 1478 mutex_enter(&statep->state_mutex); 1479 IBCM_REF_CNT_DECR(statep); 1480 mutex_exit(&statep->state_mutex); 1481 } 1482 1483 void 1484 ibcm_open_enqueue(ibcm_state_data_t *statep) 1485 { 1486 int run; 1487 1488 mutex_enter(&statep->state_mutex); 1489 statep->post_time = gethrtime(); 1490 mutex_exit(&statep->state_mutex); 1491 mutex_enter(&ibcm_open.mutex); 1492 if (ibcm_open.queued == 0 && ibcm_ok_to_start(&ibcm_open)) { 1493 ibcm_open.in_progress++; 1494 mutex_exit(&ibcm_open.mutex); 1495 ibcm_open_start(statep); 1496 } else { 1497 ibcm_open.queued++; 1498 statep->open_link = &ibcm_open.head; 1499 ibcm_open.tail->open_link = statep; 1500 ibcm_open.tail = statep; 1501 run = ibcm_ok_to_start(&ibcm_open); 1502 mutex_exit(&ibcm_open.mutex); 1503 if (run) 1504 ibcm_run_tlist_thread(); 1505 } 1506 } 1507 1508 ibcm_state_data_t * 1509 ibcm_open_dequeue(void) 1510 { 1511 ibcm_state_data_t *statep; 1512 1513 ASSERT(MUTEX_HELD(&ibcm_open.mutex)); 1514 ibcm_open.queued--; 1515 ibcm_open.in_progress++; 1516 statep = ibcm_open.head.open_link; 1517 ibcm_open.head.open_link = statep->open_link; 1518 statep->open_link = NULL; 1519 /* 1520 * If we remove what tail pointed to, we need 1521 * to reassign tail (it is never NULL). 1522 * tail points to head for the empty list. 1523 */ 1524 if (ibcm_open.tail == statep) 1525 ibcm_open.tail = &ibcm_open.head; 1526 return (statep); 1527 } 1528 1529 void 1530 ibcm_check_for_opens(void) 1531 { 1532 ibcm_state_data_t *statep; 1533 1534 mutex_enter(&ibcm_open.mutex); 1535 1536 while (ibcm_open.queued > 0) { 1537 if (ibcm_ok_to_start(&ibcm_open)) { 1538 statep = ibcm_open_dequeue(); 1539 mutex_exit(&ibcm_open.mutex); 1540 1541 ibcm_open_start(statep); 1542 1543 mutex_enter(&ibcm_open.mutex); 1544 } else { 1545 break; 1546 } 1547 } 1548 mutex_exit(&ibcm_open.mutex); 1549 } 1550 1551 1552 static void 1553 ibcm_flow_init(ibcm_flow_t *flow, uint_t simul_max) 1554 { 1555 flow->list = NULL; 1556 flow->simul = 0; 1557 flow->waiters_per_chunk = 4; 1558 flow->simul_max = simul_max; 1559 flow->lowat = simul_max - flow->waiters_per_chunk; 1560 flow->lowat_default = flow->lowat; 1561 /* stats */ 1562 flow->total = 0; 1563 } 1564 1565 static void 1566 ibcm_rc_flow_control_init(void) 1567 { 1568 mutex_init(&ibcm_open.mutex, NULL, MUTEX_DEFAULT, NULL); 1569 mutex_enter(&ibcm_open.mutex); 1570 ibcm_flow_init(&ibcm_close_flow, ibcm_close_simul_max); 1571 ibcm_flow_init(&ibcm_lapr_flow, ibcm_lapr_simul_max); 1572 ibcm_flow_init(&ibcm_saa_flow, ibcm_saa_simul_max); 1573 1574 ibcm_open.queued = 0; 1575 ibcm_open.exit_deferred = 0; 1576 ibcm_open.in_progress = 0; 1577 ibcm_open.in_progress_max = 16; 1578 ibcm_open.sends = 0; 1579 ibcm_open.sends_max = 0; 1580 ibcm_open.sends_lowat = 8; 1581 ibcm_open.sends_hiwat = 16; 1582 ibcm_open.tail = &ibcm_open.head; 1583 ibcm_open.head.open_link = NULL; 1584 mutex_exit(&ibcm_open.mutex); 1585 1586 mutex_init(&ibcm_close.mutex, NULL, MUTEX_DEFAULT, NULL); 1587 mutex_enter(&ibcm_close.mutex); 1588 ibcm_close.tail = &ibcm_close.head; 1589 ibcm_close.head.close_link = NULL; 1590 mutex_exit(&ibcm_close.mutex); 1591 } 1592 1593 static void 1594 ibcm_rc_flow_control_fini(void) 1595 { 1596 mutex_destroy(&ibcm_open.mutex); 1597 mutex_destroy(&ibcm_close.mutex); 1598 } 1599 1600 static ibcm_flow1_t * 1601 ibcm_flow_find(ibcm_flow_t *flow) 1602 { 1603 ibcm_flow1_t *flow1; 1604 ibcm_flow1_t *f; 1605 1606 f = flow->list; 1607 if (f) { /* most likely code path */ 1608 while (f->link != NULL) 1609 f = f->link; 1610 if (f->waiters < flow->waiters_per_chunk) 1611 return (f); 1612 } 1613 1614 /* There was no flow1 list element ready for another waiter */ 1615 mutex_exit(&ibcm_open.mutex); 1616 flow1 = kmem_alloc(sizeof (*flow1), KM_SLEEP); 1617 mutex_enter(&ibcm_open.mutex); 1618 1619 f = flow->list; 1620 if (f) { 1621 while (f->link != NULL) 1622 f = f->link; 1623 if (f->waiters < flow->waiters_per_chunk) { 1624 kmem_free(flow1, sizeof (*flow1)); 1625 return (f); 1626 } 1627 f->link = flow1; 1628 } else { 1629 flow->list = flow1; 1630 } 1631 cv_init(&flow1->cv, NULL, CV_DRIVER, NULL); 1632 flow1->waiters = 0; 1633 flow1->link = NULL; 1634 return (flow1); 1635 } 1636 1637 static void 1638 ibcm_flow_enter(ibcm_flow_t *flow) 1639 { 1640 mutex_enter(&ibcm_open.mutex); 1641 if (flow->list == NULL && flow->simul < flow->simul_max) { 1642 flow->simul++; 1643 flow->total++; 1644 mutex_exit(&ibcm_open.mutex); 1645 } else { 1646 ibcm_flow1_t *flow1; 1647 1648 flow1 = ibcm_flow_find(flow); 1649 flow1->waiters++; 1650 cv_wait(&flow1->cv, &ibcm_open.mutex); 1651 if (--flow1->waiters == 0) { 1652 cv_destroy(&flow1->cv); 1653 mutex_exit(&ibcm_open.mutex); 1654 kmem_free(flow1, sizeof (*flow1)); 1655 } else 1656 mutex_exit(&ibcm_open.mutex); 1657 } 1658 } 1659 1660 static void 1661 ibcm_flow_exit(ibcm_flow_t *flow) 1662 { 1663 mutex_enter(&ibcm_open.mutex); 1664 if (--flow->simul < flow->lowat) { 1665 if (flow->lowat < flow->lowat_default) 1666 flow->lowat++; 1667 if (flow->list) { 1668 ibcm_flow1_t *flow1; 1669 1670 flow1 = flow->list; 1671 flow->list = flow1->link; /* unlink */ 1672 flow1->link = NULL; /* be clean */ 1673 flow->total += flow1->waiters; 1674 flow->simul += flow1->waiters; 1675 cv_broadcast(&flow1->cv); 1676 } 1677 } 1678 mutex_exit(&ibcm_open.mutex); 1679 } 1680 1681 void 1682 ibcm_flow_inc(void) 1683 { 1684 mutex_enter(&ibcm_open.mutex); 1685 if (++ibcm_open.sends > ibcm_open.sends_max) { 1686 ibcm_open.sends_max = ibcm_open.sends; 1687 IBTF_DPRINTF_L2(cmlog, "ibcm_flow_inc: sends max = %d", 1688 ibcm_open.sends_max); 1689 } 1690 mutex_exit(&ibcm_open.mutex); 1691 } 1692 1693 static void 1694 ibcm_check_send_cmpltn_time(hrtime_t delta, char *event_msg) 1695 { 1696 if (delta > 4000000LL) { 1697 IBTF_DPRINTF_L2(cmlog, "ibcm_check_send_cmpltn_time: " 1698 "%s: %lldns", event_msg, delta); 1699 } 1700 } 1701 1702 void 1703 ibcm_flow_dec(hrtime_t time, char *mad_type) 1704 { 1705 int flow_exit = 0; 1706 int run = 0; 1707 1708 if (ibcm_dtrace) 1709 ibcm_check_send_cmpltn_time(gethrtime() - time, mad_type); 1710 mutex_enter(&ibcm_open.mutex); 1711 ibcm_open.sends--; 1712 if (ibcm_open.sends < ibcm_open.sends_lowat) { 1713 run = ibcm_ok_to_start(&ibcm_open); 1714 if (ibcm_open.exit_deferred) { 1715 ibcm_open.exit_deferred--; 1716 flow_exit = 1; 1717 } 1718 } 1719 mutex_exit(&ibcm_open.mutex); 1720 if (flow_exit) 1721 ibcm_flow_exit(&ibcm_close_flow); 1722 if (run) 1723 ibcm_run_tlist_thread(); 1724 } 1725 1726 void 1727 ibcm_close_enqueue(ibcm_state_data_t *statep) 1728 { 1729 mutex_enter(&ibcm_close.mutex); 1730 statep->close_link = NULL; 1731 ibcm_close.tail->close_link = statep; 1732 ibcm_close.tail = statep; 1733 mutex_exit(&ibcm_close.mutex); 1734 ibcm_run_tlist_thread(); 1735 } 1736 1737 void 1738 ibcm_check_for_async_close() 1739 { 1740 ibcm_state_data_t *statep; 1741 1742 mutex_enter(&ibcm_close.mutex); 1743 1744 while (ibcm_close.head.close_link) { 1745 statep = ibcm_close.head.close_link; 1746 ibcm_close.head.close_link = statep->close_link; 1747 statep->close_link = NULL; 1748 if (ibcm_close.tail == statep) 1749 ibcm_close.tail = &ibcm_close.head; 1750 mutex_exit(&ibcm_close.mutex); 1751 ibcm_close_start(statep); 1752 mutex_enter(&ibcm_close.mutex); 1753 } 1754 mutex_exit(&ibcm_close.mutex); 1755 } 1756 1757 void 1758 ibcm_close_enter(void) 1759 { 1760 ibcm_flow_enter(&ibcm_close_flow); 1761 } 1762 1763 void 1764 ibcm_close_exit(void) 1765 { 1766 int flow_exit; 1767 1768 mutex_enter(&ibcm_open.mutex); 1769 if (ibcm_open.sends < ibcm_open.sends_lowat || 1770 ibcm_open.exit_deferred >= 4) 1771 flow_exit = 1; 1772 else { 1773 flow_exit = 0; 1774 ibcm_open.exit_deferred++; 1775 } 1776 mutex_exit(&ibcm_open.mutex); 1777 if (flow_exit) 1778 ibcm_flow_exit(&ibcm_close_flow); 1779 } 1780 1781 /* 1782 * This function needs to be called twice to finish our flow 1783 * control accounting when closing down a connection. One 1784 * call has send_done set to 1, while the other has it set to 0. 1785 * Because of retries, this could get called more than once 1786 * with either 0 or 1, but additional calls have no effect. 1787 */ 1788 void 1789 ibcm_close_done(ibcm_state_data_t *statep, int send_done) 1790 { 1791 int flow_exit; 1792 1793 ASSERT(MUTEX_HELD(&statep->state_mutex)); 1794 if (statep->close_flow == 1) { 1795 if (send_done) 1796 statep->close_flow = 3; 1797 else 1798 statep->close_flow = 2; 1799 } else if ((send_done && statep->close_flow == 2) || 1800 (!send_done && statep->close_flow == 3)) { 1801 statep->close_flow = 0; 1802 mutex_enter(&ibcm_open.mutex); 1803 if (ibcm_open.sends < ibcm_open.sends_lowat || 1804 ibcm_open.exit_deferred >= 4) 1805 flow_exit = 1; 1806 else { 1807 flow_exit = 0; 1808 ibcm_open.exit_deferred++; 1809 } 1810 mutex_exit(&ibcm_open.mutex); 1811 if (flow_exit) 1812 ibcm_flow_exit(&ibcm_close_flow); 1813 } 1814 } 1815 1816 void 1817 ibcm_lapr_enter(void) 1818 { 1819 ibcm_flow_enter(&ibcm_lapr_flow); 1820 } 1821 1822 void 1823 ibcm_lapr_exit(void) 1824 { 1825 ibcm_flow_exit(&ibcm_lapr_flow); 1826 } 1827 1828 void 1829 ibcm_sa_access_enter() 1830 { 1831 ibcm_flow_enter(&ibcm_saa_flow); 1832 } 1833 1834 void 1835 ibcm_sa_access_exit() 1836 { 1837 ibcm_flow_exit(&ibcm_saa_flow); 1838 } 1839 1840 static void 1841 ibcm_sm_notice_handler(ibmf_saa_handle_t saa_handle, 1842 ibmf_saa_subnet_event_t saa_event_code, 1843 ibmf_saa_event_details_t *saa_event_details, 1844 void *callback_arg) 1845 { 1846 ibcm_port_info_t *portp = (ibcm_port_info_t *)callback_arg; 1847 ibt_subnet_event_code_t code; 1848 ibt_subnet_event_t event; 1849 uint8_t event_status; 1850 1851 IBTF_DPRINTF_L3(cmlog, "ibcm_sm_notice_handler: saa_hdl %p, code = %d", 1852 saa_handle, saa_event_code); 1853 1854 mutex_enter(&ibcm_sm_notice_serialize_lock); 1855 1856 switch (saa_event_code) { 1857 case IBMF_SAA_EVENT_MCG_CREATED: 1858 code = IBT_SM_EVENT_MCG_CREATED; 1859 break; 1860 case IBMF_SAA_EVENT_MCG_DELETED: 1861 code = IBT_SM_EVENT_MCG_DELETED; 1862 break; 1863 case IBMF_SAA_EVENT_GID_AVAILABLE: 1864 code = IBT_SM_EVENT_GID_AVAIL; 1865 ibcm_path_cache_purge(); 1866 break; 1867 case IBMF_SAA_EVENT_GID_UNAVAILABLE: 1868 code = IBT_SM_EVENT_GID_UNAVAIL; 1869 ibcm_path_cache_purge(); 1870 break; 1871 case IBMF_SAA_EVENT_SUBSCRIBER_STATUS_CHG: 1872 event_status = 1873 saa_event_details->ie_producer_event_status_mask & 1874 IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM; 1875 if (event_status == (portp->port_event_status & 1876 IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM)) { 1877 mutex_exit(&ibcm_sm_notice_serialize_lock); 1878 return; /* no change */ 1879 } 1880 portp->port_event_status = event_status; 1881 if (event_status == IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM) 1882 code = IBT_SM_EVENT_AVAILABLE; 1883 else 1884 code = IBT_SM_EVENT_UNAVAILABLE; 1885 break; 1886 default: 1887 mutex_exit(&ibcm_sm_notice_serialize_lock); 1888 return; 1889 } 1890 1891 mutex_enter(&ibcm_global_hca_lock); 1892 1893 /* don't send the event if we're tearing down */ 1894 if (!IBCM_ACCESS_HCA_OK(portp->port_hcap)) { 1895 mutex_exit(&ibcm_global_hca_lock); 1896 mutex_exit(&ibcm_sm_notice_serialize_lock); 1897 return; 1898 } 1899 1900 ++(portp->port_hcap->hca_acc_cnt); 1901 mutex_exit(&ibcm_global_hca_lock); 1902 1903 event.sm_notice_gid = saa_event_details->ie_gid; 1904 ibtl_cm_sm_notice_handler(portp->port_sgid0, code, &event); 1905 1906 mutex_exit(&ibcm_sm_notice_serialize_lock); 1907 1908 ibcm_dec_hca_acc_cnt(portp->port_hcap); 1909 } 1910 1911 void 1912 ibt_register_subnet_notices(ibt_clnt_hdl_t ibt_hdl, 1913 ibt_sm_notice_handler_t sm_notice_handler, void *private) 1914 { 1915 ibcm_port_info_t *portp; 1916 ibcm_hca_info_t *hcap; 1917 uint8_t port; 1918 int num_failed_sgids; 1919 ibtl_cm_sm_init_fail_t *ifail; 1920 ib_gid_t *sgidp; 1921 1922 IBTF_DPRINTF_L3(cmlog, "ibt_register_subnet_notices(%p, %s)", 1923 ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl)); 1924 1925 mutex_enter(&ibcm_sm_notice_serialize_lock); 1926 1927 ibtl_cm_set_sm_notice_handler(ibt_hdl, sm_notice_handler, private); 1928 if (sm_notice_handler == NULL) { 1929 mutex_exit(&ibcm_sm_notice_serialize_lock); 1930 return; 1931 } 1932 1933 /* for each port, if service is not available, make a call */ 1934 mutex_enter(&ibcm_global_hca_lock); 1935 num_failed_sgids = 0; 1936 hcap = ibcm_hca_listp; 1937 while (hcap != NULL) { 1938 portp = hcap->hca_port_info; 1939 for (port = 0; port < hcap->hca_num_ports; port++) { 1940 if (!(portp->port_event_status & 1941 IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM)) 1942 num_failed_sgids++; 1943 portp++; 1944 } 1945 hcap = hcap->hca_next; 1946 } 1947 if (num_failed_sgids != 0) { 1948 ifail = kmem_alloc(sizeof (*ifail) + 1949 (num_failed_sgids - 1) * sizeof (ib_gid_t), KM_SLEEP); 1950 ifail->smf_num_sgids = num_failed_sgids; 1951 ifail->smf_ibt_hdl = ibt_hdl; 1952 sgidp = &ifail->smf_sgid[0]; 1953 hcap = ibcm_hca_listp; 1954 while (hcap != NULL) { 1955 portp = hcap->hca_port_info; 1956 for (port = 0; port < hcap->hca_num_ports; port++) { 1957 if (!(portp->port_event_status & 1958 IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM)) 1959 *sgidp++ = portp->port_sgid0; 1960 portp++; 1961 } 1962 hcap = hcap->hca_next; 1963 } 1964 } 1965 mutex_exit(&ibcm_global_hca_lock); 1966 1967 if (num_failed_sgids != 0) { 1968 ibtl_cm_sm_notice_init_failure(ifail); 1969 kmem_free(ifail, sizeof (*ifail) + 1970 (num_failed_sgids - 1) * sizeof (ib_gid_t)); 1971 } 1972 mutex_exit(&ibcm_sm_notice_serialize_lock); 1973 } 1974 1975 /* The following is run from a taskq because we've seen the stack overflow. */ 1976 static void 1977 ibcm_init_saa(void *arg) 1978 { 1979 ibcm_port_info_t *portp = (ibcm_port_info_t *)arg; 1980 int status; 1981 ib_guid_t port_guid; 1982 ibmf_saa_subnet_event_args_t event_args; 1983 1984 port_guid = portp->port_sgid0.gid_guid; 1985 1986 IBTF_DPRINTF_L3(cmlog, "ibcm_init_saa: port guid %llX", port_guid); 1987 1988 event_args.is_event_callback_arg = portp; 1989 event_args.is_event_callback = ibcm_sm_notice_handler; 1990 1991 if ((status = ibmf_sa_session_open(port_guid, 0, &event_args, 1992 IBMF_VERSION, 0, &portp->port_ibmf_saa_hdl)) != IBMF_SUCCESS) { 1993 IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa: " 1994 "ibmf_sa_session_open failed for port guid %llX " 1995 "status = %d", port_guid, status); 1996 } else { 1997 IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa: " 1998 "registered sa_hdl 0x%p for port guid %llX", 1999 portp->port_ibmf_saa_hdl, port_guid); 2000 } 2001 2002 mutex_enter(&ibcm_sa_open_lock); 2003 portp->port_saa_open_in_progress = 0; 2004 cv_broadcast(&ibcm_sa_open_cv); 2005 mutex_exit(&ibcm_sa_open_lock); 2006 } 2007 2008 void 2009 ibcm_init_saa_handle(ibcm_hca_info_t *hcap, uint8_t port) 2010 { 2011 ibmf_saa_handle_t saa_handle; 2012 uint8_t port_index = port - 1; 2013 ibcm_port_info_t *portp = &hcap->hca_port_info[port_index]; 2014 ibt_status_t ibt_status; 2015 2016 if (port_index >= hcap->hca_num_ports) 2017 return; 2018 2019 mutex_enter(&ibcm_sa_open_lock); 2020 if (portp->port_saa_open_in_progress) { 2021 mutex_exit(&ibcm_sa_open_lock); 2022 return; 2023 } 2024 2025 saa_handle = portp->port_ibmf_saa_hdl; 2026 if (saa_handle != NULL) { 2027 mutex_exit(&ibcm_sa_open_lock); 2028 return; 2029 } 2030 2031 portp->port_saa_open_in_progress = 1; 2032 mutex_exit(&ibcm_sa_open_lock); 2033 2034 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(portp->port_event_status)) 2035 2036 /* The assumption is that we're getting event notifications */ 2037 portp->port_event_status = IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM; 2038 2039 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(portp->port_event_status)) 2040 2041 ibt_status = ibt_get_port_state_byguid(portp->port_hcap->hca_guid, 2042 portp->port_num, &portp->port_sgid0, NULL); 2043 if (ibt_status != IBT_SUCCESS) { 2044 IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa_handle: " 2045 "ibt_get_port_state_byguid failed for guid %llX " 2046 "with status %d", portp->port_hcap->hca_guid, ibt_status); 2047 mutex_enter(&ibcm_sa_open_lock); 2048 portp->port_saa_open_in_progress = 0; 2049 cv_broadcast(&ibcm_sa_open_cv); 2050 mutex_exit(&ibcm_sa_open_lock); 2051 return; 2052 } 2053 /* if the port is UP, try sa_session_open */ 2054 (void) taskq_dispatch(ibcm_taskq, ibcm_init_saa, portp, TQ_SLEEP); 2055 } 2056 2057 2058 ibmf_saa_handle_t 2059 ibcm_get_saa_handle(ibcm_hca_info_t *hcap, uint8_t port) 2060 { 2061 ibmf_saa_handle_t saa_handle; 2062 uint8_t port_index = port - 1; 2063 ibcm_port_info_t *portp = &hcap->hca_port_info[port_index]; 2064 ibt_status_t ibt_status; 2065 2066 if (port_index >= hcap->hca_num_ports) 2067 return (NULL); 2068 2069 mutex_enter(&ibcm_sa_open_lock); 2070 while (portp->port_saa_open_in_progress) { 2071 cv_wait(&ibcm_sa_open_cv, &ibcm_sa_open_lock); 2072 } 2073 2074 saa_handle = portp->port_ibmf_saa_hdl; 2075 if (saa_handle != NULL) { 2076 mutex_exit(&ibcm_sa_open_lock); 2077 return (saa_handle); 2078 } 2079 2080 portp->port_saa_open_in_progress = 1; 2081 mutex_exit(&ibcm_sa_open_lock); 2082 2083 ibt_status = ibt_get_port_state_byguid(portp->port_hcap->hca_guid, 2084 portp->port_num, &portp->port_sgid0, NULL); 2085 if (ibt_status != IBT_SUCCESS) { 2086 IBTF_DPRINTF_L2(cmlog, "ibcm_get_saa_handle: " 2087 "ibt_get_port_state_byguid failed for guid %llX " 2088 "with status %d", portp->port_hcap->hca_guid, ibt_status); 2089 mutex_enter(&ibcm_sa_open_lock); 2090 portp->port_saa_open_in_progress = 0; 2091 cv_broadcast(&ibcm_sa_open_cv); 2092 mutex_exit(&ibcm_sa_open_lock); 2093 return (NULL); 2094 } 2095 /* if the port is UP, try sa_session_open */ 2096 (void) taskq_dispatch(ibcm_taskq, ibcm_init_saa, portp, TQ_SLEEP); 2097 2098 mutex_enter(&ibcm_sa_open_lock); 2099 while (portp->port_saa_open_in_progress) { 2100 cv_wait(&ibcm_sa_open_cv, &ibcm_sa_open_lock); 2101 } 2102 saa_handle = portp->port_ibmf_saa_hdl; 2103 mutex_exit(&ibcm_sa_open_lock); 2104 return (saa_handle); 2105 } 2106 2107 2108 /* 2109 * ibcm_hca_init_port(): 2110 * - Register port with IBMA 2111 * 2112 * Arguments: 2113 * hcap - HCA's guid 2114 * port_index - port number minus 1 2115 * 2116 * Return values: 2117 * IBCM_SUCCESS - success 2118 */ 2119 ibt_status_t 2120 ibcm_hca_init_port(ibcm_hca_info_t *hcap, uint8_t port_index) 2121 { 2122 int status; 2123 ibmf_register_info_t *ibmf_reg; 2124 2125 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_init_port: hcap = 0x%p port_num %d", 2126 hcap, port_index + 1); 2127 2128 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 2129 2130 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(hcap->hca_port_info)) 2131 2132 if (hcap->hca_port_info[port_index].port_ibmf_hdl == NULL) { 2133 /* Register with IBMF */ 2134 ibmf_reg = &hcap->hca_port_info[port_index].port_ibmf_reg; 2135 ibmf_reg->ir_ci_guid = hcap->hca_guid; 2136 ibmf_reg->ir_port_num = port_index + 1; 2137 ibmf_reg->ir_client_class = COMM_MGT_MANAGER_AGENT; 2138 2139 /* 2140 * register with management framework 2141 */ 2142 status = ibmf_register(ibmf_reg, IBMF_VERSION, 2143 IBMF_REG_FLAG_NO_OFFLOAD, NULL, NULL, 2144 &(hcap->hca_port_info[port_index].port_ibmf_hdl), 2145 &(hcap->hca_port_info[port_index].port_ibmf_caps)); 2146 2147 if (status != IBMF_SUCCESS) { 2148 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_init_port: " 2149 "ibmf_register failed for port_num %x, " 2150 "status = %x", port_index + 1, status); 2151 return (ibcm_ibmf_analyze_error(status)); 2152 } 2153 2154 hcap->hca_port_info[port_index].port_qp1.qp_cm = 2155 IBMF_QP_HANDLE_DEFAULT; 2156 hcap->hca_port_info[port_index].port_qp1.qp_port = 2157 &(hcap->hca_port_info[port_index]); 2158 2159 /* 2160 * Register the read callback with IBMF. 2161 * Since we just did an ibmf_register, handle is 2162 * valid and ibcm_recv_cb() is valid so we can 2163 * safely assert for success of ibmf_setup_recv_cb() 2164 * 2165 * Depending on the "state" of the HCA, 2166 * CM may drop incoming packets 2167 */ 2168 status = ibmf_setup_async_cb( 2169 hcap->hca_port_info[port_index].port_ibmf_hdl, 2170 IBMF_QP_HANDLE_DEFAULT, ibcm_recv_cb, 2171 &(hcap->hca_port_info[port_index].port_qp1), 0); 2172 ASSERT(status == IBMF_SUCCESS); 2173 2174 IBTF_DPRINTF_L5(cmlog, "ibcm_hca_init_port: " 2175 "IBMF hdl[%x] = 0x%p", port_index, 2176 hcap->hca_port_info[port_index].port_ibmf_hdl); 2177 2178 /* Attempt to get the saa_handle for this port */ 2179 ibcm_init_saa_handle(hcap, port_index + 1); 2180 } 2181 2182 return (IBT_SUCCESS); 2183 } 2184 2185 /* 2186 * useful, to re attempt to initialize port ibma handles from elsewhere in 2187 * cm code 2188 */ 2189 ibt_status_t 2190 ibcm_hca_reinit_port(ibcm_hca_info_t *hcap, uint8_t port_index) 2191 { 2192 ibt_status_t status; 2193 2194 IBTF_DPRINTF_L5(cmlog, "ibcm_hca_reinit_port: hcap 0x%p port_num %d", 2195 hcap, port_index + 1); 2196 2197 mutex_enter(&ibcm_global_hca_lock); 2198 status = ibcm_hca_init_port(hcap, port_index); 2199 mutex_exit(&ibcm_global_hca_lock); 2200 return (status); 2201 } 2202 2203 2204 /* 2205 * ibcm_hca_fini_port(): 2206 * - Deregister port with IBMA 2207 * 2208 * Arguments: 2209 * hcap - HCA's guid 2210 * port_index - port number minus 1 2211 * 2212 * Return values: 2213 * IBCM_SUCCESS - success 2214 */ 2215 static ibcm_status_t 2216 ibcm_hca_fini_port(ibcm_hca_info_t *hcap, uint8_t port_index) 2217 { 2218 int ibmf_status; 2219 ibcm_status_t ibcm_status; 2220 2221 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_fini_port: hcap = 0x%p port_num %d ", 2222 hcap, port_index + 1); 2223 2224 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock)); 2225 2226 if (hcap->hca_port_info[port_index].port_ibmf_saa_hdl != NULL) { 2227 IBTF_DPRINTF_L5(cmlog, "ibcm_hca_fini_port: " 2228 "ibmf_sa_session_close IBMF SAA hdl %p", 2229 hcap->hca_port_info[port_index].port_ibmf_saa_hdl); 2230 2231 ibmf_status = ibmf_sa_session_close( 2232 &hcap->hca_port_info[port_index].port_ibmf_saa_hdl, 0); 2233 if (ibmf_status != IBMF_SUCCESS) { 2234 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: " 2235 "ibmf_sa_session_close of port %d returned %x", 2236 port_index + 1, ibmf_status); 2237 return (IBCM_FAILURE); 2238 } 2239 } 2240 2241 if (hcap->hca_port_info[port_index].port_ibmf_hdl != NULL) { 2242 IBTF_DPRINTF_L5(cmlog, "ibcm_hca_fini_port: " 2243 "ibmf_unregister IBMF Hdl %p", 2244 hcap->hca_port_info[port_index].port_ibmf_hdl); 2245 2246 /* clean-up all the ibmf qp's allocated on this port */ 2247 ibcm_status = ibcm_free_allqps(hcap, port_index + 1); 2248 2249 if (ibcm_status != IBCM_SUCCESS) { 2250 2251 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: " 2252 "ibcm_free_allqps failed for port_num %d", 2253 port_index + 1); 2254 return (IBCM_FAILURE); 2255 } 2256 2257 /* Tear down the receive callback */ 2258 ibmf_status = ibmf_tear_down_async_cb( 2259 hcap->hca_port_info[port_index].port_ibmf_hdl, 2260 IBMF_QP_HANDLE_DEFAULT, 0); 2261 2262 if (ibmf_status != IBMF_SUCCESS) { 2263 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: " 2264 "ibmf_tear_down_async_cb failed %d port_num %d", 2265 ibmf_status, port_index + 1); 2266 return (IBCM_FAILURE); 2267 } 2268 2269 /* Now, unregister with IBMF */ 2270 ibmf_status = ibmf_unregister( 2271 &hcap->hca_port_info[port_index].port_ibmf_hdl, 0); 2272 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_fini_port: " 2273 "ibmf_unregister of port_num %x returned %x", 2274 port_index + 1, ibmf_status); 2275 2276 if (ibmf_status == IBMF_SUCCESS) 2277 hcap->hca_port_info[port_index].port_ibmf_hdl = NULL; 2278 else { 2279 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: " 2280 "ibmf_unregister failed %d port_num %d", 2281 ibmf_status, port_index + 1); 2282 return (IBCM_FAILURE); 2283 } 2284 } 2285 return (IBCM_SUCCESS); 2286 } 2287 2288 /* 2289 * ibcm_comm_est_handler(): 2290 * Check if the given channel is in ESTABLISHED state or not 2291 * 2292 * Arguments: 2293 * eventp - A pointer to an ibt_async_event_t struct 2294 * 2295 * Return values: NONE 2296 */ 2297 static void 2298 ibcm_comm_est_handler(ibt_async_event_t *eventp) 2299 { 2300 ibcm_state_data_t *statep; 2301 2302 IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler:"); 2303 2304 /* Both QP and EEC handles can't be NULL */ 2305 if (eventp->ev_chan_hdl == NULL) { 2306 IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: " 2307 "both QP and EEC handles are NULL"); 2308 return; 2309 } 2310 2311 /* get the "statep" from qp/eec handles */ 2312 IBCM_GET_CHAN_PRIVATE(eventp->ev_chan_hdl, statep); 2313 if (statep == NULL) { 2314 IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: statep is NULL"); 2315 return; 2316 } 2317 2318 mutex_enter(&statep->state_mutex); 2319 2320 IBCM_RELEASE_CHAN_PRIVATE(eventp->ev_chan_hdl); 2321 2322 IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler: statep = %p", statep); 2323 2324 IBCM_REF_CNT_INCR(statep); 2325 2326 if ((statep->state == IBCM_STATE_REP_SENT) || 2327 (statep->state == IBCM_STATE_MRA_REP_RCVD)) { 2328 timeout_id_t timer_val = statep->timerid; 2329 2330 statep->state = IBCM_STATE_TRANSIENT_ESTABLISHED; 2331 2332 if (timer_val) { 2333 statep->timerid = 0; 2334 mutex_exit(&statep->state_mutex); 2335 (void) untimeout(timer_val); 2336 } else 2337 mutex_exit(&statep->state_mutex); 2338 2339 /* CM doesn't have RTU message here */ 2340 ibcm_cep_state_rtu(statep, NULL); 2341 2342 } else { 2343 if (statep->state == IBCM_STATE_ESTABLISHED || 2344 statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) { 2345 IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler: " 2346 "Channel already in ESTABLISHED state"); 2347 } else { 2348 /* An unexpected behavior from remote */ 2349 IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: " 2350 "Unexpected in state = %d", statep->state); 2351 } 2352 mutex_exit(&statep->state_mutex); 2353 2354 ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_COMEST); 2355 } 2356 2357 mutex_enter(&statep->state_mutex); 2358 IBCM_REF_CNT_DECR(statep); 2359 mutex_exit(&statep->state_mutex); 2360 } 2361 2362 2363 /* 2364 * ibcm_async_handler(): 2365 * CM's Async Handler 2366 * (Handles ATTACH, DETACH, COM_EST events) 2367 * 2368 * Arguments: 2369 * eventp - A pointer to an ibt_async_event_t struct 2370 * 2371 * Return values: None 2372 * 2373 * NOTE : CM assumes that all HCA DR events are delivered sequentially 2374 * i.e., until ibcm_async_handler completes for a given HCA DR, framework 2375 * shall not invoke ibcm_async_handler with another DR event for the same 2376 * HCA 2377 */ 2378 /* ARGSUSED */ 2379 void 2380 ibcm_async_handler(void *clnt_hdl, ibt_hca_hdl_t hca_hdl, 2381 ibt_async_code_t code, ibt_async_event_t *eventp) 2382 { 2383 ibcm_hca_info_t *hcap; 2384 ibcm_port_up_t *pup; 2385 2386 IBTF_DPRINTF_L3(cmlog, "ibcm_async_handler: " 2387 "clnt_hdl = %p, code = 0x%x, eventp = 0x%p", 2388 clnt_hdl, code, eventp); 2389 2390 mutex_enter(&ibcm_global_hca_lock); 2391 2392 /* If fini is going to complete successfully, then return */ 2393 if (ibcm_finit_state != IBCM_FINIT_IDLE) { 2394 2395 /* 2396 * This finit state implies one of the following: 2397 * Init either didn't start or didn't complete OR 2398 * Fini is about to return SUCCESS and release the global lock. 2399 * In all these cases, it is safe to ignore the async. 2400 */ 2401 2402 IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler: ignoring event %x, " 2403 "as either init didn't complete or fini about to succeed", 2404 code); 2405 mutex_exit(&ibcm_global_hca_lock); 2406 return; 2407 } 2408 2409 switch (code) { 2410 case IBT_PORT_CHANGE_EVENT: 2411 if ((eventp->ev_port_flags & IBT_PORT_CHANGE_SM_LID) == 0) 2412 break; 2413 /* FALLTHROUGH */ 2414 case IBT_CLNT_REREG_EVENT: 2415 case IBT_EVENT_PORT_UP: 2416 mutex_exit(&ibcm_global_hca_lock); 2417 pup = kmem_alloc(sizeof (ibcm_port_up_t), KM_SLEEP); 2418 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pup)) 2419 pup->pup_hca_guid = eventp->ev_hca_guid; 2420 pup->pup_port = eventp->ev_port; 2421 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*pup)) 2422 (void) taskq_dispatch(ibcm_taskq, 2423 ibcm_service_record_rewrite_task, pup, TQ_SLEEP); 2424 ibcm_path_cache_purge(); 2425 return; 2426 2427 case IBT_HCA_ATTACH_EVENT: 2428 2429 /* eventp->ev_hcaguid is the HCA GUID of interest */ 2430 ibcm_hca_attach(eventp->ev_hca_guid); 2431 break; 2432 2433 case IBT_HCA_DETACH_EVENT: 2434 2435 /* eventp->ev_hca_guid is the HCA GUID of interest */ 2436 if ((hcap = ibcm_find_hcap_entry(eventp->ev_hca_guid)) == 2437 NULL) { 2438 IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler:" 2439 " hca %llX doesn't exist", eventp->ev_hca_guid); 2440 break; 2441 } 2442 2443 (void) ibcm_hca_detach(hcap); 2444 break; 2445 2446 case IBT_EVENT_COM_EST_QP: 2447 /* eventp->ev_qp_hdl is the ibt_qp_hdl_t of interest */ 2448 case IBT_EVENT_COM_EST_EEC: 2449 /* eventp->ev_eec_hdl is the ibt_eec_hdl_t of interest */ 2450 ibcm_comm_est_handler(eventp); 2451 break; 2452 default: 2453 break; 2454 } 2455 2456 /* Unblock, any blocked fini/init operations */ 2457 mutex_exit(&ibcm_global_hca_lock); 2458 }