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 /*
  23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * hermon.c
  28  *    Hermon (InfiniBand) HCA Driver attach/detach Routines
  29  *
  30  *    Implements all the routines necessary for the attach, setup,
  31  *    initialization (and subsequent possible teardown and detach) of the
  32  *    Hermon InfiniBand HCA driver.
  33  */
  34 
  35 #include <sys/types.h>
  36 #include <sys/file.h>
  37 #include <sys/open.h>
  38 #include <sys/conf.h>
  39 #include <sys/ddi.h>
  40 #include <sys/sunddi.h>
  41 #include <sys/modctl.h>
  42 #include <sys/stat.h>
  43 #include <sys/pci.h>
  44 #include <sys/pci_cap.h>
  45 #include <sys/bitmap.h>
  46 #include <sys/policy.h>
  47 
  48 #include <sys/ib/adapters/hermon/hermon.h>
  49 
  50 /* /etc/system can tune this down, if that is desirable. */
  51 int hermon_msix_max = HERMON_MSIX_MAX;
  52 
  53 /* The following works around a problem in pre-2_7_000 firmware. */
  54 #define HERMON_FW_WORKAROUND
  55 
  56 int hermon_verbose = 0;
  57 
  58 /* Hermon HCA State Pointer */
  59 void *hermon_statep;
  60 
  61 int debug_vpd = 0;
  62 
  63 /* Disable the internal error-check polling thread */
  64 int hermon_no_inter_err_chk = 0;
  65 
  66 /*
  67  * The Hermon "userland resource database" is common to instances of the
  68  * Hermon HCA driver.  This structure "hermon_userland_rsrc_db" contains all
  69  * the necessary information to maintain it.
  70  */
  71 hermon_umap_db_t hermon_userland_rsrc_db;
  72 
  73 static int hermon_attach(dev_info_t *, ddi_attach_cmd_t);
  74 static int hermon_detach(dev_info_t *, ddi_detach_cmd_t);
  75 static int hermon_open(dev_t *, int, int, cred_t *);
  76 static int hermon_close(dev_t, int, int, cred_t *);
  77 static int hermon_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
  78 
  79 static int hermon_drv_init(hermon_state_t *state, dev_info_t *dip,
  80     int instance);
  81 static void hermon_drv_fini(hermon_state_t *state);
  82 static void hermon_drv_fini2(hermon_state_t *state);
  83 static int hermon_isr_init(hermon_state_t *state);
  84 static void hermon_isr_fini(hermon_state_t *state);
  85 
  86 static int hermon_hw_init(hermon_state_t *state);
  87 
  88 static void hermon_hw_fini(hermon_state_t *state,
  89     hermon_drv_cleanup_level_t cleanup);
  90 static int hermon_soft_state_init(hermon_state_t *state);
  91 static void hermon_soft_state_fini(hermon_state_t *state);
  92 static int hermon_icm_config_setup(hermon_state_t *state,
  93     hermon_hw_initqueryhca_t *inithca);
  94 static void hermon_icm_tables_init(hermon_state_t *state);
  95 static void hermon_icm_tables_fini(hermon_state_t *state);
  96 static int hermon_icm_dma_init(hermon_state_t *state);
  97 static void hermon_icm_dma_fini(hermon_state_t *state);
  98 static void hermon_inithca_set(hermon_state_t *state,
  99     hermon_hw_initqueryhca_t *inithca);
 100 static int hermon_hca_port_init(hermon_state_t *state);
 101 static int hermon_hca_ports_shutdown(hermon_state_t *state, uint_t num_init);
 102 static int hermon_internal_uarpg_init(hermon_state_t *state);
 103 static void hermon_internal_uarpg_fini(hermon_state_t *state);
 104 static int hermon_special_qp_contexts_reserve(hermon_state_t *state);
 105 static void hermon_special_qp_contexts_unreserve(hermon_state_t *state);
 106 static int hermon_sw_reset(hermon_state_t *state);
 107 static int hermon_mcg_init(hermon_state_t *state);
 108 static void hermon_mcg_fini(hermon_state_t *state);
 109 static int hermon_fw_version_check(hermon_state_t *state);
 110 static void hermon_device_info_report(hermon_state_t *state);
 111 static int hermon_pci_capability_list(hermon_state_t *state,
 112     ddi_acc_handle_t hdl);
 113 static void hermon_pci_capability_vpd(hermon_state_t *state,
 114     ddi_acc_handle_t hdl, uint_t offset);
 115 static int hermon_pci_read_vpd(ddi_acc_handle_t hdl, uint_t offset,
 116     uint32_t addr, uint32_t *data);
 117 static int hermon_intr_or_msi_init(hermon_state_t *state);
 118 static int hermon_add_intrs(hermon_state_t *state, int intr_type);
 119 static int hermon_intr_or_msi_fini(hermon_state_t *state);
 120 void hermon_pci_capability_msix(hermon_state_t *state, ddi_acc_handle_t hdl,
 121     uint_t offset);
 122 
 123 static uint64_t hermon_size_icm(hermon_state_t *state);
 124 
 125 /* X86 fastreboot support */
 126 static ushort_t get_msix_ctrl(dev_info_t *);
 127 static size_t get_msix_tbl_size(dev_info_t *);
 128 static size_t get_msix_pba_size(dev_info_t *);
 129 static void hermon_set_msix_info(hermon_state_t *);
 130 static int hermon_intr_disable(hermon_state_t *);
 131 static int hermon_quiesce(dev_info_t *);
 132 
 133 
 134 /* Character/Block Operations */
 135 static struct cb_ops hermon_cb_ops = {
 136         hermon_open,            /* open */
 137         hermon_close,           /* close */
 138         nodev,                  /* strategy (block) */
 139         nodev,                  /* print (block) */
 140         nodev,                  /* dump (block) */
 141         nodev,                  /* read */
 142         nodev,                  /* write */
 143         hermon_ioctl,           /* ioctl */
 144         hermon_devmap,          /* devmap */
 145         NULL,                   /* mmap */
 146         nodev,                  /* segmap */
 147         nochpoll,               /* chpoll */
 148         ddi_prop_op,            /* prop_op */
 149         NULL,                   /* streams */
 150         D_NEW | D_MP |
 151         D_64BIT | D_HOTPLUG |
 152         D_DEVMAP,               /* flags */
 153         CB_REV                  /* rev */
 154 };
 155 
 156 /* Driver Operations */
 157 static struct dev_ops hermon_ops = {
 158         DEVO_REV,               /* struct rev */
 159         0,                      /* refcnt */
 160         hermon_getinfo,         /* getinfo */
 161         nulldev,                /* identify */
 162         nulldev,                /* probe */
 163         hermon_attach,          /* attach */
 164         hermon_detach,          /* detach */
 165         nodev,                  /* reset */
 166         &hermon_cb_ops,             /* cb_ops */
 167         NULL,                   /* bus_ops */
 168         nodev,                  /* power */
 169         hermon_quiesce,         /* devo_quiesce */
 170 };
 171 
 172 /* Module Driver Info */
 173 static struct modldrv hermon_modldrv = {
 174         &mod_driverops,
 175         "ConnectX IB Driver",
 176         &hermon_ops
 177 };
 178 
 179 /* Module Linkage */
 180 static struct modlinkage hermon_modlinkage = {
 181         MODREV_1,
 182         &hermon_modldrv,
 183         NULL
 184 };
 185 
 186 /*
 187  * This extern refers to the ibc_operations_t function vector that is defined
 188  * in the hermon_ci.c file.
 189  */
 190 extern ibc_operations_t hermon_ibc_ops;
 191 
 192 /*
 193  * _init()
 194  */
 195 int
 196 _init()
 197 {
 198         int     status;
 199 
 200         status = ddi_soft_state_init(&hermon_statep, sizeof (hermon_state_t),
 201             (size_t)HERMON_INITIAL_STATES);
 202         if (status != 0) {
 203                 return (status);
 204         }
 205 
 206         status = ibc_init(&hermon_modlinkage);
 207         if (status != 0) {
 208                 ddi_soft_state_fini(&hermon_statep);
 209                 return (status);
 210         }
 211 
 212         status = mod_install(&hermon_modlinkage);
 213         if (status != 0) {
 214                 ibc_fini(&hermon_modlinkage);
 215                 ddi_soft_state_fini(&hermon_statep);
 216                 return (status);
 217         }
 218 
 219         /* Initialize the Hermon "userland resources database" */
 220         hermon_umap_db_init();
 221 
 222         return (status);
 223 }
 224 
 225 
 226 /*
 227  * _info()
 228  */
 229 int
 230 _info(struct modinfo *modinfop)
 231 {
 232         int     status;
 233 
 234         status = mod_info(&hermon_modlinkage, modinfop);
 235         return (status);
 236 }
 237 
 238 
 239 /*
 240  * _fini()
 241  */
 242 int
 243 _fini()
 244 {
 245         int     status;
 246 
 247         status = mod_remove(&hermon_modlinkage);
 248         if (status != 0) {
 249                 return (status);
 250         }
 251 
 252         /* Destroy the Hermon "userland resources database" */
 253         hermon_umap_db_fini();
 254 
 255         ibc_fini(&hermon_modlinkage);
 256         ddi_soft_state_fini(&hermon_statep);
 257 
 258         return (status);
 259 }
 260 
 261 
 262 /*
 263  * hermon_getinfo()
 264  */
 265 /* ARGSUSED */
 266 static int
 267 hermon_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
 268 {
 269         dev_t           dev;
 270         hermon_state_t  *state;
 271         minor_t         instance;
 272 
 273         switch (cmd) {
 274         case DDI_INFO_DEVT2DEVINFO:
 275                 dev = (dev_t)arg;
 276                 instance = HERMON_DEV_INSTANCE(dev);
 277                 state = ddi_get_soft_state(hermon_statep, instance);
 278                 if (state == NULL) {
 279                         return (DDI_FAILURE);
 280                 }
 281                 *result = (void *)state->hs_dip;
 282                 return (DDI_SUCCESS);
 283 
 284         case DDI_INFO_DEVT2INSTANCE:
 285                 dev = (dev_t)arg;
 286                 instance = HERMON_DEV_INSTANCE(dev);
 287                 *result = (void *)(uintptr_t)instance;
 288                 return (DDI_SUCCESS);
 289 
 290         default:
 291                 break;
 292         }
 293 
 294         return (DDI_FAILURE);
 295 }
 296 
 297 
 298 /*
 299  * hermon_open()
 300  */
 301 /* ARGSUSED */
 302 static int
 303 hermon_open(dev_t *devp, int flag, int otyp, cred_t *credp)
 304 {
 305         hermon_state_t          *state;
 306         hermon_rsrc_t           *rsrcp;
 307         hermon_umap_db_entry_t  *umapdb, *umapdb2;
 308         minor_t                 instance;
 309         uint64_t                key, value;
 310         uint_t                  hr_indx;
 311         dev_t                   dev;
 312         int                     status;
 313 
 314         instance = HERMON_DEV_INSTANCE(*devp);
 315         state = ddi_get_soft_state(hermon_statep, instance);
 316         if (state == NULL) {
 317                 return (ENXIO);
 318         }
 319 
 320         /*
 321          * Only allow driver to be opened for character access, and verify
 322          * whether exclusive access is allowed.
 323          */
 324         if ((otyp != OTYP_CHR) || ((flag & FEXCL) &&
 325             secpolicy_excl_open(credp) != 0)) {
 326                 return (EINVAL);
 327         }
 328 
 329         /*
 330          * Search for the current process PID in the "userland resources
 331          * database".  If it is not found, then attempt to allocate a UAR
 332          * page and add the ("key", "value") pair to the database.
 333          * Note:  As a last step we always return a devp appropriate for
 334          * the open.  Either we return a new minor number (based on the
 335          * instance and the UAR page index) or we return the current minor
 336          * number for the given client process.
 337          *
 338          * We also add an entry to the database to allow for lookup from
 339          * "dev_t" to the current process PID.  This is necessary because,
 340          * under certain circumstance, the process PID that calls the Hermon
 341          * close() entry point may not be the same as the one who called
 342          * open().  Specifically, this can happen if a child process calls
 343          * the Hermon's open() entry point, gets a UAR page, maps it out (using
 344          * mmap()), and then exits without calling munmap().  Because mmap()
 345          * adds a reference to the file descriptor, at the exit of the child
 346          * process the file descriptor is "inherited" by the parent (and will
 347          * be close()'d by the parent's PID only when it exits).
 348          *
 349          * Note: We use the hermon_umap_db_find_nolock() and
 350          * hermon_umap_db_add_nolock() database access routines below (with
 351          * an explicit mutex_enter of the database lock - "hdl_umapdb_lock")
 352          * to ensure that the multiple accesses (in this case searching for,
 353          * and then adding _two_ database entries) can be done atomically.
 354          */
 355         key = ddi_get_pid();
 356         mutex_enter(&hermon_userland_rsrc_db.hdl_umapdb_lock);
 357         status = hermon_umap_db_find_nolock(instance, key,
 358             MLNX_UMAP_UARPG_RSRC, &value, 0, NULL);
 359         if (status != DDI_SUCCESS) {
 360                 /*
 361                  * If we are in 'maintenance mode', we cannot alloc a UAR page.
 362                  * But we still need some rsrcp value, and a mostly unique
 363                  * hr_indx value.  So we set rsrcp to NULL for maintenance
 364                  * mode, and use a rolling count for hr_indx.  The field
 365                  * 'hs_open_hr_indx' is used only in this maintenance mode
 366                  * condition.
 367                  *
 368                  * Otherwise, if we are in operational mode then we allocate
 369                  * the UAR page as normal, and use the rsrcp value and tr_indx
 370                  * value from that allocation.
 371                  */
 372                 if (!HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
 373                         rsrcp = NULL;
 374                         hr_indx = state->hs_open_ar_indx++;
 375                 } else {
 376                         /* Allocate a new UAR page for this process */
 377                         status = hermon_rsrc_alloc(state, HERMON_UARPG, 1,
 378                             HERMON_NOSLEEP, &rsrcp);
 379                         if (status != DDI_SUCCESS) {
 380                                 mutex_exit(
 381                                     &hermon_userland_rsrc_db.hdl_umapdb_lock);
 382                                 return (EAGAIN);
 383                         }
 384 
 385                         hr_indx = rsrcp->hr_indx;
 386                 }
 387 
 388                 /*
 389                  * Allocate an entry to track the UAR page resource in the
 390                  * "userland resources database".
 391                  */
 392                 umapdb = hermon_umap_db_alloc(instance, key,
 393                     MLNX_UMAP_UARPG_RSRC, (uint64_t)(uintptr_t)rsrcp);
 394                 if (umapdb == NULL) {
 395                         mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
 396                         /* If in "maintenance mode", don't free the rsrc */
 397                         if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
 398                                 hermon_rsrc_free(state, &rsrcp);
 399                         }
 400                         return (EAGAIN);
 401                 }
 402 
 403                 /*
 404                  * Create a new device number.  Minor number is a function of
 405                  * the UAR page index (15 bits) and the device instance number
 406                  * (3 bits).
 407                  */
 408                 dev = makedevice(getmajor(*devp), (hr_indx <<
 409                     HERMON_MINORNUM_SHIFT) | instance);
 410 
 411                 /*
 412                  * Allocate another entry in the "userland resources database"
 413                  * to track the association of the device number (above) to
 414                  * the current process ID (in "key").
 415                  */
 416                 umapdb2 = hermon_umap_db_alloc(instance, dev,
 417                     MLNX_UMAP_PID_RSRC, (uint64_t)key);
 418                 if (umapdb2 == NULL) {
 419                         mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
 420                         hermon_umap_db_free(umapdb);
 421                         /* If in "maintenance mode", don't free the rsrc */
 422                         if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
 423                                 hermon_rsrc_free(state, &rsrcp);
 424                         }
 425                         return (EAGAIN);
 426                 }
 427 
 428                 /* Add the entries to the database */
 429                 hermon_umap_db_add_nolock(umapdb);
 430                 hermon_umap_db_add_nolock(umapdb2);
 431 
 432         } else {
 433                 /*
 434                  * Return the same device number as on the original open()
 435                  * call.  This was calculated as a function of the UAR page
 436                  * index (top 16 bits) and the device instance number
 437                  */
 438                 rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
 439                 dev = makedevice(getmajor(*devp), (rsrcp->hr_indx <<
 440                     HERMON_MINORNUM_SHIFT) | instance);
 441         }
 442         mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
 443 
 444         *devp = dev;
 445 
 446         return (0);
 447 }
 448 
 449 
 450 /*
 451  * hermon_close()
 452  */
 453 /* ARGSUSED */
 454 static int
 455 hermon_close(dev_t dev, int flag, int otyp, cred_t *credp)
 456 {
 457         hermon_state_t          *state;
 458         hermon_rsrc_t           *rsrcp;
 459         hermon_umap_db_entry_t  *umapdb;
 460         hermon_umap_db_priv_t   *priv;
 461         minor_t                 instance;
 462         uint64_t                key, value;
 463         int                     status, reset_status = 0;
 464 
 465         instance = HERMON_DEV_INSTANCE(dev);
 466         state = ddi_get_soft_state(hermon_statep, instance);
 467         if (state == NULL) {
 468                 return (ENXIO);
 469         }
 470 
 471         /*
 472          * Search for "dev_t" in the "userland resources database".  As
 473          * explained above in hermon_open(), we can't depend on using the
 474          * current process ID here to do the lookup because the process
 475          * that ultimately closes may not be the same one who opened
 476          * (because of inheritance).
 477          * So we lookup the "dev_t" (which points to the PID of the process
 478          * that opened), and we remove the entry from the database (and free
 479          * it up).  Then we do another query based on the PID value.  And when
 480          * we find that database entry, we free it up too and then free the
 481          * Hermon UAR page resource.
 482          *
 483          * Note: We use the hermon_umap_db_find_nolock() database access
 484          * routine below (with an explicit mutex_enter of the database lock)
 485          * to ensure that the multiple accesses (which attempt to remove the
 486          * two database entries) can be done atomically.
 487          *
 488          * This works the same in both maintenance mode and HCA mode, except
 489          * for the call to hermon_rsrc_free().  In the case of maintenance mode,
 490          * this call is not needed, as it was not allocated in hermon_open()
 491          * above.
 492          */
 493         key = dev;
 494         mutex_enter(&hermon_userland_rsrc_db.hdl_umapdb_lock);
 495         status = hermon_umap_db_find_nolock(instance, key, MLNX_UMAP_PID_RSRC,
 496             &value, HERMON_UMAP_DB_REMOVE, &umapdb);
 497         if (status == DDI_SUCCESS) {
 498                 /*
 499                  * If the "hdb_priv" field is non-NULL, it indicates that
 500                  * some "on close" handling is still necessary.  Call
 501                  * hermon_umap_db_handle_onclose_cb() to do the handling (i.e.
 502                  * to invoke all the registered callbacks).  Then free up
 503                  * the resources associated with "hdb_priv" and continue
 504                  * closing.
 505                  */
 506                 priv = (hermon_umap_db_priv_t *)umapdb->hdbe_common.hdb_priv;
 507                 if (priv != NULL) {
 508                         reset_status = hermon_umap_db_handle_onclose_cb(priv);
 509                         kmem_free(priv, sizeof (hermon_umap_db_priv_t));
 510                         umapdb->hdbe_common.hdb_priv = (void *)NULL;
 511                 }
 512 
 513                 hermon_umap_db_free(umapdb);
 514 
 515                 /*
 516                  * Now do another lookup using PID as the key (copy it from
 517                  * "value").  When this lookup is complete, the "value" field
 518                  * will contain the hermon_rsrc_t pointer for the UAR page
 519                  * resource.
 520                  */
 521                 key = value;
 522                 status = hermon_umap_db_find_nolock(instance, key,
 523                     MLNX_UMAP_UARPG_RSRC, &value, HERMON_UMAP_DB_REMOVE,
 524                     &umapdb);
 525                 if (status == DDI_SUCCESS) {
 526                         hermon_umap_db_free(umapdb);
 527                         /* If in "maintenance mode", don't free the rsrc */
 528                         if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
 529                                 rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
 530                                 hermon_rsrc_free(state, &rsrcp);
 531                         }
 532                 }
 533         }
 534         mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
 535         return (reset_status);
 536 }
 537 
 538 
 539 /*
 540  * hermon_attach()
 541  *    Context: Only called from attach() path context
 542  */
 543 static int
 544 hermon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 545 {
 546         hermon_state_t  *state;
 547         ibc_clnt_hdl_t  tmp_ibtfpriv;
 548         ibc_status_t    ibc_status;
 549         int             instance;
 550         int             status;
 551 
 552 #ifdef __lock_lint
 553         (void) hermon_quiesce(dip);
 554 #endif
 555 
 556         switch (cmd) {
 557         case DDI_ATTACH:
 558                 instance = ddi_get_instance(dip);
 559                 status = ddi_soft_state_zalloc(hermon_statep, instance);
 560                 if (status != DDI_SUCCESS) {
 561                         cmn_err(CE_NOTE, "hermon%d: driver failed to attach: "
 562                             "attach_ssz_fail", instance);
 563                         goto fail_attach_nomsg;
 564 
 565                 }
 566                 state = ddi_get_soft_state(hermon_statep, instance);
 567                 if (state == NULL) {
 568                         ddi_soft_state_free(hermon_statep, instance);
 569                         cmn_err(CE_NOTE, "hermon%d: driver failed to attach: "
 570                             "attach_gss_fail", instance);
 571                         goto fail_attach_nomsg;
 572                 }
 573 
 574                 /* clear the attach error buffer */
 575                 HERMON_ATTACH_MSG_INIT(state->hs_attach_buf);
 576 
 577                 /* Save away devinfo and instance before hermon_fm_init() */
 578                 state->hs_dip = dip;
 579                 state->hs_instance = instance;
 580 
 581                 hermon_fm_init(state);
 582 
 583                 /*
 584                  * Initialize Hermon driver and hardware.
 585                  *
 586                  * Note: If this initialization fails we may still wish to
 587                  * create a device node and remain operational so that Hermon
 588                  * firmware can be updated/flashed (i.e. "maintenance mode").
 589                  * If this is the case, then "hs_operational_mode" will be
 590                  * equal to HERMON_MAINTENANCE_MODE.  We will not attempt to
 591                  * attach to the IBTF or register with the IBMF (i.e. no
 592                  * InfiniBand interfaces will be enabled).
 593                  */
 594                 status = hermon_drv_init(state, dip, instance);
 595                 if ((status != DDI_SUCCESS) &&
 596                     (HERMON_IS_OPERATIONAL(state->hs_operational_mode))) {
 597                         goto fail_attach;
 598                 }
 599 
 600                 /*
 601                  * Change the Hermon FM mode
 602                  */
 603                 if ((hermon_get_state(state) & HCA_PIO_FM) &&
 604                     HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
 605                         /*
 606                          * Now we wait for 50ms to give an opportunity
 607                          * to Solaris FMA so that HW errors can be notified.
 608                          * Then check if there are HW errors or not. If
 609                          * a HW error is detected, the Hermon attachment
 610                          * must be failed.
 611                          */
 612                         delay(drv_usectohz(50000));
 613                         if (hermon_init_failure(state)) {
 614                                 hermon_drv_fini(state);
 615                                 HERMON_WARNING(state, "unable to "
 616                                     "attach Hermon due to a HW error");
 617                                 HERMON_ATTACH_MSG(state->hs_attach_buf,
 618                                     "hermon_attach_failure");
 619                                 goto fail_attach;
 620                         }
 621 
 622                         /*
 623                          * There seems no HW errors during the attachment,
 624                          * so let's change the Hermon FM state to the
 625                          * ereport only mode.
 626                          */
 627                         if (hermon_fm_ereport_init(state) != DDI_SUCCESS) {
 628                                 /* unwind the resources */
 629                                 hermon_drv_fini(state);
 630                                 HERMON_ATTACH_MSG(state->hs_attach_buf,
 631                                     "hermon_attach_failure");
 632                                 goto fail_attach;
 633                         }
 634                 }
 635 
 636                 /* Create the minor node for device */
 637                 status = ddi_create_minor_node(dip, "devctl", S_IFCHR, instance,
 638                     DDI_PSEUDO, 0);
 639                 if (status != DDI_SUCCESS) {
 640                         hermon_drv_fini(state);
 641                         HERMON_ATTACH_MSG(state->hs_attach_buf,
 642                             "attach_create_mn_fail");
 643                         goto fail_attach;
 644                 }
 645 
 646                 /*
 647                  * If we are in "maintenance mode", then we don't want to
 648                  * register with the IBTF.  All InfiniBand interfaces are
 649                  * uninitialized, and the device is only capable of handling
 650                  * requests to update/flash firmware (or test/debug requests).
 651                  */
 652                 if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
 653                         cmn_err(CE_NOTE, "!Hermon is operational\n");
 654 
 655                         /* Attach to InfiniBand Transport Framework (IBTF) */
 656                         ibc_status = ibc_attach(&tmp_ibtfpriv,
 657                             &state->hs_ibtfinfo);
 658                         if (ibc_status != IBC_SUCCESS) {
 659                                 cmn_err(CE_CONT, "hermon_attach: ibc_attach "
 660                                     "failed\n");
 661                                 ddi_remove_minor_node(dip, "devctl");
 662                                 hermon_drv_fini(state);
 663                                 HERMON_ATTACH_MSG(state->hs_attach_buf,
 664                                     "attach_ibcattach_fail");
 665                                 goto fail_attach;
 666                         }
 667 
 668                         /*
 669                          * Now that we've successfully attached to the IBTF,
 670                          * we enable all appropriate asynch and CQ events to
 671                          * be forwarded to the IBTF.
 672                          */
 673                         HERMON_ENABLE_IBTF_CALLB(state, tmp_ibtfpriv);
 674 
 675                         ibc_post_attach(state->hs_ibtfpriv);
 676 
 677                         /* Register agents with IB Mgmt Framework (IBMF) */
 678                         status = hermon_agent_handlers_init(state);
 679                         if (status != DDI_SUCCESS) {
 680                                 (void) ibc_pre_detach(tmp_ibtfpriv, DDI_DETACH);
 681                                 HERMON_QUIESCE_IBTF_CALLB(state);
 682                                 if (state->hs_in_evcallb != 0) {
 683                                         HERMON_WARNING(state, "unable to "
 684                                             "quiesce Hermon IBTF callbacks");
 685                                 }
 686                                 ibc_detach(tmp_ibtfpriv);
 687                                 ddi_remove_minor_node(dip, "devctl");
 688                                 hermon_drv_fini(state);
 689                                 HERMON_ATTACH_MSG(state->hs_attach_buf,
 690                                     "attach_agentinit_fail");
 691                                 goto fail_attach;
 692                         }
 693                 }
 694 
 695                 /* Report attach in maintenance mode, if appropriate */
 696                 if (!(HERMON_IS_OPERATIONAL(state->hs_operational_mode))) {
 697                         cmn_err(CE_NOTE, "hermon%d: driver attached "
 698                             "(for maintenance mode only)", state->hs_instance);
 699                         hermon_fm_ereport(state, HCA_IBA_ERR, HCA_ERR_DEGRADED);
 700                 }
 701 
 702                 /* Report that driver was loaded */
 703                 ddi_report_dev(dip);
 704 
 705                 /* Send device information to log file */
 706                 hermon_device_info_report(state);
 707 
 708                 /* DEBUG PRINT */
 709                 cmn_err(CE_CONT, "!Hermon attach complete\n");
 710                 return (DDI_SUCCESS);
 711 
 712         case DDI_RESUME:
 713                 /* Add code here for DDI_RESUME XXX */
 714                 return (DDI_FAILURE);
 715 
 716         default:
 717                 cmn_err(CE_WARN, "hermon_attach: unknown cmd (0x%x)\n", cmd);
 718                 break;
 719         }
 720 
 721 fail_attach:
 722         cmn_err(CE_NOTE, "hermon%d: driver failed to attach: %s", instance,
 723             state->hs_attach_buf);
 724         if (hermon_get_state(state) & HCA_EREPORT_FM) {
 725                 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
 726         }
 727         hermon_drv_fini2(state);
 728         hermon_fm_fini(state);
 729         ddi_soft_state_free(hermon_statep, instance);
 730 
 731 fail_attach_nomsg:
 732         return (DDI_FAILURE);
 733 }
 734 
 735 
 736 /*
 737  * hermon_detach()
 738  *    Context: Only called from detach() path context
 739  */
 740 static int
 741 hermon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 742 {
 743         hermon_state_t  *state;
 744         ibc_clnt_hdl_t  tmp_ibtfpriv;
 745         ibc_status_t    ibc_status;
 746         int             instance, status;
 747 
 748         instance = ddi_get_instance(dip);
 749         state = ddi_get_soft_state(hermon_statep, instance);
 750         if (state == NULL) {
 751                 return (DDI_FAILURE);
 752         }
 753 
 754         switch (cmd) {
 755         case DDI_DETACH:
 756                 /*
 757                  * If we are in "maintenance mode", then we do not want to
 758                  * do teardown for any of the InfiniBand interfaces.
 759                  * Specifically, this means not detaching from IBTF (we never
 760                  * attached to begin with) and not deregistering from IBMF.
 761                  */
 762                 if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
 763                         /* Unregister agents from IB Mgmt Framework (IBMF) */
 764                         status = hermon_agent_handlers_fini(state);
 765                         if (status != DDI_SUCCESS) {
 766                                 return (DDI_FAILURE);
 767                         }
 768 
 769                         /*
 770                          * Attempt the "pre-detach" from InfiniBand Transport
 771                          * Framework (IBTF).  At this point the IBTF is still
 772                          * capable of handling incoming asynch and completion
 773                          * events.  This "pre-detach" is primarily a mechanism
 774                          * to notify the appropriate IBTF clients that the
 775                          * HCA is being removed/offlined.
 776                          */
 777                         ibc_status = ibc_pre_detach(state->hs_ibtfpriv, cmd);
 778                         if (ibc_status != IBC_SUCCESS) {
 779                                 status = hermon_agent_handlers_init(state);
 780                                 if (status != DDI_SUCCESS) {
 781                                         HERMON_WARNING(state, "failed to "
 782                                             "restart Hermon agents");
 783                                 }
 784                                 return (DDI_FAILURE);
 785                         }
 786 
 787                         /*
 788                          * Before we can fully detach from the IBTF we need to
 789                          * ensure that we have handled all outstanding event
 790                          * callbacks.  This is accomplished by quiescing the
 791                          * event callback mechanism.  Note: if we are unable
 792                          * to successfully quiesce the callbacks, then this is
 793                          * an indication that something has probably gone
 794                          * seriously wrong.  We print out a warning, but
 795                          * continue.
 796                          */
 797                         tmp_ibtfpriv = state->hs_ibtfpriv;
 798                         HERMON_QUIESCE_IBTF_CALLB(state);
 799                         if (state->hs_in_evcallb != 0) {
 800                                 HERMON_WARNING(state, "unable to quiesce "
 801                                     "Hermon IBTF callbacks");
 802                         }
 803 
 804                         /* Complete the detach from the IBTF */
 805                         ibc_detach(tmp_ibtfpriv);
 806                 }
 807 
 808                 /* Remove the minor node for device */
 809                 ddi_remove_minor_node(dip, "devctl");
 810 
 811                 /*
 812                  * Only call hermon_drv_fini() if we are in Hermon HCA mode.
 813                  * (Because if we are in "maintenance mode", then we never
 814                  * successfully finished init.)  Only report successful
 815                  * detach for normal HCA mode.
 816                  */
 817                 if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
 818                         /* Cleanup driver resources and shutdown hardware */
 819                         hermon_drv_fini(state);
 820                         cmn_err(CE_CONT, "!Hermon driver successfully "
 821                             "detached\n");
 822                 }
 823 
 824                 hermon_drv_fini2(state);
 825                 hermon_fm_fini(state);
 826                 ddi_soft_state_free(hermon_statep, instance);
 827 
 828                 return (DDI_SUCCESS);
 829 
 830         case DDI_SUSPEND:
 831                 /* Add code here for DDI_SUSPEND XXX */
 832                 return (DDI_FAILURE);
 833 
 834         default:
 835                 cmn_err(CE_WARN, "hermon_detach: unknown cmd (0x%x)\n", cmd);
 836                 break;
 837         }
 838 
 839         return (DDI_FAILURE);
 840 }
 841 
 842 /*
 843  * hermon_dma_attr_init()
 844  *    Context: Can be called from interrupt or base context.
 845  */
 846 
 847 /* ARGSUSED */
 848 void
 849 hermon_dma_attr_init(hermon_state_t *state, ddi_dma_attr_t *dma_attr)
 850 {
 851         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dma_attr))
 852 
 853         dma_attr->dma_attr_version   = DMA_ATTR_V0;
 854         dma_attr->dma_attr_addr_lo   = 0;
 855         dma_attr->dma_attr_addr_hi   = 0xFFFFFFFFFFFFFFFFull;
 856         dma_attr->dma_attr_count_max = 0xFFFFFFFFFFFFFFFFull;
 857         dma_attr->dma_attr_align     = HERMON_PAGESIZE;  /* default 4K */
 858         dma_attr->dma_attr_burstsizes        = 0x3FF;
 859         dma_attr->dma_attr_minxfer   = 1;
 860         dma_attr->dma_attr_maxxfer   = 0xFFFFFFFFFFFFFFFFull;
 861         dma_attr->dma_attr_seg               = 0xFFFFFFFFFFFFFFFFull;
 862         dma_attr->dma_attr_sgllen    = 0x7FFFFFFF;
 863         dma_attr->dma_attr_granular  = 1;
 864         dma_attr->dma_attr_flags     = 0;
 865 }
 866 
 867 /*
 868  * hermon_dma_alloc()
 869  *    Context: Can be called from base context.
 870  */
 871 int
 872 hermon_dma_alloc(hermon_state_t *state, hermon_dma_info_t *dma_info,
 873     uint16_t opcode)
 874 {
 875         ddi_dma_handle_t        dma_hdl;
 876         ddi_dma_attr_t          dma_attr;
 877         ddi_acc_handle_t        acc_hdl;
 878         ddi_dma_cookie_t        cookie;
 879         uint64_t                kaddr;
 880         uint64_t                real_len;
 881         uint_t                  ccount;
 882         int                     status;
 883 
 884         hermon_dma_attr_init(state, &dma_attr);
 885 #ifdef  __sparc
 886         if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS)
 887                 dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL;
 888 #endif
 889 
 890         /* Allocate a DMA handle */
 891         status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, DDI_DMA_SLEEP,
 892             NULL, &dma_hdl);
 893         if (status != DDI_SUCCESS) {
 894                 IBTF_DPRINTF_L2("DMA", "alloc handle failed: %d", status);
 895                 cmn_err(CE_CONT, "DMA alloc handle failed(status %d)", status);
 896                 return (DDI_FAILURE);
 897         }
 898 
 899         /* Allocate DMA memory */
 900         status = ddi_dma_mem_alloc(dma_hdl, dma_info->length,
 901             &state->hs_reg_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
 902             (caddr_t *)&kaddr, (size_t *)&real_len, &acc_hdl);
 903         if (status != DDI_SUCCESS) {
 904                 ddi_dma_free_handle(&dma_hdl);
 905                 IBTF_DPRINTF_L2("DMA", "memory alloc failed: %d", status);
 906                 cmn_err(CE_CONT, "DMA memory alloc failed(status %d)", status);
 907                 return (DDI_FAILURE);
 908         }
 909         bzero((caddr_t)(uintptr_t)kaddr, real_len);
 910 
 911         /* Bind the memory to the handle */
 912         status = ddi_dma_addr_bind_handle(dma_hdl, NULL,
 913             (caddr_t)(uintptr_t)kaddr, (size_t)real_len, DDI_DMA_RDWR |
 914             DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &cookie, &ccount);
 915         if (status != DDI_SUCCESS) {
 916                 ddi_dma_mem_free(&acc_hdl);
 917                 ddi_dma_free_handle(&dma_hdl);
 918                 IBTF_DPRINTF_L2("DMA", "bind handle failed: %d", status);
 919                 cmn_err(CE_CONT, "DMA bind handle failed(status %d)", status);
 920                 return (DDI_FAILURE);
 921         }
 922 
 923         /* Package the hermon_dma_info contents and return */
 924         dma_info->vaddr   = kaddr;
 925         dma_info->dma_hdl = dma_hdl;
 926         dma_info->acc_hdl = acc_hdl;
 927 
 928         /* Pass the mapping information to the firmware */
 929         status = hermon_map_cmd_post(state, dma_info, opcode, cookie, ccount);
 930         if (status != DDI_SUCCESS) {
 931                 char *s;
 932                 hermon_dma_free(dma_info);
 933                 switch (opcode) {
 934                 case MAP_ICM:
 935                         s = "MAP_ICM";
 936                         break;
 937                 case MAP_FA:
 938                         s = "MAP_FA";
 939                         break;
 940                 case MAP_ICM_AUX:
 941                         s = "MAP_ICM_AUX";
 942                         break;
 943                 default:
 944                         s = "UNKNOWN";
 945                 }
 946                 cmn_err(CE_NOTE, "Map cmd '%s' failed, status %08x\n",
 947                     s, status);
 948                 return (DDI_FAILURE);
 949         }
 950 
 951         return (DDI_SUCCESS);
 952 }
 953 
 954 /*
 955  * hermon_dma_free()
 956  *    Context: Can be called from base context.
 957  */
 958 void
 959 hermon_dma_free(hermon_dma_info_t *info)
 960 {
 961         /* Unbind the handles and free the memory */
 962         (void) ddi_dma_unbind_handle(info->dma_hdl);
 963         ddi_dma_mem_free(&info->acc_hdl);
 964         ddi_dma_free_handle(&info->dma_hdl);
 965 }
 966 
 967 /* These macros are valid for use only in hermon_icm_alloc/hermon_icm_free. */
 968 #define HERMON_ICM_ALLOC(rsrc) \
 969         hermon_icm_alloc(state, rsrc, index1, index2)
 970 #define HERMON_ICM_FREE(rsrc) \
 971         hermon_icm_free(state, rsrc, index1, index2)
 972 
 973 /*
 974  * hermon_icm_alloc()
 975  *    Context: Can be called from base context.
 976  *
 977  * Only one thread can be here for a given hermon_rsrc_type_t "type".
 978  *
 979  * "num_to_hdl" is set if there is a need for lookups from resource
 980  * number/index to resource handle.  This is needed for QPs/CQs/SRQs
 981  * for the various affiliated events/errors.
 982  */
 983 int
 984 hermon_icm_alloc(hermon_state_t *state, hermon_rsrc_type_t type,
 985     uint32_t index1, uint32_t index2)
 986 {
 987         hermon_icm_table_t      *icm;
 988         hermon_dma_info_t       *dma_info;
 989         uint8_t                 *bitmap;
 990         int                     status;
 991         int                     num_to_hdl = 0;
 992 
 993         if (hermon_verbose) {
 994                 IBTF_DPRINTF_L2("hermon", "hermon_icm_alloc: rsrc_type (0x%x) "
 995                     "index1/2 (0x%x/0x%x)", type, index1, index2);
 996         }
 997 
 998         icm = &state->hs_icm[type];
 999 
1000         switch (type) {
1001         case HERMON_QPC:
1002                 status = HERMON_ICM_ALLOC(HERMON_CMPT_QPC);
1003                 if (status != DDI_SUCCESS) {
1004                         return (status);
1005                 }
1006                 status = HERMON_ICM_ALLOC(HERMON_RDB);
1007                 if (status != DDI_SUCCESS) {    /* undo icm_alloc's */
1008                         HERMON_ICM_FREE(HERMON_CMPT_QPC);
1009                         return (status);
1010                 }
1011                 status = HERMON_ICM_ALLOC(HERMON_ALTC);
1012                 if (status != DDI_SUCCESS) {    /* undo icm_alloc's */
1013                         HERMON_ICM_FREE(HERMON_RDB);
1014                         HERMON_ICM_FREE(HERMON_CMPT_QPC);
1015                         return (status);
1016                 }
1017                 status = HERMON_ICM_ALLOC(HERMON_AUXC);
1018                 if (status != DDI_SUCCESS) {    /* undo icm_alloc's */
1019                         HERMON_ICM_FREE(HERMON_ALTC);
1020                         HERMON_ICM_FREE(HERMON_RDB);
1021                         HERMON_ICM_FREE(HERMON_CMPT_QPC);
1022                         return (status);
1023                 }
1024                 num_to_hdl = 1;
1025                 break;
1026         case HERMON_SRQC:
1027                 status = HERMON_ICM_ALLOC(HERMON_CMPT_SRQC);
1028                 if (status != DDI_SUCCESS) {
1029                         return (status);
1030                 }
1031                 num_to_hdl = 1;
1032                 break;
1033         case HERMON_CQC:
1034                 status = HERMON_ICM_ALLOC(HERMON_CMPT_CQC);
1035                 if (status != DDI_SUCCESS) {
1036                         return (status);
1037                 }
1038                 num_to_hdl = 1;
1039                 break;
1040         case HERMON_EQC:
1041                 status = HERMON_ICM_ALLOC(HERMON_CMPT_EQC);
1042                 if (status != DDI_SUCCESS) {    /* undo icm_alloc's */
1043                         return (status);
1044                 }
1045                 break;
1046         }
1047 
1048         /* ensure existence of bitmap and dmainfo, sets "dma_info" */
1049         hermon_bitmap(bitmap, dma_info, icm, index1, num_to_hdl);
1050 
1051         /* Set up the DMA handle for allocation and mapping */
1052         dma_info += index2;
1053         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dma_info))
1054         dma_info->length  = icm->span << icm->log_object_size;
1055         dma_info->icmaddr = icm->icm_baseaddr +
1056             (((index1 << icm->split_shift) +
1057             (index2 << icm->span_shift)) << icm->log_object_size);
1058 
1059         /* Allocate memory for the num_to_qp/cq/srq pointers */
1060         if (num_to_hdl)
1061                 icm->num_to_hdl[index1][index2] =
1062                     kmem_zalloc(HERMON_ICM_SPAN * sizeof (void *), KM_SLEEP);
1063 
1064         if (hermon_verbose) {
1065                 IBTF_DPRINTF_L2("hermon", "alloc DMA: "
1066                     "rsrc (0x%x) index (%x, %x) "
1067                     "icm_addr/len (%llx/%x) bitmap %p", type, index1, index2,
1068                     (longlong_t)dma_info->icmaddr, dma_info->length, bitmap);
1069         }
1070 
1071         /* Allocate and map memory for this span */
1072         status = hermon_dma_alloc(state, dma_info, MAP_ICM);
1073         if (status != DDI_SUCCESS) {
1074                 IBTF_DPRINTF_L2("hermon", "hermon_icm_alloc: DMA "
1075                     "allocation failed, status 0x%x", status);
1076                 switch (type) {
1077                 case HERMON_QPC:
1078                         HERMON_ICM_FREE(HERMON_AUXC);
1079                         HERMON_ICM_FREE(HERMON_ALTC);
1080                         HERMON_ICM_FREE(HERMON_RDB);
1081                         HERMON_ICM_FREE(HERMON_CMPT_QPC);
1082                         break;
1083                 case HERMON_SRQC:
1084                         HERMON_ICM_FREE(HERMON_CMPT_SRQC);
1085                         break;
1086                 case HERMON_CQC:
1087                         HERMON_ICM_FREE(HERMON_CMPT_CQC);
1088                         break;
1089                 case HERMON_EQC:
1090                         HERMON_ICM_FREE(HERMON_CMPT_EQC);
1091                         break;
1092                 }
1093 
1094                 return (DDI_FAILURE);
1095         }
1096         if (hermon_verbose) {
1097                 IBTF_DPRINTF_L2("hermon", "hermon_icm_alloc: mapping ICM: "
1098                     "rsrc_type (0x%x) index (0x%x, 0x%x) alloc length (0x%x) "
1099                     "icm_addr (0x%lx)", type, index1, index2, dma_info->length,
1100                     dma_info->icmaddr);
1101         }
1102 
1103         /* Set the bit for this slot in the table bitmap */
1104         HERMON_BMAP_BIT_SET(icm->icm_bitmap[index1], index2);
1105 
1106         return (DDI_SUCCESS);
1107 }
1108 
1109 /*
1110  * hermon_icm_free()
1111  *    Context: Can be called from base context.
1112  *
1113  * ICM resources have been successfully returned from hermon_icm_alloc().
1114  * Associated dma_info is no longer in use.  Free the ICM backing memory.
1115  */
1116 void
1117 hermon_icm_free(hermon_state_t *state, hermon_rsrc_type_t type,
1118     uint32_t index1, uint32_t index2)
1119 {
1120         hermon_icm_table_t      *icm;
1121         hermon_dma_info_t       *dma_info;
1122         int                     status;
1123 
1124         icm = &state->hs_icm[type];
1125         ASSERT(icm->icm_dma[index1][index2].icm_refcnt == 0);
1126 
1127         if (hermon_verbose) {
1128                 IBTF_DPRINTF_L2("hermon", "hermon_icm_free: rsrc_type (0x%x) "
1129                     "index (0x%x, 0x%x)", type, index1, index2);
1130         }
1131 
1132         dma_info = icm->icm_dma[index1] + index2;
1133 
1134         /* The following only happens if attach() is failing. */
1135         if (dma_info == NULL)
1136                 return;
1137 
1138         /* Unmap the ICM allocation, then free the backing DMA memory */
1139         status = hermon_unmap_icm_cmd_post(state, dma_info);
1140         if (status != DDI_SUCCESS) {
1141                 HERMON_WARNING(state, "UNMAP_ICM failure");
1142         }
1143         hermon_dma_free(dma_info);
1144 
1145         /* Clear the bit in the ICM table bitmap */
1146         HERMON_BMAP_BIT_CLR(icm->icm_bitmap[index1], index2);
1147 
1148         switch (type) {
1149         case HERMON_QPC:
1150                 HERMON_ICM_FREE(HERMON_AUXC);
1151                 HERMON_ICM_FREE(HERMON_ALTC);
1152                 HERMON_ICM_FREE(HERMON_RDB);
1153                 HERMON_ICM_FREE(HERMON_CMPT_QPC);
1154                 break;
1155         case HERMON_SRQC:
1156                 HERMON_ICM_FREE(HERMON_CMPT_SRQC);
1157                 break;
1158         case HERMON_CQC:
1159                 HERMON_ICM_FREE(HERMON_CMPT_CQC);
1160                 break;
1161         case HERMON_EQC:
1162                 HERMON_ICM_FREE(HERMON_CMPT_EQC);
1163                 break;
1164 
1165         }
1166 }
1167 
1168 
1169 /*
1170  * hermon_icm_num_to_hdl()
1171  *    Context: Can be called from base or interrupt context.
1172  *
1173  * Given an index of a resource, index through the sparsely allocated
1174  * arrays to find the pointer to its software handle.  Return NULL if
1175  * any of the arrays of pointers has been freed (should never happen).
1176  */
1177 void *
1178 hermon_icm_num_to_hdl(hermon_state_t *state, hermon_rsrc_type_t type,
1179     uint32_t idx)
1180 {
1181         hermon_icm_table_t      *icm;
1182         uint32_t                span_offset;
1183         uint32_t                index1, index2;
1184         void                    ***p1, **p2;
1185 
1186         icm = &state->hs_icm[type];
1187         hermon_index(index1, index2, idx, icm, span_offset);
1188         p1 = icm->num_to_hdl[index1];
1189         if (p1 == NULL) {
1190                 IBTF_DPRINTF_L2("hermon", "icm_num_to_hdl failed at level 1"
1191                     ": rsrc_type %d, index 0x%x", type, idx);
1192                 return (NULL);
1193         }
1194         p2 = p1[index2];
1195         if (p2 == NULL) {
1196                 IBTF_DPRINTF_L2("hermon", "icm_num_to_hdl failed at level 2"
1197                     ": rsrc_type %d, index 0x%x", type, idx);
1198                 return (NULL);
1199         }
1200         return (p2[span_offset]);
1201 }
1202 
1203 /*
1204  * hermon_icm_set_num_to_hdl()
1205  *    Context: Can be called from base or interrupt context.
1206  *
1207  * Given an index of a resource, we index through the sparsely allocated
1208  * arrays to store the software handle, used by hermon_icm_num_to_hdl().
1209  * This function is used to both set and reset (set to NULL) the handle.
1210  * This table is allocated during ICM allocation for the given resource,
1211  * so its existence is a given, and the store location does not conflict
1212  * with any other stores to the table (no locking needed).
1213  */
1214 void
1215 hermon_icm_set_num_to_hdl(hermon_state_t *state, hermon_rsrc_type_t type,
1216     uint32_t idx, void *hdl)
1217 {
1218         hermon_icm_table_t      *icm;
1219         uint32_t                span_offset;
1220         uint32_t                index1, index2;
1221 
1222         icm = &state->hs_icm[type];
1223         hermon_index(index1, index2, idx, icm, span_offset);
1224         ASSERT((hdl == NULL) ^
1225             (icm->num_to_hdl[index1][index2][span_offset] == NULL));
1226         icm->num_to_hdl[index1][index2][span_offset] = hdl;
1227 }
1228 
1229 /*
1230  * hermon_device_mode()
1231  *    Context: Can be called from base or interrupt context.
1232  *
1233  * Return HERMON_HCA_MODE for operational mode
1234  * Return HERMON_MAINTENANCE_MODE for maintenance mode
1235  * Return 0 otherwise
1236  *
1237  * A non-zero return for either operational or maintenance mode simplifies
1238  * one of the 2 uses of this function.
1239  */
1240 int
1241 hermon_device_mode(hermon_state_t *state)
1242 {
1243         if (state->hs_vendor_id != PCI_VENID_MLX)
1244                 return (0);
1245 
1246         switch (state->hs_device_id) {
1247         case PCI_DEVID_HERMON_SDR:
1248         case PCI_DEVID_HERMON_DDR:
1249         case PCI_DEVID_HERMON_DDRG2:
1250         case PCI_DEVID_HERMON_QDRG2:
1251         case PCI_DEVID_HERMON_QDRG2V:
1252                 return (HERMON_HCA_MODE);
1253         case PCI_DEVID_HERMON_MAINT:
1254                 return (HERMON_MAINTENANCE_MODE);
1255         default:
1256                 return (0);
1257         }
1258 }
1259 
1260 /*
1261  * hermon_drv_init()
1262  *    Context: Only called from attach() path context
1263  */
1264 /* ARGSUSED */
1265 static int
1266 hermon_drv_init(hermon_state_t *state, dev_info_t *dip, int instance)
1267 {
1268         int     status;
1269 
1270         /* Retrieve PCI device, vendor and rev IDs */
1271         state->hs_vendor_id   = HERMON_GET_VENDOR_ID(state->hs_dip);
1272         state->hs_device_id   = HERMON_GET_DEVICE_ID(state->hs_dip);
1273         state->hs_revision_id         = HERMON_GET_REVISION_ID(state->hs_dip);
1274 
1275         /*
1276          * Check and set the operational mode of the device. If the driver is
1277          * bound to the Hermon device in "maintenance mode", then this generally
1278          * means that either the device has been specifically jumpered to
1279          * start in this mode or the firmware boot process has failed to
1280          * successfully load either the primary or the secondary firmware
1281          * image.
1282          */
1283         state->hs_operational_mode = hermon_device_mode(state);
1284         switch (state->hs_operational_mode) {
1285         case HERMON_HCA_MODE:
1286                 state->hs_cfg_profile_setting = HERMON_CFG_MEMFREE;
1287                 break;
1288         case HERMON_MAINTENANCE_MODE:
1289                 HERMON_FMANOTE(state, HERMON_FMA_MAINT);
1290                 state->hs_fm_degraded_reason = HCA_FW_MISC; /* not fw reason */
1291                 return (DDI_FAILURE);
1292         default:
1293                 HERMON_FMANOTE(state, HERMON_FMA_PCIID);
1294                 HERMON_WARNING(state, "unexpected device type detected");
1295                 return (DDI_FAILURE);
1296         }
1297 
1298         /*
1299          * Initialize the Hermon hardware.
1300          *
1301          * Note:  If this routine returns an error, it is often a reasonably
1302          * good indication that something Hermon firmware-related has caused
1303          * the failure or some HW related errors have caused the failure.
1304          * (also there are few possibilities that SW (e.g. SW resource
1305          * shortage) can cause the failure, but the majority case is due to
1306          * either a firmware related error or a HW related one) In order to
1307          * give the user an opportunity (if desired) to update or reflash
1308          * the Hermon firmware image, we set "hs_operational_mode" flag
1309          * (described above) to indicate that we wish to enter maintenance
1310          * mode in case of the firmware-related issue.
1311          */
1312         status = hermon_hw_init(state);
1313         if (status != DDI_SUCCESS) {
1314                 cmn_err(CE_NOTE, "hermon%d: error during attach: %s", instance,
1315                     state->hs_attach_buf);
1316                 return (DDI_FAILURE);
1317         }
1318 
1319         /*
1320          * Now that the ISR has been setup, arm all the EQs for event
1321          * generation.
1322          */
1323 
1324         status = hermon_eq_arm_all(state);
1325         if (status != DDI_SUCCESS) {
1326                 cmn_err(CE_NOTE, "EQ Arm All failed\n");
1327                 hermon_hw_fini(state, HERMON_DRV_CLEANUP_ALL);
1328                 return (DDI_FAILURE);
1329         }
1330 
1331         /* test interrupts and event queues */
1332         status = hermon_nop_post(state, 0x0, 0x0);
1333         if (status != DDI_SUCCESS) {
1334                 cmn_err(CE_NOTE, "Interrupts/EQs failed\n");
1335                 hermon_hw_fini(state, HERMON_DRV_CLEANUP_ALL);
1336                 return (DDI_FAILURE);
1337         }
1338 
1339         /* Initialize Hermon softstate */
1340         status = hermon_soft_state_init(state);
1341         if (status != DDI_SUCCESS) {
1342                 cmn_err(CE_NOTE, "Failed to init soft state\n");
1343                 hermon_hw_fini(state, HERMON_DRV_CLEANUP_ALL);
1344                 return (DDI_FAILURE);
1345         }
1346 
1347         return (DDI_SUCCESS);
1348 }
1349 
1350 
1351 /*
1352  * hermon_drv_fini()
1353  *    Context: Only called from attach() and/or detach() path contexts
1354  */
1355 static void
1356 hermon_drv_fini(hermon_state_t *state)
1357 {
1358         /* Cleanup Hermon softstate */
1359         hermon_soft_state_fini(state);
1360 
1361         /* Cleanup Hermon resources and shutdown hardware */
1362         hermon_hw_fini(state, HERMON_DRV_CLEANUP_ALL);
1363 }
1364 
1365 
1366 /*
1367  * hermon_drv_fini2()
1368  *    Context: Only called from attach() and/or detach() path contexts
1369  */
1370 static void
1371 hermon_drv_fini2(hermon_state_t *state)
1372 {
1373         if (state->hs_fm_poll_thread) {
1374                 ddi_periodic_delete(state->hs_fm_poll_thread);
1375                 state->hs_fm_poll_thread = NULL;
1376         }
1377 
1378         /* HERMON_DRV_CLEANUP_LEVEL1 */
1379         if (state->hs_fm_cmdhdl) {
1380                 hermon_regs_map_free(state, &state->hs_fm_cmdhdl);
1381                 state->hs_fm_cmdhdl = NULL;
1382         }
1383 
1384         if (state->hs_reg_cmdhdl) {
1385                 ddi_regs_map_free(&state->hs_reg_cmdhdl);
1386                 state->hs_reg_cmdhdl = NULL;
1387         }
1388 
1389         /* HERMON_DRV_CLEANUP_LEVEL0 */
1390         if (state->hs_msix_tbl_entries) {
1391                 kmem_free(state->hs_msix_tbl_entries,
1392                     state->hs_msix_tbl_size);
1393                 state->hs_msix_tbl_entries = NULL;
1394         }
1395 
1396         if (state->hs_msix_pba_entries) {
1397                 kmem_free(state->hs_msix_pba_entries,
1398                     state->hs_msix_pba_size);
1399                 state->hs_msix_pba_entries = NULL;
1400         }
1401 
1402         if (state->hs_fm_msix_tblhdl) {
1403                 hermon_regs_map_free(state, &state->hs_fm_msix_tblhdl);
1404                 state->hs_fm_msix_tblhdl = NULL;
1405         }
1406 
1407         if (state->hs_reg_msix_tblhdl) {
1408                 ddi_regs_map_free(&state->hs_reg_msix_tblhdl);
1409                 state->hs_reg_msix_tblhdl = NULL;
1410         }
1411 
1412         if (state->hs_fm_msix_pbahdl) {
1413                 hermon_regs_map_free(state, &state->hs_fm_msix_pbahdl);
1414                 state->hs_fm_msix_pbahdl = NULL;
1415         }
1416 
1417         if (state->hs_reg_msix_pbahdl) {
1418                 ddi_regs_map_free(&state->hs_reg_msix_pbahdl);
1419                 state->hs_reg_msix_pbahdl = NULL;
1420         }
1421 
1422         if (state->hs_fm_pcihdl) {
1423                 hermon_pci_config_teardown(state, &state->hs_fm_pcihdl);
1424                 state->hs_fm_pcihdl = NULL;
1425         }
1426 
1427         if (state->hs_reg_pcihdl) {
1428                 pci_config_teardown(&state->hs_reg_pcihdl);
1429                 state->hs_reg_pcihdl = NULL;
1430         }
1431 }
1432 
1433 
1434 /*
1435  * hermon_isr_init()
1436  *    Context: Only called from attach() path context
1437  */
1438 static int
1439 hermon_isr_init(hermon_state_t *state)
1440 {
1441         int     status;
1442         int     intr;
1443 
1444         for (intr = 0; intr < state->hs_intrmsi_allocd; intr++) {
1445 
1446                 /*
1447                  * Add a handler for the interrupt or MSI
1448                  */
1449                 status = ddi_intr_add_handler(state->hs_intrmsi_hdl[intr],
1450                     hermon_isr, (caddr_t)state, (void *)(uintptr_t)intr);
1451                 if (status  != DDI_SUCCESS) {
1452                         return (DDI_FAILURE);
1453                 }
1454 
1455                 /*
1456                  * Enable the software interrupt.  Note: depending on the value
1457                  * returned in the capability flag, we have to call either
1458                  * ddi_intr_block_enable() or ddi_intr_enable().
1459                  */
1460                 if (state->hs_intrmsi_cap & DDI_INTR_FLAG_BLOCK) {
1461                         status = ddi_intr_block_enable(
1462                             &state->hs_intrmsi_hdl[intr], 1);
1463                         if (status != DDI_SUCCESS) {
1464                                 return (DDI_FAILURE);
1465                         }
1466                 } else {
1467                         status = ddi_intr_enable(state->hs_intrmsi_hdl[intr]);
1468                         if (status != DDI_SUCCESS) {
1469                                 return (DDI_FAILURE);
1470                         }
1471                 }
1472         }
1473 
1474         /*
1475          * Now that the ISR has been enabled, defer arm_all  EQs for event
1476          * generation until later, in case MSIX is enabled
1477          */
1478         return (DDI_SUCCESS);
1479 }
1480 
1481 
1482 /*
1483  * hermon_isr_fini()
1484  *    Context: Only called from attach() and/or detach() path contexts
1485  */
1486 static void
1487 hermon_isr_fini(hermon_state_t *state)
1488 {
1489         int     intr;
1490 
1491         for (intr = 0; intr < state->hs_intrmsi_allocd; intr++) {
1492                 /* Disable the software interrupt */
1493                 if (state->hs_intrmsi_cap & DDI_INTR_FLAG_BLOCK) {
1494                         (void) ddi_intr_block_disable(
1495                             &state->hs_intrmsi_hdl[intr], 1);
1496                 } else {
1497                         (void) ddi_intr_disable(state->hs_intrmsi_hdl[intr]);
1498                 }
1499 
1500                 /*
1501                  * Remove the software handler for the interrupt or MSI
1502                  */
1503                 (void) ddi_intr_remove_handler(state->hs_intrmsi_hdl[intr]);
1504         }
1505 }
1506 
1507 
1508 /*
1509  * Sum of ICM configured values:
1510  *     cMPT, dMPT, MTT, QPC, SRQC, RDB, CQC, ALTC, AUXC, EQC, MCG
1511  *
1512  */
1513 static uint64_t
1514 hermon_size_icm(hermon_state_t *state)
1515 {
1516         hermon_hw_querydevlim_t *devlim;
1517         hermon_cfg_profile_t    *cfg;
1518         uint64_t                num_cmpts, num_dmpts, num_mtts;
1519         uint64_t                num_qpcs, num_srqc, num_rdbs;
1520 #ifndef HERMON_FW_WORKAROUND
1521         uint64_t                num_auxc;
1522 #endif
1523         uint64_t                num_cqcs, num_altc;
1524         uint64_t                num_eqcs, num_mcgs;
1525         uint64_t                size;
1526 
1527         devlim = &state->hs_devlim;
1528         cfg = state->hs_cfg_profile;
1529         /* number of respective entries */
1530         num_cmpts = (uint64_t)0x1 << cfg->cp_log_num_cmpt;
1531         num_mtts = (uint64_t)0x1 << cfg->cp_log_num_mtt;
1532         num_dmpts = (uint64_t)0x1 << cfg->cp_log_num_dmpt;
1533         num_qpcs = (uint64_t)0x1 << cfg->cp_log_num_qp;
1534         num_srqc = (uint64_t)0x1 << cfg->cp_log_num_srq;
1535         num_rdbs = (uint64_t)0x1 << cfg->cp_log_num_rdb;
1536         num_cqcs = (uint64_t)0x1 << cfg->cp_log_num_cq;
1537         num_altc = (uint64_t)0x1 << cfg->cp_log_num_qp;
1538 #ifndef HERMON_FW_WORKAROUND
1539         num_auxc = (uint64_t)0x1 << cfg->cp_log_num_qp;
1540 #endif
1541         num_eqcs = (uint64_t)0x1 << cfg->cp_log_num_eq;
1542         num_mcgs = (uint64_t)0x1 << cfg->cp_log_num_mcg;
1543 
1544         size =
1545             num_cmpts   * devlim->cmpt_entry_sz +
1546             num_dmpts   * devlim->dmpt_entry_sz +
1547             num_mtts    * devlim->mtt_entry_sz +
1548             num_qpcs    * devlim->qpc_entry_sz +
1549             num_srqc    * devlim->srq_entry_sz +
1550             num_rdbs    * devlim->rdmardc_entry_sz +
1551             num_cqcs    * devlim->cqc_entry_sz +
1552             num_altc    * devlim->altc_entry_sz +
1553 #ifdef HERMON_FW_WORKAROUND
1554             0x80000000ull +
1555 #else
1556             num_auxc    * devlim->aux_entry_sz       +
1557 #endif
1558             num_eqcs    * devlim->eqc_entry_sz +
1559             num_mcgs    * HERMON_MCGMEM_SZ(state);
1560         return (size);
1561 }
1562 
1563 
1564 /*
1565  * hermon_hw_init()
1566  *    Context: Only called from attach() path context
1567  */
1568 static int
1569 hermon_hw_init(hermon_state_t *state)
1570 {
1571         hermon_drv_cleanup_level_t      cleanup;
1572         sm_nodeinfo_t                   nodeinfo;
1573         uint64_t                        clr_intr_offset;
1574         int                             status;
1575         uint32_t                        fw_size;        /* in page */
1576         uint64_t                        offset;
1577 
1578         /* This is where driver initialization begins */
1579         cleanup = HERMON_DRV_CLEANUP_LEVEL0;
1580 
1581         /* Setup device access attributes */
1582         state->hs_reg_accattr.devacc_attr_version = DDI_DEVICE_ATTR_V1;
1583         state->hs_reg_accattr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
1584         state->hs_reg_accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1585         state->hs_reg_accattr.devacc_attr_access = DDI_DEFAULT_ACC;
1586 
1587         /* Setup fma-protected access attributes */
1588         state->hs_fm_accattr.devacc_attr_version =
1589             hermon_devacc_attr_version(state);
1590         state->hs_fm_accattr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
1591         state->hs_fm_accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1592         /* set acc err protection type */
1593         state->hs_fm_accattr.devacc_attr_access =
1594             hermon_devacc_attr_access(state);
1595 
1596         /* Setup for PCI config read/write of HCA device */
1597         status = hermon_pci_config_setup(state, &state->hs_fm_pcihdl);
1598         if (status != DDI_SUCCESS) {
1599                 hermon_hw_fini(state, cleanup);
1600                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1601                     "hw_init_PCI_config_space_regmap_fail");
1602                 /* This case is not the degraded one */
1603                 return (DDI_FAILURE);
1604         }
1605 
1606         /* Map PCI config space and MSI-X tables/pba */
1607         hermon_set_msix_info(state);
1608 
1609         /* Map in Hermon registers (CMD, UAR, MSIX) and setup offsets */
1610         status = hermon_regs_map_setup(state, HERMON_CMD_BAR,
1611             &state->hs_reg_cmd_baseaddr, 0, 0, &state->hs_fm_accattr,
1612             &state->hs_fm_cmdhdl);
1613         if (status != DDI_SUCCESS) {
1614                 hermon_hw_fini(state, cleanup);
1615                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1616                     "hw_init_CMD_BAR_regmap_fail");
1617                 /* This case is not the degraded one */
1618                 return (DDI_FAILURE);
1619         }
1620 
1621         cleanup = HERMON_DRV_CLEANUP_LEVEL1;
1622         /*
1623          * We defer UAR-BAR mapping until later.  Need to know if
1624          * blueflame mapping is to be done, and don't know that until after
1625          * we get the dev_caps, so do it right after that
1626          */
1627 
1628         /*
1629          * There is a third BAR defined for Hermon - it is for MSIX
1630          *
1631          * Will need to explore it's possible need/use w/ Mellanox
1632          * [es] Temporary mapping maybe
1633          */
1634 
1635 #ifdef HERMON_SUPPORTS_MSIX_BAR
1636         status = ddi_regs_map_setup(state->hs_dip, HERMON_MSIX_BAR,
1637             &state->hs_reg_msi_baseaddr, 0, 0, &state->hs_reg_accattr,
1638             &state->hs_reg_msihdl);
1639         if (status != DDI_SUCCESS) {
1640                 hermon_hw_fini(state, cleanup);
1641                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1642                     "hw_init_MSIX_BAR_regmap_fail");
1643                 /* This case is not the degraded one */
1644                 return (DDI_FAILURE);
1645         }
1646 #endif
1647 
1648         cleanup = HERMON_DRV_CLEANUP_LEVEL2;
1649 
1650         /*
1651          * Save interesting registers away. The offsets of the first two
1652          * here (HCR and sw_reset) are detailed in the PRM, the others are
1653          * derived from values in the QUERY_FW output, so we'll save them
1654          * off later.
1655          */
1656         /* Host Command Register (HCR) */
1657         state->hs_cmd_regs.hcr = (hermon_hw_hcr_t *)
1658             ((uintptr_t)state->hs_reg_cmd_baseaddr + HERMON_CMD_HCR_OFFSET);
1659         state->hs_cmd_toggle = 0;    /* initialize it for use */
1660 
1661         /* Software Reset register (sw_reset) and semaphore */
1662         state->hs_cmd_regs.sw_reset = (uint32_t *)
1663             ((uintptr_t)state->hs_reg_cmd_baseaddr +
1664             HERMON_CMD_SW_RESET_OFFSET);
1665         state->hs_cmd_regs.sw_semaphore = (uint32_t *)
1666             ((uintptr_t)state->hs_reg_cmd_baseaddr +
1667             HERMON_CMD_SW_SEMAPHORE_OFFSET);
1668 
1669         /* make sure init'd before we start filling things in */
1670         bzero(&state->hs_hcaparams, sizeof (struct hermon_hw_initqueryhca_s));
1671 
1672         /* Initialize the Phase1 configuration profile */
1673         status = hermon_cfg_profile_init_phase1(state);
1674         if (status != DDI_SUCCESS) {
1675                 hermon_hw_fini(state, cleanup);
1676                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1677                     "hw_init_cfginit1_fail");
1678                 /* This case is not the degraded one */
1679                 return (DDI_FAILURE);
1680         }
1681         cleanup = HERMON_DRV_CLEANUP_LEVEL3;
1682 
1683         /* Do a software reset of the adapter to ensure proper state */
1684         status = hermon_sw_reset(state);
1685         if (status != HERMON_CMD_SUCCESS) {
1686                 hermon_hw_fini(state, cleanup);
1687                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1688                     "hw_init_sw_reset_fail");
1689                 /* This case is not the degraded one */
1690                 return (DDI_FAILURE);
1691         }
1692 
1693         /* Initialize mailboxes */
1694         status = hermon_rsrc_init_phase1(state);
1695         if (status != DDI_SUCCESS) {
1696                 hermon_hw_fini(state, cleanup);
1697                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1698                     "hw_init_rsrcinit1_fail");
1699                 /* This case is not the degraded one */
1700                 return (DDI_FAILURE);
1701         }
1702         cleanup = HERMON_DRV_CLEANUP_LEVEL4;
1703 
1704         /* Post QUERY_FW */
1705         status = hermon_cmn_query_cmd_post(state, QUERY_FW, 0, 0, &state->hs_fw,
1706             sizeof (hermon_hw_queryfw_t), HERMON_CMD_NOSLEEP_SPIN);
1707         if (status != HERMON_CMD_SUCCESS) {
1708                 cmn_err(CE_NOTE, "QUERY_FW command failed: %08x\n", status);
1709                 hermon_hw_fini(state, cleanup);
1710                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1711                     "hw_init_query_fw_cmd_fail");
1712                 /* This case is not the degraded one */
1713                 return (DDI_FAILURE);
1714         }
1715 
1716         /* Validate what/that HERMON FW version is appropriate */
1717 
1718         status = hermon_fw_version_check(state);
1719         if (status != DDI_SUCCESS) {
1720                 HERMON_FMANOTE(state, HERMON_FMA_FWVER);
1721                 if (state->hs_operational_mode == HERMON_HCA_MODE) {
1722                         cmn_err(CE_CONT, "Unsupported Hermon FW version: "
1723                             "expected: %04d.%04d.%04d, "
1724                             "actual: %04d.%04d.%04d\n",
1725                             HERMON_FW_VER_MAJOR,
1726                             HERMON_FW_VER_MINOR,
1727                             HERMON_FW_VER_SUBMINOR,
1728                             state->hs_fw.fw_rev_major,
1729                             state->hs_fw.fw_rev_minor,
1730                             state->hs_fw.fw_rev_subminor);
1731                 } else {
1732                         cmn_err(CE_CONT, "Unsupported FW version: "
1733                             "%04d.%04d.%04d\n",
1734                             state->hs_fw.fw_rev_major,
1735                             state->hs_fw.fw_rev_minor,
1736                             state->hs_fw.fw_rev_subminor);
1737                 }
1738                 state->hs_operational_mode = HERMON_MAINTENANCE_MODE;
1739                 state->hs_fm_degraded_reason = HCA_FW_MISMATCH;
1740                 hermon_hw_fini(state, cleanup);
1741                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1742                     "hw_init_checkfwver_fail");
1743                 /* This case is the degraded one */
1744                 return (HERMON_CMD_BAD_NVMEM);
1745         }
1746 
1747         /*
1748          * Save off the rest of the interesting registers that we'll be using.
1749          * Setup the offsets for the other registers.
1750          */
1751 
1752         /*
1753          * Hermon does the intr_offset from the BAR - technically should get the
1754          * BAR info from the response, but PRM says it's from BAR0-1, which is
1755          * for us the CMD BAR
1756          */
1757 
1758         clr_intr_offset  = state->hs_fw.clr_intr_offs & HERMON_CMD_OFFSET_MASK;
1759 
1760         /* Save Clear Interrupt address */
1761         state->hs_cmd_regs.clr_intr = (uint64_t *)
1762             (uintptr_t)(state->hs_reg_cmd_baseaddr + clr_intr_offset);
1763 
1764         /*
1765          * Set the error buffer also into the structure - used in hermon_event.c
1766          * to check for internal error on the HCA, not reported in eqe or
1767          * (necessarily) by interrupt
1768          */
1769         state->hs_cmd_regs.fw_err_buf = (uint32_t *)(uintptr_t)
1770             (state->hs_reg_cmd_baseaddr + state->hs_fw.error_buf_addr);
1771 
1772         /*
1773          * Invoke a polling thread to check the error buffer periodically.
1774          */
1775         if (!hermon_no_inter_err_chk) {
1776                 state->hs_fm_poll_thread = ddi_periodic_add(
1777                     hermon_inter_err_chk, (void *)state, FM_POLL_INTERVAL,
1778                     DDI_IPL_0);
1779         }
1780 
1781         cleanup = HERMON_DRV_CLEANUP_LEVEL5;
1782 
1783         /*
1784          * Allocate, map, and run the HCA Firmware.
1785          */
1786 
1787         /* Allocate memory for the firmware to load into and map it */
1788 
1789         /* get next higher power of 2 */
1790         fw_size = 1 << highbit(state->hs_fw.fw_pages);
1791         state->hs_fw_dma.length = fw_size << HERMON_PAGESHIFT;
1792         status = hermon_dma_alloc(state, &state->hs_fw_dma, MAP_FA);
1793         if (status != DDI_SUCCESS) {
1794                 cmn_err(CE_NOTE, "FW alloc failed\n");
1795                 hermon_hw_fini(state, cleanup);
1796                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1797                     "hw_init_dma_alloc_fw_fail");
1798                 /* This case is not the degraded one */
1799                 return (DDI_FAILURE);
1800         }
1801 
1802         cleanup = HERMON_DRV_CLEANUP_LEVEL6;
1803 
1804         /* Invoke the RUN_FW cmd to run the firmware */
1805         status = hermon_run_fw_cmd_post(state);
1806         if (status != DDI_SUCCESS) {
1807                 cmn_err(CE_NOTE, "RUN_FW command failed: 0x%08x\n", status);
1808                 if (status == HERMON_CMD_BAD_NVMEM) {
1809                         state->hs_operational_mode = HERMON_MAINTENANCE_MODE;
1810                         state->hs_fm_degraded_reason = HCA_FW_CORRUPT;
1811                 }
1812                 hermon_hw_fini(state, cleanup);
1813                 HERMON_ATTACH_MSG(state->hs_attach_buf, "hw_init_run_fw_fail");
1814                 /*
1815                  * If the status is HERMON_CMD_BAD_NVMEM, it's likely the
1816                  * firmware is corrupted, so the mode falls into the
1817                  * maintenance mode.
1818                  */
1819                 return (status == HERMON_CMD_BAD_NVMEM ? HERMON_CMD_BAD_NVMEM :
1820                     DDI_FAILURE);
1821         }
1822 
1823 
1824         /*
1825          * QUERY DEVICE LIMITS/CAPABILITIES
1826          * NOTE - in Hermon, the command is changed to QUERY_DEV_CAP,
1827          * but for familiarity we have kept the structure name the
1828          * same as Tavor/Arbel
1829          */
1830 
1831         status = hermon_cmn_query_cmd_post(state, QUERY_DEV_CAP, 0, 0,
1832             &state->hs_devlim, sizeof (hermon_hw_querydevlim_t),
1833             HERMON_CMD_NOSLEEP_SPIN);
1834         if (status != HERMON_CMD_SUCCESS) {
1835                 cmn_err(CE_NOTE, "QUERY_DEV_CAP command failed: 0x%08x\n",
1836                     status);
1837                 hermon_hw_fini(state, cleanup);
1838                 HERMON_ATTACH_MSG(state->hs_attach_buf, "hw_init_devcap_fail");
1839                 /* This case is not the degraded one */
1840                 return (DDI_FAILURE);
1841         }
1842 
1843         state->hs_rsvd_eqs = max(state->hs_devlim.num_rsvd_eq,
1844             (4 * state->hs_devlim.num_rsvd_uar));
1845 
1846         /* now we have enough info to map in the UAR BAR */
1847         /*
1848          * First, we figure out how to map the BAR for UAR - use only half if
1849          * BlueFlame is enabled - in that case the mapped length is 1/2 the
1850          * log_max_uar_sz (max__uar - 1) * 1MB ( +20).
1851          */
1852 
1853         if (state->hs_devlim.blu_flm) {              /* Blue Flame Enabled */
1854                 offset = (uint64_t)1 << (state->hs_devlim.log_max_uar_sz + 20);
1855         } else {
1856                 offset = 0;     /* a zero length means map the whole thing */
1857         }
1858         status = hermon_regs_map_setup(state, HERMON_UAR_BAR,
1859             &state->hs_reg_uar_baseaddr, 0, offset, &state->hs_fm_accattr,
1860             &state->hs_fm_uarhdl);
1861         if (status != DDI_SUCCESS) {
1862                 HERMON_ATTACH_MSG(state->hs_attach_buf, "UAR BAR mapping");
1863                 /* This case is not the degraded one */
1864                 return (DDI_FAILURE);
1865         }
1866 
1867         /* and if BlueFlame is enabled, map the other half there */
1868         if (state->hs_devlim.blu_flm) {              /* Blue Flame Enabled */
1869                 offset = (uint64_t)1 << (state->hs_devlim.log_max_uar_sz + 20);
1870                 status = ddi_regs_map_setup(state->hs_dip, HERMON_UAR_BAR,
1871                     &state->hs_reg_bf_baseaddr, offset, offset,
1872                     &state->hs_reg_accattr, &state->hs_reg_bfhdl);
1873                 if (status != DDI_SUCCESS) {
1874                         HERMON_ATTACH_MSG(state->hs_attach_buf,
1875                             "BlueFlame BAR mapping");
1876                         /* This case is not the degraded one */
1877                         return (DDI_FAILURE);
1878                 }
1879                 /* This will be used in hw_fini if we fail to init. */
1880                 state->hs_bf_offset = offset;
1881         }
1882         cleanup = HERMON_DRV_CLEANUP_LEVEL7;
1883 
1884         /* Hermon has a couple of things needed for phase 2 in query port */
1885 
1886         status = hermon_cmn_query_cmd_post(state, QUERY_PORT, 0, 0x01,
1887             &state->hs_queryport, sizeof (hermon_hw_query_port_t),
1888             HERMON_CMD_NOSLEEP_SPIN);
1889         if (status != HERMON_CMD_SUCCESS) {
1890                 cmn_err(CE_NOTE, "QUERY_PORT command failed: 0x%08x\n",
1891                     status);
1892                 hermon_hw_fini(state, cleanup);
1893                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1894                     "hw_init_queryport_fail");
1895                 /* This case is not the degraded one */
1896                 return (DDI_FAILURE);
1897         }
1898 
1899         /* Initialize the Phase2 Hermon configuration profile */
1900         status = hermon_cfg_profile_init_phase2(state);
1901         if (status != DDI_SUCCESS) {
1902                 cmn_err(CE_NOTE, "CFG phase 2 failed: 0x%08x\n", status);
1903                 hermon_hw_fini(state, cleanup);
1904                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1905                     "hw_init_cfginit2_fail");
1906                 /* This case is not the degraded one */
1907                 return (DDI_FAILURE);
1908         }
1909 
1910         /* Determine and set the ICM size */
1911         state->hs_icm_sz = hermon_size_icm(state);
1912         status           = hermon_set_icm_size_cmd_post(state);
1913         if (status != DDI_SUCCESS) {
1914                 cmn_err(CE_NOTE, "Hermon: SET_ICM_SIZE cmd failed: 0x%08x\n",
1915                     status);
1916                 hermon_hw_fini(state, cleanup);
1917                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1918                     "hw_init_seticmsz_fail");
1919                 /* This case is not the degraded one */
1920                 return (DDI_FAILURE);
1921         }
1922         /* alloc icm aux physical memory and map it */
1923 
1924         state->hs_icma_dma.length = 1 << highbit(state->hs_icma_sz);
1925 
1926         status = hermon_dma_alloc(state, &state->hs_icma_dma, MAP_ICM_AUX);
1927         if (status != DDI_SUCCESS) {
1928                 cmn_err(CE_NOTE, "failed to alloc (0x%llx) bytes for ICMA\n",
1929                     (longlong_t)state->hs_icma_dma.length);
1930                 hermon_hw_fini(state, cleanup);
1931                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1932                     "hw_init_dma_alloc_icm_aux_fail");
1933                 /* This case is not the degraded one */
1934                 return (DDI_FAILURE);
1935         }
1936         cleanup = HERMON_DRV_CLEANUP_LEVEL8;
1937 
1938         cleanup = HERMON_DRV_CLEANUP_LEVEL9;
1939 
1940         /* Allocate an array of structures to house the ICM tables */
1941         state->hs_icm = kmem_zalloc(HERMON_NUM_ICM_RESOURCES *
1942             sizeof (hermon_icm_table_t), KM_SLEEP);
1943 
1944         /* Set up the ICM address space and the INIT_HCA command input */
1945         status = hermon_icm_config_setup(state, &state->hs_hcaparams);
1946         if (status != HERMON_CMD_SUCCESS) {
1947                 cmn_err(CE_NOTE, "ICM configuration failed\n");
1948                 hermon_hw_fini(state, cleanup);
1949                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1950                     "hw_init_icm_config_setup_fail");
1951                 /* This case is not the degraded one */
1952                 return (DDI_FAILURE);
1953         }
1954         cleanup = HERMON_DRV_CLEANUP_LEVEL10;
1955 
1956         /* Initialize the adapter with the INIT_HCA cmd */
1957         status = hermon_init_hca_cmd_post(state, &state->hs_hcaparams,
1958             HERMON_CMD_NOSLEEP_SPIN);
1959         if (status != HERMON_CMD_SUCCESS) {
1960                 cmn_err(CE_NOTE, "INIT_HCA command failed: %08x\n", status);
1961                 hermon_hw_fini(state, cleanup);
1962                 HERMON_ATTACH_MSG(state->hs_attach_buf, "hw_init_hca_fail");
1963                 /* This case is not the degraded one */
1964                 return (DDI_FAILURE);
1965         }
1966         cleanup = HERMON_DRV_CLEANUP_LEVEL11;
1967 
1968         /* Enter the second phase of init for Hermon configuration/resources */
1969         status = hermon_rsrc_init_phase2(state);
1970         if (status != DDI_SUCCESS) {
1971                 hermon_hw_fini(state, cleanup);
1972                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1973                     "hw_init_rsrcinit2_fail");
1974                 /* This case is not the degraded one */
1975                 return (DDI_FAILURE);
1976         }
1977         cleanup = HERMON_DRV_CLEANUP_LEVEL12;
1978 
1979         /* Query the adapter via QUERY_ADAPTER */
1980         status = hermon_cmn_query_cmd_post(state, QUERY_ADAPTER, 0, 0,
1981             &state->hs_adapter, sizeof (hermon_hw_queryadapter_t),
1982             HERMON_CMD_NOSLEEP_SPIN);
1983         if (status != HERMON_CMD_SUCCESS) {
1984                 cmn_err(CE_NOTE, "Hermon: QUERY_ADAPTER command failed: %08x\n",
1985                     status);
1986                 hermon_hw_fini(state, cleanup);
1987                 HERMON_ATTACH_MSG(state->hs_attach_buf,
1988                     "hw_init_query_adapter_fail");
1989                 /* This case is not the degraded one */
1990                 return (DDI_FAILURE);
1991         }
1992 
1993         /* Allocate protection domain (PD) for Hermon internal use */
1994         status = hermon_pd_alloc(state, &state->hs_pdhdl_internal,
1995             HERMON_SLEEP);
1996         if (status != DDI_SUCCESS) {
1997                 cmn_err(CE_NOTE, "failed to alloc internal PD\n");
1998                 hermon_hw_fini(state, cleanup);
1999                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2000                     "hw_init_internal_pd_alloc_fail");
2001                 /* This case is not the degraded one */
2002                 return (DDI_FAILURE);
2003         }
2004         cleanup = HERMON_DRV_CLEANUP_LEVEL13;
2005 
2006         /* Setup UAR page for kernel use */
2007         status = hermon_internal_uarpg_init(state);
2008         if (status != DDI_SUCCESS) {
2009                 cmn_err(CE_NOTE, "failed to setup internal UAR\n");
2010                 hermon_hw_fini(state, cleanup);
2011                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2012                     "hw_init_internal_uarpg_alloc_fail");
2013                 /* This case is not the degraded one */
2014                 return (DDI_FAILURE);
2015         }
2016         cleanup = HERMON_DRV_CLEANUP_LEVEL14;
2017 
2018         /* Query and initialize the Hermon interrupt/MSI information */
2019         status = hermon_intr_or_msi_init(state);
2020         if (status != DDI_SUCCESS) {
2021                 cmn_err(CE_NOTE, "failed to setup INTR/MSI\n");
2022                 hermon_hw_fini(state, cleanup);
2023                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2024                     "hw_init_intr_or_msi_init_fail");
2025                 /* This case is not the degraded one */
2026                 return (DDI_FAILURE);
2027         }
2028         cleanup = HERMON_DRV_CLEANUP_LEVEL15;
2029 
2030         status = hermon_isr_init(state);        /* set up the isr */
2031         if (status != DDI_SUCCESS) {
2032                 cmn_err(CE_NOTE, "failed to init isr\n");
2033                 hermon_hw_fini(state, cleanup);
2034                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2035                     "hw_init_isrinit_fail");
2036                 /* This case is not the degraded one */
2037                 return (DDI_FAILURE);
2038         }
2039         cleanup = HERMON_DRV_CLEANUP_LEVEL16;
2040 
2041         /* Setup the event queues */
2042         status = hermon_eq_init_all(state);
2043         if (status != DDI_SUCCESS) {
2044                 cmn_err(CE_NOTE, "failed to init EQs\n");
2045                 hermon_hw_fini(state, cleanup);
2046                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2047                     "hw_init_eqinitall_fail");
2048                 /* This case is not the degraded one */
2049                 return (DDI_FAILURE);
2050         }
2051         cleanup = HERMON_DRV_CLEANUP_LEVEL17;
2052 
2053 
2054 
2055         /* Reserve contexts for QP0 and QP1 */
2056         status = hermon_special_qp_contexts_reserve(state);
2057         if (status != DDI_SUCCESS) {
2058                 cmn_err(CE_NOTE, "failed to init special QPs\n");
2059                 hermon_hw_fini(state, cleanup);
2060                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2061                     "hw_init_rsrv_sqp_fail");
2062                 /* This case is not the degraded one */
2063                 return (DDI_FAILURE);
2064         }
2065         cleanup = HERMON_DRV_CLEANUP_LEVEL18;
2066 
2067         /* Initialize for multicast group handling */
2068         status = hermon_mcg_init(state);
2069         if (status != DDI_SUCCESS) {
2070                 cmn_err(CE_NOTE, "failed to init multicast\n");
2071                 hermon_hw_fini(state, cleanup);
2072                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2073                     "hw_init_mcg_init_fail");
2074                 /* This case is not the degraded one */
2075                 return (DDI_FAILURE);
2076         }
2077         cleanup = HERMON_DRV_CLEANUP_LEVEL19;
2078 
2079         /* Initialize the Hermon IB port(s) */
2080         status = hermon_hca_port_init(state);
2081         if (status != DDI_SUCCESS) {
2082                 cmn_err(CE_NOTE, "failed to init HCA Port\n");
2083                 hermon_hw_fini(state, cleanup);
2084                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2085                     "hw_init_hca_port_init_fail");
2086                 /* This case is not the degraded one */
2087                 return (DDI_FAILURE);
2088         }
2089 
2090         cleanup = HERMON_DRV_CLEANUP_ALL;
2091 
2092         /* Determine NodeGUID and SystemImageGUID */
2093         status = hermon_getnodeinfo_cmd_post(state, HERMON_CMD_NOSLEEP_SPIN,
2094             &nodeinfo);
2095         if (status != HERMON_CMD_SUCCESS) {
2096                 cmn_err(CE_NOTE, "GetNodeInfo command failed: %08x\n", status);
2097                 hermon_hw_fini(state, cleanup);
2098                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2099                     "hw_init_getnodeinfo_cmd_fail");
2100                 /* This case is not the degraded one */
2101                 return (DDI_FAILURE);
2102         }
2103 
2104         /*
2105          * If the NodeGUID value was set in OBP properties, then we use that
2106          * value.  But we still print a message if the value we queried from
2107          * firmware does not match this value.
2108          *
2109          * Otherwise if OBP value is not set then we use the value from
2110          * firmware unconditionally.
2111          */
2112         if (state->hs_cfg_profile->cp_nodeguid) {
2113                 state->hs_nodeguid   = state->hs_cfg_profile->cp_nodeguid;
2114         } else {
2115                 state->hs_nodeguid = nodeinfo.NodeGUID;
2116         }
2117 
2118         if (state->hs_nodeguid != nodeinfo.NodeGUID) {
2119                 cmn_err(CE_NOTE, "!NodeGUID value queried from firmware "
2120                     "does not match value set by device property");
2121         }
2122 
2123         /*
2124          * If the SystemImageGUID value was set in OBP properties, then we use
2125          * that value.  But we still print a message if the value we queried
2126          * from firmware does not match this value.
2127          *
2128          * Otherwise if OBP value is not set then we use the value from
2129          * firmware unconditionally.
2130          */
2131         if (state->hs_cfg_profile->cp_sysimgguid) {
2132                 state->hs_sysimgguid = state->hs_cfg_profile->cp_sysimgguid;
2133         } else {
2134                 state->hs_sysimgguid = nodeinfo.SystemImageGUID;
2135         }
2136 
2137         if (state->hs_sysimgguid != nodeinfo.SystemImageGUID) {
2138                 cmn_err(CE_NOTE, "!SystemImageGUID value queried from firmware "
2139                     "does not match value set by device property");
2140         }
2141 
2142         /* Get NodeDescription */
2143         status = hermon_getnodedesc_cmd_post(state, HERMON_CMD_NOSLEEP_SPIN,
2144             (sm_nodedesc_t *)&state->hs_nodedesc);
2145         if (status != HERMON_CMD_SUCCESS) {
2146                 cmn_err(CE_CONT, "GetNodeDesc command failed: %08x\n", status);
2147                 hermon_hw_fini(state, cleanup);
2148                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2149                     "hw_init_getnodedesc_cmd_fail");
2150                 /* This case is not the degraded one */
2151                 return (DDI_FAILURE);
2152         }
2153 
2154         return (DDI_SUCCESS);
2155 }
2156 
2157 
2158 /*
2159  * hermon_hw_fini()
2160  *    Context: Only called from attach() and/or detach() path contexts
2161  */
2162 static void
2163 hermon_hw_fini(hermon_state_t *state, hermon_drv_cleanup_level_t cleanup)
2164 {
2165         uint_t          num_ports;
2166         int             i, status;
2167 
2168 
2169         /*
2170          * JBDB - We might not want to run these returns in all cases of
2171          * Bad News. We should still attempt to free all of the DMA memory
2172          * resources...  This needs to be worked last, after all allocations
2173          * are implemented. For now, and possibly for later, this works.
2174          */
2175 
2176         switch (cleanup) {
2177         /*
2178          * If we add more driver initialization steps that should be cleaned
2179          * up here, we need to ensure that HERMON_DRV_CLEANUP_ALL is still the
2180          * first entry (i.e. corresponds to the last init step).
2181          */
2182         case HERMON_DRV_CLEANUP_ALL:
2183                 /* Shutdown the Hermon IB port(s) */
2184                 num_ports = state->hs_cfg_profile->cp_num_ports;
2185                 (void) hermon_hca_ports_shutdown(state, num_ports);
2186                 /* FALLTHROUGH */
2187 
2188         case HERMON_DRV_CLEANUP_LEVEL19:
2189                 /* Teardown resources used for multicast group handling */
2190                 hermon_mcg_fini(state);
2191                 /* FALLTHROUGH */
2192 
2193         case HERMON_DRV_CLEANUP_LEVEL18:
2194                 /* Unreserve the special QP contexts */
2195                 hermon_special_qp_contexts_unreserve(state);
2196                 /* FALLTHROUGH */
2197 
2198         case HERMON_DRV_CLEANUP_LEVEL17:
2199                 /*
2200                  * Attempt to teardown all event queues (EQ).  If we fail
2201                  * here then print a warning message and return.  Something
2202                  * (either in HW or SW) has gone seriously wrong.
2203                  */
2204                 status = hermon_eq_fini_all(state);
2205                 if (status != DDI_SUCCESS) {
2206                         HERMON_WARNING(state, "failed to teardown EQs");
2207                         return;
2208                 }
2209                 /* FALLTHROUGH */
2210         case HERMON_DRV_CLEANUP_LEVEL16:
2211                 /* Teardown Hermon interrupts */
2212                 hermon_isr_fini(state);
2213                 /* FALLTHROUGH */
2214 
2215         case HERMON_DRV_CLEANUP_LEVEL15:
2216                 status = hermon_intr_or_msi_fini(state);
2217                 if (status != DDI_SUCCESS) {
2218                         HERMON_WARNING(state, "failed to free intr/MSI");
2219                         return;
2220                 }
2221                 /* FALLTHROUGH */
2222 
2223         case HERMON_DRV_CLEANUP_LEVEL14:
2224                 /* Free the resources for the Hermon internal UAR pages */
2225                 hermon_internal_uarpg_fini(state);
2226                 /* FALLTHROUGH */
2227 
2228         case HERMON_DRV_CLEANUP_LEVEL13:
2229                 /*
2230                  * Free the PD that was used internally by Hermon software.  If
2231                  * we fail here then print a warning and return.  Something
2232                  * (probably software-related, but perhaps HW) has gone wrong.
2233                  */
2234                 status = hermon_pd_free(state, &state->hs_pdhdl_internal);
2235                 if (status != DDI_SUCCESS) {
2236                         HERMON_WARNING(state, "failed to free internal PD");
2237                         return;
2238                 }
2239                 /* FALLTHROUGH */
2240 
2241         case HERMON_DRV_CLEANUP_LEVEL12:
2242                 /* Cleanup all the phase2 resources first */
2243                 hermon_rsrc_fini(state, HERMON_RSRC_CLEANUP_ALL);
2244                 /* FALLTHROUGH */
2245 
2246         case HERMON_DRV_CLEANUP_LEVEL11:
2247                 /* LEVEL11 is after INIT_HCA */
2248                 /* FALLTHROUGH */
2249 
2250 
2251         case HERMON_DRV_CLEANUP_LEVEL10:
2252                 /*
2253                  * Unmap the ICM memory area with UNMAP_ICM command.
2254                  */
2255                 status = hermon_unmap_icm_cmd_post(state, NULL);
2256                 if (status != DDI_SUCCESS) {
2257                         cmn_err(CE_WARN,
2258                             "hermon_hw_fini: failed to unmap ICM\n");
2259                 }
2260 
2261                 /* Free the initial ICM DMA handles */
2262                 hermon_icm_dma_fini(state);
2263 
2264                 /* Free the ICM table structures */
2265                 hermon_icm_tables_fini(state);
2266 
2267                 /* Free the ICM table handles */
2268                 kmem_free(state->hs_icm, HERMON_NUM_ICM_RESOURCES *
2269                     sizeof (hermon_icm_table_t));
2270 
2271                 /* FALLTHROUGH */
2272 
2273         case HERMON_DRV_CLEANUP_LEVEL9:
2274                 /*
2275                  * Unmap the ICM Aux memory area with UNMAP_ICM_AUX command.
2276                  */
2277                 status = hermon_unmap_icm_aux_cmd_post(state);
2278                 if (status != HERMON_CMD_SUCCESS) {
2279                         cmn_err(CE_NOTE,
2280                             "hermon_hw_fini: failed to unmap ICMA\n");
2281                 }
2282                 /* FALLTHROUGH */
2283 
2284         case HERMON_DRV_CLEANUP_LEVEL8:
2285                 /*
2286                  * Deallocate ICM Aux DMA memory.
2287                  */
2288                 hermon_dma_free(&state->hs_icma_dma);
2289                 /* FALLTHROUGH */
2290 
2291         case HERMON_DRV_CLEANUP_LEVEL7:
2292                 if (state->hs_fm_uarhdl) {
2293                         hermon_regs_map_free(state, &state->hs_fm_uarhdl);
2294                         state->hs_fm_uarhdl = NULL;
2295                 }
2296 
2297                 if (state->hs_reg_uarhdl) {
2298                         ddi_regs_map_free(&state->hs_reg_uarhdl);
2299                         state->hs_reg_uarhdl = NULL;
2300                 }
2301 
2302                 if (state->hs_bf_offset != 0 && state->hs_reg_bfhdl) {
2303                         ddi_regs_map_free(&state->hs_reg_bfhdl);
2304                         state->hs_reg_bfhdl = NULL;
2305                 }
2306 
2307                 for (i = 0; i < HERMON_MAX_PORTS; i++) {
2308                         if (state->hs_pkey[i]) {
2309                                 kmem_free(state->hs_pkey[i], (1 <<
2310                                     state->hs_cfg_profile->cp_log_max_pkeytbl) *
2311                                     sizeof (ib_pkey_t));
2312                                 state->hs_pkey[i] = NULL;
2313                         }
2314                         if (state->hs_guid[i]) {
2315                                 kmem_free(state->hs_guid[i], (1 <<
2316                                     state->hs_cfg_profile->cp_log_max_gidtbl) *
2317                                     sizeof (ib_guid_t));
2318                                 state->hs_guid[i] = NULL;
2319                         }
2320                 }
2321                 /* FALLTHROUGH */
2322 
2323         case HERMON_DRV_CLEANUP_LEVEL6:
2324                 /*
2325                  * Unmap the firmware memory area with UNMAP_FA command.
2326                  */
2327                 status = hermon_unmap_fa_cmd_post(state);
2328 
2329                 if (status != HERMON_CMD_SUCCESS) {
2330                         cmn_err(CE_NOTE,
2331                             "hermon_hw_fini: failed to unmap FW\n");
2332                 }
2333 
2334                 /*
2335                  * Deallocate firmware DMA memory.
2336                  */
2337                 hermon_dma_free(&state->hs_fw_dma);
2338                 /* FALLTHROUGH */
2339 
2340         case HERMON_DRV_CLEANUP_LEVEL5:
2341                 /* stop the poll thread */
2342                 if (state->hs_fm_poll_thread) {
2343                         ddi_periodic_delete(state->hs_fm_poll_thread);
2344                         state->hs_fm_poll_thread = NULL;
2345                 }
2346                 /* FALLTHROUGH */
2347 
2348         case HERMON_DRV_CLEANUP_LEVEL4:
2349                 /* Then cleanup the phase1 resources */
2350                 hermon_rsrc_fini(state, HERMON_RSRC_CLEANUP_PHASE1_COMPLETE);
2351                 /* FALLTHROUGH */
2352 
2353         case HERMON_DRV_CLEANUP_LEVEL3:
2354                 /* Teardown any resources allocated for the config profile */
2355                 hermon_cfg_profile_fini(state);
2356                 /* FALLTHROUGH */
2357 
2358         case HERMON_DRV_CLEANUP_LEVEL2:
2359 #ifdef HERMON_SUPPORTS_MSIX_BAR
2360                 /*
2361                  * unmap 3rd BAR, MSIX BAR
2362                  */
2363                 if (state->hs_reg_msihdl) {
2364                         ddi_regs_map_free(&state->hs_reg_msihdl);
2365                         state->hs_reg_msihdl = NULL;
2366                 }
2367                 /* FALLTHROUGH */
2368 #endif
2369         case HERMON_DRV_CLEANUP_LEVEL1:
2370         case HERMON_DRV_CLEANUP_LEVEL0:
2371                 /*
2372                  * LEVEL1 and LEVEL0 resources are freed in
2373                  * hermon_drv_fini2().
2374                  */
2375                 break;
2376 
2377         default:
2378                 HERMON_WARNING(state, "unexpected driver cleanup level");
2379                 return;
2380         }
2381 }
2382 
2383 
2384 /*
2385  * hermon_soft_state_init()
2386  *    Context: Only called from attach() path context
2387  */
2388 static int
2389 hermon_soft_state_init(hermon_state_t *state)
2390 {
2391         ibt_hca_attr_t          *hca_attr;
2392         uint64_t                maxval, val;
2393         ibt_hca_flags_t         caps = IBT_HCA_NO_FLAGS;
2394         ibt_hca_flags2_t        caps2 = IBT_HCA2_NO_FLAGS;
2395         int                     status;
2396         int                     max_send_wqe_bytes;
2397         int                     max_recv_wqe_bytes;
2398 
2399         /*
2400          * The ibc_hca_info_t struct is passed to the IBTF.  This is the
2401          * routine where we initialize it.  Many of the init values come from
2402          * either configuration variables or successful queries of the Hermon
2403          * hardware abilities
2404          */
2405         state->hs_ibtfinfo.hca_ci_vers       = IBCI_V4;
2406         state->hs_ibtfinfo.hca_handle        = (ibc_hca_hdl_t)state;
2407         state->hs_ibtfinfo.hca_ops   = &hermon_ibc_ops;
2408 
2409         hca_attr = kmem_zalloc(sizeof (ibt_hca_attr_t), KM_SLEEP);
2410         state->hs_ibtfinfo.hca_attr = hca_attr;
2411 
2412         hca_attr->hca_dip = state->hs_dip;
2413         hca_attr->hca_fw_major_version = state->hs_fw.fw_rev_major;
2414         hca_attr->hca_fw_minor_version = state->hs_fw.fw_rev_minor;
2415         hca_attr->hca_fw_micro_version = state->hs_fw.fw_rev_subminor;
2416 
2417         /* CQ interrupt moderation maximums - each limited to 16 bits */
2418         hca_attr->hca_max_cq_mod_count = 0xFFFF;
2419         hca_attr->hca_max_cq_mod_usec = 0xFFFF;
2420         hca_attr->hca_max_cq_handlers = state->hs_intrmsi_allocd;
2421 
2422 
2423         /*
2424          * Determine HCA capabilities:
2425          * No default support for IBT_HCA_RD, IBT_HCA_RAW_MULTICAST,
2426          *    IBT_HCA_ATOMICS_GLOBAL, IBT_HCA_RESIZE_CHAN, IBT_HCA_INIT_TYPE,
2427          *    or IBT_HCA_SHUTDOWN_PORT
2428          * But IBT_HCA_AH_PORT_CHECK, IBT_HCA_SQD_RTS_PORT, IBT_HCA_SI_GUID,
2429          *    IBT_HCA_RNR_NAK, IBT_HCA_CURRENT_QP_STATE, IBT_HCA_PORT_UP,
2430          *    IBT_HCA_SRQ, IBT_HCA_RESIZE_SRQ and IBT_HCA_FMR are always
2431          *    supported
2432          * All other features are conditionally supported, depending on the
2433          *    status return by the Hermon HCA in QUERY_DEV_LIM.
2434          */
2435         if (state->hs_devlim.ud_multi) {
2436                 caps |= IBT_HCA_UD_MULTICAST;
2437         }
2438         if (state->hs_devlim.atomic) {
2439                 caps |= IBT_HCA_ATOMICS_HCA;
2440         }
2441         if (state->hs_devlim.apm) {
2442                 caps |= IBT_HCA_AUTO_PATH_MIG;
2443         }
2444         if (state->hs_devlim.pkey_v) {
2445                 caps |= IBT_HCA_PKEY_CNTR;
2446         }
2447         if (state->hs_devlim.qkey_v) {
2448                 caps |= IBT_HCA_QKEY_CNTR;
2449         }
2450         if (state->hs_devlim.ipoib_cksm) {
2451                 caps |= IBT_HCA_CKSUM_FULL;
2452                 caps2 |= IBT_HCA2_IP_CLASS;
2453         }
2454         if (state->hs_devlim.mod_wr_srq) {
2455                 caps |= IBT_HCA_RESIZE_SRQ;
2456         }
2457         if (state->hs_devlim.lif) {
2458                 caps |= IBT_HCA_LOCAL_INVAL_FENCE;
2459         }
2460         if (state->hs_devlim.reserved_lkey) {
2461                 caps2 |= IBT_HCA2_RES_LKEY;
2462                 hca_attr->hca_reserved_lkey = state->hs_devlim.rsv_lkey;
2463         }
2464         if (state->hs_devlim.local_inv && state->hs_devlim.remote_inv &&
2465             state->hs_devlim.fast_reg_wr) {  /* fw needs to be >= 2.7.000 */
2466                 if ((state->hs_fw.fw_rev_major > 2) ||
2467                     ((state->hs_fw.fw_rev_major == 2) &&
2468                     (state->hs_fw.fw_rev_minor >= 7)))
2469                         caps2 |= IBT_HCA2_MEM_MGT_EXT;
2470         }
2471         if (state->hs_devlim.log_max_rss_tbl_sz) {
2472                 hca_attr->hca_rss_max_log2_table =
2473                     state->hs_devlim.log_max_rss_tbl_sz;
2474                 if (state->hs_devlim.rss_xor)
2475                         caps2 |= IBT_HCA2_RSS_XOR_ALG;
2476                 if (state->hs_devlim.rss_toep)
2477                         caps2 |= IBT_HCA2_RSS_TPL_ALG;
2478         }
2479         if (state->hs_devlim.mps) {
2480                 caps |= IBT_HCA_ZERO_BASED_VA;
2481         }
2482         if (state->hs_devlim.zb) {
2483                 caps |= IBT_HCA_MULT_PAGE_SZ_MR;
2484         }
2485         caps |= (IBT_HCA_AH_PORT_CHECK | IBT_HCA_SQD_SQD_PORT |
2486             IBT_HCA_SI_GUID | IBT_HCA_RNR_NAK | IBT_HCA_CURRENT_QP_STATE |
2487             IBT_HCA_PORT_UP | IBT_HCA_RC_SRQ | IBT_HCA_UD_SRQ | IBT_HCA_FMR);
2488         caps2 |= IBT_HCA2_DMA_MR;
2489 
2490         if (state->hs_devlim.log_max_gso_sz) {
2491                 hca_attr->hca_max_lso_size =
2492                     (1 << state->hs_devlim.log_max_gso_sz);
2493                 /* 64 = ctrl & datagram seg, 4 = LSO seg, 16 = 1 SGL */
2494                 hca_attr->hca_max_lso_hdr_size =
2495                     state->hs_devlim.max_desc_sz_sq - (64 + 4 + 16);
2496         }
2497 
2498         caps |= IBT_HCA_WQE_SIZE_INFO;
2499         max_send_wqe_bytes = state->hs_devlim.max_desc_sz_sq;
2500         max_recv_wqe_bytes = state->hs_devlim.max_desc_sz_rq;
2501         hca_attr->hca_ud_send_sgl_sz = (max_send_wqe_bytes / 16) - 4;
2502         hca_attr->hca_conn_send_sgl_sz = (max_send_wqe_bytes / 16) - 1;
2503         hca_attr->hca_conn_rdma_sgl_overhead = 1;
2504         hca_attr->hca_conn_rdma_write_sgl_sz = (max_send_wqe_bytes / 16) - 2;
2505         hca_attr->hca_conn_rdma_read_sgl_sz = (512 / 16) - 2; /* see PRM */
2506         hca_attr->hca_recv_sgl_sz = max_recv_wqe_bytes / 16;
2507 
2508         /* We choose not to support "inline" unless it improves performance */
2509         hca_attr->hca_max_inline_size = 0;
2510         hca_attr->hca_ud_send_inline_sz = 0;
2511         hca_attr->hca_conn_send_inline_sz = 0;
2512         hca_attr->hca_conn_rdmaw_inline_overhead = 4;
2513 
2514 #if defined(_ELF64)
2515         /* 32-bit kernels are too small for Fibre Channel over IB */
2516         if (state->hs_devlim.fcoib && (caps2 & IBT_HCA2_MEM_MGT_EXT)) {
2517                 caps2 |= IBT_HCA2_FC;
2518                 hca_attr->hca_rfci_max_log2_qp = 7;  /* 128 per port */
2519                 hca_attr->hca_fexch_max_log2_qp = 16;        /* 64K per port */
2520                 hca_attr->hca_fexch_max_log2_mem = 20;       /* 1MB per MPT */
2521         }
2522 #endif
2523 
2524         hca_attr->hca_flags = caps;
2525         hca_attr->hca_flags2 = caps2;
2526 
2527         /*
2528          * Set hca_attr's IDs
2529          */
2530         hca_attr->hca_vendor_id       = state->hs_vendor_id;
2531         hca_attr->hca_device_id       = state->hs_device_id;
2532         hca_attr->hca_version_id = state->hs_revision_id;
2533 
2534         /*
2535          * Determine number of available QPs and max QP size.  Number of
2536          * available QPs is determined by subtracting the number of
2537          * "reserved QPs" (i.e. reserved for firmware use) from the
2538          * total number configured.
2539          */
2540         val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_qp);
2541         hca_attr->hca_max_qp = val - ((uint64_t)1 <<
2542             state->hs_devlim.log_rsvd_qp);
2543         maxval  = ((uint64_t)1 << state->hs_devlim.log_max_qp_sz);
2544         val     = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_qp_sz);
2545         if (val > maxval) {
2546                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2547                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2548                     "soft_state_init_maxqpsz_toobig_fail");
2549                 return (DDI_FAILURE);
2550         }
2551         /* we need to reduce this by the max space needed for headroom */
2552         hca_attr->hca_max_qp_sz = (uint_t)val - (HERMON_QP_OH_SIZE >>
2553             HERMON_QP_WQE_LOG_MINIMUM) - 1;
2554 
2555         /*
2556          * Determine max scatter-gather size in WQEs. The HCA has split
2557          * the max sgl into rec'v Q and send Q values. Use the least.
2558          *
2559          * This is mainly useful for legacy clients.  Smart clients
2560          * such as IPoIB will use the IBT_HCA_WQE_SIZE_INFO sgl info.
2561          */
2562         if (state->hs_devlim.max_sg_rq <= state->hs_devlim.max_sg_sq) {
2563                 maxval = state->hs_devlim.max_sg_rq;
2564         } else {
2565                 maxval = state->hs_devlim.max_sg_sq;
2566         }
2567         val     = state->hs_cfg_profile->cp_wqe_max_sgl;
2568         if (val > maxval) {
2569                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2570                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2571                     "soft_state_init_toomanysgl_fail");
2572                 return (DDI_FAILURE);
2573         }
2574         /* If the rounded value for max SGL is too large, cap it */
2575         if (state->hs_cfg_profile->cp_wqe_real_max_sgl > maxval) {
2576                 state->hs_cfg_profile->cp_wqe_real_max_sgl = (uint32_t)maxval;
2577                 val = maxval;
2578         } else {
2579                 val = state->hs_cfg_profile->cp_wqe_real_max_sgl;
2580         }
2581 
2582         hca_attr->hca_max_sgl         = (uint_t)val;
2583         hca_attr->hca_max_rd_sgl = 0;        /* zero because RD is unsupported */
2584 
2585         /*
2586          * Determine number of available CQs and max CQ size. Number of
2587          * available CQs is determined by subtracting the number of
2588          * "reserved CQs" (i.e. reserved for firmware use) from the
2589          * total number configured.
2590          */
2591         val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_cq);
2592         hca_attr->hca_max_cq = val - ((uint64_t)1 <<
2593             state->hs_devlim.log_rsvd_cq);
2594         maxval  = ((uint64_t)1 << state->hs_devlim.log_max_cq_sz);
2595         val     = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_cq_sz) - 1;
2596         if (val > maxval) {
2597                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2598                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2599                     "soft_state_init_maxcqsz_toobig_fail");
2600                 return (DDI_FAILURE);
2601         }
2602         hca_attr->hca_max_cq_sz = (uint_t)val;
2603 
2604         /*
2605          * Determine number of available SRQs and max SRQ size. Number of
2606          * available SRQs is determined by subtracting the number of
2607          * "reserved SRQs" (i.e. reserved for firmware use) from the
2608          * total number configured.
2609          */
2610         val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_srq);
2611         hca_attr->hca_max_srqs = val - ((uint64_t)1 <<
2612             state->hs_devlim.log_rsvd_srq);
2613         maxval  = ((uint64_t)1 << state->hs_devlim.log_max_srq_sz);
2614         val     = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_srq_sz);
2615 
2616         if (val > maxval) {
2617                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2618                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2619                     "soft_state_init_maxsrqsz_toobig_fail");
2620                 return (DDI_FAILURE);
2621         }
2622         hca_attr->hca_max_srqs_sz = (uint_t)val;
2623 
2624         val     = hca_attr->hca_recv_sgl_sz - 1; /* SRQ has a list link */
2625         maxval  = state->hs_devlim.max_sg_rq - 1;
2626         if (val > maxval) {
2627                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2628                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2629                     "soft_state_init_toomanysrqsgl_fail");
2630                 return (DDI_FAILURE);
2631         }
2632         hca_attr->hca_max_srq_sgl = (uint_t)val;
2633 
2634         /*
2635          * Determine supported HCA page sizes
2636          * XXX
2637          * For now we simply return the system pagesize as the only supported
2638          * pagesize
2639          */
2640         hca_attr->hca_page_sz = ((PAGESIZE == (1 << 13)) ? IBT_PAGE_8K :
2641             IBT_PAGE_4K);
2642 
2643         /*
2644          * Determine number of available MemReg, MemWin, and their max size.
2645          * Number of available MRs and MWs is determined by subtracting
2646          * the number of "reserved MPTs" (i.e. reserved for firmware use)
2647          * from the total number configured for each.
2648          */
2649         val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_dmpt);
2650         hca_attr->hca_max_memr         = val - ((uint64_t)1 <<
2651             state->hs_devlim.log_rsvd_dmpt);
2652         hca_attr->hca_max_mem_win = state->hs_devlim.mem_win ? (val -
2653             ((uint64_t)1 << state->hs_devlim.log_rsvd_dmpt)) : 0;
2654         maxval  = state->hs_devlim.log_max_mrw_sz;
2655         val     = state->hs_cfg_profile->cp_log_max_mrw_sz;
2656         if (val > maxval) {
2657                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2658                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2659                     "soft_state_init_maxmrwsz_toobig_fail");
2660                 return (DDI_FAILURE);
2661         }
2662         hca_attr->hca_max_memr_len = ((uint64_t)1 << val);
2663 
2664         /* Determine RDMA/Atomic properties */
2665         val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_rdb);
2666         hca_attr->hca_max_rsc = (uint_t)val;
2667         val = state->hs_cfg_profile->cp_hca_max_rdma_in_qp;
2668         hca_attr->hca_max_rdma_in_qp  = (uint8_t)val;
2669         val = state->hs_cfg_profile->cp_hca_max_rdma_out_qp;
2670         hca_attr->hca_max_rdma_out_qp = (uint8_t)val;
2671         hca_attr->hca_max_rdma_in_ee  = 0;
2672         hca_attr->hca_max_rdma_out_ee = 0;
2673 
2674         /*
2675          * Determine maximum number of raw IPv6 and Ether QPs.  Set to 0
2676          * because neither type of raw QP is supported
2677          */
2678         hca_attr->hca_max_ipv6_qp  = 0;
2679         hca_attr->hca_max_ether_qp = 0;
2680 
2681         /* Determine max number of MCGs and max QP-per-MCG */
2682         val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_qp);
2683         hca_attr->hca_max_mcg_qps   = (uint_t)val;
2684         val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_mcg);
2685         hca_attr->hca_max_mcg            = (uint_t)val;
2686         val = state->hs_cfg_profile->cp_num_qp_per_mcg;
2687         hca_attr->hca_max_qp_per_mcg = (uint_t)val;
2688 
2689         /* Determine max number partitions (i.e. PKeys) */
2690         maxval  = ((uint64_t)state->hs_cfg_profile->cp_num_ports <<
2691             state->hs_queryport.log_max_pkey);
2692         val     = ((uint64_t)state->hs_cfg_profile->cp_num_ports <<
2693             state->hs_cfg_profile->cp_log_max_pkeytbl);
2694 
2695         if (val > maxval) {
2696                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2697                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2698                     "soft_state_init_toomanypkey_fail");
2699                 return (DDI_FAILURE);
2700         }
2701         hca_attr->hca_max_partitions = (uint16_t)val;
2702 
2703         /* Determine number of ports */
2704         maxval = state->hs_devlim.num_ports;
2705         val = state->hs_cfg_profile->cp_num_ports;
2706         if ((val > maxval) || (val == 0)) {
2707                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2708                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2709                     "soft_state_init_toomanyports_fail");
2710                 return (DDI_FAILURE);
2711         }
2712         hca_attr->hca_nports = (uint8_t)val;
2713 
2714         /* Copy NodeGUID and SystemImageGUID from softstate */
2715         hca_attr->hca_node_guid = state->hs_nodeguid;
2716         hca_attr->hca_si_guid        = state->hs_sysimgguid;
2717 
2718         /*
2719          * Determine local ACK delay.  Use the value suggested by the Hermon
2720          * hardware (from the QUERY_DEV_CAP command)
2721          */
2722         hca_attr->hca_local_ack_delay = state->hs_devlim.ca_ack_delay;
2723 
2724         /* Determine max SGID table and PKey table sizes */
2725         val     = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_gidtbl);
2726         hca_attr->hca_max_port_sgid_tbl_sz = (uint_t)val;
2727         val     = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
2728         hca_attr->hca_max_port_pkey_tbl_sz = (uint16_t)val;
2729 
2730         /* Determine max number of PDs */
2731         maxval  = ((uint64_t)1 << state->hs_devlim.log_max_pd);
2732         val     = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_pd);
2733         if (val > maxval) {
2734                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2735                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2736                     "soft_state_init_toomanypd_fail");
2737                 return (DDI_FAILURE);
2738         }
2739         hca_attr->hca_max_pd = (uint_t)val;
2740 
2741         /* Determine max number of Address Handles (NOT IN ARBEL or HERMON) */
2742         hca_attr->hca_max_ah = 0;
2743 
2744         /* No RDDs or EECs (since Reliable Datagram is not supported) */
2745         hca_attr->hca_max_rdd = 0;
2746         hca_attr->hca_max_eec = 0;
2747 
2748         /* Initialize lock for reserved UAR page access */
2749         mutex_init(&state->hs_uar_lock, NULL, MUTEX_DRIVER,
2750             DDI_INTR_PRI(state->hs_intrmsi_pri));
2751 
2752         /* Initialize the flash fields */
2753         state->hs_fw_flashstarted = 0;
2754         mutex_init(&state->hs_fw_flashlock, NULL, MUTEX_DRIVER,
2755             DDI_INTR_PRI(state->hs_intrmsi_pri));
2756 
2757         /* Initialize the lock for the info ioctl */
2758         mutex_init(&state->hs_info_lock, NULL, MUTEX_DRIVER,
2759             DDI_INTR_PRI(state->hs_intrmsi_pri));
2760 
2761         /* Initialize the AVL tree for QP number support */
2762         hermon_qpn_avl_init(state);
2763 
2764         /* Initialize the cq_sched info structure */
2765         status = hermon_cq_sched_init(state);
2766         if (status != DDI_SUCCESS) {
2767                 hermon_qpn_avl_fini(state);
2768                 mutex_destroy(&state->hs_info_lock);
2769                 mutex_destroy(&state->hs_fw_flashlock);
2770                 mutex_destroy(&state->hs_uar_lock);
2771                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2772                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2773                     "soft_state_init_cqsched_init_fail");
2774                 return (DDI_FAILURE);
2775         }
2776 
2777         /* Initialize the fcoib info structure */
2778         status = hermon_fcoib_init(state);
2779         if (status != DDI_SUCCESS) {
2780                 hermon_cq_sched_fini(state);
2781                 hermon_qpn_avl_fini(state);
2782                 mutex_destroy(&state->hs_info_lock);
2783                 mutex_destroy(&state->hs_fw_flashlock);
2784                 mutex_destroy(&state->hs_uar_lock);
2785                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2786                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2787                     "soft_state_init_fcoibinit_fail");
2788                 return (DDI_FAILURE);
2789         }
2790 
2791         /* Initialize the kstat info structure */
2792         status = hermon_kstat_init(state);
2793         if (status != DDI_SUCCESS) {
2794                 hermon_fcoib_fini(state);
2795                 hermon_cq_sched_fini(state);
2796                 hermon_qpn_avl_fini(state);
2797                 mutex_destroy(&state->hs_info_lock);
2798                 mutex_destroy(&state->hs_fw_flashlock);
2799                 mutex_destroy(&state->hs_uar_lock);
2800                 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
2801                 HERMON_ATTACH_MSG(state->hs_attach_buf,
2802                     "soft_state_init_kstatinit_fail");
2803                 return (DDI_FAILURE);
2804         }
2805 
2806         return (DDI_SUCCESS);
2807 }
2808 
2809 
2810 /*
2811  * hermon_soft_state_fini()
2812  *    Context: Called only from detach() path context
2813  */
2814 static void
2815 hermon_soft_state_fini(hermon_state_t *state)
2816 {
2817 
2818         /* Teardown the kstat info */
2819         hermon_kstat_fini(state);
2820 
2821         /* Teardown the fcoib info */
2822         hermon_fcoib_fini(state);
2823 
2824         /* Teardown the cq_sched info */
2825         hermon_cq_sched_fini(state);
2826 
2827         /* Teardown the AVL tree for QP number support */
2828         hermon_qpn_avl_fini(state);
2829 
2830         /* Free up info ioctl mutex */
2831         mutex_destroy(&state->hs_info_lock);
2832 
2833         /* Free up flash mutex */
2834         mutex_destroy(&state->hs_fw_flashlock);
2835 
2836         /* Free up the UAR page access mutex */
2837         mutex_destroy(&state->hs_uar_lock);
2838 
2839         /* Free up the hca_attr struct */
2840         kmem_free(state->hs_ibtfinfo.hca_attr, sizeof (ibt_hca_attr_t));
2841 
2842 }
2843 
2844 /*
2845  * hermon_icm_config_setup()
2846  *    Context: Only called from attach() path context
2847  */
2848 static int
2849 hermon_icm_config_setup(hermon_state_t *state,
2850     hermon_hw_initqueryhca_t *inithca)
2851 {
2852         hermon_hw_querydevlim_t *devlim;
2853         hermon_cfg_profile_t    *cfg;
2854         hermon_icm_table_t      *icm_p[HERMON_NUM_ICM_RESOURCES];
2855         hermon_icm_table_t      *icm;
2856         hermon_icm_table_t      *tmp;
2857         uint64_t                icm_addr;
2858         uint64_t                icm_size;
2859         int                     status, i, j;
2860 
2861 
2862         /* Bring in local devlims, cfg_profile and hs_icm table list */
2863         devlim = &state->hs_devlim;
2864         cfg = state->hs_cfg_profile;
2865         icm = state->hs_icm;
2866 
2867         /*
2868          * Assign each ICM table's entry size from data in the devlims,
2869          * except for RDB and MCG sizes, which are not returned in devlims
2870          * but do have a fixed size, and the UAR context entry size, which
2871          * we determine. For this, we use the "cp_num_pgs_per_uce" value
2872          * from our hs_cfg_profile.
2873          */
2874         icm[HERMON_CMPT].object_size    = devlim->cmpt_entry_sz;
2875         icm[HERMON_CMPT_QPC].object_size        = devlim->cmpt_entry_sz;
2876         icm[HERMON_CMPT_SRQC].object_size       = devlim->cmpt_entry_sz;
2877         icm[HERMON_CMPT_CQC].object_size        = devlim->cmpt_entry_sz;
2878         icm[HERMON_CMPT_EQC].object_size        = devlim->cmpt_entry_sz;
2879         icm[HERMON_MTT].object_size     = devlim->mtt_entry_sz;
2880         icm[HERMON_DMPT].object_size    = devlim->dmpt_entry_sz;
2881         icm[HERMON_QPC].object_size     = devlim->qpc_entry_sz;
2882         icm[HERMON_CQC].object_size     = devlim->cqc_entry_sz;
2883         icm[HERMON_SRQC].object_size    = devlim->srq_entry_sz;
2884         icm[HERMON_EQC].object_size     = devlim->eqc_entry_sz;
2885         icm[HERMON_RDB].object_size     = devlim->rdmardc_entry_sz *
2886             cfg->cp_hca_max_rdma_in_qp;
2887         icm[HERMON_MCG].object_size     = HERMON_MCGMEM_SZ(state);
2888         icm[HERMON_ALTC].object_size    = devlim->altc_entry_sz;
2889         icm[HERMON_AUXC].object_size    = devlim->aux_entry_sz;
2890 
2891         /* Assign each ICM table's log2 number of entries */
2892         icm[HERMON_CMPT].log_num_entries = cfg->cp_log_num_cmpt;
2893         icm[HERMON_CMPT_QPC].log_num_entries = cfg->cp_log_num_qp;
2894         icm[HERMON_CMPT_SRQC].log_num_entries = cfg->cp_log_num_srq;
2895         icm[HERMON_CMPT_CQC].log_num_entries = cfg->cp_log_num_cq;
2896         icm[HERMON_CMPT_EQC].log_num_entries = HERMON_NUM_EQ_SHIFT;
2897         icm[HERMON_MTT].log_num_entries = cfg->cp_log_num_mtt;
2898         icm[HERMON_DMPT].log_num_entries = cfg->cp_log_num_dmpt;
2899         icm[HERMON_QPC].log_num_entries = cfg->cp_log_num_qp;
2900         icm[HERMON_SRQC].log_num_entries = cfg->cp_log_num_srq;
2901         icm[HERMON_CQC].log_num_entries = cfg->cp_log_num_cq;
2902         icm[HERMON_EQC].log_num_entries = HERMON_NUM_EQ_SHIFT;
2903         icm[HERMON_RDB].log_num_entries = cfg->cp_log_num_qp;
2904         icm[HERMON_MCG].log_num_entries = cfg->cp_log_num_mcg;
2905         icm[HERMON_ALTC].log_num_entries = cfg->cp_log_num_qp;
2906         icm[HERMON_AUXC].log_num_entries = cfg->cp_log_num_qp;
2907 
2908         /* Initialize the ICM tables */
2909         hermon_icm_tables_init(state);
2910 
2911         /*
2912          * ICM tables must be aligned on their size in the ICM address
2913          * space. So, here we order the tables from largest total table
2914          * size to the smallest. All tables are a power of 2 in size, so
2915          * this will ensure that all tables are aligned on their own size
2916          * without wasting space in the ICM.
2917          *
2918          * In order to easily set the ICM addresses without needing to
2919          * worry about the ordering of our table indices as relates to
2920          * the hermon_rsrc_type_t enum, we will use a list of pointers
2921          * representing the tables for the sort, then assign ICM addresses
2922          * below using it.
2923          */
2924         for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
2925                 icm_p[i] = &icm[i];
2926         }
2927         for (i = HERMON_NUM_ICM_RESOURCES; i > 0; i--) {
2928                 switch (i) {
2929                 case HERMON_CMPT_QPC:
2930                 case HERMON_CMPT_SRQC:
2931                 case HERMON_CMPT_CQC:
2932                 case HERMON_CMPT_EQC:
2933                         continue;
2934                 }
2935                 for (j = 1; j < i; j++) {
2936                         if (icm_p[j]->table_size > icm_p[j - 1]->table_size) {
2937                                 tmp             = icm_p[j];
2938                                 icm_p[j]        = icm_p[j - 1];
2939                                 icm_p[j - 1]    = tmp;
2940                         }
2941                 }
2942         }
2943 
2944         /* Initialize the ICM address and ICM size */
2945         icm_addr = icm_size = 0;
2946 
2947         /*
2948          * Set the ICM base address of each table, using our sorted
2949          * list of pointers from above.
2950          */
2951         for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
2952                 j = icm_p[i]->icm_type;
2953                 switch (j) {
2954                 case HERMON_CMPT_QPC:
2955                 case HERMON_CMPT_SRQC:
2956                 case HERMON_CMPT_CQC:
2957                 case HERMON_CMPT_EQC:
2958                         continue;
2959                 }
2960                 if (icm[j].table_size) {
2961                         /*
2962                          * Set the ICM base address in the table, save the
2963                          * ICM offset in the rsrc pool and increment the
2964                          * total ICM allocation.
2965                          */
2966                         icm[j].icm_baseaddr = icm_addr;
2967                         if (hermon_verbose) {
2968                                 IBTF_DPRINTF_L2("ICMADDR", "rsrc %x @ %p"
2969                                     " size %llx", j, icm[j].icm_baseaddr,
2970                                     icm[j].table_size);
2971                         }
2972                         icm_size += icm[j].table_size;
2973                 }
2974 
2975                 /* Verify that we don't exceed maximum ICM size */
2976                 if (icm_size > devlim->max_icm_size) {
2977                         /* free the ICM table memory resources */
2978                         hermon_icm_tables_fini(state);
2979                         cmn_err(CE_WARN, "ICM configuration exceeds maximum "
2980                             "configuration: max (0x%lx) requested (0x%lx)\n",
2981                             (ulong_t)devlim->max_icm_size, (ulong_t)icm_size);
2982                         HERMON_ATTACH_MSG(state->hs_attach_buf,
2983                             "icm_config_toobig_fail");
2984                         return (DDI_FAILURE);
2985                 }
2986 
2987                 /* assign address to the 4 pieces of the CMPT */
2988                 if (j == HERMON_CMPT) {
2989                         uint64_t cmpt_size = icm[j].table_size >> 2;
2990 #define init_cmpt_icm_baseaddr(rsrc, indx)                              \
2991         icm[rsrc].icm_baseaddr  = icm_addr + (indx * cmpt_size);
2992                         init_cmpt_icm_baseaddr(HERMON_CMPT_QPC, 0);
2993                         init_cmpt_icm_baseaddr(HERMON_CMPT_SRQC, 1);
2994                         init_cmpt_icm_baseaddr(HERMON_CMPT_CQC, 2);
2995                         init_cmpt_icm_baseaddr(HERMON_CMPT_EQC, 3);
2996                 }
2997 
2998                 /* Increment the ICM address for the next table */
2999                 icm_addr += icm[j].table_size;
3000         }
3001 
3002         /* Populate the structure for the INIT_HCA command */
3003         hermon_inithca_set(state, inithca);
3004 
3005         /*
3006          * Prior to invoking INIT_HCA, we must have ICM memory in place
3007          * for the reserved objects in each table. We will allocate and map
3008          * this initial ICM memory here. Note that given the assignment
3009          * of span_size above, tables that are smaller or equal in total
3010          * size to the default span_size will be mapped in full.
3011          */
3012         status = hermon_icm_dma_init(state);
3013         if (status != DDI_SUCCESS) {
3014                 /* free the ICM table memory resources */
3015                 hermon_icm_tables_fini(state);
3016                 HERMON_WARNING(state, "Failed to allocate initial ICM");
3017                 HERMON_ATTACH_MSG(state->hs_attach_buf,
3018                     "icm_config_dma_init_fail");
3019                 return (DDI_FAILURE);
3020         }
3021 
3022         return (DDI_SUCCESS);
3023 }
3024 
3025 /*
3026  * hermon_inithca_set()
3027  *    Context: Only called from attach() path context
3028  */
3029 static void
3030 hermon_inithca_set(hermon_state_t *state, hermon_hw_initqueryhca_t *inithca)
3031 {
3032         hermon_cfg_profile_t    *cfg;
3033         hermon_icm_table_t      *icm;
3034         int                     i;
3035 
3036 
3037         /* Populate the INIT_HCA structure */
3038         icm = state->hs_icm;
3039         cfg = state->hs_cfg_profile;
3040 
3041         /* set version */
3042         inithca->version = 0x02;     /* PRM 0.36 */
3043         /* set cacheline - log2 in 16-byte chunks */
3044         inithca->log2_cacheline = 0x2;       /* optimized for 64 byte cache */
3045 
3046         /* we need to update the inithca info with thie UAR info too */
3047         inithca->uar.log_max_uars = highbit(cfg->cp_log_num_uar);
3048         inithca->uar.uar_pg_sz = PAGESHIFT - HERMON_PAGESHIFT;
3049 
3050         /* Set endianess */
3051 #ifdef  _LITTLE_ENDIAN
3052         inithca->big_endian  = 0;
3053 #else
3054         inithca->big_endian  = 1;
3055 #endif
3056 
3057         /* Port Checking is on by default */
3058         inithca->udav_port_chk       = HERMON_UDAV_PORTCHK_ENABLED;
3059 
3060         /* Enable IPoIB checksum */
3061         if (state->hs_devlim.ipoib_cksm)
3062                 inithca->chsum_en = 1;
3063 
3064         /* Set each ICM table's attributes */
3065         for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
3066                 switch (icm[i].icm_type) {
3067                 case HERMON_CMPT:
3068                         inithca->tpt.cmpt_baseaddr = icm[i].icm_baseaddr;
3069                         break;
3070 
3071                 case HERMON_MTT:
3072                         inithca->tpt.mtt_baseaddr = icm[i].icm_baseaddr;
3073                         break;
3074 
3075                 case HERMON_DMPT:
3076                         inithca->tpt.dmpt_baseaddr = icm[i].icm_baseaddr;
3077                         inithca->tpt.log_dmpt_sz   = icm[i].log_num_entries;
3078                         inithca->tpt.pgfault_rnr_to = 0; /* just in case */
3079                         break;
3080 
3081                 case HERMON_QPC:
3082                         inithca->context.log_num_qp = icm[i].log_num_entries;
3083                         inithca->context.qpc_baseaddr_h =
3084                             icm[i].icm_baseaddr >> 32;
3085                         inithca->context.qpc_baseaddr_l =
3086                             (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
3087                         break;
3088 
3089                 case HERMON_CQC:
3090                         inithca->context.log_num_cq = icm[i].log_num_entries;
3091                         inithca->context.cqc_baseaddr_h =
3092                             icm[i].icm_baseaddr >> 32;
3093                         inithca->context.cqc_baseaddr_l =
3094                             (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
3095                         break;
3096 
3097                 case HERMON_SRQC:
3098                         inithca->context.log_num_srq = icm[i].log_num_entries;
3099                         inithca->context.srqc_baseaddr_h =
3100                             icm[i].icm_baseaddr >> 32;
3101                         inithca->context.srqc_baseaddr_l =
3102                             (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
3103                         break;
3104 
3105                 case HERMON_EQC:
3106                         inithca->context.log_num_eq = icm[i].log_num_entries;
3107                         inithca->context.eqc_baseaddr_h =
3108                             icm[i].icm_baseaddr >> 32;
3109                         inithca->context.eqc_baseaddr_l =
3110                             (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
3111                         break;
3112 
3113                 case HERMON_RDB:
3114                         inithca->context.rdmardc_baseaddr_h =
3115                             icm[i].icm_baseaddr >> 32;
3116                         inithca->context.rdmardc_baseaddr_l =
3117                             (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
3118                         inithca->context.log_num_rdmardc =
3119                             cfg->cp_log_num_rdb - cfg->cp_log_num_qp;
3120                         break;
3121 
3122                 case HERMON_MCG:
3123                         inithca->multi.mc_baseaddr    = icm[i].icm_baseaddr;
3124                         inithca->multi.log_mc_tbl_sz  = icm[i].log_num_entries;
3125                         inithca->multi.log_mc_tbl_ent =
3126                             highbit(HERMON_MCGMEM_SZ(state)) - 1;
3127                         inithca->multi.log_mc_tbl_hash_sz =
3128                             cfg->cp_log_num_mcg_hash;
3129                         inithca->multi.mc_hash_fn = HERMON_MCG_DEFAULT_HASH_FN;
3130                         break;
3131 
3132                 case HERMON_ALTC:
3133                         inithca->context.altc_baseaddr = icm[i].icm_baseaddr;
3134                         break;
3135 
3136                 case HERMON_AUXC:
3137                         inithca->context.auxc_baseaddr = icm[i].icm_baseaddr;
3138                         break;
3139 
3140                 default:
3141                         break;
3142 
3143                 }
3144         }
3145 
3146 }
3147 
3148 /*
3149  * hermon_icm_tables_init()
3150  *    Context: Only called from attach() path context
3151  *
3152  * Dynamic ICM breaks the various ICM tables into "span_size" chunks
3153  * to enable allocation of backing memory on demand.  Arbel used a
3154  * fixed size ARBEL_ICM_SPAN_SIZE (initially was 512KB) as the
3155  * span_size for all ICM chunks.  Hermon has other considerations,
3156  * so the span_size used differs from Arbel.
3157  *
3158  * The basic considerations for why Hermon differs are:
3159  *
3160  *      1) ICM memory is in units of HERMON pages.
3161  *
3162  *      2) The AUXC table is approximately 1 byte per QP.
3163  *
3164  *      3) ICM memory for AUXC, ALTC, and RDB is allocated when
3165  *      the ICM memory for the corresponding QPC is allocated.
3166  *
3167  *      4) ICM memory for the CMPT corresponding to the various primary
3168  *      resources (QPC, SRQC, CQC, and EQC) is allocated when the ICM
3169  *      memory for the primary resource is allocated.
3170  *
3171  * One HERMON page (4KB) would typically map 4K QPs worth of AUXC.
3172  * So, the minimum chunk for the various QPC related ICM memory should
3173  * all be allocated to support the 4K QPs.  Currently, this means the
3174  * amount of memory for the various QP chunks is:
3175  *
3176  *      QPC     256*4K bytes
3177  *      RDB     128*4K bytes
3178  *      CMPT     64*4K bytes
3179  *      ALTC     64*4K bytes
3180  *      AUXC      1*4K bytes
3181  *
3182  * The span_size chosen for the QP resource is 4KB of AUXC entries,
3183  * or 1 HERMON_PAGESIZE worth, which is the minimum ICM mapping size.
3184  *
3185  * Other ICM resources can have their span_size be more arbitrary.
3186  * This is 4K (HERMON_ICM_SPAN), except for MTTs because they are tiny.
3187  */
3188 
3189 /* macro to make the code below cleaner */
3190 #define init_dependent(rsrc, dep)                               \
3191         icm[dep].span           = icm[rsrc].span;               \
3192         icm[dep].num_spans      = icm[rsrc].num_spans;          \
3193         icm[dep].split_shift    = icm[rsrc].split_shift;        \
3194         icm[dep].span_mask      = icm[rsrc].span_mask;          \
3195         icm[dep].span_shift     = icm[rsrc].span_shift;         \
3196         icm[dep].rsrc_mask      = icm[rsrc].rsrc_mask;          \
3197         if (hermon_verbose) {                                   \
3198                 IBTF_DPRINTF_L2("hermon", "tables_init: "       \
3199                     "rsrc (0x%x) size (0x%lx) span (0x%x) "     \
3200                     "num_spans (0x%x)", dep, icm[dep].table_size, \
3201                     icm[dep].span, icm[dep].num_spans);         \
3202                 IBTF_DPRINTF_L2("hermon", "tables_init: "       \
3203                     "span_shift (0x%x) split_shift (0x%x)",     \
3204                     icm[dep].span_shift, icm[dep].split_shift); \
3205                 IBTF_DPRINTF_L2("hermon", "tables_init: "       \
3206                     "span_mask (0x%x)  rsrc_mask   (0x%x)",     \
3207                     icm[dep].span_mask, icm[dep].rsrc_mask);    \
3208         }
3209 
3210 static void
3211 hermon_icm_tables_init(hermon_state_t *state)
3212 {
3213         hermon_icm_table_t      *icm;
3214         int                     i, k;
3215         uint32_t                per_split;
3216 
3217 
3218         icm = state->hs_icm;
3219 
3220         for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
3221                 icm[i].icm_type         = i;
3222                 icm[i].num_entries      = 1 << icm[i].log_num_entries;
3223                 icm[i].log_object_size  = highbit(icm[i].object_size) - 1;
3224                 icm[i].table_size       = icm[i].num_entries <<
3225                     icm[i].log_object_size;
3226 
3227                 /* deal with "dependent" resource types */
3228                 switch (i) {
3229                 case HERMON_AUXC:
3230 #ifdef HERMON_FW_WORKAROUND
3231                         icm[i].table_size = 0x80000000ull;
3232                         /* FALLTHROUGH */
3233 #endif
3234                 case HERMON_CMPT_QPC:
3235                 case HERMON_RDB:
3236                 case HERMON_ALTC:
3237                         init_dependent(HERMON_QPC, i);
3238                         continue;
3239                 case HERMON_CMPT_SRQC:
3240                         init_dependent(HERMON_SRQC, i);
3241                         continue;
3242                 case HERMON_CMPT_CQC:
3243                         init_dependent(HERMON_CQC, i);
3244                         continue;
3245                 case HERMON_CMPT_EQC:
3246                         init_dependent(HERMON_EQC, i);
3247                         continue;
3248                 }
3249 
3250                 icm[i].span = HERMON_ICM_SPAN;  /* default #rsrc's in 1 span */
3251                 if (i == HERMON_MTT) /* Alloc enough MTTs to map 256MB */
3252                         icm[i].span = HERMON_ICM_SPAN * 16;
3253                 icm[i].num_spans = icm[i].num_entries / icm[i].span;
3254                 if (icm[i].num_spans == 0) {
3255                         icm[i].span = icm[i].num_entries;
3256                         per_split = 1;
3257                         icm[i].num_spans = icm[i].num_entries / icm[i].span;
3258                 } else {
3259                         per_split = icm[i].num_spans / HERMON_ICM_SPLIT;
3260                         if (per_split == 0) {
3261                                 per_split = 1;
3262                         }
3263                 }
3264                 if (hermon_verbose)
3265                         IBTF_DPRINTF_L2("ICM", "rsrc %x  span %x  num_spans %x",
3266                             i, icm[i].span, icm[i].num_spans);
3267 
3268                 /*
3269                  * Ensure a minimum table size of an ICM page, and a
3270                  * maximum span size of the ICM table size.  This ensures
3271                  * that we don't have less than an ICM page to map, which is
3272                  * impossible, and that we will map an entire table at
3273                  * once if it's total size is less than the span size.
3274                  */
3275                 icm[i].table_size = max(icm[i].table_size, HERMON_PAGESIZE);
3276 
3277                 icm[i].span_shift = 0;
3278                 for (k = icm[i].span; k != 1; k >>= 1)
3279                         icm[i].span_shift++;
3280                 icm[i].split_shift = icm[i].span_shift;
3281                 for (k = per_split; k != 1; k >>= 1)
3282                         icm[i].split_shift++;
3283                 icm[i].span_mask = (1 << icm[i].split_shift) -
3284                     (1 << icm[i].span_shift);
3285                 icm[i].rsrc_mask = (1 << icm[i].span_shift) - 1;
3286 
3287 
3288                 /* Initialize the table lock */
3289                 mutex_init(&icm[i].icm_table_lock, NULL, MUTEX_DRIVER,
3290                     DDI_INTR_PRI(state->hs_intrmsi_pri));
3291                 cv_init(&icm[i].icm_table_cv, NULL, CV_DRIVER, NULL);
3292 
3293                 if (hermon_verbose) {
3294                         IBTF_DPRINTF_L2("hermon", "tables_init: "
3295                             "rsrc (0x%x) size (0x%lx)", i, icm[i].table_size);
3296                         IBTF_DPRINTF_L2("hermon", "tables_init: "
3297                             "span (0x%x) num_spans (0x%x)",
3298                             icm[i].span, icm[i].num_spans);
3299                         IBTF_DPRINTF_L2("hermon", "tables_init: "
3300                             "span_shift (0x%x) split_shift (0x%x)",
3301                             icm[i].span_shift, icm[i].split_shift);
3302                         IBTF_DPRINTF_L2("hermon", "tables_init: "
3303                             "span_mask (0x%x)  rsrc_mask   (0x%x)",
3304                             icm[i].span_mask, icm[i].rsrc_mask);
3305                 }
3306         }
3307 
3308 }
3309 
3310 /*
3311  * hermon_icm_tables_fini()
3312  *    Context: Only called from attach() path context
3313  *
3314  * Clean up all icm_tables.  Free the bitmap and dma_info arrays.
3315  */
3316 static void
3317 hermon_icm_tables_fini(hermon_state_t *state)
3318 {
3319         hermon_icm_table_t      *icm;
3320         int                     nspans;
3321         int                     i, j;
3322 
3323 
3324         icm = state->hs_icm;
3325 
3326         for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
3327 
3328                 mutex_enter(&icm[i].icm_table_lock);
3329                 nspans = icm[i].num_spans;
3330 
3331                 for (j = 0; j < HERMON_ICM_SPLIT; j++) {
3332                         if (icm[i].icm_dma[j])
3333                                 /* Free the ICM DMA slots */
3334                                 kmem_free(icm[i].icm_dma[j],
3335                                     nspans * sizeof (hermon_dma_info_t));
3336 
3337                         if (icm[i].icm_bitmap[j])
3338                                 /* Free the table bitmap */
3339                                 kmem_free(icm[i].icm_bitmap[j],
3340                                     (nspans + 7) / 8);
3341                 }
3342                 /* Destroy the table lock */
3343                 cv_destroy(&icm[i].icm_table_cv);
3344                 mutex_exit(&icm[i].icm_table_lock);
3345                 mutex_destroy(&icm[i].icm_table_lock);
3346         }
3347 
3348 }
3349 
3350 /*
3351  * hermon_icm_dma_init()
3352  *    Context: Only called from attach() path context
3353  */
3354 static int
3355 hermon_icm_dma_init(hermon_state_t *state)
3356 {
3357         hermon_icm_table_t      *icm;
3358         hermon_rsrc_type_t      type;
3359         int                     status;
3360 
3361 
3362         /*
3363          * This routine will allocate initial ICM DMA resources for ICM
3364          * tables that have reserved ICM objects. This is the only routine
3365          * where we should have to allocate ICM outside of hermon_rsrc_alloc().
3366          * We need to allocate ICM here explicitly, rather than in
3367          * hermon_rsrc_alloc(), because we've not yet completed the resource
3368          * pool initialization. When the resource pools are initialized
3369          * (in hermon_rsrc_init_phase2(), see hermon_rsrc.c for more
3370          * information), resource preallocations will be invoked to match
3371          * the ICM allocations seen here. We will then be able to use the
3372          * normal allocation path.  Note we don't need to set a refcnt on
3373          * these initial allocations because that will be done in the calls
3374          * to hermon_rsrc_alloc() from hermon_hw_entries_init() for the
3375          * "prealloc" objects (see hermon_rsrc.c for more information).
3376          */
3377         for (type = 0; type < HERMON_NUM_ICM_RESOURCES; type++) {
3378 
3379                 /* ICM for these is allocated within hermon_icm_alloc() */
3380                 switch (type) {
3381                 case HERMON_CMPT:
3382                 case HERMON_CMPT_QPC:
3383                 case HERMON_CMPT_SRQC:
3384                 case HERMON_CMPT_CQC:
3385                 case HERMON_CMPT_EQC:
3386                 case HERMON_AUXC:
3387                 case HERMON_ALTC:
3388                 case HERMON_RDB:
3389                         continue;
3390                 }
3391 
3392                 icm = &state->hs_icm[type];
3393 
3394                 mutex_enter(&icm->icm_table_lock);
3395                 status = hermon_icm_alloc(state, type, 0, 0);
3396                 mutex_exit(&icm->icm_table_lock);
3397                 if (status != DDI_SUCCESS) {
3398                         while (type--) {
3399                                 icm = &state->hs_icm[type];
3400                                 mutex_enter(&icm->icm_table_lock);
3401                                 hermon_icm_free(state, type, 0, 0);
3402                                 mutex_exit(&icm->icm_table_lock);
3403                         }
3404                         return (DDI_FAILURE);
3405                 }
3406 
3407                 if (hermon_verbose) {
3408                         IBTF_DPRINTF_L2("hermon", "hermon_icm_dma_init: "
3409                             "table (0x%x) index (0x%x) allocated", type, 0);
3410                 }
3411         }
3412 
3413         return (DDI_SUCCESS);
3414 }
3415 
3416 /*
3417  * hermon_icm_dma_fini()
3418  *    Context: Only called from attach() path context
3419  *
3420  * ICM has been completely unmapped.  We just free the memory here.
3421  */
3422 static void
3423 hermon_icm_dma_fini(hermon_state_t *state)
3424 {
3425         hermon_icm_table_t      *icm;
3426         hermon_dma_info_t       *dma_info;
3427         hermon_rsrc_type_t      type;
3428         int                     index1, index2;
3429 
3430 
3431         for (type = 0; type < HERMON_NUM_ICM_RESOURCES; type++) {
3432                 icm = &state->hs_icm[type];
3433                 for (index1 = 0; index1 < HERMON_ICM_SPLIT; index1++) {
3434                         dma_info = icm->icm_dma[index1];
3435                         if (dma_info == NULL)
3436                                 continue;
3437                         for (index2 = 0; index2 < icm->num_spans; index2++) {
3438                                 if (dma_info[index2].dma_hdl)
3439                                         hermon_dma_free(&dma_info[index2]);
3440                                 dma_info[index2].dma_hdl = NULL;
3441                         }
3442                 }
3443         }
3444 
3445 }
3446 
3447 /*
3448  * hermon_hca_port_init()
3449  *    Context: Only called from attach() path context
3450  */
3451 static int
3452 hermon_hca_port_init(hermon_state_t *state)
3453 {
3454         hermon_hw_set_port_t    *portinits, *initport;
3455         hermon_cfg_profile_t    *cfgprof;
3456         uint_t                  num_ports;
3457         int                     i = 0, status;
3458         uint64_t                maxval, val;
3459         uint64_t                sysimgguid, nodeguid, portguid;
3460 
3461 
3462         cfgprof = state->hs_cfg_profile;
3463 
3464         /* Get number of HCA ports */
3465         num_ports = cfgprof->cp_num_ports;
3466 
3467         /* Allocate space for Hermon set port  struct(s) */
3468         portinits = (hermon_hw_set_port_t *)kmem_zalloc(num_ports *
3469             sizeof (hermon_hw_set_port_t), KM_SLEEP);
3470 
3471 
3472 
3473         /* Post commands to initialize each Hermon HCA port */
3474         /*
3475          * In Hermon, the process is different than in previous HCAs.
3476          * Here, you have to:
3477          *      QUERY_PORT - to get basic information from the HCA
3478          *      set the fields accordingly
3479          *      SET_PORT - to change/set everything as desired
3480          *      INIT_PORT - to bring the port up
3481          *
3482          * Needs to be done for each port in turn
3483          */
3484 
3485         for (i = 0; i < num_ports; i++) {
3486                 bzero(&state->hs_queryport, sizeof (hermon_hw_query_port_t));
3487                 status = hermon_cmn_query_cmd_post(state, QUERY_PORT, 0,
3488                     (i + 1), &state->hs_queryport,
3489                     sizeof (hermon_hw_query_port_t), HERMON_CMD_NOSLEEP_SPIN);
3490                 if (status != HERMON_CMD_SUCCESS) {
3491                         cmn_err(CE_CONT, "Hermon: QUERY_PORT (port %02d) "
3492                             "command failed: %08x\n", i + 1, status);
3493                         goto init_ports_fail;
3494                 }
3495                 initport = &portinits[i];
3496                 state->hs_initport = &portinits[i];
3497 
3498                 bzero(initport, sizeof (hermon_hw_query_port_t));
3499 
3500                 /*
3501                  * Determine whether we need to override the firmware's
3502                  * default SystemImageGUID setting.
3503                  */
3504                 sysimgguid = cfgprof->cp_sysimgguid;
3505                 if (sysimgguid != 0) {
3506                         initport->sig                = 1;
3507                         initport->sys_img_guid       = sysimgguid;
3508                 }
3509 
3510                 /*
3511                  * Determine whether we need to override the firmware's
3512                  * default NodeGUID setting.
3513                  */
3514                 nodeguid = cfgprof->cp_nodeguid;
3515                 if (nodeguid != 0) {
3516                         initport->ng         = 1;
3517                         initport->node_guid  = nodeguid;
3518                 }
3519 
3520                 /*
3521                  * Determine whether we need to override the firmware's
3522                  * default PortGUID setting.
3523                  */
3524                 portguid = cfgprof->cp_portguid[i];
3525                 if (portguid != 0) {
3526                         initport->g0         = 1;
3527                         initport->guid0              = portguid;
3528                 }
3529 
3530                 /* Validate max MTU size */
3531                 maxval  = state->hs_queryport.ib_mtu;
3532                 val     = cfgprof->cp_max_mtu;
3533                 if (val > maxval) {
3534                         goto init_ports_fail;
3535                 }
3536 
3537                 /* Set mtu_cap to 4096 bytes */
3538                 initport->mmc = 1;   /* set the change bit */
3539                 initport->mtu_cap = 5;       /* for 4096 bytes */
3540 
3541                 /* Validate the max port width */
3542                 maxval  = state->hs_queryport.ib_port_wid;
3543                 val     = cfgprof->cp_max_port_width;
3544                 if (val > maxval) {
3545                         goto init_ports_fail;
3546                 }
3547 
3548                 /* Validate max VL cap size */
3549                 maxval  = state->hs_queryport.max_vl;
3550                 val     = cfgprof->cp_max_vlcap;
3551                 if (val > maxval) {
3552                         goto init_ports_fail;
3553                 }
3554 
3555                 /* Since we're doing mtu_cap, cut vl_cap down */
3556                 initport->mvc = 1;   /* set this change bit */
3557                 initport->vl_cap = 3;        /* 3 means vl0-vl3, 4 total */
3558 
3559                 /* Validate max GID table size */
3560                 maxval  = ((uint64_t)1 << state->hs_queryport.log_max_gid);
3561                 val     = ((uint64_t)1 << cfgprof->cp_log_max_gidtbl);
3562                 if (val > maxval) {
3563                         goto init_ports_fail;
3564                 }
3565                 initport->max_gid = (uint16_t)val;
3566                 initport->mg = 1;
3567 
3568                 /* Validate max PKey table size */
3569                 maxval  = ((uint64_t)1 << state->hs_queryport.log_max_pkey);
3570                 val     = ((uint64_t)1 << cfgprof->cp_log_max_pkeytbl);
3571                 if (val > maxval) {
3572                         goto init_ports_fail;
3573                 }
3574                 initport->max_pkey = (uint16_t)val;
3575                 initport->mp = 1;
3576                 /*
3577                  * Post the SET_PORT cmd to Hermon firmware. This sets
3578                  * the parameters of the port.
3579                  */
3580                 status = hermon_set_port_cmd_post(state, initport, i + 1,
3581                     HERMON_CMD_NOSLEEP_SPIN);
3582                 if (status != HERMON_CMD_SUCCESS) {
3583                         cmn_err(CE_CONT, "Hermon: SET_PORT (port %02d) command "
3584                             "failed: %08x\n", i + 1, status);
3585                         goto init_ports_fail;
3586                 }
3587                 /* issue another SET_PORT cmd - performance fix/workaround */
3588                 /* XXX - need to discuss with Mellanox */
3589                 bzero(initport, sizeof (hermon_hw_query_port_t));
3590                 initport->cap_mask = 0x02500868;
3591                 status = hermon_set_port_cmd_post(state, initport, i + 1,
3592                     HERMON_CMD_NOSLEEP_SPIN);
3593                 if (status != HERMON_CMD_SUCCESS) {
3594                         cmn_err(CE_CONT, "Hermon: SET_PORT (port %02d) command "
3595                             "failed: %08x\n", i + 1, status);
3596                         goto init_ports_fail;
3597                 }
3598         }
3599 
3600         /*
3601          * Finally, do the INIT_PORT for each port in turn
3602          * When this command completes, the corresponding Hermon port
3603          * will be physically "Up" and initialized.
3604          */
3605         for (i = 0; i < num_ports; i++) {
3606                 status = hermon_init_port_cmd_post(state, i + 1,
3607                     HERMON_CMD_NOSLEEP_SPIN);
3608                 if (status != HERMON_CMD_SUCCESS) {
3609                         cmn_err(CE_CONT, "Hermon: INIT_PORT (port %02d) "
3610                             "comman failed: %08x\n", i + 1, status);
3611                         goto init_ports_fail;
3612                 }
3613         }
3614 
3615         /* Free up the memory for Hermon port init struct(s), return success */
3616         kmem_free(portinits, num_ports * sizeof (hermon_hw_set_port_t));
3617         return (DDI_SUCCESS);
3618 
3619 init_ports_fail:
3620         /*
3621          * Free up the memory for Hermon port init struct(s), shutdown any
3622          * successfully initialized ports, and return failure
3623          */
3624         kmem_free(portinits, num_ports * sizeof (hermon_hw_set_port_t));
3625         (void) hermon_hca_ports_shutdown(state, i);
3626 
3627         return (DDI_FAILURE);
3628 }
3629 
3630 
3631 /*
3632  * hermon_hca_ports_shutdown()
3633  *    Context: Only called from attach() and/or detach() path contexts
3634  */
3635 static int
3636 hermon_hca_ports_shutdown(hermon_state_t *state, uint_t num_init)
3637 {
3638         int     i, status;
3639 
3640         /*
3641          * Post commands to shutdown all init'd Hermon HCA ports.  Note: if
3642          * any of these commands fail for any reason, it would be entirely
3643          * unexpected and probably indicative a serious problem (HW or SW).
3644          * Although we do return void from this function, this type of failure
3645          * should not go unreported.  That is why we have the warning message.
3646          */
3647         for (i = 0; i < num_init; i++) {
3648                 status = hermon_close_port_cmd_post(state, i + 1,
3649                     HERMON_CMD_NOSLEEP_SPIN);
3650                 if (status != HERMON_CMD_SUCCESS) {
3651                         HERMON_WARNING(state, "failed to shutdown HCA port");
3652                         return (status);
3653                 }
3654         }
3655         return (HERMON_CMD_SUCCESS);
3656 }
3657 
3658 
3659 /*
3660  * hermon_internal_uarpg_init
3661  *    Context: Only called from attach() path context
3662  */
3663 static int
3664 hermon_internal_uarpg_init(hermon_state_t *state)
3665 {
3666         int     status;
3667         hermon_dbr_info_t       *info;
3668 
3669         /*
3670          * Allocate the UAR page for kernel use. This UAR page is
3671          * the privileged UAR page through which all kernel generated
3672          * doorbells will be rung. There are a number of UAR pages
3673          * reserved by hardware at the front of the UAR BAR, indicated
3674          * by DEVCAP.num_rsvd_uar, which we have already allocated. So,
3675          * the kernel page, or UAR page index num_rsvd_uar, will be
3676          * allocated here for kernel use.
3677          */
3678 
3679         status = hermon_rsrc_alloc(state, HERMON_UARPG, 1, HERMON_SLEEP,
3680             &state->hs_uarkpg_rsrc);
3681         if (status != DDI_SUCCESS) {
3682                 return (DDI_FAILURE);
3683         }
3684 
3685         /* Setup pointer to kernel UAR page */
3686         state->hs_uar = (hermon_hw_uar_t *)state->hs_uarkpg_rsrc->hr_addr;
3687 
3688         /* need to set up DBr tracking as well */
3689         status = hermon_dbr_page_alloc(state, &info);
3690         if (status != DDI_SUCCESS) {
3691                 return (DDI_FAILURE);
3692         }
3693         state->hs_kern_dbr = info;
3694         return (DDI_SUCCESS);
3695 }
3696 
3697 
3698 /*
3699  * hermon_internal_uarpg_fini
3700  *    Context: Only called from attach() and/or detach() path contexts
3701  */
3702 static void
3703 hermon_internal_uarpg_fini(hermon_state_t *state)
3704 {
3705         /* Free up Hermon UAR page #1 (kernel driver doorbells) */
3706         hermon_rsrc_free(state, &state->hs_uarkpg_rsrc);
3707 }
3708 
3709 
3710 /*
3711  * hermon_special_qp_contexts_reserve()
3712  *    Context: Only called from attach() path context
3713  */
3714 static int
3715 hermon_special_qp_contexts_reserve(hermon_state_t *state)
3716 {
3717         hermon_rsrc_t   *qp0_rsrc, *qp1_rsrc, *qp_resvd;
3718         int             status;
3719 
3720         /* Initialize the lock used for special QP rsrc management */
3721         mutex_init(&state->hs_spec_qplock, NULL, MUTEX_DRIVER,
3722             DDI_INTR_PRI(state->hs_intrmsi_pri));
3723 
3724         /*
3725          * Reserve contexts for QP0.  These QP contexts will be setup to
3726          * act as aliases for the real QP0.  Note: We are required to grab
3727          * two QPs (one per port) even if we are operating in single-port
3728          * mode.
3729          */
3730         status = hermon_rsrc_alloc(state, HERMON_QPC, 2,
3731             HERMON_SLEEP, &qp0_rsrc);
3732         if (status != DDI_SUCCESS) {
3733                 mutex_destroy(&state->hs_spec_qplock);
3734                 return (DDI_FAILURE);
3735         }
3736         state->hs_spec_qp0 = qp0_rsrc;
3737 
3738         /*
3739          * Reserve contexts for QP1.  These QP contexts will be setup to
3740          * act as aliases for the real QP1.  Note: We are required to grab
3741          * two QPs (one per port) even if we are operating in single-port
3742          * mode.
3743          */
3744         status = hermon_rsrc_alloc(state, HERMON_QPC, 2,
3745             HERMON_SLEEP, &qp1_rsrc);
3746         if (status != DDI_SUCCESS) {
3747                 hermon_rsrc_free(state, &qp0_rsrc);
3748                 mutex_destroy(&state->hs_spec_qplock);
3749                 return (DDI_FAILURE);
3750         }
3751         state->hs_spec_qp1 = qp1_rsrc;
3752 
3753         status = hermon_rsrc_alloc(state, HERMON_QPC, 4,
3754             HERMON_SLEEP, &qp_resvd);
3755         if (status != DDI_SUCCESS) {
3756                 hermon_rsrc_free(state, &qp1_rsrc);
3757                 hermon_rsrc_free(state, &qp0_rsrc);
3758                 mutex_destroy(&state->hs_spec_qplock);
3759                 return (DDI_FAILURE);
3760         }
3761         state->hs_spec_qp_unused = qp_resvd;
3762 
3763         return (DDI_SUCCESS);
3764 }
3765 
3766 
3767 /*
3768  * hermon_special_qp_contexts_unreserve()
3769  *    Context: Only called from attach() and/or detach() path contexts
3770  */
3771 static void
3772 hermon_special_qp_contexts_unreserve(hermon_state_t *state)
3773 {
3774 
3775         /* Unreserve contexts for spec_qp_unused */
3776         hermon_rsrc_free(state, &state->hs_spec_qp_unused);
3777 
3778         /* Unreserve contexts for QP1 */
3779         hermon_rsrc_free(state, &state->hs_spec_qp1);
3780 
3781         /* Unreserve contexts for QP0 */
3782         hermon_rsrc_free(state, &state->hs_spec_qp0);
3783 
3784         /* Destroy the lock used for special QP rsrc management */
3785         mutex_destroy(&state->hs_spec_qplock);
3786 
3787 }
3788 
3789 
3790 /*
3791  * hermon_sw_reset()
3792  *    Context: Currently called only from attach() path context
3793  */
3794 static int
3795 hermon_sw_reset(hermon_state_t *state)
3796 {
3797         ddi_acc_handle_t        hdl = hermon_get_pcihdl(state);
3798         ddi_acc_handle_t        cmdhdl = hermon_get_cmdhdl(state);
3799         uint32_t                reset_delay;
3800         int                     status, i;
3801         uint32_t                sem;
3802         uint_t                  offset;
3803         uint32_t                data32;         /* for devctl & linkctl */
3804         int                     loopcnt;
3805 
3806         /* initialize the FMA retry loop */
3807         hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
3808         hermon_pio_init(fm_loop_cnt2, fm_status2, fm_test2);
3809 
3810         /*
3811          * If the configured software reset delay is set to zero, then we
3812          * will not attempt a software reset of the Hermon device.
3813          */
3814         reset_delay = state->hs_cfg_profile->cp_sw_reset_delay;
3815         if (reset_delay == 0) {
3816                 return (DDI_SUCCESS);
3817         }
3818 
3819         /* the FMA retry loop starts. */
3820         hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
3821             fm_test);
3822         hermon_pio_start(state, hdl, pio_error2, fm_loop_cnt2, fm_status2,
3823             fm_test2);
3824 
3825         /* Query the PCI capabilities of the HCA device */
3826         /* but don't process the VPD until after reset */
3827         status = hermon_pci_capability_list(state, hdl);
3828         if (status != DDI_SUCCESS) {
3829                 cmn_err(CE_NOTE, "failed to get pci capabilities list(0x%x)\n",
3830                     status);
3831                 return (DDI_FAILURE);
3832         }
3833 
3834         /*
3835          * Read all PCI config info (reg0...reg63).  Note: According to the
3836          * Hermon software reset application note, we should not read or
3837          * restore the values in reg22 and reg23.
3838          * NOTE:  For Hermon (and Arbel too) it says to restore the command
3839          * register LAST, and technically, you need to restore the
3840          * PCIE Capability "device control" and "link control" (word-sized,
3841          * at offsets 0x08 and 0x10 from the capbility ID respectively).
3842          * We hold off restoring the command register - offset 0x4 - till last
3843          */
3844 
3845         /* 1st, wait for the semaphore assure accessibility - per PRM */
3846         status = -1;
3847         for (i = 0; i < NANOSEC/MICROSEC /* 1sec timeout */; i++) {
3848                 sem = ddi_get32(cmdhdl, state->hs_cmd_regs.sw_semaphore);
3849                 if (sem == 0) {
3850                         status = 0;
3851                         break;
3852                 }
3853                 drv_usecwait(1);
3854         }
3855 
3856         /* Check if timeout happens */
3857         if (status == -1) {
3858                 /*
3859                  * Remove this acc handle from Hermon, then log
3860                  * the error.
3861                  */
3862                 hermon_pci_config_teardown(state, &hdl);
3863 
3864                 cmn_err(CE_WARN, "hermon_sw_reset timeout: "
3865                     "failed to get the semaphore(0x%p)\n",
3866                     (void *)state->hs_cmd_regs.sw_semaphore);
3867 
3868                 hermon_fm_ereport(state, HCA_IBA_ERR, HCA_ERR_NON_FATAL);
3869                 return (DDI_FAILURE);
3870         }
3871 
3872         for (i = 0; i < HERMON_SW_RESET_NUMREGS; i++) {
3873                 if ((i != HERMON_SW_RESET_REG22_RSVD) &&
3874                     (i != HERMON_SW_RESET_REG23_RSVD)) {
3875                         state->hs_cfg_data[i]  = pci_config_get32(hdl, i << 2);
3876                 }
3877         }
3878 
3879         /*
3880          * Perform the software reset (by writing 1 at offset 0xF0010)
3881          */
3882         ddi_put32(cmdhdl, state->hs_cmd_regs.sw_reset, HERMON_SW_RESET_START);
3883 
3884         /*
3885          * This delay is required so as not to cause a panic here. If the
3886          * device is accessed too soon after reset it will not respond to
3887          * config cycles, causing a Master Abort and panic.
3888          */
3889         drv_usecwait(reset_delay);
3890 
3891         /*
3892          * Poll waiting for the device to finish resetting.
3893          */
3894         loopcnt = 100;  /* 100 times @ 100 usec - total delay 10 msec */
3895         while ((pci_config_get32(hdl, 0) & 0x0000FFFF) != PCI_VENID_MLX) {
3896                 drv_usecwait(HERMON_SW_RESET_POLL_DELAY);
3897                 if (--loopcnt == 0)
3898                         break;  /* just in case, break and go on */
3899         }
3900         if (loopcnt == 0)
3901                 cmn_err(CE_CONT, "!Never see VEND_ID - read == %X",
3902                     pci_config_get32(hdl, 0));
3903 
3904         /*
3905          * Restore the config info
3906          */
3907         for (i = 0; i < HERMON_SW_RESET_NUMREGS; i++) {
3908                 if (i == 1) continue;   /* skip the status/ctrl reg */
3909                 if ((i != HERMON_SW_RESET_REG22_RSVD) &&
3910                     (i != HERMON_SW_RESET_REG23_RSVD)) {
3911                         pci_config_put32(hdl, i << 2, state->hs_cfg_data[i]);
3912                 }
3913         }
3914 
3915         /*
3916          * PCI Express Capability - we saved during capability list, and
3917          * we'll restore them here.
3918          */
3919         offset = state->hs_pci_cap_offset;
3920         data32 = state->hs_pci_cap_devctl;
3921         pci_config_put32(hdl, offset + HERMON_PCI_CAP_DEV_OFFS, data32);
3922         data32 = state->hs_pci_cap_lnkctl;
3923         pci_config_put32(hdl, offset + HERMON_PCI_CAP_LNK_OFFS, data32);
3924 
3925         pci_config_put32(hdl, 0x04, (state->hs_cfg_data[1] | 0x0006));
3926 
3927         /* the FMA retry loop ends. */
3928         hermon_pio_end(state, hdl, pio_error2, fm_loop_cnt2, fm_status2,
3929             fm_test2);
3930         hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
3931             fm_test);
3932 
3933         return (DDI_SUCCESS);
3934 
3935 pio_error2:
3936         /* fall through */
3937 pio_error:
3938         hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_NON_FATAL);
3939         return (DDI_FAILURE);
3940 }
3941 
3942 
3943 /*
3944  * hermon_mcg_init()
3945  *    Context: Only called from attach() path context
3946  */
3947 static int
3948 hermon_mcg_init(hermon_state_t *state)
3949 {
3950         uint_t          mcg_tmp_sz;
3951 
3952 
3953         /*
3954          * Allocate space for the MCG temporary copy buffer.  This is
3955          * used by the Attach/Detach Multicast Group code
3956          */
3957         mcg_tmp_sz = HERMON_MCGMEM_SZ(state);
3958         state->hs_mcgtmp = kmem_zalloc(mcg_tmp_sz, KM_SLEEP);
3959 
3960         /*
3961          * Initialize the multicast group mutex.  This ensures atomic
3962          * access to add, modify, and remove entries in the multicast
3963          * group hash lists.
3964          */
3965         mutex_init(&state->hs_mcglock, NULL, MUTEX_DRIVER,
3966             DDI_INTR_PRI(state->hs_intrmsi_pri));
3967 
3968         return (DDI_SUCCESS);
3969 }
3970 
3971 
3972 /*
3973  * hermon_mcg_fini()
3974  *    Context: Only called from attach() and/or detach() path contexts
3975  */
3976 static void
3977 hermon_mcg_fini(hermon_state_t *state)
3978 {
3979         uint_t          mcg_tmp_sz;
3980 
3981 
3982         /* Free up the space used for the MCG temporary copy buffer */
3983         mcg_tmp_sz = HERMON_MCGMEM_SZ(state);
3984         kmem_free(state->hs_mcgtmp, mcg_tmp_sz);
3985 
3986         /* Destroy the multicast group mutex */
3987         mutex_destroy(&state->hs_mcglock);
3988 
3989 }
3990 
3991 
3992 /*
3993  * hermon_fw_version_check()
3994  *    Context: Only called from attach() path context
3995  */
3996 static int
3997 hermon_fw_version_check(hermon_state_t *state)
3998 {
3999 
4000         uint_t  hermon_fw_ver_major;
4001         uint_t  hermon_fw_ver_minor;
4002         uint_t  hermon_fw_ver_subminor;
4003 
4004 #ifdef FMA_TEST
4005         if (hermon_test_num == -1) {
4006                 return (DDI_FAILURE);
4007         }
4008 #endif
4009 
4010         /*
4011          * Depending on which version of driver we have attached, and which
4012          * HCA we've attached, the firmware version checks will be different.
4013          * We set up the comparison values for both Arbel and Sinai HCAs.
4014          */
4015         switch (state->hs_operational_mode) {
4016         case HERMON_HCA_MODE:
4017                 hermon_fw_ver_major = HERMON_FW_VER_MAJOR;
4018                 hermon_fw_ver_minor = HERMON_FW_VER_MINOR;
4019                 hermon_fw_ver_subminor = HERMON_FW_VER_SUBMINOR;
4020                 break;
4021 
4022         default:
4023                 return (DDI_FAILURE);
4024         }
4025 
4026         /*
4027          * If FW revision major number is less than acceptable,
4028          * return failure, else if greater return success.  If
4029          * the major numbers are equal than check the minor number
4030          */
4031         if (state->hs_fw.fw_rev_major < hermon_fw_ver_major) {
4032                 return (DDI_FAILURE);
4033         } else if (state->hs_fw.fw_rev_major > hermon_fw_ver_major) {
4034                 return (DDI_SUCCESS);
4035         }
4036 
4037         /*
4038          * Do the same check as above, except for minor revision numbers
4039          * If the minor numbers are equal than check the subminor number
4040          */
4041         if (state->hs_fw.fw_rev_minor < hermon_fw_ver_minor) {
4042                 return (DDI_FAILURE);
4043         } else if (state->hs_fw.fw_rev_minor > hermon_fw_ver_minor) {
4044                 return (DDI_SUCCESS);
4045         }
4046 
4047         /*
4048          * Once again we do the same check as above, except for the subminor
4049          * revision number.  If the subminor numbers are equal here, then
4050          * these are the same firmware version, return success
4051          */
4052         if (state->hs_fw.fw_rev_subminor < hermon_fw_ver_subminor) {
4053                 return (DDI_FAILURE);
4054         } else if (state->hs_fw.fw_rev_subminor > hermon_fw_ver_subminor) {
4055                 return (DDI_SUCCESS);
4056         }
4057 
4058         return (DDI_SUCCESS);
4059 }
4060 
4061 
4062 /*
4063  * hermon_device_info_report()
4064  *    Context: Only called from attach() path context
4065  */
4066 static void
4067 hermon_device_info_report(hermon_state_t *state)
4068 {
4069 
4070         cmn_err(CE_CONT, "?hermon%d: FW ver: %04d.%04d.%04d, "
4071             "HW rev: %02d\n", state->hs_instance, state->hs_fw.fw_rev_major,
4072             state->hs_fw.fw_rev_minor, state->hs_fw.fw_rev_subminor,
4073             state->hs_revision_id);
4074         cmn_err(CE_CONT, "?hermon%d: %64s (0x%016" PRIx64 ")\n",
4075             state->hs_instance, state->hs_nodedesc, state->hs_nodeguid);
4076 
4077 }
4078 
4079 
4080 /*
4081  * hermon_pci_capability_list()
4082  *    Context: Only called from attach() path context
4083  */
4084 static int
4085 hermon_pci_capability_list(hermon_state_t *state, ddi_acc_handle_t hdl)
4086 {
4087         uint_t          offset, data;
4088         uint32_t        data32;
4089 
4090         state->hs_pci_cap_offset = 0;                /* make sure it's cleared */
4091 
4092         /*
4093          * Check for the "PCI Capabilities" bit in the "Status Register".
4094          * Bit 4 in this register indicates the presence of a "PCI
4095          * Capabilities" list.
4096          *
4097          * PCI-Express requires this bit to be set to 1.
4098          */
4099         data = pci_config_get16(hdl, 0x06);
4100         if ((data & 0x10) == 0) {
4101                 return (DDI_FAILURE);
4102         }
4103 
4104         /*
4105          * Starting from offset 0x34 in PCI config space, find the
4106          * head of "PCI capabilities" list, and walk the list.  If
4107          * capabilities of a known type are encountered (e.g.
4108          * "PCI-X Capability"), then call the appropriate handler
4109          * function.
4110          */
4111         offset = pci_config_get8(hdl, 0x34);
4112         while (offset != 0x0) {
4113                 data = pci_config_get8(hdl, offset);
4114                 /*
4115                  * Check for known capability types.  Hermon has the
4116                  * following:
4117                  *    o Power Mgmt       (0x02)
4118                  *    o VPD Capability   (0x03)
4119                  *    o PCI-E Capability (0x10)
4120                  *    o MSIX Capability  (0x11)
4121                  */
4122                 switch (data) {
4123                 case 0x01:
4124                         /* power mgmt handling */
4125                         break;
4126                 case 0x03:
4127 
4128 /*
4129  * Reading the PCIe VPD is inconsistent - that is, sometimes causes
4130  * problems on (mostly) X64, though we've also seen problems w/ Sparc
4131  * and Tavor --- so, for now until it's root caused, don't try and
4132  * read it
4133  */
4134 #ifdef HERMON_VPD_WORKS
4135                         hermon_pci_capability_vpd(state, hdl, offset);
4136 #else
4137                         delay(100);
4138                         hermon_pci_capability_vpd(state, hdl, offset);
4139 #endif
4140                         break;
4141                 case 0x10:
4142                         /*
4143                          * PCI Express Capability - save offset & contents
4144                          * for later in reset
4145                          */
4146                         state->hs_pci_cap_offset = offset;
4147                         data32 = pci_config_get32(hdl,
4148                             offset + HERMON_PCI_CAP_DEV_OFFS);
4149                         state->hs_pci_cap_devctl = data32;
4150                         data32 = pci_config_get32(hdl,
4151                             offset + HERMON_PCI_CAP_LNK_OFFS);
4152                         state->hs_pci_cap_lnkctl = data32;
4153                         break;
4154                 case 0x11:
4155                         /*
4156                          * MSIX support - nothing to do, taken care of in the
4157                          * MSI/MSIX interrupt frameworkd
4158                          */
4159                         break;
4160                 default:
4161                         /* just go on to the next */
4162                         break;
4163                 }
4164 
4165                 /* Get offset of next entry in list */
4166                 offset = pci_config_get8(hdl, offset + 1);
4167         }
4168 
4169         return (DDI_SUCCESS);
4170 }
4171 
4172 /*
4173  * hermon_pci_read_vpd()
4174  *    Context: Only called from attach() path context
4175  *    utility routine for hermon_pci_capability_vpd()
4176  */
4177 static int
4178 hermon_pci_read_vpd(ddi_acc_handle_t hdl, uint_t offset, uint32_t addr,
4179     uint32_t *data)
4180 {
4181         int             retry = 40;  /* retry counter for EEPROM poll */
4182         uint32_t        val;
4183         int             vpd_addr = offset + 2;
4184         int             vpd_data = offset + 4;
4185 
4186         /*
4187          * In order to read a 32-bit value from VPD, we are to write down
4188          * the address (offset in the VPD itself) to the address register.
4189          * To signal the read, we also clear bit 31.  We then poll on bit 31
4190          * and when it is set, we can then read our 4 bytes from the data
4191          * register.
4192          */
4193         (void) pci_config_put32(hdl, offset, addr << 16);
4194         do {
4195                 drv_usecwait(1000);
4196                 val = pci_config_get16(hdl, vpd_addr);
4197                 if (val & 0x8000) {         /* flag bit set */
4198                         *data = pci_config_get32(hdl, vpd_data);
4199                         return (DDI_SUCCESS);
4200                 }
4201         } while (--retry);
4202         /* read of flag failed write one message but count the failures */
4203         if (debug_vpd == 0)
4204                 cmn_err(CE_NOTE,
4205                     "!Failed to see flag bit after VPD addr write\n");
4206         debug_vpd++;
4207 
4208 
4209 vpd_read_fail:
4210         return (DDI_FAILURE);
4211 }
4212 
4213 
4214 
4215 /*
4216  *   hermon_pci_capability_vpd()
4217  *    Context: Only called from attach() path context
4218  */
4219 static void
4220 hermon_pci_capability_vpd(hermon_state_t *state, ddi_acc_handle_t hdl,
4221     uint_t offset)
4222 {
4223         uint8_t                 name_length;
4224         uint8_t                 pn_length;
4225         int                     i, err = 0;
4226         int                     vpd_str_id = 0;
4227         int                     vpd_ro_desc;
4228         int                     vpd_ro_pn_desc;
4229 #ifdef _BIG_ENDIAN
4230         uint32_t                data32;
4231 #endif /* _BIG_ENDIAN */
4232         union {
4233                 uint32_t        vpd_int[HERMON_VPD_HDR_DWSIZE];
4234                 uchar_t         vpd_char[HERMON_VPD_HDR_BSIZE];
4235         } vpd;
4236 
4237 
4238         /*
4239          * Read in the Vital Product Data (VPD) to the extend needed
4240          * by the fwflash utility
4241          */
4242         for (i = 0; i < HERMON_VPD_HDR_DWSIZE; i++) {
4243                 err = hermon_pci_read_vpd(hdl, offset, i << 2, &vpd.vpd_int[i]);
4244                 if (err != DDI_SUCCESS) {
4245                         cmn_err(CE_NOTE, "!VPD read failed\n");
4246                         goto out;
4247                 }
4248         }
4249 
4250 #ifdef _BIG_ENDIAN
4251         /* Need to swap bytes for big endian. */
4252         for (i = 0; i < HERMON_VPD_HDR_DWSIZE; i++) {
4253                 data32 = vpd.vpd_int[i];
4254                 vpd.vpd_char[(i << 2) + 3] =
4255                     (uchar_t)((data32 & 0xFF000000) >> 24);
4256                 vpd.vpd_char[(i << 2) + 2] =
4257                     (uchar_t)((data32 & 0x00FF0000) >> 16);
4258                 vpd.vpd_char[(i << 2) + 1] =
4259                     (uchar_t)((data32 & 0x0000FF00) >> 8);
4260                 vpd.vpd_char[i << 2] = (uchar_t)(data32 & 0x000000FF);
4261         }
4262 #endif  /* _BIG_ENDIAN */
4263 
4264         /* Check for VPD String ID Tag */
4265         if (vpd.vpd_char[vpd_str_id] == 0x82) {
4266                 /* get the product name */
4267                 name_length = (uint8_t)vpd.vpd_char[vpd_str_id + 1];
4268                 if (name_length > sizeof (state->hs_hca_name)) {
4269                         cmn_err(CE_NOTE, "!VPD name too large (0x%x)\n",
4270                             name_length);
4271                         goto out;
4272                 }
4273                 (void) memcpy(state->hs_hca_name, &vpd.vpd_char[vpd_str_id + 3],
4274                     name_length);
4275                 state->hs_hca_name[name_length] = 0;
4276 
4277                 /* get the part number */
4278                 vpd_ro_desc = name_length + 3; /* read-only tag location */
4279                 vpd_ro_pn_desc = vpd_ro_desc + 3; /* P/N keyword location */
4280 
4281                 /* Verify read-only tag and Part Number keyword. */
4282                 if (vpd.vpd_char[vpd_ro_desc] != 0x90 ||
4283                     (vpd.vpd_char[vpd_ro_pn_desc] != 'P' &&
4284                     vpd.vpd_char[vpd_ro_pn_desc + 1] != 'N')) {
4285                         cmn_err(CE_NOTE, "!VPD Part Number not found\n");
4286                         goto out;
4287                 }
4288 
4289                 pn_length = (uint8_t)vpd.vpd_char[vpd_ro_pn_desc + 2];
4290                 if (pn_length > sizeof (state->hs_hca_pn)) {
4291                         cmn_err(CE_NOTE, "!VPD part number too large (0x%x)\n",
4292                             name_length);
4293                         goto out;
4294                 }
4295                 (void) memcpy(state->hs_hca_pn,
4296                     &vpd.vpd_char[vpd_ro_pn_desc + 3],
4297                     pn_length);
4298                 state->hs_hca_pn[pn_length] = 0;
4299                 state->hs_hca_pn_len = pn_length;
4300                 cmn_err(CE_CONT, "!vpd %s\n", state->hs_hca_pn);
4301         } else {
4302                 /* Wrong VPD String ID Tag */
4303                 cmn_err(CE_NOTE, "!VPD String ID Tag not found, tag: %02x\n",
4304                     vpd.vpd_char[0]);
4305                 goto out;
4306         }
4307         return;
4308 out:
4309         state->hs_hca_pn_len = 0;
4310 }
4311 
4312 
4313 
4314 /*
4315  * hermon_intr_or_msi_init()
4316  *    Context: Only called from attach() path context
4317  */
4318 static int
4319 hermon_intr_or_msi_init(hermon_state_t *state)
4320 {
4321         int     status;
4322 
4323         /* Query for the list of supported interrupt event types */
4324         status = ddi_intr_get_supported_types(state->hs_dip,
4325             &state->hs_intr_types_avail);
4326         if (status != DDI_SUCCESS) {
4327                 return (DDI_FAILURE);
4328         }
4329 
4330         /*
4331          * If Hermon supports MSI-X in this system (and, if it
4332          * hasn't been overridden by a configuration variable), then
4333          * the default behavior is to use a single MSI-X.  Otherwise,
4334          * fallback to using legacy interrupts.  Also, if MSI-X is chosen,
4335          * but fails for whatever reasons, then next try MSI
4336          */
4337         if ((state->hs_cfg_profile->cp_use_msi_if_avail != 0) &&
4338             (state->hs_intr_types_avail & DDI_INTR_TYPE_MSIX)) {
4339                 status = hermon_add_intrs(state, DDI_INTR_TYPE_MSIX);
4340                 if (status == DDI_SUCCESS) {
4341                         state->hs_intr_type_chosen = DDI_INTR_TYPE_MSIX;
4342                         return (DDI_SUCCESS);
4343                 }
4344         }
4345 
4346         /*
4347          * If Hermon supports MSI in this system (and, if it
4348          * hasn't been overridden by a configuration variable), then
4349          * the default behavior is to use a single MSIX.  Otherwise,
4350          * fallback to using legacy interrupts.  Also, if MSI is chosen,
4351          * but fails for whatever reasons, then fallback to using legacy
4352          * interrupts.
4353          */
4354         if ((state->hs_cfg_profile->cp_use_msi_if_avail != 0) &&
4355             (state->hs_intr_types_avail & DDI_INTR_TYPE_MSI)) {
4356                 status = hermon_add_intrs(state, DDI_INTR_TYPE_MSI);
4357                 if (status == DDI_SUCCESS) {
4358                         state->hs_intr_type_chosen = DDI_INTR_TYPE_MSI;
4359                         return (DDI_SUCCESS);
4360                 }
4361         }
4362 
4363         /*
4364          * MSI interrupt allocation failed, or was not available.  Fallback to
4365          * legacy interrupt support.
4366          */
4367         if (state->hs_intr_types_avail & DDI_INTR_TYPE_FIXED) {
4368                 status = hermon_add_intrs(state, DDI_INTR_TYPE_FIXED);
4369                 if (status == DDI_SUCCESS) {
4370                         state->hs_intr_type_chosen = DDI_INTR_TYPE_FIXED;
4371                         return (DDI_SUCCESS);
4372                 }
4373         }
4374 
4375         /*
4376          * None of MSI, MSI-X, nor legacy interrupts were successful.
4377          * Return failure.
4378          */
4379         return (DDI_FAILURE);
4380 }
4381 
4382 /* ARGSUSED */
4383 static int
4384 hermon_intr_cb_handler(dev_info_t *dip, ddi_cb_action_t action, void *cbarg,
4385     void *arg1, void *arg2)
4386 {
4387         hermon_state_t *state = (hermon_state_t *)arg1;
4388 
4389         IBTF_DPRINTF_L2("hermon", "interrupt callback: instance %d, "
4390             "action %d, cbarg %d\n", state->hs_instance, action,
4391             (uint32_t)(uintptr_t)cbarg);
4392         return (DDI_SUCCESS);
4393 }
4394 
4395 /*
4396  * hermon_add_intrs()
4397  *    Context: Only called from attach() patch context
4398  */
4399 static int
4400 hermon_add_intrs(hermon_state_t *state, int intr_type)
4401 {
4402         int     status;
4403 
4404         if (state->hs_intr_cb_hdl == NULL) {
4405                 status = ddi_cb_register(state->hs_dip, DDI_CB_FLAG_INTR,
4406                     hermon_intr_cb_handler, state, NULL,
4407                     &state->hs_intr_cb_hdl);
4408                 if (status != DDI_SUCCESS) {
4409                         cmn_err(CE_CONT, "ddi_cb_register failed: 0x%x\n",
4410                             status);
4411                         state->hs_intr_cb_hdl = NULL;
4412                         return (DDI_FAILURE);
4413                 }
4414         }
4415 
4416         /* Get number of interrupts/MSI supported */
4417         status = ddi_intr_get_nintrs(state->hs_dip, intr_type,
4418             &state->hs_intrmsi_count);
4419         if (status != DDI_SUCCESS) {
4420                 (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
4421                 state->hs_intr_cb_hdl = NULL;
4422                 return (DDI_FAILURE);
4423         }
4424 
4425         /* Get number of available interrupts/MSI */
4426         status = ddi_intr_get_navail(state->hs_dip, intr_type,
4427             &state->hs_intrmsi_avail);
4428         if (status != DDI_SUCCESS) {
4429                 (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
4430                 state->hs_intr_cb_hdl = NULL;
4431                 return (DDI_FAILURE);
4432         }
4433 
4434         /* Ensure that we have at least one (1) usable MSI or interrupt */
4435         if ((state->hs_intrmsi_avail < 1) || (state->hs_intrmsi_count < 1)) {
4436                 (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
4437                 state->hs_intr_cb_hdl = NULL;
4438                 return (DDI_FAILURE);
4439         }
4440 
4441         /*
4442          * Allocate the #interrupt/MSI handles.
4443          * The number we request is the minimum of these three values:
4444          *      HERMON_MSIX_MAX                 driver maximum (array size)
4445          *      hermon_msix_max                 /etc/system override to...
4446          *                                              HERMON_MSIX_MAX
4447          *      state->hs_intrmsi_avail              Maximum the ddi provides.
4448          */
4449         status = ddi_intr_alloc(state->hs_dip, &state->hs_intrmsi_hdl[0],
4450             intr_type, 0, min(min(HERMON_MSIX_MAX, state->hs_intrmsi_avail),
4451             hermon_msix_max), &state->hs_intrmsi_allocd, DDI_INTR_ALLOC_NORMAL);
4452         if (status != DDI_SUCCESS) {
4453                 (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
4454                 state->hs_intr_cb_hdl = NULL;
4455                 return (DDI_FAILURE);
4456         }
4457 
4458         /* Ensure that we have allocated at least one (1) MSI or interrupt */
4459         if (state->hs_intrmsi_allocd < 1) {
4460                 (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
4461                 state->hs_intr_cb_hdl = NULL;
4462                 return (DDI_FAILURE);
4463         }
4464 
4465         /*
4466          * Extract the priority for the allocated interrupt/MSI.  This
4467          * will be used later when initializing certain mutexes.
4468          */
4469         status = ddi_intr_get_pri(state->hs_intrmsi_hdl[0],
4470             &state->hs_intrmsi_pri);
4471         if (status != DDI_SUCCESS) {
4472                 /* Free the allocated interrupt/MSI handle */
4473                 (void) ddi_intr_free(state->hs_intrmsi_hdl[0]);
4474 
4475                 (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
4476                 state->hs_intr_cb_hdl = NULL;
4477                 return (DDI_FAILURE);
4478         }
4479 
4480         /* Make sure the interrupt/MSI priority is below 'high level' */
4481         if (state->hs_intrmsi_pri >= ddi_intr_get_hilevel_pri()) {
4482                 /* Free the allocated interrupt/MSI handle */
4483                 (void) ddi_intr_free(state->hs_intrmsi_hdl[0]);
4484 
4485                 return (DDI_FAILURE);
4486         }
4487 
4488         /* Get add'l capability information regarding interrupt/MSI */
4489         status = ddi_intr_get_cap(state->hs_intrmsi_hdl[0],
4490             &state->hs_intrmsi_cap);
4491         if (status != DDI_SUCCESS) {
4492                 /* Free the allocated interrupt/MSI handle */
4493                 (void) ddi_intr_free(state->hs_intrmsi_hdl[0]);
4494 
4495                 return (DDI_FAILURE);
4496         }
4497 
4498         return (DDI_SUCCESS);
4499 }
4500 
4501 
4502 /*
4503  * hermon_intr_or_msi_fini()
4504  *    Context: Only called from attach() and/or detach() path contexts
4505  */
4506 static int
4507 hermon_intr_or_msi_fini(hermon_state_t *state)
4508 {
4509         int     status;
4510         int     intr;
4511 
4512         for (intr = 0; intr < state->hs_intrmsi_allocd; intr++) {
4513 
4514                 /* Free the allocated interrupt/MSI handle */
4515                 status = ddi_intr_free(state->hs_intrmsi_hdl[intr]);
4516                 if (status != DDI_SUCCESS) {
4517                         return (DDI_FAILURE);
4518                 }
4519         }
4520         if (state->hs_intr_cb_hdl) {
4521                 (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
4522                 state->hs_intr_cb_hdl = NULL;
4523         }
4524         return (DDI_SUCCESS);
4525 }
4526 
4527 
4528 /*ARGSUSED*/
4529 void
4530 hermon_pci_capability_msix(hermon_state_t *state, ddi_acc_handle_t hdl,
4531     uint_t offset)
4532 {
4533         uint32_t        msix_data;
4534         uint16_t        msg_cntr;
4535         uint32_t        t_offset;       /* table offset */
4536         uint32_t        t_bir;
4537         uint32_t        p_offset;       /* pba */
4538         uint32_t        p_bir;
4539         int             t_size;         /* size in entries - each is 4 dwords */
4540 
4541         /* come in with offset pointing at the capability structure */
4542 
4543         msix_data = pci_config_get32(hdl, offset);
4544         cmn_err(CE_CONT, "Full cap structure dword = %X\n", msix_data);
4545         msg_cntr =  pci_config_get16(hdl, offset+2);
4546         cmn_err(CE_CONT, "MSIX msg_control = %X\n", msg_cntr);
4547         offset += 4;
4548         msix_data = pci_config_get32(hdl, offset);      /* table info */
4549         t_offset = (msix_data & 0xFFF8) >> 3;
4550         t_bir = msix_data & 0x07;
4551         offset += 4;
4552         cmn_err(CE_CONT, "  table %X --offset = %X, bir(bar) = %X\n",
4553             msix_data, t_offset, t_bir);
4554         msix_data = pci_config_get32(hdl, offset);      /* PBA info */
4555         p_offset = (msix_data & 0xFFF8) >> 3;
4556         p_bir = msix_data & 0x07;
4557 
4558         cmn_err(CE_CONT, "  PBA   %X --offset = %X, bir(bar) = %X\n",
4559             msix_data, p_offset, p_bir);
4560         t_size = msg_cntr & 0x7FF;          /* low eleven bits */
4561         cmn_err(CE_CONT, "    table size = %X entries\n", t_size);
4562 
4563         offset = t_offset;              /* reuse this for offset from BAR */
4564 #ifdef HERMON_SUPPORTS_MSIX_BAR
4565         cmn_err(CE_CONT, "First 2 table entries behind BAR2 \n");
4566         for (i = 0; i < 2; i++) {
4567                 for (j = 0; j < 4; j++, offset += 4) {
4568                         msix_data = ddi_get32(state->hs_reg_msihdl,
4569                             (uint32_t *)((uintptr_t)state->hs_reg_msi_baseaddr
4570                             + offset));
4571                         cmn_err(CE_CONT, "MSI table entry %d, dword %d == %X\n",
4572                             i, j, msix_data);
4573                 }
4574         }
4575 #endif
4576 
4577 }
4578 
4579 /*
4580  * X86 fastreboot support functions.
4581  * These functions are used to save/restore MSI-X table/PBA and also
4582  * to disable MSI-X interrupts in hermon_quiesce().
4583  */
4584 
4585 /* Return the message control for MSI-X */
4586 static ushort_t
4587 get_msix_ctrl(dev_info_t *dip)
4588 {
4589         ushort_t msix_ctrl = 0, caps_ctrl = 0;
4590         hermon_state_t *state = ddi_get_soft_state(hermon_statep,
4591             DEVI(dip)->devi_instance);
4592         ddi_acc_handle_t pci_cfg_hdl = hermon_get_pcihdl(state);
4593         ASSERT(pci_cfg_hdl != NULL);
4594 
4595         if ((PCI_CAP_LOCATE(pci_cfg_hdl,
4596             PCI_CAP_ID_MSI_X, &caps_ctrl) == DDI_SUCCESS)) {
4597                 if ((msix_ctrl = PCI_CAP_GET16(pci_cfg_hdl, NULL, caps_ctrl,
4598                     PCI_MSIX_CTRL)) == PCI_CAP_EINVAL16)
4599                         return (0);
4600         }
4601         ASSERT(msix_ctrl != 0);
4602 
4603         return (msix_ctrl);
4604 }
4605 
4606 /* Return the MSI-X table size */
4607 static size_t
4608 get_msix_tbl_size(dev_info_t *dip)
4609 {
4610         ushort_t msix_ctrl = get_msix_ctrl(dip);
4611         ASSERT(msix_ctrl != 0);
4612 
4613         return (((msix_ctrl & PCI_MSIX_TBL_SIZE_MASK) + 1) *
4614             PCI_MSIX_VECTOR_SIZE);
4615 }
4616 
4617 /* Return the MSI-X PBA size */
4618 static size_t
4619 get_msix_pba_size(dev_info_t *dip)
4620 {
4621         ushort_t msix_ctrl = get_msix_ctrl(dip);
4622         ASSERT(msix_ctrl != 0);
4623 
4624         return (((msix_ctrl & PCI_MSIX_TBL_SIZE_MASK) + 64) / 64 * 8);
4625 }
4626 
4627 /* Set up the MSI-X table/PBA save area */
4628 static void
4629 hermon_set_msix_info(hermon_state_t *state)
4630 {
4631         uint_t                  rnumber, breg, nregs;
4632         ushort_t                caps_ctrl, msix_ctrl;
4633         pci_regspec_t           *rp;
4634         int                     reg_size, addr_space, offset, *regs_list, i;
4635 
4636         /*
4637          * MSI-X BIR Index Table:
4638          * BAR indicator register (BIR) to Base Address register.
4639          */
4640         uchar_t pci_msix_bir_index[8] = {0x10, 0x14, 0x18, 0x1c,
4641             0x20, 0x24, 0xff, 0xff};
4642 
4643         /* Fastreboot data access  attribute */
4644         ddi_device_acc_attr_t   dev_attr = {
4645                 0,                              /* version */
4646                 DDI_STRUCTURE_LE_ACC,
4647                 DDI_STRICTORDER_ACC,            /* attr access */
4648                 0
4649         };
4650 
4651         ddi_acc_handle_t pci_cfg_hdl = hermon_get_pcihdl(state);
4652         ASSERT(pci_cfg_hdl != NULL);
4653 
4654         if ((PCI_CAP_LOCATE(pci_cfg_hdl,
4655             PCI_CAP_ID_MSI_X, &caps_ctrl) == DDI_SUCCESS)) {
4656                 if ((msix_ctrl = PCI_CAP_GET16(pci_cfg_hdl, NULL, caps_ctrl,
4657                     PCI_MSIX_CTRL)) == PCI_CAP_EINVAL16)
4658                         return;
4659         }
4660         ASSERT(msix_ctrl != 0);
4661 
4662         state->hs_msix_tbl_offset = PCI_CAP_GET32(pci_cfg_hdl, NULL, caps_ctrl,
4663             PCI_MSIX_TBL_OFFSET);
4664 
4665         /* Get the BIR for MSI-X table */
4666         breg = pci_msix_bir_index[state->hs_msix_tbl_offset &
4667             PCI_MSIX_TBL_BIR_MASK];
4668         ASSERT(breg != 0xFF);
4669 
4670         /* Set the MSI-X table offset */
4671         state->hs_msix_tbl_offset = state->hs_msix_tbl_offset &
4672             ~PCI_MSIX_TBL_BIR_MASK;
4673 
4674         /* Set the MSI-X table size */
4675         state->hs_msix_tbl_size = ((msix_ctrl & PCI_MSIX_TBL_SIZE_MASK) + 1) *
4676             PCI_MSIX_VECTOR_SIZE;
4677 
4678         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, state->hs_dip,
4679             DDI_PROP_DONTPASS, "reg", (int **)&regs_list, &nregs) !=
4680             DDI_PROP_SUCCESS) {
4681                 return;
4682         }
4683         reg_size = sizeof (pci_regspec_t) / sizeof (int);
4684 
4685         /* Check the register number for MSI-X table */
4686         for (i = 1, rnumber = 0; i < nregs/reg_size; i++) {
4687                 rp = (pci_regspec_t *)&regs_list[i * reg_size];
4688                 addr_space = rp->pci_phys_hi & PCI_ADDR_MASK;
4689                 offset = PCI_REG_REG_G(rp->pci_phys_hi);
4690 
4691                 if ((offset == breg) && ((addr_space == PCI_ADDR_MEM32) ||
4692                     (addr_space == PCI_ADDR_MEM64))) {
4693                         rnumber = i;
4694                         break;
4695                 }
4696         }
4697         ASSERT(rnumber != 0);
4698         state->hs_msix_tbl_rnumber = rnumber;
4699 
4700         /* Set device attribute version and access according to Hermon FM */
4701         dev_attr.devacc_attr_version = hermon_devacc_attr_version(state);
4702         dev_attr.devacc_attr_access = hermon_devacc_attr_access(state);
4703 
4704         /* Map the entire MSI-X vector table */
4705         if (hermon_regs_map_setup(state, state->hs_msix_tbl_rnumber,
4706             (caddr_t *)&state->hs_msix_tbl_addr, state->hs_msix_tbl_offset,
4707             state->hs_msix_tbl_size, &dev_attr,
4708             &state->hs_fm_msix_tblhdl) != DDI_SUCCESS) {
4709                 return;
4710         }
4711 
4712         state->hs_msix_pba_offset = PCI_CAP_GET32(pci_cfg_hdl, NULL, caps_ctrl,
4713             PCI_MSIX_PBA_OFFSET);
4714 
4715         /* Get the BIR for MSI-X PBA */
4716         breg = pci_msix_bir_index[state->hs_msix_pba_offset &
4717             PCI_MSIX_PBA_BIR_MASK];
4718         ASSERT(breg != 0xFF);
4719 
4720         /* Set the MSI-X PBA offset */
4721         state->hs_msix_pba_offset = state->hs_msix_pba_offset &
4722             ~PCI_MSIX_PBA_BIR_MASK;
4723 
4724         /* Set the MSI-X PBA size */
4725         state->hs_msix_pba_size =
4726             ((msix_ctrl & PCI_MSIX_TBL_SIZE_MASK) + 64) / 64 * 8;
4727 
4728         /* Check the register number for MSI-X PBA */
4729         for (i = 1, rnumber = 0; i < nregs/reg_size; i++) {
4730                 rp = (pci_regspec_t *)&regs_list[i * reg_size];
4731                 addr_space = rp->pci_phys_hi & PCI_ADDR_MASK;
4732                 offset = PCI_REG_REG_G(rp->pci_phys_hi);
4733 
4734                 if ((offset == breg) && ((addr_space == PCI_ADDR_MEM32) ||
4735                     (addr_space == PCI_ADDR_MEM64))) {
4736                         rnumber = i;
4737                         break;
4738                 }
4739         }
4740         ASSERT(rnumber != 0);
4741         state->hs_msix_pba_rnumber = rnumber;
4742         ddi_prop_free(regs_list);
4743 
4744         /* Map in the MSI-X Pending Bit Array */
4745         if (hermon_regs_map_setup(state, state->hs_msix_pba_rnumber,
4746             (caddr_t *)&state->hs_msix_pba_addr, state->hs_msix_pba_offset,
4747             state->hs_msix_pba_size, &dev_attr,
4748             &state->hs_fm_msix_pbahdl) != DDI_SUCCESS) {
4749                 hermon_regs_map_free(state, &state->hs_fm_msix_tblhdl);
4750                 state->hs_fm_msix_tblhdl = NULL;
4751                 return;
4752         }
4753 
4754         /* Set the MSI-X table save area */
4755         state->hs_msix_tbl_entries = kmem_alloc(state->hs_msix_tbl_size,
4756             KM_SLEEP);
4757 
4758         /* Set the MSI-X PBA save area */
4759         state->hs_msix_pba_entries = kmem_alloc(state->hs_msix_pba_size,
4760             KM_SLEEP);
4761 }
4762 
4763 /* Disable Hermon interrupts */
4764 static int
4765 hermon_intr_disable(hermon_state_t *state)
4766 {
4767         ushort_t msix_ctrl = 0, caps_ctrl = 0;
4768         ddi_acc_handle_t pci_cfg_hdl = hermon_get_pcihdl(state);
4769         ddi_acc_handle_t msix_tblhdl = hermon_get_msix_tblhdl(state);
4770         int i, j;
4771         ASSERT(pci_cfg_hdl != NULL && msix_tblhdl != NULL);
4772         ASSERT(state->hs_intr_types_avail &
4773             (DDI_INTR_TYPE_FIXED | DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_MSIX));
4774 
4775         /*
4776          * Check if MSI-X interrupts are used. If so, disable MSI-X interupts.
4777          * If not, since Hermon doesn't support MSI interrupts, assuming the
4778          * legacy interrupt is used instead, disable the legacy interrupt.
4779          */
4780         if ((state->hs_cfg_profile->cp_use_msi_if_avail != 0) &&
4781             (state->hs_intr_types_avail & DDI_INTR_TYPE_MSIX)) {
4782 
4783                 if ((PCI_CAP_LOCATE(pci_cfg_hdl,
4784                     PCI_CAP_ID_MSI_X, &caps_ctrl) == DDI_SUCCESS)) {
4785                         if ((msix_ctrl = PCI_CAP_GET16(pci_cfg_hdl, NULL,
4786                             caps_ctrl, PCI_MSIX_CTRL)) == PCI_CAP_EINVAL16)
4787                                 return (DDI_FAILURE);
4788                 }
4789                 ASSERT(msix_ctrl != 0);
4790 
4791                 if (!(msix_ctrl & PCI_MSIX_ENABLE_BIT))
4792                         return (DDI_SUCCESS);
4793 
4794                 /* Clear all inums in MSI-X table */
4795                 for (i = 0; i < get_msix_tbl_size(state->hs_dip);
4796                     i += PCI_MSIX_VECTOR_SIZE) {
4797                         for (j = 0; j < PCI_MSIX_VECTOR_SIZE; j += 4) {
4798                                 char *addr = state->hs_msix_tbl_addr + i + j;
4799                                 ddi_put32(msix_tblhdl,
4800                                     (uint32_t *)(uintptr_t)addr, 0x0);
4801                         }
4802                 }
4803 
4804                 /* Disable MSI-X interrupts */
4805                 msix_ctrl &= ~PCI_MSIX_ENABLE_BIT;
4806                 PCI_CAP_PUT16(pci_cfg_hdl, NULL, caps_ctrl, PCI_MSIX_CTRL,
4807                     msix_ctrl);
4808 
4809         } else {
4810                 uint16_t cmdreg = pci_config_get16(pci_cfg_hdl, PCI_CONF_COMM);
4811                 ASSERT(state->hs_intr_types_avail & DDI_INTR_TYPE_FIXED);
4812 
4813                 /* Disable the legacy interrupts */
4814                 cmdreg |= PCI_COMM_INTX_DISABLE;
4815                 pci_config_put16(pci_cfg_hdl, PCI_CONF_COMM, cmdreg);
4816         }
4817 
4818         return (DDI_SUCCESS);
4819 }
4820 
4821 /* Hermon quiesce(9F) entry */
4822 static int
4823 hermon_quiesce(dev_info_t *dip)
4824 {
4825         hermon_state_t *state = ddi_get_soft_state(hermon_statep,
4826             DEVI(dip)->devi_instance);
4827         ddi_acc_handle_t pcihdl = hermon_get_pcihdl(state);
4828         ddi_acc_handle_t cmdhdl = hermon_get_cmdhdl(state);
4829         ddi_acc_handle_t msix_tbl_hdl = hermon_get_msix_tblhdl(state);
4830         ddi_acc_handle_t msix_pba_hdl = hermon_get_msix_pbahdl(state);
4831         uint32_t sem, reset_delay = state->hs_cfg_profile->cp_sw_reset_delay;
4832         uint64_t data64;
4833         uint32_t data32;
4834         int status, i, j, loopcnt;
4835         uint_t offset;
4836 
4837         ASSERT(state != NULL);
4838 
4839         /* start fastreboot */
4840         state->hs_quiescing = B_TRUE;
4841 
4842         /* If it's in maintenance mode, do nothing but return with SUCCESS */
4843         if (!HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
4844                 return (DDI_SUCCESS);
4845         }
4846 
4847         /* suppress Hermon FM ereports */
4848         if (hermon_get_state(state) & HCA_EREPORT_FM) {
4849                 hermon_clr_state_nolock(state, HCA_EREPORT_FM);
4850         }
4851 
4852         /* Shutdown HCA ports */
4853         if (hermon_hca_ports_shutdown(state,
4854             state->hs_cfg_profile->cp_num_ports) != HERMON_CMD_SUCCESS) {
4855                 state->hs_quiescing = B_FALSE;
4856                 return (DDI_FAILURE);
4857         }
4858 
4859         /* Close HCA */
4860         if (hermon_close_hca_cmd_post(state, HERMON_CMD_NOSLEEP_SPIN) !=
4861             HERMON_CMD_SUCCESS) {
4862                 state->hs_quiescing = B_FALSE;
4863                 return (DDI_FAILURE);
4864         }
4865 
4866         /* Disable interrupts */
4867         if (hermon_intr_disable(state) != DDI_SUCCESS) {
4868                 state->hs_quiescing = B_FALSE;
4869                 return (DDI_FAILURE);
4870         }
4871 
4872         /*
4873          * Query the PCI capabilities of the HCA device, but don't process
4874          * the VPD until after reset.
4875          */
4876         if (hermon_pci_capability_list(state, pcihdl) != DDI_SUCCESS) {
4877                 state->hs_quiescing = B_FALSE;
4878                 return (DDI_FAILURE);
4879         }
4880 
4881         /*
4882          * Read all PCI config info (reg0...reg63).  Note: According to the
4883          * Hermon software reset application note, we should not read or
4884          * restore the values in reg22 and reg23.
4885          * NOTE:  For Hermon (and Arbel too) it says to restore the command
4886          * register LAST, and technically, you need to restore the
4887          * PCIE Capability "device control" and "link control" (word-sized,
4888          * at offsets 0x08 and 0x10 from the capbility ID respectively).
4889          * We hold off restoring the command register - offset 0x4 - till last
4890          */
4891 
4892         /* 1st, wait for the semaphore assure accessibility - per PRM */
4893         status = -1;
4894         for (i = 0; i < NANOSEC/MICROSEC /* 1sec timeout */; i++) {
4895                 sem = ddi_get32(cmdhdl, state->hs_cmd_regs.sw_semaphore);
4896                 if (sem == 0) {
4897                         status = 0;
4898                         break;
4899                 }
4900                 drv_usecwait(1);
4901         }
4902 
4903         /* Check if timeout happens */
4904         if (status == -1) {
4905                 state->hs_quiescing = B_FALSE;
4906                 return (DDI_FAILURE);
4907         }
4908 
4909         /* MSI-X interrupts are used, save the MSI-X table */
4910         if (msix_tbl_hdl && msix_pba_hdl) {
4911                 /* save MSI-X table */
4912                 for (i = 0; i < get_msix_tbl_size(state->hs_dip);
4913                     i += PCI_MSIX_VECTOR_SIZE) {
4914                         for (j = 0; j < PCI_MSIX_VECTOR_SIZE; j += 4) {
4915                                 char *addr = state->hs_msix_tbl_addr + i + j;
4916                                 data32 = ddi_get32(msix_tbl_hdl,
4917                                     (uint32_t *)(uintptr_t)addr);
4918                                 *(uint32_t *)(uintptr_t)(state->
4919                                     hs_msix_tbl_entries + i + j) = data32;
4920                         }
4921                 }
4922                 /* save MSI-X PBA */
4923                 for (i = 0; i < get_msix_pba_size(state->hs_dip); i += 8) {
4924                         char *addr = state->hs_msix_pba_addr + i;
4925                         data64 = ddi_get64(msix_pba_hdl,
4926                             (uint64_t *)(uintptr_t)addr);
4927                         *(uint64_t *)(uintptr_t)(state->
4928                             hs_msix_pba_entries + i) = data64;
4929                 }
4930         }
4931 
4932         /* save PCI config space */
4933         for (i = 0; i < HERMON_SW_RESET_NUMREGS; i++) {
4934                 if ((i != HERMON_SW_RESET_REG22_RSVD) &&
4935                     (i != HERMON_SW_RESET_REG23_RSVD)) {
4936                         state->hs_cfg_data[i]  =
4937                             pci_config_get32(pcihdl, i << 2);
4938                 }
4939         }
4940 
4941         /* SW-reset HCA */
4942         ddi_put32(cmdhdl, state->hs_cmd_regs.sw_reset, HERMON_SW_RESET_START);
4943 
4944         /*
4945          * This delay is required so as not to cause a panic here. If the
4946          * device is accessed too soon after reset it will not respond to
4947          * config cycles, causing a Master Abort and panic.
4948          */
4949         drv_usecwait(reset_delay);
4950 
4951         /* Poll waiting for the device to finish resetting */
4952         loopcnt = 100;  /* 100 times @ 100 usec - total delay 10 msec */
4953         while ((pci_config_get32(pcihdl, 0) & 0x0000FFFF) != PCI_VENID_MLX) {
4954                 drv_usecwait(HERMON_SW_RESET_POLL_DELAY);
4955                 if (--loopcnt == 0)
4956                         break;  /* just in case, break and go on */
4957         }
4958         if (loopcnt == 0) {
4959                 state->hs_quiescing = B_FALSE;
4960                 return (DDI_FAILURE);
4961         }
4962 
4963         /* Restore the config info */
4964         for (i = 0; i < HERMON_SW_RESET_NUMREGS; i++) {
4965                 if (i == 1) continue;   /* skip the status/ctrl reg */
4966                 if ((i != HERMON_SW_RESET_REG22_RSVD) &&
4967                     (i != HERMON_SW_RESET_REG23_RSVD)) {
4968                         pci_config_put32(pcihdl, i << 2, state->hs_cfg_data[i]);
4969                 }
4970         }
4971 
4972         /* If MSI-X interrupts are used, restore the MSI-X table */
4973         if (msix_tbl_hdl && msix_pba_hdl) {
4974                 /* restore MSI-X PBA */
4975                 for (i = 0; i < get_msix_pba_size(state->hs_dip); i += 8) {
4976                         char *addr = state->hs_msix_pba_addr + i;
4977                         data64 = *(uint64_t *)(uintptr_t)
4978                             (state->hs_msix_pba_entries + i);
4979                         ddi_put64(msix_pba_hdl,
4980                             (uint64_t *)(uintptr_t)addr, data64);
4981                 }
4982                 /* restore MSI-X table */
4983                 for (i = 0; i < get_msix_tbl_size(state->hs_dip);
4984                     i += PCI_MSIX_VECTOR_SIZE) {
4985                         for (j = 0; j < PCI_MSIX_VECTOR_SIZE; j += 4) {
4986                                 char *addr = state->hs_msix_tbl_addr + i + j;
4987                                 data32 = *(uint32_t *)(uintptr_t)
4988                                     (state->hs_msix_tbl_entries + i + j);
4989                                 ddi_put32(msix_tbl_hdl,
4990                                     (uint32_t *)(uintptr_t)addr, data32);
4991                         }
4992                 }
4993         }
4994 
4995         /*
4996          * PCI Express Capability - we saved during capability list, and
4997          * we'll restore them here.
4998          */
4999         offset = state->hs_pci_cap_offset;
5000         data32 = state->hs_pci_cap_devctl;
5001         pci_config_put32(pcihdl, offset + HERMON_PCI_CAP_DEV_OFFS, data32);
5002         data32 = state->hs_pci_cap_lnkctl;
5003         pci_config_put32(pcihdl, offset + HERMON_PCI_CAP_LNK_OFFS, data32);
5004 
5005         /* restore the command register */
5006         pci_config_put32(pcihdl, 0x04, (state->hs_cfg_data[1] | 0x0006));
5007 
5008         return (DDI_SUCCESS);
5009 }