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 }