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