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