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